/** * usb_clear_halt - tells device to clear endpoint halt/stall condition * @dev: device whose endpoint is halted * @pipe: endpoint "pipe" being cleared * Context: !in_interrupt () * * This is used to clear halt conditions for bulk and interrupt endpoints, * as reported by URB completion status. Endpoints that are halted are * sometimes referred to as being "stalled". Such endpoints are unable * to transmit or receive data until the halt status is cleared. Any URBs * queued for such an endpoint should normally be unlinked by the driver * before clearing the halt condition, as described in sections 5.7.5 * and 5.8.5 of the USB 2.0 spec. * * Note that control and isochronous endpoints don't halt, although control * endpoints report "protocol stall" (for unsupported requests) using the * same status code used to report a true stall. * * This call is synchronous, and may not be used in an interrupt context. * * Returns zero on success, or else the status code returned by the * underlying usb_control_msg() call. */ int usb_clear_halt(struct usb_device *dev, int pipe) { int result; int endp = usb_pipeendpoint(pipe); if (usb_pipein (pipe)) endp |= USB_DIR_IN; /* we don't care if it wasn't halted first. in fact some devices * (like some ibmcam model 1 units) seem to expect hosts to make * this request for iso endpoints, which can't halt! */ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, USB_ENDPOINT_HALT, endp, NULL, 0, USB_CTRL_SET_TIMEOUT); /* don't un-halt or force to DATA0 except on success */ if (result < 0) return result; /* NOTE: seems like Microsoft and Apple don't bother verifying * the clear "took", so some devices could lock up if you check... * such as the Hagiwara FlashGate DUAL. So we won't bother. * * NOTE: make sure the logic here doesn't diverge much from * the copy in usb-storage, for as long as we need two copies. */ /* toggle was reset by the clear */ usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); return 0; }
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); int max = usb_maxpacket(dev, pipe); int done = 0; PDEBUG(7, "dev = %ld pipe = %ld buf = %p size = %d dir_out = %d\n", usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out); dev->status = 0; sl811_write(SL811_DEV_A, usb_pipedevice(pipe)); sl811_write(SL811_PIDEP_A, PIDEP(!dir_out ? USB_PID_IN : USB_PID_OUT, ep)); while (done < len) { int res = sl811_send_packet(dev, pipe, (__u8*)buffer+done, max > len - done ? len - done : max); if (res < 0) { dev->status = -res; return res; } if (!dir_out && res < max) /* short packet */ break; done += res; usb_dotoggle(dev, ep, dir_out); } dev->act_len = done; return 0; }
int32 USBHost::submit_bulk_msg(uint32 pipe, memptr buffer, int32 len) { D(bug("\nUSBHost: submit_bulk_msg()")); uint8 *tempbuff; int32 dir_out; uint8 endpoint; int32 devnum; int32 transferred; unsigned int dev_idx = 0; int32 r; tempbuff = (uint8 *)Atari2HostAddr(buffer); dir_out = usb_pipeout(pipe); endpoint = usb_pipeendpoint(pipe) | (dir_out ? LIBUSB_ENDPOINT_OUT : LIBUSB_ENDPOINT_IN); devnum = usb_pipedevice(pipe); D(bug("USBHost: devnum %d ", devnum)); D(bug("USBHost: pipe %x ", pipe)); D(bug("USBHost: --- BULK -----------------------------------------------")); D(bug("USBHost: dev=%d endpoint=%d endpoint address= %x buf=%p size=%d dir_out=%d", usb_pipedevice(pipe), usb_pipeendpoint(pipe), endpoint, tempbuff, len, dir_out)); dev_idx = roothub.port[devnum - 2].device_index; D(bug("USBHost: dev_idx %d ", dev_idx)); r = libusb_bulk_transfer(devh[dev_idx], endpoint, tempbuff, len, &transferred, 1000); D(bug("USBHost: return: %d len: %d transferred: %d", r, len, transferred)); return r; }
static inline void qtd_copy_status (struct urb *urb, size_t length, u32 token) { /* count IN/OUT bytes, not SETUP (even short packets) */ if (likely (QTD_PID (token) != 2)) urb->actual_length += length - QTD_LENGTH (token); /* don't modify error codes */ if (unlikely (urb->status == -EINPROGRESS && (token & QTD_STS_HALT))) { if (token & QTD_STS_BABBLE) { /* FIXME "must" disable babbling device's port too */ urb->status = -EOVERFLOW; } else if (token & QTD_STS_MMF) { /* fs/ls interrupt xfer missed the complete-split */ urb->status = -EPROTO; } else if (token & QTD_STS_DBE) { urb->status = (QTD_PID (token) == 1) /* IN ? */ ? -ENOSR /* hc couldn't read data */ : -ECOMM; /* hc couldn't write data */ } else if (token & QTD_STS_XACT) { /* timeout, bad crc, wrong PID, etc; retried */ if (QTD_CERR (token)) urb->status = -EPIPE; else { dbg ("3strikes"); urb->status = -EPROTO; } /* CERR nonzero + no errors + halt --> stall */ } else if (QTD_CERR (token)) urb->status = -EPIPE; else /* unknown */ urb->status = -EPROTO; dbg ("ep %d-%s qtd token %08x --> status %d", /* devpath */ usb_pipeendpoint (urb->pipe), usb_pipein (urb->pipe) ? "in" : "out", token, urb->status); /* stall indicates some recovery action is needed */ if (urb->status == -EPIPE) { int pipe = urb->pipe; if (!usb_pipecontrol (pipe)) usb_endpoint_halt (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); if (urb->dev->tt && !usb_pipeint (pipe)) { err ("must CLEAR_TT_BUFFER, hub port %d%s addr %d ep %d", urb->dev->ttport, /* devpath */ urb->dev->tt->multi ? "" : " (all-ports TT)", urb->dev->devnum, usb_pipeendpoint (urb->pipe)); // FIXME something (khubd?) should make the hub // CLEAR_TT_BUFFER ASAP, it's blocking other // fs/ls requests... hub_tt_clear_buffer() ? } } } }
vsf_err_t vsfusbh_submit_urb(struct vsfusbh_t *usbh, struct vsfusbh_urb_t *vsfurb) { if (usb_pipein(vsfurb->pipe)) vsfurb->packet_size = vsfurb->vsfdev->epmaxpacketin[usb_pipeendpoint(vsfurb->pipe)]; else vsfurb->packet_size = vsfurb->vsfdev->epmaxpacketout[usb_pipeendpoint(vsfurb->pipe)]; if (vsfurb->vsfdev == usbh->rh_dev) return vsfusbh_rh_submit_urb(usbh, vsfurb); else return usbh->hcd->submit_urb(usbh->hcd_data, vsfurb); }
static int vstusb_complete_urb(struct urb *urb, struct completion *done, int timeout, int *actual_length) { unsigned long expire; int status; expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; if (!wait_for_completion_interruptible_timeout(done, expire)) { usb_kill_urb(urb); status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status; dev_dbg(&urb->dev->dev, "%s timed out on ep%d%s len=%d/%d, urb status = %d\n", current->comm, usb_pipeendpoint(urb->pipe), usb_pipein(urb->pipe) ? "in" : "out", urb->actual_length, urb->transfer_buffer_length, urb->status); } else { if (signal_pending(current)) { /* if really an error */ if (urb->status && !((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || (urb->status == -ESHUTDOWN))) { status = -EINTR; usb_kill_urb(urb); } else { status = 0; } dev_dbg(&urb->dev->dev, "%s: signal pending on ep%d%s len=%d/%d," "urb status = %d\n", current->comm, usb_pipeendpoint(urb->pipe), usb_pipein(urb->pipe) ? "in" : "out", urb->actual_length, urb->transfer_buffer_length, urb->status); } else { status = urb->status; } } if (actual_length) *actual_length = urb->actual_length; return status; }
static void hsictty_write_callback(struct urb *urb) { struct usb_serial_port *port; struct hsictty_port_private *portdata; struct hsictty_intf_private *intfdata; int i; port = urb->context; intfdata = usb_get_serial_data(port->serial); portdata = usb_get_serial_port_data(port); if (urb->actual_length <= 0) { hsictty_error ("%s: write failed, write length: %d in channel:%d, endpoint:%d\n", __func__, urb->actual_length, portdata->channel, usb_pipeendpoint(urb->pipe)); } else { hsictty_dbg("%s: write length: %d in channel:%d, endpoint:%d\n", __func__, urb->actual_length, portdata->channel, usb_pipeendpoint(urb->pipe)); } #ifdef BACKUP_DATA_DUMP if (!dumped) backup_log(portdata->channel, 1, urb->transfer_buffer, urb->transfer_buffer_length); #endif usb_serial_port_softint(port); usb_autopm_put_interface_async(port->serial->interface); portdata = usb_get_serial_port_data(port); spin_lock(&intfdata->susp_lock); intfdata->in_flight--; spin_unlock(&intfdata->susp_lock); for (i = 0; i < N_OUT_URB; ++i) { if (portdata->out_urbs[i] == urb) { smp_mb__before_clear_bit(); hsictty_dbg ("%s: urb(%d) freed on channel:%d, endpoint:%d, in_flight:%d, pm use cnt:%d\n", __func__, i, portdata->channel, usb_pipeendpoint(urb->pipe), intfdata->in_flight, atomic_read(&port->serial->interface->dev.power. usage_count)); clear_bit(i, &portdata->out_busy); complete_all(&portdata->tx_notifier); break; } } }
/* * Check an aimed rpipe to make sure it points to where we want * * We use bit 19 of the Linux USB pipe bitmap for unauth vs auth * space; when it is like that, we or 0x80 to make an unauth address. */ static int rpipe_check_aim(const struct wa_rpipe *rpipe, const struct wahc *wa, const struct usb_host_endpoint *ep, const struct urb *urb, gfp_t gfp) { int result = 0; /* better code for lack of companion? */ struct device *dev = &wa->usb_iface->dev; struct usb_device *usb_dev = urb->dev; u8 unauth = (usb_dev->wusb && !usb_dev->authenticated) ? 0x80 : 0; u8 portnum = wusb_port_no_to_idx(urb->dev->portnum); #define AIM_CHECK(rdf, val, text) \ do { \ if (rpipe->descr.rdf != (val)) { \ dev_err(dev, \ "rpipe aim discrepancy: " #rdf " " text "\n", \ rpipe->descr.rdf, (val)); \ result = -EINVAL; \ WARN_ON(1); \ } \ } while (0) AIM_CHECK(wMaxPacketSize, cpu_to_le16(ep->desc.wMaxPacketSize), "(%u vs %u)"); AIM_CHECK(bHSHubPort, portnum, "(%u vs %u)"); AIM_CHECK(bSpeed, usb_pipeendpoint(urb->pipe) == 0 ? UWB_PHY_RATE_53 : UWB_PHY_RATE_200, "(%u vs %u)"); AIM_CHECK(bDeviceAddress, urb->dev->devnum | unauth, "(%u vs %u)"); AIM_CHECK(bEndpointAddress, ep->desc.bEndpointAddress, "(%u vs %u)"); AIM_CHECK(bInterval, ep->desc.bInterval, "(%u vs %u)"); AIM_CHECK(bmAttribute, ep->desc.bmAttributes & 0x03, "(%u vs %u)"); #undef AIM_CHECK return result; }
static void dump_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int len, char *str) { #if defined(VERBOSE) int i; #endif DBG("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d stat:%#lx", str, isp116x_get_current_frame_number(dev), usb_pipedevice(pipe), usb_pipeendpoint(pipe), usb_pipeout(pipe) ? 'O' : 'I', usb_pipetype(pipe) < 2 ? (usb_pipeint(pipe) ? "INTR" : "ISOC") : (usb_pipecontrol(pipe) ? "CTRL" : "BULK"), len, dev->status); #if defined(VERBOSE) if (len > 0 && buffer) { printf(__FILE__ ": data(%d):", len); for (i = 0; i < 16 && i < len; i++) printf(" %02x", ((__u8 *) buffer)[i]); printf("%s\n", i < len ? "..." : ""); } #endif }
/* * Starts urb and waits for completion or timeout. Note that this call * is NOT interruptible. Many device driver i/o requests should be * interruptible and therefore these drivers should implement their * own interruptible routines. */ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) { struct completion done; unsigned long expire; int status; init_completion(&done); urb->context = &done; urb->actual_length = 0; status = usb_submit_urb(urb, GFP_NOIO); if (unlikely(status)) goto out; expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; if (!wait_for_completion_timeout(&done, expire)) { dev_dbg(&urb->dev->dev, "%s timed out on ep%d%s len=%d/%d\n", current->comm, usb_pipeendpoint(urb->pipe), usb_pipein(urb->pipe) ? "in" : "out", urb->actual_length, urb->transfer_buffer_length); usb_kill_urb(urb); status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status; } else status = urb->status; out: if (actual_length) *actual_length = urb->actual_length; usb_free_urb(urb); return status; }
static void usbip_dump_pipe(unsigned int p) { unsigned char type = usb_pipetype(p); unsigned char ep = usb_pipeendpoint(p); unsigned char dev = usb_pipedevice(p); unsigned char dir = usb_pipein(p); printk(KERN_DEBUG "dev(%d) ", dev); printk(KERN_DEBUG "ep(%d) ", ep); printk(KERN_DEBUG "%s ", dir ? "IN" : "OUT"); switch (type) { case PIPE_ISOCHRONOUS: printk(KERN_DEBUG "%s ", "ISO"); break; case PIPE_INTERRUPT: printk(KERN_DEBUG "%s ", "INT"); break; case PIPE_CONTROL: printk(KERN_DEBUG "%s ", "CTL"); break; case PIPE_BULK: printk(KERN_DEBUG "%s ", "BLK"); break; default: printk(KERN_DEBUG "ERR"); } printk(KERN_DEBUG "\n"); }
static int g19_ep1_read(struct hid_device *hdev) { struct usb_interface *intf; struct usb_device *usb_dev; struct g19_data *data = hid_get_g19data(hdev); struct usb_host_endpoint *ep; unsigned int pipe; int retval = 0; /* Get the usb device to send the image on */ intf = to_usb_interface(hdev->dev.parent); usb_dev = interface_to_usbdev(intf); pipe = usb_rcvintpipe(usb_dev, 0x01); ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)[usb_pipeendpoint(pipe)]; if (unlikely(!ep)) return -EINVAL; usb_fill_int_urb(data->ep1_urb, usb_dev, pipe, data->ep1keys, 2, g19_ep1_urb_completion, NULL, 10); data->ep1_urb->context = hdev; data->ep1_urb->actual_length = 0; retval = usb_submit_urb(data->ep1_urb, GFP_KERNEL); return retval; }
/* * Check an aimed rpipe to make sure it points to where we want * * We use bit 19 of the Linux USB pipe bitmap for unauth vs auth * space; when it is like that, we or 0x80 to make an unauth address. */ static int rpipe_check_aim(const struct wa_rpipe *rpipe, const struct wahc *wa, const struct usb_host_endpoint *ep, const struct urb *urb, gfp_t gfp) { int result = 0; struct device *dev = &wa->usb_iface->dev; u8 portnum = wusb_port_no_to_idx(urb->dev->portnum); #define AIM_CHECK(rdf, val, text) \ do { \ if (rpipe->descr.rdf != (val)) { \ dev_err(dev, \ "rpipe aim discrepancy: " #rdf " " text "\n", \ rpipe->descr.rdf, (val)); \ result = -EINVAL; \ WARN_ON(1); \ } \ } while (0) AIM_CHECK(hwa_bDeviceInfoIndex, portnum, "(%u vs %u)"); AIM_CHECK(bSpeed, usb_pipeendpoint(urb->pipe) == 0 ? UWB_PHY_RATE_53 : UWB_PHY_RATE_200, "(%u vs %u)"); AIM_CHECK(bEndpointAddress, ep->desc.bEndpointAddress, "(%u vs %u)"); AIM_CHECK(bInterval, ep->desc.bInterval, "(%u vs %u)"); AIM_CHECK(bmAttribute, ep->desc.bmAttributes & 0x03, "(%u vs %u)"); #undef AIM_CHECK return result; }
/** * usb_hub_tt_clear_buffer - clear control/bulk TT state in high speed hub * @dev: the device whose split transaction failed * @pipe: identifies the endpoint of the failed transaction * * High speed HCDs use this to tell the hub driver that some split control or * bulk transaction failed in a way that requires clearing internal state of * a transaction translator. This is normally detected (and reported) from * interrupt context. * * It may not be possible for that hub to handle additional full (or low) * speed transactions until that state is fully cleared out. */ void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe) { struct usb_tt *tt = dev->tt; unsigned long flags; struct usb_tt_clear *clear; /* we've got to cope with an arbitrary number of pending TT clears, * since each TT has "at least two" buffers that can need it (and * there can be many TTs per hub). even if they're uncommon. */ if ((clear = kmalloc (sizeof *clear, SLAB_ATOMIC)) == 0) { err ("can't save CLEAR_TT_BUFFER state for hub at usb-%s-%s", dev->bus->bus_name, tt->hub->devpath); /* FIXME recover somehow ... RESET_TT? */ return; } /* info that CLEAR_TT_BUFFER needs */ clear->tt = tt->multi ? dev->ttport : 1; clear->devinfo = usb_pipeendpoint (pipe); clear->devinfo |= dev->devnum << 4; clear->devinfo |= usb_pipecontrol (pipe) ? (USB_ENDPOINT_XFER_CONTROL << 11) : (USB_ENDPOINT_XFER_BULK << 11); if (usb_pipein (pipe)) clear->devinfo |= 1 << 15; /* tell keventd to clear state for this TT */ spin_lock_irqsave (&tt->lock, flags); list_add_tail (&clear->clear_list, &tt->clear_list); schedule_work (&tt->kevent); spin_unlock_irqrestore (&tt->lock, flags); }
static struct int_queue *_musb_create_int_queue(struct musb_host_data *host, struct usb_device *dev, unsigned long pipe, int queuesize, int elementsize, void *buffer, int interval) { struct int_queue *queue; int ret, index = usb_pipein(pipe) * 16 + usb_pipeendpoint(pipe); if (queuesize != 1) { printf("ERROR musb int-queues only support queuesize 1\n"); return NULL; } if (dev->int_pending & (1 << index)) { printf("ERROR int-urb is already pending on pipe %lx\n", pipe); return NULL; } queue = malloc(sizeof(*queue)); if (!queue) return NULL; construct_urb(&queue->urb, &queue->hep, dev, USB_ENDPOINT_XFER_INT, pipe, buffer, elementsize, NULL, interval); ret = musb_urb_enqueue(&host->hcd, &queue->urb, 0); if (ret < 0) { printf("Failed to enqueue URB to controller\n"); free(queue); return NULL; } dev->int_pending |= 1 << index; return queue; }
/** * usb_submit_urb - issue an asynchronous transfer request for an endpoint * @urb: pointer to the urb describing the request * @mem_flags: the type of memory to allocate, see kmalloc() for a list * of valid options for this. * * This submits a transfer request, and transfers control of the URB * describing that request to the USB subsystem. Request completion will * be indicated later, asynchronously, by calling the completion handler. * The three types of completion are success, error, and unlink * (a software-induced fault, also called "request cancelation"). * * URBs may be submitted in interrupt context. * * The caller must have correctly initialized the URB before submitting * it. Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are * available to ensure that most fields are correctly initialized, for * the particular kind of transfer, although they will not initialize * any transfer flags. * * Successful submissions return 0; otherwise this routine returns a * negative error number. If the submission is successful, the complete() * callback from the URB will be called exactly once, when the USB core and * Host Controller Driver (HCD) are finished with the URB. When the completion * function is called, control of the URB is returned to the device * driver which issued the request. The completion handler may then * immediately free or reuse that URB. * * With few exceptions, USB device drivers should never access URB fields * provided by usbcore or the HCD until its complete() is called. * The exceptions relate to periodic transfer scheduling. For both * interrupt and isochronous urbs, as part of successful URB submission * urb->interval is modified to reflect the actual transfer period used * (normally some power of two units). And for isochronous urbs, * urb->start_frame is modified to reflect when the URB's transfers were * scheduled to start. Not all isochronous transfer scheduling policies * will work, but most host controller drivers should easily handle ISO * queues going from now until 10-200 msec into the future. * * For control endpoints, the synchronous usb_control_msg() call is * often used (in non-interrupt context) instead of this call. * That is often used through convenience wrappers, for the requests * that are standardized in the USB 2.0 specification. For bulk * endpoints, a synchronous usb_bulk_msg() call is available. * * Request Queuing: * * URBs may be submitted to endpoints before previous ones complete, to * minimize the impact of interrupt latencies and system overhead on data * throughput. With that queuing policy, an endpoint's queue would never * be empty. This is required for continuous isochronous data streams, * and may also be required for some kinds of interrupt transfers. Such * queuing also maximizes bandwidth utilization by letting USB controllers * start work on later requests before driver software has finished the * completion processing for earlier (successful) requests. * * As of Linux 2.6, all USB endpoint transfer queues support depths greater * than one. This was previously a HCD-specific behavior, except for ISO * transfers. Non-isochronous endpoint queues are inactive during cleanup * after faults (transfer errors or cancelation). * * Reserved Bandwidth Transfers: * * Periodic transfers (interrupt or isochronous) are performed repeatedly, * using the interval specified in the urb. Submitting the first urb to * the endpoint reserves the bandwidth necessary to make those transfers. * If the USB subsystem can't allocate sufficient bandwidth to perform * the periodic request, submitting such a periodic request should fail. * * Device drivers must explicitly request that repetition, by ensuring that * some URB is always on the endpoint's queue (except possibly for short * periods during completion callacks). When there is no longer an urb * queued, the endpoint's bandwidth reservation is canceled. This means * drivers can use their completion handlers to ensure they keep bandwidth * they need, by reinitializing and resubmitting the just-completed urb * until the driver longer needs that periodic bandwidth. * * Memory Flags: * * The general rules for how to decide which mem_flags to use * are the same as for kmalloc. There are four * different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and * GFP_ATOMIC. * * GFP_NOFS is not ever used, as it has not been implemented yet. * * GFP_ATOMIC is used when * (a) you are inside a completion handler, an interrupt, bottom half, * tasklet or timer, or * (b) you are holding a spinlock or rwlock (does not apply to * semaphores), or * (c) current->state != TASK_RUNNING, this is the case only after * you've changed it. * * GFP_NOIO is used in the block io path and error handling of storage * devices. * * All other situations use GFP_KERNEL. * * Some more specific rules for mem_flags can be inferred, such as * (1) start_xmit, timeout, and receive methods of network drivers must * use GFP_ATOMIC (they are called with a spinlock held); * (2) queuecommand methods of scsi drivers must use GFP_ATOMIC (also * called with a spinlock held); * (3) If you use a kernel thread with a network driver you must use * GFP_NOIO, unless (b) or (c) apply; * (4) after you have done a down() you can use GFP_KERNEL, unless (b) or (c) * apply or your are in a storage driver's block io path; * (5) USB probe and disconnect can use GFP_KERNEL unless (b) or (c) apply; and * (6) changing firmware on a running storage or net device uses * GFP_NOIO, unless b) or c) apply * */ int usb_submit_urb(struct urb *urb, int mem_flags) { int pipe, temp, max; struct usb_device *dev; struct usb_operations *op; int is_out; if (!urb || urb->hcpriv || !urb->complete) return -EINVAL; if (!(dev = urb->dev) || (dev->state < USB_STATE_DEFAULT) || (!dev->bus) || (dev->devnum <= 0)) return -ENODEV; if (dev->state == USB_STATE_SUSPENDED) return -EHOSTUNREACH; if (!(op = dev->bus->op) || !op->submit_urb) return -ENODEV; urb->status = -EINPROGRESS; urb->actual_length = 0; urb->bandwidth = 0; /* Lots of sanity checks, so HCDs can rely on clean data * and don't need to duplicate tests */ pipe = urb->pipe; temp = usb_pipetype (pipe); is_out = usb_pipeout (pipe); if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED) return -ENODEV; /* FIXME there should be a sharable lock protecting us against * config/altsetting changes and disconnects, kicking in here. * (here == before maxpacket, and eventually endpoint type, * checks get made.) */ max = usb_maxpacket (dev, pipe, is_out); if (max <= 0) { dev_dbg(&dev->dev, "bogus endpoint ep%d%s in %s (bad maxpacket %d)", usb_pipeendpoint (pipe), is_out ? "out" : "in", __FUNCTION__, max); return -EMSGSIZE; } /* periodic transfers limit size per frame/uframe, * but drivers only control those sizes for ISO. * while we're checking, initialize return status. */ if (temp == PIPE_ISOCHRONOUS) { int n, len; /* "high bandwidth" mode, 1-3 packets/uframe? */ if (dev->speed == USB_SPEED_HIGH) { int mult = 1 + ((max >> 11) & 0x03); max &= 0x07ff; max *= mult; }
static struct urb *construct_urb(struct usb_device *dev, int endpoint_type, unsigned long pipe, void *buffer, int len, struct devrequest *setup, int interval) { int epnum = usb_pipeendpoint(pipe); int is_in = usb_pipein(pipe); memset(&urb, 0, sizeof(struct urb)); memset(&hep, 0, sizeof(struct usb_host_endpoint)); INIT_LIST_HEAD(&hep.urb_list); INIT_LIST_HEAD(&urb.urb_list); urb.ep = &hep; urb.complete = musb_host_complete_urb; urb.status = -EINPROGRESS; urb.dev = dev; urb.pipe = pipe; urb.transfer_buffer = buffer; urb.transfer_dma = (unsigned long)buffer; urb.transfer_buffer_length = len; urb.setup_packet = (unsigned char *)setup; urb.ep->desc.wMaxPacketSize = __cpu_to_le16(is_in ? dev->epmaxpacketin[epnum] : dev->epmaxpacketout[epnum]); urb.ep->desc.bmAttributes = endpoint_type; urb.ep->desc.bEndpointAddress = (is_in ? USB_DIR_IN : USB_DIR_OUT) | epnum; urb.ep->desc.bInterval = interval; return &urb; }
/** * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion * @usb_dev: pointer to the usb device to send the message to * @pipe: endpoint "pipe" to send the message to * @data: pointer to the data to send * @len: length in bytes of the data to send * @actual_length: pointer to a location to put the actual length transferred in bytes * @timeout: time in msecs to wait for the message to complete before * timing out (if 0 the wait is forever) * Context: !in_interrupt () * * This function sends a simple bulk message to a specified endpoint * and waits for the message to complete, or timeout. * * If successful, it returns 0, otherwise a negative error number. * The number of actual bytes transferred will be stored in the * actual_length paramater. * * Don't use this function from within an interrupt context, like a * bottom half handler. If you need an asynchronous message, or need to * send a message from within interrupt context, use usb_submit_urb() * If a thread in your driver uses this call, make sure your disconnect() * method can wait for it to complete. Since you don't have a handle on * the URB used, you can't cancel the request. * * Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT * ioctl, users are forced to abuse this routine by using it to submit * URBs for interrupt endpoints. We will take the liberty of creating * an interrupt URB (with the default interval) if the target is an * interrupt endpoint. */ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout) { struct urb *urb; struct usb_host_endpoint *ep; ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out) [usb_pipeendpoint(pipe)]; if (!ep || len < 0) return -EINVAL; urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return -ENOMEM; if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); usb_fill_int_urb(urb, usb_dev, pipe, data, len, usb_api_blocking_completion, NULL, ep->desc.bInterval); } else usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, usb_api_blocking_completion, NULL); return usb_start_wait_urb(urb, timeout, actual_length); }
static int hci_submit_urb (struct urb * urb) { hci_t * hci; unsigned int pipe = urb->pipe; unsigned long flags; int ret; if (!urb->dev || !urb->dev->bus || urb->hcpriv) return -EINVAL; if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) return -EPIPE; hci = (hci_t *) urb->dev->bus->hcpriv; /* a request to the virtual root hub */ if (usb_pipedevice (pipe) == hci->rh.devnum) { return rh_submit_urb (urb); } if (urb_debug) urb_print (urb, "SUB", usb_pipein (pipe)); /* queue the URB to its endpoint-queue */ spin_lock_irqsave (&usb_urb_lock, flags); ret = hcs_urb_queue (hci, urb); spin_unlock_irqrestore (&usb_urb_lock, flags); return ret; }
static int init_status (struct usbnet *dev, struct usb_interface *intf) { char *buf = NULL; unsigned pipe = 0; unsigned maxp; unsigned period; if (!dev->driver_info->status) return 0; pipe = usb_rcvintpipe (dev->udev, dev->status->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); maxp = usb_maxpacket (dev->udev, pipe, 0); /* avoid 1 msec chatter: min 8 msec poll rate */ period = max ((int) dev->status->desc.bInterval, (dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3); buf = kmalloc (maxp, GFP_KERNEL); if (buf) { dev->interrupt = usb_alloc_urb (0, GFP_KERNEL); if (!dev->interrupt) { kfree (buf); return -ENOMEM; } else { usb_fill_int_urb(dev->interrupt, dev->udev, pipe, buf, maxp, intr_complete, dev, period); dev_dbg(&intf->dev, "status ep%din, %d bytes period %d\n", usb_pipeendpoint(pipe), maxp, period); } } return 0; }
/*-------------------------------------------------------------------*/ static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb) { int ret; unsigned int pipe; int actual_length; dbg("dabusb_bulk"); if (!pb->pipe) pipe = usb_rcvbulkpipe (s->usbdev, 2); else pipe = usb_sndbulkpipe (s->usbdev, 2); ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100); if(ret<0) { err("dabusb: usb_bulk_msg failed(%d)",ret); if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { err("set_interface failed"); return -EINVAL; } } if( ret == -EPIPE ) { warn("CLEAR_FEATURE request to remove STALL condition."); if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe))) err("request failed"); } pb->size = actual_length; return ret; }
static void usbip_dump_pipe(unsigned int p) { unsigned char type = usb_pipetype(p); unsigned char ep = usb_pipeendpoint(p); unsigned char dev = usb_pipedevice(p); unsigned char dir = usb_pipein(p); pr_debug("dev(%d) ep(%d) [%s] ", dev, ep, dir ? "IN" : "OUT"); switch (type) { case PIPE_ISOCHRONOUS: pr_debug("ISO\n"); break; case PIPE_INTERRUPT: pr_debug("INT\n"); break; case PIPE_CONTROL: pr_debug("CTRL\n"); break; case PIPE_BULK: pr_debug("BULK\n"); break; default: pr_debug("ERR\n"); break; } }
static void cdc_ncm_status(struct if_usb_devdata *pipe_data, struct urb *urb) { struct cdc_ncm_ctx *ctx; struct usb_cdc_notification *event; ctx = (struct cdc_ncm_ctx *)pipe_data->sedata; if (urb->actual_length < sizeof(*event)) return; /* test for split data in 8-byte chunks */ if (test_and_clear_bit(EVENT_STS_SPLIT, &pipe_data->flags)) { cdc_ncm_speed_change(ctx, (struct usb_cdc_speed_change *)urb->transfer_buffer); return; } event = urb->transfer_buffer; mif_debug("event: %d by ep=%d\n", event->bNotificationType, usb_pipeendpoint(urb->pipe)); switch (event->bNotificationType) { case USB_CDC_NOTIFY_NETWORK_CONNECTION: /* * According to the CDC NCM specification ch.7.1 * USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be * sent by device after USB_CDC_NOTIFY_SPEED_CHANGE. */ ctx->connected = event->wValue; pipe_data->net_connected = (event->wValue) ? true : false; printk(KERN_INFO KBUILD_MODNAME ": network connection: %s connected\n", ctx->connected ? "" : "dis"); if (ctx->connected) netif_carrier_on(pipe_data->iod->ndev); else { netif_carrier_off(pipe_data->iod->ndev); ctx->tx_speed = ctx->rx_speed = 0; } break; case USB_CDC_NOTIFY_SPEED_CHANGE: if (urb->actual_length < (sizeof(*event) + sizeof(struct usb_cdc_speed_change))) set_bit(EVENT_STS_SPLIT, &pipe_data->flags); else cdc_ncm_speed_change(ctx, (struct usb_cdc_speed_change *) &event[1]); break; default: mif_err("unexpected notification 0x%02x!\n", event->bNotificationType); break; } }
//Update int queue status in interrupt,it is revised according the routine //_ehci_poll_int_queue. static BOOL _ehciQueueIntHandler(struct int_queue* queue) { struct QH *cur = queue->current; struct qTD *cur_td; uint32_t token, toggle; unsigned long pipe = queue->pipe; struct usb_device* dev = queue->pUsbDev; //Queue is canceled by user,maybe triggered by wait time out. if (INT_QUEUE_STATUS_CANCELED == queue->dwStatus) { return FALSE; } /* depleted queue */ if (cur == NULL) { queue->dwStatus = INT_QUEUE_STATUS_COMPLETED; return TRUE; } /* still active */ cur_td = &queue->tds[queue->current - queue->first]; invalidate_dcache_range((unsigned long)cur_td, ALIGN_END_ADDR(struct qTD, cur_td, 1)); token = hc32_to_cpu(cur_td->qt_token); if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE) { queue->dwStatus = INT_QUEUE_STATUS_INPROCESS; debug("Exit %s with no completed intr transfer. token is %x\r\n", __func__, token); return FALSE; } if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_HALTED){ queue->dwStatus = INT_QUEUE_STATUS_ERROR; debug("Exit %s with halted intr transfer,token is %X.\r\n", __func__, token); return FALSE; } toggle = QT_TOKEN_GET_DT(token); usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), toggle); if (!(cur->qh_link & QH_LINK_TERMINATE)) queue->current++; else queue->current = NULL; invalidate_dcache_range((unsigned long)cur->buffer, ALIGN_END_ADDR(char, cur->buffer, queue->elementsize)); //Last qTD is transfer over. if (NULL == queue->current) { queue->dwStatus = INT_QUEUE_STATUS_COMPLETED; debug("Exit %s with completed intr transfer. token is %x at %p (first at %p)\r\n", __func__, token, cur, queue->first); return TRUE; } return FALSE; }
/* Write */ static int option_write(struct usb_serial_port *port, const unsigned char *buf, int count) { struct option_port_private *portdata; int i; int left, todo; struct urb *this_urb = NULL; /* spurious */ int err; portdata = usb_get_serial_port_data(port); dbg("%s: write (%d chars)", __FUNCTION__, count); i = 0; left = count; for (i=0; left > 0 && i < N_OUT_URB; i++) { todo = left; if (todo > OUT_BUFLEN) todo = OUT_BUFLEN; this_urb = portdata->out_urbs[i]; if (test_and_set_bit(i, &portdata->out_busy)) { if (time_before(jiffies, portdata->tx_start_time[i] + 10 * HZ)) continue; usb_unlink_urb(this_urb); continue; } if (this_urb->status != 0) dbg("usb_write %p failed (err=%d)", this_urb, this_urb->status); dbg("%s: endpoint %d buf %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), i); /* send the data */ memcpy (this_urb->transfer_buffer, buf, todo); this_urb->transfer_buffer_length = todo; this_urb->dev = port->serial->dev; err = usb_submit_urb(this_urb, GFP_ATOMIC); if (err) { dbg("usb_submit_urb %p (write bulk) failed " "(%d, has %d)", this_urb, err, this_urb->status); clear_bit(i, &portdata->out_busy); continue; } portdata->tx_start_time[i] = jiffies; buf += todo; left -= todo; } count -= left; dbg("%s: wrote (did %d)", __FUNCTION__, count); return count; }
static u16 r8a66597_get_pipenum(struct urb *urb, struct usb_host_endpoint *hep) { struct r8a66597_pipe *pipe = hep->hcpriv; if (usb_pipeendpoint(urb->pipe) == 0) return 0; else return pipe->info.pipenum; }
static int receive_bulk_packet(struct r8a66597 *r8a66597, struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len) { u16 tmp; u16 *buf; const u16 pipenum = BULK_IN_PIPENUM; int rcv_len; int maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)]; R8A66597_DPRINT("%s\n", __func__); /* prepare */ if (dev->act_len == 0) { r8a66597_mdfy(r8a66597, PID_NAK, PID, get_pipectr_addr(pipenum)); r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS); r8a66597_write(r8a66597, TRCLR, get_pipetre_addr(pipenum)); r8a66597_write(r8a66597, (transfer_len + maxpacket - 1) / maxpacket, get_pipetrn_addr(pipenum)); r8a66597_bset(r8a66597, TRENB, get_pipetre_addr(pipenum)); r8a66597_mdfy(r8a66597, PID_BUF, PID, get_pipectr_addr(pipenum)); } r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL); r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum); while (!(r8a66597_read(r8a66597, BRDYSTS) & (1 << pipenum))) if (ctrlc()) return -1; r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS); tmp = r8a66597_read(r8a66597, CFIFOCTR); if ((tmp & FRDY) == 0) { printf("%s FRDY is not set. (%x)\n", __func__, tmp); return -1; } buf = (u16 *)(buffer + dev->act_len); rcv_len = tmp & DTLN; dev->act_len += rcv_len; if (buffer) { if (rcv_len == 0) r8a66597_write(r8a66597, BCLR, CFIFOCTR); else r8a66597_read_fifo(r8a66597, CFIFO, buf, rcv_len); } return 0; }
/* This is a version of usb_clear_halt() that doesn't read the status from * the device -- this is because some devices crash their internal firmware * when the status is requested after a halt */ int usb_stor_clear_halt(struct usb_device *dev, int pipe) { int result; int endp = usb_pipeendpoint(pipe) | (usb_pipein(pipe) << 7); result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, HZ * 3); /* this is a failure case */ if (result < 0) return result; /* reset the toggles and endpoint flags */ usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); return 0; }
/** Gets the usb_host_endpoint associated with an URB. */ inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb) { struct usb_device *dev = urb->dev; int ep_num = usb_pipeendpoint(urb->pipe); if (usb_pipein(urb->pipe)) return dev->ep_in[ep_num]; else return dev->ep_out[ep_num]; }
static void timeout_kill(unsigned long data) { struct urb *urb = (struct urb *) data; dev_warn(&urb->dev->dev, "%s timeout on ep%d%s\n", usb_pipecontrol(urb->pipe) ? "control" : "bulk", usb_pipeendpoint(urb->pipe), usb_pipein(urb->pipe) ? "in" : "out"); usb_unlink_urb(urb); }