/* Return the polling or NAK interval. * * The polling interval is expressed in "microframes". If xHCI's Interval field * is set to N, it will service the endpoint every 2^(Interval)*125us. * * The NAK interval is one NAK per 1 to 255 microframes, or no NAKs if interval * is set to 0. */ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev, struct usb_host_endpoint *ep) { unsigned int interval = 0; switch (udev->speed) { case USB_SPEED_HIGH: /* Max NAK rate */ if (usb_endpoint_xfer_control(&ep->desc) || usb_endpoint_xfer_bulk(&ep->desc)) interval = ep->desc.bInterval; /* Fall through - SS and HS isoc/int have same decoding */ case USB_SPEED_SUPER: if (usb_endpoint_xfer_int(&ep->desc) || usb_endpoint_xfer_isoc(&ep->desc)) { if (ep->desc.bInterval == 0) interval = 0; else interval = ep->desc.bInterval - 1; if (interval > 15) interval = 15; if (interval != ep->desc.bInterval + 1) dev_warn(&udev->dev, "ep %#x - rounding interval to %d microframes\n", ep->desc.bEndpointAddress, 1 << interval); } break; /* Convert bInterval (in 1-255 frames) to microframes and round down to * nearest power of 2. */ case USB_SPEED_FULL: case USB_SPEED_LOW: if (usb_endpoint_xfer_int(&ep->desc) || usb_endpoint_xfer_isoc(&ep->desc)) { interval = fls(8*ep->desc.bInterval) - 1; if (interval > 10) interval = 10; if (interval < 3) interval = 3; if ((1 << interval) != 8*ep->desc.bInterval) dev_warn(&udev->dev, "ep %#x - rounding interval" " to %d microframes, " "ep desc says %d microframes\n", ep->desc.bEndpointAddress, 1 << interval, 8*ep->desc.bInterval); } break; default: BUG(); } return EP_INTERVAL(interval); }
static inline u32 xhci_get_endpoint_type(struct usb_device *udev, struct usb_host_endpoint *ep) { int in; u32 type; in = usb_endpoint_dir_in(&ep->desc); if (usb_endpoint_xfer_control(&ep->desc)) { type = EP_TYPE(CTRL_EP); } else if (usb_endpoint_xfer_bulk(&ep->desc)) { if (in) type = EP_TYPE(BULK_IN_EP); else type = EP_TYPE(BULK_OUT_EP); } else if (usb_endpoint_xfer_isoc(&ep->desc)) { if (in) type = EP_TYPE(ISOC_IN_EP); else type = EP_TYPE(ISOC_OUT_EP); } else if (usb_endpoint_xfer_int(&ep->desc)) { if (in) type = EP_TYPE(INT_IN_EP); else type = EP_TYPE(INT_OUT_EP); } else { BUG(); } return type; }
/* Return the polling or NAK interval. * * The polling interval is expressed in "microframes". If xHCI's Interval field * is set to N, it will service the endpoint every 2^(Interval)*125us. * * The NAK interval is one NAK per 1 to 255 microframes, or no NAKs if interval * is set to 0. */ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev, struct usb_host_endpoint *ep) { unsigned int interval = 0; switch (udev->speed) { case USB_SPEED_HIGH: /* Max NAK rate */ if (usb_endpoint_xfer_control(&ep->desc) || usb_endpoint_xfer_bulk(&ep->desc)) { interval = xhci_parse_microframe_interval(udev, ep); break; } /* Fall through - SS and HS isoc/int have same decoding */ case USB_SPEED_SUPER: if (usb_endpoint_xfer_int(&ep->desc) || usb_endpoint_xfer_isoc(&ep->desc)) { interval = xhci_parse_exponent_interval(udev, ep); } break; case USB_SPEED_FULL: if (usb_endpoint_xfer_isoc(&ep->desc)) { interval = xhci_parse_exponent_interval(udev, ep); break; } /* * Fall through for interrupt endpoint interval decoding * since it uses the same rules as low speed interrupt * endpoints. */ case USB_SPEED_LOW: if (usb_endpoint_xfer_int(&ep->desc) || usb_endpoint_xfer_isoc(&ep->desc)) { interval = xhci_parse_frame_interval(udev, ep); } break; default: BUG(); } return EP_INTERVAL(interval); }
static int get_pipe(struct stub_device *sdev, int epnum, int dir) { struct usb_device *udev = interface_to_usbdev(sdev->interface); struct usb_host_endpoint *ep; struct usb_endpoint_descriptor *epd = NULL; ep = get_ep_from_epnum(udev, epnum); if (!ep) { uerr("no such endpoint?, %d", epnum); BUG(); } epd = &ep->desc; #if 0 /* epnum 0 is always control */ if (epnum == 0) { if (dir == USBIP_DIR_OUT) return usb_sndctrlpipe(udev, 0); else return usb_rcvctrlpipe(udev, 0); } #endif if (usb_endpoint_xfer_control(epd)) { if (dir == USBIP_DIR_OUT) return usb_sndctrlpipe(udev, epnum); else return usb_rcvctrlpipe(udev, epnum); } if (usb_endpoint_xfer_bulk(epd)) { if (dir == USBIP_DIR_OUT) return usb_sndbulkpipe(udev, epnum); else return usb_rcvbulkpipe(udev, epnum); } if (usb_endpoint_xfer_int(epd)) { if (dir == USBIP_DIR_OUT) return usb_sndintpipe(udev, epnum); else return usb_rcvintpipe(udev, epnum); } if (usb_endpoint_xfer_isoc(epd)) { if (dir == USBIP_DIR_OUT) return usb_sndisocpipe(udev, epnum); else return usb_rcvisocpipe(udev, epnum); } /* NOT REACHED */ uerr("get pipe, epnum %d\n", epnum); return 0; }
/* handle a synchronous IN bulk/intr/iso transfer */ static ssize_t ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) { struct ep_data *data = fd->private_data; void *kbuf; ssize_t value; if ((value = get_ready_ep (fd->f_flags, data)) < 0) return value; /* halt any endpoint by doing a "wrong direction" i/o call */ if (!usb_endpoint_dir_in(&data->desc)) { if (usb_endpoint_xfer_isoc(&data->desc)) { mutex_unlock(&data->lock); return -EINVAL; } DBG (data->dev, "%s halt\n", data->name); spin_lock_irq (&data->dev->lock); if (likely (data->ep != NULL)) usb_ep_set_halt (data->ep); spin_unlock_irq (&data->dev->lock); mutex_unlock(&data->lock); return -EBADMSG; } /* FIXME writebehind for O_NONBLOCK and poll(), qlen = 1 */ value = -ENOMEM; kbuf = kmalloc (len, GFP_KERNEL); if (!kbuf) goto free1; if (copy_from_user (kbuf, buf, len)) { value = -EFAULT; goto free1; } value = ep_io (data, kbuf, len); VDEBUG (data->dev, "%s write %zu IN, status %d\n", data->name, len, (int) value); free1: mutex_unlock(&data->lock); kfree (kbuf); return value; }
/* handle a synchronous OUT bulk/intr/iso transfer */ static ssize_t ep_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) { struct ep_data *data = fd->private_data; void *kbuf; ssize_t value; if ((value = get_ready_ep (fd->f_flags, data)) < 0) return value; /* halt any endpoint by doing a "wrong direction" i/o call */ if (usb_endpoint_dir_in(&data->desc)) { if (usb_endpoint_xfer_isoc(&data->desc)) { mutex_unlock(&data->lock); return -EINVAL; } DBG (data->dev, "%s halt\n", data->name); spin_lock_irq (&data->dev->lock); if (likely (data->ep != NULL)) usb_ep_set_halt (data->ep); spin_unlock_irq (&data->dev->lock); mutex_unlock(&data->lock); return -EBADMSG; } /* FIXME readahead for O_NONBLOCK and poll(); careful with ZLPs */ value = -ENOMEM; kbuf = kmalloc (len, GFP_KERNEL); if (unlikely (!kbuf)) goto free1; value = ep_io (data, kbuf, len); VDEBUG (data->dev, "%s read %zu OUT, status %d\n", data->name, len, (int) value); if (value >= 0 && copy_to_user (buf, kbuf, value)) value = -EFAULT; free1: mutex_unlock(&data->lock); kfree (kbuf); return value; }
/* Configure an endpoint */ int bdc_config_ep(struct bdc *bdc, struct bdc_ep *ep) { const struct usb_ss_ep_comp_descriptor *comp_desc; const struct usb_endpoint_descriptor *desc; u32 param0, param1, param2, cmd_sc; u32 mps, mbs, mul, si; int ret; desc = ep->desc; comp_desc = ep->comp_desc; cmd_sc = mul = mbs = param2 = 0; param0 = lower_32_bits(ep->bd_list.bd_table_array[0]->dma); param1 = upper_32_bits(ep->bd_list.bd_table_array[0]->dma); cpu_to_le32s(¶m0); cpu_to_le32s(¶m1); dev_dbg(bdc->dev, "%s: param0=%08x param1=%08x", __func__, param0, param1); si = desc->bInterval; si = clamp_val(si, 1, 16) - 1; mps = usb_endpoint_maxp(desc); mps &= 0x7ff; param2 |= mps << MP_SHIFT; param2 |= usb_endpoint_type(desc) << EPT_SHIFT; switch (bdc->gadget.speed) { case USB_SPEED_SUPER: if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) { param2 |= si; if (usb_endpoint_xfer_isoc(desc) && comp_desc) mul = comp_desc->bmAttributes; } param2 |= mul << EPM_SHIFT; if (comp_desc) mbs = comp_desc->bMaxBurst; param2 |= mbs << MB_SHIFT; break; case USB_SPEED_HIGH: if (usb_endpoint_xfer_isoc(desc) || usb_endpoint_xfer_int(desc)) { param2 |= si; mbs = (usb_endpoint_maxp(desc) & 0x1800) >> 11; param2 |= mbs << MB_SHIFT; } break; case USB_SPEED_FULL: case USB_SPEED_LOW: /* the hardware accepts SI in 125usec range */ if (usb_endpoint_xfer_isoc(desc)) si += 3; /* * FS Int endpoints can have si of 1-255ms but the controller * accepts 2^bInterval*125usec, so convert ms to nearest power * of 2 */ if (usb_endpoint_xfer_int(desc)) si = fls(desc->bInterval * 8) - 1; param2 |= si; break; default: dev_err(bdc->dev, "UNKNOWN speed ERR\n"); return -EINVAL; }
static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id *devid) { struct usb_device *dev = interface_to_usbdev(intf); struct uvd *uvd = NULL; int ix, i, nas; int actInterface=-1, inactInterface=-1, maxPS=0; unsigned char video_ep = 0; DEBUG(1, "konicawc_probe(%p)", intf); /* We don't handle multi-config cameras */ if (dev->descriptor.bNumConfigurations != 1) return -ENODEV; dev_info(&intf->dev, "Konica Webcam (rev. 0x%04x)\n", le16_to_cpu(dev->descriptor.bcdDevice)); RESTRICT_TO_RANGE(speed, 0, MAX_SPEED); /* Validate found interface: must have one ISO endpoint */ nas = intf->num_altsetting; if (nas != 8) { err("Incorrect number of alternate settings (%d) for this camera!", nas); return -ENODEV; } /* Validate all alternate settings */ for (ix=0; ix < nas; ix++) { const struct usb_host_interface *interface; const struct usb_endpoint_descriptor *endpoint; interface = &intf->altsetting[ix]; i = interface->desc.bAlternateSetting; if (interface->desc.bNumEndpoints != 2) { err("Interface %d. has %u. endpoints!", interface->desc.bInterfaceNumber, (unsigned)(interface->desc.bNumEndpoints)); return -ENODEV; } endpoint = &interface->endpoint[1].desc; DEBUG(1, "found endpoint: addr: 0x%2.2x maxps = 0x%4.4x", endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize)); if (video_ep == 0) video_ep = endpoint->bEndpointAddress; else if (video_ep != endpoint->bEndpointAddress) { err("Alternate settings have different endpoint addresses!"); return -ENODEV; } if (!usb_endpoint_xfer_isoc(endpoint)) { err("Interface %d. has non-ISO endpoint!", interface->desc.bInterfaceNumber); return -ENODEV; } if (usb_endpoint_dir_out(endpoint)) { err("Interface %d. has ISO OUT endpoint!", interface->desc.bInterfaceNumber); return -ENODEV; } if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { if (inactInterface < 0) inactInterface = i; else { err("More than one inactive alt. setting!"); return -ENODEV; } } else { if (i == spd_to_iface[speed]) { /* This one is the requested one */ actInterface = i; } } if (le16_to_cpu(endpoint->wMaxPacketSize) > maxPS) maxPS = le16_to_cpu(endpoint->wMaxPacketSize); } if(actInterface == -1) { err("Cant find required endpoint"); return -ENODEV; } DEBUG(1, "Selecting requested active setting=%d. maxPS=%d.", actInterface, maxPS); uvd = usbvideo_AllocateDevice(cams); if (uvd != NULL) { struct konicawc *cam = (struct konicawc *)(uvd->user_data); /* Here uvd is a fully allocated uvd object */ for(i = 0; i < USBVIDEO_NUMSBUF; i++) { cam->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); if(cam->sts_urb[i] == NULL) { while(i--) { usb_free_urb(cam->sts_urb[i]); } err("can't allocate urbs"); return -ENOMEM; } } cam->speed = speed; RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240); cam->width = camera_sizes[size].width; cam->height = camera_sizes[size].height; cam->size = size; uvd->flags = 0; uvd->debug = debug; uvd->dev = dev; uvd->iface = intf->altsetting->desc.bInterfaceNumber; uvd->ifaceAltInactive = inactInterface; uvd->ifaceAltActive = actInterface; uvd->video_endp = video_ep; uvd->iso_packet_len = maxPS; uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P; uvd->defaultPalette = VIDEO_PALETTE_YUV420P; uvd->canvas = VIDEOSIZE(320, 240); uvd->videosize = VIDEOSIZE(cam->width, cam->height); /* Initialize konicawc specific data */ konicawc_configure_video(uvd); i = usbvideo_RegisterVideoDevice(uvd); uvd->max_frame_size = (320 * 240 * 3)/2; if (i != 0) { err("usbvideo_RegisterVideoDevice() failed."); uvd = NULL; } konicawc_register_input(cam, dev); } if (uvd) { usb_set_intfdata (intf, uvd); return 0; } return -EIO; }
static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, int asnum, struct usb_host_interface *ifp, int num_ep, unsigned char *buffer, int size) { unsigned char *buffer0 = buffer; struct usb_endpoint_descriptor *d; struct usb_host_endpoint *endpoint; int n, i, j; d = (struct usb_endpoint_descriptor *) buffer; buffer += d->bLength; size -= d->bLength; if (d->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE) n = USB_DT_ENDPOINT_AUDIO_SIZE; else if (d->bLength >= USB_DT_ENDPOINT_SIZE) n = USB_DT_ENDPOINT_SIZE; else { dev_warn(ddev, "config %d interface %d altsetting %d has an " "invalid endpoint descriptor of length %d, skipping\n", cfgno, inum, asnum, d->bLength); goto skip_to_next_endpoint_or_interface_descriptor; } i = d->bEndpointAddress & ~USB_ENDPOINT_DIR_MASK; if (i >= 16 || i == 0) { dev_warn(ddev, "config %d interface %d altsetting %d has an " "invalid endpoint with address 0x%X, skipping\n", cfgno, inum, asnum, d->bEndpointAddress); goto skip_to_next_endpoint_or_interface_descriptor; } /* Only store as many endpoints as we have room for */ if (ifp->desc.bNumEndpoints >= num_ep) goto skip_to_next_endpoint_or_interface_descriptor; endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints]; ++ifp->desc.bNumEndpoints; memcpy(&endpoint->desc, d, n); INIT_LIST_HEAD(&endpoint->urb_list); /* Fix up bInterval values outside the legal range. Use 32 ms if no * proper value can be guessed. */ i = 0; /* i = min, j = max, n = default */ j = 255; if (usb_endpoint_xfer_int(d)) { i = 1; switch (to_usb_device(ddev)->speed) { case USB_SPEED_HIGH: /* Many device manufacturers are using full-speed * bInterval values in high-speed interrupt endpoint * descriptors. Try to fix those and fall back to a * 32 ms default value otherwise. */ n = fls(d->bInterval*8); if (n == 0) n = 9; /* 32 ms = 2^(9-1) uframes */ j = 16; break; default: /* USB_SPEED_FULL or _LOW */ /* For low-speed, 10 ms is the official minimum. * But some "overclocked" devices might want faster * polling so we'll allow it. */ n = 32; break; } } else if (usb_endpoint_xfer_isoc(d)) { i = 1; j = 16; switch (to_usb_device(ddev)->speed) { case USB_SPEED_HIGH: n = 9; /* 32 ms = 2^(9-1) uframes */ break; default: /* USB_SPEED_FULL */ n = 6; /* 32 ms = 2^(6-1) frames */ break; } } if (d->bInterval < i || d->bInterval > j) { dev_warn(ddev, "config %d interface %d altsetting %d " "endpoint 0x%X has an invalid bInterval %d, " "changing to %d\n", cfgno, inum, asnum, d->bEndpointAddress, d->bInterval, n); endpoint->desc.bInterval = n; } /* Some buggy low-speed devices have Bulk endpoints, which is * explicitly forbidden by the USB spec. In an attempt to make * them usable, we will try treating them as Interrupt endpoints. */ if (to_usb_device(ddev)->speed == USB_SPEED_LOW && usb_endpoint_xfer_bulk(d)) { dev_warn(ddev, "config %d interface %d altsetting %d " "endpoint 0x%X is Bulk; changing to Interrupt\n", cfgno, inum, asnum, d->bEndpointAddress); endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT; endpoint->desc.bInterval = 1; if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8) endpoint->desc.wMaxPacketSize = cpu_to_le16(8); } /* Skip over any Class Specific or Vendor Specific descriptors; * find the next endpoint or interface descriptor */ endpoint->extra = buffer; i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, USB_DT_INTERFACE, &n); endpoint->extralen = i; if (n > 0) dev_dbg(ddev, "skipped %d descriptor%s after %s\n", n, plural(n), "endpoint"); return buffer - buffer0 + i; skip_to_next_endpoint_or_interface_descriptor: i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, USB_DT_INTERFACE, NULL); return buffer - buffer0 + i; }
static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, int inum, int asnum, struct usb_host_endpoint *ep, unsigned char *buffer, int size) { struct usb_ss_ep_comp_descriptor *desc; int max_tx; /* The SuperSpeed endpoint companion descriptor is supposed to * be the first thing immediately following the endpoint descriptor. */ desc = (struct usb_ss_ep_comp_descriptor *) buffer; if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP || size < USB_DT_SS_EP_COMP_SIZE) { dev_warn(ddev, "No SuperSpeed endpoint companion for config %d " " interface %d altsetting %d ep %d: " "using minimum values\n", cfgno, inum, asnum, ep->desc.bEndpointAddress); /* Fill in some default values. * Leave bmAttributes as zero, which will mean no streams for * bulk, and isoc won't support multiple bursts of packets. * With bursts of only one packet, and a Mult of 1, the max * amount of data moved per endpoint service interval is one * packet. */ ep->ss_ep_comp.bLength = USB_DT_SS_EP_COMP_SIZE; ep->ss_ep_comp.bDescriptorType = USB_DT_SS_ENDPOINT_COMP; if (usb_endpoint_xfer_isoc(&ep->desc) || usb_endpoint_xfer_int(&ep->desc)) ep->ss_ep_comp.wBytesPerInterval = ep->desc.wMaxPacketSize; return; } memcpy(&ep->ss_ep_comp, desc, USB_DT_SS_EP_COMP_SIZE); /* Check the various values */ if (usb_endpoint_xfer_control(&ep->desc) && desc->bMaxBurst != 0) { dev_warn(ddev, "Control endpoint with bMaxBurst = %d in " "config %d interface %d altsetting %d ep %d: " "setting to zero\n", desc->bMaxBurst, cfgno, inum, asnum, ep->desc.bEndpointAddress); ep->ss_ep_comp.bMaxBurst = 0; } else if (desc->bMaxBurst > 15) { dev_warn(ddev, "Endpoint with bMaxBurst = %d in " "config %d interface %d altsetting %d ep %d: " "setting to 15\n", desc->bMaxBurst, cfgno, inum, asnum, ep->desc.bEndpointAddress); ep->ss_ep_comp.bMaxBurst = 15; } if ((usb_endpoint_xfer_control(&ep->desc) || usb_endpoint_xfer_int(&ep->desc)) && desc->bmAttributes != 0) { dev_warn(ddev, "%s endpoint with bmAttributes = %d in " "config %d interface %d altsetting %d ep %d: " "setting to zero\n", usb_endpoint_xfer_control(&ep->desc) ? "Control" : "Bulk", desc->bmAttributes, cfgno, inum, asnum, ep->desc.bEndpointAddress); ep->ss_ep_comp.bmAttributes = 0; } else if (usb_endpoint_xfer_bulk(&ep->desc) && desc->bmAttributes > 16) { dev_warn(ddev, "Bulk endpoint with more than 65536 streams in " "config %d interface %d altsetting %d ep %d: " "setting to max\n", cfgno, inum, asnum, ep->desc.bEndpointAddress); ep->ss_ep_comp.bmAttributes = 16; } else if (usb_endpoint_xfer_isoc(&ep->desc) && desc->bmAttributes > 2) { dev_warn(ddev, "Isoc endpoint has Mult of %d in " "config %d interface %d altsetting %d ep %d: " "setting to 3\n", desc->bmAttributes + 1, cfgno, inum, asnum, ep->desc.bEndpointAddress); ep->ss_ep_comp.bmAttributes = 2; } if (usb_endpoint_xfer_isoc(&ep->desc)) max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) * usb_endpoint_maxp(&ep->desc); else if (usb_endpoint_xfer_int(&ep->desc)) max_tx = usb_endpoint_maxp(&ep->desc) * (desc->bMaxBurst + 1); else max_tx = 999999; if (le16_to_cpu(desc->wBytesPerInterval) > max_tx) { dev_warn(ddev, "%s endpoint with wBytesPerInterval of %d in " "config %d interface %d altsetting %d ep %d: " "setting to %d\n", usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int", le16_to_cpu(desc->wBytesPerInterval), cfgno, inum, asnum, ep->desc.bEndpointAddress, max_tx); ep->ss_ep_comp.wBytesPerInterval = cpu_to_le16(max_tx); } }
static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, int inum, int asnum, struct usb_host_endpoint *ep, int num_ep, unsigned char *buffer, int size) { unsigned char *buffer_start = buffer; struct usb_ss_ep_comp_descriptor *desc; int retval; int num_skipped; int max_tx; int i; desc = (struct usb_ss_ep_comp_descriptor *) buffer; if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) { dev_warn(ddev, "No SuperSpeed endpoint companion for config %d " " interface %d altsetting %d ep %d: " "using minimum values\n", cfgno, inum, asnum, ep->desc.bEndpointAddress); /* * The next descriptor is for an Endpoint or Interface, * no extra descriptors to copy into the companion structure, * and we didn't eat up any of the buffer. */ return 0; } memcpy(&ep->ss_ep_comp->desc, desc, USB_DT_SS_EP_COMP_SIZE); desc = &ep->ss_ep_comp->desc; buffer += desc->bLength; size -= desc->bLength; /* Eat up the other descriptors we don't care about */ ep->ss_ep_comp->extra = buffer; i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, USB_DT_INTERFACE, &num_skipped); ep->ss_ep_comp->extralen = i; buffer += i; size -= i; retval = buffer - buffer_start; if (num_skipped > 0) dev_dbg(ddev, "skipped %d descriptor%s after %s\n", num_skipped, plural(num_skipped), "SuperSpeed endpoint companion"); /* Check the various values */ if (usb_endpoint_xfer_control(&ep->desc) && desc->bMaxBurst != 0) { dev_warn(ddev, "Control endpoint with bMaxBurst = %d in " "config %d interface %d altsetting %d ep %d: " "setting to zero\n", desc->bMaxBurst, cfgno, inum, asnum, ep->desc.bEndpointAddress); desc->bMaxBurst = 0; } if (desc->bMaxBurst > 15) { dev_warn(ddev, "Endpoint with bMaxBurst = %d in " "config %d interface %d altsetting %d ep %d: " "setting to 15\n", desc->bMaxBurst, cfgno, inum, asnum, ep->desc.bEndpointAddress); desc->bMaxBurst = 15; } if ((usb_endpoint_xfer_control(&ep->desc) || usb_endpoint_xfer_int(&ep->desc)) && desc->bmAttributes != 0) { dev_warn(ddev, "%s endpoint with bmAttributes = %d in " "config %d interface %d altsetting %d ep %d: " "setting to zero\n", usb_endpoint_xfer_control(&ep->desc) ? "Control" : "Bulk", desc->bmAttributes, cfgno, inum, asnum, ep->desc.bEndpointAddress); desc->bmAttributes = 0; } if (usb_endpoint_xfer_bulk(&ep->desc) && desc->bmAttributes > 16) { dev_warn(ddev, "Bulk endpoint with more than 65536 streams in " "config %d interface %d altsetting %d ep %d: " "setting to max\n", cfgno, inum, asnum, ep->desc.bEndpointAddress); desc->bmAttributes = 16; } if (usb_endpoint_xfer_isoc(&ep->desc) && desc->bmAttributes > 2) { dev_warn(ddev, "Isoc endpoint has Mult of %d in " "config %d interface %d altsetting %d ep %d: " "setting to 3\n", desc->bmAttributes + 1, cfgno, inum, asnum, ep->desc.bEndpointAddress); desc->bmAttributes = 2; } if (usb_endpoint_xfer_isoc(&ep->desc)) { max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) * le16_to_cpu(ep->desc.wMaxPacketSize); } else if (usb_endpoint_xfer_int(&ep->desc)) { max_tx = le16_to_cpu(ep->desc.wMaxPacketSize) * (desc->bMaxBurst + 1); } else { goto valid; } if (le16_to_cpu(desc->wBytesPerInterval) > max_tx) { dev_warn(ddev, "%s endpoint with wBytesPerInterval of %d in " "config %d interface %d altsetting %d ep %d: " "setting to %d\n", usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int", le16_to_cpu(desc->wBytesPerInterval), cfgno, inum, asnum, ep->desc.bEndpointAddress, max_tx); desc->wBytesPerInterval = cpu_to_le16(max_tx); } valid: return retval; }
/* * non-error returns are a promise to giveback() the urb later * we drop ownership so next owner (or urb unlink) can get it */ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_td *buffer; unsigned long flags; int ret = 0; unsigned int slot_id, ep_index; struct urb_priv *urb_priv; int size, i; if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, true, __func__) <= 0) return -EINVAL; slot_id = urb->dev->slot_id; ep_index = xhci_get_endpoint_index(&urb->ep->desc); if (!HCD_HW_ACCESSIBLE(hcd)) { if (!in_interrupt()) xhci_dbg(xhci, "urb submitted during PCI suspend\n"); ret = -ESHUTDOWN; goto exit; } if (usb_endpoint_xfer_isoc(&urb->ep->desc)) size = urb->number_of_packets; else size = 1; urb_priv = kzalloc(sizeof(struct urb_priv) + size * sizeof(struct xhci_td *), mem_flags); if (!urb_priv) return -ENOMEM; buffer = kzalloc(size * sizeof(struct xhci_td), mem_flags); if (!buffer) { kfree(urb_priv); return -ENOMEM; } for (i = 0; i < size; i++) { urb_priv->td[i] = buffer; buffer++; } urb_priv->length = size; urb_priv->td_cnt = 0; urb->hcpriv = urb_priv; if (usb_endpoint_xfer_control(&urb->ep->desc)) { /* Check to see if the max packet size for the default control * endpoint changed during FS device enumeration */ if (urb->dev->speed == USB_SPEED_FULL) { ret = xhci_check_maxpacket(xhci, slot_id, ep_index, urb); if (ret < 0) { xhci_urb_free_priv(urb_priv); urb->hcpriv = NULL; return ret; } } /* We have a spinlock and interrupts disabled, so we must pass * atomic context to this function, which may allocate memory. */ spin_lock_irqsave(&xhci->lock, flags); if (xhci->xhc_state & XHCI_STATE_DYING) goto dying; ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); if (ret) goto free_priv; spin_unlock_irqrestore(&xhci->lock, flags); } else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) { spin_lock_irqsave(&xhci->lock, flags); if (xhci->xhc_state & XHCI_STATE_DYING) goto dying; if (xhci->devs[slot_id]->eps[ep_index].ep_state & EP_GETTING_STREAMS) { xhci_warn(xhci, "WARN: Can't enqueue URB while bulk ep " "is transitioning to using streams.\n"); ret = -EINVAL; } else if (xhci->devs[slot_id]->eps[ep_index].ep_state & EP_GETTING_NO_STREAMS) { xhci_warn(xhci, "WARN: Can't enqueue URB while bulk ep " "is transitioning to " "not having streams.\n"); ret = -EINVAL; } else { ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); } if (ret) goto free_priv; spin_unlock_irqrestore(&xhci->lock, flags); } else if (usb_endpoint_xfer_int(&urb->ep->desc)) { spin_lock_irqsave(&xhci->lock, flags); if (xhci->xhc_state & XHCI_STATE_DYING) goto dying; ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); if (ret) goto free_priv; spin_unlock_irqrestore(&xhci->lock, flags); } else { spin_lock_irqsave(&xhci->lock, flags); if (xhci->xhc_state & XHCI_STATE_DYING) goto dying; ret = xhci_queue_isoc_tx_prepare(xhci, GFP_ATOMIC, urb, slot_id, ep_index); if (ret) goto free_priv; spin_unlock_irqrestore(&xhci->lock, flags); } exit: return ret; dying: xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for " "non-responsive xHCI host.\n", urb->ep->desc.bEndpointAddress, urb); ret = -ESHUTDOWN; free_priv: xhci_urb_free_priv(urb_priv); urb->hcpriv = NULL; spin_unlock_irqrestore(&xhci->lock, flags); return ret; }
static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, int inum, int asnum, struct usb_host_endpoint *ep, unsigned char *buffer, int size) { struct usb_ss_ep_comp_descriptor *desc; int max_tx; desc = (struct usb_ss_ep_comp_descriptor *) buffer; if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP || size < USB_DT_SS_EP_COMP_SIZE) { dev_warn(ddev, "No SuperSpeed endpoint companion for config %d " " interface %d altsetting %d ep %d: " "using minimum values\n", cfgno, inum, asnum, ep->desc.bEndpointAddress); ep->ss_ep_comp.bLength = USB_DT_SS_EP_COMP_SIZE; ep->ss_ep_comp.bDescriptorType = USB_DT_SS_ENDPOINT_COMP; if (usb_endpoint_xfer_isoc(&ep->desc) || usb_endpoint_xfer_int(&ep->desc)) ep->ss_ep_comp.wBytesPerInterval = ep->desc.wMaxPacketSize; return; } memcpy(&ep->ss_ep_comp, desc, USB_DT_SS_EP_COMP_SIZE); if (usb_endpoint_xfer_control(&ep->desc) && desc->bMaxBurst != 0) { dev_warn(ddev, "Control endpoint with bMaxBurst = %d in " "config %d interface %d altsetting %d ep %d: " "setting to zero\n", desc->bMaxBurst, cfgno, inum, asnum, ep->desc.bEndpointAddress); ep->ss_ep_comp.bMaxBurst = 0; } else if (desc->bMaxBurst > 15) { dev_warn(ddev, "Endpoint with bMaxBurst = %d in " "config %d interface %d altsetting %d ep %d: " "setting to 15\n", desc->bMaxBurst, cfgno, inum, asnum, ep->desc.bEndpointAddress); ep->ss_ep_comp.bMaxBurst = 15; } if ((usb_endpoint_xfer_control(&ep->desc) || usb_endpoint_xfer_int(&ep->desc)) && desc->bmAttributes != 0) { dev_warn(ddev, "%s endpoint with bmAttributes = %d in " "config %d interface %d altsetting %d ep %d: " "setting to zero\n", usb_endpoint_xfer_control(&ep->desc) ? "Control" : "Bulk", desc->bmAttributes, cfgno, inum, asnum, ep->desc.bEndpointAddress); ep->ss_ep_comp.bmAttributes = 0; } else if (usb_endpoint_xfer_bulk(&ep->desc) && desc->bmAttributes > 16) { dev_warn(ddev, "Bulk endpoint with more than 65536 streams in " "config %d interface %d altsetting %d ep %d: " "setting to max\n", cfgno, inum, asnum, ep->desc.bEndpointAddress); ep->ss_ep_comp.bmAttributes = 16; } else if (usb_endpoint_xfer_isoc(&ep->desc) && desc->bmAttributes > 2) { dev_warn(ddev, "Isoc endpoint has Mult of %d in " "config %d interface %d altsetting %d ep %d: " "setting to 3\n", desc->bmAttributes + 1, cfgno, inum, asnum, ep->desc.bEndpointAddress); ep->ss_ep_comp.bmAttributes = 2; } if (usb_endpoint_xfer_isoc(&ep->desc)) max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) * usb_endpoint_maxp(&ep->desc); else if (usb_endpoint_xfer_int(&ep->desc)) max_tx = usb_endpoint_maxp(&ep->desc) * (desc->bMaxBurst + 1); else max_tx = 999999; if (le16_to_cpu(desc->wBytesPerInterval) > max_tx) { dev_warn(ddev, "%s endpoint with wBytesPerInterval of %d in " "config %d interface %d altsetting %d ep %d: " "setting to %d\n", usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int", le16_to_cpu(desc->wBytesPerInterval), cfgno, inum, asnum, ep->desc.bEndpointAddress, max_tx); ep->ss_ep_comp.wBytesPerInterval = cpu_to_le16(max_tx); } }
static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, int asnum, struct usb_host_interface *ifp, int num_ep, unsigned char *buffer, int size) { unsigned char *buffer0 = buffer; struct usb_endpoint_descriptor *d; struct usb_host_endpoint *endpoint; int n, i, j, retval; d = (struct usb_endpoint_descriptor *) buffer; buffer += d->bLength; size -= d->bLength; if (d->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE) n = USB_DT_ENDPOINT_AUDIO_SIZE; else if (d->bLength >= USB_DT_ENDPOINT_SIZE) n = USB_DT_ENDPOINT_SIZE; else { dev_warn(ddev, "config %d interface %d altsetting %d has an " "invalid endpoint descriptor of length %d, skipping\n", cfgno, inum, asnum, d->bLength); goto skip_to_next_endpoint_or_interface_descriptor; } i = d->bEndpointAddress & ~USB_ENDPOINT_DIR_MASK; if (i >= 16 || i == 0) { dev_warn(ddev, "config %d interface %d altsetting %d has an " "invalid endpoint with address 0x%X, skipping\n", cfgno, inum, asnum, d->bEndpointAddress); goto skip_to_next_endpoint_or_interface_descriptor; } if (ifp->desc.bNumEndpoints >= num_ep) goto skip_to_next_endpoint_or_interface_descriptor; endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints]; ++ifp->desc.bNumEndpoints; memcpy(&endpoint->desc, d, n); INIT_LIST_HEAD(&endpoint->urb_list); i = 0; j = 255; if (usb_endpoint_xfer_int(d)) { i = 1; switch (to_usb_device(ddev)->speed) { case USB_SPEED_SUPER: case USB_SPEED_HIGH: n = fls(d->bInterval*8); if (n == 0) n = 9; j = 16; break; default: n = 32; break; } } else if (usb_endpoint_xfer_isoc(d)) { i = 1; j = 16; switch (to_usb_device(ddev)->speed) { case USB_SPEED_HIGH: n = 9; break; default: n = 6; break; } } if (d->bInterval < i || d->bInterval > j) { dev_warn(ddev, "config %d interface %d altsetting %d " "endpoint 0x%X has an invalid bInterval %d, " "changing to %d\n", cfgno, inum, asnum, d->bEndpointAddress, d->bInterval, n); endpoint->desc.bInterval = n; } if (to_usb_device(ddev)->speed == USB_SPEED_LOW && usb_endpoint_xfer_bulk(d)) { dev_warn(ddev, "config %d interface %d altsetting %d " "endpoint 0x%X is Bulk; changing to Interrupt\n", cfgno, inum, asnum, d->bEndpointAddress); endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT; endpoint->desc.bInterval = 1; if (usb_endpoint_maxp(&endpoint->desc) > 8) endpoint->desc.wMaxPacketSize = cpu_to_le16(8); } if (to_usb_device(ddev)->speed == USB_SPEED_HIGH && usb_endpoint_xfer_bulk(d)) { unsigned maxp; maxp = usb_endpoint_maxp(&endpoint->desc) & 0x07ff; if (maxp != 512) dev_warn(ddev, "config %d interface %d altsetting %d " "bulk endpoint 0x%X has invalid maxpacket %d\n", cfgno, inum, asnum, d->bEndpointAddress, maxp); } if (to_usb_device(ddev)->speed == USB_SPEED_SUPER) usb_parse_ss_endpoint_companion(ddev, cfgno, inum, asnum, endpoint, buffer, size); endpoint->extra = buffer; i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, USB_DT_INTERFACE, &n); endpoint->extralen = i; retval = buffer - buffer0 + i; if (n > 0) dev_dbg(ddev, "skipped %d descriptor%s after %s\n", n, plural(n), "endpoint"); return retval; skip_to_next_endpoint_or_interface_descriptor: i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, USB_DT_INTERFACE, NULL); return buffer - buffer0 + i; }
/* * Aim an rpipe to its device & endpoint destination * * Make sure we change the address to unauthenticated if the device * is WUSB and it is not authenticated. */ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa, struct usb_host_endpoint *ep, struct urb *urb, gfp_t gfp) { int result = -ENOMSG; /* better code for lack of companion? */ struct device *dev = &wa->usb_iface->dev; struct usb_device *usb_dev = urb->dev; struct usb_wireless_ep_comp_descriptor *epcd; u32 ack_window, epcd_max_sequence; u8 unauth; epcd = rpipe_epc_find(dev, ep); if (epcd == NULL) { dev_err(dev, "ep 0x%02x: can't find companion descriptor\n", ep->desc.bEndpointAddress); goto error; } unauth = usb_dev->wusb && !usb_dev->authenticated ? 0x80 : 0; __rpipe_reset(wa, le16_to_cpu(rpipe->descr.wRPipeIndex)); atomic_set(&rpipe->segs_available, le16_to_cpu(rpipe->descr.wRequests)); /* FIXME: block allocation system; request with queuing and timeout */ /* FIXME: compute so seg_size > ep->maxpktsize */ rpipe->descr.wBlocks = cpu_to_le16(16); /* given */ /* ep0 maxpktsize is 0x200 (WUSB1.0[4.8.1]) */ if (usb_endpoint_xfer_isoc(&ep->desc)) rpipe->descr.wMaxPacketSize = epcd->wOverTheAirPacketSize; else rpipe->descr.wMaxPacketSize = ep->desc.wMaxPacketSize; rpipe->descr.hwa_bMaxBurst = max(min_t(unsigned int, epcd->bMaxBurst, 16U), 1U); rpipe->descr.hwa_bDeviceInfoIndex = wusb_port_no_to_idx(urb->dev->portnum); /* FIXME: use maximum speed as supported or recommended by device */ rpipe->descr.bSpeed = usb_pipeendpoint(urb->pipe) == 0 ? UWB_PHY_RATE_53 : UWB_PHY_RATE_200; dev_dbg(dev, "addr %u (0x%02x) rpipe #%u ep# %u speed %d\n", urb->dev->devnum, urb->dev->devnum | unauth, le16_to_cpu(rpipe->descr.wRPipeIndex), usb_pipeendpoint(urb->pipe), rpipe->descr.bSpeed); rpipe->descr.hwa_reserved = 0; rpipe->descr.bEndpointAddress = ep->desc.bEndpointAddress; /* FIXME: bDataSequence */ rpipe->descr.bDataSequence = 0; /* start with base window of hwa_bMaxBurst bits starting at 0. */ ack_window = 0xFFFFFFFF >> (32 - rpipe->descr.hwa_bMaxBurst); rpipe->descr.dwCurrentWindow = cpu_to_le32(ack_window); epcd_max_sequence = max(min_t(unsigned int, epcd->bMaxSequence, 32U), 2U); rpipe->descr.bMaxDataSequence = epcd_max_sequence - 1; rpipe->descr.bInterval = ep->desc.bInterval; if (usb_endpoint_xfer_isoc(&ep->desc)) rpipe->descr.bOverTheAirInterval = epcd->bOverTheAirInterval; else rpipe->descr.bOverTheAirInterval = 0; /* 0 if not isoc */ /* FIXME: xmit power & preamble blah blah */ rpipe->descr.bmAttribute = (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); /* rpipe->descr.bmCharacteristics RO */ rpipe->descr.bmRetryOptions = (wa->wusb->retry_count & 0xF); /* FIXME: use for assessing link quality? */ rpipe->descr.wNumTransactionErrors = 0; result = __rpipe_set_descr(wa, &rpipe->descr, le16_to_cpu(rpipe->descr.wRPipeIndex)); if (result < 0) { dev_err(dev, "Cannot aim rpipe: %d\n", result); goto error; } result = 0; error: return result; }
static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, int asnum, struct usb_host_interface *ifp, int num_ep, unsigned char *buffer, int size) { unsigned char *buffer0 = buffer; struct usb_endpoint_descriptor *d; struct usb_host_endpoint *endpoint; int n, i, j, retval; unsigned int maxp; const unsigned short *maxpacket_maxes; d = (struct usb_endpoint_descriptor *) buffer; buffer += d->bLength; size -= d->bLength; if (d->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE) n = USB_DT_ENDPOINT_AUDIO_SIZE; else if (d->bLength >= USB_DT_ENDPOINT_SIZE) n = USB_DT_ENDPOINT_SIZE; else { dev_warn(ddev, "config %d interface %d altsetting %d has an " "invalid endpoint descriptor of length %d, skipping\n", cfgno, inum, asnum, d->bLength); goto skip_to_next_endpoint_or_interface_descriptor; } i = d->bEndpointAddress & ~USB_ENDPOINT_DIR_MASK; if (i >= 16 || i == 0) { dev_warn(ddev, "config %d interface %d altsetting %d has an " "invalid endpoint with address 0x%X, skipping\n", cfgno, inum, asnum, d->bEndpointAddress); goto skip_to_next_endpoint_or_interface_descriptor; } /* Only store as many endpoints as we have room for */ if (ifp->desc.bNumEndpoints >= num_ep) goto skip_to_next_endpoint_or_interface_descriptor; endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints]; ++ifp->desc.bNumEndpoints; memcpy(&endpoint->desc, d, n); INIT_LIST_HEAD(&endpoint->urb_list); /* * Fix up bInterval values outside the legal range. * Use 10 or 8 ms if no proper value can be guessed. */ i = 0; /* i = min, j = max, n = default */ j = 255; if (usb_endpoint_xfer_int(d)) { i = 1; switch (to_usb_device(ddev)->speed) { case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: case USB_SPEED_HIGH: /* * Many device manufacturers are using full-speed * bInterval values in high-speed interrupt endpoint * descriptors. Try to fix those and fall back to an * 8-ms default value otherwise. */ n = fls(d->bInterval*8); if (n == 0) n = 7; /* 8 ms = 2^(7-1) uframes */ j = 16; /* * Adjust bInterval for quirked devices. * This quirk fixes bIntervals reported in * linear microframes. */ if (to_usb_device(ddev)->quirks & USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL) { n = clamp(fls(d->bInterval), i, j); i = j = n; } break; default: /* USB_SPEED_FULL or _LOW */ /* * For low-speed, 10 ms is the official minimum. * But some "overclocked" devices might want faster * polling so we'll allow it. */ n = 10; break; } } else if (usb_endpoint_xfer_isoc(d)) { i = 1; j = 16; switch (to_usb_device(ddev)->speed) { case USB_SPEED_HIGH: n = 7; /* 8 ms = 2^(7-1) uframes */ break; default: /* USB_SPEED_FULL */ n = 4; /* 8 ms = 2^(4-1) frames */ break; } } if (d->bInterval < i || d->bInterval > j) { dev_warn(ddev, "config %d interface %d altsetting %d " "endpoint 0x%X has an invalid bInterval %d, " "changing to %d\n", cfgno, inum, asnum, d->bEndpointAddress, d->bInterval, n); endpoint->desc.bInterval = n; } /* Some buggy low-speed devices have Bulk endpoints, which is * explicitly forbidden by the USB spec. In an attempt to make * them usable, we will try treating them as Interrupt endpoints. */ if (to_usb_device(ddev)->speed == USB_SPEED_LOW && usb_endpoint_xfer_bulk(d)) { dev_warn(ddev, "config %d interface %d altsetting %d " "endpoint 0x%X is Bulk; changing to Interrupt\n", cfgno, inum, asnum, d->bEndpointAddress); endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT; endpoint->desc.bInterval = 1; if (usb_endpoint_maxp(&endpoint->desc) > 8) endpoint->desc.wMaxPacketSize = cpu_to_le16(8); } /* Validate the wMaxPacketSize field */ maxp = usb_endpoint_maxp(&endpoint->desc); /* Find the highest legal maxpacket size for this endpoint */ i = 0; /* additional transactions per microframe */ switch (to_usb_device(ddev)->speed) { case USB_SPEED_LOW: maxpacket_maxes = low_speed_maxpacket_maxes; break; case USB_SPEED_FULL: maxpacket_maxes = full_speed_maxpacket_maxes; break; case USB_SPEED_HIGH: /* Bits 12..11 are allowed only for HS periodic endpoints */ if (usb_endpoint_xfer_int(d) || usb_endpoint_xfer_isoc(d)) { i = maxp & (BIT(12) | BIT(11)); maxp &= ~i; } /* fallthrough */ default: maxpacket_maxes = high_speed_maxpacket_maxes; break; case USB_SPEED_SUPER: case USB_SPEED_SUPER_PLUS: maxpacket_maxes = super_speed_maxpacket_maxes; break; } j = maxpacket_maxes[usb_endpoint_type(&endpoint->desc)]; if (maxp > j) { dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid maxpacket %d, setting to %d\n", cfgno, inum, asnum, d->bEndpointAddress, maxp, j); maxp = j; endpoint->desc.wMaxPacketSize = cpu_to_le16(i | maxp); } /* * Some buggy high speed devices have bulk endpoints using * maxpacket sizes other than 512. High speed HCDs may not * be able to handle that particular bug, so let's warn... */ if (to_usb_device(ddev)->speed == USB_SPEED_HIGH && usb_endpoint_xfer_bulk(d)) { if (maxp != 512) dev_warn(ddev, "config %d interface %d altsetting %d " "bulk endpoint 0x%X has invalid maxpacket %d\n", cfgno, inum, asnum, d->bEndpointAddress, maxp); } /* Parse a possible SuperSpeed endpoint companion descriptor */ if (to_usb_device(ddev)->speed >= USB_SPEED_SUPER) usb_parse_ss_endpoint_companion(ddev, cfgno, inum, asnum, endpoint, buffer, size); /* Skip over any Class Specific or Vendor Specific descriptors; * find the next endpoint or interface descriptor */ endpoint->extra = buffer; i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, USB_DT_INTERFACE, &n); endpoint->extralen = i; retval = buffer - buffer0 + i; if (n > 0) dev_dbg(ddev, "skipped %d descriptor%s after %s\n", n, plural(n), "endpoint"); return retval; skip_to_next_endpoint_or_interface_descriptor: i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, USB_DT_INTERFACE, NULL); return buffer - buffer0 + i; }
int xhci_endpoint_init(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_device *udev, struct usb_host_endpoint *ep, gfp_t mem_flags) { unsigned int ep_index; struct xhci_ep_ctx *ep_ctx; struct xhci_ring *ep_ring; unsigned int max_packet; unsigned int max_burst; ep_index = xhci_get_endpoint_index(&ep->desc); ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); /* Set up the endpoint ring */ virt_dev->eps[ep_index].new_ring = xhci_ring_alloc(xhci, 1, true, mem_flags); if (!virt_dev->eps[ep_index].new_ring) { /* Attempt to use the ring cache */ if (virt_dev->num_rings_cached == 0) return -ENOMEM; virt_dev->eps[ep_index].new_ring = virt_dev->ring_cache[virt_dev->num_rings_cached]; virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL; virt_dev->num_rings_cached--; xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring); } ep_ring = virt_dev->eps[ep_index].new_ring; ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state; ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep); /* FIXME dig Mult and streams info out of ep companion desc */ /* Allow 3 retries for everything but isoc; * error count = 0 means infinite retries. */ if (!usb_endpoint_xfer_isoc(&ep->desc)) ep_ctx->ep_info2 = ERROR_COUNT(3); else ep_ctx->ep_info2 = ERROR_COUNT(1); ep_ctx->ep_info2 |= xhci_get_endpoint_type(udev, ep); /* Set the max packet size and max burst */ switch (udev->speed) { case USB_SPEED_SUPER: max_packet = ep->desc.wMaxPacketSize; ep_ctx->ep_info2 |= MAX_PACKET(max_packet); /* dig out max burst from ep companion desc */ if (!ep->ss_ep_comp) { xhci_warn(xhci, "WARN no SS endpoint companion descriptor.\n"); max_packet = 0; } else { max_packet = ep->ss_ep_comp->desc.bMaxBurst; } ep_ctx->ep_info2 |= MAX_BURST(max_packet); break; case USB_SPEED_HIGH: /* bits 11:12 specify the number of additional transaction * opportunities per microframe (USB 2.0, section 9.6.6) */ if (usb_endpoint_xfer_isoc(&ep->desc) || usb_endpoint_xfer_int(&ep->desc)) { max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11; ep_ctx->ep_info2 |= MAX_BURST(max_burst); } /* Fall through */ case USB_SPEED_FULL: case USB_SPEED_LOW: max_packet = ep->desc.wMaxPacketSize & 0x3ff; ep_ctx->ep_info2 |= MAX_PACKET(max_packet); break; default: BUG(); }
/* * ultracam_probe() * * This procedure queries device descriptor and accepts the interface * if it looks like our camera. * * History: * 12-Nov-2000 Reworked to comply with new probe() signature. * 23-Jan-2001 Added compatibility with 2.2.x kernels. */ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id *devid) { struct usb_device *dev = interface_to_usbdev(intf); struct uvd *uvd = NULL; int ix, i, nas; int actInterface=-1, inactInterface=-1, maxPS=0; unsigned char video_ep = 0; if (debug >= 1) dev_info(&intf->dev, "ultracam_probe\n"); /* We don't handle multi-config cameras */ if (dev->descriptor.bNumConfigurations != 1) return -ENODEV; dev_info(&intf->dev, "IBM Ultra camera found (rev. 0x%04x)\n", le16_to_cpu(dev->descriptor.bcdDevice)); /* Validate found interface: must have one ISO endpoint */ nas = intf->num_altsetting; if (debug > 0) dev_info(&intf->dev, "Number of alternate settings=%d.\n", nas); if (nas < 8) { err("Too few alternate settings for this camera!"); return -ENODEV; } /* Validate all alternate settings */ for (ix=0; ix < nas; ix++) { const struct usb_host_interface *interface; const struct usb_endpoint_descriptor *endpoint; interface = &intf->altsetting[ix]; i = interface->desc.bAlternateSetting; if (interface->desc.bNumEndpoints != 1) { err("Interface %d. has %u. endpoints!", interface->desc.bInterfaceNumber, (unsigned)(interface->desc.bNumEndpoints)); return -ENODEV; } endpoint = &interface->endpoint[0].desc; if (video_ep == 0) video_ep = endpoint->bEndpointAddress; else if (video_ep != endpoint->bEndpointAddress) { err("Alternate settings have different endpoint addresses!"); return -ENODEV; } if (!usb_endpoint_xfer_isoc(endpoint)) { err("Interface %d. has non-ISO endpoint!", interface->desc.bInterfaceNumber); return -ENODEV; } if (usb_endpoint_dir_out(endpoint)) { err("Interface %d. has ISO OUT endpoint!", interface->desc.bInterfaceNumber); return -ENODEV; } if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { if (inactInterface < 0) inactInterface = i; else { err("More than one inactive alt. setting!"); return -ENODEV; } } else { if (actInterface < 0) { actInterface = i; maxPS = le16_to_cpu(endpoint->wMaxPacketSize); if (debug > 0) dev_info(&intf->dev, "Active setting=%d. " "maxPS=%d.\n", i, maxPS); } else { /* Got another active alt. setting */ if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) { /* This one is better! */ actInterface = i; maxPS = le16_to_cpu(endpoint->wMaxPacketSize); if (debug > 0) { dev_info(&intf->dev, "Even better ctive " "setting=%d. " "maxPS=%d.\n", i, maxPS); } } } } } if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) { err("Failed to recognize the camera!"); return -ENODEV; } uvd = usbvideo_AllocateDevice(cams); if (uvd != NULL) { /* Here uvd is a fully allocated uvd object */ uvd->flags = flags; uvd->debug = debug; uvd->dev = dev; uvd->iface = intf->altsetting->desc.bInterfaceNumber; uvd->ifaceAltInactive = inactInterface; uvd->ifaceAltActive = actInterface; uvd->video_endp = video_ep; uvd->iso_packet_len = maxPS; uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; uvd->defaultPalette = VIDEO_PALETTE_RGB24; uvd->canvas = VIDEOSIZE(640, 480); uvd->videosize = uvd->canvas; /* ultracam_size_to_videosize(size);*/ /* Initialize ibmcam-specific data */ assert(ULTRACAM_T(uvd) != NULL); ULTRACAM_T(uvd)->camera_model = 0; /* Not used yet */ ULTRACAM_T(uvd)->initialized = 0; ultracam_configure_video(uvd); i = usbvideo_RegisterVideoDevice(uvd); if (i != 0) { err("usbvideo_RegisterVideoDevice() failed."); uvd = NULL; } } if (uvd) { usb_set_intfdata (intf, uvd); return 0; } return -EIO; }
/* * Aim an rpipe to its device & endpoint destination * * Make sure we change the address to unauthenticathed if the device * is WUSB and it is not authenticated. */ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa, struct usb_host_endpoint *ep, struct urb *urb, gfp_t gfp) { int result = -ENOMSG; /* better code for lack of companion? */ struct device *dev = &wa->usb_iface->dev; struct usb_device *usb_dev = urb->dev; struct usb_wireless_ep_comp_descriptor *epcd; u8 unauth; epcd = rpipe_epc_find(dev, ep); if (epcd == NULL) { dev_err(dev, "ep 0x%02x: can't find companion descriptor\n", ep->desc.bEndpointAddress); goto error; } unauth = usb_dev->wusb && !usb_dev->authenticated ? 0x80 : 0; __rpipe_reset(wa, le16_to_cpu(rpipe->descr.wRPipeIndex)); atomic_set(&rpipe->segs_available, le16_to_cpu(rpipe->descr.wRequests)); /* FIXME: block allocation system; request with queuing and timeout */ /* FIXME: compute so seg_size > ep->maxpktsize */ rpipe->descr.wBlocks = cpu_to_le16(16); /* given */ /* ep0 maxpktsize is 0x200 (WUSB1.0[4.8.1]) */ if (usb_endpoint_xfer_isoc(&ep->desc)) rpipe->descr.wMaxPacketSize = epcd->wOverTheAirPacketSize; else rpipe->descr.wMaxPacketSize = ep->desc.wMaxPacketSize; rpipe->descr.bHSHubAddress = 0; /* reserved: zero */ rpipe->descr.bHSHubPort = wusb_port_no_to_idx(urb->dev->portnum); /* FIXME: use maximum speed as supported or recommended by device */ rpipe->descr.bSpeed = usb_pipeendpoint(urb->pipe) == 0 ? UWB_PHY_RATE_53 : UWB_PHY_RATE_200; dev_dbg(dev, "addr %u (0x%02x) rpipe #%u ep# %u speed %d\n", urb->dev->devnum, urb->dev->devnum | unauth, le16_to_cpu(rpipe->descr.wRPipeIndex), usb_pipeendpoint(urb->pipe), rpipe->descr.bSpeed); /* see security.c:wusb_update_address() */ if (unlikely(urb->dev->devnum == 0x80)) rpipe->descr.bDeviceAddress = 0; else rpipe->descr.bDeviceAddress = urb->dev->devnum | unauth; rpipe->descr.bEndpointAddress = ep->desc.bEndpointAddress; /* FIXME: bDataSequence */ rpipe->descr.bDataSequence = 0; /* FIXME: dwCurrentWindow */ rpipe->descr.dwCurrentWindow = cpu_to_le32(1); /* FIXME: bMaxDataSequence */ rpipe->descr.bMaxDataSequence = epcd->bMaxSequence - 1; rpipe->descr.bInterval = ep->desc.bInterval; /* FIXME: bOverTheAirInterval */ rpipe->descr.bOverTheAirInterval = 0; /* 0 if not isoc */ /* FIXME: xmit power & preamble blah blah */ rpipe->descr.bmAttribute = ep->desc.bmAttributes & 0x03; /* rpipe->descr.bmCharacteristics RO */ /* FIXME: bmRetryOptions */ rpipe->descr.bmRetryOptions = 15; /* FIXME: use for assessing link quality? */ rpipe->descr.wNumTransactionErrors = 0; result = __rpipe_set_descr(wa, &rpipe->descr, le16_to_cpu(rpipe->descr.wRPipeIndex)); if (result < 0) { dev_err(dev, "Cannot aim rpipe: %d\n", result); goto error; } result = 0; error: return result; }
static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, int asnum, struct usb_host_interface *ifp, int num_ep, unsigned char *buffer, int size) { unsigned char *buffer0 = buffer; struct usb_endpoint_descriptor *d; struct usb_host_endpoint *endpoint; int n, i, j, retval; d = (struct usb_endpoint_descriptor *) buffer; buffer += d->bLength; size -= d->bLength; if (d->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE) n = USB_DT_ENDPOINT_AUDIO_SIZE; else if (d->bLength >= USB_DT_ENDPOINT_SIZE) n = USB_DT_ENDPOINT_SIZE; else { dev_warn(ddev, "config %d interface %d altsetting %d has an " "invalid endpoint descriptor of length %d, skipping\n", cfgno, inum, asnum, d->bLength); goto skip_to_next_endpoint_or_interface_descriptor; } i = d->bEndpointAddress & ~USB_ENDPOINT_DIR_MASK; if (i >= 16 || i == 0) { dev_warn(ddev, "config %d interface %d altsetting %d has an " "invalid endpoint with address 0x%X, skipping\n", cfgno, inum, asnum, d->bEndpointAddress); goto skip_to_next_endpoint_or_interface_descriptor; } /* Only store as many endpoints as we have room for */ if (ifp->desc.bNumEndpoints >= num_ep) goto skip_to_next_endpoint_or_interface_descriptor; endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints]; ++ifp->desc.bNumEndpoints; memcpy(&endpoint->desc, d, n); INIT_LIST_HEAD(&endpoint->urb_list); /* Fix up bInterval values outside the legal range. Use 32 ms if no * proper value can be guessed. */ i = 0; /* i = min, j = max, n = default */ j = 255; if (usb_endpoint_xfer_int(d)) { i = 1; switch (to_usb_device(ddev)->speed) { case USB_SPEED_SUPER: case USB_SPEED_HIGH: /* Many device manufacturers are using full-speed * bInterval values in high-speed interrupt endpoint * descriptors. Try to fix those and fall back to a * 32 ms default value otherwise. */ n = fls(d->bInterval*8); if (n == 0) n = 9; /* 32 ms = 2^(9-1) uframes */ j = 16; break; default: /* USB_SPEED_FULL or _LOW */ /* For low-speed, 10 ms is the official minimum. * But some "overclocked" devices might want faster * polling so we'll allow it. */ n = 32; break; } } else if (usb_endpoint_xfer_isoc(d)) { i = 1; j = 16; switch (to_usb_device(ddev)->speed) { case USB_SPEED_HIGH: n = 9; /* 32 ms = 2^(9-1) uframes */ break; default: /* USB_SPEED_FULL */ n = 6; /* 32 ms = 2^(6-1) frames */ break; } } if (d->bInterval < i || d->bInterval > j) { dev_warn(ddev, "config %d interface %d altsetting %d " "endpoint 0x%X has an invalid bInterval %d, " "changing to %d\n", cfgno, inum, asnum, d->bEndpointAddress, d->bInterval, n); endpoint->desc.bInterval = n; } /* Some buggy low-speed devices have Bulk endpoints, which is * explicitly forbidden by the USB spec. In an attempt to make * them usable, we will try treating them as Interrupt endpoints. */ if (to_usb_device(ddev)->speed == USB_SPEED_LOW && usb_endpoint_xfer_bulk(d)) { dev_warn(ddev, "config %d interface %d altsetting %d " "endpoint 0x%X is Bulk; changing to Interrupt\n", cfgno, inum, asnum, d->bEndpointAddress); endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT; endpoint->desc.bInterval = 1; if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8) endpoint->desc.wMaxPacketSize = cpu_to_le16(8); } /* * Some buggy high speed devices have bulk endpoints using * maxpacket sizes other than 512. High speed HCDs may not * be able to handle that particular bug, so let's warn... */ if (to_usb_device(ddev)->speed == USB_SPEED_HIGH && usb_endpoint_xfer_bulk(d)) { unsigned maxp; maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize) & 0x07ff; if (maxp != 512) dev_warn(ddev, "config %d interface %d altsetting %d " "bulk endpoint 0x%X has invalid maxpacket %d\n", cfgno, inum, asnum, d->bEndpointAddress, maxp); } /* Allocate room for and parse any SS endpoint companion descriptors */ if (to_usb_device(ddev)->speed == USB_SPEED_SUPER) { endpoint->extra = buffer; i = find_next_descriptor_more(buffer, size, USB_DT_SS_ENDPOINT_COMP, USB_DT_ENDPOINT, USB_DT_INTERFACE, &n); endpoint->extralen = i; buffer += i; size -= i; /* Allocate space for the SS endpoint companion descriptor */ endpoint->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp), GFP_KERNEL); if (!endpoint->ss_ep_comp) return -ENOMEM; /* Fill in some default values (may be overwritten later) */ endpoint->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE; endpoint->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP; endpoint->ss_ep_comp->desc.bMaxBurst = 0; /* * Leave bmAttributes as zero, which will mean no streams for * bulk, and isoc won't support multiple bursts of packets. * With bursts of only one packet, and a Mult of 1, the max * amount of data moved per endpoint service interval is one * packet. */ if (usb_endpoint_xfer_isoc(&endpoint->desc) || usb_endpoint_xfer_int(&endpoint->desc)) endpoint->ss_ep_comp->desc.wBytesPerInterval = endpoint->desc.wMaxPacketSize; if (size > 0) { retval = usb_parse_ss_endpoint_companion(ddev, cfgno, inum, asnum, endpoint, num_ep, buffer, size); if (retval >= 0) { buffer += retval; retval = buffer - buffer0; } } else { dev_warn(ddev, "config %d interface %d altsetting %d " "endpoint 0x%X has no " "SuperSpeed companion descriptor\n", cfgno, inum, asnum, d->bEndpointAddress); retval = buffer - buffer0; } } else { /* Skip over any Class Specific or Vendor Specific descriptors; * find the next endpoint or interface descriptor */ endpoint->extra = buffer; i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, USB_DT_INTERFACE, &n); endpoint->extralen = i; retval = buffer - buffer0 + i; } if (n > 0) dev_dbg(ddev, "skipped %d descriptor%s after %s\n", n, plural(n), "endpoint"); return retval; skip_to_next_endpoint_or_interface_descriptor: i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, USB_DT_INTERFACE, NULL); return buffer - buffer0 + i; }