NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/37978: [PATCH] add NTT DoCoMo A2502 3G/HSDPA modem support to uhmodem driver
>Number: 37978
>Category: kern
>Synopsis: [PATCH] add NTT DoCoMo A2502 3G/HSDPA modem support to uhmodem
>driver
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Thu Feb 07 21:15:00 +0000 2008
>Originator: Yojiro UO
>Release: NetBSD 4.99.52
>Organization:
>Environment:
System: NetBSD robohoc 4.99.52 NetBSD 4.99.52 (ALIX) #307: Thu Feb 7 00:49:20
JST 2008 yuo%nui.org@localhost:/usr/src/sys/arch/i386/compile/obj/ALIX i386
Architecture: i386
Machine: i386
>Description:
- new device support: "AnyData.inc Foma A2502 3G/HSDPA modem"
- fix some code to share E220 and A2502
- fix typo and comment in uhmodem.c
Note: i submitted this pr about 30 hours ago, but I've not receive any
automatically reply message and I can't find the report in gnats DB. So,
i resubmit it via web-interface. please ignore if duplicated.
>How-To-Repeat:
>Fix:
apply following patch
Index: ubsavar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ubsavar.h,v
retrieving revision 1.2
diff -u -r1.2 ubsavar.h
--- ubsavar.h 21 Jan 2008 12:16:31 -0000 1.2
+++ ubsavar.h 6 Feb 2008 16:20:01 -0000
@@ -142,6 +142,7 @@
u_char sc_dying; /* disconnecting */
u_char sc_quadumts;
+ u_int16_t sc_devflags;
};
Index: uhmodem.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/uhmodem.c,v
retrieving revision 1.1
diff -u -r1.1 uhmodem.c
--- uhmodem.c 21 Jan 2008 11:36:47 -0000 1.1
+++ uhmodem.c 6 Feb 2008 16:20:02 -0000
@@ -107,6 +107,10 @@
#include <dev/usb/ucomvar.h>
#include <dev/usb/ubsavar.h>
+/* vendor specific bRequest */
+#define UHMODEM_REGWRITE 0x20
+#define UHMODEM_REGREAD 0x21
+#define UHMODEM_SETUP 0x22
#define UHMODEMIBUFSIZE 4096
#define UHMODEMOBUFSIZE 4096
@@ -124,13 +128,14 @@
Static int uhmodem_open(void *, int);
Static usbd_status e220_modechange_request(usbd_device_handle);
-Static usbd_status e220_endpointhalt(usbd_device_handle);
+Static usbd_status uhmodem_endpointhalt(struct ubsa_softc *, int);
+Static usbd_status uhmodem_regwrite(usbd_device_handle, uint8_t *, size_t);
+Static usbd_status uhmodem_regread(usbd_device_handle, uint8_t *, size_t);
+Static usbd_status uhmodem_regsetup(usbd_device_handle, uint16_t);
+Static usbd_status a2502_init(usbd_device_handle);
#if 0
-Static usbd_status e220_testreq(usbd_device_handle);
+Static usbd_status e220_init(usbd_device_handle);
#endif
-void e220_modechange_request_test(usbd_device_handle);
-
-#define UHMODEM_MAXCONN 2
struct uhmodem_softc {
struct ubsa_softc sc_ubsa;
@@ -147,11 +152,21 @@
NULL
};
-Static const struct usb_devno uhmodem_devs[] = {
+struct uhmodem_type {
+ struct usb_devno uhmodem_dev;
+ u_int16_t uhmodem_coms; /* number of serial interfaces
on the device */
+ u_int16_t uhmodem_flags;
+#define E220 0x0001
+#define A2502 0x0002
+};
+
+Static const struct uhmodem_type uhmodem_devs[] = {
/* HUAWEI E220 / Emobile D0[12]HW */
- { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220 },
+ {{ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220 }, 2, E220},
+ /* ANYDATA / NTT DoCoMo A2502 */
+ {{ USB_VENDOR_ANYDATA, USB_PRODUCT_ANYDATA_A2502 }, 3, A2502},
};
-#define uhmodem_lookup(v, p) usb_lookup(uhmodem_devs, v, p)
+#define uhmodem_lookup(v, p) ((const struct uhmodem_type
*)usb_lookup(uhmodem_devs, v, p))
USB_DECLARE_DRIVER(uhmodem);
@@ -215,7 +230,8 @@
sc->sc_ubsa.sc_quadumts = 1;
sc->sc_ubsa.sc_config_index = 0;
- sc->sc_ubsa.sc_numif = 2; /* E220 has 2coms */
+ sc->sc_ubsa.sc_numif = uhmodem_lookup(uaa->vendor,
uaa->product)->uhmodem_coms;
+ sc->sc_ubsa.sc_devflags = uhmodem_lookup(uaa->vendor,
uaa->product)->uhmodem_flags;
DPRINTF(("uhmodem attach: sc = %p\n", sc));
@@ -308,10 +324,10 @@
sprintf(comname, "modem");
break;
case 1:
- sprintf(comname, "monitor");
+ sprintf(comname, "alt#1");
break;
case 2:
- sprintf(comname, "unknown");
+ sprintf(comname, "alt#2");
break;
default:
sprintf(comname, "int#%d", i);
@@ -332,6 +348,13 @@
i, uca.bulkin, uca.bulkout,
sc->sc_ubsa.sc_intr_number));
sc->sc_ubsa.sc_subdevs[i] = config_found_sm_loc(self,
"ucombus", NULL,
&uca, ucomprint, ucomsubmatch);
+
+ /* issue endpoint halt to each interface */
+ err = uhmodem_endpointhalt(&sc->sc_ubsa, i);
+ if (err)
+ printf("%s: endpointhalt fail\n", __func__);
+ else
+ usbd_delay_ms(sc->sc_ubsa.sc_udev, 50);
} /* end of Interface loop */
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_ubsa.sc_udev,
@@ -405,19 +428,28 @@
DPRINTF(("%s: sc = %p\n", __func__, sc));
- err = e220_endpointhalt(sc->sc_udev);
+ err = uhmodem_endpointhalt(sc, 0);
if (err)
printf("%s: endpointhalt fail\n", __func__);
else
usbd_delay_ms(sc->sc_udev, 50);
-#if 0 /* currenly disable */
- err = e220_testreq(sc->sc_udev);
- if (err)
- printf("%s: send testreq fail\n", __func__);
- else
- usbd_delay_ms(sc->sc_udev, 50);
-#endif
+ if (sc->sc_devflags & A2502) {
+ err = a2502_init(sc->sc_udev);
+ if (err)
+ printf("%s: a2502init fail\n", __func__);
+ else
+ usbd_delay_ms(sc->sc_udev, 50);
+ }
+#if 0 /* currently disabled */
+ if (sc->sc_devflags & E220) {
+ err = e220_init(sc->sc_udev);
+ if (err)
+ printf("%s: e220init fail\n", __func__);
+ else
+ usbd_delay_ms(sc->sc_udev, 50);
+ }
+#endif
if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
/* XXX only iface# = 0 has intr line */
@@ -471,36 +503,135 @@
}
Static usbd_status
-e220_endpointhalt(usbd_device_handle dev)
+uhmodem_endpointhalt(struct ubsa_softc *sc, int iface)
+{
+ usb_device_request_t req;
+ usb_endpoint_descriptor_t *ed;
+ usb_interface_descriptor_t *id;
+ usbd_status err;
+ int i;
+
+ /* Find the endpoints */
+ id = usbd_get_interface_descriptor(sc->sc_iface[iface]);
+
+ for (i = 0; i < id->bNumEndpoints; i++) {
+ ed = usbd_interface2endpoint_descriptor(sc->sc_iface[iface], i);
+ if (ed == NULL)
+ return (EIO);
+
+ if (UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
+ /* issue ENDPOINT_HALT request */
+ req.bmRequestType = UT_WRITE_ENDPOINT;
+ req.bRequest = UR_CLEAR_FEATURE;
+ USETW(req.wValue, UF_ENDPOINT_HALT);
+ USETW(req.wIndex, ed->bEndpointAddress);
+ USETW(req.wLength, 0);
+ err = usbd_do_request(sc->sc_udev, &req, 0);
+ if (err) {
+ DPRINTF(("%s: ENDPOINT_HALT to EP:%d fail\n",
+ __func__, ed->bEndpointAddress));
+ return (EIO);
+ }
+
+ }
+ } /* end of Endpoint loop */
+
+ return (0);
+}
+
+Static usbd_status
+uhmodem_regwrite(usbd_device_handle dev, uint8_t *data, size_t len)
+{
+ usb_device_request_t req;
+ usbd_status err;
+
+ req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
+ req.bRequest = UHMODEM_REGWRITE;
+ USETW(req.wValue, 0x0000);
+ USETW(req.wIndex, 0x0000);
+ USETW(req.wLength, len);
+ err = usbd_do_request(dev, &req, data);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+Static usbd_status
+uhmodem_regread(usbd_device_handle dev, uint8_t *data, size_t len)
+{
+ usb_device_request_t req;
+ usbd_status err;
+
+ req.bmRequestType = UT_READ_CLASS_INTERFACE;
+ req.bRequest = UHMODEM_REGREAD;
+ USETW(req.wValue, 0x0000);
+ USETW(req.wIndex, 0x0000);
+ USETW(req.wLength, len);
+ err = usbd_do_request(dev, &req, data);
+
+ if (err)
+ return err;
+
+ return 0;
+}
+
+Static usbd_status
+uhmodem_regsetup(usbd_device_handle dev, uint16_t cmd)
{
usb_device_request_t req;
usbd_status err;
- /* CLEAR feature / endpoint halt to modem i/o */
- req.bmRequestType = UT_WRITE_ENDPOINT;
- req.bRequest = UR_CLEAR_FEATURE;
- USETW(req.wValue, UF_ENDPOINT_HALT);
- USETW(req.wIndex, 0x0082); /* should get value from softc etc.*/
+ req.bmRequestType = UT_READ_CLASS_INTERFACE;
+ req.bRequest = UHMODEM_SETUP;
+ USETW(req.wValue, cmd);
+ USETW(req.wIndex, 0x0000);
USETW(req.wLength, 0);
err = usbd_do_request(dev, &req, 0);
- if (err) {
- DPRINTF(("%s: E220 request test ENDPOINT_HALT fail\n",
__func__));
- return (EIO);
+
+ if (err)
+ return err;
+
+ return 0;
+}
+
+Static usbd_status
+a2502_init(usbd_device_handle dev)
+{
+ uint8_t data[8];
+ static uint8_t init_cmd[] = {0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x08};
+#ifdef UHMODEM_DEBUG
+ int i;
+#endif
+ if (uhmodem_regread(dev, data, 7)) {
+ DPRINTF(("%s: read fail\n", __func__));
+ return EIO;
}
- req.bmRequestType = UT_WRITE_ENDPOINT;
- req.bRequest = UR_CLEAR_FEATURE;
- USETW(req.wValue, UF_ENDPOINT_HALT);
- USETW(req.wIndex, 0x0002); /* should get value from softc etc.*/
- USETW(req.wLength, 0);
- err = usbd_do_request(dev, &req, 0);
- if (err) {
- DPRINTF(("%s: E220 request test ENDPOINT_HALT fail\n",
__func__));
- return (EIO);
+#ifdef UHMODEM_DEBUG
+ printf("%s: readdata: ", __func__);
+ for (i = 0; i < 7; i++)
+ printf("0x%x ", data[i]);
+#endif
+ if (uhmodem_regwrite(dev, init_cmd, sizeof(init_cmd)) ) {
+ DPRINTF(("%s: write fail\n", __func__));
+ return EIO;
}
- return (0);
+ if (uhmodem_regread(dev, data, 7)) {
+ DPRINTF(("%s: read fail\n", __func__));
+ return EIO;
+ }
+#ifdef UHMODEM_DEBUG
+ printf("%s: readdata: ", __func__);
+ printf(" => ");
+ for (i = 0; i < 7; i++)
+ printf("0x%x ", data[i]);
+ printf("\n");
+#endif
+ return 0;
}
+
#if 0
/*
* Windows device driver send these sequens of USB requests.
@@ -508,14 +639,13 @@
* disable this code when I get more information about it.
*/
Static usbd_status
-e220_testreq(usbd_device_handle dev)
+e220_init(usbd_device_handle dev)
{
uint8_t data[8];
usb_device_request_t req;
- usbd_status err;
int i;
- /* vendor specific unknown requres */
+ /* vendor specific unknown request */
req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
req.bRequest = 0x02;
USETW(req.wValue, 0x0001);
@@ -523,66 +653,31 @@
USETW(req.wLength, 2);
data[0] = 0x0;
data[1] = 0x0;
- err = usbd_do_request(dev, &req, data);
- if (err)
+ if (usbd_do_request(dev, &req, data))
goto error;
/* vendor specific unknown sequence */
-#define E220_CLASS_SETUP 0x22
-#define E220_CLASS_READ 0x21
-#define E220_CLASS_WRITE 0x20
-
- req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
- req.bRequest = E220_CLASS_SETUP; // 0x22
- USETW(req.wValue, 0x0001);
- USETW(req.wIndex, 0x0000);
- USETW(req.wLength, 0);
- err = usbd_do_request(dev, &req, 0);
- if (err)
+ if(uhmodem_regsetup(dev, 0x1))
goto error;
- req.bmRequestType = UT_READ_CLASS_INTERFACE;
- req.bRequest = E220_CLASS_READ;
- USETW(req.wValue, 0x0000);
- USETW(req.wIndex, 0x0000);
- USETW(req.wLength, 7);
- err = usbd_do_request(dev, &req, &data);
- if (err)
+ if (uhmodem_regread(dev, data, 7))
goto error;
data[1] = 0x8;
data[2] = 0x7;
- req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
- req.bRequest = E220_CLASS_WRITE;
- USETW(req.wValue, 0x0000);
- USETW(req.wIndex, 0x0000);
- USETW(req.wLength, 7);
- err = usbd_do_request(dev, &req, data);
- if (err)
+ if (uhmodem_regwrite(dev, data, sizeof(data)) )
goto error;
- req.bmRequestType = UT_READ_CLASS_INTERFACE;
- req.bRequest = E220_CLASS_READ;
- USETW(req.wValue, 0x0000);
- USETW(req.wIndex, 0x0000);
- USETW(req.wLength, 7);
- err = usbd_do_request(dev, &req, &data);
- if (err)
+ if (uhmodem_regread(dev, data, 7))
goto error;
- printf("%s(0x21):", __func__);
+ /* XXX should verify the read data ? */
- req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
- req.bRequest = E220_CLASS_SETUP; // 0x22
- USETW(req.wValue, 0x0003);
- USETW(req.wIndex, 0x0000);
- USETW(req.wLength, 0);
- err = usbd_do_request(dev, &req, 0);
- if (err)
+ if (uhmodem_regsetup(dev, 0x3))
goto error;
return (0);
error:
- DPRINTF(("%s: E220 request test SETUP fail\n", __func__));
+ DPRINTF(("%s: E220 init request fail\n", __func__));
return (EIO);
}
#endif
Index: usbdevs
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/usbdevs,v
retrieving revision 1.492
diff -u -r1.492 usbdevs
--- usbdevs 15 Dec 2007 12:50:12 -0000 1.492
+++ usbdevs 6 Feb 2008 16:20:02 -0000
@@ -662,6 +663,7 @@
product ANCHOR EZLINK 0x2720 EZLINK
/* AnyDATA Inc. products */
+product ANYDATA A2502 0x6202 NTT DoCoMo A2502
product ANYDATA ADU_E100H 0x6501 ADU-E100H
/* AOX, Inc. products */
Home |
Main Index |
Thread Index |
Old Index