Subject: Re: Huawei E220 support?
To: None <current-users@netbsd.org>
From: Yojiro UO <yuo@nui.org>
List: current-users
Date: 12/23/2007 20:07:52
This is a multi-part message in MIME format.
--------------060608060000090702080701
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Hi
Marco Trillo wrote:
> Maybe this can be fixed by making ubsa(4) issue the non-standard
> request to switch device mode that the Linux hack does; but I haven't
> tried it yet.
I wrote a patch to send special request to enable modem function of
E220 deivce. It seems to work well (I use OEM version of E220 /
Emobile D02HW). (special thanks to ichiro@netbsd.org)
Once the device is plugged in, this patch act as
attach -> send special request -> re-attach -> attach as ucom.
Following is dmesg:
ubsa0 at uhub0 port 2
ubsa0: HUAWEI Technologies HUAWEI Mobile, rev 1.10/0.00, addr 2
ubsa0: HAUWEI E220 need to re-attach to enable modem function
ubsa0: at uhub0 port 2 (addr 2) disconnected
ubsa0 detached
ubsa0 at uhub0 port 2
ubsa0: HUAWEI Technologies HUAWEI Mobile, rev 1.10/0.00, addr 2
ucom0 at ubsa0
This patch is send-pred.
-- Yojiro UO
--------------060608060000090702080701
Content-Type: text/plain;
name="diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="diff"
Index: ubsa.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ubsa.c,v
retrieving revision 1.19
diff -u -r1.19 ubsa.c
--- ubsa.c 13 Mar 2007 13:51:55 -0000 1.19
+++ ubsa.c 23 Dec 2007 10:20:44 -0000
@@ -95,8 +95,9 @@
#include <dev/usb/ucomvar.h>
+#define UBSA_DEBUG
#ifdef UBSA_DEBUG
-Static int ubsadebug = 0;
+Static int ubsadebug = 1;
#ifdef __FreeBSD__
SYSCTL_NODE(_hw_usb, OID_AUTO, ubsa, CTLFLAG_RW, 0, "USB ubsa");
SYSCTL_INT(_hw_usb_ubsa, OID_AUTO, debug, CTLFLAG_RW,
@@ -114,7 +115,7 @@
#define UBSA_MODVER 1 /* module version */
-#define UBSA_CONFIG_INDEX 1
+#define UBSA_DEFAULT_CONFIG_INDEX 1
#define UBSA_IFACE_INDEX 0
#define UBSA_INTR_INTERVAL 100 /* ms */
@@ -174,6 +175,7 @@
usbd_interface_handle sc_iface; /* interface */
int sc_iface_number; /* interface number */
+ int sc_config_index; /* USB CONFIG_INDEX */
int sc_intr_number; /* interrupt number */
usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */
@@ -190,6 +192,7 @@
u_char sc_dying; /* disconnecting */
u_char sc_quadumts;
+ int sc_devtype_e220; /* hauwei e220 */
};
@@ -213,6 +216,8 @@
Static void ubsa_stopbits(struct ubsa_softc *, tcflag_t);
Static void ubsa_flow(struct ubsa_softc *, tcflag_t, tcflag_t);
+Static usbd_status ubsa_e220_modechange_request(struct ubsa_softc *);
+
struct ucom_methods ubsa_methods = {
ubsa_get_status,
ubsa_set,
@@ -241,6 +246,8 @@
{ USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_QUADUMTS },
/* AnyDATA ADU-E100H */
{ USB_VENDOR_ANYDATA, USB_PRODUCT_ANYDATA_ADU_E100H },
+ /* HUAWEI E220 / Emobile D0[12]HW */
+ { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220 },
};
#define ubsa_lookup(v, p) usb_lookup(ubsa_devs, v, p)
@@ -273,6 +280,8 @@
usbd_devinfo_free(devinfop);
sc->sc_udev = dev;
+ sc->sc_config_index = UBSA_DEFAULT_CONFIG_INDEX;
+ sc->sc_devtype_e220 = 0;
/*
* initialize rts, dtr variables to something
@@ -294,6 +303,13 @@
break;
}
}
+ /* Huawei E220 needs special care */
+ if (uaa->vendor == USB_VENDOR_HUAWEI)
+ if (uaa->product == USB_PRODUCT_HUAWEI_E220) {
+ sc->sc_quadumts = 1;
+ sc->sc_config_index = 0;
+ sc->sc_devtype_e220 = 1;
+ }
DPRINTF(("ubsa attach: sc = %p\n", sc));
@@ -303,7 +319,7 @@
sc->sc_intr_pipe = NULL;
/* Move the device into the configured state. */
- err = usbd_set_config_index(dev, UBSA_CONFIG_INDEX, 1);
+ err = usbd_set_config_index(dev, sc->sc_config_index, 1);
if (err) {
printf("%s: failed to set configuration: %s\n",
devname, usbd_errstr(err));
@@ -332,6 +348,17 @@
}
/* Find the endpoints */
+ /* Hauwei E220 need special request to change its mode to modem */
+ if (sc->sc_devtype_e220) {
+ err = ubsa_e220_modechange_request(sc);
+ if (err) {
+ printf("%s: failed to change mode: %s\n",
+ devname, usbd_errstr(err));
+ sc->sc_dying = 1;
+ goto error;
+ }
+// usbd_delay_ms(dev, 50);
+ }
id = usbd_get_interface_descriptor(sc->sc_iface);
sc->sc_iface_number = id->bInterfaceNumber;
@@ -361,7 +388,10 @@
}
if (sc->sc_intr_number == -1) {
- printf("%s: Could not find interrupt in\n", devname);
+ if (sc->sc_devtype_e220)
+ printf("%s: HUAWEI E220 need to re-attach to enable modem function\n", devname);
+ else
+ printf("%s: Could not find interrupt in\n", devname);
sc->sc_dying = 1;
goto error;
}
@@ -785,3 +815,31 @@
if (msr != NULL)
*msr = sc->sc_msr;
}
+
+/*
+ * Hauwei E220 needs special request to enable modem function
+ * XXX: is there more smart methods?
+ */
+Static usbd_status
+ubsa_e220_modechange_request(struct ubsa_softc *sc)
+{
+#define UBSA_E220_MODE_CHANGE_REQUEST 0x2
+ usb_device_request_t req;
+ usbd_status err;
+
+ req.bmRequestType = UT_WRITE_DEVICE;
+ req.bRequest = UR_SET_FEATURE;
+ USETW(req.wValue, 0x1);
+ USETW(req.wIndex, UBSA_E220_MODE_CHANGE_REQUEST);
+ USETW(req.wLength, 0);
+
+ DPRINTF(("%s: send e220 mode change request\n", __func__));
+ err = usbd_do_request(sc->sc_udev, &req, 0);
+ if (err) {
+ DPRINTF(("%s: E220 mode change fail\n", __func__));
+ return (EIO);
+ }
+
+ return (0);
+#undef UBSA_E220_MODE_CHANGE_REQUEST
+}
Index: umass_quirks.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/umass_quirks.c,v
retrieving revision 1.71
diff -u -r1.71 umass_quirks.c
--- umass_quirks.c 9 Jan 2007 16:46:02 -0000 1.71
+++ umass_quirks.c 23 Dec 2007 10:20:44 -0000
@@ -194,6 +194,13 @@
UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
NULL, NULL
},
+ { { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220 },
+ 0, 0,
+ 0,
+ 0,
+ 0,
+ NULL, NULL
+ },
};
const struct umass_quirk *
--------------060608060000090702080701--