Unix Technical Forum

cdce(4), working with zaurus?

This is a discussion on cdce(4), working with zaurus? within the mailing.openbsd.tech forums, part of the OpenBSD category; --> I'm searching for zaurus users who could test my diff again. I need to know if there are any ...


Go Back   Unix Technical Forum > Unix Operating Systems > OpenBSD > mailing.openbsd.tech

Register FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 02-18-2008, 09:30 AM
Marc Winiger
 
Posts: n/a
Default cdce(4), working with zaurus?

I'm searching for zaurus users who could test my diff again. I need to
know if there are any differences between -current and this diff.

This patch is for the host side (cdce(4)), not the zaurus side.

Feedback for any other cdce(4) devices are welcome.


Index: if_cdce.c
================================================== =================
RCS file: /var/cvs/src/sys/dev/usb/if_cdce.c,v
retrieving revision 1.33
diff -u -r1.33 if_cdce.c
--- if_cdce.c 14 Jun 2007 10:11:15 -0000 1.33
+++ if_cdce.c 18 Jul 2007 17:34:34 -0000
@@ -73,7 +73,6 @@

#include <dev/usb/if_cdcereg.h>

-void *cdce_get_desc(usbd_device_handle dev, int type, int subtype);
int cdce_tx_list_init(struct cdce_softc *);
int cdce_rx_list_init(struct cdce_softc *);
int cdce_newbuf(struct cdce_softc *, struct cdce_chain *,
@@ -86,22 +85,23 @@
void cdce_init(void *);
void cdce_watchdog(struct ifnet *);
void cdce_stop(struct cdce_softc *);
+void cdce_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
static uint32_t cdce_crc32(const void *, size_t);

const struct cdce_type cdce_devs[] = {
- {{ USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632 }, CDCE_NO_UNION },
- {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, CDCE_NO_UNION },
+ {{ USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632 }, 0 },
+ {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, 0 },
{{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_ZAURUS },
- {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_ZAURUS | CDCE_NO_UNION },
- {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS | CDCE_NO_UNION },
- {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_ZAURUS | CDCE_NO_UNION },
- {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_ZAURUS | CDCE_NO_UNION },
- {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN }, CDCE_ZAURUS | CDCE_NO_UNION },
- {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2 }, CDCE_ZAURUS | CDCE_NO_UNION },
- {{ USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00 }, CDCE_NO_UNION },
- {{ USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_ETHERNETGADGET }, CDCE_NO_UNION },
- {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX }, CDCE_NO_UNION },
- {{ USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250 }, CDCE_NO_UNION },
+ {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_ZAURUS },
+ {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS },
+ {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_ZAURUS },
+ {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_ZAURUS },
+ {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN }, CDCE_ZAURUS },
+ {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2 }, CDCE_ZAURUS },
+ {{ USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00 }, 0 },
+ {{ USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_ETHERNETGADGET }, 0 },
+ {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX }, 0 },
+ {{ USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250 }, CDCE_SWAPUNION },
};
#define cdce_lookup(v, p) ((const struct cdce_type *)usb_lookup(cdce_devs, v, p))

@@ -158,10 +158,15 @@
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
usb_cdc_union_descriptor_t *ud;
+ usb_cdc_ethernet_descriptor_t *ethd;
usb_config_descriptor_t *cd;
- int data_ifcno;
+ const usb_descriptor_t *desc;
+ usbd_desc_iter_t iter;
+ usb_string_descriptor_t eaddr_str;
u_int16_t macaddr_hi;
- int i, j, numalts;
+ int i, j, numalts, len;
+ int ctl_ifcno = -1;
+ int data_ifcno = -1;

devinfop = usbd_devinfo_alloc(dev, 0);
printf("\n%s: %s\n", sc->cdce_dev.dv_xname, devinfop);
@@ -169,23 +174,47 @@

sc->cdce_udev = uaa->device;
sc->cdce_ctl_iface = uaa->iface;
+ id = usbd_get_interface_descriptor(sc->cdce_ctl_iface);
+ ctl_ifcno = id->bInterfaceNumber;

t = cdce_lookup(uaa->vendor, uaa->product);
if (t)
sc->cdce_flags = t->cdce_flags;

