From owner-p4-projects@FreeBSD.ORG Tue Dec 23 19:58:26 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id A59FB1065674; Tue, 23 Dec 2008 19:58:26 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6857D1065670 for ; Tue, 23 Dec 2008 19:58:26 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 538FF8FC17 for ; Tue, 23 Dec 2008 19:58:26 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id mBNJwQJk030242 for ; Tue, 23 Dec 2008 19:58:26 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id mBNJwQQ2030240 for perforce@freebsd.org; Tue, 23 Dec 2008 19:58:26 GMT (envelope-from hselasky@FreeBSD.org) Date: Tue, 23 Dec 2008 19:58:26 GMT Message-Id: <200812231958.mBNJwQQ2030240@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 155195 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Dec 2008 19:58:26 -0000 http://perforce.freebsd.org/chv.cgi?CH=155195 Change 155195 by hselasky@hselasky_laptop001 on 2008/12/23 19:57:37 U3G cleanup - move Huawei ID's out of the USB core. Affected files ... .. //depot/projects/usb/src/sys/dev/usb2/core/usb2_device.c#42 edit .. //depot/projects/usb/src/sys/dev/usb2/core/usb2_dynamic.c#7 edit .. //depot/projects/usb/src/sys/dev/usb2/core/usb2_dynamic.h#7 edit .. //depot/projects/usb/src/sys/dev/usb2/core/usb2_msctest.c#15 edit .. //depot/projects/usb/src/sys/dev/usb2/core/usb2_msctest.h#8 edit .. //depot/projects/usb/src/sys/dev/usb2/serial/u3g2.c#3 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_device.c#42 (text+ko) ==== @@ -1635,7 +1635,7 @@ goto repeat_set_config; } } - } else if (usb2_test_huawei(udev, &uaa) == 0) { + } else if (usb2_test_huawei_autoinst_p(udev, &uaa) == 0) { DPRINTFN(0, "Found Huawei auto-install disk!\n"); err = USB_ERR_STALLED; /* fake an error */ } ==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_dynamic.c#7 (text+ko) ==== @@ -39,6 +39,7 @@ static usb2_temp_setup_by_index_t usb2_temp_setup_by_index_w; static usb2_temp_unsetup_t usb2_temp_unsetup_w; static usb2_test_quirk_t usb2_test_quirk_w; +static usb2_test_huawei_autoinst_t usb2_test_huawei_autoinst_w; static usb2_quirk_ioctl_t usb2_quirk_ioctl_w; /* global variables */ @@ -46,6 +47,7 @@ usb2_temp_setup_by_index_t *usb2_temp_setup_by_index_p = &usb2_temp_setup_by_index_w; usb2_temp_unsetup_t *usb2_temp_unsetup_p = &usb2_temp_unsetup_w; usb2_test_quirk_t *usb2_test_quirk_p = &usb2_test_quirk_w; +usb2_test_huawei_autoinst_t *usb2_test_huawei_autoinst_p = &usb2_test_huawei_autoinst_w; usb2_quirk_ioctl_t *usb2_quirk_ioctl_p = &usb2_quirk_ioctl_w; devclass_t usb2_devclass_ptr = NULL; @@ -86,6 +88,13 @@ } } +static uint8_t +usb2_test_huawei_autoinst_w(struct usb2_device *udev, + struct usb2_attach_arg *uaa) +{ + return (USB_ERR_INVAL); +} + void usb2_quirk_unload(void *arg) { @@ -130,3 +139,17 @@ pause("WAIT", hz); } + +void +usb2_test_huawei_unload(void *arg) +{ + /* reset function pointers */ + + usb2_test_huawei_autoinst_p = &usb2_test_huawei_autoinst_w; + + /* wait for CPU to exit the loaded functions, if any */ + + /* XXX this is a tradeoff */ + + pause("WAIT", 16*hz); +} ==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_dynamic.h#7 (text+ko) ==== @@ -37,6 +37,8 @@ typedef usb2_error_t (usb2_temp_setup_by_index_t)(struct usb2_device *udev, uint16_t index); +typedef usb2_error_t (usb2_test_huawei_autoinst_t)(struct usb2_device *udev, + struct usb2_attach_arg *uaa); typedef uint8_t (usb2_test_quirk_t)(const struct usb2_lookup_info *info, uint16_t quirk); typedef int (usb2_quirk_ioctl_t)(unsigned long cmd, caddr_t data, @@ -52,11 +54,13 @@ extern usb2_temp_setup_by_index_t *usb2_temp_setup_by_index_p; extern usb2_temp_unsetup_t *usb2_temp_unsetup_p; extern usb2_test_quirk_t *usb2_test_quirk_p; +extern usb2_test_huawei_autoinst_t *usb2_test_huawei_autoinst_p; extern usb2_quirk_ioctl_t *usb2_quirk_ioctl_p; extern devclass_t usb2_devclass_ptr; /* function prototypes */ +void usb2_test_huawei_unload(void *); void usb2_temp_unload(void *); void usb2_quirk_unload(void *); void usb2_bus_unload(void *); ==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_msctest.c#15 (text+ko) ==== @@ -36,7 +36,6 @@ #include #include #include -#include #define USB_DEBUG_VAR usb2_debug @@ -577,164 +576,3 @@ free(sc, M_USB); return (err); } - -/* - * NOTE: The entries marked with XXX should be checked for the correct - * speed indication to set the buffer sizes. - */ -static const struct usb2_device_id u3g_devs[] = { - /* OEM: Option */ - {USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, - {USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUAD, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, - {USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GPLUS, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, - {USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAX36, U3GINFO(U3GSP_HSDPA, U3GFL_NONE))}, - {USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAXHSUPA, U3GINFO(U3GSP_HSDPA, U3GFL_NONE))}, - {USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_VODAFONEMC3G, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, - /* OEM: Qualcomm, Inc. */ - {USB_VPI(USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_ZTE_STOR, U3GINFO(U3GSP_CDMA, U3GFL_SCSI_EJECT))}, - {USB_VPI(USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM, U3GINFO(U3GSP_CDMA, U3GFL_SCSI_EJECT))}, - /* OEM: Huawei */ - {USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE, U3GINFO(U3GSP_HSDPA, U3GFL_HUAWEI_INIT))}, - {USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220, U3GINFO(U3GSP_HSPA, U3GFL_HUAWEI_INIT))}, - /* OEM: Novatel */ - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_CDMA_MODEM, U3GINFO(U3GSP_CDMA, U3GFL_SCSI_EJECT))}, - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ES620, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MC950D, U3GINFO(U3GSP_HSUPA, U3GFL_SCSI_EJECT))}, - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U720, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U727, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))}, - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740_2, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))}, - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U870, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V620, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V640, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V720, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V740, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))}, - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_X950D, U3GINFO(U3GSP_HSUPA, U3GFL_SCSI_EJECT))}, - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_XU870, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))}, - {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ZEROCD, U3GINFO(U3GSP_HSUPA, U3GFL_SCSI_EJECT))}, - {USB_VPI(USB_VENDOR_DELL, USB_PRODUCT_DELL_U740, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))}, - /* OEM: Merlin */ - {USB_VPI(USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - /* OEM: Sierra Wireless: */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ - {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_HS2300, U3GINFO(U3GSP_HSPA, U3GFL_NONE))}, /* XXX */ - /* Sierra TruInstaller device ID */ - {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_TRUINSTALL, U3GINFO(U3GSP_UMTS, U3GFL_SIERRA_INIT))}, -}; - -static void -u3g_sierra_init(struct usb2_device *udev) -{ - struct usb2_device_request req; - - DPRINTFN(0, "\n"); - - req.bmRequestType = UT_VENDOR; - req.bRequest = UR_SET_INTERFACE; - USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); - USETW(req.wIndex, UHF_PORT_CONNECTION); - USETW(req.wLength, 0); - - if (usb2_do_request_flags(udev, NULL, &req, - NULL, 0, NULL, USB_MS_HZ)) { - /* ignore any errors */ - } - return; -} - -static void -u3g_huawei_init(struct usb2_device *udev) -{ - struct usb2_device_request req; - - DPRINTFN(0, "\n"); - - req.bmRequestType = UT_WRITE_DEVICE; - req.bRequest = UR_SET_FEATURE; - USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); - USETW(req.wIndex, UHF_PORT_SUSPEND); - USETW(req.wLength, 0); - - if (usb2_do_request_flags(udev, NULL, &req, - NULL, 0, NULL, USB_MS_HZ)) { - /* ignore any errors */ - } - return; -} - -int -usb2_lookup_huawei(struct usb2_attach_arg *uaa) -{ - /* Calling the lookup function will also set the driver info! */ - return (usb2_lookup_id_by_uaa(u3g_devs, sizeof(u3g_devs), uaa)); -} - -/* - * The following function handles 3G modem devices (E220, Mobile, - * etc.) with auto-install flash disks for Windows/MacOSX on the first - * interface. After some command or some delay they change appearance - * to a modem. - */ -usb2_error_t -usb2_test_huawei(struct usb2_device *udev, struct usb2_attach_arg *uaa) -{ - struct usb2_interface *iface; - struct usb2_interface_descriptor *id; - uint32_t flags; - - if (udev == NULL) { - return (USB_ERR_INVAL); - } - iface = usb2_get_iface(udev, 0); - if (iface == NULL) { - return (USB_ERR_INVAL); - } - id = iface->idesc; - if (id == NULL) { - return (USB_ERR_INVAL); - } - if (id->bInterfaceClass != UICLASS_MASS) { - return (USB_ERR_INVAL); - } - if (usb2_lookup_huawei(uaa)) { - /* no device match */ - return (USB_ERR_INVAL); - } - flags = USB_GET_DRIVER_INFO(uaa); - - if (flags & U3GFL_HUAWEI_INIT) { - u3g_huawei_init(udev); - } else if (flags & U3GFL_SCSI_EJECT) { - return (usb2_test_autoinstall(udev, 0, 1)); - } else if (flags & U3GFL_SIERRA_INIT) { - u3g_sierra_init(udev); - } else { - /* no quirks */ - return (USB_ERR_INVAL); - } - return (0); /* success */ -} ==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_msctest.h#8 (text+ko) ==== @@ -29,30 +29,5 @@ usb2_error_t usb2_test_autoinstall(struct usb2_device *udev, uint8_t iface_index, uint8_t do_eject); -usb2_error_t usb2_test_huawei(struct usb2_device *udev, - struct usb2_attach_arg *uaa); -int usb2_lookup_huawei(struct usb2_attach_arg *uaa); - -/* Huawei specific defines */ - -#define U3GINFO(flag,speed) ((flag)|((speed) * 256)) -#define U3G_GET_SPEED(uaa) (USB_GET_DRIVER_INFO(uaa) / 256) - -#define U3GFL_NONE 0x00 -#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 U3GSP_GPRS 0 -#define U3GSP_EDGE 1 -#define U3GSP_CDMA 2 -#define U3GSP_UMTS 3 -#define U3GSP_HSDPA 4 -#define U3GSP_HSUPA 5 -#define U3GSP_HSPA 6 -#define U3GSP_MAX 7 #endif /* _USB2_MSCTEST_H_ */ ==== //depot/projects/usb/src/sys/dev/usb2/serial/u3g2.c#3 (text+ko) ==== @@ -37,7 +37,7 @@ #include #include #include -#include +#include #define USB_DEBUG_VAR u3g_debug @@ -50,6 +50,8 @@ #include #include #include +#include +#include #include @@ -66,6 +68,20 @@ #define U3G_CONFIG_INDEX 0 #define U3G_BSIZE 2048 +#define U3GSP_GPRS 0 +#define U3GSP_EDGE 1 +#define U3GSP_CDMA 2 +#define U3GSP_UMTS 3 +#define U3GSP_HSDPA 4 +#define U3GSP_HSUPA 5 +#define U3GSP_HSPA 6 +#define U3GSP_MAX 7 + +#define U3GFL_NONE 0x00 /* No flags */ +#define U3GFL_HUAWEI_INIT 0x01 /* Init command required */ +#define U3GFL_SCSI_EJECT 0x02 /* SCSI eject command required */ +#define U3GFL_SIERRA_INIT 0x04 /* Init command required */ + struct u3g_speeds_s { uint32_t ispeed; uint32_t ospeed; @@ -98,6 +114,8 @@ static void u3g_start_write(struct usb2_com_softc *ucom); static void u3g_stop_write(struct usb2_com_softc *ucom); +static int u3g_driver_loaded(struct module *mod, int what, void *arg); + static const struct usb2_config u3g_config[U3G_N_TRANSFER] = { [0] = { @@ -151,10 +169,195 @@ .size = sizeof(struct u3g_softc), }; -DRIVER_MODULE(u3g, ushub, u3g_driver, u3g_devclass, NULL, 0); +DRIVER_MODULE(u3g, ushub, u3g_driver, u3g_devclass, u3g_driver_loaded, 0); MODULE_DEPEND(u3g, usb2_serial, 1, 1, 1); MODULE_DEPEND(u3g, usb2_core, 1, 1, 1); +/* Huawei specific defines */ + +#define U3GINFO(flag,speed) ((flag)|((speed) * 256)) +#define U3G_GET_SPEED(uaa) (USB_GET_DRIVER_INFO(uaa) / 256) + +/* + * NOTE: The entries marked with XXX should be checked for the correct + * speed indication to set the buffer sizes. + */ +static const struct usb2_device_id u3g_devs[] = { + /* OEM: Option */ + {USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, + {USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUAD, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, + {USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GPLUS, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, + {USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAX36, U3GINFO(U3GSP_HSDPA, U3GFL_NONE))}, + {USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAXHSUPA, U3GINFO(U3GSP_HSDPA, U3GFL_NONE))}, + {USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_VODAFONEMC3G, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, + /* OEM: Qualcomm, Inc. */ + {USB_VPI(USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_ZTE_STOR, U3GINFO(U3GSP_CDMA, U3GFL_SCSI_EJECT))}, + {USB_VPI(USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM, U3GINFO(U3GSP_CDMA, U3GFL_SCSI_EJECT))}, + /* OEM: Huawei */ + {USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE, U3GINFO(U3GSP_HSDPA, U3GFL_HUAWEI_INIT))}, + {USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220, U3GINFO(U3GSP_HSPA, U3GFL_HUAWEI_INIT))}, + /* OEM: Novatel */ + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_CDMA_MODEM, U3GINFO(U3GSP_CDMA, U3GFL_SCSI_EJECT))}, + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ES620, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MC950D, U3GINFO(U3GSP_HSUPA, U3GFL_SCSI_EJECT))}, + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U720, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U727, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))}, + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740_2, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))}, + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U870, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V620, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V640, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V720, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */ + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V740, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))}, + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_X950D, U3GINFO(U3GSP_HSUPA, U3GFL_SCSI_EJECT))}, + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_XU870, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))}, + {USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ZEROCD, U3GINFO(U3GSP_HSUPA, U3GFL_SCSI_EJECT))}, + {USB_VPI(USB_VENDOR_DELL, USB_PRODUCT_DELL_U740, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))}, + /* OEM: Merlin */ + {USB_VPI(USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + /* OEM: Sierra Wireless: */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2, U3GINFO(U3GSP_HSDPA, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_HS2300, U3GINFO(U3GSP_HSDPA, U3GFL_NONE))}, + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */ + {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_HS2300, U3GINFO(U3GSP_HSPA, U3GFL_NONE))}, /* XXX */ + /* Sierra TruInstaller device ID */ + {USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_TRUINSTALL, U3GINFO(U3GSP_UMTS, U3GFL_SIERRA_INIT))}, +}; + +static void +u3g_sierra_init(struct usb2_device *udev) +{ + struct usb2_device_request req; + + DPRINTFN(0, "\n"); + + req.bmRequestType = UT_VENDOR; + req.bRequest = UR_SET_INTERFACE; + USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); + USETW(req.wIndex, UHF_PORT_CONNECTION); + USETW(req.wLength, 0); + + if (usb2_do_request_flags(udev, NULL, &req, + NULL, 0, NULL, USB_MS_HZ)) { + /* ignore any errors */ + } + return; +} + +static void +u3g_huawei_init(struct usb2_device *udev) +{ + struct usb2_device_request req; + + DPRINTFN(0, "\n"); + + req.bmRequestType = UT_WRITE_DEVICE; + req.bRequest = UR_SET_FEATURE; + USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); + USETW(req.wIndex, UHF_PORT_SUSPEND); + USETW(req.wLength, 0); + + if (usb2_do_request_flags(udev, NULL, &req, + NULL, 0, NULL, USB_MS_HZ)) { + /* ignore any errors */ + } + return; +} + +static int +u3g_lookup_huawei(struct usb2_attach_arg *uaa) +{ + /* Calling the lookup function will also set the driver info! */ + return (usb2_lookup_id_by_uaa(u3g_devs, sizeof(u3g_devs), uaa)); +} + +/* + * The following function handles 3G modem devices (E220, Mobile, + * etc.) with auto-install flash disks for Windows/MacOSX on the first + * interface. After some command or some delay they change appearance + * to a modem. + */ +static usb2_error_t +u3g_test_huawei_autoinst(struct usb2_device *udev, + struct usb2_attach_arg *uaa) +{ + struct usb2_interface *iface; + struct usb2_interface_descriptor *id; + uint32_t flags; + + if (udev == NULL) { + return (USB_ERR_INVAL); + } + iface = usb2_get_iface(udev, 0); + if (iface == NULL) { + return (USB_ERR_INVAL); + } + id = iface->idesc; + if (id == NULL) { + return (USB_ERR_INVAL); + } + if (id->bInterfaceClass != UICLASS_MASS) { + return (USB_ERR_INVAL); + } + if (u3g_lookup_huawei(uaa)) { + /* no device match */ + return (USB_ERR_INVAL); + } + flags = USB_GET_DRIVER_INFO(uaa); + + if (flags & U3GFL_HUAWEI_INIT) { + u3g_huawei_init(udev); + } else if (flags & U3GFL_SCSI_EJECT) { + return (usb2_test_autoinstall(udev, 0, 1)); + } else if (flags & U3GFL_SIERRA_INIT) { + u3g_sierra_init(udev); + } else { + /* no quirks */ + return (USB_ERR_INVAL); + } + return (0); /* success */ +} + +static int +u3g_driver_loaded(struct module *mod, int what, void *arg) +{ + switch (what) { + case MOD_LOAD: + /* register our autoinstall handler */ + usb2_test_huawei_autoinst_p = &u3g_test_huawei_autoinst; + break; + case MOD_UNLOAD: + usb2_test_huawei_unload(NULL); + break; + default: + return (EOPNOTSUPP); + } + return (0); +} + static int u3g_probe(device_t self) { @@ -169,7 +372,7 @@ if (uaa->info.bInterfaceClass != UICLASS_VENDOR) { return (ENXIO); } - return (usb2_lookup_huawei(uaa)); + return (u3g_lookup_huawei(uaa)); } static int