Что не так?
Код: Выделить всё
# uname -a
FreeBSD sms.local 7.1-RELEASE FreeBSD 7.1-RELEASE #0: Wed Mar 11 10:48:18 YEKT 2009 root@sms.local:/usr/obj/usr/src/sys/ASD_kernel.2009-11-03 i386
Код: Выделить всё
# ls /dev/cua*
/dev/cuad0 /dev/cuad0.init /dev/cuad0.lock /dev/cuad1 /dev/cuad1.init /dev/cuad1.lock
Код: Выделить всё
# usbdevs -v
Controller /dev/usb0:
addr 1: full speed, self powered, config 1, UHCI root hub(0x0000), Intel(0x0000), rev 1.00
port 1 addr 2: full speed, self powered, config 1, Nokia N73(0x0486), Nokia(0x0421), rev 1.00
port 2 powered
Код: Выделить всё
ucom0: <Nokia Nokia N73, class 2/0, rev 2.00/1.00, addr 2> on uhub0
ucom0: iclass 2/2
ucom0: no CM and Union descriptor
device_attach: ucom0 attach returned 6
Код: Выделить всё
--- /root/old/123/umodem.c 2009-03-12 11:14:08.000000000 +0500
+++ umodem.c 2009-03-12 13:13:37.000000000 +0500
@@ -127,6 +127,7 @@
{ USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_AHK3001V, 0 },
{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720, 0 },
{ USB_VENDOR_CURITEL, USB_PRODUCT_CURITEL_PC5740, 0 },
+ { 0x0421, 0x0486, 0 },
{ 0, 0, 0 },
};
@@ -179,7 +180,8 @@
usb_cdc_line_state_t *state);
static void umodem_get_caps(usbd_device_handle, int *, int *);
-
+static usb_cdc_union_descriptor_t *
+ umodem_get_union(usbd_device_handle dev, int iface_no);
static void umodem_get_status(void *, int portno, u_char *lsr, u_char *msr);
static void umodem_set(void *, int, int, int);
static void umodem_dtr(struct umodem_softc *, int);
@@ -280,6 +282,7 @@
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
usb_cdc_cm_descriptor_t *cmd;
+ usb_cdc_union_descriptor_t *cud;
int data_ifcno;
int i;
struct ucom_softc *ucom;
@@ -302,10 +305,16 @@
/* Get the data interface no. */
cmd = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM);
if (cmd == NULL) {
- device_printf(sc->sc_dev, "no CM descriptor\n");
- goto bad;
- }
- sc->sc_data_iface_no = data_ifcno = cmd->bDataInterface;
- device_printf(sc->sc_dev, "no CM descriptor\n");
+ cud = umodem_get_union(dev, sc->sc_ctl_iface_no);
+ if (cud == NULL) {
+ device_printf(sc->sc_dev, "no CM and Union descriptor\n");
+ goto bad;
- }
- sc->sc_data_iface_no = data_ifcno = cmd->bDataInterface;
+ }else data_ifcno = cud->bSlaveInterface[0];
+ }else data_ifcno = cmd->bDataInterface;
+ sc->sc_data_iface_no = data_ifcno;
device_printf(sc->sc_dev,
"data interface %d, has %sCM over data, has %sbreak\n",
@@ -538,12 +547,12 @@
*cm = *acm = 0;
- cmd = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM);
- if (cmd == NULL) {
- DPRINTF(("umodem_get_desc: no CM desc\n"));
- return;
- }
- *cm = cmd->bmCapabilities;
cad = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_ACM);
if (cad == NULL) {
@@ -551,6 +560,13 @@
return;
}
*acm = cad->bmCapabilities;
+
+ cmd = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM);
+ if (cmd == NULL) {
+ DPRINTF(("umodem_get_desc: no CM desc\n"));
+ *cm = USB_CDC_CM_DOES_CM | USB_CDC_CM_OVER_DATA;
- return;
+ }else *cm = cmd->bmCapabilities;
}
void
@@ -821,3 +837,21 @@
return (rv);
}
+
+usb_cdc_union_descriptor_t *
+umodem_get_union(usbd_device_handle dev, int iface_no)
+{
+ usb_cdc_union_descriptor_t *desc;
+ usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev);
+ uByte *p = (uByte *)cd;
+ uByte *end = p + UGETW(cd->wTotalLength);
+ while (p < end) {
+ desc = (usb_cdc_union_descriptor_t *)p;
+ if (desc->bDescriptorSubtype == UDESC_CS_INTERFACE &&
+ desc->bDescriptorSubtype == UDESCSUB_CDC_UNION &&
+ desc->bMasterInterface == iface_no)
+ return (desc);
+ p += desc->bLength;
+ }
+ return (0);
+}
void