- if (sc->cdce_flags & CDCE_NO_UNION)
- sc->cdce_data_iface = sc->cdce_ctl_iface;
- else {
- ud = cdce_get_desc(sc->cdce_udev, UDESC_CS_INTERFACE,
- UDESCSUB_CDC_UNION);
- if (ud == NULL) {
- printf("%s: no union descriptor\n",
- sc->cdce_dev.dv_xname);
- return;
+ /* Get the data interface no. and capabilities */
+ ethd = NULL;
+ usb_desc_iter_init(dev, &iter);
+ desc = usb_desc_iter_next(&iter);
+ while (desc) {
+ if (desc->bDescriptorType != UDESC_CS_INTERFACE) {
+ desc = usb_desc_iter_next(&iter);
+ continue;
+ }
+ switch(desc->bDescriptorSubtype) {
+ case UDESCSUB_CDC_UNION:
+ ud = (usb_cdc_union_descriptor_t *)desc;
+ if ((sc->cdce_flags & CDCE_SWAPUNION) == 0 &&
+ ud->bMasterInterface == ctl_ifcno)
+ data_ifcno = ud->bSlaveInterface[0];
+ if ((sc->cdce_flags & CDCE_SWAPUNION) &&
+ ud->bSlaveInterface[0] == ctl_ifcno)
+ data_ifcno = ud->bMasterInterface;
+ break;
+ case UDESCSUB_CDC_ENF:
+ if (ethd) {
+ printf("%s: ", sc->cdce_dev.dv_xname);
+ printf("extra ethernet descriptor\n");
+ return;
+ }
+ ethd = (usb_cdc_ethernet_descriptor_t *)desc;
+ break;
}
- data_ifcno = ud->bSlaveInterface[0];
+ desc = usb_desc_iter_next(&iter);
+ }

+ if (data_ifcno == -1) {
+ sc->cdce_data_iface = sc->cdce_ctl_iface;
+ } else {
for (i = 0; i < uaa->nifaces; i++) {
if (uaa->ifaces[i] != NULL) {
id = usbd_get_interface_descriptor(
@@ -204,24 +233,42 @@
return;
}

- /* Find endpoints. */
+ id = usbd_get_interface_descriptor(sc->cdce_ctl_iface);
+ sc->cdce_intr_no = -1;
+ for (i = 0; i < id->bNumEndpoints && sc->cdce_intr_no == -1; i++) {
+ ed = usbd_interface2endpoint_descriptor(sc->cdce_ctl_iface, i);
+ if (!ed) {
+ printf("%s: no descriptor for interrupt endpoint %d\n",
+ sc->cdce_dev.dv_xname, i);
+ return;
+ }
+ if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
+ UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
+ printf("%s: status change notification available\n",
+ sc->cdce_dev.dv_xname);
+ sc->cdce_intr_no = ed->bEndpointAddress;
+ sc->cdce_intr_size = sizeof(sc->cdce_intr_buf);
+ }
+ }
+
id = usbd_get_interface_descriptor(sc->cdce_data_iface);
cd = usbd_get_config_descriptor(sc->cdce_udev);
numalts = usbd_get_no_alts(cd, id->bInterfaceNumber);

for (j = 0; j < numalts; j++) {
- if (usbd_set_interface(sc->cdce_data_iface, j)) {
- printf("%s: setting alternate interface failed\n",
- sc->cdce_dev.dv_xname);
+ if (usbd_set_interface(sc->cdce_data_iface, j)) {
+ printf("%s: interface alternate setting %d failed\n",
+ sc->cdce_dev.dv_xname, j);
return;
}
+ /* Find endpoints. */
id = usbd_get_interface_descriptor(sc->cdce_data_iface);
sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1;
for (i = 0; i < id->bNumEndpoints; i++) {
ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i);
if (!ed) {
- printf("%s: could not read endpoint descriptor\n",
- sc->cdce_dev.dv_xname);
+ printf("%s: no descriptor for bulk endpoint %d\n",
+ sc->cdce_dev.dv_xname, i);
return;
}
if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
@@ -232,14 +279,17 @@
sc->cdce_bulkout_no = ed->bEndpointAddress;
} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
- /* XXX: CDC spec defines an interrupt pipe, but it is not
- * needed for simple host-to-host applications. */
+ /* XXX: CDC spec defines an interrupt pipe, but it is
+ * not needed for simple host-to-host applications. */
} else {
- printf("%s: unexpected endpoint\n",
- sc->cdce_dev.dv_xname);
+ printf("%s: unexpected endpoint, ep=%x attr=%x\n",
+ sc->cdce_dev.dv_xname, ed->bEndpointAddress,
+ ed->bmAttributes);
}
}
-
+ if ((sc->cdce_bulkin_no != -1) && (sc->cdce_bulkout_no != -1)) {
+ goto found;
+ }
}

if (sc->cdce_bulkin_no == -1) {
@@ -253,12 +303,32 @@
return;
}

+found:
s = splnet();

- macaddr_hi = htons(0x2acb);
- bcopy(&macaddr_hi, &sc->cdce_arpcom.ac_enaddr[0], sizeof(u_int16_t));
- bcopy(&ticks, &sc->cdce_arpcom.ac_enaddr[2], sizeof(u_int32_t));
- sc->cdce_arpcom.ac_enaddr[5] = (u_int8_t)(sc->cdce_unit);
+ if (!ethd || usbd_get_string_desc(sc->cdce_udev, ethd->iMacAddress, 0,
+ &eaddr_str, &len)) {
+ macaddr_hi = htons(0x2acb);
+ bcopy(&macaddr_hi, &sc->cdce_arpcom.ac_enaddr[0],
+ sizeof(u_int16_t));
+ bcopy(&ticks, &sc->cdce_arpcom.ac_enaddr[2], sizeof(u_int32_t));
+ sc->cdce_arpcom.ac_enaddr[5] = (u_int8_t)(sc->cdce_unit);
+ } else {
+ for (i = 0; i < ETHER_ADDR_LEN * 2; i++) {
+ int c = UGETW(eaddr_str.bString[i]);
+
+ if ('0' <= c && c <= '9')
+ c -= '0';
+ else if ('A' <= c && c <= 'F')
+ c -= 'A' - 10;
+ else if ('a' <= c && c <= 'f')
+ c -= 'a' - 10;
+ c &= 0xf;
+ if (i % 2 == 0)
+ c <<= 4;
+ sc->cdce_arpcom.ac_enaddr[i / 2] |= c;
+ }
+ }

printf("%s: address %s\n", sc->cdce_dev.dv_xname,
ether_sprintf(sc->cdce_arpcom.ac_enaddr));
@@ -408,6 +478,18 @@
sc->cdce_bulkout_pipe = NULL;
}

+ if (sc->cdce_intr_pipe != NULL) {
+ err = usbd_abort_pipe(sc->cdce_intr_pipe);
+ if (err)
+ printf("%s: abort interrupt pipe failed: %s\n",
+ sc->cdce_dev.dv_xname, usbd_errstr(err));
+ err = usbd_close_pipe(sc->cdce_intr_pipe);
+ if (err)
+ printf("%s: close interrupt pipe failed: %s\n",
+ sc->cdce_dev.dv_xname, usbd_errstr(err));
+ sc->cdce_intr_pipe = NULL;
+ }
+
for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) {
m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf);
@@ -519,6 +601,18 @@

