Advertisement
Guest User

Untitled

a guest
Oct 18th, 2014
324
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 24.07 KB | None | 0 0
  1.  
  2. /*  $OpenBSD: umsm.c,v 1.96 2013/12/13 17:43:07 yuo Exp $   */
  3.  
  4. /*
  5.  * Copyright (c) 2008 Yojiro UO <yuo@nui.org>
  6.  * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org>
  7.  *
  8.  * Permission to use, copy, modify, and distribute this software for any
  9.  * purpose with or without fee is hereby granted, provided that the above
  10.  * copyright notice and this permission notice appear in all copies.
  11.  *
  12.  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  13.  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  14.  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  15.  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  16.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  17.  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  18.  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19.  */
  20.  
  21. /* Driver for Qualcomm MSM EVDO and UMTS communication devices */
  22.  
  23. #include <sys/param.h>
  24. #include <sys/systm.h>
  25. #include <sys/kernel.h>
  26. #include <sys/malloc.h>
  27. #include <sys/device.h>
  28. #include <sys/conf.h>
  29. #include <sys/tty.h>
  30.  
  31. #include <dev/usb/usb.h>
  32. #include <dev/usb/usbdi.h>
  33. #include <dev/usb/usbdi_util.h>
  34. #include <dev/usb/usbdevs.h>
  35. #include <dev/usb/ucomvar.h>
  36. #include <dev/usb/usbcdc.h>
  37. #include <dev/usb/umassvar.h>
  38. #undef DPRINTF  /* undef DPRINTF for umass */
  39.  
  40. #ifdef USB_DEBUG
  41. #define UMSM_DEBUG
  42. #endif
  43.  
  44. #ifdef UMSM_DEBUG
  45. int     umsmdebug = 0;
  46. #define DPRINTFN(n, x)  do { if (umsmdebug > (n)) printf x; } while (0)
  47. #else
  48. #define DPRINTFN(n, x)
  49. #endif
  50.  
  51. #define DPRINTF(x) DPRINTFN(0, x)
  52.  
  53. #define UMSMBUFSZ   4096
  54. #define UMSM_INTR_INTERVAL  100 /* ms */
  55. #define E220_MODE_CHANGE_REQUEST 0x2
  56. #define TRUINSTALL_CHANGEMODE_REQUEST 0x0b
  57.  
  58. int umsm_match(struct device *, void *, void *);
  59. void umsm_attach(struct device *, struct device *, void *);
  60. int umsm_detach(struct device *, int);
  61. int umsm_activate(struct device *, int);
  62.  
  63. int umsm_open(void *, int);
  64. void umsm_close(void *, int);
  65. void umsm_intr(struct usbd_xfer *, void *, usbd_status);
  66. void umsm_get_status(void *, int, u_char *, u_char *);
  67. void umsm_set(void *, int, int, int);
  68.  
  69. struct umsm_softc {
  70.     struct device        sc_dev;
  71.     struct usbd_device  *sc_udev;
  72.     struct usbd_interface   *sc_iface;
  73.     int          sc_iface_no;
  74.     struct device       *sc_subdev;
  75.     uint16_t         sc_flag;
  76.  
  77.     /* interrupt ep */
  78.     int          sc_intr_number;
  79.     struct usbd_pipe    *sc_intr_pipe;
  80.     u_char          *sc_intr_buf;
  81.     int          sc_isize;
  82.  
  83.     u_char           sc_lsr;    /* Local status register */
  84.     u_char           sc_msr;    /* status register */
  85.     u_char           sc_dtr;    /* current DTR state */
  86.     u_char           sc_rts;    /* current RTS state */
  87. };
  88.  
  89. usbd_status umsm_huawei_changemode(struct usbd_device *);
  90. usbd_status umsm_truinstall_changemode(struct usbd_device *);
  91. usbd_status umsm_umass_changemode(struct umsm_softc *);
  92.  
  93. struct ucom_methods umsm_methods = {
  94.     umsm_get_status,
  95.     umsm_set,
  96.     NULL,
  97.     NULL,
  98.     umsm_open,
  99.     umsm_close,
  100.     NULL,
  101.     NULL,
  102. };
  103.  
  104. struct umsm_type {
  105.     struct usb_devno    umsm_dev;
  106.     uint16_t        umsm_flag;
  107. /* device type */
  108. #define DEV_NORMAL  0x0000
  109. #define DEV_HUAWEI  0x0001
  110. #define DEV_TRUINSTALL  0x0002
  111. #define DEV_UMASS1  0x0010
  112. #define DEV_UMASS2  0x0020
  113. #define DEV_UMASS3  0x0040
  114. #define DEV_UMASS4  0x0080
  115. #define DEV_UMASS5  0x0100
  116. #define DEV_UMASS6  0x0200
  117. #define DEV_UMASS7  0x0400
  118. #define DEV_UMASS   (DEV_UMASS1 | DEV_UMASS2 | DEV_UMASS3 | DEV_UMASS4 | \
  119.     DEV_UMASS5 | DEV_UMASS6 | DEV_UMASS7)
  120. };
  121.  
  122. static const struct umsm_type umsm_devs[] = {
  123.     {{ USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_PC5220 }, 0},
  124.  
  125.     {{ USB_VENDOR_ANYDATA,  USB_PRODUCT_ANYDATA_A2502 }, 0},
  126.     {{ USB_VENDOR_ANYDATA,  USB_PRODUCT_ANYDATA_ADU_500A }, 0},
  127.     {{ USB_VENDOR_ANYDATA,  USB_PRODUCT_ANYDATA_ADU_E100H }, 0},
  128.  
  129.     {{ USB_VENDOR_DELL, USB_PRODUCT_DELL_EU870D }, 0},
  130.     {{ USB_VENDOR_DELL, USB_PRODUCT_DELL_U740 }, 0},
  131.     {{ USB_VENDOR_DELL, USB_PRODUCT_DELL_W5500 }, 0},
  132.  
  133.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E161 }, DEV_UMASS5},
  134.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E173S_INIT }, DEV_UMASS5},
  135.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E173S }, 0},
  136.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E180 }, DEV_HUAWEI},
  137.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E181 }, DEV_HUAWEI},
  138.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E182 }, DEV_UMASS5},
  139.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E1820 }, DEV_UMASS5},
  140.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E220 }, DEV_HUAWEI},
  141.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E303 }, DEV_UMASS5},
  142.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E353_INIT }, DEV_UMASS5},
  143.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E510 }, DEV_HUAWEI},
  144.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E618 }, DEV_HUAWEI},
  145.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E392_INIT }, DEV_UMASS5},
  146.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_EM770W }, 0},
  147.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_Mobile }, DEV_HUAWEI},
  148.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_K3765_INIT }, DEV_UMASS5},
  149.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_K3765 }, 0},
  150.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_K4510 }, DEV_UMASS5},
  151.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E1750 }, DEV_UMASS5},
  152.     {{ USB_VENDOR_HUAWEI,   USB_PRODUCT_HUAWEI_E1752 }, 0},
  153.  
  154.     {{ USB_VENDOR_HYUNDAI,  USB_PRODUCT_HYUNDAI_UM175 }, 0},
  155.  
  156.     {{ USB_VENDOR_LONGCHEER, USB_PRODUCT_LONGCHEER_D21LCMASS }, DEV_UMASS3},
  157.     {{ USB_VENDOR_LONGCHEER, USB_PRODUCT_LONGCHEER_D21LC }, 0},
  158.     {{ USB_VENDOR_LONGCHEER, USB_PRODUCT_LONGCHEER_510FUMASS }, DEV_UMASS3},
  159.     {{ USB_VENDOR_LONGCHEER, USB_PRODUCT_LONGCHEER_510FU }, 0},
  160.  
  161.     {{ USB_VENDOR_KYOCERA2, USB_PRODUCT_KYOCERA2_KPC650 }, 0},
  162.  
  163.     /* XXX Some qualcomm devices are missing */
  164.     {{ USB_VENDOR_QUALCOMM, USB_PRODUCT_QUALCOMM_MSM_DRIVER }, DEV_UMASS1},
  165.     {{ USB_VENDOR_QUALCOMM, USB_PRODUCT_QUALCOMM_MSM_DRIVER2 }, DEV_UMASS4},
  166.     {{ USB_VENDOR_QUALCOMM, USB_PRODUCT_QUALCOMM_MSM_HSDPA }, 0},
  167.     {{ USB_VENDOR_QUALCOMM, USB_PRODUCT_QUALCOMM_MSM_HSDPA2 }, 0},
  168.     {{ USB_VENDOR_QUALCOMM, USB_PRODUCT_QUALCOMM_MSM_HSDPA3 }, 0},
  169.  
  170.     {{ USB_VENDOR_QUANTA2, USB_PRODUCT_QUANTA2_UMASS }, DEV_UMASS4},
  171.     {{ USB_VENDOR_QUANTA2, USB_PRODUCT_QUANTA2_Q101 }, 0},
  172.  
  173.     {{ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_AC2746 }, 0},
  174.     {{ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_UMASS_INSTALLER }, DEV_UMASS4},
  175.     {{ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_UMASS_INSTALLER2 }, DEV_UMASS6},
  176.     {{ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_UMASS_INSTALLER3 }, DEV_UMASS7},
  177.     {{ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_UMASS_INSTALLER4 }, DEV_UMASS4},
  178.     {{ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_K3565Z }, 0},
  179.     {{ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MF112 }, DEV_UMASS4},
  180.     {{ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MF633 }, 0},
  181.     {{ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MF637 }, 0},
  182.     {{ USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MSA110UP }, 0},
  183.  
  184.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_EXPRESSCARD }, 0},
  185.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MERLINV620 }, 0},
  186.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MERLINV740 }, 0},
  187.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V720 }, 0},
  188.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MERLINU740 }, 0},
  189.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MERLINU740_2 }, 0},
  190.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U870 }, 0},
  191.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_XU870 }, 0},
  192.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_EU870D }, 0},
  193.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_X950D }, 0},
  194.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ES620 }, 0},
  195.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U720 }, 0},
  196.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U727 }, DEV_UMASS1},
  197.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MC950D }, 0},
  198.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MERLINX950D }, DEV_UMASS4},
  199.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ZEROCD2 }, DEV_UMASS4},
  200.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U760 }, DEV_UMASS4},
  201.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MC760 }, 0},
  202.     {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MC760CD }, DEV_UMASS4},
  203.  
  204.     {{ USB_VENDOR_NOVATEL1, USB_PRODUCT_NOVATEL1_FLEXPACKGPS }, 0},
  205.  
  206.     {{ USB_VENDOR_NOKIA2, USB_PRODUCT_NOKIA2_CS15UMASS }, DEV_UMASS4},
  207.     {{ USB_VENDOR_NOKIA2, USB_PRODUCT_NOKIA2_CS15 }, 0},
  208.  
  209.     {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GFUSION }, 0},
  210.     {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GPLUS }, 0},
  211.     {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUAD }, 0},
  212.     {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUADPLUS }, 0},
  213.     {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GSICON72 }, DEV_UMASS1},
  214.     {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTHSDPA225 }, DEV_UMASS2},
  215.     {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTHSUPA380E }, 0},
  216.     {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAX36 }, 0},
  217.     {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_SCORPION }, 0},
  218.     {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_VODAFONEMC3G }, 0},
  219.  
  220.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625 }, 0},
  221.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720 }, 0},
  222.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD_595 }, 0},
  223.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725 }, 0},
  224.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E }, 0},
  225.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597 }, 0},
  226.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U }, 0},
  227.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD_580 }, 0},
  228.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2 }, 0},
  229.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725_2 }, 0},
  230.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2 }, 0},
  231.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765 }, 0},
  232.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755 }, 0},
  233.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775 }, 0},
  234.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3 }, 0},
  235.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2 }, 0},
  236.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD_875 }, 0},
  237.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780 }, 0},
  238.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781 }, 0},
  239.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8790 }, 0},
  240.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880 }, 0},
  241.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881 }, 0},
  242.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E }, 0},
  243.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E }, 0},
  244.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U }, 0},
  245.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U }, 0},
  246.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC885U }, 0},
  247.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C01SW }, 0},
  248.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_USB305}, 0},
  249.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_TRUINSTALL }, DEV_TRUINSTALL},
  250.     {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8355}, 0},
  251.  
  252.     {{ USB_VENDOR_TCTMOBILE, USB_PRODUCT_TCTMOBILE_UMASS }, DEV_UMASS3},
  253.     {{ USB_VENDOR_TCTMOBILE, USB_PRODUCT_TCTMOBILE_UMSM }, 0},
  254.     {{ USB_VENDOR_TCTMOBILE, USB_PRODUCT_TCTMOBILE_UMSM_2 }, 0},
  255.  
  256.     {{ USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_HSDPA }, 0},
  257.  
  258.     {{ USB_VENDOR_HP, USB_PRODUCT_HP_HS2300 }, 0},
  259.  
  260.     {{ USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CNU510 }, 0}, /* ??? */
  261.     {{ USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CCU550 }, 0}, /* ??? */
  262.     {{ USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CGU628 }, DEV_UMASS1},
  263.     {{ USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CGU628_DISK }, 0},
  264.     {{ USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CNU680 }, DEV_UMASS1},
  265. };
  266.  
  267. #define umsm_lookup(v, p) ((const struct umsm_type *)usb_lookup(umsm_devs, v, p))
  268.  
  269. struct cfdriver umsm_cd = {
  270.     NULL, "umsm", DV_DULL
  271. };
  272.  
  273. const struct cfattach umsm_ca = {
  274.     sizeof(struct umsm_softc),
  275.     umsm_match,
  276.     umsm_attach,
  277.     umsm_detach,
  278.     umsm_activate,
  279. };
  280.  
  281. int
  282. umsm_match(struct device *parent, void *match, void *aux)
  283. {
  284.     struct usb_attach_arg *uaa = aux;
  285.     usb_interface_descriptor_t *id;
  286.     uint16_t flag;
  287.  
  288.     if (uaa->iface == NULL)
  289.         return UMATCH_NONE;
  290.  
  291.     /*
  292.      * Some devices (eg Huawei E220) have multiple interfaces and some
  293.      * of them are of class umass. Don't claim ownership in such case.
  294.      */
  295.     if (umsm_lookup(uaa->vendor, uaa->product) != NULL) {
  296.         id = usbd_get_interface_descriptor(uaa->iface);
  297.         flag = umsm_lookup(uaa->vendor, uaa->product)->umsm_flag;
  298.  
  299.         if (id == NULL || id->bInterfaceClass == UICLASS_MASS) {
  300.             /*
  301.              * Some high-speed modems require special care.
  302.              */
  303.             if (flag & DEV_HUAWEI) {
  304.                 if (uaa->ifaceno != 2)
  305.                     return UMATCH_VENDOR_IFACESUBCLASS;
  306.                 else
  307.                     return UMATCH_NONE;
  308.             } else if (flag & DEV_UMASS) {
  309.                 return UMATCH_VENDOR_IFACESUBCLASS;
  310.             } else if (flag & DEV_TRUINSTALL) {
  311.                 return UMATCH_VENDOR_IFACESUBCLASS;
  312.             } else
  313.                 return UMATCH_NONE;
  314.         } else
  315.             return UMATCH_VENDOR_IFACESUBCLASS;
  316.     }
  317.  
  318.     return UMATCH_NONE;
  319. }
  320.  
  321. void
  322. umsm_attach(struct device *parent, struct device *self, void *aux)
  323. {
  324.     struct umsm_softc *sc = (struct umsm_softc *)self;
  325.     struct usb_attach_arg *uaa = aux;
  326.     struct ucom_attach_args uca;
  327.     usb_interface_descriptor_t *id;
  328.     usb_endpoint_descriptor_t *ed;
  329.     int i;
  330.  
  331.     bzero(&uca, sizeof(uca));
  332.     sc->sc_udev = uaa->device;
  333.     sc->sc_iface = uaa->iface;
  334.     sc->sc_flag  = umsm_lookup(uaa->vendor, uaa->product)->umsm_flag;
  335.  
  336.     id = usbd_get_interface_descriptor(sc->sc_iface);
  337.  
  338.     /*
  339.      * Some 3G modems have multiple interfaces and some of them
  340.      * are umass class. Don't claim ownership in such case.
  341.      */
  342.     if (id == NULL || id->bInterfaceClass == UICLASS_MASS) {
  343.         /*
  344.          * Some 3G modems require a special request to
  345.          * enable their modem function.
  346.          */
  347.         if ((sc->sc_flag & DEV_HUAWEI) && uaa->ifaceno == 0) {
  348.                         umsm_huawei_changemode(uaa->device);
  349.             printf("%s: umass only mode. need to reattach\n",
  350.                 sc->sc_dev.dv_xname);
  351.         } else if ((sc->sc_flag & DEV_TRUINSTALL) &&
  352.                 uaa->ifaceno == 0) {
  353.             umsm_truinstall_changemode(uaa->device);
  354.             printf("%s: truinstall mode. need to reattach\n",
  355.                 sc->sc_dev.dv_xname);
  356.         } else if ((sc->sc_flag & DEV_UMASS) && uaa->ifaceno == 0) {
  357.             umsm_umass_changemode(sc);
  358.         }
  359.  
  360.         /*
  361.          * The device will reset its own bus from the device side
  362.          * when its mode was changed, so just return.
  363.          */
  364.         return;
  365.     }
  366.  
  367.     sc->sc_iface_no = id->bInterfaceNumber;
  368.     uca.bulkin = uca.bulkout = -1;
  369.     sc->sc_intr_number = sc->sc_isize = -1;
  370.     for (i = 0; i < id->bNumEndpoints; i++) {
  371.         ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
  372.         if (ed == NULL) {
  373.             printf("%s: no endpoint descriptor found for %d\n",
  374.                 sc->sc_dev.dv_xname, i);
  375.             usbd_deactivate(sc->sc_udev);
  376.             return;
  377.         }
  378.  
  379.         if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  380.             UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
  381.             sc->sc_intr_number = ed->bEndpointAddress;
  382.             sc->sc_isize = UGETW(ed->wMaxPacketSize);
  383.             DPRINTF(("%s: find interrupt endpoint for %s\n",
  384.                 __func__, sc->sc_dev.dv_xname));
  385.         } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  386.             UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
  387.             uca.bulkin = ed->bEndpointAddress;
  388.         else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  389.             UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
  390.             uca.bulkout = ed->bEndpointAddress;
  391.     }
  392.     if (uca.bulkin == -1 || uca.bulkout == -1) {
  393.         printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
  394.         usbd_deactivate(sc->sc_udev);
  395.         return;
  396.     }
  397.  
  398.     sc->sc_dtr = sc->sc_rts = -1;
  399.  
  400.     /* We need to force size as some devices lie */
  401.     uca.ibufsize = UMSMBUFSZ;
  402.     uca.obufsize = UMSMBUFSZ;
  403.     uca.ibufsizepad = UMSMBUFSZ;
  404.     uca.opkthdrlen = 0;
  405.     uca.device = sc->sc_udev;
  406.     uca.iface = sc->sc_iface;
  407.     uca.methods = &umsm_methods;
  408.     uca.arg = sc;
  409.     uca.info = NULL;
  410.     uca.portno = UCOM_UNK_PORTNO;
  411.  
  412.     sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
  413. }
  414.  
  415. int
  416. umsm_detach(struct device *self, int flags)
  417. {
  418.     struct umsm_softc *sc = (struct umsm_softc *)self;
  419.     int rv = 0;
  420.  
  421.     /* close the interrupt endpoint if that is opened */
  422.     if (sc->sc_intr_pipe != NULL) {
  423.         usbd_abort_pipe(sc->sc_intr_pipe);
  424.         usbd_close_pipe(sc->sc_intr_pipe);
  425.         free(sc->sc_intr_buf, M_USBDEV);
  426.         sc->sc_intr_pipe = NULL;
  427.     }
  428.  
  429.     usbd_deactivate(sc->sc_udev);
  430.     if (sc->sc_subdev != NULL) {
  431.         rv = config_detach(sc->sc_subdev, flags);
  432.         sc->sc_subdev = NULL;
  433.     }
  434.  
  435.     return (rv);
  436. }
  437.  
  438. int
  439. umsm_activate(struct device *self, int act)
  440. {
  441.     struct umsm_softc *sc = (struct umsm_softc *)self;
  442.  
  443.     switch (act) {
  444.     case DVACT_DEACTIVATE:
  445.         usbd_deactivate(sc->sc_udev);
  446.         break;
  447.     }
  448.     return (0);
  449. }
  450.  
  451. int
  452. umsm_open(void *addr, int portno)
  453. {
  454.     struct umsm_softc *sc = addr;
  455.     int err;
  456.  
  457.     if (usbd_is_dying(sc->sc_udev))
  458.         return (ENXIO);
  459.  
  460.     if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
  461.         sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
  462.         err = usbd_open_pipe_intr(sc->sc_iface,
  463.             sc->sc_intr_number,
  464.             USBD_SHORT_XFER_OK,
  465.             &sc->sc_intr_pipe,
  466.             sc,
  467.             sc->sc_intr_buf,
  468.             sc->sc_isize,
  469.             umsm_intr,
  470.             UMSM_INTR_INTERVAL);
  471.         if (err) {
  472.             printf("%s: cannot open interrupt pipe (addr %d)\n",
  473.                 sc->sc_dev.dv_xname,
  474.                 sc->sc_intr_number);
  475.             return (EIO);
  476.         }
  477.     }
  478.  
  479.     return (0);
  480. }
  481.  
  482. void
  483. umsm_close(void *addr, int portno)
  484. {
  485.     struct umsm_softc *sc = addr;
  486.     int err;
  487.  
  488.     if (usbd_is_dying(sc->sc_udev))
  489.         return;
  490.  
  491.     if (sc->sc_intr_pipe != NULL) {
  492.         usbd_abort_pipe(sc->sc_intr_pipe);
  493.         err = usbd_close_pipe(sc->sc_intr_pipe);
  494.         if (err)
  495.             printf("%s: close interrupt pipe failed: %s\n",
  496.                 sc->sc_dev.dv_xname,
  497.                 usbd_errstr(err));
  498.         free(sc->sc_intr_buf, M_USBDEV);
  499.         sc->sc_intr_pipe = NULL;
  500.     }
  501. }
  502.  
  503. void
  504. umsm_intr(struct usbd_xfer *xfer, void *priv,
  505.     usbd_status status)
  506. {
  507.     struct umsm_softc *sc = priv;
  508.     struct usb_cdc_notification *buf;
  509.     u_char mstatus;
  510.  
  511.     buf = (struct usb_cdc_notification *)sc->sc_intr_buf;
  512.     if (usbd_is_dying(sc->sc_udev))
  513.         return;
  514.  
  515.     if (status != USBD_NORMAL_COMPLETION) {
  516.         if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
  517.             return;
  518.  
  519.         DPRINTF(("%s: umsm_intr: abnormal status: %s\n",
  520.             sc->sc_dev.dv_xname, usbd_errstr(status)));
  521.         usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
  522.         return;
  523.     }
  524.  
  525.     if (buf->bmRequestType != UCDC_NOTIFICATION) {
  526. #if 1 /* test */
  527.         printf("%s: this device is not using CDC notify message in intr pipe.\n"
  528.             "Please send your dmesg to <bugs@openbsd.org>, thanks.\n",
  529.             sc->sc_dev.dv_xname);
  530.         printf("%s: intr buffer 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
  531.             sc->sc_dev.dv_xname,
  532.             sc->sc_intr_buf[0], sc->sc_intr_buf[1],
  533.             sc->sc_intr_buf[2], sc->sc_intr_buf[3],
  534.             sc->sc_intr_buf[4], sc->sc_intr_buf[5],
  535.             sc->sc_intr_buf[6]);
  536. #else
  537.         DPRINTF(("%s: umsm_intr: unknown message type(0x%02x)\n",
  538.             sc->sc_dev.dv_xname, buf->bmRequestType));
  539. #endif
  540.         return;
  541.     }
  542.  
  543.     if (buf->bNotification == UCDC_N_SERIAL_STATE) {
  544.         /* invalid message length, discard it */
  545.         if (UGETW(buf->wLength) != 2)
  546.             return;
  547.         /* XXX: sc_lsr is always 0 */
  548.         sc->sc_lsr = sc->sc_msr = 0;
  549.         mstatus = buf->data[0];
  550.         if (ISSET(mstatus, UCDC_N_SERIAL_RI))
  551.             sc->sc_msr |= UMSR_RI;
  552.         if (ISSET(mstatus, UCDC_N_SERIAL_DSR))
  553.             sc->sc_msr |= UMSR_DSR;
  554.         if (ISSET(mstatus, UCDC_N_SERIAL_DCD))
  555.             sc->sc_msr |= UMSR_DCD;
  556.     } else if (buf->bNotification != UCDC_N_CONNECTION_SPEED_CHANGE) {
  557.         DPRINTF(("%s: umsm_intr: unknown notify message (0x%02x)\n",
  558.             sc->sc_dev.dv_xname, buf->bNotification));
  559.         return;
  560.     }
  561.  
  562.     ucom_status_change((struct ucom_softc *)sc->sc_subdev);
  563. }
  564.  
  565. void
  566. umsm_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
  567. {
  568.     struct umsm_softc *sc = addr;
  569.  
  570.     if (lsr != NULL)
  571.         *lsr = sc->sc_lsr;
  572.     if (msr != NULL)
  573.         *msr = sc->sc_msr;
  574. }
  575.  
  576. void
  577. umsm_set(void *addr, int portno, int reg, int onoff)
  578. {
  579.     struct umsm_softc *sc = addr;
  580.     usb_device_request_t req;
  581.     int ls;
  582.  
  583.     switch (reg) {
  584.     case UCOM_SET_DTR:
  585.         if (sc->sc_dtr == onoff)
  586.             return;
  587.         sc->sc_dtr = onoff;
  588.         break;
  589.     case UCOM_SET_RTS:
  590.         if (sc->sc_rts == onoff)
  591.             return;
  592.         sc->sc_rts = onoff;
  593.         break;
  594.     default:
  595.         return;
  596.     }
  597.  
  598.     /* build a usb request */
  599.     ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) |
  600.          (sc->sc_rts ? UCDC_LINE_RTS : 0);
  601.     req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  602.     req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
  603.     USETW(req.wValue, ls);
  604.     USETW(req.wIndex, sc->sc_iface_no);
  605.     USETW(req.wLength, 0);
  606.  
  607.     (void)usbd_do_request(sc->sc_udev, &req, 0);
  608. }
  609.  
  610. usbd_status
  611. umsm_huawei_changemode(struct usbd_device *dev)
  612. {
  613.     usb_device_request_t req;
  614.     usbd_status err;
  615.  
  616.     req.bmRequestType = UT_WRITE_DEVICE;
  617.     req.bRequest = UR_SET_FEATURE;
  618.     USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
  619.     USETW(req.wIndex, E220_MODE_CHANGE_REQUEST);
  620.     USETW(req.wLength, 0);
  621.  
  622.     err = usbd_do_request(dev, &req, 0);
  623.     if (err)
  624.         return (EIO);
  625.  
  626.     return (0);
  627. }
  628.  
  629. usbd_status
  630. umsm_truinstall_changemode(struct usbd_device *dev)
  631. {
  632.     usb_device_request_t req;
  633.     usbd_status err;
  634.     req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  635.     req.bRequest = TRUINSTALL_CHANGEMODE_REQUEST;
  636.     USETW(req.wValue, 0x1);
  637.     USETW(req.wIndex, 0);
  638.     USETW(req.wLength, 0);
  639.  
  640.     err = usbd_do_request(dev, &req, 0);
  641.     if (err)
  642.         return (EIO);
  643.  
  644.     return (0);
  645. }
  646.  
  647. usbd_status
  648. umsm_umass_changemode(struct umsm_softc *sc)
  649. {
  650. #define UMASS_CMD_REZERO_UNIT       0x01
  651. #define UMASS_CMD_START_STOP        0x1b
  652. #define UMASS_CMDPARAM_EJECT        0x02
  653. #define UMASS_SERVICE_ACTION_OUT    0x9f
  654.     usb_interface_descriptor_t *id;
  655.     usb_endpoint_descriptor_t *ed;
  656.     struct usbd_xfer *xfer;
  657.     struct usbd_pipe *cmdpipe;
  658.     usbd_status err;
  659.     u_int32_t n;
  660.     void *bufp;
  661.     int target_ep, i;
  662.  
  663.     struct umass_bbb_cbw cbw;
  664.     static int dCBWTag = 0x12345678;
  665.  
  666.     USETDW(cbw.dCBWSignature, CBWSIGNATURE);
  667.     USETDW(cbw.dCBWTag, dCBWTag);
  668.     cbw.bCBWLUN   = 0;
  669.     cbw.bCDBLength= 6;
  670.     bzero(cbw.CBWCDB, sizeof(cbw.CBWCDB));
  671.  
  672.     switch (sc->sc_flag) {
  673.     case DEV_UMASS1:
  674.         USETDW(cbw.dCBWDataTransferLength, 0x0);
  675.         cbw.bCBWFlags = CBWFLAGS_OUT;
  676.         cbw.CBWCDB[0] = UMASS_CMD_REZERO_UNIT;
  677.         cbw.CBWCDB[1] = 0x0;    /* target LUN: 0 */
  678.         break;
  679.     case DEV_UMASS2:
  680.         USETDW(cbw.dCBWDataTransferLength, 0x1);
  681.         cbw.bCBWFlags = CBWFLAGS_IN;
  682.         cbw.CBWCDB[0] = UMASS_CMD_REZERO_UNIT;
  683.         cbw.CBWCDB[1] = 0x0;    /* target LUN: 0 */
  684.         break;
  685.     case DEV_UMASS3: /* longcheer */
  686.         USETDW(cbw.dCBWDataTransferLength, 0x80);
  687.         cbw.bCBWFlags = CBWFLAGS_IN;
  688.         cbw.CBWCDB[0] = 0x06;
  689.         cbw.CBWCDB[1] = 0xf5;
  690.         cbw.CBWCDB[2] = 0x04;
  691.         cbw.CBWCDB[3] = 0x02;
  692.         cbw.CBWCDB[4] = 0x52;
  693.         cbw.CBWCDB[5] = 0x70;
  694.         break;
  695.     case DEV_UMASS4:
  696.         USETDW(cbw.dCBWDataTransferLength, 0x0);
  697.         cbw.bCBWFlags = CBWFLAGS_OUT;
  698.         cbw.CBWCDB[0] = UMASS_CMD_START_STOP;
  699.         cbw.CBWCDB[1] = 0x00;   /* target LUN: 0 */
  700.         cbw.CBWCDB[4] = UMASS_CMDPARAM_EJECT;
  701.         break;
  702.     case DEV_UMASS5:
  703.         cbw.bCBWFlags = CBWFLAGS_OUT;
  704.         cbw.CBWCDB[0] = 0x11;
  705.         cbw.CBWCDB[1] = 0x06;
  706.         break;
  707.     case DEV_UMASS6:    /* ZTE */
  708.         USETDW(cbw.dCBWDataTransferLength, 0x20);
  709.         cbw.bCBWFlags = CBWFLAGS_IN;
  710.         cbw.bCDBLength= 12;
  711.         cbw.CBWCDB[0] = 0x85;
  712.         cbw.CBWCDB[1] = 0x01;
  713.         cbw.CBWCDB[2] = 0x01;
  714.         cbw.CBWCDB[3] = 0x01;
  715.         cbw.CBWCDB[4] = 0x18;
  716.         cbw.CBWCDB[5] = 0x01;
  717.         cbw.CBWCDB[6] = 0x01;
  718.         cbw.CBWCDB[7] = 0x01;
  719.         cbw.CBWCDB[8] = 0x01;
  720.         cbw.CBWCDB[9] = 0x01;
  721.         break;
  722.     case DEV_UMASS7:    /* ZTE */
  723.         USETDW(cbw.dCBWDataTransferLength, 0xc0);
  724.         cbw.bCBWFlags = CBWFLAGS_IN;
  725.         cbw.CBWCDB[0] = UMASS_SERVICE_ACTION_OUT;
  726.         cbw.CBWCDB[1] = 0x03;
  727.         break;
  728.     default:
  729.         DPRINTF(("%s: unknown device type.\n", sc->sc_dev.dv_xname));
  730.         break;
  731.     }
  732.  
  733.     /* get command endpoint address */
  734.     id = usbd_get_interface_descriptor(sc->sc_iface);
  735.     for (i = 0; i < id->bNumEndpoints; i++) {
  736.         ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
  737.         if (ed == NULL) {
  738.             return (USBD_IOERROR);
  739.         }
  740.  
  741.         if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  742.             UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
  743.             target_ep = ed->bEndpointAddress;
  744.     }
  745.  
  746.     /* open command endppoint */
  747.     err = usbd_open_pipe(sc->sc_iface, target_ep,
  748.         USBD_EXCLUSIVE_USE, &cmdpipe);
  749.     if (err) {
  750.         DPRINTF(("%s: open pipe for modem change cmd failed: %s\n",
  751.             sc->sc_dev.dv_xname, usbd_errstr(err)));
  752.         return (err);
  753.     }
  754.  
  755.     xfer = usbd_alloc_xfer(sc->sc_udev);
  756.     if (xfer == NULL) {
  757.         usbd_close_pipe(cmdpipe);
  758.         return (USBD_NOMEM);
  759.     } else {
  760.         bufp = usbd_alloc_buffer(xfer, UMASS_BBB_CBW_SIZE);
  761.         if (bufp == NULL)
  762.             err = USBD_NOMEM;
  763.         else {
  764.             n = UMASS_BBB_CBW_SIZE;
  765.             memcpy(bufp, &cbw, UMASS_BBB_CBW_SIZE);
  766.             usbd_setup_xfer(xfer, cmdpipe, 0, bufp, n,
  767.                 USBD_NO_COPY | USBD_SYNCHRONOUS, 0, NULL);
  768.             err = usbd_transfer(xfer);
  769.             if (err) {
  770.                 usbd_clear_endpoint_stall(cmdpipe);
  771.                 DPRINTF(("%s: send error:%s", __func__,
  772.                     usbd_errstr(err)));
  773.             }
  774.         }
  775.         usbd_close_pipe(cmdpipe);
  776.         usbd_free_buffer(xfer);
  777.         usbd_free_xfer(xfer);
  778.     }
  779.  
  780.     return (err);
  781. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement