/* * do a bulk transfer */ int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int len) { int dir_out = usb_pipeout(pipe); int ep = usb_pipeendpoint(pipe); #ifndef MUSB_NO_MULTIPOINT int devnum = usb_pipedevice(pipe); #endif u8 type; u16 csr; u32 txlen = 0; u32 nextlen = 0; u8 devspeed; /* select bulk endpoint */ writeb(MUSB_BULK_EP, &musbr->index); #ifndef MUSB_NO_MULTIPOINT /* write the address of the device */ if (dir_out) writeb(devnum, &musbr->tar[MUSB_BULK_EP].txfuncaddr); else writeb(devnum, &musbr->tar[MUSB_BULK_EP].rxfuncaddr); #endif /* configure the hub address and the port number as required */ devspeed = get_dev_speed(dev); if ((musb_ishighspeed()) && (dev->parent != NULL) && (devspeed != MUSB_TYPE_SPEED_HIGH)) { /* * MUSB is in high speed and the destination device is full * speed device. So configure the hub address and port * address registers. */ config_hub_port(dev, MUSB_BULK_EP); } else { #ifndef MUSB_NO_MULTIPOINT if (dir_out) { writeb(0, &musbr->tar[MUSB_BULK_EP].txhubaddr); writeb(0, &musbr->tar[MUSB_BULK_EP].txhubport); } else { writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubaddr); writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubport); } #endif devspeed = musb_cfg.musb_speed; } /* Write the saved toggle bit value */ write_toggle(dev, ep, dir_out); if (dir_out) { /* bulk-out transfer */ /* Program the TxType register */ type = (devspeed << MUSB_TYPE_SPEED_SHIFT) | (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) | (ep & MUSB_TYPE_REMOTE_END); writeb(type, &musbr->txtype); /* Write maximum packet size to the TxMaxp register */ writew(dev->epmaxpacketout[ep], &musbr->txmaxp); while (txlen < len) { nextlen = ((len-txlen) < dev->epmaxpacketout[ep]) ? (len-txlen) : dev->epmaxpacketout[ep]; #ifdef CONFIG_USB_BLACKFIN /* Set the transfer data size */ writew(nextlen, &musbr->txcount); #endif /* Write the data to the FIFO */ write_fifo(MUSB_BULK_EP, nextlen, (void *)(((u8 *)buffer) + txlen)); /* Set the TxPktRdy bit */ csr = readw(&musbr->txcsr); writew(csr | MUSB_TXCSR_TXPKTRDY, &musbr->txcsr); /* Wait until the TxPktRdy bit is cleared */ if (!wait_until_txep_ready(dev, MUSB_BULK_EP)) { readw(&musbr->txcsr); usb_settoggle(dev, ep, dir_out, (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1); dev->act_len = txlen; return 0; } txlen += nextlen; } /* Keep a copy of the data toggle bit */ csr = readw(&musbr->txcsr); usb_settoggle(dev, ep, dir_out, (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1); } else { /* bulk-in transfer */
static int ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) { ALLOC_ALIGN_BUFFER(struct QH, qh, 1, USB_DMA_MINALIGN); struct qTD *qtd; int qtd_count = 0; int qtd_counter = 0; volatile struct qTD *vtd; unsigned long ts; uint32_t *tdp; uint32_t endpt, maxpacket, token, usbsts; uint32_t c, toggle; uint32_t cmd; int timeout; int ret = 0; struct ehci_ctrl *ctrl = ehci_get_ctrl(dev); debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, buffer, length, req); if (req != NULL) debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n", req->request, req->request, req->requesttype, req->requesttype, le16_to_cpu(req->value), le16_to_cpu(req->value), le16_to_cpu(req->index)); #define PKT_ALIGN 512 /* * The USB transfer is split into qTD transfers. Eeach qTD transfer is * described by a transfer descriptor (the qTD). The qTDs form a linked * list with a queue head (QH). * * Each qTD transfer starts with a new USB packet, i.e. a packet cannot * have its beginning in a qTD transfer and its end in the following * one, so the qTD transfer lengths have to be chosen accordingly. * * Each qTD transfer uses up to QT_BUFFER_CNT data buffers, mapped to * single pages. The first data buffer can start at any offset within a * page (not considering the cache-line alignment issues), while the * following buffers must be page-aligned. There is no alignment * constraint on the size of a qTD transfer. */ if (req != NULL) /* 1 qTD will be needed for SETUP, and 1 for ACK. */ qtd_count += 1 + 1; if (length > 0 || req == NULL) { /* * Determine the qTD transfer size that will be used for the * data payload (not considering the first qTD transfer, which * may be longer or shorter, and the final one, which may be * shorter). * * In order to keep each packet within a qTD transfer, the qTD * transfer size is aligned to PKT_ALIGN, which is a multiple of * wMaxPacketSize (except in some cases for interrupt transfers, * see comment in submit_int_msg()). * * By default, i.e. if the input buffer is aligned to PKT_ALIGN, * QT_BUFFER_CNT full pages will be used. */ int xfr_sz = QT_BUFFER_CNT; /* * However, if the input buffer is not aligned to PKT_ALIGN, the * qTD transfer size will be one page shorter, and the first qTD * data buffer of each transfer will be page-unaligned. */ if ((unsigned long)buffer & (PKT_ALIGN - 1)) xfr_sz--; /* Convert the qTD transfer size to bytes. */ xfr_sz *= EHCI_PAGE_SIZE; /* * Approximate by excess the number of qTDs that will be * required for the data payload. The exact formula is way more * complicated and saves at most 2 qTDs, i.e. a total of 128 * bytes. */ qtd_count += 2 + length / xfr_sz; } /* * Threshold value based on the worst-case total size of the allocated qTDs for * a mass-storage transfer of 65535 blocks of 512 bytes. */ #if CONFIG_SYS_MALLOC_LEN <= 64 + 128 * 1024 #warning CONFIG_SYS_MALLOC_LEN may be too small for EHCI #endif qtd = memalign(USB_DMA_MINALIGN, qtd_count * sizeof(struct qTD)); if (qtd == NULL) { printf("unable to allocate TDs\n"); return -1; } memset(qh, 0, sizeof(struct QH)); memset(qtd, 0, qtd_count * sizeof(*qtd)); toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); /* * Setup QH (3.6 in ehci-r10.pdf) * * qh_link ................. 03-00 H * qh_endpt1 ............... 07-04 H * qh_endpt2 ............... 0B-08 H * - qh_curtd * qh_overlay.qt_next ...... 13-10 H * - qh_overlay.qt_altnext */ qh->qh_link = cpu_to_hc32(virt_to_phys(&ctrl->qh_list) | QH_LINK_TYPE_QH); c = (dev->speed != USB_SPEED_HIGH) && !usb_pipeendpoint(pipe); maxpacket = usb_maxpacket(dev, pipe); endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) | QH_ENDPT1_MAXPKTLEN(maxpacket) | QH_ENDPT1_H(0) | QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) | QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) | QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) | QH_ENDPT1_DEVADDR(usb_pipedevice(pipe)); qh->qh_endpt1 = cpu_to_hc32(endpt); endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0); qh->qh_endpt2 = cpu_to_hc32(endpt); ehci_update_endpt2_dev_n_port(dev, qh); qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); tdp = &qh->qh_overlay.qt_next; if (req != NULL) { /* * Setup request qTD (3.5 in ehci-r10.pdf) * * qt_next ................ 03-00 H * qt_altnext ............. 07-04 H * qt_token ............... 0B-08 H * * [ buffer, buffer_hi ] loaded with "req". */ qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = QT_TOKEN_DT(0) | QT_TOKEN_TOTALBYTES(sizeof(*req)) | QT_TOKEN_IOC(0) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | QT_TOKEN_PID(QT_TOKEN_PID_SETUP) | QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); qtd[qtd_counter].qt_token = cpu_to_hc32(token); if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req))) { printf("unable to construct SETUP TD\n"); goto fail; } /* Update previous qTD! */ *tdp = cpu_to_hc32(virt_to_phys(&qtd[qtd_counter])); tdp = &qtd[qtd_counter++].qt_next; toggle = 1; } if (length > 0 || req == NULL) { uint8_t *buf_ptr = buffer; int left_length = length; do { /* * Determine the size of this qTD transfer. By default, * QT_BUFFER_CNT full pages can be used. */ int xfr_bytes = QT_BUFFER_CNT * EHCI_PAGE_SIZE; /* * However, if the input buffer is not page-aligned, the * portion of the first page before the buffer start * offset within that page is unusable. */ xfr_bytes -= (unsigned long)buf_ptr & (EHCI_PAGE_SIZE - 1); /* * In order to keep each packet within a qTD transfer, * align the qTD transfer size to PKT_ALIGN. */ xfr_bytes &= ~(PKT_ALIGN - 1); /* * This transfer may be shorter than the available qTD * transfer size that has just been computed. */ xfr_bytes = min(xfr_bytes, left_length); /* * Setup request qTD (3.5 in ehci-r10.pdf) * * qt_next ................ 03-00 H * qt_altnext ............. 07-04 H * qt_token ............... 0B-08 H * * [ buffer, buffer_hi ] loaded with "buffer". */ qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = QT_TOKEN_DT(toggle) | QT_TOKEN_TOTALBYTES(xfr_bytes) | QT_TOKEN_IOC(req == NULL) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | QT_TOKEN_PID(usb_pipein(pipe) ? QT_TOKEN_PID_IN : QT_TOKEN_PID_OUT) | QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); qtd[qtd_counter].qt_token = cpu_to_hc32(token); if (ehci_td_buffer(&qtd[qtd_counter], buf_ptr, xfr_bytes)) { printf("unable to construct DATA TD\n"); goto fail; } /* Update previous qTD! */ *tdp = cpu_to_hc32(virt_to_phys(&qtd[qtd_counter])); tdp = &qtd[qtd_counter++].qt_next; /* * Data toggle has to be adjusted since the qTD transfer * size is not always an even multiple of * wMaxPacketSize. */ if ((xfr_bytes / maxpacket) & 1) toggle ^= 1; buf_ptr += xfr_bytes; left_length -= xfr_bytes; } while (left_length > 0); } if (req != NULL) { /* * Setup request qTD (3.5 in ehci-r10.pdf) * * qt_next ................ 03-00 H * qt_altnext ............. 07-04 H * qt_token ............... 0B-08 H */ qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = QT_TOKEN_DT(1) | QT_TOKEN_TOTALBYTES(0) | QT_TOKEN_IOC(1) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | QT_TOKEN_PID(usb_pipein(pipe) ? QT_TOKEN_PID_OUT : QT_TOKEN_PID_IN) | QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); qtd[qtd_counter].qt_token = cpu_to_hc32(token); /* Update previous qTD! */ *tdp = cpu_to_hc32(virt_to_phys(&qtd[qtd_counter])); tdp = &qtd[qtd_counter++].qt_next; } ctrl->qh_list.qh_link = cpu_to_hc32(virt_to_phys(qh) | QH_LINK_TYPE_QH); /* Flush dcache */ flush_dcache_range((unsigned long)&ctrl->qh_list, ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1)); flush_dcache_range((unsigned long)qh, ALIGN_END_ADDR(struct QH, qh, 1)); flush_dcache_range((unsigned long)qtd, ALIGN_END_ADDR(struct qTD, qtd, qtd_count)); /* Set async. queue head pointer. */ ehci_writel(&ctrl->hcor->or_asynclistaddr, virt_to_phys(&ctrl->qh_list)); usbsts = ehci_readl(&ctrl->hcor->or_usbsts); ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f)); /* Enable async. schedule. */ cmd = ehci_readl(&ctrl->hcor->or_usbcmd); cmd |= CMD_ASE; ehci_writel(&ctrl->hcor->or_usbcmd, cmd); ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, STS_ASS, 100 * 1000); if (ret < 0) { printf("EHCI fail timeout STS_ASS set\n"); goto fail; } /* Wait for TDs to be processed. */ ts = get_timer(0); vtd = &qtd[qtd_counter - 1]; timeout = USB_TIMEOUT_MS(pipe); do { /* Invalidate dcache */ invalidate_dcache_range((unsigned long)&ctrl->qh_list, ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1)); invalidate_dcache_range((unsigned long)qh, ALIGN_END_ADDR(struct QH, qh, 1)); invalidate_dcache_range((unsigned long)qtd, ALIGN_END_ADDR(struct qTD, qtd, qtd_count)); token = hc32_to_cpu(vtd->qt_token); if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) break; WATCHDOG_RESET(); } while (get_timer(ts) < timeout); /* * Invalidate the memory area occupied by buffer * Don't try to fix the buffer alignment, if it isn't properly * aligned it's upper layer's fault so let invalidate_dcache_range() * vow about it. But we have to fix the length as it's actual * transfer length and can be unaligned. This is potentially * dangerous operation, it's responsibility of the calling * code to make sure enough space is reserved. */ invalidate_dcache_range((unsigned long)buffer, ALIGN((unsigned long)buffer + length, ARCH_DMA_MINALIGN)); /* Check that the TD processing happened */ if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE) printf("EHCI timed out on TD - token=%#x\n", token); /* Disable async schedule. */ cmd = ehci_readl(&ctrl->hcor->or_usbcmd); cmd &= ~CMD_ASE; ehci_writel(&ctrl->hcor->or_usbcmd, cmd); ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, 0, 100 * 1000); if (ret < 0) { printf("EHCI fail timeout STS_ASS reset\n"); goto fail; } token = hc32_to_cpu(qh->qh_overlay.qt_token); if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) { debug("TOKEN=%#x\n", token); switch (QT_TOKEN_GET_STATUS(token) & ~(QT_TOKEN_STATUS_SPLITXSTATE | QT_TOKEN_STATUS_PERR)) { case 0: toggle = QT_TOKEN_GET_DT(token); usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), toggle); dev->status = 0; break; case QT_TOKEN_STATUS_HALTED: dev->status = USB_ST_STALLED; break; case QT_TOKEN_STATUS_ACTIVE | QT_TOKEN_STATUS_DATBUFERR: case QT_TOKEN_STATUS_DATBUFERR: dev->status = USB_ST_BUF_ERR; break; case QT_TOKEN_STATUS_HALTED | QT_TOKEN_STATUS_BABBLEDET: case QT_TOKEN_STATUS_BABBLEDET: dev->status = USB_ST_BABBLE_DET; break; default: dev->status = USB_ST_CRC_ERR; if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_HALTED) dev->status |= USB_ST_STALLED; break; } dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token); } else { dev->act_len = 0; #ifndef CONFIG_USB_EHCI_FARADAY debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n", dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts), ehci_readl(&ctrl->hcor->or_portsc[0]), ehci_readl(&ctrl->hcor->or_portsc[1])); #endif } free(qtd); return (dev->status != USB_ST_NOT_PROC) ? 0 : -1; fail: free(qtd); return -1; }
static inline int qu_pipeindex (__u32 pipe) { return (usb_pipeendpoint (pipe) << 1) | (usb_pipecontrol (pipe) ? 0 : usb_pipeout (pipe)); }
void dwc_otg_hcd_qh_init(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, struct urb *urb) { char *speed, *type; memset (qh, 0, sizeof (dwc_otg_qh_t)); if(urb && urb->dev){ usb_settoggle (urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 1); } /* Initialize QH */ switch (usb_pipetype(urb->pipe)) { case PIPE_CONTROL: qh->ep_type = USB_ENDPOINT_XFER_CONTROL; break; case PIPE_BULK: qh->ep_type = USB_ENDPOINT_XFER_BULK; break; case PIPE_ISOCHRONOUS: qh->ep_type = USB_ENDPOINT_XFER_ISOC; break; case PIPE_INTERRUPT: qh->ep_type = USB_ENDPOINT_XFER_INT; break; } qh->ep_is_in = usb_pipein(urb->pipe) ? 1 : 0; qh->data_toggle = DWC_OTG_HC_PID_DATA0; qh->maxp = usb_maxpacket(urb->dev, urb->pipe, !(usb_pipein(urb->pipe))); INIT_LIST_HEAD(&qh->qtd_list); INIT_LIST_HEAD(&qh->qh_list_entry); qh->channel = NULL; /* FS/LS Enpoint on HS Hub * NOT virtual root hub */ qh->do_split = 0; if (((urb->dev->speed == USB_SPEED_LOW) || (urb->dev->speed == USB_SPEED_FULL)) && (urb->dev->tt) && (urb->dev->tt->hub->devnum != 1)) { DWC_DEBUGPL(DBG_HCD, "QH init: EP %d: TT found at hub addr %d, for port %d\n", usb_pipeendpoint(urb->pipe), urb->dev->tt->hub->devnum, urb->dev->ttport); qh->do_split = 1; } if (qh->ep_type == USB_ENDPOINT_XFER_INT || qh->ep_type == USB_ENDPOINT_XFER_ISOC) { /* Compute scheduling parameters once and save them. */ hprt0_data_t hprt; /** @todo Account for split transfers in the bus time. */ int bytecount = dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp); /* FIXME: work-around patch by Steven */ qh->usecs = NS_TO_US(usb_calc_bus_time(urb->dev->speed, usb_pipein(urb->pipe), (qh->ep_type == USB_ENDPOINT_XFER_ISOC), bytecount)); /* Start in a slightly future (micro)frame. */ qh->sched_frame = dwc_frame_num_inc(hcd->frame_number, SCHEDULE_SLOP); qh->interval = urb->interval; #if 0 /* Increase interrupt polling rate for debugging. */ if (qh->ep_type == USB_ENDPOINT_XFER_INT) { qh->interval = 8; } #endif hprt.d32 = dwc_read_reg32(hcd->core_if->host_if->hprt0); if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) && ((urb->dev->speed == USB_SPEED_LOW) || (urb->dev->speed == USB_SPEED_FULL))) { qh->interval *= 8; qh->sched_frame |= 0x7; qh->start_split_frame = qh->sched_frame; } } DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n"); DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - qh = %p\n", qh); DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Device Address = %d\n", urb->dev->devnum); DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Endpoint %d, %s\n", usb_pipeendpoint(urb->pipe), usb_pipein(urb->pipe) == USB_DIR_IN ? "IN" : "OUT"); switch(urb->dev->speed) { case USB_SPEED_LOW: qh->dev_speed = DWC_OTG_EP_SPEED_LOW; speed = "low"; break; case USB_SPEED_FULL: qh->dev_speed = DWC_OTG_EP_SPEED_FULL; speed = "full"; break; case USB_SPEED_HIGH: qh->dev_speed = DWC_OTG_EP_SPEED_HIGH; speed = "high"; break; default: speed = "?"; break; } DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Speed = %s\n", speed); switch (qh->ep_type) { case USB_ENDPOINT_XFER_ISOC: type = "isochronous"; break; case USB_ENDPOINT_XFER_INT: type = "interrupt"; break; case USB_ENDPOINT_XFER_CONTROL: type = "control"; break; case USB_ENDPOINT_XFER_BULK: type = "bulk"; break; default: type = "?"; break; } DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Type = %s\n",type); #ifdef DEBUG if (qh->ep_type == USB_ENDPOINT_XFER_INT) { DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n", qh->usecs); DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n", qh->interval); } #endif qh->dw_align_buf = NULL; return; }
int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int len,struct devrequest *setup) { int done = 0; int devnum = usb_pipedevice(pipe); int ep = usb_pipeendpoint(pipe); dev->status = 0; if (devnum == root_hub_devnum) return sl811_rh_submit_urb(dev, pipe, buffer, len, setup); PDEBUG(7, "dev = %d pipe = %ld buf = %p size = %d rt = %#x req = %#x bus = %i\n", devnum, ep, buffer, len, (int)setup->requesttype, (int)setup->request, sl811_read(SL811_SOFCNTDIV)*64); sl811_write(SL811_DEV_A, devnum); sl811_write(SL811_PIDEP_A, PIDEP(USB_PID_SETUP, ep)); /* setup phase */ usb_settoggle(dev, ep, 1, 0); if (sl811_send_packet(dev, usb_sndctrlpipe(dev, ep), (__u8*)setup, sizeof(*setup)) == sizeof(*setup)) { int dir_in = usb_pipein(pipe); int max = usb_maxpacket(dev, pipe); /* data phase */ sl811_write(SL811_PIDEP_A, PIDEP(dir_in ? USB_PID_IN : USB_PID_OUT, ep)); usb_settoggle(dev, ep, usb_pipeout(pipe), 1); while (done < len) { int res = sl811_send_packet(dev, pipe, (__u8*)buffer+done, max > len - done ? len - done : max); if (res < 0) { PDEBUG(0, "status data failed!\n"); dev->status = -res; return 0; } done += res; usb_dotoggle(dev, ep, usb_pipeout(pipe)); if (dir_in && res < max) /* short packet */ break; } /* status phase */ sl811_write(SL811_PIDEP_A, PIDEP(!dir_in ? USB_PID_IN : USB_PID_OUT, ep)); usb_settoggle(dev, ep, !usb_pipeout(pipe), 1); if (sl811_send_packet(dev, !dir_in ? usb_rcvctrlpipe(dev, ep) : usb_sndctrlpipe(dev, ep), 0, 0) < 0) { PDEBUG(0, "status phase failed!\n"); dev->status = -1; } } else { PDEBUG(0, "setup phase failed!\n"); dev->status = -1; } dev->act_len = done; return done; }
/* * This routine is called by the USB subsystem for each new device * in the system. We need to check if the device is ours, and in * this case start handling it. */ static int ksdazzle_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_device *dev = interface_to_usbdev(intf); struct ksdazzle_cb *kingsun = NULL; struct net_device *net = NULL; int ret = -ENOMEM; int pipe, maxp_in, maxp_out; __u8 ep_in; __u8 ep_out; /* Check that there really are two interrupt endpoints. Check based on the one in drivers/usb/input/usbmouse.c */ interface = intf->cur_altsetting; if (interface->desc.bNumEndpoints != 2) { err("ksdazzle: expected 2 endpoints, found %d", interface->desc.bNumEndpoints); return -ENODEV; } endpoint = &interface->endpoint[KINGSUN_EP_IN].desc; if (!usb_endpoint_is_int_in(endpoint)) { err("ksdazzle: endpoint 0 is not interrupt IN"); return -ENODEV; } ep_in = endpoint->bEndpointAddress; pipe = usb_rcvintpipe(dev, ep_in); maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); if (maxp_in > 255 || maxp_in <= 1) { err("ksdazzle: endpoint 0 has max packet size %d not in range [2..255]", maxp_in); return -ENODEV; } endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc; if (!usb_endpoint_is_int_out(endpoint)) { err("ksdazzle: endpoint 1 is not interrupt OUT"); return -ENODEV; } ep_out = endpoint->bEndpointAddress; pipe = usb_sndintpipe(dev, ep_out); maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); /* Allocate network device container. */ net = alloc_irdadev(sizeof(*kingsun)); if (!net) goto err_out1; SET_NETDEV_DEV(net, &intf->dev); kingsun = netdev_priv(net); kingsun->netdev = net; kingsun->usbdev = dev; kingsun->ep_in = ep_in; kingsun->ep_out = ep_out; kingsun->irlap = NULL; kingsun->tx_urb = NULL; kingsun->tx_buf_clear = NULL; kingsun->tx_buf_clear_used = 0; kingsun->tx_buf_clear_sent = 0; kingsun->rx_urb = NULL; kingsun->rx_buf = NULL; kingsun->rx_unwrap_buff.in_frame = FALSE; kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; kingsun->rx_unwrap_buff.skb = NULL; kingsun->receiving = 0; spin_lock_init(&kingsun->lock); kingsun->speed_setuprequest = NULL; kingsun->speed_urb = NULL; kingsun->speedparams.baudrate = 0; /* Allocate input buffer */ kingsun->rx_buf = kmalloc(KINGSUN_RCV_MAX, GFP_KERNEL); if (!kingsun->rx_buf) goto free_mem; /* Allocate output buffer */ kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL); if (!kingsun->tx_buf_clear) goto free_mem; /* Allocate and initialize speed setup packet */ kingsun->speed_setuprequest = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); if (!kingsun->speed_setuprequest) goto free_mem; kingsun->speed_setuprequest->bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND; kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200); kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001); kingsun->speed_setuprequest->wLength = cpu_to_le16(sizeof(struct ksdazzle_speedparams)); printk(KERN_INFO "KingSun/Dazzle IRDA/USB found at address %d, " "Vendor: %x, Product: %x\n", dev->devnum, le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); /* Initialize QoS for this device */ irda_init_max_qos_capabilies(&kingsun->qos); /* Baud rates known to be supported. Please uncomment if devices (other than a SonyEriccson K300 phone) can be shown to support higher speeds with this dongle. */ kingsun->qos.baud_rate.bits = IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200; kingsun->qos.min_turn_time.bits &= KINGSUN_MTT; irda_qos_bits_to_value(&kingsun->qos); /* Override the network functions we need to use */ net->hard_start_xmit = ksdazzle_hard_xmit; net->open = ksdazzle_net_open; net->stop = ksdazzle_net_close; net->do_ioctl = ksdazzle_net_ioctl; ret = register_netdev(net); if (ret != 0) goto free_mem; dev_info(&net->dev, "IrDA: Registered KingSun/Dazzle device %s\n", net->name); usb_set_intfdata(intf, kingsun); /* Situation at this point: - all work buffers allocated - setup requests pre-filled - urbs not allocated, set to NULL - max rx packet known (is KINGSUN_FIFO_SIZE) - unwrap state machine (partially) initialized, but skb == NULL */ return 0; free_mem: kfree(kingsun->speed_setuprequest); kfree(kingsun->tx_buf_clear); kfree(kingsun->rx_buf); free_netdev(net); err_out1: return ret; }
static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_mouse *mouse; struct input_dev *input_dev; int pipe, maxp; int error = -ENOMEM; interface = intf->cur_altsetting; if (interface->desc.bNumEndpoints != 1) return -ENODEV; endpoint = &interface->endpoint[0].desc; if (!usb_endpoint_is_int_in(endpoint)) return -ENODEV; pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL); input_dev = input_allocate_device(); if (!mouse || !input_dev) goto fail1; mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma); if (!mouse->data) goto fail1; mouse->irq = usb_alloc_urb(0, GFP_KERNEL); if (!mouse->irq) goto fail2; mouse->usbdev = dev; mouse->dev = input_dev; if (dev->manufacturer) strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name)); if (dev->product) { if (dev->manufacturer) strlcat(mouse->name, " ", sizeof(mouse->name)); strlcat(mouse->name, dev->product, sizeof(mouse->name)); } if (!strlen(mouse->name)) snprintf(mouse->name, sizeof(mouse->name), "USB HIDBP Mouse %04x:%04x", le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); usb_make_path(dev, mouse->phys, sizeof(mouse->phys)); strlcat(mouse->phys, "/input0", sizeof(mouse->phys)); input_dev->name = mouse->name; input_dev->phys = mouse->phys; usb_to_input_id(dev, &input_dev->id); input_dev->dev.parent = &intf->dev; input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); input_dev->relbit[0] |= BIT_MASK(REL_WHEEL); input_set_drvdata(input_dev, mouse); input_dev->open = usb_mouse_open; input_dev->close = usb_mouse_close; usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data, (maxp > 8 ? 8 : maxp), usb_mouse_irq, mouse, endpoint->bInterval); mouse->irq->transfer_dma = mouse->data_dma; mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; error = input_register_device(mouse->dev); if (error) goto fail3; usb_set_intfdata(intf, mouse); return 0; fail3: usb_free_urb(mouse->irq); fail2: usb_buffer_free(dev, 8, mouse->data, mouse->data_dma); fail1: input_free_device(input_dev); kfree(mouse); return error; }
static int usb_remote_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = NULL; struct usb_host_interface *idesc = NULL; struct usb_host_endpoint *ep_ctl2; #else static void *usb_remote_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id) { struct usb_interface *intf; struct usb_interface_descriptor *idesc; struct usb_endpoint_descriptor *ep_ctl2; #endif struct igorplug *ir = NULL; struct lirc_driver *driver = NULL; int devnum, pipe, maxp; int minor = 0; char buf[63], name[128] = ""; int mem_failure = 0; int ret; dprintk(": usb probe called.\n"); #if defined(KERNEL_2_5) dev = interface_to_usbdev(intf); # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5) idesc = &intf->altsetting[intf->act_altsetting]; /* in 2.6.4 */ # else idesc = intf->cur_altsetting; /* in 2.6.6 */ # endif if (idesc->desc.bNumEndpoints != 1) return -ENODEV; ep_ctl2 = idesc->endpoint; if (((ep_ctl2->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN) || (ep_ctl2->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_CONTROL) return -ENODEV; pipe = usb_rcvctrlpipe(dev, ep_ctl2->desc.bEndpointAddress); #else intf = &dev->actconfig->interface[ifnum]; idesc = &intf->altsetting[intf->act_altsetting]; if (idesc->bNumEndpoints != 1) return NULL; ep_ctl2 = idesc->endpoint; if (((ep_ctl2->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN) || (ep_ctl2->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_CONTROL) return NULL; pipe = usb_rcvctrlpipe(dev, ep_ctl2->bEndpointAddress); #endif devnum = dev->devnum; maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); dprintk(DRIVER_NAME "[%d]: bytes_in_key=%d maxp=%d\n", devnum, CODE_LENGTH, maxp); mem_failure = 0; ir = kzalloc(sizeof(struct igorplug), GFP_KERNEL); if (!ir) { mem_failure = 1; goto mem_failure_switch; } driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); if (!driver) { mem_failure = 2; goto mem_failure_switch; } #if defined(KERNEL_2_5) ir->buf_in = usb_buffer_alloc(dev, DEVICE_BUFLEN+DEVICE_HEADERLEN, GFP_ATOMIC, &ir->dma_in); #else ir->buf_in = kmalloc(DEVICE_BUFLEN+DEVICE_HEADERLEN, GFP_KERNEL); #endif if (!ir->buf_in) { mem_failure = 3; goto mem_failure_switch; } strcpy(driver->name, DRIVER_NAME " "); driver->minor = -1; driver->code_length = CODE_LENGTH * 8; /* in bits */ driver->features = LIRC_CAN_REC_MODE2; driver->data = ir; driver->buffer_size = DEVICE_BUFLEN + ADDITIONAL_LIRC_BYTES; driver->set_use_inc = &set_use_inc; driver->set_use_dec = &set_use_dec; driver->sample_rate = sample_rate; /* per second */ driver->add_to_buf = &usb_remote_poll; #ifdef LIRC_HAVE_SYSFS driver->dev = &intf->dev; #endif driver->owner = THIS_MODULE; minor = lirc_register_driver(driver); if (minor < 0) mem_failure = 9; mem_failure_switch: switch (mem_failure) { case 9: #if defined(KERNEL_2_5) usb_buffer_free(dev, DEVICE_BUFLEN+DEVICE_HEADERLEN, ir->buf_in, ir->dma_in); #else kfree(ir->buf_in); #endif case 3: kfree(driver); case 2: kfree(ir); case 1: printk(KERN_ERR DRIVER_NAME "[%d]: out of memory (code=%d)\n", devnum, mem_failure); #if defined(KERNEL_2_5) return -ENOMEM; #else return NULL; #endif } driver->minor = minor; ir->d = driver; ir->devnum = devnum; ir->usbdev = dev; ir->len_in = DEVICE_BUFLEN+DEVICE_HEADERLEN; ir->in_space = 1; /* First mode2 event is a space. */ do_gettimeofday(&ir->last_time); if (dev->descriptor.iManufacturer && usb_string(dev, dev->descriptor.iManufacturer, buf, sizeof(buf)) > 0) strlcpy(name, buf, sizeof(name)); if (dev->descriptor.iProduct && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) snprintf(name + strlen(name), sizeof(name) - strlen(name), " %s", buf); printk(KERN_INFO DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name, dev->bus->busnum, devnum); /* clear device buffer */ ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, /*unused*/0, /*unused*/0, /*dummy*/ir->buf_in, /*dummy*/ir->len_in, /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); if (ret < 0) printk(KERN_WARNING DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n", devnum, ret); #if defined(KERNEL_2_5) usb_set_intfdata(intf, ir); return 0; #else return ir; #endif } #if defined(KERNEL_2_5) static void usb_remote_disconnect(struct usb_interface *intf) { struct usb_device *dev = interface_to_usbdev(intf); struct igorplug *ir = usb_get_intfdata(intf); #else static void usb_remote_disconnect(struct usb_device *dev, void *ptr) { struct igorplug *ir = ptr; #endif if (!ir || !ir->d) return; printk(KERN_INFO DRIVER_NAME "[%d]: usb remote disconnected\n", ir->devnum); lirc_unregister_driver(ir->d->minor); lirc_buffer_free(ir->d->rbuf); kfree(ir->d->rbuf); kfree(ir->d); #if defined(KERNEL_2_5) usb_buffer_free(dev, ir->len_in, ir->buf_in, ir->dma_in); #else kfree(ir->buf_in); #endif kfree(ir); } static struct usb_device_id usb_remote_id_table [] = { /* Igor Plug USB (Atmel's Manufact. ID) */ { USB_DEVICE(0x03eb, 0x0002) }, /* Fit PC2 Infrared Adapter */ { USB_DEVICE(0x03eb, 0x21fe) }, /* Terminating entry */ { } }; static struct usb_driver usb_remote_driver = { LIRC_THIS_MODULE(.owner = THIS_MODULE) .name = DRIVER_NAME, .probe = usb_remote_probe, .disconnect = usb_remote_disconnect, .id_table = usb_remote_id_table }; static int __init usb_remote_init(void) { int i; printk(KERN_INFO DRIVER_NAME ": " DRIVER_DESC " v" DRIVER_VERSION "\n"); printk(KERN_INFO DRIVER_NAME ": " DRIVER_AUTHOR "\n"); dprintk(": debug mode enabled\n"); i = usb_register(&usb_remote_driver); if (i < 0) { printk(KERN_ERR DRIVER_NAME ": usb register failed, result = %d\n", i); return -ENODEV; } return 0; }
static int hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint) { struct usb_device *dev = interface_to_usbdev (hub->intf); struct device *hub_dev; u16 hubstatus, hubchange; unsigned int pipe; int maxp, ret; char *message; hub->buffer = usb_buffer_alloc(dev, sizeof(*hub->buffer), GFP_KERNEL, &hub->buffer_dma); if (!hub->buffer) { message = "can't allocate hub irq buffer"; ret = -ENOMEM; goto fail; } hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL); if (!hub->status) { message = "can't kmalloc hub status buffer"; ret = -ENOMEM; goto fail; } hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); if (!hub->descriptor) { message = "can't kmalloc hub descriptor"; ret = -ENOMEM; goto fail; } /* Request the entire hub descriptor. * hub->descriptor can handle USB_MAXCHILDREN ports, * but the hub can/will return fewer bytes here. */ ret = get_hub_descriptor(dev, hub->descriptor, sizeof(*hub->descriptor)); if (ret < 0) { message = "can't read hub descriptor"; goto fail; } else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) { message = "hub has too many ports!"; ret = -ENODEV; goto fail; } hub_dev = hubdev(dev); dev->maxchild = hub->descriptor->bNbrPorts; dev_info (hub_dev, "%d port%s detected\n", dev->maxchild, (dev->maxchild == 1) ? "" : "s"); le16_to_cpus(&hub->descriptor->wHubCharacteristics); if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND) { int i; char portstr [USB_MAXCHILDREN + 1]; for (i = 0; i < dev->maxchild; i++) portstr[i] = hub->descriptor->DeviceRemovable [((i + 1) / 8)] & (1 << ((i + 1) % 8)) ? 'F' : 'R'; portstr[dev->maxchild] = 0; dev_dbg(hub_dev, "compound device; port removable status: %s\n", portstr); } else dev_dbg(hub_dev, "standalone hub\n"); switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) { case 0x00: dev_dbg(hub_dev, "ganged power switching\n"); break; case 0x01: dev_dbg(hub_dev, "individual port power switching\n"); break; case 0x02: case 0x03: dev_dbg(hub_dev, "unknown reserved power switching mode\n"); break; } switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) { case 0x00: dev_dbg(hub_dev, "global over-current protection\n"); break; case 0x08: dev_dbg(hub_dev, "individual port over-current protection\n"); break; case 0x10: case 0x18: dev_dbg(hub_dev, "no over-current protection\n"); break; } spin_lock_init (&hub->tt.lock); INIT_LIST_HEAD (&hub->tt.clear_list); INIT_WORK (&hub->tt.kevent, hub_tt_kevent, hub); switch (dev->descriptor.bDeviceProtocol) { case 0: break; case 1: dev_dbg(hub_dev, "Single TT\n"); hub->tt.hub = dev; break; case 2: dev_dbg(hub_dev, "TT per port\n"); hub->tt.hub = dev; hub->tt.multi = 1; break; default: dev_dbg(hub_dev, "Unrecognized hub protocol %d\n", dev->descriptor.bDeviceProtocol); break; } switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) { case 0x00: if (dev->descriptor.bDeviceProtocol != 0) dev_dbg(hub_dev, "TT requires at most 8 FS bit times\n"); break; case 0x20: dev_dbg(hub_dev, "TT requires at most 16 FS bit times\n"); break; case 0x40: dev_dbg(hub_dev, "TT requires at most 24 FS bit times\n"); break; case 0x60: dev_dbg(hub_dev, "TT requires at most 32 FS bit times\n"); break; } dev_dbg(hub_dev, "Port indicators are %s supported\n", (hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND) ? "" : "not"); dev_dbg(hub_dev, "power on to power good time: %dms\n", hub->descriptor->bPwrOn2PwrGood * 2); dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", hub->descriptor->bHubContrCurrent); ret = hub_hub_status(hub, &hubstatus, &hubchange); if (ret < 0) { message = "can't get hub status"; goto fail; } dev_dbg(hub_dev, "local power source is %s\n", (hubstatus & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good"); dev_dbg(hub_dev, "%sover-current condition exists\n", (hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no "); /* Start the interrupt endpoint */ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); if (maxp > sizeof(*hub->buffer)) maxp = sizeof(*hub->buffer); hub->urb = usb_alloc_urb(0, GFP_KERNEL); if (!hub->urb) { message = "couldn't allocate interrupt urb"; ret = -ENOMEM; goto fail; } usb_fill_int_urb(hub->urb, dev, pipe, *hub->buffer, maxp, hub_irq, hub, endpoint->bInterval); hub->urb->transfer_dma = hub->buffer_dma; hub->urb->transfer_flags |= URB_NO_DMA_MAP; ret = usb_submit_urb(hub->urb, GFP_KERNEL); if (ret) { message = "couldn't submit status urb"; goto fail; } /* Wake up khubd */ wake_up(&khubd_wait); hub_power_on(hub); return 0; fail: dev_err (&hub->intf->dev, "config failed, %s (err %d)\n", message, ret); /* hub_disconnect() frees urb and descriptor */ return ret; }
static int igorplugusb_remote_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = NULL; struct usb_host_interface *idesc = NULL; struct usb_endpoint_descriptor *ep; struct igorplug *ir = NULL; struct lirc_driver *driver = NULL; int devnum, pipe, maxp; int minor = 0; char buf[63], name[128] = ""; int mem_failure = 0; int ret; dprintk(DRIVER_NAME ": usb probe called.\n"); dev = interface_to_usbdev(intf); idesc = intf->cur_altsetting; if (idesc->desc.bNumEndpoints != 1) return -ENODEV; ep = &idesc->endpoint->desc; if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN) || (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_CONTROL) return -ENODEV; pipe = usb_rcvctrlpipe(dev, ep->bEndpointAddress); devnum = dev->devnum; maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); dprintk(DRIVER_NAME "[%d]: bytes_in_key=%zu maxp=%d\n", devnum, CODE_LENGTH, maxp); mem_failure = 0; ir = kzalloc(sizeof(struct igorplug), GFP_KERNEL); if (!ir) { mem_failure = 1; goto mem_failure_switch; } driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); if (!driver) { mem_failure = 2; goto mem_failure_switch; } ir->buf_in = usb_alloc_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN, GFP_ATOMIC, &ir->dma_in); if (!ir->buf_in) { mem_failure = 3; goto mem_failure_switch; } strcpy(driver->name, DRIVER_NAME " "); driver->minor = -1; driver->code_length = CODE_LENGTH * 8; /* in bits */ driver->features = LIRC_CAN_REC_MODE2; driver->data = ir; driver->chunk_size = CODE_LENGTH; driver->buffer_size = DEVICE_BUFLEN + ADDITIONAL_LIRC_BYTES; driver->set_use_inc = &set_use_inc; driver->set_use_dec = &set_use_dec; driver->sample_rate = sample_rate; /* per second */ driver->add_to_buf = &igorplugusb_remote_poll; driver->dev = &intf->dev; driver->owner = THIS_MODULE; minor = lirc_register_driver(driver); if (minor < 0) mem_failure = 9; mem_failure_switch: switch (mem_failure) { case 9: usb_free_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN, ir->buf_in, ir->dma_in); case 3: kfree(driver); case 2: kfree(ir); case 1: printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", devnum, mem_failure); return -ENOMEM; } driver->minor = minor; ir->d = driver; ir->devnum = devnum; ir->usbdev = dev; ir->len_in = DEVICE_BUFLEN + DEVICE_HEADERLEN; ir->in_space = 1; /* First mode2 event is a space. */ do_gettimeofday(&ir->last_time); if (dev->descriptor.iManufacturer && usb_string(dev, dev->descriptor.iManufacturer, buf, sizeof(buf)) > 0) strlcpy(name, buf, sizeof(name)); if (dev->descriptor.iProduct && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) snprintf(name + strlen(name), sizeof(name) - strlen(name), " %s", buf); printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name, dev->bus->busnum, devnum); /* clear device buffer */ ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, /*unused*/0, /*unused*/0, /*dummy*/ir->buf_in, /*dummy*/ir->len_in, /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); if (ret < 0) printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n", devnum, ret); usb_set_intfdata(intf, ir); return 0; }
static int onetouch_connect_input(struct us_data *ss) { struct usb_device *udev = ss->pusb_dev; struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_onetouch *onetouch; struct input_dev *input_dev; int pipe, maxp; int error = -ENOMEM; interface = ss->pusb_intf->cur_altsetting; if (interface->desc.bNumEndpoints != 3) return -ENODEV; endpoint = &interface->endpoint[2].desc; if (!usb_endpoint_is_int_in(endpoint)) return -ENODEV; pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); onetouch = kzalloc(sizeof(struct usb_onetouch), GFP_KERNEL); input_dev = input_allocate_device(); if (!onetouch || !input_dev) goto fail1; onetouch->data = usb_alloc_coherent(udev, ONETOUCH_PKT_LEN, GFP_KERNEL, &onetouch->data_dma); if (!onetouch->data) goto fail1; onetouch->irq = usb_alloc_urb(0, GFP_KERNEL); if (!onetouch->irq) goto fail2; onetouch->udev = udev; onetouch->dev = input_dev; if (udev->manufacturer) strlcpy(onetouch->name, udev->manufacturer, sizeof(onetouch->name)); if (udev->product) { if (udev->manufacturer) strlcat(onetouch->name, " ", sizeof(onetouch->name)); strlcat(onetouch->name, udev->product, sizeof(onetouch->name)); } if (!strlen(onetouch->name)) snprintf(onetouch->name, sizeof(onetouch->name), "Maxtor Onetouch %04x:%04x", le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); usb_make_path(udev, onetouch->phys, sizeof(onetouch->phys)); strlcat(onetouch->phys, "/input0", sizeof(onetouch->phys)); input_dev->name = onetouch->name; input_dev->phys = onetouch->phys; usb_to_input_id(udev, &input_dev->id); input_dev->dev.parent = &udev->dev; set_bit(EV_KEY, input_dev->evbit); set_bit(ONETOUCH_BUTTON, input_dev->keybit); clear_bit(0, input_dev->keybit); input_set_drvdata(input_dev, onetouch); input_dev->open = usb_onetouch_open; input_dev->close = usb_onetouch_close; usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data, (maxp > 8 ? 8 : maxp), usb_onetouch_irq, onetouch, endpoint->bInterval); onetouch->irq->transfer_dma = onetouch->data_dma; onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; ss->extra_destructor = onetouch_release_input; ss->extra = onetouch; #ifdef CONFIG_PM ss->suspend_resume_hook = usb_onetouch_pm_hook; #endif error = input_register_device(onetouch->dev); if (error) goto fail3; return 0; fail3: usb_free_urb(onetouch->irq); fail2: usb_free_coherent(udev, ONETOUCH_PKT_LEN, onetouch->data, onetouch->data_dma); fail1: kfree(onetouch); input_free_device(input_dev); return error; }
static int dwc2_transfer(struct usb_device *dev, unsigned long pipe, int size, int pid, ep_dir_t dir, uint32_t ch_num, u8 *data_buf) { struct dwc_ctrl *ctrl = dev->controller; pUSB_OTG_REG reg = ctrl->otgReg; uint32_t do_copy; int ret; uint32_t packet_cnt; uint32_t packet_size; uint32_t transferred = 0; uint32_t inpkt_length; uint32_t eptype; HCTSIZ_DATA hctsiz = { .d32 = 0 }; HCCHAR_DATA hcchar = { .d32 = 0 }; void *aligned_buf; debug("# %s #dev %p, size %d, pid %d, dir %d, buf %p\n", __func__, dev, size, pid, dir, data_buf); if (dev->speed != USB_SPEED_HIGH) { printf("Support high-speed only\n"); return -1; } if (size > DMA_SIZE) { printf("Transfer too large: %d\n", size); return -1; } packet_size = usb_maxpacket(dev, pipe); packet_cnt = DIV_ROUND_UP(size, packet_size); inpkt_length = roundup(size, packet_size); /* At least 1 packet should be programed */ packet_cnt = (packet_cnt == 0) ? 1 : packet_cnt; /* * For an IN, this field is the buffer size that the application has * reserved for the transfer. The application should program this field * as integer multiple of the maximum packet size for IN transactions. */ hctsiz.xfersize = (dir == EPDIR_OUT) ? size : inpkt_length; hctsiz.pktcnt = packet_cnt; hctsiz.pid = pid; hcchar.mps = packet_size; hcchar.epnum = usb_pipeendpoint(pipe); hcchar.epdir = dir; switch (usb_pipetype(pipe)) { case PIPE_CONTROL: eptype = 0; break; case PIPE_BULK: eptype = 2; break; default: printf("Un-supported type\n"); return -EOPNOTSUPP; } hcchar.eptype = eptype; hcchar.multicnt = 1; hcchar.devaddr = usb_pipedevice(pipe); hcchar.chdis = 0; hcchar.chen = 1; /* * Check the buffer address which should be 4-byte aligned and DMA * coherent */ //do_copy = !dma_coherent(data_buf) || ((uintptr_t)data_buf & 0x3); do_copy = 1;//(uintptr_t)data_buf & 0x3; aligned_buf = do_copy ? ctrl->align_buf : data_buf; if (do_copy && (dir == EPDIR_OUT)) memcpy(aligned_buf, data_buf, size); if (dir == EPDIR_OUT) flush_dcache_range(aligned_buf, aligned_buf + roundup(size, ARCH_DMA_MINALIGN)); writel(hctsiz.d32, ®->Host.hchn[ch_num].hctsizn); writel((uint32_t)aligned_buf, ®->Host.hchn[ch_num].hcdman); writel(hcchar.d32, ®->Host.hchn[ch_num].hccharn); ret = dwc_wait_for_complete(dev, ch_num); if (ret >= 0) { /* Calculate actual transferred length */ transferred = (dir == EPDIR_IN) ? inpkt_length - ret : ret; if (dir == EPDIR_IN) invalidate_dcache_range(aligned_buf, aligned_buf + roundup(transferred, ARCH_DMA_MINALIGN)); if (do_copy && (dir == EPDIR_IN)) memcpy(data_buf, aligned_buf, transferred); } /* Save data toggle */ hctsiz.d32 = readl(®->Host.hchn[ch_num].hctsizn); usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), (hctsiz.pid >> 1)); if (ret < 0) { printf("%s Transfer stop code: %d\n", __func__, ret); return ret; } return transferred; } int usb_lowlevel_stop(int index) { pUSB_OTG_REG reg = (pUSB_OTG_REG)rkusb_active_hcd->regbase; HPRT0_DATA hprt0 = { .d32 = 0 }; GUSBCFG_DATA gusbcfg = { .d32 = 0 }; /* Stop connect and put everything of port state in reset. */ hprt0.prtena = 1; hprt0.prtenchng = 1; hprt0.prtconndet = 1; writel(hprt0.d32, ®->Host.hprt); gusbcfg.d32 = 0x1400; writel(gusbcfg.d32, ®->Core.gusbcfg); return 0; } static void dwc2_reinit(pUSB_OTG_REG regbase) { pUSB_OTG_REG reg = regbase; GUSBCFG_DATA gusbcfg = { .d32 = 0 }; GRSTCTL_DATA grstctl = { .d32 = 0 }; GINTSTS_DATA gintsts = { .d32 = 0 }; GAHBCFG_DATA gahbcfg = { .d32 = 0 }; RXFIFOSIZE_DATA grxfsiz = { .d32 = 0 }; HCINTMSK_DATA hcintmsk = { .d32 = 0 }; TXFIFOSIZE_DATA gnptxfsiz = { .d32 = 0 }; const int timeout = 10000; int i; /* Wait for AHB idle */ for (i = 0; i < timeout; i++) { udelay(1); grstctl.d32 = readl(®->Core.grstctl); if (grstctl.ahbidle) break; } if (i == timeout) { printf("DWC2 Init error AHB Idle\n"); return; } /* Restart the Phy Clock */ writel(0x0, ®->ClkGate.PCGCR); /* Core soft reset */ grstctl.csftrst = 1; writel(grstctl.d32, ®->Core.grstctl); for (i = 0; i < timeout; i++) { udelay(1); grstctl.d32 = readl(®->Core.grstctl); if (!grstctl.csftrst) break; } if (i == timeout) { printf("DWC2 Init error reset fail\n"); return; } /* Set 16bit PHY if & Force host mode */ gusbcfg.d32 = readl(®->Core.gusbcfg); gusbcfg.phyif = 1; gusbcfg.forcehstmode = 1; gusbcfg.forcedevmode = 0; writel(gusbcfg.d32, ®->Core.gusbcfg); /* Wait for force host mode effect, it may takes 100ms */ for (i = 0; i < timeout; i++) { udelay(10); gintsts.d32 = readl(®->Core.gintsts); if (gintsts.curmod) break; } if (i == timeout) { printf("DWC2 Init error force host mode fail\n"); return; } /* * Config FIFO * The non-periodic tx fifo and rx fifo share one continuous * piece of IP-internal SRAM. */ grxfsiz.rxfdep = DWC2_RXFIFO_DEPTH; writel(grxfsiz.d32, ®->Core.grxfsiz); gnptxfsiz.nptxfstaddr = DWC2_RXFIFO_DEPTH; gnptxfsiz.nptxfdep = DWC2_NPTXFIFO_DEPTH; writel(gnptxfsiz.d32, ®->Core.gnptxfsiz); /* Init host channels */ hcintmsk.xfercomp = 1; hcintmsk.xacterr = 1; hcintmsk.stall = 1; hcintmsk.chhltd = 1; hcintmsk.bblerr = 1; for (i = 0; i < MAX_EPS_CHANNELS; i++) writel(hcintmsk.d32, ®->Host.hchn[i].hcintmaskn); /* Unmask interrupt & Use configure dma mode */ gahbcfg.glblintrmsk = 1; gahbcfg.hbstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR8; gahbcfg.dmaen = 1; writel(gahbcfg.d32, ®->Core.gahbcfg); printf("DWC2@0x%p init finished!\n", regbase); } int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) { pUSB_OTG_REG reg = (pUSB_OTG_REG)rkusb_active_hcd->regbase; struct dwc_ctrl *dwcctl; dwcctl = malloc(sizeof(struct dwc_ctrl)); if (!dwcctl) return -ENOMEM; dwcctl->otgReg = reg; dwcctl->rootdev = 0; dwcctl->align_buf = memalign(USB_DMA_MINALIGN, DMA_SIZE); if (!dwcctl->align_buf) return -ENOMEM; dwc2_reinit(reg); *controller = dwcctl; return 0; } int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int length) { ep_dir_t data_dir; int pid; int ret = 0; if (usb_pipetype(pipe) != PIPE_BULK) { debug("non-bulk pipe (type=%lu)", usb_pipetype(pipe)); return -1; } if (usb_pipein(pipe)) data_dir = EPDIR_IN; else if (usb_pipeout(pipe)) data_dir = EPDIR_OUT; else return -1; pid = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); if (pid) pid = DWC_HCTSIZ_DATA1; else pid = DWC_HCTSIZ_DATA0; ret = dwc2_transfer(dev, pipe, length, pid, data_dir, 0, buffer); if (ret < 0) return -1; dev->act_len = ret; dev->status = 0; return 0; } int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *setup) { int ret = 0; struct dwc_ctrl *ctrl = dev->controller; ep_dir_t data_dir; if (usb_pipetype(pipe) != PIPE_CONTROL) { debug("non-control pipe (type=%lu)", usb_pipetype(pipe)); return -1; } if (usb_pipedevice(pipe) == ctrl->rootdev) { if (!ctrl->rootdev) dev->speed = USB_SPEED_HIGH; return dwc2_submit_root(dev, pipe, buffer, length, setup); } if (usb_pipein(pipe)) data_dir = EPDIR_IN; else if (usb_pipeout(pipe)) data_dir = EPDIR_OUT; else return -1; /* Setup Phase */ if (dwc2_transfer(dev, pipe, 8, PID_SETUP, EPDIR_OUT, 0, (u8 *)setup) < 0) return -1; /* Data Phase */ if (length > 0) { ret = dwc2_transfer(dev, pipe, length, PID_DATA1, data_dir, 0, buffer); if (ret < 0) return -1; } /* Status Phase */ if (dwc2_transfer(dev, pipe, 0, PID_DATA1, !data_dir, 0, NULL) < 0) return -1; dev->act_len = ret; dev->status = 0; return 0; } int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int length, int interval) { return 0; }
/* * queue up an urb for anything except the root hub */ static int admhc_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) { struct admhcd *ahcd = hcd_to_admhcd(hcd); struct ed *ed; struct urb_priv *urb_priv; unsigned int pipe = urb->pipe; int td_cnt = 0; unsigned long flags; int ret = 0; #ifdef ADMHC_VERBOSE_DEBUG spin_lock_irqsave(&ahcd->lock, flags); urb_print(ahcd, urb, "ENQEUE", usb_pipein(pipe), -EINPROGRESS); spin_unlock_irqrestore(&ahcd->lock, flags); #endif /* every endpoint has an ed, locate and maybe (re)initialize it */ ed = ed_get(ahcd, urb->ep, urb->dev, pipe, urb->interval); if (!ed) return -ENOMEM; /* for the private part of the URB we need the number of TDs */ switch (ed->type) { case PIPE_CONTROL: if (urb->transfer_buffer_length > TD_DATALEN_MAX) /* td_submit_urb() doesn't yet handle these */ return -EMSGSIZE; /* 1 TD for setup, 1 for ACK, plus ... */ td_cnt = 2; /* FALLTHROUGH */ case PIPE_BULK: /* one TD for every 4096 Bytes (can be upto 8K) */ td_cnt += urb->transfer_buffer_length / TD_DATALEN_MAX; /* ... and for any remaining bytes ... */ if ((urb->transfer_buffer_length % TD_DATALEN_MAX) != 0) td_cnt++; /* ... and maybe a zero length packet to wrap it up */ if (td_cnt == 0) td_cnt++; else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0 && (urb->transfer_buffer_length % usb_maxpacket(urb->dev, pipe, usb_pipeout (pipe))) == 0) td_cnt++; break; case PIPE_INTERRUPT: /* * for Interrupt IN/OUT transactions, each ED contains * only 1 TD. * TODO: check transfer_buffer_length? */ td_cnt = 1; break; case PIPE_ISOCHRONOUS: /* number of packets from URB */ td_cnt = urb->number_of_packets; break; } urb_priv = urb_priv_alloc(ahcd, td_cnt, mem_flags); if (!urb_priv) return -ENOMEM; urb_priv->ed = ed; spin_lock_irqsave(&ahcd->lock, flags); /* don't submit to a dead HC */ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { ret = -ENODEV; goto fail; } if (!HC_IS_RUNNING(hcd->state)) { ret = -ENODEV; goto fail; } ret = usb_hcd_link_urb_to_ep(hcd, urb); if (ret) goto fail; /* schedule the ed if needed */ if (ed->state == ED_IDLE) { ret = ed_schedule(ahcd, ed); if (ret < 0) { usb_hcd_unlink_urb_from_ep(hcd, urb); goto fail; } if (ed->type == PIPE_ISOCHRONOUS) { u16 frame = admhc_frame_no(ahcd); /* delay a few frames before the first TD */ frame += max_t (u16, 8, ed->interval); frame &= ~(ed->interval - 1); frame |= ed->branch; urb->start_frame = frame; /* yes, only URB_ISO_ASAP is supported, and * urb->start_frame is never used as input. */ } } else if (ed->type == PIPE_ISOCHRONOUS) urb->start_frame = ed->last_iso + ed->interval; /* fill the TDs and link them to the ed; and * enable that part of the schedule, if needed * and update count of queued periodic urbs */ urb->hcpriv = urb_priv; td_submit_urb(ahcd, urb); #ifdef ADMHC_VERBOSE_DEBUG admhc_dump_ed(ahcd, "admhc_urb_enqueue", urb_priv->ed, 1); #endif fail: if (ret) urb_priv_free(ahcd, urb_priv); spin_unlock_irqrestore(&ahcd->lock, flags); return ret; }
static int usb_hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint) { struct usb_device *dev = hub->dev; struct usb_hub_status hubstatus; char portstr[USB_MAXCHILDREN + 1]; unsigned int pipe; int i, maxp, ret; hub->descriptor = kmalloc(HUB_DESCRIPTOR_MAX_SIZE, GFP_KERNEL); if (!hub->descriptor) { err("Unable to kmalloc %d bytes for hub descriptor", HUB_DESCRIPTOR_MAX_SIZE); return -1; } /* Request the entire hub descriptor. */ ret = usb_get_hub_descriptor(dev, hub->descriptor, HUB_DESCRIPTOR_MAX_SIZE); /* <hub->descriptor> is large enough for a hub with 127 ports; * the hub can/will return fewer bytes here. */ if (ret < 0) { err("Unable to get hub descriptor (err = %d)", ret); kfree(hub->descriptor); return -1; } hub->nports = dev->maxchild = hub->descriptor->bNbrPorts; info("%d port%s detected", hub->nports, (hub->nports == 1) ? "" : "s"); if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND) dbg("part of a compound device"); else dbg("standalone hub"); switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) { case 0x00: dbg("ganged power switching"); break; case 0x01: dbg("individual port power switching"); break; case 0x02: case 0x03: dbg("unknown reserved power switching mode"); break; } switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) { case 0x00: dbg("global over-current protection"); break; case 0x08: dbg("individual port over-current protection"); break; case 0x10: case 0x18: dbg("no over-current protection"); break; } dbg("power on to power good time: %dms", hub->descriptor->bPwrOn2PwrGood * 2); dbg("hub controller current requirement: %dmA", hub->descriptor->bHubContrCurrent); for (i = 0; i < dev->maxchild; i++) portstr[i] = hub->descriptor->bitmap[((i + 1) / 8)] & (1 << ((i + 1) % 8)) ? 'F' : 'R'; portstr[dev->maxchild] = 0; dbg("port removable status: %s", portstr); ret = usb_get_hub_status(dev, &hubstatus); if (ret < 0) { err("Unable to get hub status (err = %d)", ret); kfree(hub->descriptor); return -1; } le16_to_cpus(&hubstatus.wHubStatus); dbg("local power source is %s", (hubstatus.wHubStatus & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good"); dbg("%sover-current condition exists", (hubstatus.wHubStatus & HUB_STATUS_OVERCURRENT) ? "" : "no "); /* Start the interrupt endpoint */ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); if (maxp > sizeof(hub->buffer)) maxp = sizeof(hub->buffer); hub->urb = usb_alloc_urb(0); if (!hub->urb) { err("couldn't allocate interrupt urb"); kfree(hub->descriptor); return -1; } FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq, hub, endpoint->bInterval); ret = usb_submit_urb(hub->urb); if (ret) { err("usb_submit_urb failed (%d)", ret); kfree(hub->descriptor); return -1; } /* Wake up khubd */ wake_up(&khubd_wait); usb_hub_power_on(hub); return 0; }
static int usb_hub_configure(USB_HUB_T *hub, EP_INFO_T *ep_info) { USB_DEV_T *dev = hub->dev; USB_HUB_STATUS_T hubstatus; uint32_t pipe; int maxp, ret; USB_info("[HUB] Enter usb_hub_configure()... hub:%d\n", hub->dev->devnum); /* Request the entire hub descriptor. */ ret = usb_get_hub_descriptor(dev, &hub->descriptor, sizeof(USB_HUB_DESC_T)); /* <hub->descriptor> is large enough for a hub with 127 ports; * the hub can/will return fewer bytes here. */ if(ret < 0) { USB_error("Erro - Unable to get hub descriptor (err = %d)\n", ret); return ret; } dev->maxchild = hub->descriptor.bNbrPorts; #ifdef USB_VERBOSE_DEBUG USB_info("%d port%s detected\n", hub->descriptor.bNbrPorts, (hub->descriptor.bNbrPorts == 1) ? "" : "s"); /* D2: Identifying a Compound Device */ if(hub->descriptor.wHubCharacteristics & HUB_CHAR_COMPOUND) { USB_info("part of a compound device\n"); } else { USB_info("standalone hub\n"); } /* D1..D0: Logical Power Switching Mode */ switch(hub->descriptor.wHubCharacteristics & HUB_CHAR_LPSM) { case 0x00: USB_info("ganged power switching\n"); break; case 0x01: USB_info("individual port power switching\n"); break; case 0x02: case 0x03: USB_info("unknown reserved power switching mode\n"); break; } /* D4..D3: Over-current Protection Mode */ switch(hub->descriptor.wHubCharacteristics & HUB_CHAR_OCPM) { case 0x00: USB_info("global over-current protection\n"); break; case 0x08: USB_info("individual port over-current protection\n"); break; case 0x10: case 0x18: USB_info("no over-current protection\n"); break; } switch(dev->descriptor.bDeviceProtocol) { case 0: break; case 1: USB_debug("Single TT, "); break; case 2: USB_debug("TT per port, "); break; default: USB_debug("Unrecognized hub protocol %d", dev->descriptor.bDeviceProtocol); break; } USB_info("power on to power good time: %dms\n", hub->descriptor.bPwrOn2PwrGood * 2); USB_info("hub controller current requirement: %dmA\n", hub->descriptor.bHubContrCurrent); #endif ret = usb_get_hub_status(dev, &hubstatus); if(ret < 0) { USB_error("Unable to get hub %d status (err = %d)\n", hub->dev->devnum, ret); return ret; } hubstatus.wHubStatus = USB_SWAP16(hubstatus.wHubStatus); #ifdef USB_VERBOSE_DEBUG /* Hub status bit 0, Local Power Source */ if(hubstatus.wHubStatus & HUB_STATUS_LOCAL_POWER) { USB_info("local power source is lost (inactive)\n"); } else { USB_info("local power source is good\n"); } /* Hub status bit 1, Over-current Indicator */ if(hubstatus.wHubStatus & HUB_STATUS_OVERCURRENT) { USB_info("!! over-current\n"); } else { USB_info("No over-current.\n"); } #endif /* Start the interrupt endpoint */ pipe = usb_rcvintpipe(dev, ep_info->bEndpointAddress); maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); if(maxp > sizeof(hub->buffer)) maxp = sizeof(hub->buffer); hub->urb = USBH_AllocUrb(); if(!hub->urb) { USB_error("Error - couldn't allocate interrupt urb"); return USB_ERR_NOMEM; } #if 1 /* YCHuang 2012.06.01 */ if(ep_info->bInterval < 16) ep_info->bInterval = 16; #endif FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq, hub, ep_info->bInterval); ret = USBH_SubmitUrb(hub->urb); if(ret) { USB_error("Error - USBH_SubmitUrb failed (%d)", ret); USBH_FreeUrb(hub->urb); return ret; } if(g_ohci_bus.root_hub != hub->dev) usb_hub_power_on(hub); return 0; }
static void * hci_usb_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id) { struct usb_endpoint_descriptor *bulk_out_ep, *intr_in_ep, *bulk_in_ep; struct usb_interface_descriptor *uif; struct usb_endpoint_descriptor *ep; struct hci_usb *husb; struct hci_dev *hdev; int i, size, pipe; __u8 * buf; DBG("udev %p ifnum %d", udev, ifnum); /* Check device signature */ if ((udev->descriptor.bDeviceClass != HCI_DEV_CLASS) || (udev->descriptor.bDeviceSubClass != HCI_DEV_SUBCLASS)|| (udev->descriptor.bDeviceProtocol != HCI_DEV_PROTOCOL) ) return NULL; MOD_INC_USE_COUNT; uif = &udev->actconfig->interface[ifnum].altsetting[0]; if (uif->bNumEndpoints != 3) { DBG("Wrong number of endpoints %d", uif->bNumEndpoints); MOD_DEC_USE_COUNT; return NULL; } bulk_out_ep = intr_in_ep = bulk_in_ep = NULL; /* Find endpoints that we need */ for ( i = 0; i < uif->bNumEndpoints; ++i) { ep = &uif->endpoint[i]; switch (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { case USB_ENDPOINT_XFER_BULK: if (ep->bEndpointAddress & USB_DIR_IN) bulk_in_ep = ep; else bulk_out_ep = ep; break; case USB_ENDPOINT_XFER_INT: intr_in_ep = ep; break; }; } if (!bulk_in_ep || !bulk_out_ep || !intr_in_ep) { DBG("Endpoints not found: %p %p %p", bulk_in_ep, bulk_out_ep, intr_in_ep); MOD_DEC_USE_COUNT; return NULL; } if (!(husb = kmalloc(sizeof(struct hci_usb), GFP_KERNEL))) { ERR("Can't allocate: control structure"); MOD_DEC_USE_COUNT; return NULL; } memset(husb, 0, sizeof(struct hci_usb)); husb->udev = udev; husb->bulk_out_ep_addr = bulk_out_ep->bEndpointAddress; if (!(husb->ctrl_urb = usb_alloc_urb(0))) { ERR("Can't allocate: control URB"); goto probe_error; } if (!(husb->write_urb = usb_alloc_urb(0))) { ERR("Can't allocate: write URB"); goto probe_error; } if (!(husb->read_urb = usb_alloc_urb(0))) { ERR("Can't allocate: read URB"); goto probe_error; } ep = bulk_in_ep; pipe = usb_rcvbulkpipe(udev, ep->bEndpointAddress); size = HCI_MAX_FRAME_SIZE; if (!(buf = kmalloc(size, GFP_KERNEL))) { ERR("Can't allocate: read buffer"); goto probe_error; } FILL_BULK_URB(husb->read_urb, udev, pipe, buf, size, hci_usb_bulk_read, husb); husb->read_urb->transfer_flags |= USB_QUEUE_BULK; ep = intr_in_ep; pipe = usb_rcvintpipe(udev, ep->bEndpointAddress); size = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); if (!(husb->intr_urb = usb_alloc_urb(0))) { ERR("Can't allocate: interrupt URB"); goto probe_error; } if (!(buf = kmalloc(size, GFP_KERNEL))) { ERR("Can't allocate: interrupt buffer"); goto probe_error; } FILL_INT_URB(husb->intr_urb, udev, pipe, buf, size, hci_usb_intr, husb, ep->bInterval); skb_queue_head_init(&husb->tx_ctrl_q); skb_queue_head_init(&husb->tx_write_q); /* Initialize and register HCI device */ hdev = &husb->hdev; hdev->type = HCI_USB; hdev->driver_data = husb; hdev->open = hci_usb_open; hdev->close = hci_usb_close; hdev->flush = hci_usb_flush; hdev->send = hci_usb_send_frame; if (hci_register_dev(hdev) < 0) { ERR("Can't register HCI device %s", hdev->name); goto probe_error; } return husb; probe_error: hci_usb_free_bufs(husb); kfree(husb); MOD_DEC_USE_COUNT; return NULL; }
static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id) //@: vf_usb_operation_probe_t /*@ requires usb_interface(usb_mouse_probe, ?disconnect_cb, intf, _, ?originalData, false, ?fracsize) &*& permission_to_submit_urb(?urbs_submitted, false) &*& not_in_interrupt_context(currentThread) &*& [fracsize]probe_disconnect_userdata(usb_mouse_probe, disconnect_cb)() &*& [?callback_link_f]usb_probe_callback_link(usb_mouse_probe)(disconnect_cb); @*/ /*@ ensures not_in_interrupt_context(currentThread) &*& [callback_link_f]usb_probe_callback_link(usb_mouse_probe)(disconnect_cb) &*& result == 0 ? // success // probe_disconnect_userdata is not returned, so the user "has to put it somewhere", // and give it back with _disconnect. // you can put it in usb_interface: it includes userdata which // can eat whatever probe_disconnect_userdata contains. usb_interface(usb_mouse_probe, disconnect_cb, intf, _, ?data, true, fracsize) //&*& permission_to_submit_urb(_, false) : // failure usb_interface(usb_mouse_probe, disconnect_cb, intf, _, ?data, false, fracsize) // XXX meh, the permission count thing is annoying and I don't think it actually // solves much at all, so made it "_" for now. &*& permission_to_submit_urb(_, false) &*& data == originalData || data == 0 &*& [fracsize]probe_disconnect_userdata(usb_mouse_probe, _)() ; @*/ { struct usb_host_endpoint* ep; //@ open [callback_link_f]usb_probe_callback_link(usb_mouse_probe)(disconnect_cb); //@ close [callback_link_f]usb_probe_callback_link(usb_mouse_probe)(disconnect_cb); struct usb_device *dev = interface_to_usbdev(intf); struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_mouse *mouse; struct input_dev *input_dev; int pipe, maxp; int error = -ENOMEM; //@ open usb_interface(usb_mouse_probe, _, _, _, _, _, _); interface = intf->cur_altsetting; //@ open [?f2]usb_host_interface(interface); //@ open [?f3]usb_interface_descriptor(&interface->desc, ?bNumEndpoints, ?bInterfaceNumber); if (interface->desc.bNumEndpoints != 1) { //@ close [f3]usb_interface_descriptor(&interface->desc, bNumEndpoints, bInterfaceNumber); //@ close [f2]usb_host_interface(interface); //@ close usb_interface(usb_mouse_probe, disconnect_cb, intf, _, originalData, false, fracsize); return -ENODEV; } ep = interface->endpoint; endpoint = &(ep->desc); //@ open usb_host_endpoint(interface->endpoint); //int usb_endpoint_is_int_in_res = ; if (! usb_endpoint_is_int_in(endpoint)) { //@ close usb_host_endpoint(interface->endpoint); //@ close [f3]usb_interface_descriptor(&interface->desc, bNumEndpoints, bInterfaceNumber); //@ close [f2]usb_host_interface(interface); //@ close usb_interface(usb_mouse_probe, disconnect_cb, intf, _, originalData, false, fracsize); return -ENODEV; } pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); // original: maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); __u16 usb_maxpacket_ret = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); maxp = usb_maxpacket_ret; mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL); input_dev = input_allocate_device(); if (! mouse || ! input_dev) goto fail1; //@ uchars_to_chars(mouse); //@ close_struct(mouse); //@ assert chars((void*) &mouse->name, 128, ?zeros); //@ assume(mem(0, zeros)); // follows because kzalloc is used //@ assert chars((void*) &mouse->phys, 64, ?zeros2); //@ assume(mem(0, zeros2)); // follows because kzalloc is used mouse->usbdev = 0; mouse->dev = 0; mouse->irq = 0; mouse->data = 0; mouse->data_dma = 0; mouse->data = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &mouse->data_dma); //@ signed char* data_tmp = mouse->data; if (! mouse->data) { //@ open_struct(mouse); //@ chars_to_uchars(mouse); goto fail1; } mouse->irq = usb_alloc_urb(0, GFP_KERNEL); if (! mouse->irq) goto fail2; mouse->usbdev = dev; mouse->dev = input_dev; if (dev->manufacturer) strlcpy(mouse->name, dev->manufacturer, 128/*sizeof(mouse->name)*/); if (dev->product) { if (dev->manufacturer) { strlcat(mouse->name, " ", 128/*sizeof(mouse->name)*/); } strlcat(mouse->name, dev->product, 128/*sizeof(mouse->name)*/); } if (strlen(mouse->name)) ; //TODO //snprintf(mouse->name, 128 /*sizeof(mouse->name)*/, // "USB HIDBP Mouse %04x:%04x", // le16_to_cpu(dev->descriptor.idVendor), // le16_to_cpu(dev->descriptor.idProduct)); usb_make_path(dev, mouse->phys, 64/*sizeof(mouse->phys)*/); strlcat(mouse->phys, "/input0", 64/*sizeof(mouse->phys)*/); //@ open input_dev_unregistered(input_dev, _, _, _, _, _, _); input_dev->name = mouse->name; input_dev->phys = mouse->phys; //@ close usb_device(dev, _); usb_to_input_id(dev, &input_dev->id); //@ open usb_device(dev, _); //TODO: input_dev->dev.parent = &intf->dev; //TODO: /*input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);*/ //@ close input_dev_unregistered(input_dev, _, _, _, _, _, _); input_set_drvdata(input_dev, mouse); //@ open input_dev_unregistered(input_dev, _, _, _, _, _, _); input_dev->open = usb_mouse_open; input_dev->close = usb_mouse_close; input_dev->event = usb_mouse_event_dummy; // not original code, HACK //@ close usb_device(dev, _); //@ close complete_t_ghost_param(usb_mouse_irq, usb_mouse_irq); usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data, (maxp > 8 ? 8 : maxp), usb_mouse_irq, mouse, endpoint->bInterval); mouse->irq->transfer_dma = mouse->data_dma; mouse->irq->transfer_flags = mouse->irq->transfer_flags | URB_NO_TRANSFER_DMA_MAP; /*@ urb_transfer_flags_add_no_transfer_dma_map( mouse->irq, data_tmp, mouse->data_dma, 8, mouse->irq->transfer_flags); @*/ //@ assert mouse->irq |-> ?irq; //@ close urb_struct(true, irq, _, data_tmp, mouse->data_dma, 8, true, usb_mouse_irq, mouse, 0); //@ close input_open_t_ghost_param(usb_mouse_open, usb_mouse_open); //@ close input_close_t_ghost_param(usb_mouse_close, usb_mouse_close); //@ assume(is_input_event_t_no_pointer(usb_mouse_event_dummy) == true); // HACK HACK HACK, there are no events for this driver //@ close input_event_t_ghost_param(usb_mouse_event_dummy, usb_mouse_event_dummy); //@ close input_dev_unregistered(input_dev, _, _, _, _, _, _); //@ input_ghost_register_device(input_dev, fracsize); //@ close input_open_callback_link(usb_mouse_open)(usb_mouse_close, usb_mouse_event_dummy); //@ close input_close_callback_link(usb_mouse_close)(usb_mouse_open, usb_mouse_event_dummy); //@ close input_event_callback_link(usb_mouse_event_dummy)(usb_mouse_open, usb_mouse_close); //@ assert input_dev_ghost_registered(_, _, _, _, _, _, _, _, ?input_register_result); /*@ if (input_register_result == 0){ close userdef_input_drvdata(usb_mouse_open, usb_mouse_close, usb_mouse_event_dummy)(input_dev, false, mouse, fracsize); } @*/ //@ assume( true && (void*) 0 != ((void*) mouse->phys)); //@ assert chars(mouse->phys, 64, ?phys_text); //@ close maybe_chars(1, mouse->phys, 64, phys_text); error = input_register_device(mouse->dev); if (error != 0) { //@ open maybe_chars(1, _, _, _); //@ open input_open_callback_link(usb_mouse_open)(usb_mouse_close, usb_mouse_event_dummy); //@ open input_close_callback_link(usb_mouse_close)(usb_mouse_open, usb_mouse_event_dummy); //@ open input_event_callback_link(usb_mouse_event_dummy)(usb_mouse_open, usb_mouse_close); //@ open input_open_t_ghost_param(usb_mouse_open, usb_mouse_open); //@ open input_close_t_ghost_param(usb_mouse_close, usb_mouse_close); //@ open input_event_t_ghost_param(usb_mouse_event_dummy, usb_mouse_event_dummy); goto fail3; } //@ close usb_interface_descriptor(&interface->desc, 1, _); //@ close usb_host_endpoint(interface->endpoint); //@ close [f2]usb_host_interface(interface); //@ close usb_interface(usb_mouse_probe, usb_mouse_disconnect, intf, dev, originalData, false, fracsize); //@ close userdef_usb_interface_data(usb_mouse_probe, usb_mouse_disconnect)(intf, dev, mouse, fracsize); usb_set_intfdata(intf, mouse); return 0; fail3: //@ close urb_struct_maybe(true, irq, _, _, _, _, _, _, _, _); usb_free_urb(mouse->irq); fail2: usb_free_coherent(dev, 8, mouse->data, mouse->data_dma); //@ open_struct(mouse); //@ chars_to_uchars(mouse); fail1: input_free_device(input_dev); kfree(mouse); //@ close [f3]usb_interface_descriptor(&interface->desc, bNumEndpoints, bInterfaceNumber); //@ close usb_host_endpoint(interface->endpoint); //@ close [f2]usb_host_interface(interface); //@ close usb_interface(usb_mouse_probe, disconnect_cb, intf, _, originalData, false, fracsize); return error; }
static int sl811_send_packet(struct usb_device *dev, unsigned long pipe, __u8 *buffer, int len) { __u8 ctrl = SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE; __u16 status = 0; int err = 0, time_start = get_timer(0); int need_preamble = !(rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) && (dev->speed == USB_SPEED_LOW); if (len > 239) return -1; if (usb_pipeout(pipe)) ctrl |= SL811_USB_CTRL_DIR_OUT; if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) ctrl |= SL811_USB_CTRL_TOGGLE_1; if (need_preamble) ctrl |= SL811_USB_CTRL_PREAMBLE; sl811_write(SL811_INTRSTS, 0xff); while (err < 3) { sl811_write(SL811_ADDR_A, 0x10); sl811_write(SL811_LEN_A, len); if (usb_pipeout(pipe) && len) sl811_write_buf(0x10, buffer, len); if (!(rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) && sl811_read(SL811_SOFCNTDIV)*64 < calc_needed_buswidth(len, need_preamble)) ctrl |= SL811_USB_CTRL_SOF; else ctrl &= ~SL811_USB_CTRL_SOF; sl811_write(SL811_CTRL_A, ctrl); while (!(sl811_read(SL811_INTRSTS) & SL811_INTR_DONE_A)) { if (5*CONFIG_SYS_HZ < get_timer(time_start)) { printf("USB transmit timed out\n"); return -USB_ST_CRC_ERR; } } sl811_write(SL811_INTRSTS, 0xff); status = sl811_read(SL811_STS_A); if (status & SL811_USB_STS_ACK) { int remainder = sl811_read(SL811_CNT_A); if (remainder) { PDEBUG(0, "usb transfer remainder = %d\n", remainder); len -= remainder; } if (usb_pipein(pipe) && len) sl811_read_buf(0x10, buffer, len); return len; } if ((status & SL811_USB_STS_NAK) == SL811_USB_STS_NAK) continue; PDEBUG(0, "usb transfer error %#x\n", (int)status); err++; } err = 0; if (status & SL811_USB_STS_ERROR) err |= USB_ST_BUF_ERR; if (status & SL811_USB_STS_TIMEOUT) err |= USB_ST_CRC_ERR; if (status & SL811_USB_STS_STALL) err |= USB_ST_STALLED; return -err; }
static int usb_lmpcm_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; lmpcm_t *mouse; int pipe, maxp; char *buf; // Get mouse endpoint interface = intf->cur_altsetting; if ( interface->desc.bNumEndpoints != 1 ) return -ENODEV; endpoint = &interface->endpoint[0].desc; // Check endpoint if (!(endpoint->bEndpointAddress & USB_DIR_IN)) return -ENODEV; if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) return -ENODEV; // Create endpoint pipe pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); // Create lmpcm object if (!(mouse = lmpcm_new(dev))) return -ENOMEM; // Initialize input device input_device_init(mouse->inputdev,intf,dev); // Set device name if (!(buf = kmalloc(63, GFP_KERNEL))) { lmpcm_free(mouse); return -ENOMEM; } if (dev->descriptor.iManufacturer && usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0) strcat(mouse->name, buf); if (dev->descriptor.iProduct && usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0) sprintf(mouse->name, "%s %s", mouse->name, buf); if (!strlen(mouse->name)) sprintf(mouse->name, "lmpcm_usb.c: Logitech MediaPlay Mouse on usb%04x:%04x", mouse->inputdev->id.vendor, mouse->inputdev->id.product); kfree(buf); // Initialize interrupt transfer usb_fill_int_urb(mouse->urb,dev,pipe,mouse->data,((maxp > 8)?8:maxp),usb_lmpcm_handle,mouse,endpoint->bInterval); mouse->urb->transfer_dma = mouse->data_dma; mouse->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; // Register input device input_register_device(mouse->inputdev); printk(KERN_INFO "lmpcm_usb.c: Detected device: %s\n", mouse->name); // Set usb handler interface data usb_set_intfdata(intf,mouse); return 0; }
int tm6000_ir_init(struct tm6000_core *dev) { struct tm6000_IR *ir; struct ir_input_dev *ir_input_dev; int err = -ENOMEM; int pipe, size, rc; if (!enable_ir) return -ENODEV; if (!dev->caps.has_remote) return 0; if (!dev->ir_codes) return 0; ir = kzalloc(sizeof(*ir), GFP_KERNEL); ir_input_dev = kzalloc(sizeof(*ir_input_dev), GFP_KERNEL); ir_input_dev->input_dev = input_allocate_device(); if (!ir || !ir_input_dev || !ir_input_dev->input_dev) goto err_out_free; /* record handles to ourself */ ir->dev = dev; dev->ir = ir; ir->input = ir_input_dev; /* input einrichten */ ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; ir->props.priv = ir; ir->props.change_protocol = tm6000_ir_change_protocol; ir->props.open = tm6000_ir_start; ir->props.close = tm6000_ir_stop; ir->props.driver_type = RC_DRIVER_SCANCODE; ir->polling = 50; snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)", dev->name); usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); strlcat(ir->phys, "/input0", sizeof(ir->phys)); tm6000_ir_change_protocol(ir, IR_TYPE_UNKNOWN); err = ir_input_init(ir_input_dev->input_dev, &ir->ir, IR_TYPE_OTHER); if (err < 0) goto err_out_free; ir_input_dev->input_dev->name = ir->name; ir_input_dev->input_dev->phys = ir->phys; ir_input_dev->input_dev->id.bustype = BUS_USB; ir_input_dev->input_dev->id.version = 1; ir_input_dev->input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); ir_input_dev->input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); ir_input_dev->input_dev->dev.parent = &dev->udev->dev; if (&dev->int_in) { dprintk("IR over int\n"); ir->int_urb = usb_alloc_urb(0, GFP_KERNEL); pipe = usb_rcvintpipe(dev->udev, dev->int_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); dprintk("IR max size: %d\n", size); ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); if (ir->int_urb->transfer_buffer == NULL) { usb_free_urb(ir->int_urb); goto err_out_stop; } dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval); usb_fill_int_urb(ir->int_urb, dev->udev, pipe, ir->int_urb->transfer_buffer, size, tm6000_ir_urb_received, dev, dev->int_in.endp->desc.bInterval); rc = usb_submit_urb(ir->int_urb, GFP_KERNEL); if (rc) { kfree(ir->int_urb->transfer_buffer); usb_free_urb(ir->int_urb); err = rc; goto err_out_stop; } ir->urb_data = kzalloc(size, GFP_KERNEL); } /* ir register */ err = ir_input_register(ir->input->input_dev, dev->ir_codes, &ir->props, "tm6000"); if (err) goto err_out_stop; return 0; err_out_stop: dev->ir = NULL; err_out_free: kfree(ir_input_dev); kfree(ir); return err; }
static int ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) { struct QH *qh; struct qTD *td; volatile struct qTD *vtd; unsigned long ts; uint32_t *tdp; uint32_t endpt, token, usbsts; uint32_t c, toggle; uint32_t cmd; int timeout; int ret = 0; debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, buffer, length, req); if (req != NULL) debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n", req->request, req->request, req->requesttype, req->requesttype, le16_to_cpu(req->value), le16_to_cpu(req->value), le16_to_cpu(req->index)); qh = ehci_alloc(sizeof(struct QH), 32); if (qh == NULL) { debug("unable to allocate QH\n"); return -1; } qh->qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH); c = (usb_pipespeed(pipe) != USB_SPEED_HIGH && usb_pipeendpoint(pipe) == 0) ? 1 : 0; endpt = (8 << 28) | (c << 27) | (usb_maxpacket(dev, pipe) << 16) | (0 << 15) | (1 << 14) | (usb_pipespeed(pipe) << 12) | (usb_pipeendpoint(pipe) << 8) | (0 << 7) | (usb_pipedevice(pipe) << 0); qh->qh_endpt1 = cpu_to_hc32(endpt); endpt = (1 << 30) | (dev->portnr << 23) | (dev->parent->devnum << 16) | (0 << 8) | (0 << 0); qh->qh_endpt2 = cpu_to_hc32(endpt); qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); td = NULL; tdp = &qh->qh_overlay.qt_next; toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); if (req != NULL) { td = ehci_alloc(sizeof(struct qTD), 32); if (td == NULL) { debug("unable to allocate SETUP td\n"); goto fail; } td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = (0 << 31) | (sizeof(*req) << 16) | (0 << 15) | (0 << 12) | (3 << 10) | (2 << 8) | (0x80 << 0); td->qt_token = cpu_to_hc32(token); if (ehci_td_buffer(td, req, sizeof(*req)) != 0) { debug("unable construct SETUP td\n"); ehci_free(td, sizeof(*td)); goto fail; } *tdp = cpu_to_hc32((uint32_t) td); tdp = &td->qt_next; toggle = 1; } if (length > 0 || req == NULL) { td = ehci_alloc(sizeof(struct qTD), 32); if (td == NULL) { debug("unable to allocate DATA td\n"); goto fail; } td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = (toggle << 31) | (length << 16) | ((req == NULL ? 1 : 0) << 15) | (0 << 12) | (3 << 10) | ((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0); td->qt_token = cpu_to_hc32(token); if (ehci_td_buffer(td, buffer, length) != 0) { debug("unable construct DATA td\n"); ehci_free(td, sizeof(*td)); goto fail; } *tdp = cpu_to_hc32((uint32_t) td); tdp = &td->qt_next; } if (req != NULL) { td = ehci_alloc(sizeof(struct qTD), 32); if (td == NULL) { debug("unable to allocate ACK td\n"); goto fail; } td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = (toggle << 31) | (0 << 16) | (1 << 15) | (0 << 12) | (3 << 10) | ((usb_pipein(pipe) ? 0 : 1) << 8) | (0x80 << 0); td->qt_token = cpu_to_hc32(token); *tdp = cpu_to_hc32((uint32_t) td); tdp = &td->qt_next; } qh_list.qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH); /* Flush dcache */ ehci_flush_dcache(&qh_list); usbsts = ehci_readl(&hcor->or_usbsts); ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f)); /* Enable async. schedule. */ cmd = ehci_readl(&hcor->or_usbcmd); cmd |= CMD_ASE; ehci_writel(&hcor->or_usbcmd, cmd); ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, STD_ASS, 100 * 1000); if (ret < 0) { printf("EHCI fail timeout STD_ASS set\n"); goto fail; } /* Wait for TDs to be processed. */ ts = get_timer(0); vtd = td; timeout = USB_TIMEOUT_MS(pipe); do { /* Invalidate dcache */ ehci_invalidate_dcache(&qh_list); token = hc32_to_cpu(vtd->qt_token); if (!(token & 0x80)) break; WATCHDOG_RESET(); } while (get_timer(ts) < timeout); /* Check that the TD processing happened */ if (token & 0x80) { printf("EHCI timed out on TD - token=%#x\n", token); } /* Disable async schedule. */ cmd = ehci_readl(&hcor->or_usbcmd); cmd &= ~CMD_ASE; ehci_writel(&hcor->or_usbcmd, cmd); ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, 0, 100 * 1000); if (ret < 0) { printf("EHCI fail timeout STD_ASS reset\n"); goto fail; } qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH); token = hc32_to_cpu(qh->qh_overlay.qt_token); if (!(token & 0x80)) { debug("TOKEN=%#x\n", token); switch (token & 0xfc) { case 0: toggle = token >> 31; usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), toggle); dev->status = 0; break; case 0x40: dev->status = USB_ST_STALLED; break; case 0xa0: case 0x20: dev->status = USB_ST_BUF_ERR; break; case 0x50: case 0x10: dev->status = USB_ST_BABBLE_DET; break; default: dev->status = USB_ST_CRC_ERR; if ((token & 0x40) == 0x40) dev->status |= USB_ST_STALLED; break; } dev->act_len = length - ((token >> 16) & 0x7fff); } else {
/* * This routine is called by the USB subsystem for each new device * in the system. We need to check if the device is ours, and in * this case start handling it. */ static int kingsun_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_device *dev = interface_to_usbdev(intf); struct kingsun_cb *kingsun = NULL; struct net_device *net = NULL; int ret = -ENOMEM; int pipe, maxp_in, maxp_out; __u8 ep_in; __u8 ep_out; /* Check that there really are two interrupt endpoints. Check based on the one in drivers/usb/input/usbmouse.c */ interface = intf->cur_altsetting; if (interface->desc.bNumEndpoints != 2) { err("kingsun-sir: expected 2 endpoints, found %d", interface->desc.bNumEndpoints); return -ENODEV; } endpoint = &interface->endpoint[KINGSUN_EP_IN].desc; if (!usb_endpoint_is_int_in(endpoint)) { err("kingsun-sir: endpoint 0 is not interrupt IN"); return -ENODEV; } ep_in = endpoint->bEndpointAddress; pipe = usb_rcvintpipe(dev, ep_in); maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); if (maxp_in > 255 || maxp_in <= 1) { err("%s: endpoint 0 has max packet size %d not in range", __FILE__, maxp_in); return -ENODEV; } endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc; if (!usb_endpoint_is_int_out(endpoint)) { err("kingsun-sir: endpoint 1 is not interrupt OUT"); return -ENODEV; } ep_out = endpoint->bEndpointAddress; pipe = usb_sndintpipe(dev, ep_out); maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); /* Allocate network device container. */ net = alloc_irdadev(sizeof(*kingsun)); if(!net) goto err_out1; SET_NETDEV_DEV(net, &intf->dev); kingsun = netdev_priv(net); kingsun->irlap = NULL; kingsun->tx_urb = NULL; kingsun->rx_urb = NULL; kingsun->ep_in = ep_in; kingsun->ep_out = ep_out; kingsun->in_buf = NULL; kingsun->out_buf = NULL; kingsun->max_rx = (__u8)maxp_in; kingsun->max_tx = (__u8)maxp_out; kingsun->netdev = net; kingsun->usbdev = dev; kingsun->rx_buff.in_frame = FALSE; kingsun->rx_buff.state = OUTSIDE_FRAME; kingsun->rx_buff.skb = NULL; kingsun->receiving = 0; spin_lock_init(&kingsun->lock); /* Allocate input buffer */ kingsun->in_buf = kmalloc(kingsun->max_rx, GFP_KERNEL); if (!kingsun->in_buf) goto free_mem; /* Allocate output buffer */ kingsun->out_buf = kmalloc(KINGSUN_FIFO_SIZE, GFP_KERNEL); if (!kingsun->out_buf) goto free_mem; printk(KERN_INFO "KingSun/DonShine IRDA/USB found at address %d, " "Vendor: %x, Product: %x\n", dev->devnum, le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); /* Initialize QoS for this device */ irda_init_max_qos_capabilies(&kingsun->qos); /* That's the Rx capability. */ kingsun->qos.baud_rate.bits &= IR_9600; kingsun->qos.min_turn_time.bits &= KINGSUN_MTT; irda_qos_bits_to_value(&kingsun->qos); /* Override the network functions we need to use */ net->hard_start_xmit = kingsun_hard_xmit; net->open = kingsun_net_open; net->stop = kingsun_net_close; net->get_stats = kingsun_net_get_stats; net->do_ioctl = kingsun_net_ioctl; ret = register_netdev(net); if (ret != 0) goto free_mem; dev_info(&net->dev, "IrDA: Registered KingSun/DonShine device %s\n", net->name); usb_set_intfdata(intf, kingsun); /* Situation at this point: - all work buffers allocated - urbs not allocated, set to NULL - max rx packet known (in max_rx) - unwrap state machine (partially) initialized, but skb == NULL */ return 0; free_mem: if (kingsun->out_buf) kfree(kingsun->out_buf); if (kingsun->in_buf) kfree(kingsun->in_buf); free_netdev(net); err_out1: return ret; }
static int ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) { static struct QH qh __attribute__((aligned(32))); static struct qTD qtd[3] __attribute__((aligned (32))); int qtd_counter = 0; volatile struct qTD *vtd; unsigned long ts; uint32_t *tdp; uint32_t endpt, token, usbsts; uint32_t c, toggle; uint32_t cmd; int timeout; int ret = 0; debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, buffer, length, req); if (req != NULL) debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n", req->request, req->request, req->requesttype, req->requesttype, le16_to_cpu(req->value), le16_to_cpu(req->value), le16_to_cpu(req->index)); memset(&qh, 0, sizeof(struct QH)); memset(qtd, 0, sizeof(qtd)); toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); /* * Setup QH (3.6 in ehci-r10.pdf) * * qh_link ................. 03-00 H * qh_endpt1 ............... 07-04 H * qh_endpt2 ............... 0B-08 H * - qh_curtd * qh_overlay.qt_next ...... 13-10 H * - qh_overlay.qt_altnext */ qh.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH); c = (usb_pipespeed(pipe) != USB_SPEED_HIGH && usb_pipeendpoint(pipe) == 0) ? 1 : 0; endpt = (8 << 28) | (c << 27) | (usb_maxpacket(dev, pipe) << 16) | (0 << 15) | (1 << 14) | (usb_pipespeed(pipe) << 12) | (usb_pipeendpoint(pipe) << 8) | (0 << 7) | (usb_pipedevice(pipe) << 0); qh.qh_endpt1 = cpu_to_hc32(endpt); endpt = (1 << 30) | (dev->portnr << 23) | (dev->parent->devnum << 16) | (0 << 8) | (0 << 0); qh.qh_endpt2 = cpu_to_hc32(endpt); qh.qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); tdp = &qh.qh_overlay.qt_next; if (req != NULL) { /* * Setup request qTD (3.5 in ehci-r10.pdf) * * qt_next ................ 03-00 H * qt_altnext ............. 07-04 H * qt_token ............... 0B-08 H * * [ buffer, buffer_hi ] loaded with "req". */ qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = (0 << 31) | (sizeof(*req) << 16) | (0 << 15) | (0 << 12) | (3 << 10) | (2 << 8) | (0x80 << 0); qtd[qtd_counter].qt_token = cpu_to_hc32(token); if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req)) != 0) { debug("unable construct SETUP td\n"); goto fail; } /* Update previous qTD! */ *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); tdp = &qtd[qtd_counter++].qt_next; toggle = 1; } if (length > 0 || req == NULL) { /* * Setup request qTD (3.5 in ehci-r10.pdf) * * qt_next ................ 03-00 H * qt_altnext ............. 07-04 H * qt_token ............... 0B-08 H * * [ buffer, buffer_hi ] loaded with "buffer". */ qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = (toggle << 31) | (length << 16) | ((req == NULL ? 1 : 0) << 15) | (0 << 12) | (3 << 10) | ((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0); qtd[qtd_counter].qt_token = cpu_to_hc32(token); if (ehci_td_buffer(&qtd[qtd_counter], buffer, length) != 0) { debug("unable construct DATA td\n"); goto fail; } /* Update previous qTD! */ *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); tdp = &qtd[qtd_counter++].qt_next; } if (req != NULL) { /* * Setup request qTD (3.5 in ehci-r10.pdf) * * qt_next ................ 03-00 H * qt_altnext ............. 07-04 H * qt_token ............... 0B-08 H */ qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = (toggle << 31) | (0 << 16) | (1 << 15) | (0 << 12) | (3 << 10) | ((usb_pipein(pipe) ? 0 : 1) << 8) | (0x80 << 0); qtd[qtd_counter].qt_token = cpu_to_hc32(token); /* Update previous qTD! */ *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); tdp = &qtd[qtd_counter++].qt_next; } qh_list.qh_link = cpu_to_hc32((uint32_t)&qh | QH_LINK_TYPE_QH); /* Flush dcache */ flush_dcache_range((uint32_t)&qh_list, (uint32_t)&qh_list + sizeof(struct QH)); flush_dcache_range((uint32_t)&qh, (uint32_t)&qh + sizeof(struct QH)); flush_dcache_range((uint32_t)qtd, (uint32_t)qtd + sizeof(qtd)); usbsts = ehci_readl(&hcor->or_usbsts); ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f)); /* Enable async. schedule. */ cmd = ehci_readl(&hcor->or_usbcmd); cmd |= CMD_ASE; ehci_writel(&hcor->or_usbcmd, cmd); ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, STD_ASS, 100 * 1000); if (ret < 0) { printf("EHCI fail timeout STD_ASS set\n"); goto fail; } /* Wait for TDs to be processed. */ ts = get_timer(0); vtd = &qtd[qtd_counter - 1]; timeout = USB_TIMEOUT_MS(pipe); do { /* Invalidate dcache */ invalidate_dcache_range((uint32_t)&qh_list, (uint32_t)&qh_list + sizeof(struct QH)); invalidate_dcache_range((uint32_t)&qh, (uint32_t)&qh + sizeof(struct QH)); invalidate_dcache_range((uint32_t)qtd, (uint32_t)qtd + sizeof(qtd)); token = hc32_to_cpu(vtd->qt_token); if (!(token & 0x80)) break; WATCHDOG_RESET(); } while (get_timer(ts) < timeout); /* Invalidate the memory area occupied by buffer */ invalidate_dcache_range(((uint32_t)buffer & ~31), ((uint32_t)buffer & ~31) + roundup(length, 32)); /* Check that the TD processing happened */ if (token & 0x80) { printf("EHCI timed out on TD - token=%#x\n", token); } /* Disable async schedule. */ cmd = ehci_readl(&hcor->or_usbcmd); cmd &= ~CMD_ASE; ehci_writel(&hcor->or_usbcmd, cmd); ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, 0, 100 * 1000); if (ret < 0) { printf("EHCI fail timeout STD_ASS reset\n"); goto fail; } qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH); token = hc32_to_cpu(qh.qh_overlay.qt_token); if (!(token & 0x80)) { debug("TOKEN=%#x\n", token); switch (token & 0xfc) { case 0: toggle = token >> 31; usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), toggle); dev->status = 0; break; case 0x40: dev->status = USB_ST_STALLED; break; case 0xa0: case 0x20: dev->status = USB_ST_BUF_ERR; break; case 0x50: case 0x10: dev->status = USB_ST_BABBLE_DET; break; default: dev->status = USB_ST_CRC_ERR; if ((token & 0x40) == 0x40) dev->status |= USB_ST_STALLED; break; } dev->act_len = length - ((token >> 16) & 0x7fff); } else {
static int usb_hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint) { struct usb_device *dev = hub->dev; struct usb_hub_status *hubstatus; char portstr[USB_MAXCHILDREN + 1]; unsigned int pipe; int i, maxp, ret; hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); if (!hub->descriptor) { err("Unable to kmalloc %Zd bytes for hub descriptor", sizeof(*hub->descriptor)); return -1; } /* Request the entire hub descriptor. */ ret = usb_get_hub_descriptor(dev, hub->descriptor, sizeof(*hub->descriptor)); /* <hub->descriptor> is large enough for a hub with 127 ports; * the hub can/will return fewer bytes here. */ if (ret < 0) { err("Unable to get hub descriptor (err = %d)", ret); kfree(hub->descriptor); return -1; } dev->maxchild = hub->descriptor->bNbrPorts; info("%d port%s detected", hub->descriptor->bNbrPorts, (hub->descriptor->bNbrPorts == 1) ? "" : "s"); le16_to_cpus(&hub->descriptor->wHubCharacteristics); if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND) dbg("part of a compound device"); else dbg("standalone hub"); switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) { case 0x00: dbg("ganged power switching"); break; case 0x01: dbg("individual port power switching"); break; case 0x02: case 0x03: dbg("unknown reserved power switching mode"); break; } switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) { case 0x00: dbg("global over-current protection"); break; case 0x08: dbg("individual port over-current protection"); break; case 0x10: case 0x18: dbg("no over-current protection"); break; } switch (dev->descriptor.bDeviceProtocol) { case 0: break; case 1: dbg("Single TT"); hub->tt.hub = dev; break; case 2: dbg("TT per port"); hub->tt.hub = dev; hub->tt.multi = 1; break; default: dbg("Unrecognized hub protocol %d", dev->descriptor.bDeviceProtocol); break; } switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) { case 0x00: if (dev->descriptor.bDeviceProtocol != 0) dbg("TT requires at most 8 FS bit times"); break; case 0x20: dbg("TT requires at most 16 FS bit times"); break; case 0x40: dbg("TT requires at most 24 FS bit times"); break; case 0x60: dbg("TT requires at most 32 FS bit times"); break; } dbg("Port indicators are %s supported", (hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND) ? "" : "not"); dbg("power on to power good time: %dms", hub->descriptor->bPwrOn2PwrGood * 2); dbg("hub controller current requirement: %dmA", hub->descriptor->bHubContrCurrent); for (i = 0; i < dev->maxchild; i++) portstr[i] = hub->descriptor->DeviceRemovable[((i + 1) / 8)] & (1 << ((i + 1) % 8)) ? 'F' : 'R'; portstr[dev->maxchild] = 0; dbg("port removable status: %s", portstr); hubstatus = kmalloc(sizeof *hubstatus, GFP_KERNEL); if (!hubstatus) { err("Unable to allocate hubstatus"); kfree(hub->descriptor); return -1; } ret = usb_get_hub_status(dev, hubstatus); if (ret < 0) { err("Unable to get hub status (err = %d)", ret); kfree(hubstatus); kfree(hub->descriptor); return -1; } le16_to_cpus(&hubstatus->wHubStatus); dbg("local power source is %s", (hubstatus->wHubStatus & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good"); dbg("%sover-current condition exists", (hubstatus->wHubStatus & HUB_STATUS_OVERCURRENT) ? "" : "no "); kfree(hubstatus); /* Start the interrupt endpoint */ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); if (maxp > sizeof(hub->buffer)) maxp = sizeof(hub->buffer); hub->urb = usb_alloc_urb(0); if (!hub->urb) { err("couldn't allocate interrupt urb"); kfree(hub->descriptor); return -1; } FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq, hub, /* NOTE: in 2.5 fill_int_urb() converts the encoding */ (dev->speed == USB_SPEED_HIGH) ? 1 << (endpoint->bInterval - 1) : endpoint->bInterval); ret = usb_submit_urb(hub->urb); if (ret) { err("usb_submit_urb failed (%d)", ret); kfree(hub->descriptor); return -1; } /* Wake up khubd */ wake_up(&khubd_wait); usb_hub_power_on(hub); return 0; }
static int kingsun_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_device *dev = interface_to_usbdev(intf); struct kingsun_cb *kingsun = NULL; struct net_device *net = NULL; int ret = -ENOMEM; int pipe, maxp_in, maxp_out; __u8 ep_in; __u8 ep_out; interface = intf->cur_altsetting; if (interface->desc.bNumEndpoints != 2) { err("kingsun-sir: expected 2 endpoints, found %d", interface->desc.bNumEndpoints); return -ENODEV; } endpoint = &interface->endpoint[KINGSUN_EP_IN].desc; if (!usb_endpoint_is_int_in(endpoint)) { err("kingsun-sir: endpoint 0 is not interrupt IN"); return -ENODEV; } ep_in = endpoint->bEndpointAddress; pipe = usb_rcvintpipe(dev, ep_in); maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); if (maxp_in > 255 || maxp_in <= 1) { err("%s: endpoint 0 has max packet size %d not in range", __FILE__, maxp_in); return -ENODEV; } endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc; if (!usb_endpoint_is_int_out(endpoint)) { err("kingsun-sir: endpoint 1 is not interrupt OUT"); return -ENODEV; } ep_out = endpoint->bEndpointAddress; pipe = usb_sndintpipe(dev, ep_out); maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); net = alloc_irdadev(sizeof(*kingsun)); if(!net) goto err_out1; SET_NETDEV_DEV(net, &intf->dev); kingsun = netdev_priv(net); kingsun->irlap = NULL; kingsun->tx_urb = NULL; kingsun->rx_urb = NULL; kingsun->ep_in = ep_in; kingsun->ep_out = ep_out; kingsun->in_buf = NULL; kingsun->out_buf = NULL; kingsun->max_rx = (__u8)maxp_in; kingsun->max_tx = (__u8)maxp_out; kingsun->netdev = net; kingsun->usbdev = dev; kingsun->rx_buff.in_frame = FALSE; kingsun->rx_buff.state = OUTSIDE_FRAME; kingsun->rx_buff.skb = NULL; kingsun->receiving = 0; spin_lock_init(&kingsun->lock); kingsun->in_buf = kmalloc(kingsun->max_rx, GFP_KERNEL); if (!kingsun->in_buf) goto free_mem; kingsun->out_buf = kmalloc(KINGSUN_FIFO_SIZE, GFP_KERNEL); if (!kingsun->out_buf) goto free_mem; printk(KERN_INFO "KingSun/DonShine IRDA/USB found at address %d, " "Vendor: %x, Product: %x\n", dev->devnum, le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); irda_init_max_qos_capabilies(&kingsun->qos); kingsun->qos.baud_rate.bits &= IR_9600; kingsun->qos.min_turn_time.bits &= KINGSUN_MTT; irda_qos_bits_to_value(&kingsun->qos); net->netdev_ops = &kingsun_ops; ret = register_netdev(net); if (ret != 0) goto free_mem; dev_info(&net->dev, "IrDA: Registered KingSun/DonShine device %s\n", net->name); usb_set_intfdata(intf, kingsun); return 0; free_mem: if (kingsun->out_buf) kfree(kingsun->out_buf); if (kingsun->in_buf) kfree(kingsun->in_buf); free_netdev(net); err_out1: return ret; }