s = splnet();

+ if (sc->cdce_intr_no != -1 && sc->cdce_intr_pipe == NULL) {
+ err = usbd_open_pipe_intr(sc->cdce_ctl_iface, sc->cdce_intr_no,
+ USBD_SHORT_XFER_OK, &sc->cdce_intr_pipe, sc,
+ &sc->cdce_intr_buf, sc->cdce_intr_size, cdce_intr,
+ USBD_DEFAULT_INTERVAL);
+ if (err) {
+ printf("Failed to establish interrupt pipe: %s\n",
+ usbd_errstr(err));
+ return;
+ }
+ }
+
if (cdce_tx_list_init(sc) == ENOBUFS) {
printf("%s: tx list init failed\n", sc->cdce_dev.dv_xname);
splx(s);
@@ -775,25 +869,6 @@
splx(s);
}

-void *
-cdce_get_desc(usbd_device_handle dev, int type, int subtype)
-{
- usb_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_descriptor_t *)p;
- if (desc->bDescriptorType == type &&
- desc->bDescriptorSubtype == subtype)
- return (desc);
- p += desc->bLength;
- }
-
- return (NULL);
-}
-
int
cdce_activate(struct device *self, enum devact act)
{
@@ -808,6 +883,50 @@
break;
}
return (0);
+}
+
+void
+cdce_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
+{
+ struct cdce_softc *sc = addr;
+ usb_cdc_notification_t *buf = &sc->cdce_intr_buf;
+ usb_cdc_connection_speed_t *speed;
+ u_int32_t count;
+
+ if (status == USBD_CANCELLED)
+ return;
+
+ if (status != USBD_NORMAL_COMPLETION) {
+ printf("cdce_intr: status=%d\n", status);
+ if (status == USBD_STALLED)
+ usbd_clear_endpoint_stall_async(sc->cdce_intr_pipe);
+ return;
+ }
+
+ usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
+
+ if (buf->bmRequestType == UCDC_NOTIFICATION) {
+ switch (buf->bNotification) {
+ case UCDC_N_NETWORK_CONNECTION:
+ printf("%s: network %s\n", sc->cdce_dev.dv_xname,
+ UGETW(buf->wValue) ? "connected" : "disconnected");
+ break;
+ case UCDC_N_CONNECTION_SPEED_CHANGE:
+ speed = (usb_cdc_connection_speed_t *)&buf->data;
+ printf("%s: upstream %d bps, downstream %d bps\n",
+ sc->cdce_dev.dv_xname, UGETDW(speed->dwUSBitRate),
+ UGETDW(speed->dwDSBitRate));
+ break;
+ default:
+ printf("%s: bNotification 0x%x\n",
+ sc->cdce_dev.dv_xname, buf->bNotification);
+ }
+ } else {
+ printf("%s: bmRequestType=%d ", sc->cdce_dev.dv_xname,
+ buf->bmRequestType);
+ printf("wValue=%d wIndex=%d wLength=%d\n", UGETW(buf->wValue),
+ UGETW(buf->wIndex), UGETW(buf->wLength));
+ }
}


