From owner-svn-src-all@FreeBSD.ORG Fri Feb 13 19:49:51 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DA1F0106567B; Fri, 13 Feb 2009 19:49:51 +0000 (UTC) (envelope-from n_hibma@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C07BF8FC22; Fri, 13 Feb 2009 19:49:51 +0000 (UTC) (envelope-from n_hibma@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n1DJnpkk097746; Fri, 13 Feb 2009 19:49:51 GMT (envelope-from n_hibma@svn.freebsd.org) Received: (from n_hibma@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n1DJnprm097744; Fri, 13 Feb 2009 19:49:51 GMT (envelope-from n_hibma@svn.freebsd.org) Message-Id: <200902131949.n1DJnprm097744@svn.freebsd.org> From: Nick Hibma Date: Fri, 13 Feb 2009 19:49:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r188597 - head/sys/dev/usb X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 13 Feb 2009 19:49:53 -0000 Author: n_hibma Date: Fri Feb 13 19:49:51 2009 New Revision: 188597 URL: http://svn.freebsd.org/changeset/base/188597 Log: Add support for CMOTECH devices (not sure whether this is the correct name) (not sure whether this works correctly, but should be close). Fix the stub attach phase for some Novatel cards. They expect the CSW (repsonse to CBW, SCSI eject command) to be fetched before switching to modem mode. MFC after: 2 weeks Modified: head/sys/dev/usb/u3g.c head/sys/dev/usb/usbdevs Modified: head/sys/dev/usb/u3g.c ============================================================================== --- head/sys/dev/usb/u3g.c Fri Feb 13 19:49:35 2009 (r188596) +++ head/sys/dev/usb/u3g.c Fri Feb 13 19:49:51 2009 (r188597) @@ -87,25 +87,25 @@ struct ucom_callback u3g_callback = { struct u3g_speeds_s { - u_int32_t ispeed; // Speed in bits per second - u_int32_t ospeed; // Speed in bits per second + u_int32_t ispeed; + u_int32_t ospeed; }; static const struct u3g_speeds_s u3g_speeds[] = { -#define U3GSP_GPRS 0 - {64000, 64000}, -#define U3GSP_EDGE 1 - {384000, 64000}, -#define U3GSP_CDMA 2 - {384000, 64000}, -#define U3GSP_UMTS 3 - {384000, 64000}, -#define U3GSP_HSDPA 4 - {1200000, 384000}, -#define U3GSP_HSUPA 5 - {1200000, 384000}, -#define U3GSP_HSPA 6 - {7200000, 384000}, +#define U3GSP_GPRS 0 + {64000, 64000}, +#define U3GSP_EDGE 1 + {384000, 64000}, +#define U3GSP_CDMA 2 + {384000, 64000}, +#define U3GSP_UMTS 3 + {384000, 64000}, +#define U3GSP_HSDPA 4 + {1200000, 384000}, +#define U3GSP_HSUPA 5 + {1200000, 384000}, +#define U3GSP_HSPA 6 + {7200000, 384000}, }; #define U3GIBUFSIZE 1024 @@ -122,7 +122,8 @@ struct u3g_dev_type_s { #define U3GFL_HUAWEI_INIT 0x01 // Requires init command (Huawei cards) #define U3GFL_SCSI_EJECT 0x02 // Requires SCSI eject command (Novatel) #define U3GFL_SIERRA_INIT 0x04 // Requires init command (Sierra cards) -#define U3GFL_STUB_WAIT 0x08 // Device reappears after a short delay +#define U3GFL_CMOTECH_INIT 0x08 // Requires init command (CMOTECH cards) +#define U3GFL_STUB_WAIT 0x80 // Device reappears after a short delay }; // Note: The entries marked with XXX should be checked for the correct speed @@ -184,10 +185,13 @@ static const struct u3g_dev_type_s u3g_d {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765 }, U3GSP_UMTS, U3GFL_NONE }, // XXX {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U }, U3GSP_UMTS, U3GFL_NONE }, // XXX {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2 }, U3GSP_HSDPA, U3GFL_NONE }, // XXX - {{ USB_VENDOR_HP, USB_PRODUCT_HP_HS2300 }, U3GSP_HSDPA, U3GFL_NONE }, // XXX {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780 }, U3GSP_UMTS, U3GFL_NONE }, // XXX {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_TRUINSTALL }, U3GSP_UMTS, U3GFL_SIERRA_INIT }, // Sierra TruInstaller device ID + {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_TRUINSTALL }, U3GSP_UMTS, U3GFL_SIERRA_INIT }, + {{ USB_VENDOR_HP, USB_PRODUCT_HP_HS2300 }, U3GSP_HSDPA, U3GFL_NONE }, + /* OEM: CMOTECH */ + {{ USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CGU628 }, U3GSP_HSDPA, U3GFL_CMOTECH_INIT }, + {{ USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_DISK }, U3GSP_HSDPA, U3GFL_NONE }, }; #define u3g_lookup(v, p) ((const struct u3g_dev_type_s *)usb_lookup(u3g_devs, v, p)) @@ -437,7 +441,7 @@ MODULE_VERSION(u3g, 1); struct u3gstub_softc { device_t sc_dev; usbd_device_handle sc_udev; - usbd_pipe_handle sc_pipe; + usbd_pipe_handle sc_pipe_out, sc_pipe_in; usbd_xfer_handle sc_xfer; }; @@ -457,6 +461,25 @@ u3gstub_huawei_init(struct u3gstub_softc return 1; } +static void +u3gstub_BBB_cb(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status err) +{ + struct u3gstub_softc *sc = (struct u3gstub_softc *) priv; + unsigned char cmd[13]; + + if (err) { + device_printf(sc->sc_dev, + "Failed to send CD eject command to " + "change to modem mode\n"); + } else { + usbd_setup_xfer(sc->sc_xfer, sc->sc_pipe_in, NULL, cmd, sizeof(cmd), + 0, USBD_DEFAULT_TIMEOUT, NULL); + int err = usbd_transfer(sc->sc_xfer) != USBD_NORMAL_COMPLETION; + if (err != USBD_NORMAL_COMPLETION && err != USBD_IN_PROGRESS) + DPRINTF("failed to start transfer (CSW)\n"); + } +} + static int u3gstub_scsi_eject(struct u3gstub_softc *sc, struct usb_attach_arg *uaa) { @@ -467,7 +490,7 @@ u3gstub_scsi_eject(struct u3gstub_softc 0x55, 0x53, 0x42, 0x43, /* 0..3: Command Block Wrapper (CBW) signature */ 0x01, 0x00, 0x00, 0x00, /* 4..7: CBW Tag, unique 32-bit number */ 0x00, 0x00, 0x00, 0x00, /* 8..11: CBW Transfer Length, no data here */ - 0x00, /* 12: CBW Flag: output, so 0 */ + 0x00, /* 12: CBW Flag: output */ 0x00, /* 13: CBW Lun */ 0x06, /* 14: CBW Length */ @@ -488,11 +511,33 @@ u3gstub_scsi_eject(struct u3gstub_softc /* Find the bulk-out endpoints */ id = usbd_get_interface_descriptor(uaa->iface); - for (i = 0 ; i < id->bNumEndpoints ; i++) { + for (i = 0 ; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(uaa->iface, i); if (ed != NULL - && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT - && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) + && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { + if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) { + if (usbd_open_pipe(uaa->iface, + ed->bEndpointAddress, + USBD_EXCLUSIVE_USE, + &sc->sc_pipe_out) + != USBD_NORMAL_COMPLETION) { + DPRINTF("failed to open bulk-out pipe on endpoint %d\n", + ed->bEndpointAddress); + return 0; + } + } else { + if (usbd_open_pipe(uaa->iface, + ed->bEndpointAddress, + USBD_EXCLUSIVE_USE, + &sc->sc_pipe_in) + != USBD_NORMAL_COMPLETION) { + DPRINTF("failed to open bulk-in pipe on endpoint %d\n", + ed->bEndpointAddress); + return 0; + } + } + } + if (sc->sc_pipe_out && sc->sc_pipe_in) break; } @@ -501,10 +546,88 @@ u3gstub_scsi_eject(struct u3gstub_softc return 0; } - if (usbd_open_pipe(uaa->iface, ed->bEndpointAddress, - USBD_EXCLUSIVE_USE, &sc->sc_pipe) != USBD_NORMAL_COMPLETION) { - DPRINTF("failed to open bulk-out pipe on endpoint %d\n", - ed->bEndpointAddress); + sc->sc_xfer = usbd_alloc_xfer(uaa->device); + if (sc->sc_xfer == NULL) { + DPRINTF("failed to allocate xfer\n"); + return 0; + } + + usbd_setup_xfer(sc->sc_xfer, sc->sc_pipe_out, NULL, cmd, sizeof(cmd), + 0, USBD_DEFAULT_TIMEOUT, u3gstub_BBB_cb); + int err = usbd_transfer(sc->sc_xfer) != USBD_NORMAL_COMPLETION; + if (err != USBD_NORMAL_COMPLETION && err != USBD_IN_PROGRESS) { + DPRINTF("failed to start transfer (CBW)\n"); + return 0; + } + + return 1; +} + +static int +u3gstub_cmotech_init(struct u3gstub_softc *sc, struct usb_attach_arg *uaa) +{ + /* See definition of umass_bbb_cbw_t in sys/dev/usb/umass.c + * in sys/cam/scsi/scsi_all.h . + */ + unsigned char cmd[31] = { + 0x55, 0x53, 0x42, 0x43, /* 0..3: Command Block Wrapper (CBW) signature */ + 0x01, 0x00, 0x00, 0x00, /* 4..7: CBW Tag, unique 32-bit number */ + 0x00, 0x00, 0x00, 0x00, /* 8..11: CBW Transfer Length, no data here */ + 0x80, /* 12: CBW Flag: output, so 0 */ + 0x00, /* 13: CBW Lun */ + 0x08, /* 14: CBW Length */ + + 0xff, /* 15+0 */ + 0x52, /* 15+1 */ + 0x44, /* 15+2 */ + 0x45, /* 15+2 */ + 0x56, /* 15+4 */ + 0x43, /* 15+5 */ + 0x48, /* 15+5 */ + 0x47, /* 15+5 */ + 0x00, 0x00, 0x00, 0x00, /* 15+8..15: unused */ + 0x00, 0x00, 0x00, 0x00 + }; + + usb_interface_descriptor_t *id; + usb_endpoint_descriptor_t *ed = NULL; + int i; + + + /* Find the bulk-out endpoints */ + id = usbd_get_interface_descriptor(uaa->iface); + for (i = 0 ; i < id->bNumEndpoints ; i++) { + ed = usbd_interface2endpoint_descriptor(uaa->iface, i); + if (ed != NULL + && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { + if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) { + if (usbd_open_pipe(uaa->iface, + ed->bEndpointAddress, + USBD_EXCLUSIVE_USE, + &sc->sc_pipe_out) + != USBD_NORMAL_COMPLETION) { + DPRINTF("failed to open bulk-out pipe on endpoint %d\n", + ed->bEndpointAddress); + return 0; + } + } else { + if (usbd_open_pipe(uaa->iface, + ed->bEndpointAddress, + USBD_EXCLUSIVE_USE, + &sc->sc_pipe_in) + != USBD_NORMAL_COMPLETION) { + DPRINTF("failed to open bulk-in pipe on endpoint %d\n", + ed->bEndpointAddress); + return 0; + } + } + } + if (sc->sc_pipe_out && sc->sc_pipe_in) + break; + } + + if (i == id->bNumEndpoints) { + DPRINTF("failed to find bulk-out pipe\n"); return 0; } @@ -514,11 +637,11 @@ u3gstub_scsi_eject(struct u3gstub_softc return 0; } - usbd_setup_xfer(sc->sc_xfer, sc->sc_pipe, NULL, cmd, sizeof(cmd), - 0, USBD_DEFAULT_TIMEOUT, NULL); + usbd_setup_xfer(sc->sc_xfer, sc->sc_pipe_out, NULL, cmd, sizeof(cmd), + 0, USBD_DEFAULT_TIMEOUT, u3gstub_BBB_cb); int err = usbd_transfer(sc->sc_xfer) != USBD_NORMAL_COMPLETION; if (err != USBD_NORMAL_COMPLETION && err != USBD_IN_PROGRESS) { - DPRINTF("failed to start transfer\n"); + DPRINTF("failed to start transfer (CBW)\n"); return 0; } @@ -563,6 +686,7 @@ u3gstub_match(device_t self) if (u3g_dev_type->flags&U3GFL_HUAWEI_INIT || u3g_dev_type->flags&U3GFL_SCSI_EJECT || u3g_dev_type->flags&U3GFL_SIERRA_INIT + || u3g_dev_type->flags&U3GFL_CMOTECH_INIT || u3g_dev_type->flags&U3GFL_STUB_WAIT) { /* We assume that if the first interface is still a mass * storage device the device has not yet changed appearance. @@ -620,6 +744,12 @@ u3gstub_attach(device_t self) "changing Sierra modem to modem mode\n"); if (!u3gstub_sierra_init(sc, uaa)) return ENXIO; + } else if (u3g_dev_type->flags&U3GFL_CMOTECH_INIT) { + if (bootverbose) + device_printf(sc->sc_dev, + "changing CMOTECH modem to modem mode\n"); + if (!u3gstub_cmotech_init(sc, uaa)) + return ENXIO; } else if (u3g_dev_type->flags&U3GFL_STUB_WAIT) { if (bootverbose) device_printf(sc->sc_dev, "waiting for modem to change " @@ -638,9 +768,13 @@ u3gstub_detach(device_t self) if (sc->sc_xfer) usbd_free_xfer(sc->sc_xfer); - if (sc->sc_pipe) { - usbd_abort_pipe(sc->sc_pipe); - usbd_close_pipe(sc->sc_pipe); + if (sc->sc_pipe_in) { + usbd_abort_pipe(sc->sc_pipe_in); + usbd_close_pipe(sc->sc_pipe_in); + } + if (sc->sc_pipe_out) { + usbd_abort_pipe(sc->sc_pipe_out); + usbd_close_pipe(sc->sc_pipe_out); } return 0; Modified: head/sys/dev/usb/usbdevs ============================================================================== --- head/sys/dev/usb/usbdevs Fri Feb 13 19:49:35 2009 (r188596) +++ head/sys/dev/usb/usbdevs Fri Feb 13 19:49:51 2009 (r188597) @@ -613,7 +613,7 @@ vendor GIGASET 0x1690 Gigaset vendor GLOBALSUN 0x16ab Global Sun Technology vendor ANYDATA 0x16d5 AnyDATA Corporation vendor JABLOTRON 0x16d6 Jablotron -vendor CMOTECH 0x16d8 CMOTECH Co., Ltd. +vendor CMOTECH 0x16d8 C-motech vendor AXESSTEL 0x1726 Axesstel Co., Ltd. vendor LINKSYS4 0x1737 Linksys vendor SENAO 0x1740 Senao @@ -1030,9 +1030,11 @@ product CISCOLINKSYS WUSB54GR 0x0023 WUS product CISCOLINKSYS WUSBF54G 0x0024 WUSBF54G /* CMOTECH products */ -product CMOTECH CNU510 0x5141 CMOTECH CDMA Technologies USB modem +product CMOTECH CNU510 0x5141 CDMA Technologies USB modem product CMOTECH CNU550 0x5543 CDMA 2000 1xRTT/1xEVDO USB modem -product CMOTECH CDMA_MODEM1 0x6280 CMOTECH CDMA Technologies USB modem +product CMOTECH CGU628 0x6006 CGU-628 +product CMOTECH CDMA_MODEM1 0x6280 CDMA Technologies USB modem +product CMOTECH DISK 0xf000 disk mode /* Compaq products */ product COMPAQ IPAQPOCKETPC 0x0003 iPAQ PocketPC