ugen(7D) man page changes. --- ugen.man.orig Fri Nov 2 11:04:20 2007 +++ ugen.man.new Sat Nov 3 11:17:53 2007 @@ -25,11 +25,10 @@ is obtained by reading file descriptors created for endpoint and full device status. - ugen supports control, bulk, and interrupt (in and out) - transfers. Isochronous transfers are not supported. - libusb(3LIB) uses ugen to access devices that do not contain - drivers such as digital cameras and PDAs. Refer to - /usr/sfw/share/doc/libusb/libusb.txt for details + ugen supports control, bulk, isochronous and interrupt (in + and out) transfers. libusb(3LIB) uses ugen to access devices + that do not contain drivers such as digital cameras and + PDAs. Refer to /usr/sfw/share/doc/libusb/libusb.txt for details BINDING In general, no explicit binding of the ugen driver is neces- @@ -670,7 +669,7 @@ ing parts are omitted. #include - #include uchar_t *config_cloud; uchar_t *curr_descr; @@ -1037,6 +1036,257 @@ } +ISOCHRONOUS TRANSFERS + Applications requiring I/O on an isochronous endpoint can open + the corresponding logical device name and perform regular UNIX + I/O system calls, such as read(2), write(2), poll(2), + aioread(3AIO) and aiowrite(3AIO). An isochronous endpoint must + be opened with O_RDWR. + + fd = open("/dev/usb/472.b0b0/0/if0.3in2", O_RDWR); + + + fdstat = open("/dev/usb/472.b0b0/0/if0.3in2stat", O_RDONLY); + + Application can use the status logical name to retrieve the + state of the isochronous data endpoint, including detail on how + its most recent transfer failed. + + Applications have the flexibility to specify number of isochronous + packets and the size of individual packet they want to transfer. + Applications should use the following data structures to exchange + isochronous packet information with ugen driver: + + typedef struct ugen_isoc_pkt_descr { + /* + * Set by the application, for all isochronous + * requests, to the number of bytes to transfer + * in a packet. + */ + ushort_t dsc_isoc_pkt_len; + + /* + * Set by ugen to actual number of bytes sent/received + * in a packet. + */ + ushort_t dsc_isoc_pkt_actual_len; + + /* + * Per packet status set by ugen driver both for the + * isochronous IN and OUT requests. Application can + * use USB_LC_STAT_* to parse the status. + */ + int dsc_isoc_pkt_status; + } ugen_isoc_pkt_descr_t; + + typedef struct ugen_isoc_req_head { + /* pkt count of the isoc request */ + int req_isoc_pkts_count; + + /* pkt descriptors */ + ugen_isoc_pkt_descr_t req_isoc_pkt_descrs[1]; + } ugen_isoc_req_head_t; + + + req_isoc_pkts_count is limited by the capability of USB host + controller driver. The current upper bounds of UHCI and OHCI + driver is 512 and EHCI is 1024. + + For an isochronous-IN endpoint, application must first use + ugen_isoc_req_head_t structure, following by the + ugen_isoc_pkt_descr_t, to write packet request information to + the ugen node. + + Ugen driver will check validity of this request. If it is valid, + ugen will immediately start isochronous polling on this IN + endpoint, then application can go on with read(2) of data on this + isochronous-IN endpoint. Upon every successful return of read(2), + isochronous packet descriptors, whose dsc_isoc_pkt_actual_len + and dsc_isoc_pkt_status field were filled by ugen driver, will + be returned. Following the packet descriptors is the device + payload data of this request. + + Applications should continuously check for and consume + isochronous data. ugen enables buffering of up to eight seconds + of incoming data for full-speed isochronous endpoint, one second + of data for high-speed isochronous endpoints who request one + transactions per microframe, and about 1/3 second of incoming + data for high-speed high-bandwidth isochronous endpoints who + request three transactions per microframe. In case of buffer + overflow, ugen will discard the oldest data. + + The isochronous-IN polling can only be stopped by close(2) + associated file descriptor. If applications want to change + packet information, they must first close(2) the endpoint to + stop the isochronous-IN polling, then open(2) this endpoint and + write(2) new packets request. + + Here is a more extensive example to demonstrate how to read an + isochronous-IN endpoint, + + #include + + char *buf, *p; + ushort_t pktlen; + int pktcnt, i; + int len; + ugen_isoc_req_head_t *req; + ugen_isoc_pkt_descr_t *pktdesc; + char rdbuf[5000]; + + pktcnt = 4; /* 4 packets in this request */ + + len = sizeof(int) + + sizeof(ugen_isoc_pkt_descr_t) * pktcount; + + buf = malloc(len); + if (!buf) { + /* Error recovery. */ + } + + req = (ugen_isoc_req_head_t *)buf; + req->req_isoc_pkts_count = pktcnt; + + pktdesc = (ugen_isoc_pkt_descr_t *) + (req->req_isoc_pkt_descrs); + + for (i = 0; i < pktcnt; i++) { + /* + * pktlen should not exceed transfer capability + * of an endpoint + */ + pktdesc[i].dsc_isoc_pkt_len = pktlen; + + pktdesc[i].dsc_isoc_pkt_actual_len = 0; + pktdesc[i].dsc_isoc_pkt_status = 0; + } + + /* + * write request information to ugen driver and len must + * be exactly the sum of + * sizeof(int) + sizeof(ugen_isoc_pkt_descr_t) * pktcnt. + * Otherwise, an error will be returned. + */ + if (write(fd, buf, len) < 0) { + /* Error recovery. */ + } + + /* + * Read length should be the sum of all packet descriptors + * length + payload data length of all packets + * (sizeof(ugen_isoc_pkt_descr_t) + pktlen) * pktcnt + */ + if (read(fd, rdbuf, (sizeof(ugen_isoc_pkt_descr_t) + + pktlen) * pktcnt) < 0) { + /* Error recovery. */ + } + + pktdesc = (ugen_isoc_pkt_descr_t *) rdbuf; + + /* points to payload beginning */ + p = rdbuf + pktcnt * sizeof(ugen_isoc_pkt_descr_t); + + for (i = 0; i < pktcnt; i++) { + printf("packet %d len = %d," + " actual_len = %d, status = 0x%x\n", + i, pktdesc->dsc_isoc_pkt_len, + pktdesc->dsc_isoc_pkt_actual_len, + pktdesc->dsc_isoc_pkt_status); + + /* Processing data */ + + /* + * next packet data payload, do NOT use + * dsc_isoc_pkt_actual_len + */ + p += pktdesc->dsc_isoc_pkt_len; + + pktdesc++; + } + + + + For an isochronous-OUT endpoint, applications use the same + packet descriptor and request structures to write request + information to ugen node. Following the packet request head + information is the payload data of these packets. Upon + successful return of write(2), application can read(2) the same + ugen file immediately to retrieve individual packet transfer + status of last request. If application doesn't care the status, + it can choose to omit it. + + For example, application may transfer data on an + isochronous-OUT endpoint as the following, + + #include + + char *buf, *p; + ushort_t i, pktlen; + int len, pktcnt; + ugen_isoc_req_head_t *req; + ugen_isoc_pkt_descr_t *pktdesc; + char rdbuf[4096]; + + pktcnt = 4; + + /* + * set packet length to a proper value, don't + * exceed endpoint's capability + */ + pktlen = 1024; + + len = sizeof(int) + + sizeof(ugen_isoc_pkt_descr_t) * pktcount; + + len += pktlen * pktcnt; + + buf = malloc(len); + if (!buf) { + /* Error recovery. */ + } + + req = (ugen_isoc_req_head_t *)buf; + req->req_isoc_pkts_count = pktcnt; + + pktdesc = + (ugen_isoc_pkt_descr_t *)(req->req_isoc_pkt_descrs); + + for (i = 0; i < pktcnt; i++) { + pktdesc[i].dsc_isoc_pkt_len = pktlen; + pktdesc[i].dsc_isoc_pkt_actual_len = 0; + pktdesc[i].dsc_isoc_pkt_status = 0; + } + + /* moving to beginning of payload data */ + p = buf + sizeof(int) + sizeof(*pktdesc) * pktcnt; + for (i = 0; i < pktcnt; i++) { + + /* fill in the data buffer */ + + p += pktlen; + } + + /* + * write packet request information and data to ugen driver + * + * len should be the exact value of sizeof(int) + + * sizeof(ugen_isoc_pkt_descr_t) * pktcnt + payload length + */ + if (write(fd, buf, len) < 0) { + /* Error recovery. */ + } + + /* read packet status */ + if (read(fd, rdbuf, sizeof(*pktdesc) * pktcnt) < 0) { + + /* Error recovery. */ + + } else { + + /* Parse every packet's transfer status */ + + } + ERRORS The following statuses are returned by endpoint status dev- ice logical names: @@ -1196,8 +1446,21 @@ USB_LC_STAT_INTR_POLLING_FAILED Failed to restart polling. + + USB_LC_STAT_ISOC_POLLING_FAILED + Failed to start isochronous polling. + + USB_LC_STAT_ISOC_UNINITIALIZED + Isochronous packet information not initialized. + + USB_LC_STAT_ISOC_PKT_ERROR + All packets in this isochronous request have errors. The + polling on this isochronous-IN endpoint is suspended and + can be resumed on next read(2). + + The following system call errno values are returned: EINVAL An attempt was made to enable or disable "one @@ -1356,7 +1619,6 @@ NOTES - Isochronous transfers are not supported. ugen returns -1 for all commands and sets errno to ENODEV when device has been hot-removed or resumed from a suspend.