Index: if_cdcereg.h
================================================== =================
RCS file: /var/cvs/src/sys/dev/usb/if_cdcereg.h,v
retrieving revision 1.2
diff -u -r1.2 if_cdcereg.h
--- if_cdcereg.h 6 Jun 2007 19:25:49 -0000 1.2
+++ if_cdcereg.h 18 Jul 2007 17:34:34 -0000
@@ -42,7 +42,7 @@
struct usb_devno cdce_dev;
u_int16_t cdce_flags;
#define CDCE_ZAURUS 1
-#define CDCE_NO_UNION 2
+#define CDCE_SWAPUNION 2
};

struct cdce_softc;
@@ -71,6 +71,10 @@
#define GET_IFP(sc) (&(sc)->cdce_arpcom.ac_if)
usbd_device_handle cdce_udev;
usbd_interface_handle cdce_ctl_iface;
+ int cdce_intr_no;
+ usbd_pipe_handle cdce_intr_pipe;
+ usb_cdc_notification_t cdce_intr_buf;
+ int cdce_intr_size;
usbd_interface_handle cdce_data_iface;
int cdce_bulkin_no;
usbd_pipe_handle cdce_bulkin_pipe;
Index: usbcdc.h
diff -u -r1.6 usbcdc.h
--- usbcdc.h 9 Jun 2007 11:06:53 -0000 1.6
+++ usbcdc.h 18 Jul 2007 17:34:35 -0000
@@ -52,6 +52,13 @@
#define UDESCSUB_CDC_CS 7 /* Country Selection */
#define UDESCSUB_CDC_TOM 8 /* Telephone Operational Modes */
#define UDESCSUB_CDC_USBT 9 /* USB Terminal */
+#define UDESCSUB_CDC_NCT 10 /* Network Channel Terminal */
+#define UDESCSUB_CDC_PUF 11 /* Protocol Unit */
+#define UDESCSUB_CDC_EUF 12 /* Extension Unit */
+#define UDESCSUB_CDC_MCMF 13 /* Multi-Channel Management */
+#define UDESCSUB_CDC_CCMF 14 /* CAPI Control Management */
+#define UDESCSUB_CDC_ENF 15 /* Ethernet Networking */
+#define UDESCSUB_CDC_ANF 16 /* ATM Networking */

typedef struct {
uByte bLength;
@@ -89,6 +96,17 @@
uByte bSlaveInterface[1];
} __packed usb_cdc_union_descriptor_t;

+typedef struct {
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uByte iMacAddress;
+ uDWord bmEthernetStatistics;
+ uWord wMaxSegmentSize;
+ uWord wNumberMCFilters;
+ uByte bNumberPowerFilters;
+} __packed usb_cdc_ethernet_descriptor_t;
+
#define UCDC_SEND_ENCAPSULATED_COMMAND 0x00
#define UCDC_GET_ENCAPSULATED_RESPONSE 0x01
#define UCDC_SET_COMM_FEATURE 0x02
@@ -146,6 +164,12 @@
uByte data[16];
} __packed usb_cdc_notification_t;
#define UCDC_NOTIFICATION_LENGTH 8
+
+typedef struct {
+ uDWord dwUSBitRate;
+ uDWord dwDSBitRate;
+} __packed usb_cdc_connection_speed_t;
+#define UCDC_CONNECTION_SPEED_LENGTH 8

/*
* Bits set in the SERIAL STATE notifcation (first byte of data)

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 05:40 PM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com