Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (229 commits)
  USB: remove unused usb_buffer_alloc and usb_buffer_free macros
  usb: musb: update gfp/slab.h includes
  USB: ftdi_sio: fix legacy SIO-device header
  USB: kl5usb105: reimplement using generic framework
  USB: kl5usb105: minor clean ups
  USB: kl5usb105: fix memory leak
  USB: io_ti: use kfifo to implement write buffering
  USB: io_ti: remove unsused private counter
  USB: ti_usb: use kfifo to implement write buffering
  USB: ir-usb: fix incorrect write-buffer length
  USB: aircable: fix incorrect write-buffer length
  USB: safe_serial: straighten out read processing
  USB: safe_serial: reimplement read using generic framework
  USB: safe_serial: reimplement write using generic framework
  usb-storage: always print quirks
  USB: usb-storage: trivial debug improvements
  USB: oti6858: use port write fifo
  USB: oti6858: use kfifo to implement write buffering
  USB: cypress_m8: use kfifo to implement write buffering
  USB: cypress_m8: remove unused drain define
  ...

Fix up conflicts (due to usb_buffer_alloc/free renaming) in
	drivers/input/tablet/acecad.c
	drivers/input/tablet/kbtab.c
	drivers/input/tablet/wacom_sys.c
	drivers/media/video/gspca/gspca.c
	sound/usb/usbaudio.c
This commit is contained in:
Linus Torvalds 2010-05-20 21:26:12 -07:00
commit 7a9b149212
261 changed files with 17242 additions and 8360 deletions

View file

@ -783,13 +783,12 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
{
struct usbhid_device *usbhid = hid->driver_data;
usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
usbhid->inbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
&usbhid->inbuf_dma);
usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
usbhid->outbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
&usbhid->outbuf_dma);
usbhid->cr = usb_buffer_alloc(dev, sizeof(*usbhid->cr), GFP_KERNEL,
&usbhid->cr_dma);
usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
usbhid->cr = kmalloc(sizeof(*usbhid->cr), GFP_KERNEL);
usbhid->ctrlbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
&usbhid->ctrlbuf_dma);
if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr ||
!usbhid->ctrlbuf)
@ -844,10 +843,10 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
{
struct usbhid_device *usbhid = hid->driver_data;
usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
usb_free_coherent(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
usb_free_coherent(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
kfree(usbhid->cr);
usb_free_coherent(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
}
static int usbhid_parse(struct hid_device *hid)
@ -1007,9 +1006,8 @@ static int usbhid_start(struct hid_device *hid)
usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr,
usbhid->ctrlbuf, 1, hid_ctrl, hid);
usbhid->urbctrl->setup_dma = usbhid->cr_dma;
usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
usbhid->urbctrl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS))
usbhid_init_reports(hid);

View file

@ -75,7 +75,6 @@ struct usbhid_device {
struct urb *urbctrl; /* Control URB */
struct usb_ctrlrequest *cr; /* Control request struct */
dma_addr_t cr_dma; /* Control request struct dma */
struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */
unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */
char *ctrlbuf; /* Control buffer */

View file

@ -74,7 +74,6 @@ struct usb_kbd {
unsigned char *new;
struct usb_ctrlrequest *cr;
unsigned char *leds;
dma_addr_t cr_dma;
dma_addr_t new_dma;
dma_addr_t leds_dma;
};
@ -197,11 +196,11 @@ static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
return -1;
if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL)))
return -1;
if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma)))
if (!(kbd->new = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &kbd->new_dma)))
return -1;
if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), GFP_ATOMIC, &kbd->cr_dma)))
if (!(kbd->cr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
return -1;
if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma)))
if (!(kbd->leds = usb_alloc_coherent(dev, 1, GFP_ATOMIC, &kbd->leds_dma)))
return -1;
return 0;
@ -211,9 +210,9 @@ static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
{
usb_free_urb(kbd->irq);
usb_free_urb(kbd->led);
usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma);
usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma);
usb_free_coherent(dev, 8, kbd->new, kbd->new_dma);
kfree(kbd->cr);
usb_free_coherent(dev, 1, kbd->leds, kbd->leds_dma);
}
static int usb_kbd_probe(struct usb_interface *iface,
@ -304,9 +303,8 @@ static int usb_kbd_probe(struct usb_interface *iface,
usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
(void *) kbd->cr, kbd->leds, 1,
usb_kbd_led, kbd);
kbd->led->setup_dma = kbd->cr_dma;
kbd->led->transfer_dma = kbd->leds_dma;
kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
kbd->led->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
error = input_register_device(kbd->dev);
if (error)

View file

@ -142,7 +142,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
if (!mouse || !input_dev)
goto fail1;
mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma);
mouse->data = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &mouse->data_dma);
if (!mouse->data)
goto fail1;
@ -205,7 +205,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
fail3:
usb_free_urb(mouse->irq);
fail2:
usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
usb_free_coherent(dev, 8, mouse->data, mouse->data_dma);
fail1:
input_free_device(input_dev);
kfree(mouse);
@ -221,7 +221,7 @@ static void usb_mouse_disconnect(struct usb_interface *intf)
usb_kill_urb(mouse->irq);
input_unregister_device(mouse->dev);
usb_free_urb(mouse->irq);
usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);
usb_free_coherent(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);
kfree(mouse);
}
}

View file

@ -533,8 +533,8 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
return 0;
xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN,
GFP_KERNEL, &xpad->odata_dma);
xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
GFP_KERNEL, &xpad->odata_dma);
if (!xpad->odata)
goto fail1;
@ -554,7 +554,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
return 0;
fail2: usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
fail2: usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
fail1: return error;
}
@ -568,7 +568,7 @@ static void xpad_deinit_output(struct usb_xpad *xpad)
{
if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) {
usb_free_urb(xpad->irq_out);
usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
xpad->odata, xpad->odata_dma);
}
}
@ -788,8 +788,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
if (!xpad || !input_dev)
goto fail1;
xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
GFP_KERNEL, &xpad->idata_dma);
xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN,
GFP_KERNEL, &xpad->idata_dma);
if (!xpad->idata)
goto fail1;
@ -942,7 +942,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
fail5: usb_kill_urb(xpad->irq_in);
fail4: usb_free_urb(xpad->irq_in);
fail3: xpad_deinit_output(xpad);
fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
fail2: usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
fail1: input_free_device(input_dev);
kfree(xpad);
return error;
@ -964,7 +964,7 @@ static void xpad_disconnect(struct usb_interface *intf)
usb_kill_urb(xpad->irq_in);
}
usb_free_urb(xpad->irq_in);
usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
xpad->idata, xpad->idata_dma);
kfree(xpad);
}

View file

@ -624,13 +624,13 @@ static void ati_remote_irq_in(struct urb *urb)
static int ati_remote_alloc_buffers(struct usb_device *udev,
struct ati_remote *ati_remote)
{
ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC,
&ati_remote->inbuf_dma);
ati_remote->inbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
&ati_remote->inbuf_dma);
if (!ati_remote->inbuf)
return -1;
ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC,
&ati_remote->outbuf_dma);
ati_remote->outbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
&ati_remote->outbuf_dma);
if (!ati_remote->outbuf)
return -1;
@ -653,10 +653,10 @@ static void ati_remote_free_buffers(struct ati_remote *ati_remote)
usb_free_urb(ati_remote->irq_urb);
usb_free_urb(ati_remote->out_urb);
usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
ati_remote->inbuf, ati_remote->inbuf_dma);
usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
ati_remote->outbuf, ati_remote->outbuf_dma);
}

View file

@ -589,7 +589,7 @@ static int ati_remote2_urb_init(struct ati_remote2 *ar2)
int i, pipe, maxp;
for (i = 0; i < 2; i++) {
ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]);
ar2->buf[i] = usb_alloc_coherent(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]);
if (!ar2->buf[i])
return -ENOMEM;
@ -617,7 +617,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2)
for (i = 0; i < 2; i++) {
usb_free_urb(ar2->urb[i]);
usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
usb_free_coherent(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
}
}

View file

@ -102,7 +102,6 @@ struct cm109_dev {
struct cm109_ctl_packet *ctl_data;
dma_addr_t ctl_dma;
struct usb_ctrlrequest *ctl_req;
dma_addr_t ctl_req_dma;
struct urb *urb_ctl;
/*
* The 3 bitfields below are protected by ctl_submit_lock.
@ -629,15 +628,13 @@ static const struct usb_device_id cm109_usb_table[] = {
static void cm109_usb_cleanup(struct cm109_dev *dev)
{
if (dev->ctl_req)
usb_buffer_free(dev->udev, sizeof(*(dev->ctl_req)),
dev->ctl_req, dev->ctl_req_dma);
kfree(dev->ctl_req);
if (dev->ctl_data)
usb_buffer_free(dev->udev, USB_PKT_LEN,
dev->ctl_data, dev->ctl_dma);
usb_free_coherent(dev->udev, USB_PKT_LEN,
dev->ctl_data, dev->ctl_dma);
if (dev->irq_data)
usb_buffer_free(dev->udev, USB_PKT_LEN,
dev->irq_data, dev->irq_dma);
usb_free_coherent(dev->udev, USB_PKT_LEN,
dev->irq_data, dev->irq_dma);
usb_free_urb(dev->urb_irq); /* parameter validation in core/urb */
usb_free_urb(dev->urb_ctl); /* parameter validation in core/urb */
@ -686,18 +683,17 @@ static int cm109_usb_probe(struct usb_interface *intf,
goto err_out;
/* allocate usb buffers */
dev->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN,
GFP_KERNEL, &dev->irq_dma);
dev->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN,
GFP_KERNEL, &dev->irq_dma);
if (!dev->irq_data)
goto err_out;
dev->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN,
GFP_KERNEL, &dev->ctl_dma);
dev->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN,
GFP_KERNEL, &dev->ctl_dma);
if (!dev->ctl_data)
goto err_out;
dev->ctl_req = usb_buffer_alloc(udev, sizeof(*(dev->ctl_req)),
GFP_KERNEL, &dev->ctl_req_dma);
dev->ctl_req = kmalloc(sizeof(*(dev->ctl_req)), GFP_KERNEL);
if (!dev->ctl_req)
goto err_out;
@ -735,10 +731,8 @@ static int cm109_usb_probe(struct usb_interface *intf,
usb_fill_control_urb(dev->urb_ctl, udev, usb_sndctrlpipe(udev, 0),
(void *)dev->ctl_req, dev->ctl_data, USB_PKT_LEN,
cm109_urb_ctl_callback, dev);
dev->urb_ctl->setup_dma = dev->ctl_req_dma;
dev->urb_ctl->transfer_dma = dev->ctl_dma;
dev->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP |
URB_NO_TRANSFER_DMA_MAP;
dev->urb_ctl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
dev->urb_ctl->dev = udev;
/* find out the physical bus location */

View file

@ -464,7 +464,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
remote->in_endpoint = endpoint;
remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */
remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma);
remote->in_buffer = usb_alloc_coherent(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma);
if (!remote->in_buffer) {
error = -ENOMEM;
goto fail1;
@ -543,7 +543,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
return 0;
fail3: usb_free_urb(remote->irq_urb);
fail2: usb_buffer_free(udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
fail2: usb_free_coherent(udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
fail1: kfree(remote);
input_free_device(input_dev);
@ -564,7 +564,7 @@ static void keyspan_disconnect(struct usb_interface *interface)
input_unregister_device(remote->input);
usb_kill_urb(remote->irq_urb);
usb_free_urb(remote->irq_urb);
usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
usb_free_coherent(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
kfree(remote);
}
}

View file

@ -64,7 +64,6 @@ struct powermate_device {
dma_addr_t data_dma;
struct urb *irq, *config;
struct usb_ctrlrequest *configcr;
dma_addr_t configcr_dma;
struct usb_device *udev;
struct input_dev *input;
spinlock_t lock;
@ -182,8 +181,6 @@ static void powermate_sync_state(struct powermate_device *pm)
usb_fill_control_urb(pm->config, pm->udev, usb_sndctrlpipe(pm->udev, 0),
(void *) pm->configcr, NULL, 0,
powermate_config_complete, pm);
pm->config->setup_dma = pm->configcr_dma;
pm->config->transfer_flags |= URB_NO_SETUP_DMA_MAP;
if (usb_submit_urb(pm->config, GFP_ATOMIC))
printk(KERN_ERR "powermate: usb_submit_urb(config) failed");
@ -276,13 +273,12 @@ static int powermate_input_event(struct input_dev *dev, unsigned int type, unsig
static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm)
{
pm->data = usb_buffer_alloc(udev, POWERMATE_PAYLOAD_SIZE_MAX,
GFP_ATOMIC, &pm->data_dma);
pm->data = usb_alloc_coherent(udev, POWERMATE_PAYLOAD_SIZE_MAX,
GFP_ATOMIC, &pm->data_dma);
if (!pm->data)
return -1;
pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)),
GFP_ATOMIC, &pm->configcr_dma);
pm->configcr = kmalloc(sizeof(*(pm->configcr)), GFP_KERNEL);
if (!pm->configcr)
return -1;
@ -291,10 +287,9 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev
static void powermate_free_buffers(struct usb_device *udev, struct powermate_device *pm)
{
usb_buffer_free(udev, POWERMATE_PAYLOAD_SIZE_MAX,
pm->data, pm->data_dma);
usb_buffer_free(udev, sizeof(*(pm->configcr)),
pm->configcr, pm->configcr_dma);
usb_free_coherent(udev, POWERMATE_PAYLOAD_SIZE_MAX,
pm->data, pm->data_dma);
kfree(pm->configcr);
}
/* Called whenever a USB device matching one in our supported devices table is connected */

View file

@ -111,7 +111,6 @@ struct yealink_dev {
struct yld_ctl_packet *ctl_data;
dma_addr_t ctl_dma;
struct usb_ctrlrequest *ctl_req;
dma_addr_t ctl_req_dma;
struct urb *urb_ctl;
char phys[64]; /* physical device path */
@ -836,12 +835,9 @@ static int usb_cleanup(struct yealink_dev *yld, int err)
usb_free_urb(yld->urb_irq);
usb_free_urb(yld->urb_ctl);
usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)),
yld->ctl_req, yld->ctl_req_dma);
usb_buffer_free(yld->udev, USB_PKT_LEN,
yld->ctl_data, yld->ctl_dma);
usb_buffer_free(yld->udev, USB_PKT_LEN,
yld->irq_data, yld->irq_dma);
kfree(yld->ctl_req);
usb_free_coherent(yld->udev, USB_PKT_LEN, yld->ctl_data, yld->ctl_dma);
usb_free_coherent(yld->udev, USB_PKT_LEN, yld->irq_data, yld->irq_dma);
kfree(yld);
return err;
@ -886,18 +882,17 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
return usb_cleanup(yld, -ENOMEM);
/* allocate usb buffers */
yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN,
GFP_ATOMIC, &yld->irq_dma);
yld->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN,
GFP_ATOMIC, &yld->irq_dma);
if (yld->irq_data == NULL)
return usb_cleanup(yld, -ENOMEM);
yld->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN,
GFP_ATOMIC, &yld->ctl_dma);
yld->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN,
GFP_ATOMIC, &yld->ctl_dma);
if (!yld->ctl_data)
return usb_cleanup(yld, -ENOMEM);
yld->ctl_req = usb_buffer_alloc(udev, sizeof(*(yld->ctl_req)),
GFP_ATOMIC, &yld->ctl_req_dma);
yld->ctl_req = kmalloc(sizeof(*(yld->ctl_req)), GFP_KERNEL);
if (yld->ctl_req == NULL)
return usb_cleanup(yld, -ENOMEM);
@ -936,10 +931,8 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
usb_fill_control_urb(yld->urb_ctl, udev, usb_sndctrlpipe(udev, 0),
(void *)yld->ctl_req, yld->ctl_data, USB_PKT_LEN,
urb_ctl_callback, yld);
yld->urb_ctl->setup_dma = yld->ctl_req_dma;
yld->urb_ctl->transfer_dma = yld->ctl_dma;
yld->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP |
URB_NO_TRANSFER_DMA_MAP;
yld->urb_ctl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
yld->urb_ctl->dev = udev;
/* find out the physical bus location */

View file

@ -806,8 +806,8 @@ static int atp_probe(struct usb_interface *iface,
if (!dev->urb)
goto err_free_devs;
dev->data = usb_buffer_alloc(dev->udev, dev->info->datalen, GFP_KERNEL,
&dev->urb->transfer_dma);
dev->data = usb_alloc_coherent(dev->udev, dev->info->datalen, GFP_KERNEL,
&dev->urb->transfer_dma);
if (!dev->data)
goto err_free_urb;
@ -862,8 +862,8 @@ static int atp_probe(struct usb_interface *iface,
return 0;
err_free_buffer:
usb_buffer_free(dev->udev, dev->info->datalen,
dev->data, dev->urb->transfer_dma);
usb_free_coherent(dev->udev, dev->info->datalen,
dev->data, dev->urb->transfer_dma);
err_free_urb:
usb_free_urb(dev->urb);
err_free_devs:
@ -881,8 +881,8 @@ static void atp_disconnect(struct usb_interface *iface)
if (dev) {
usb_kill_urb(dev->urb);
input_unregister_device(dev->input);
usb_buffer_free(dev->udev, dev->info->datalen,
dev->data, dev->urb->transfer_dma);
usb_free_coherent(dev->udev, dev->info->datalen,
dev->data, dev->urb->transfer_dma);
usb_free_urb(dev->urb);
kfree(dev);
}

View file

@ -715,15 +715,15 @@ static int bcm5974_probe(struct usb_interface *iface,
if (!dev->tp_urb)
goto err_free_bt_urb;
dev->bt_data = usb_buffer_alloc(dev->udev,
dev->cfg.bt_datalen, GFP_KERNEL,
&dev->bt_urb->transfer_dma);
dev->bt_data = usb_alloc_coherent(dev->udev,
dev->cfg.bt_datalen, GFP_KERNEL,
&dev->bt_urb->transfer_dma);
if (!dev->bt_data)
goto err_free_urb;
dev->tp_data = usb_buffer_alloc(dev->udev,
dev->cfg.tp_datalen, GFP_KERNEL,
&dev->tp_urb->transfer_dma);
dev->tp_data = usb_alloc_coherent(dev->udev,
dev->cfg.tp_datalen, GFP_KERNEL,
&dev->tp_urb->transfer_dma);
if (!dev->tp_data)
goto err_free_bt_buffer;
@ -765,10 +765,10 @@ static int bcm5974_probe(struct usb_interface *iface,
return 0;
err_free_buffer:
usb_buffer_free(dev->udev, dev->cfg.tp_datalen,
usb_free_coherent(dev->udev, dev->cfg.tp_datalen,
dev->tp_data, dev->tp_urb->transfer_dma);
err_free_bt_buffer:
usb_buffer_free(dev->udev, dev->cfg.bt_datalen,
usb_free_coherent(dev->udev, dev->cfg.bt_datalen,
dev->bt_data, dev->bt_urb->transfer_dma);
err_free_urb:
usb_free_urb(dev->tp_urb);
@ -788,10 +788,10 @@ static void bcm5974_disconnect(struct usb_interface *iface)
usb_set_intfdata(iface, NULL);
input_unregister_device(dev->input);
usb_buffer_free(dev->udev, dev->cfg.tp_datalen,
dev->tp_data, dev->tp_urb->transfer_dma);
usb_buffer_free(dev->udev, dev->cfg.bt_datalen,
dev->bt_data, dev->bt_urb->transfer_dma);
usb_free_coherent(dev->udev, dev->cfg.tp_datalen,
dev->tp_data, dev->tp_urb->transfer_dma);
usb_free_coherent(dev->udev, dev->cfg.bt_datalen,
dev->bt_data, dev->bt_urb->transfer_dma);
usb_free_urb(dev->tp_urb);
usb_free_urb(dev->bt_urb);
kfree(dev);

View file

@ -155,7 +155,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
goto fail1;
}
acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma);
acecad->data = usb_alloc_coherent(dev, 8, GFP_KERNEL, &acecad->data_dma);
if (!acecad->data) {
err= -ENOMEM;
goto fail1;
@ -235,7 +235,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
return 0;
fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma);
fail2: usb_free_coherent(dev, 8, acecad->data, acecad->data_dma);
fail1: input_free_device(input_dev);
kfree(acecad);
return err;
@ -249,7 +249,7 @@ static void usb_acecad_disconnect(struct usb_interface *intf)
input_unregister_device(acecad->input);
usb_free_urb(acecad->irq);
usb_buffer_free(acecad->usbdev, 8, acecad->data, acecad->data_dma);
usb_free_coherent(acecad->usbdev, 8, acecad->data, acecad->data_dma);
kfree(acecad);
}

View file

@ -1711,8 +1711,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
goto fail1;
}
aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,
GFP_ATOMIC, &aiptek->data_dma);
aiptek->data = usb_alloc_coherent(usbdev, AIPTEK_PACKET_LENGTH,
GFP_ATOMIC, &aiptek->data_dma);
if (!aiptek->data) {
dev_warn(&intf->dev, "cannot allocate usb buffer\n");
goto fail1;
@ -1884,8 +1884,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
fail4: sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
fail3: usb_free_urb(aiptek->urb);
fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
aiptek->data_dma);
fail2: usb_free_coherent(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
aiptek->data_dma);
fail1: usb_set_intfdata(intf, NULL);
input_free_device(inputdev);
kfree(aiptek);
@ -1909,9 +1909,9 @@ static void aiptek_disconnect(struct usb_interface *intf)
input_unregister_device(aiptek->inputdev);
sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
usb_free_urb(aiptek->urb);
usb_buffer_free(interface_to_usbdev(intf),
AIPTEK_PACKET_LENGTH,
aiptek->data, aiptek->data_dma);
usb_free_coherent(interface_to_usbdev(intf),
AIPTEK_PACKET_LENGTH,
aiptek->data, aiptek->data_dma);
kfree(aiptek);
}
}

View file

@ -850,8 +850,8 @@ static int gtco_probe(struct usb_interface *usbinterface,
gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface));
/* Allocate some data for incoming reports */
gtco->buffer = usb_buffer_alloc(gtco->usbdev, REPORT_MAX_SIZE,
GFP_KERNEL, &gtco->buf_dma);
gtco->buffer = usb_alloc_coherent(gtco->usbdev, REPORT_MAX_SIZE,
GFP_KERNEL, &gtco->buf_dma);
if (!gtco->buffer) {
err("No more memory for us buffers");
error = -ENOMEM;
@ -982,8 +982,8 @@ static int gtco_probe(struct usb_interface *usbinterface,
err_free_urb:
usb_free_urb(gtco->urbinfo);
err_free_buf:
usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE,
gtco->buffer, gtco->buf_dma);
usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE,
gtco->buffer, gtco->buf_dma);
err_free_devs:
input_free_device(input_dev);
kfree(gtco);
@ -1005,8 +1005,8 @@ static void gtco_disconnect(struct usb_interface *interface)
input_unregister_device(gtco->inputdevice);
usb_kill_urb(gtco->urbinfo);
usb_free_urb(gtco->urbinfo);
usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE,
gtco->buffer, gtco->buf_dma);
usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE,
gtco->buffer, gtco->buf_dma);
kfree(gtco);
}

View file

@ -122,7 +122,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
if (!kbtab || !input_dev)
goto fail1;
kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma);
kbtab->data = usb_alloc_coherent(dev, 8, GFP_KERNEL, &kbtab->data_dma);
if (!kbtab->data)
goto fail1;
@ -173,7 +173,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
return 0;
fail3: usb_free_urb(kbtab->irq);
fail2: usb_buffer_free(dev, 8, kbtab->data, kbtab->data_dma);
fail2: usb_free_coherent(dev, 8, kbtab->data, kbtab->data_dma);
fail1: input_free_device(input_dev);
kfree(kbtab);
return error;
@ -187,7 +187,7 @@ static void kbtab_disconnect(struct usb_interface *intf)
input_unregister_device(kbtab->dev);
usb_free_urb(kbtab->irq);
usb_buffer_free(kbtab->usbdev, 8, kbtab->data, kbtab->data_dma);
usb_free_coherent(kbtab->usbdev, 8, kbtab->data, kbtab->data_dma);
kfree(kbtab);
}

View file

@ -465,8 +465,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
goto fail1;
}
wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX,
GFP_KERNEL, &wacom->data_dma);
wacom_wac->data = usb_alloc_coherent(dev, WACOM_PKGLEN_MAX,
GFP_KERNEL, &wacom->data_dma);
if (!wacom_wac->data) {
error = -ENOMEM;
goto fail1;
@ -536,7 +536,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
fail4: wacom_remove_shared_data(wacom_wac);
fail3: usb_free_urb(wacom->irq);
fail2: usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
fail1: input_free_device(input_dev);
kfree(wacom);
return error;
@ -551,7 +551,7 @@ static void wacom_disconnect(struct usb_interface *intf)
usb_kill_urb(wacom->irq);
input_unregister_device(wacom->wacom_wac.input);
usb_free_urb(wacom->irq);
usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
wacom->wacom_wac.data, wacom->data_dma);
wacom_remove_shared_data(&wacom->wacom_wac);
kfree(wacom);

View file

@ -1290,8 +1290,8 @@ static void usbtouch_close(struct input_dev *input)
static void usbtouch_free_buffers(struct usb_device *udev,
struct usbtouch_usb *usbtouch)
{
usb_buffer_free(udev, usbtouch->type->rept_size,
usbtouch->data, usbtouch->data_dma);
usb_free_coherent(udev, usbtouch->type->rept_size,
usbtouch->data, usbtouch->data_dma);
kfree(usbtouch->buffer);
}
@ -1335,8 +1335,8 @@ static int usbtouch_probe(struct usb_interface *intf,
if (!type->process_pkt)
type->process_pkt = usbtouch_process_pkt;
usbtouch->data = usb_buffer_alloc(udev, type->rept_size,
GFP_KERNEL, &usbtouch->data_dma);
usbtouch->data = usb_alloc_coherent(udev, type->rept_size,
GFP_KERNEL, &usbtouch->data_dma);
if (!usbtouch->data)
goto out_free;

View file

@ -96,8 +96,9 @@ static int usb_free_stream_buffers(struct usb_data_stream *stream)
while (stream->buf_num) {
stream->buf_num--;
deb_mem("freeing buffer %d\n",stream->buf_num);
usb_buffer_free(stream->udev, stream->buf_size,
stream->buf_list[stream->buf_num], stream->dma_addr[stream->buf_num]);
usb_free_coherent(stream->udev, stream->buf_size,
stream->buf_list[stream->buf_num],
stream->dma_addr[stream->buf_num]);
}
}
@ -116,7 +117,7 @@ static int usb_allocate_stream_buffers(struct usb_data_stream *stream, int num,
for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {
deb_mem("allocating buffer %d\n",stream->buf_num);
if (( stream->buf_list[stream->buf_num] =
usb_buffer_alloc(stream->udev, size, GFP_ATOMIC,
usb_alloc_coherent(stream->udev, size, GFP_ATOMIC,
&stream->dma_addr[stream->buf_num]) ) == NULL) {
deb_mem("not enough memory for urb-buffer allocation.\n");
usb_free_stream_buffers(stream);

View file

@ -1257,7 +1257,7 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec)
if(!dec->irq_urb) {
return -ENOMEM;
}
dec->irq_buffer = usb_buffer_alloc(dec->udev,IRQ_PACKET_SIZE,
dec->irq_buffer = usb_alloc_coherent(dec->udev,IRQ_PACKET_SIZE,
GFP_ATOMIC, &dec->irq_dma_handle);
if(!dec->irq_buffer) {
usb_free_urb(dec->irq_urb);
@ -1550,8 +1550,8 @@ static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
usb_free_urb(dec->irq_urb);
usb_buffer_free(dec->udev,IRQ_PACKET_SIZE,
dec->irq_buffer, dec->irq_dma_handle);
usb_free_coherent(dec->udev,IRQ_PACKET_SIZE,
dec->irq_buffer, dec->irq_dma_handle);
if (dec->rc_input_dev) {
input_unregister_device(dec->rc_input_dev);

View file

@ -177,7 +177,7 @@ void au0828_uninit_isoc(struct au0828_dev *dev)
usb_unlink_urb(urb);
if (dev->isoc_ctl.transfer_buffer[i]) {
usb_buffer_free(dev->usbdev,
usb_free_coherent(dev->usbdev,
urb->transfer_buffer_length,
dev->isoc_ctl.transfer_buffer[i],
urb->transfer_dma);
@ -247,7 +247,7 @@ int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
}
dev->isoc_ctl.urb[i] = urb;
dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->usbdev,
dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev,
sb_size, GFP_KERNEL, &urb->transfer_dma);
if (!dev->isoc_ctl.transfer_buffer[i]) {
printk("unable to allocate %i bytes for transfer"

View file

@ -676,11 +676,11 @@ void cx231xx_uninit_isoc(struct cx231xx *dev)
usb_unlink_urb(urb);
if (dev->video_mode.isoc_ctl.transfer_buffer[i]) {
usb_buffer_free(dev->udev,
urb->transfer_buffer_length,
dev->video_mode.isoc_ctl.
transfer_buffer[i],
urb->transfer_dma);
usb_free_coherent(dev->udev,
urb->transfer_buffer_length,
dev->video_mode.isoc_ctl.
transfer_buffer[i],
urb->transfer_dma);
}
usb_free_urb(urb);
dev->video_mode.isoc_ctl.urb[i] = NULL;
@ -767,8 +767,8 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
dev->video_mode.isoc_ctl.urb[i] = urb;
dev->video_mode.isoc_ctl.transfer_buffer[i] =
usb_buffer_alloc(dev->udev, sb_size, GFP_KERNEL,
&urb->transfer_dma);
usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
&urb->transfer_dma);
if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) {
cx231xx_err("unable to allocate %i bytes for transfer"
" buffer %i%s\n",

View file

@ -970,7 +970,7 @@ void em28xx_uninit_isoc(struct em28xx *dev)
usb_unlink_urb(urb);
if (dev->isoc_ctl.transfer_buffer[i]) {
usb_buffer_free(dev->udev,
usb_free_coherent(dev->udev,
urb->transfer_buffer_length,
dev->isoc_ctl.transfer_buffer[i],
urb->transfer_dma);
@ -1045,7 +1045,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
}
dev->isoc_ctl.urb[i] = urb;
dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev,
dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev,
sb_size, GFP_KERNEL, &urb->transfer_dma);
if (!dev->isoc_ctl.transfer_buffer[i]) {
em28xx_err("unable to allocate %i bytes for transfer"

View file

@ -117,13 +117,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
return -ENOMEM;
}
gspca_dev->urb[n] = urb;
urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
SD_PKT_SZ * SD_NPKT,
GFP_KERNEL,
&urb->transfer_dma);
if (urb->transfer_buffer == NULL) {
err("usb_buffer_alloc failed");
err("usb_alloc_coherent failed");
return -ENOMEM;
}
urb->dev = gspca_dev->dev;

View file

@ -213,7 +213,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
goto error;
}
buffer = usb_buffer_alloc(dev, buffer_len,
buffer = usb_alloc_coherent(dev, buffer_len,
GFP_KERNEL, &urb->transfer_dma);
if (!buffer) {
ret = -ENOMEM;
@ -232,10 +232,10 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
return ret;
error_submit:
usb_buffer_free(dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);
usb_free_coherent(dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);
error_buffer:
usb_free_urb(urb);
error:
@ -272,10 +272,10 @@ static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev)
if (urb) {
gspca_dev->int_urb = NULL;
usb_kill_urb(urb);
usb_buffer_free(gspca_dev->dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);
usb_free_coherent(gspca_dev->dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);
usb_free_urb(urb);
}
}
@ -605,10 +605,10 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
gspca_dev->urb[i] = NULL;
usb_kill_urb(urb);
if (urb->transfer_buffer != NULL)
usb_buffer_free(gspca_dev->dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);
usb_free_coherent(gspca_dev->dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);
usb_free_urb(urb);
}
}
@ -760,13 +760,13 @@ static int create_urbs(struct gspca_dev *gspca_dev,
return -ENOMEM;
}
gspca_dev->urb[n] = urb;
urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
bsize,
GFP_KERNEL,
&urb->transfer_dma);
if (urb->transfer_buffer == NULL) {
err("usb_buffer_alloc failed");
err("usb_alloc_coherent failed");
return -ENOMEM;
}
urb->dev = gspca_dev->dev;

View file

@ -92,8 +92,8 @@ static int hdpvr_free_queue(struct list_head *q)
buf = list_entry(p, struct hdpvr_buffer, buff_list);
urb = buf->urb;
usb_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
usb_free_coherent(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
usb_free_urb(urb);
tmp = p->next;
list_del(p);
@ -143,8 +143,8 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count)
}
buf->urb = urb;
mem = usb_buffer_alloc(dev->udev, dev->bulk_in_size, GFP_KERNEL,
&urb->transfer_dma);
mem = usb_alloc_coherent(dev->udev, dev->bulk_in_size, GFP_KERNEL,
&urb->transfer_dma);
if (!mem) {
v4l2_err(&dev->v4l2_dev,
"cannot allocate usb transfer buffer\n");

View file

@ -454,8 +454,8 @@ static int poseidon_probe(struct usb_interface *interface,
device_init_wakeup(&udev->dev, 1);
#ifdef CONFIG_PM
pd->udev->autosuspend_disabled = 0;
pd->udev->autosuspend_delay = HZ * PM_SUSPEND_DELAY;
usb_enable_autosuspend(pd->udev);
if (in_hibernation(pd)) {
INIT_WORK(&pd->pm_work, hibernation_resume);

View file

@ -478,10 +478,10 @@ static int prepare_iso_urb(struct video_data *video)
goto out;
video->urb_array[i] = urb;
mem = usb_buffer_alloc(udev,
ISO_PKT_SIZE * PK_PER_URB,
GFP_KERNEL,
&urb->transfer_dma);
mem = usb_alloc_coherent(udev,
ISO_PKT_SIZE * PK_PER_URB,
GFP_KERNEL,
&urb->transfer_dma);
urb->complete = urb_complete_iso; /* handler */
urb->dev = udev;
@ -521,8 +521,8 @@ int alloc_bulk_urbs_generic(struct urb **urb_array, int num,
if (urb == NULL)
return i;
mem = usb_buffer_alloc(udev, buf_size, gfp_flags,
&urb->transfer_dma);
mem = usb_alloc_coherent(udev, buf_size, gfp_flags,
&urb->transfer_dma);
if (mem == NULL)
return i;
@ -542,7 +542,7 @@ void free_all_urb_generic(struct urb **urb_array, int num)
for (i = 0; i < num; i++) {
urb = urb_array[i];
if (urb) {
usb_buffer_free(urb->dev,
usb_free_coherent(urb->dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);

View file

@ -2493,10 +2493,10 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
}
usbvision->sbuf[bufIdx].urb = urb;
usbvision->sbuf[bufIdx].data =
usb_buffer_alloc(usbvision->dev,
sb_size,
GFP_KERNEL,
&urb->transfer_dma);
usb_alloc_coherent(usbvision->dev,
sb_size,
GFP_KERNEL,
&urb->transfer_dma);
urb->dev = dev;
urb->context = usbvision;
urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);
@ -2552,10 +2552,10 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
usb_kill_urb(usbvision->sbuf[bufIdx].urb);
if (usbvision->sbuf[bufIdx].data){
usb_buffer_free(usbvision->dev,
sb_size,
usbvision->sbuf[bufIdx].data,
usbvision->sbuf[bufIdx].urb->transfer_dma);
usb_free_coherent(usbvision->dev,
sb_size,
usbvision->sbuf[bufIdx].data,
usbvision->sbuf[bufIdx].urb->transfer_dma);
}
usb_free_urb(usbvision->sbuf[bufIdx].urb);
usbvision->sbuf[bufIdx].urb = NULL;

View file

@ -739,7 +739,7 @@ static void uvc_free_urb_buffers(struct uvc_streaming *stream)
for (i = 0; i < UVC_URBS; ++i) {
if (stream->urb_buffer[i]) {
usb_buffer_free(stream->dev->udev, stream->urb_size,
usb_free_coherent(stream->dev->udev, stream->urb_size,
stream->urb_buffer[i], stream->urb_dma[i]);
stream->urb_buffer[i] = NULL;
}
@ -780,7 +780,7 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream,
for (; npackets > 1; npackets /= 2) {
for (i = 0; i < UVC_URBS; ++i) {
stream->urb_size = psize * npackets;
stream->urb_buffer[i] = usb_buffer_alloc(
stream->urb_buffer[i] = usb_alloc_coherent(
stream->dev->udev, stream->urb_size,
gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]);
if (!stream->urb_buffer[i]) {

View file

@ -512,8 +512,8 @@ static void ems_usb_write_bulk_callback(struct urb *urb)
netdev = dev->netdev;
/* free up our allocated buffer */
usb_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
usb_free_coherent(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
atomic_dec(&dev->active_tx_urbs);
@ -610,8 +610,8 @@ static int ems_usb_start(struct ems_usb *dev)
return -ENOMEM;
}
buf = usb_buffer_alloc(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
&urb->transfer_dma);
buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
&urb->transfer_dma);
if (!buf) {
dev_err(netdev->dev.parent,
"No memory left for USB buffer\n");
@ -631,8 +631,8 @@ static int ems_usb_start(struct ems_usb *dev)
netif_device_detach(dev->netdev);
usb_unanchor_urb(urb);
usb_buffer_free(dev->udev, RX_BUFFER_SIZE, buf,
urb->transfer_dma);
usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
urb->transfer_dma);
break;
}
@ -773,7 +773,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
goto nomem;
}
buf = usb_buffer_alloc(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma);
buf = usb_alloc_coherent(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma);
if (!buf) {
dev_err(netdev->dev.parent, "No memory left for USB buffer\n");
usb_free_urb(urb);
@ -816,7 +816,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
*/
if (!context) {
usb_unanchor_urb(urb);
usb_buffer_free(dev->udev, size, buf, urb->transfer_dma);
usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
dev_warn(netdev->dev.parent, "couldn't find free context\n");
@ -841,7 +841,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
can_free_echo_skb(netdev, context->echo_index);
usb_unanchor_urb(urb);
usb_buffer_free(dev->udev, size, buf, urb->transfer_dma);
usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
dev_kfree_skb(skb);
atomic_dec(&dev->active_tx_urbs);

View file

@ -128,17 +128,13 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone)
if (rx_urb == NULL)
goto free_tx_urb;
tx_buf = usb_buffer_alloc(iphone->udev,
IPHETH_BUF_SIZE,
GFP_KERNEL,
&tx_urb->transfer_dma);
tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE,
GFP_KERNEL, &tx_urb->transfer_dma);
if (tx_buf == NULL)
goto free_rx_urb;
rx_buf = usb_buffer_alloc(iphone->udev,
IPHETH_BUF_SIZE,
GFP_KERNEL,
&rx_urb->transfer_dma);
rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE,
GFP_KERNEL, &rx_urb->transfer_dma);
if (rx_buf == NULL)
goto free_tx_buf;
@ -150,8 +146,8 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone)
return 0;
free_tx_buf:
usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, tx_buf,
tx_urb->transfer_dma);
usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, tx_buf,
tx_urb->transfer_dma);
free_rx_urb:
usb_free_urb(rx_urb);
free_tx_urb:
@ -162,10 +158,10 @@ error_nomem:
static void ipheth_free_urbs(struct ipheth_device *iphone)
{
usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, iphone->rx_buf,
iphone->rx_urb->transfer_dma);
usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf,
iphone->tx_urb->transfer_dma);
usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->rx_buf,
iphone->rx_urb->transfer_dma);
usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf,
iphone->tx_urb->transfer_dma);
usb_free_urb(iphone->rx_urb);
usb_free_urb(iphone->tx_urb);
}

View file

@ -1155,13 +1155,13 @@ err_fw:
if (!kaweth->irq_urb)
goto err_tx_and_rx;
kaweth->intbuffer = usb_buffer_alloc( kaweth->dev,
kaweth->intbuffer = usb_alloc_coherent( kaweth->dev,
INTBUFFERSIZE,
GFP_KERNEL,
&kaweth->intbufferhandle);
if (!kaweth->intbuffer)
goto err_tx_and_rx_and_irq;
kaweth->rx_buf = usb_buffer_alloc( kaweth->dev,
kaweth->rx_buf = usb_alloc_coherent( kaweth->dev,
KAWETH_BUF_SIZE,
GFP_KERNEL,
&kaweth->rxbufferhandle);
@ -1202,9 +1202,9 @@ err_fw:
err_intfdata:
usb_set_intfdata(intf, NULL);
usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle);
usb_free_coherent(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle);
err_all_but_rxbuf:
usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle);
usb_free_coherent(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle);
err_tx_and_rx_and_irq:
usb_free_urb(kaweth->irq_urb);
err_tx_and_rx:
@ -1241,8 +1241,8 @@ static void kaweth_disconnect(struct usb_interface *intf)
usb_free_urb(kaweth->tx_urb);
usb_free_urb(kaweth->irq_urb);
usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle);
usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle);
usb_free_coherent(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle);
usb_free_coherent(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle);
free_netdev(netdev);
}

View file

@ -514,7 +514,7 @@ int i2400mu_probe(struct usb_interface *iface,
iface->needs_remote_wakeup = 1; /* autosuspend (15s delay) */
device_init_wakeup(dev, 1);
usb_dev->autosuspend_delay = 15 * HZ;
usb_dev->autosuspend_disabled = 0;
usb_enable_autosuspend(usb_dev);
#endif
result = i2400m_setup(i2400m, I2400M_BRI_MAC_REINIT);

View file

@ -215,7 +215,7 @@ resubmit:
return;
free:
usb_buffer_free(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma);
usb_free_coherent(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma);
}
static void ar9170_usb_rx_completed(struct urb *urb)
@ -296,7 +296,7 @@ static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru)
if (!urb)
goto out;
ibuf = usb_buffer_alloc(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma);
ibuf = usb_alloc_coherent(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma);
if (!ibuf)
goto out;
@ -309,8 +309,8 @@ static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru)
err = usb_submit_urb(urb, GFP_KERNEL);
if (err) {
usb_unanchor_urb(urb);
usb_buffer_free(aru->udev, 64, urb->transfer_buffer,
urb->transfer_dma);
usb_free_coherent(aru->udev, 64, urb->transfer_buffer,
urb->transfer_dma);
}
out:

View file

@ -664,15 +664,15 @@ static struct urb *alloc_rx_urb(struct zd_usb *usb)
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return NULL;
buffer = usb_buffer_alloc(udev, USB_MAX_RX_SIZE, GFP_KERNEL,
&urb->transfer_dma);
buffer = usb_alloc_coherent(udev, USB_MAX_RX_SIZE, GFP_KERNEL,
&urb->transfer_dma);
if (!buffer) {
usb_free_urb(urb);
return NULL;
}
usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, EP_DATA_IN),
buffer, USB_MAX_RX_SIZE,
buffer, USB_MAX_RX_SIZE,
rx_urb_complete, usb);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@ -683,8 +683,8 @@ static void free_rx_urb(struct urb *urb)
{
if (!urb)
return;
usb_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
usb_free_coherent(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
usb_free_urb(urb);
}

View file

@ -81,8 +81,8 @@ extern u8 EpToQueue[6];
#define RT28XX_PUT_DEVICE usb_put_dev
#define RTUSB_ALLOC_URB(iso) usb_alloc_urb(iso, GFP_ATOMIC)
#define RTUSB_SUBMIT_URB(pUrb) usb_submit_urb(pUrb, GFP_ATOMIC)
#define RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr) usb_buffer_alloc(pUsb_Dev, BufSize, GFP_ATOMIC, pDma_addr)
#define RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) usb_buffer_free(pUsb_Dev, BufSize, pTransferBuf, Dma_addr)
#define RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr) usb_alloc_coherent(pUsb_Dev, BufSize, GFP_ATOMIC, pDma_addr)
#define RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) usb_free_coherent(pUsb_Dev, BufSize, pTransferBuf, Dma_addr)
#define RTUSB_FREE_URB(pUrb) usb_free_urb(pUrb)

View file

@ -1508,8 +1508,8 @@ static void dlfb_free_urb_list(struct dlfb_data *dev)
urb = unode->urb;
/* Free each separately allocated piece */
usb_buffer_free(urb->dev, dev->urbs.size,
urb->transfer_buffer, urb->transfer_dma);
usb_free_coherent(urb->dev, dev->urbs.size,
urb->transfer_buffer, urb->transfer_dma);
usb_free_urb(urb);
kfree(node);
}
@ -1543,8 +1543,8 @@ static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
}
unode->urb = urb;
buf = usb_buffer_alloc(dev->udev, MAX_TRANSFER, GFP_KERNEL,
&urb->transfer_dma);
buf = usb_alloc_coherent(dev->udev, MAX_TRANSFER, GFP_KERNEL,
&urb->transfer_dma);
if (!buf) {
kfree(unode);
usb_free_urb(urb);

View file

@ -21,7 +21,7 @@
#include "usbip_common.h"
#include "stub.h"
#include "../../usb/core/hcd.h"
#include <linux/usb/hcd.h>
static int is_clear_halt_cmd(struct urb *urb)

View file

@ -562,7 +562,7 @@ EXPORT_SYMBOL_GPL(sockfd_to_socket);
/* there may be more cases to tweak the flags. */
static unsigned int tweak_transfer_flags(unsigned int flags)
{
flags &= ~(URB_NO_TRANSFER_DMA_MAP|URB_NO_SETUP_DMA_MAP);
flags &= ~URB_NO_TRANSFER_DMA_MAP;
return flags;
}

View file

@ -18,7 +18,7 @@
*/
#include <linux/platform_device.h>
#include "../../usb/core/hcd.h"
#include <linux/usb/hcd.h>
struct vhci_device {

View file

@ -94,19 +94,19 @@
} while (0)
#define uea_enters(usb_dev) \
uea_vdbg(usb_dev, "entering %s\n", __func__)
uea_vdbg(usb_dev, "entering %s\n" , __func__)
#define uea_leaves(usb_dev) \
uea_vdbg(usb_dev, "leaving %s\n", __func__)
uea_vdbg(usb_dev, "leaving %s\n" , __func__)
#define uea_err(usb_dev, format,args...) \
dev_err(&(usb_dev)->dev ,"[UEAGLE-ATM] " format , ##args)
#define uea_err(usb_dev, format, args...) \
dev_err(&(usb_dev)->dev , "[UEAGLE-ATM] " format , ##args)
#define uea_warn(usb_dev, format,args...) \
dev_warn(&(usb_dev)->dev ,"[Ueagle-atm] " format, ##args)
#define uea_warn(usb_dev, format, args...) \
dev_warn(&(usb_dev)->dev , "[Ueagle-atm] " format, ##args)
#define uea_info(usb_dev, format,args...) \
dev_info(&(usb_dev)->dev ,"[ueagle-atm] " format, ##args)
#define uea_info(usb_dev, format, args...) \
dev_info(&(usb_dev)->dev , "[ueagle-atm] " format, ##args)
struct intr_pkt;
@ -289,7 +289,7 @@ enum {
#define IS_ISDN(x) \
((x)->annex & ANNEXB)
#define INS_TO_USBDEV(ins) ins->usb_dev
#define INS_TO_USBDEV(ins) (ins->usb_dev)
#define GET_STATUS(data) \
((data >> 8) & 0xf)
@ -304,7 +304,7 @@ enum {
* The FW_GET_BYTE() macro is provided only for consistency.
*/
#define FW_GET_BYTE(p) *((__u8 *) (p))
#define FW_GET_BYTE(p) (*((__u8 *) (p)))
#define FW_DIR "ueagle-atm/"
#define UEA_FW_NAME_MAX 30
@ -315,7 +315,7 @@ enum {
#define ACK_TIMEOUT msecs_to_jiffies(3000)
#define UEA_INTR_IFACE_NO 0
#define UEA_INTR_IFACE_NO 0
#define UEA_US_IFACE_NO 1
#define UEA_DS_IFACE_NO 2
@ -326,9 +326,9 @@ enum {
#define UEA_INTR_PIPE 0x04
#define UEA_ISO_DATA_PIPE 0x08
#define UEA_E1_SET_BLOCK 0x0001
#define UEA_E1_SET_BLOCK 0x0001
#define UEA_E4_SET_BLOCK 0x002c
#define UEA_SET_MODE 0x0003
#define UEA_SET_MODE 0x0003
#define UEA_SET_2183_DATA 0x0004
#define UEA_SET_TIMEOUT 0x0011
@ -366,7 +366,7 @@ struct l1_code {
u8 string_header[E4_L1_STRING_HEADER];
u8 page_number_to_block_index[E4_MAX_PAGE_NUMBER];
struct block_index page_header[E4_NO_SWAPPAGE_HEADERS];
u8 code [0];
u8 code[0];
} __attribute__ ((packed));
/* structures describing a block within a DSP page */
@ -428,7 +428,8 @@ struct block_info_e4 {
#define E4_MODEMREADY 0x1
#define E1_MAKEFUNCTION(t, s) (((t) & 0xf) << 4 | ((s) & 0xf))
#define E4_MAKEFUNCTION(t, st, s) (((t) & 0xf) << 8 | ((st) & 0xf) << 4 | ((s) & 0xf))
#define E4_MAKEFUNCTION(t, st, s) (((t) & 0xf) << 8 | \
((st) & 0xf) << 4 | ((s) & 0xf))
#define E1_MAKESA(a, b, c, d) \
(((c) & 0xff) << 24 | \
@ -473,7 +474,7 @@ struct cmv_e4 {
__be16 wFunction;
__be16 wOffset;
__be16 wAddress;
__be32 dwData [6];
__be32 dwData[6];
} __attribute__ ((packed));
/* structures representing swap information */
@ -534,11 +535,13 @@ struct intr_pkt {
static struct usb_driver uea_driver;
static DEFINE_MUTEX(uea_mutex);
static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III", "Eagle IV"};
static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III",
"Eagle IV"};
static int modem_index;
static unsigned int debug;
static unsigned int altsetting[NB_MODEM] = {[0 ... (NB_MODEM - 1)] = FASTEST_ISO_INTF};
static unsigned int altsetting[NB_MODEM] = {
[0 ... (NB_MODEM - 1)] = FASTEST_ISO_INTF};
static int sync_wait[NB_MODEM];
static char *cmv_file[NB_MODEM];
static int annex[NB_MODEM];
@ -555,7 +558,7 @@ MODULE_PARM_DESC(cmv_file,
"file name with configuration and management variables");
module_param_array(annex, uint, NULL, 0644);
MODULE_PARM_DESC(annex,
"manually set annex a/b (0=auto, 1=annex a, 2=annex b)");
"manually set annex a/b (0=auto, 1=annex a, 2=annex b)");
#define uea_wait(sc, cond, timeo) \
({ \
@ -602,7 +605,8 @@ static int uea_send_modem_cmd(struct usb_device *usb,
return (ret == size) ? 0 : -EIO;
}
static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *context)
static void uea_upload_pre_firmware(const struct firmware *fw_entry,
void *context)
{
struct usb_device *usb = context;
const u8 *pfw;
@ -707,7 +711,8 @@ static int uea_load_firmware(struct usb_device *usb, unsigned int ver)
}
ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev,
GFP_KERNEL, usb, uea_upload_pre_firmware);
GFP_KERNEL, usb,
uea_upload_pre_firmware);
if (ret)
uea_err(usb, "firmware %s is not available\n", fw_name);
else
@ -876,7 +881,7 @@ static int request_dsp(struct uea_softc *sc)
if (ret < 0) {
uea_err(INS_TO_USBDEV(sc),
"requesting firmware %s failed with error %d\n",
dsp_name, ret);
dsp_name, ret);
return ret;
}
@ -994,14 +999,17 @@ static void __uea_load_page_e4(struct uea_softc *sc, u8 pageno, int boot)
blockidx = &p->page_header[blockno];
blocksize = E4_PAGE_BYTES(blockidx->PageSize);
blockoffset = sc->dsp_firm->data + le32_to_cpu(blockidx->PageOffset);
blockoffset = sc->dsp_firm->data + le32_to_cpu(
blockidx->PageOffset);
bi.dwSize = cpu_to_be32(blocksize);
bi.dwAddress = cpu_to_be32(le32_to_cpu(blockidx->PageAddress));
uea_dbg(INS_TO_USBDEV(sc),
"sending block %u for DSP page %u size %u address %x\n",
blockno, pageno, blocksize, le32_to_cpu(blockidx->PageAddress));
"sending block %u for DSP page "
"%u size %u address %x\n",
blockno, pageno, blocksize,
le32_to_cpu(blockidx->PageAddress));
/* send block info through the IDMA pipe */
if (uea_idma_write(sc, &bi, E4_BLOCK_INFO_SIZE))
@ -1042,7 +1050,8 @@ static void uea_load_page_e4(struct work_struct *work)
p = (struct l1_code *) sc->dsp_firm->data;
if (pageno >= le16_to_cpu(p->page_header[0].PageNumber)) {
uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno);
uea_err(INS_TO_USBDEV(sc), "invalid DSP "
"page %u requested\n", pageno);
return;
}
@ -1059,7 +1068,7 @@ static void uea_load_page_e4(struct work_struct *work)
__uea_load_page_e4(sc, i, 1);
}
uea_dbg(INS_TO_USBDEV(sc),"sending start bi\n");
uea_dbg(INS_TO_USBDEV(sc) , "sending start bi\n");
bi.wHdr = cpu_to_be16(UEA_BIHDR);
bi.bBootPage = 0;
@ -1139,8 +1148,10 @@ static int uea_cmv_e1(struct uea_softc *sc,
uea_enters(INS_TO_USBDEV(sc));
uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Address : %c%c%c%c, "
"offset : 0x%04x, data : 0x%08x\n",
E1_FUNCTION_TYPE(function), E1_FUNCTION_SUBTYPE(function),
E1_GETSA1(address), E1_GETSA2(address), E1_GETSA3(address),
E1_FUNCTION_TYPE(function),
E1_FUNCTION_SUBTYPE(function),
E1_GETSA1(address), E1_GETSA2(address),
E1_GETSA3(address),
E1_GETSA4(address), offset, data);
/* we send a request, but we expect a reply */
@ -1157,7 +1168,8 @@ static int uea_cmv_e1(struct uea_softc *sc,
cmv.wOffsetAddress = cpu_to_le16(offset);
put_unaligned_le32(data >> 16 | data << 16, &cmv.dwData);
ret = uea_request(sc, UEA_E1_SET_BLOCK, UEA_MPTX_START, sizeof(cmv), &cmv);
ret = uea_request(sc, UEA_E1_SET_BLOCK, UEA_MPTX_START,
sizeof(cmv), &cmv);
if (ret < 0)
return ret;
ret = wait_cmv_ack(sc);
@ -1191,7 +1203,8 @@ static int uea_cmv_e4(struct uea_softc *sc,
cmv.wOffset = cpu_to_be16(offset);
cmv.dwData[0] = cpu_to_be32(data);
ret = uea_request(sc, UEA_E4_SET_BLOCK, UEA_MPTX_START, sizeof(cmv), &cmv);
ret = uea_request(sc, UEA_E4_SET_BLOCK, UEA_MPTX_START,
sizeof(cmv), &cmv);
if (ret < 0)
return ret;
ret = wait_cmv_ack(sc);
@ -1208,7 +1221,7 @@ static inline int uea_read_cmv_e1(struct uea_softc *sc,
uea_err(INS_TO_USBDEV(sc),
"reading cmv failed with error %d\n", ret);
else
*data = sc->data;
*data = sc->data;
return ret;
}
@ -1216,13 +1229,14 @@ static inline int uea_read_cmv_e1(struct uea_softc *sc,
static inline int uea_read_cmv_e4(struct uea_softc *sc,
u8 size, u16 group, u16 address, u16 offset, u32 *data)
{
int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS, E4_REQUESTREAD, size),
int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS,
E4_REQUESTREAD, size),
group, address, offset, 0);
if (ret < 0)
uea_err(INS_TO_USBDEV(sc),
"reading cmv failed with error %d\n", ret);
else {
*data = sc->data;
*data = sc->data;
/* size is in 16-bit word quantities */
if (size > 2)
*(data + 1) = sc->data1;
@ -1245,7 +1259,8 @@ static inline int uea_write_cmv_e1(struct uea_softc *sc,
static inline int uea_write_cmv_e4(struct uea_softc *sc,
u8 size, u16 group, u16 address, u16 offset, u32 data)
{
int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS, E4_REQUESTWRITE, size),
int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS,
E4_REQUESTWRITE, size),
group, address, offset, data);
if (ret < 0)
uea_err(INS_TO_USBDEV(sc),
@ -1442,27 +1457,29 @@ static int uea_stat_e4(struct uea_softc *sc)
return ret;
switch (sc->stats.phy.state) {
case 0x0: /* not yet synchronized */
case 0x1:
case 0x3:
case 0x4:
uea_dbg(INS_TO_USBDEV(sc), "modem not yet synchronized\n");
return 0;
case 0x5: /* initialization */
case 0x6:
case 0x9:
case 0xa:
uea_dbg(INS_TO_USBDEV(sc), "modem initializing\n");
return 0;
case 0x2: /* fail ... */
uea_info(INS_TO_USBDEV(sc), "modem synchronization failed"
" (may be try other cmv/dsp)\n");
return -EAGAIN;
case 0x7: /* operational */
break;
default:
uea_warn(INS_TO_USBDEV(sc), "unknown state: %x\n", sc->stats.phy.state);
return 0;
case 0x0: /* not yet synchronized */
case 0x1:
case 0x3:
case 0x4:
uea_dbg(INS_TO_USBDEV(sc), "modem not yet "
"synchronized\n");
return 0;
case 0x5: /* initialization */
case 0x6:
case 0x9:
case 0xa:
uea_dbg(INS_TO_USBDEV(sc), "modem initializing\n");
return 0;
case 0x2: /* fail ... */
uea_info(INS_TO_USBDEV(sc), "modem synchronization "
"failed (may be try other cmv/dsp)\n");
return -EAGAIN;
case 0x7: /* operational */
break;
default:
uea_warn(INS_TO_USBDEV(sc), "unknown state: %x\n",
sc->stats.phy.state);
return 0;
}
if (data != 7) {
@ -1502,9 +1519,9 @@ static int uea_stat_e4(struct uea_softc *sc)
if (sc->stats.phy.flags) {
uea_dbg(INS_TO_USBDEV(sc), "Stat flag = 0x%x\n",
sc->stats.phy.flags);
if (sc->stats.phy.flags & 1) //delineation LOSS
if (sc->stats.phy.flags & 1) /* delineation LOSS */
return -EAGAIN;
if (sc->stats.phy.flags & 0x4000) //Reset Flag
if (sc->stats.phy.flags & 0x4000) /* Reset Flag */
return -EAGAIN;
return 0;
}
@ -1618,7 +1635,8 @@ static int request_cmvs(struct uea_softc *sc,
if (ret < 0) {
/* if caller can handle old version, try to provide it */
if (*ver == 1) {
uea_warn(INS_TO_USBDEV(sc), "requesting firmware %s failed, "
uea_warn(INS_TO_USBDEV(sc), "requesting "
"firmware %s failed, "
"try to get older cmvs\n", cmv_name);
return request_cmvs_old(sc, cmvs, fw);
}
@ -1632,8 +1650,8 @@ static int request_cmvs(struct uea_softc *sc,
data = (u8 *) (*fw)->data;
if (size < 4 || strncmp(data, "cmv2", 4) != 0) {
if (*ver == 1) {
uea_warn(INS_TO_USBDEV(sc), "firmware %s is corrupted, "
"try to get older cmvs\n", cmv_name);
uea_warn(INS_TO_USBDEV(sc), "firmware %s is corrupted,"
" try to get older cmvs\n", cmv_name);
release_firmware(*fw);
return request_cmvs_old(sc, cmvs, fw);
}
@ -1670,7 +1688,7 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
int i, ret, len;
void *cmvs_ptr;
const struct firmware *cmvs_fw;
int ver = 1; // we can handle v1 cmv firmware version;
int ver = 1; /* we can handle v1 cmv firmware version; */
/* Enter in R-IDLE (cmv) until instructed otherwise */
ret = uea_write_cmv_e1(sc, E1_SA_CNTL, 0, 1);
@ -1685,7 +1703,7 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
sc->stats.phy.firmid);
/* get options */
ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver);
ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver);
if (ret < 0)
return ret;
@ -1697,9 +1715,10 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
"please update your firmware\n");
for (i = 0; i < len; i++) {
ret = uea_write_cmv_e1(sc, get_unaligned_le32(&cmvs_v1[i].address),
get_unaligned_le16(&cmvs_v1[i].offset),
get_unaligned_le32(&cmvs_v1[i].data));
ret = uea_write_cmv_e1(sc,
get_unaligned_le32(&cmvs_v1[i].address),
get_unaligned_le16(&cmvs_v1[i].offset),
get_unaligned_le32(&cmvs_v1[i].data));
if (ret < 0)
goto out;
}
@ -1707,9 +1726,10 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
struct uea_cmvs_v2 *cmvs_v2 = cmvs_ptr;
for (i = 0; i < len; i++) {
ret = uea_write_cmv_e1(sc, get_unaligned_le32(&cmvs_v2[i].address),
(u16) get_unaligned_le32(&cmvs_v2[i].offset),
get_unaligned_le32(&cmvs_v2[i].data));
ret = uea_write_cmv_e1(sc,
get_unaligned_le32(&cmvs_v2[i].address),
(u16) get_unaligned_le32(&cmvs_v2[i].offset),
get_unaligned_le32(&cmvs_v2[i].data));
if (ret < 0)
goto out;
}
@ -1722,7 +1742,8 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
/* Enter in R-ACT-REQ */
ret = uea_write_cmv_e1(sc, E1_SA_CNTL, 0, 2);
uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n");
uea_info(INS_TO_USBDEV(sc), "modem started, waiting synchronization...\n");
uea_info(INS_TO_USBDEV(sc), "modem started, waiting "
"synchronization...\n");
out:
release_firmware(cmvs_fw);
return ret;
@ -1733,7 +1754,7 @@ static int uea_send_cmvs_e4(struct uea_softc *sc)
int i, ret, len;
void *cmvs_ptr;
const struct firmware *cmvs_fw;
int ver = 2; // we can only handle v2 cmv firmware version;
int ver = 2; /* we can only handle v2 cmv firmware version; */
/* Enter in R-IDLE (cmv) until instructed otherwise */
ret = uea_write_cmv_e4(sc, 1, E4_SA_CNTL, 0, 0, 1);
@ -1750,7 +1771,7 @@ static int uea_send_cmvs_e4(struct uea_softc *sc)
/* get options */
ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver);
ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver);
if (ret < 0)
return ret;
@ -1760,10 +1781,10 @@ static int uea_send_cmvs_e4(struct uea_softc *sc)
for (i = 0; i < len; i++) {
ret = uea_write_cmv_e4(sc, 1,
get_unaligned_le32(&cmvs_v2[i].group),
get_unaligned_le32(&cmvs_v2[i].address),
get_unaligned_le32(&cmvs_v2[i].offset),
get_unaligned_le32(&cmvs_v2[i].data));
get_unaligned_le32(&cmvs_v2[i].group),
get_unaligned_le32(&cmvs_v2[i].address),
get_unaligned_le32(&cmvs_v2[i].offset),
get_unaligned_le32(&cmvs_v2[i].data));
if (ret < 0)
goto out;
}
@ -1776,7 +1797,8 @@ static int uea_send_cmvs_e4(struct uea_softc *sc)
/* Enter in R-ACT-REQ */
ret = uea_write_cmv_e4(sc, 1, E4_SA_CNTL, 0, 0, 2);
uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n");
uea_info(INS_TO_USBDEV(sc), "modem started, waiting synchronization...\n");
uea_info(INS_TO_USBDEV(sc), "modem started, waiting "
"synchronization...\n");
out:
release_firmware(cmvs_fw);
return ret;
@ -1812,7 +1834,7 @@ static int uea_start_reset(struct uea_softc *sc)
uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL);
uea_request(sc, UEA_SET_MODE, UEA_BOOT_IDMA, 0, NULL);
/* enter reset mode */
/* enter reset mode */
uea_request(sc, UEA_SET_MODE, UEA_START_RESET, 0, NULL);
/* original driver use 200ms, but windows driver use 100ms */
@ -1824,7 +1846,7 @@ static int uea_start_reset(struct uea_softc *sc)
uea_request(sc, UEA_SET_MODE, UEA_END_RESET, 0, NULL);
if (UEA_CHIP_VERSION(sc) != EAGLE_IV) {
/* clear tx and rx mailboxes */
/* clear tx and rx mailboxes */
uea_request(sc, UEA_SET_2183_DATA, UEA_MPTX_MAILBOX, 2, &zero);
uea_request(sc, UEA_SET_2183_DATA, UEA_MPRX_MAILBOX, 2, &zero);
uea_request(sc, UEA_SET_2183_DATA, UEA_SWAP_MAILBOX, 2, &zero);
@ -1835,9 +1857,11 @@ static int uea_start_reset(struct uea_softc *sc)
return ret;
if (UEA_CHIP_VERSION(sc) == EAGLE_IV)
sc->cmv_dsc.e4.function = E4_MAKEFUNCTION(E4_ADSLDIRECTIVE, E4_MODEMREADY, 1);
sc->cmv_dsc.e4.function = E4_MAKEFUNCTION(E4_ADSLDIRECTIVE,
E4_MODEMREADY, 1);
else
sc->cmv_dsc.e1.function = E1_MAKEFUNCTION(E1_ADSLDIRECTIVE, E1_MODEMREADY);
sc->cmv_dsc.e1.function = E1_MAKEFUNCTION(E1_ADSLDIRECTIVE,
E1_MODEMREADY);
/* demask interrupt */
sc->booting = 0;
@ -1937,7 +1961,8 @@ static int load_XILINX_firmware(struct uea_softc *sc)
value = 0;
ret = uea_send_modem_cmd(sc->usb_dev, 0xe, 1, &value);
if (ret < 0)
uea_err(sc->usb_dev, "elsa de-assert failed with error %d\n", ret);
uea_err(sc->usb_dev, "elsa de-assert failed with error"
" %d\n", ret);
err1:
release_firmware(fw_entry);
@ -1966,13 +1991,15 @@ static void uea_dispatch_cmv_e1(struct uea_softc *sc, struct intr_pkt *intr)
if (UEA_CHIP_VERSION(sc) == ADI930
&& cmv->bFunction == E1_MAKEFUNCTION(2, 2)) {
cmv->wIndex = cpu_to_le16(dsc->idx);
put_unaligned_le32(dsc->address, &cmv->dwSymbolicAddress);
put_unaligned_le32(dsc->address,
&cmv->dwSymbolicAddress);
cmv->wOffsetAddress = cpu_to_le16(dsc->offset);
} else
goto bad2;
}
if (cmv->bFunction == E1_MAKEFUNCTION(E1_ADSLDIRECTIVE, E1_MODEMREADY)) {
if (cmv->bFunction == E1_MAKEFUNCTION(E1_ADSLDIRECTIVE,
E1_MODEMREADY)) {
wake_up_cmv_ack(sc);
uea_leaves(INS_TO_USBDEV(sc));
return;
@ -2021,7 +2048,8 @@ static void uea_dispatch_cmv_e4(struct uea_softc *sc, struct intr_pkt *intr)
if (be16_to_cpu(cmv->wFunction) != dsc->function)
goto bad2;
if (be16_to_cpu(cmv->wFunction) == E4_MAKEFUNCTION(E4_ADSLDIRECTIVE, E4_MODEMREADY, 1)) {
if (be16_to_cpu(cmv->wFunction) == E4_MAKEFUNCTION(E4_ADSLDIRECTIVE,
E4_MODEMREADY, 1)) {
wake_up_cmv_ack(sc);
uea_leaves(INS_TO_USBDEV(sc));
return;
@ -2048,14 +2076,16 @@ bad2:
return;
}
static void uea_schedule_load_page_e1(struct uea_softc *sc, struct intr_pkt *intr)
static void uea_schedule_load_page_e1(struct uea_softc *sc,
struct intr_pkt *intr)
{
sc->pageno = intr->e1_bSwapPageNo;
sc->ovl = intr->e1_bOvl >> 4 | intr->e1_bOvl << 4;
queue_work(sc->work_q, &sc->task);
}
static void uea_schedule_load_page_e4(struct uea_softc *sc, struct intr_pkt *intr)
static void uea_schedule_load_page_e4(struct uea_softc *sc,
struct intr_pkt *intr)
{
sc->pageno = intr->e4_bSwapPageNo;
queue_work(sc->work_q, &sc->task);
@ -2263,8 +2293,8 @@ out:
static DEVICE_ATTR(stat_status, S_IWUGO | S_IRUGO, read_status, reboot);
static ssize_t read_human_status(struct device *dev, struct device_attribute *attr,
char *buf)
static ssize_t read_human_status(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret = -ENODEV;
int modem_state;
@ -2289,7 +2319,7 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at
case 0xa:
modem_state = 1;
break;
case 0x7: /* operational */
case 0x7: /* operational */
modem_state = 2;
break;
case 0x2: /* fail ... */
@ -2324,7 +2354,8 @@ out:
return ret;
}
static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO, read_human_status, NULL);
static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO,
read_human_status, NULL);
static ssize_t read_delin(struct device *dev, struct device_attribute *attr,
char *buf)
@ -2358,25 +2389,25 @@ out:
static DEVICE_ATTR(stat_delin, S_IWUGO | S_IRUGO, read_delin, NULL);
#define UEA_ATTR(name, reset) \
#define UEA_ATTR(name, reset) \
\
static ssize_t read_##name(struct device *dev, \
static ssize_t read_##name(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
int ret = -ENODEV; \
struct uea_softc *sc; \
\
mutex_lock(&uea_mutex); \
{ \
int ret = -ENODEV; \
struct uea_softc *sc; \
\
mutex_lock(&uea_mutex); \
sc = dev_to_uea(dev); \
if (!sc) \
goto out; \
if (!sc) \
goto out; \
ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.name); \
if (reset) \
sc->stats.phy.name = 0; \
out: \
mutex_unlock(&uea_mutex); \
return ret; \
} \
out: \
mutex_unlock(&uea_mutex); \
return ret; \
} \
\
static DEVICE_ATTR(stat_##name, S_IRUGO, read_##name, NULL)
@ -2527,12 +2558,14 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
else if (sc->driver_info & AUTO_ANNEX_B)
sc->annex = ANNEXB;
else
sc->annex = (le16_to_cpu(sc->usb_dev->descriptor.bcdDevice) & 0x80)?ANNEXB:ANNEXA;
sc->annex = (le16_to_cpu
(sc->usb_dev->descriptor.bcdDevice) & 0x80) ? ANNEXB : ANNEXA;
alt = altsetting[sc->modem_index];
/* ADI930 don't support iso */
if (UEA_CHIP_VERSION(id) != ADI930 && alt > 0) {
if (alt <= 8 && usb_set_interface(usb, UEA_DS_IFACE_NO, alt) == 0) {
if (alt <= 8 &&
usb_set_interface(usb, UEA_DS_IFACE_NO, alt) == 0) {
uea_dbg(usb, "set alternate %u for 2 interface\n", alt);
uea_info(usb, "using iso mode\n");
usbatm->flags |= UDSL_USE_ISOC | UDSL_IGNORE_EILSEQ;
@ -2621,40 +2654,74 @@ static void uea_disconnect(struct usb_interface *intf)
* List of supported VID/PID
*/
static const struct usb_device_id uea_ids[] = {
{USB_DEVICE(ANALOG_VID, ADI930_PID_PREFIRM), .driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ANALOG_VID, ADI930_PID_PSTFIRM), .driver_info = ADI930 | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PREFIRM), .driver_info = EAGLE_III | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PSTFIRM), .driver_info = EAGLE_III | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PREFIRM), .driver_info = EAGLE_IV | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PSTFIRM), .driver_info = EAGLE_IV | PSTFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(ELSA_VID, ELSA_PID_PREFIRM), .driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_PSTFIRM), .driver_info = ADI930 | PSTFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_A_PREFIRM), .driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_A_PSTFIRM), .driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(ELSA_VID, ELSA_PID_B_PREFIRM), .driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_B_PSTFIRM), .driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(USR_VID, MILLER_A_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, MILLER_A_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(USR_VID, MILLER_B_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, MILLER_B_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(USR_VID, HEINEKEN_A_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, HEINEKEN_A_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(USR_VID, HEINEKEN_B_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, HEINEKEN_B_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(ANALOG_VID, ADI930_PID_PREFIRM),
.driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ANALOG_VID, ADI930_PID_PSTFIRM),
.driver_info = ADI930 | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PREFIRM),
.driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PSTFIRM),
.driver_info = EAGLE_II | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PREFIRM),
.driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PSTFIRM),
.driver_info = EAGLE_II | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PREFIRM),
.driver_info = EAGLE_III | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PSTFIRM),
.driver_info = EAGLE_III | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PREFIRM),
.driver_info = EAGLE_IV | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PSTFIRM),
.driver_info = EAGLE_IV | PSTFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PREFIRM),
.driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PSTFIRM),
.driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PREFIRM),
.driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PSTFIRM),
.driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(ELSA_VID, ELSA_PID_PREFIRM),
.driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_PSTFIRM),
.driver_info = ADI930 | PSTFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_A_PREFIRM),
.driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_A_PSTFIRM),
.driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(ELSA_VID, ELSA_PID_B_PREFIRM),
.driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_B_PSTFIRM),
.driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(USR_VID, MILLER_A_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, MILLER_A_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(USR_VID, MILLER_B_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, MILLER_B_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(USR_VID, HEINEKEN_A_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, HEINEKEN_A_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(USR_VID, HEINEKEN_B_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, HEINEKEN_B_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
{}
};

View file

@ -28,7 +28,7 @@
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/usb.h>
#include "../core/hcd.h"
#include <linux/usb/hcd.h>
#include "c67x00.h"
/*

View file

@ -892,7 +892,7 @@ static void acm_write_buffers_free(struct acm *acm)
struct usb_device *usb_dev = interface_to_usbdev(acm->control);
for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++)
usb_buffer_free(usb_dev, acm->writesize, wb->buf, wb->dmah);
usb_free_coherent(usb_dev, acm->writesize, wb->buf, wb->dmah);
}
static void acm_read_buffers_free(struct acm *acm)
@ -901,8 +901,8 @@ static void acm_read_buffers_free(struct acm *acm)
int i, n = acm->rx_buflimit;
for (i = 0; i < n; i++)
usb_buffer_free(usb_dev, acm->readsize,
acm->rb[i].base, acm->rb[i].dma);
usb_free_coherent(usb_dev, acm->readsize,
acm->rb[i].base, acm->rb[i].dma);
}
/* Little helper: write buffers allocate */
@ -912,13 +912,13 @@ static int acm_write_buffers_alloc(struct acm *acm)
struct acm_wb *wb;
for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) {
wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL,
wb->buf = usb_alloc_coherent(acm->dev, acm->writesize, GFP_KERNEL,
&wb->dmah);
if (!wb->buf) {
while (i != 0) {
--i;
--wb;
usb_buffer_free(acm->dev, acm->writesize,
usb_free_coherent(acm->dev, acm->writesize,
wb->buf, wb->dmah);
}
return -ENOMEM;
@ -1177,7 +1177,7 @@ made_compressed_probe:
tty_port_init(&acm->port);
acm->port.ops = &acm_port_ops;
buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
if (!buf) {
dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n");
goto alloc_fail2;
@ -1210,11 +1210,11 @@ made_compressed_probe:
for (i = 0; i < num_rx_buf; i++) {
struct acm_rb *rb = &(acm->rb[i]);
rb->base = usb_buffer_alloc(acm->dev, readsize,
rb->base = usb_alloc_coherent(acm->dev, readsize,
GFP_KERNEL, &rb->dma);
if (!rb->base) {
dev_dbg(&intf->dev,
"out of memory (read bufs usb_buffer_alloc)\n");
"out of memory (read bufs usb_alloc_coherent)\n");
goto alloc_fail7;
}
}
@ -1306,7 +1306,7 @@ alloc_fail7:
alloc_fail5:
acm_write_buffers_free(acm);
alloc_fail4:
usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
alloc_fail2:
kfree(acm);
alloc_fail:
@ -1356,8 +1356,8 @@ static void acm_disconnect(struct usb_interface *intf)
stop_data_traffic(acm);
acm_write_buffers_free(acm);
usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer,
acm->ctrl_dma);
usb_free_coherent(usb_dev, acm->ctrlsize, acm->ctrl_buffer,
acm->ctrl_dma);
acm_read_buffers_free(acm);
if (!acm->combined_interfaces)

View file

@ -124,8 +124,8 @@ struct acm {
unsigned char clocal; /* termios CLOCAL */
unsigned int ctrl_caps; /* control capabilities from the class specific header */
unsigned int susp_count; /* number of suspended interfaces */
int combined_interfaces:1; /* control and data collapsed */
int is_int_ep:1; /* interrupt endpoints contrary to spec used */
unsigned int combined_interfaces:1; /* control and data collapsed */
unsigned int is_int_ep:1; /* interrupt endpoints contrary to spec used */
u8 bInterval;
struct acm_wb *delayed_wb; /* write queued for a device about to be woken */
};

View file

@ -276,14 +276,14 @@ static void free_urbs(struct wdm_device *desc)
static void cleanup(struct wdm_device *desc)
{
usb_buffer_free(interface_to_usbdev(desc->intf),
desc->wMaxPacketSize,
desc->sbuf,
desc->validity->transfer_dma);
usb_buffer_free(interface_to_usbdev(desc->intf),
desc->wMaxCommand,
desc->inbuf,
desc->response->transfer_dma);
usb_free_coherent(interface_to_usbdev(desc->intf),
desc->wMaxPacketSize,
desc->sbuf,
desc->validity->transfer_dma);
usb_free_coherent(interface_to_usbdev(desc->intf),
desc->wMaxCommand,
desc->inbuf,
desc->response->transfer_dma);
kfree(desc->orq);
kfree(desc->irq);
kfree(desc->ubuf);
@ -705,17 +705,17 @@ next_desc:
if (!desc->ubuf)
goto err;
desc->sbuf = usb_buffer_alloc(interface_to_usbdev(intf),
desc->sbuf = usb_alloc_coherent(interface_to_usbdev(intf),
desc->wMaxPacketSize,
GFP_KERNEL,
&desc->validity->transfer_dma);
if (!desc->sbuf)
goto err;
desc->inbuf = usb_buffer_alloc(interface_to_usbdev(intf),
desc->bMaxPacketSize0,
GFP_KERNEL,
&desc->response->transfer_dma);
desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf),
desc->bMaxPacketSize0,
GFP_KERNEL,
&desc->response->transfer_dma);
if (!desc->inbuf)
goto err2;
@ -742,15 +742,15 @@ out:
return rv;
err3:
usb_set_intfdata(intf, NULL);
usb_buffer_free(interface_to_usbdev(desc->intf),
desc->bMaxPacketSize0,
usb_free_coherent(interface_to_usbdev(desc->intf),
desc->bMaxPacketSize0,
desc->inbuf,
desc->response->transfer_dma);
err2:
usb_buffer_free(interface_to_usbdev(desc->intf),
desc->wMaxPacketSize,
desc->sbuf,
desc->validity->transfer_dma);
usb_free_coherent(interface_to_usbdev(desc->intf),
desc->wMaxPacketSize,
desc->sbuf,
desc->validity->transfer_dma);
err:
free_urbs(desc);
kfree(desc->ubuf);

View file

@ -27,7 +27,7 @@
* v0.11 - add proto_bias option (Pete Zaitcev)
* v0.12 - add hpoj.sourceforge.net ioctls (David Paschal)
* v0.13 - alloc space for statusbuf (<status> not on stack);
* use usb_buffer_alloc() for read buf & write buf;
* use usb_alloc_coherent() for read buf & write buf;
* none - Maintained in Linux kernel after v0.13
*/

View file

@ -14,7 +14,7 @@
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/usb.h>
#include "hcd.h"
#include <linux/usb/hcd.h>
/*

View file

@ -1,12 +1,14 @@
#include <linux/usb.h>
#include <linux/usb/ch9.h>
#include <linux/usb/hcd.h>
#include <linux/usb/quirks.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <asm/byteorder.h>
#include "usb.h"
#include "hcd.h"
#define USB_MAXALTSETTING 128 /* Hard limit */
#define USB_MAXENDPOINTS 30 /* Hard limit */
@ -19,32 +21,6 @@ static inline const char *plural(int n)
return (n == 1 ? "" : "s");
}
/* FIXME: this is a kludge */
static int find_next_descriptor_more(unsigned char *buffer, int size,
int dt1, int dt2, int dt3, int *num_skipped)
{
struct usb_descriptor_header *h;
int n = 0;
unsigned char *buffer0 = buffer;
/* Find the next descriptor of type dt1 or dt2 or dt3 */
while (size > 0) {
h = (struct usb_descriptor_header *) buffer;
if (h->bDescriptorType == dt1 || h->bDescriptorType == dt2 ||
h->bDescriptorType == dt3)
break;
buffer += h->bLength;
size -= h->bLength;
++n;
}
/* Store the number of descriptors skipped and return the
* number of bytes skipped */
if (num_skipped)
*num_skipped = n;
return buffer - buffer0;
}
static int find_next_descriptor(unsigned char *buffer, int size,
int dt1, int dt2, int *num_skipped)
{
@ -69,47 +45,41 @@ static int find_next_descriptor(unsigned char *buffer, int size,
return buffer - buffer0;
}
static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
static void 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, int size)
{
unsigned char *buffer_start = buffer;
struct usb_ss_ep_comp_descriptor *desc;
int retval;
int num_skipped;
struct usb_ss_ep_comp_descriptor *desc;
int max_tx;
int i;
/* 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) {
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);
/*
* 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");
/* 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) {
@ -117,47 +87,48 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
"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) {
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);
desc->bMaxBurst = 15;
ep->ss_ep_comp.bMaxBurst = 15;
}
if ((usb_endpoint_xfer_control(&ep->desc) || usb_endpoint_xfer_int(&ep->desc))
&& desc->bmAttributes != 0) {
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) {
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);
desc->bmAttributes = 16;
}
if (usb_endpoint_xfer_isoc(&ep->desc) && desc->bmAttributes > 2) {
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);
desc->bmAttributes = 2;
ep->ss_ep_comp.bmAttributes = 2;
}
if (usb_endpoint_xfer_isoc(&ep->desc)) {
if (usb_endpoint_xfer_isoc(&ep->desc))
max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1) *
(desc->bmAttributes + 1);
} else if (usb_endpoint_xfer_int(&ep->desc)) {
else if (usb_endpoint_xfer_int(&ep->desc))
max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1);
} else {
goto valid;
}
else
max_tx = 999999;
if (desc->wBytesPerInterval > max_tx) {
dev_warn(ddev, "%s endpoint with wBytesPerInterval of %d in "
"config %d interface %d altsetting %d ep %d: "
@ -166,10 +137,8 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
desc->wBytesPerInterval,
cfgno, inum, asnum, ep->desc.bEndpointAddress,
max_tx);
desc->wBytesPerInterval = max_tx;
ep->ss_ep_comp.wBytesPerInterval = max_tx;
}
valid:
return retval;
}
static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
@ -291,61 +260,19 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
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;
/* 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);
/* 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;
}
/* 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");
@ -478,9 +405,10 @@ skip_to_next_interface_descriptor:
return buffer - buffer0 + i;
}
static int usb_parse_configuration(struct device *ddev, int cfgidx,
static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
struct usb_host_config *config, unsigned char *buffer, int size)
{
struct device *ddev = &dev->dev;
unsigned char *buffer0 = buffer;
int cfgno;
int nintf, nintf_orig;
@ -549,6 +477,16 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
}
inum = d->bInterfaceNumber;
if ((dev->quirks & USB_QUIRK_HONOR_BNUMINTERFACES) &&
n >= nintf_orig) {
dev_warn(ddev, "config %d has more interface "
"descriptors, than it declares in "
"bNumInterfaces, ignoring interface "
"number: %d\n", cfgno, inum);
continue;
}
if (inum >= nintf_orig)
dev_warn(ddev, "config %d has an invalid "
"interface number: %d but max is %d\n",
@ -722,7 +660,6 @@ int usb_get_configuration(struct usb_device *dev)
int ncfg = dev->descriptor.bNumConfigurations;
int result = 0;
unsigned int cfgno, length;
unsigned char *buffer;
unsigned char *bigbuffer;
struct usb_config_descriptor *desc;
@ -751,17 +688,16 @@ int usb_get_configuration(struct usb_device *dev)
if (!dev->rawdescriptors)
goto err2;
buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
if (!buffer)
desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
if (!desc)
goto err2;
desc = (struct usb_config_descriptor *)buffer;
result = 0;
for (; cfgno < ncfg; cfgno++) {
/* We grab just the first descriptor so we know how long
* the whole configuration is */
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
buffer, USB_DT_CONFIG_SIZE);
desc, USB_DT_CONFIG_SIZE);
if (result < 0) {
dev_err(ddev, "unable to read config index %d "
"descriptor/%s: %d\n", cfgno, "start", result);
@ -800,7 +736,7 @@ int usb_get_configuration(struct usb_device *dev)
dev->rawdescriptors[cfgno] = bigbuffer;
result = usb_parse_configuration(&dev->dev, cfgno,
result = usb_parse_configuration(dev, cfgno,
&dev->config[cfgno], bigbuffer, length);
if (result < 0) {
++cfgno;
@ -810,7 +746,7 @@ int usb_get_configuration(struct usb_device *dev)
result = 0;
err:
kfree(buffer);
kfree(desc);
out_not_authorized:
dev->descriptor.bNumConfigurations = cfgno;
err2:

View file

@ -1,7 +1,8 @@
/*
* devices.c
* (C) Copyright 1999 Randy Dunlap.
* (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
* (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>.
* (proc file per device)
* (C) Copyright 1999 Deti Fliegl (new USB architecture)
*
* This program is free software; you can redistribute it and/or modify
@ -55,11 +56,11 @@
#include <linux/usb.h>
#include <linux/smp_lock.h>
#include <linux/usbdevice_fs.h>
#include <linux/usb/hcd.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <linux/uaccess.h>
#include "usb.h"
#include "hcd.h"
/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
#define ALLOW_SERIAL_NUMBER
@ -138,8 +139,8 @@ struct class_info {
char *class_name;
};
static const struct class_info clas_info[] =
{ /* max. 5 chars. per name string */
static const struct class_info clas_info[] = {
/* max. 5 chars. per name string */
{USB_CLASS_PER_INTERFACE, ">ifc"},
{USB_CLASS_AUDIO, "audio"},
{USB_CLASS_COMM, "comm."},
@ -191,8 +192,10 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
if (speed == USB_SPEED_HIGH) {
switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) {
case 1 << 11: bandwidth = 2; break;
case 2 << 11: bandwidth = 3; break;
case 1 << 11:
bandwidth = 2; break;
case 2 << 11:
bandwidth = 3; break;
}
}
@ -200,7 +203,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_CONTROL:
type = "Ctrl";
if (speed == USB_SPEED_HIGH) /* uframes per NAK */
if (speed == USB_SPEED_HIGH) /* uframes per NAK */
interval = desc->bInterval;
else
interval = 0;

View file

@ -43,6 +43,7 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
#include <linux/usb/hcd.h> /* for usbcore internals */
#include <linux/cdev.h>
#include <linux/notifier.h>
#include <linux/security.h>
@ -50,9 +51,7 @@
#include <asm/byteorder.h>
#include <linux/moduleparam.h>
#include "hcd.h" /* for usbcore internals */
#include "usb.h"
#include "hub.h"
#define USB_MAXBUS 64
#define USB_DEVICE_MAX USB_MAXBUS * 128

View file

@ -26,8 +26,9 @@
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/usb/quirks.h>
#include <linux/usb/hcd.h>
#include <linux/pm_runtime.h>
#include "hcd.h"
#include "usb.h"
@ -333,7 +334,8 @@ static int usb_probe_interface(struct device *dev)
usb_cancel_queued_reset(intf);
/* Unbound interfaces are always runtime-PM-disabled and -suspended */
pm_runtime_disable(dev);
if (driver->supports_autosuspend)
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
usb_autosuspend_device(udev);
@ -388,7 +390,8 @@ static int usb_unbind_interface(struct device *dev)
intf->needs_remote_wakeup = 0;
/* Unbound interfaces are always runtime-PM-disabled and -suspended */
pm_runtime_disable(dev);
if (driver->supports_autosuspend)
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
/* Undo any residual pm_autopm_get_interface_* calls */
@ -437,14 +440,17 @@ int usb_driver_claim_interface(struct usb_driver *driver,
iface->condition = USB_INTERFACE_BOUND;
/* Claimed interfaces are initially inactive (suspended). They are
* runtime-PM-enabled only if the driver has autosuspend support.
* They are sensitive to their children's power states.
/* Claimed interfaces are initially inactive (suspended) and
* runtime-PM-enabled, but only if the driver has autosuspend
* support. Otherwise they are marked active, to prevent the
* device from being autosuspended, but left disabled. In either
* case they are sensitive to their children's power states.
*/
pm_runtime_set_suspended(dev);
pm_suspend_ignore_children(dev, false);
if (driver->supports_autosuspend)
pm_runtime_enable(dev);
else
pm_runtime_set_active(dev);
/* if interface was already added, bind now; else let
* the future device_add() bind it, bypassing probe()
@ -1355,13 +1361,9 @@ int usb_resume(struct device *dev, pm_message_t msg)
*
* The caller must hold @udev's device lock.
*/
int usb_enable_autosuspend(struct usb_device *udev)
void usb_enable_autosuspend(struct usb_device *udev)
{
if (udev->autosuspend_disabled) {
udev->autosuspend_disabled = 0;
usb_autosuspend_device(udev);
}
return 0;
pm_runtime_allow(&udev->dev);
}
EXPORT_SYMBOL_GPL(usb_enable_autosuspend);
@ -1374,16 +1376,9 @@ EXPORT_SYMBOL_GPL(usb_enable_autosuspend);
*
* The caller must hold @udev's device lock.
*/
int usb_disable_autosuspend(struct usb_device *udev)
void usb_disable_autosuspend(struct usb_device *udev)
{
int rc = 0;
if (!udev->autosuspend_disabled) {
rc = usb_autoresume_device(udev);
if (rc == 0)
udev->autosuspend_disabled = 1;
}
return rc;
pm_runtime_forbid(&udev->dev);
}
EXPORT_SYMBOL_GPL(usb_disable_autosuspend);
@ -1485,9 +1480,6 @@ int usb_autoresume_device(struct usb_device *udev)
* 0, a delayed autosuspend request for @intf's device is attempted. The
* attempt may fail (see autosuspend_check()).
*
* If the driver has set @intf->needs_remote_wakeup then autosuspend will
* take place only if the device's remote-wakeup facility is enabled.
*
* This routine can run only in process context.
*/
void usb_autopm_put_interface(struct usb_interface *intf)
@ -1530,7 +1522,7 @@ void usb_autopm_put_interface_async(struct usb_interface *intf)
atomic_dec(&intf->pm_usage_cnt);
pm_runtime_put_noidle(&intf->dev);
if (!udev->autosuspend_disabled) {
if (udev->dev.power.runtime_auto) {
/* Optimization: Don't schedule a delayed autosuspend if
* the timer is already running and the expiration time
* wouldn't change.
@ -1672,14 +1664,14 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume);
/* Internal routine to check whether we may autosuspend a device. */
static int autosuspend_check(struct usb_device *udev)
{
int i;
int w, i;
struct usb_interface *intf;
unsigned long suspend_time, j;
/* Fail if autosuspend is disabled, or any interfaces are in use, or
* any interface drivers require remote wakeup but it isn't available.
*/
udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
w = 0;
if (udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
@ -1693,12 +1685,7 @@ static int autosuspend_check(struct usb_device *udev)
continue;
if (atomic_read(&intf->dev.power.usage_count) > 0)
return -EBUSY;
if (intf->needs_remote_wakeup &&
!udev->do_remote_wakeup) {
dev_dbg(&udev->dev, "remote wakeup needed "
"for autosuspend\n");
return -EOPNOTSUPP;
}
w |= intf->needs_remote_wakeup;
/* Don't allow autosuspend if the device will need
* a reset-resume and any of its interface drivers
@ -1714,6 +1701,11 @@ static int autosuspend_check(struct usb_device *udev)
}
}
}
if (w && !device_can_wakeup(&udev->dev)) {
dev_dbg(&udev->dev, "remote wakeup needed for autosuspend\n");
return -EOPNOTSUPP;
}
udev->do_remote_wakeup = w;
/* If everything is okay but the device hasn't been idle for long
* enough, queue a delayed autosuspend request.

View file

@ -18,8 +18,8 @@
*/
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include "usb.h"
#include "hcd.h"
static inline const char *plural(int n)
{

View file

@ -21,6 +21,7 @@
#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <asm/io.h>
#include <asm/irq.h>
@ -33,7 +34,6 @@
#endif
#include "usb.h"
#include "hcd.h"
/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */

View file

@ -38,14 +38,12 @@
#include <asm/unaligned.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/pm_runtime.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include "usb.h"
#include "hcd.h"
#include "hub.h"
/*-------------------------------------------------------------------------*/
@ -1261,6 +1259,51 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle,
*dma_handle = 0;
}
static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
{
enum dma_data_direction dir;
if (urb->transfer_flags & URB_SETUP_MAP_SINGLE)
dma_unmap_single(hcd->self.controller,
urb->setup_dma,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
else if (urb->transfer_flags & URB_SETUP_MAP_LOCAL)
hcd_free_coherent(urb->dev->bus,
&urb->setup_dma,
(void **) &urb->setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
if (urb->transfer_flags & URB_DMA_MAP_SG)
dma_unmap_sg(hcd->self.controller,
urb->sg,
urb->num_sgs,
dir);
else if (urb->transfer_flags & URB_DMA_MAP_PAGE)
dma_unmap_page(hcd->self.controller,
urb->transfer_dma,
urb->transfer_buffer_length,
dir);
else if (urb->transfer_flags & URB_DMA_MAP_SINGLE)
dma_unmap_single(hcd->self.controller,
urb->transfer_dma,
urb->transfer_buffer_length,
dir);
else if (urb->transfer_flags & URB_MAP_LOCAL)
hcd_free_coherent(urb->dev->bus,
&urb->transfer_dma,
&urb->transfer_buffer,
urb->transfer_buffer_length,
dir);
/* Make it safe to call this routine more than once */
urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
URB_DMA_MAP_SINGLE | URB_MAP_LOCAL);
}
static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
gfp_t mem_flags)
{
@ -1272,11 +1315,8 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
* unless it uses pio or talks to another transport,
* or uses the provided scatter gather list for bulk.
*/
if (is_root_hub(urb->dev))
return 0;
if (usb_endpoint_xfer_control(&urb->ep->desc)
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
if (usb_endpoint_xfer_control(&urb->ep->desc)) {
if (hcd->self.uses_dma) {
urb->setup_dma = dma_map_single(
hcd->self.controller,
@ -1286,27 +1326,64 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
if (dma_mapping_error(hcd->self.controller,
urb->setup_dma))
return -EAGAIN;
} else if (hcd->driver->flags & HCD_LOCAL_MEM)
urb->transfer_flags |= URB_SETUP_MAP_SINGLE;
} else if (hcd->driver->flags & HCD_LOCAL_MEM) {
ret = hcd_alloc_coherent(
urb->dev->bus, mem_flags,
&urb->setup_dma,
(void **)&urb->setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
if (ret)
return ret;
urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
}
}
dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
if (ret == 0 && urb->transfer_buffer_length != 0
if (urb->transfer_buffer_length != 0
&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
if (hcd->self.uses_dma) {
urb->transfer_dma = dma_map_single (
hcd->self.controller,
urb->transfer_buffer,
urb->transfer_buffer_length,
dir);
if (dma_mapping_error(hcd->self.controller,
if (urb->num_sgs) {
int n = dma_map_sg(
hcd->self.controller,
urb->sg,
urb->num_sgs,
dir);
if (n <= 0)
ret = -EAGAIN;
else
urb->transfer_flags |= URB_DMA_MAP_SG;
if (n != urb->num_sgs) {
urb->num_sgs = n;
urb->transfer_flags |=
URB_DMA_SG_COMBINED;
}
} else if (urb->sg) {
struct scatterlist *sg = urb->sg;
urb->transfer_dma = dma_map_page(
hcd->self.controller,
sg_page(sg),
sg->offset,
urb->transfer_buffer_length,
dir);
if (dma_mapping_error(hcd->self.controller,
urb->transfer_dma))
return -EAGAIN;
ret = -EAGAIN;
else
urb->transfer_flags |= URB_DMA_MAP_PAGE;
} else {
urb->transfer_dma = dma_map_single(
hcd->self.controller,
urb->transfer_buffer,
urb->transfer_buffer_length,
dir);
if (dma_mapping_error(hcd->self.controller,
urb->transfer_dma))
ret = -EAGAIN;
else
urb->transfer_flags |= URB_DMA_MAP_SINGLE;
}
} else if (hcd->driver->flags & HCD_LOCAL_MEM) {
ret = hcd_alloc_coherent(
urb->dev->bus, mem_flags,
@ -1314,55 +1391,16 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
&urb->transfer_buffer,
urb->transfer_buffer_length,
dir);
if (ret && usb_endpoint_xfer_control(&urb->ep->desc)
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
hcd_free_coherent(urb->dev->bus,
&urb->setup_dma,
(void **)&urb->setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
if (ret == 0)
urb->transfer_flags |= URB_MAP_LOCAL;
}
if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE |
URB_SETUP_MAP_LOCAL)))
unmap_urb_for_dma(hcd, urb);
}
return ret;
}
static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
{
enum dma_data_direction dir;
if (is_root_hub(urb->dev))
return;
if (usb_endpoint_xfer_control(&urb->ep->desc)
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
if (hcd->self.uses_dma)
dma_unmap_single(hcd->self.controller, urb->setup_dma,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
else if (hcd->driver->flags & HCD_LOCAL_MEM)
hcd_free_coherent(urb->dev->bus, &urb->setup_dma,
(void **)&urb->setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
}
dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
if (urb->transfer_buffer_length != 0
&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
if (hcd->self.uses_dma)
dma_unmap_single(hcd->self.controller,
urb->transfer_dma,
urb->transfer_buffer_length,
dir);
else if (hcd->driver->flags & HCD_LOCAL_MEM)
hcd_free_coherent(urb->dev->bus, &urb->transfer_dma,
&urb->transfer_buffer,
urb->transfer_buffer_length,
dir);
}
}
/*-------------------------------------------------------------------------*/
/* may be called in any context with a valid urb->dev usecount
@ -1391,21 +1429,20 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
* URBs must be submitted in process context with interrupts
* enabled.
*/
status = map_urb_for_dma(hcd, urb, mem_flags);
if (unlikely(status)) {
usbmon_urb_submit_error(&hcd->self, urb, status);
goto error;
if (is_root_hub(urb->dev)) {
status = rh_urb_enqueue(hcd, urb);
} else {
status = map_urb_for_dma(hcd, urb, mem_flags);
if (likely(status == 0)) {
status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
if (unlikely(status))
unmap_urb_for_dma(hcd, urb);
}
}
if (is_root_hub(urb->dev))
status = rh_urb_enqueue(hcd, urb);
else
status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
if (unlikely(status)) {
usbmon_urb_submit_error(&hcd->self, urb, status);
unmap_urb_for_dma(hcd, urb);
error:
urb->hcpriv = NULL;
INIT_LIST_HEAD(&urb->urb_list);
atomic_dec(&urb->use_count);
@ -1775,6 +1812,75 @@ void usb_hcd_reset_endpoint(struct usb_device *udev,
}
}
/**
* usb_alloc_streams - allocate bulk endpoint stream IDs.
* @interface: alternate setting that includes all endpoints.
* @eps: array of endpoints that need streams.
* @num_eps: number of endpoints in the array.
* @num_streams: number of streams to allocate.
* @mem_flags: flags hcd should use to allocate memory.
*
* Sets up a group of bulk endpoints to have num_streams stream IDs available.
* Drivers may queue multiple transfers to different stream IDs, which may
* complete in a different order than they were queued.
*/
int usb_alloc_streams(struct usb_interface *interface,
struct usb_host_endpoint **eps, unsigned int num_eps,
unsigned int num_streams, gfp_t mem_flags)
{
struct usb_hcd *hcd;
struct usb_device *dev;
int i;
dev = interface_to_usbdev(interface);
hcd = bus_to_hcd(dev->bus);
if (!hcd->driver->alloc_streams || !hcd->driver->free_streams)
return -EINVAL;
if (dev->speed != USB_SPEED_SUPER)
return -EINVAL;
/* Streams only apply to bulk endpoints. */
for (i = 0; i < num_eps; i++)
if (!usb_endpoint_xfer_bulk(&eps[i]->desc))
return -EINVAL;
return hcd->driver->alloc_streams(hcd, dev, eps, num_eps,
num_streams, mem_flags);
}
EXPORT_SYMBOL_GPL(usb_alloc_streams);
/**
* usb_free_streams - free bulk endpoint stream IDs.
* @interface: alternate setting that includes all endpoints.
* @eps: array of endpoints to remove streams from.
* @num_eps: number of endpoints in the array.
* @mem_flags: flags hcd should use to allocate memory.
*
* Reverts a group of bulk endpoints back to not using stream IDs.
* Can fail if we are given bad arguments, or HCD is broken.
*/
void usb_free_streams(struct usb_interface *interface,
struct usb_host_endpoint **eps, unsigned int num_eps,
gfp_t mem_flags)
{
struct usb_hcd *hcd;
struct usb_device *dev;
int i;
dev = interface_to_usbdev(interface);
hcd = bus_to_hcd(dev->bus);
if (dev->speed != USB_SPEED_SUPER)
return;
/* Streams only apply to bulk endpoints. */
for (i = 0; i < num_eps; i++)
if (!usb_endpoint_xfer_bulk(&eps[i]->desc))
return;
hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
}
EXPORT_SYMBOL_GPL(usb_free_streams);
/* Protect against drivers that try to unlink URBs after the device
* is gone, by waiting until all unlinks for @udev are finished.
* Since we don't currently track URBs by device, simply wait until

View file

@ -1,578 +0,0 @@
/*
* Copyright (c) 2001-2002 by David Brownell
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __USB_CORE_HCD_H
#define __USB_CORE_HCD_H
#ifdef __KERNEL__
#include <linux/rwsem.h>
#define MAX_TOPO_LEVEL 6
/* This file contains declarations of usbcore internals that are mostly
* used or exposed by Host Controller Drivers.
*/
/*
* USB Packet IDs (PIDs)
*/
#define USB_PID_EXT 0xf0 /* USB 2.0 LPM ECN */
#define USB_PID_OUT 0xe1
#define USB_PID_ACK 0xd2
#define USB_PID_DATA0 0xc3
#define USB_PID_PING 0xb4 /* USB 2.0 */
#define USB_PID_SOF 0xa5
#define USB_PID_NYET 0x96 /* USB 2.0 */
#define USB_PID_DATA2 0x87 /* USB 2.0 */
#define USB_PID_SPLIT 0x78 /* USB 2.0 */
#define USB_PID_IN 0x69
#define USB_PID_NAK 0x5a
#define USB_PID_DATA1 0x4b
#define USB_PID_PREAMBLE 0x3c /* Token mode */
#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */
#define USB_PID_SETUP 0x2d
#define USB_PID_STALL 0x1e
#define USB_PID_MDATA 0x0f /* USB 2.0 */
/*-------------------------------------------------------------------------*/
/*
* USB Host Controller Driver (usb_hcd) framework
*
* Since "struct usb_bus" is so thin, you can't share much code in it.
* This framework is a layer over that, and should be more sharable.
*
* @authorized_default: Specifies if new devices are authorized to
* connect by default or they require explicit
* user space authorization; this bit is settable
* through /sys/class/usb_host/X/authorized_default.
* For the rest is RO, so we don't lock to r/w it.
*/
/*-------------------------------------------------------------------------*/
struct usb_hcd {
/*
* housekeeping
*/
struct usb_bus self; /* hcd is-a bus */
struct kref kref; /* reference counter */
const char *product_desc; /* product/vendor string */
char irq_descr[24]; /* driver + bus # */
struct timer_list rh_timer; /* drives root-hub polling */
struct urb *status_urb; /* the current status urb */
#ifdef CONFIG_USB_SUSPEND
struct work_struct wakeup_work; /* for remote wakeup */
#endif
/*
* hardware info/state
*/
const struct hc_driver *driver; /* hw-specific hooks */
/* Flags that need to be manipulated atomically */
unsigned long flags;
#define HCD_FLAG_HW_ACCESSIBLE 0x00000001
#define HCD_FLAG_SAW_IRQ 0x00000002
unsigned rh_registered:1;/* is root hub registered? */
/* The next flag is a stopgap, to be removed when all the HCDs
* support the new root-hub polling mechanism. */
unsigned uses_new_polling:1;
unsigned poll_rh:1; /* poll for rh status? */
unsigned poll_pending:1; /* status has changed? */
unsigned wireless:1; /* Wireless USB HCD */
unsigned authorized_default:1;
unsigned has_tt:1; /* Integrated TT in root hub */
int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */
u64 rsrc_start; /* memory/io resource start */
u64 rsrc_len; /* memory/io resource length */
unsigned power_budget; /* in mA, 0 = no limit */
/* bandwidth_mutex should be taken before adding or removing
* any new bus bandwidth constraints:
* 1. Before adding a configuration for a new device.
* 2. Before removing the configuration to put the device into
* the addressed state.
* 3. Before selecting a different configuration.
* 4. Before selecting an alternate interface setting.
*
* bandwidth_mutex should be dropped after a successful control message
* to the device, or resetting the bandwidth after a failed attempt.
*/
struct mutex bandwidth_mutex;
#define HCD_BUFFER_POOLS 4
struct dma_pool *pool [HCD_BUFFER_POOLS];
int state;
# define __ACTIVE 0x01
# define __SUSPEND 0x04
# define __TRANSIENT 0x80
# define HC_STATE_HALT 0
# define HC_STATE_RUNNING (__ACTIVE)
# define HC_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
# define HC_STATE_RESUMING (__SUSPEND|__TRANSIENT)
# define HC_STATE_SUSPENDED (__SUSPEND)
#define HC_IS_RUNNING(state) ((state) & __ACTIVE)
#define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)
/* more shared queuing code would be good; it should support
* smarter scheduling, handle transaction translators, etc;
* input size of periodic table to an interrupt scheduler.
* (ohci 32, uhci 1024, ehci 256/512/1024).
*/
/* The HC driver's private data is stored at the end of
* this structure.
*/
unsigned long hcd_priv[0]
__attribute__ ((aligned(sizeof(unsigned long))));
};
/* 2.4 does this a bit differently ... */
static inline struct usb_bus *hcd_to_bus(struct usb_hcd *hcd)
{
return &hcd->self;
}
static inline struct usb_hcd *bus_to_hcd(struct usb_bus *bus)
{
return container_of(bus, struct usb_hcd, self);
}
struct hcd_timeout { /* timeouts we allocate */
struct list_head timeout_list;
struct timer_list timer;
};
/*-------------------------------------------------------------------------*/
struct hc_driver {
const char *description; /* "ehci-hcd" etc */
const char *product_desc; /* product/vendor string */
size_t hcd_priv_size; /* size of private data */
/* irq handler */
irqreturn_t (*irq) (struct usb_hcd *hcd);
int flags;
#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */
#define HCD_LOCAL_MEM 0x0002 /* HC needs local memory */
#define HCD_USB11 0x0010 /* USB 1.1 */
#define HCD_USB2 0x0020 /* USB 2.0 */
#define HCD_USB3 0x0040 /* USB 3.0 */
#define HCD_MASK 0x0070
/* called to init HCD and root hub */
int (*reset) (struct usb_hcd *hcd);
int (*start) (struct usb_hcd *hcd);
/* NOTE: these suspend/resume calls relate to the HC as
* a whole, not just the root hub; they're for PCI bus glue.
*/
/* called after suspending the hub, before entering D3 etc */
int (*pci_suspend)(struct usb_hcd *hcd);
/* called after entering D0 (etc), before resuming the hub */
int (*pci_resume)(struct usb_hcd *hcd, bool hibernated);
/* cleanly make HCD stop writing memory and doing I/O */
void (*stop) (struct usb_hcd *hcd);
/* shutdown HCD */
void (*shutdown) (struct usb_hcd *hcd);
/* return current frame number */
int (*get_frame_number) (struct usb_hcd *hcd);
/* manage i/o requests, device state */
int (*urb_enqueue)(struct usb_hcd *hcd,
struct urb *urb, gfp_t mem_flags);
int (*urb_dequeue)(struct usb_hcd *hcd,
struct urb *urb, int status);
/* hw synch, freeing endpoint resources that urb_dequeue can't */
void (*endpoint_disable)(struct usb_hcd *hcd,
struct usb_host_endpoint *ep);
/* (optional) reset any endpoint state such as sequence number
and current window */
void (*endpoint_reset)(struct usb_hcd *hcd,
struct usb_host_endpoint *ep);
/* root hub support */
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
int (*hub_control) (struct usb_hcd *hcd,
u16 typeReq, u16 wValue, u16 wIndex,
char *buf, u16 wLength);
int (*bus_suspend)(struct usb_hcd *);
int (*bus_resume)(struct usb_hcd *);
int (*start_port_reset)(struct usb_hcd *, unsigned port_num);
/* force handover of high-speed port to full-speed companion */
void (*relinquish_port)(struct usb_hcd *, int);
/* has a port been handed over to a companion? */
int (*port_handed_over)(struct usb_hcd *, int);
/* CLEAR_TT_BUFFER completion callback */
void (*clear_tt_buffer_complete)(struct usb_hcd *,
struct usb_host_endpoint *);
/* xHCI specific functions */
/* Called by usb_alloc_dev to alloc HC device structures */
int (*alloc_dev)(struct usb_hcd *, struct usb_device *);
/* Called by usb_disconnect to free HC device structures */
void (*free_dev)(struct usb_hcd *, struct usb_device *);
/* Bandwidth computation functions */
/* Note that add_endpoint() can only be called once per endpoint before
* check_bandwidth() or reset_bandwidth() must be called.
* drop_endpoint() can only be called once per endpoint also.
* A call to xhci_drop_endpoint() followed by a call to xhci_add_endpoint() will
* add the endpoint to the schedule with possibly new parameters denoted by a
* different endpoint descriptor in usb_host_endpoint.
* A call to xhci_add_endpoint() followed by a call to xhci_drop_endpoint() is
* not allowed.
*/
/* Allocate endpoint resources and add them to a new schedule */
int (*add_endpoint)(struct usb_hcd *, struct usb_device *, struct usb_host_endpoint *);
/* Drop an endpoint from a new schedule */
int (*drop_endpoint)(struct usb_hcd *, struct usb_device *, struct usb_host_endpoint *);
/* Check that a new hardware configuration, set using
* endpoint_enable and endpoint_disable, does not exceed bus
* bandwidth. This must be called before any set configuration
* or set interface requests are sent to the device.
*/
int (*check_bandwidth)(struct usb_hcd *, struct usb_device *);
/* Reset the device schedule to the last known good schedule,
* which was set from a previous successful call to
* check_bandwidth(). This reverts any add_endpoint() and
* drop_endpoint() calls since that last successful call.
* Used for when a check_bandwidth() call fails due to resource
* or bandwidth constraints.
*/
void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
/* Returns the hardware-chosen device address */
int (*address_device)(struct usb_hcd *, struct usb_device *udev);
/* Notifies the HCD after a hub descriptor is fetched.
* Will block.
*/
int (*update_hub_device)(struct usb_hcd *, struct usb_device *hdev,
struct usb_tt *tt, gfp_t mem_flags);
int (*reset_device)(struct usb_hcd *, struct usb_device *);
};
extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
int status);
extern void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb);
extern int usb_hcd_submit_urb(struct urb *urb, gfp_t mem_flags);
extern int usb_hcd_unlink_urb(struct urb *urb, int status);
extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb,
int status);
extern void usb_hcd_flush_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep);
extern void usb_hcd_disable_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep);
extern void usb_hcd_reset_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep);
extern void usb_hcd_synchronize_unlinks(struct usb_device *udev);
extern int usb_hcd_alloc_bandwidth(struct usb_device *udev,
struct usb_host_config *new_config,
struct usb_host_interface *old_alt,
struct usb_host_interface *new_alt);
extern int usb_hcd_get_frame_number(struct usb_device *udev);
extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
struct device *dev, const char *bus_name);
extern struct usb_hcd *usb_get_hcd(struct usb_hcd *hcd);
extern void usb_put_hcd(struct usb_hcd *hcd);
extern int usb_add_hcd(struct usb_hcd *hcd,
unsigned int irqnum, unsigned long irqflags);
extern void usb_remove_hcd(struct usb_hcd *hcd);
struct platform_device;
extern void usb_hcd_platform_shutdown(struct platform_device *dev);
#ifdef CONFIG_PCI
struct pci_dev;
struct pci_device_id;
extern int usb_hcd_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id);
extern void usb_hcd_pci_remove(struct pci_dev *dev);
extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
#ifdef CONFIG_PM_SLEEP
extern const struct dev_pm_ops usb_hcd_pci_pm_ops;
#endif
#endif /* CONFIG_PCI */
/* pci-ish (pdev null is ok) buffer alloc/mapping support */
int hcd_buffer_create(struct usb_hcd *hcd);
void hcd_buffer_destroy(struct usb_hcd *hcd);
void *hcd_buffer_alloc(struct usb_bus *bus, size_t size,
gfp_t mem_flags, dma_addr_t *dma);
void hcd_buffer_free(struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
/* generic bus glue, needed for host controllers that don't use PCI */
extern irqreturn_t usb_hcd_irq(int irq, void *__hcd);
extern void usb_hc_died(struct usb_hcd *hcd);
extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
/* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep)))
#define usb_settoggle(dev, ep, out, bit) \
((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | \
((bit) << (ep)))
/* -------------------------------------------------------------------------- */
/* Enumeration is only for the hub driver, or HCD virtual root hubs */
extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
struct usb_bus *, unsigned port);
extern int usb_new_device(struct usb_device *dev);
extern void usb_disconnect(struct usb_device **);
extern int usb_get_configuration(struct usb_device *dev);
extern void usb_destroy_configuration(struct usb_device *dev);
/*-------------------------------------------------------------------------*/
/*
* HCD Root Hub support
*/
#include "hub.h"
/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
#define DeviceRequest \
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
#define DeviceOutRequest \
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
#define InterfaceRequest \
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
#define EndpointRequest \
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
#define EndpointOutRequest \
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
/* class requests from the USB 2.0 hub spec, table 11-15 */
/* GetBusState and SetHubDescriptor are optional, omitted */
#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE)
#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE)
#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR)
#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS)
#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS)
#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE)
#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE)
/*-------------------------------------------------------------------------*/
/*
* Generic bandwidth allocation constants/support
*/
#define FRAME_TIME_USECS 1000L
#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
/* Trying not to use worst-case bit-stuffing
* of (7/6 * 8 * bytecount) = 9.33 * bytecount */
/* bytecount = data payload byte count */
#define NS_TO_US(ns) ((ns + 500L) / 1000L)
/* convert & round nanoseconds to microseconds */
/*
* Full/low speed bandwidth allocation constants/support.
*/
#define BW_HOST_DELAY 1000L /* nanoseconds */
#define BW_HUB_LS_SETUP 333L /* nanoseconds */
/* 4 full-speed bit times (est.) */
#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */
#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L)
#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L)
/*
* Ceiling [nano/micro]seconds (typical) for that many bytes at high speed
* ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed
* to preallocate bandwidth)
*/
#define USB2_HOST_DELAY 5 /* nsec, guess */
#define HS_NSECS(bytes) (((55 * 8 * 2083) \
+ (2083UL * (3 + BitTime(bytes))))/1000 \
+ USB2_HOST_DELAY)
#define HS_NSECS_ISO(bytes) (((38 * 8 * 2083) \
+ (2083UL * (3 + BitTime(bytes))))/1000 \
+ USB2_HOST_DELAY)
#define HS_USECS(bytes) NS_TO_US (HS_NSECS(bytes))
#define HS_USECS_ISO(bytes) NS_TO_US (HS_NSECS_ISO(bytes))
extern long usb_calc_bus_time(int speed, int is_input,
int isoc, int bytecount);
/*-------------------------------------------------------------------------*/
extern void usb_set_device_state(struct usb_device *udev,
enum usb_device_state new_state);
/*-------------------------------------------------------------------------*/
/* exported only within usbcore */
extern struct list_head usb_bus_list;
extern struct mutex usb_bus_list_lock;
extern wait_queue_head_t usb_kill_urb_queue;
extern int usb_find_interface_driver(struct usb_device *dev,
struct usb_interface *interface);
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
#ifdef CONFIG_PM
extern void usb_root_hub_lost_power(struct usb_device *rhdev);
extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg);
extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg);
#endif /* CONFIG_PM */
#ifdef CONFIG_USB_SUSPEND
extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
#else
static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
{
return;
}
#endif /* CONFIG_USB_SUSPEND */
/*
* USB device fs stuff
*/
#ifdef CONFIG_USB_DEVICEFS
/*
* these are expected to be called from the USB core/hub thread
* with the kernel lock held
*/
extern void usbfs_update_special(void);
extern int usbfs_init(void);
extern void usbfs_cleanup(void);
#else /* CONFIG_USB_DEVICEFS */
static inline void usbfs_update_special(void) {}
static inline int usbfs_init(void) { return 0; }
static inline void usbfs_cleanup(void) { }
#endif /* CONFIG_USB_DEVICEFS */
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
struct usb_mon_operations {
void (*urb_submit)(struct usb_bus *bus, struct urb *urb);
void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err);
void (*urb_complete)(struct usb_bus *bus, struct urb *urb, int status);
/* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */
};
extern struct usb_mon_operations *mon_ops;
static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb)
{
if (bus->monitored)
(*mon_ops->urb_submit)(bus, urb);
}
static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
int error)
{
if (bus->monitored)
(*mon_ops->urb_submit_error)(bus, urb, error);
}
static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
int status)
{
if (bus->monitored)
(*mon_ops->urb_complete)(bus, urb, status);
}
int usb_mon_register(struct usb_mon_operations *ops);
void usb_mon_deregister(void);
#else
static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {}
static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
int error) {}
static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
int status) {}
#endif /* CONFIG_USB_MON || CONFIG_USB_MON_MODULE */
/*-------------------------------------------------------------------------*/
/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
/* bleech -- resurfaced in 2.4.11 or 2.4.12 */
#define bitmap DeviceRemovable
/*-------------------------------------------------------------------------*/
/* random stuff */
#define RUN_CONTEXT (in_irq() ? "in_irq" \
: (in_interrupt() ? "in_interrupt" : "can sleep"))
/* This rwsem is for use only by the hub driver and ehci-hcd.
* Nobody else should touch it.
*/
extern struct rw_semaphore ehci_cf_port_reset_rwsem;
/* Keep track of which host controller drivers are loaded */
#define USB_UHCI_LOADED 0
#define USB_OHCI_LOADED 1
#define USB_EHCI_LOADED 2
extern unsigned long usb_hcds_loaded;
#endif /* __KERNEL__ */
#endif /* __USB_CORE_HCD_H */

View file

@ -19,6 +19,7 @@
#include <linux/ioctl.h>
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
#include <linux/usb/hcd.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
#include <linux/freezer.h>
@ -28,8 +29,6 @@
#include <asm/byteorder.h>
#include "usb.h"
#include "hcd.h"
#include "hub.h"
/* if we are in debug mode, always announce new devices */
#ifdef DEBUG
@ -154,11 +153,11 @@ static int usb_reset_and_verify_device(struct usb_device *udev);
static inline char *portspeed(int portstatus)
{
if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED))
if (portstatus & USB_PORT_STAT_HIGH_SPEED)
return "480 Mb/s";
else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED))
else if (portstatus & USB_PORT_STAT_LOW_SPEED)
return "1.5 Mb/s";
else if (portstatus & (1 << USB_PORT_FEAT_SUPERSPEED))
else if (portstatus & USB_PORT_STAT_SUPER_SPEED)
return "5.0 Gb/s";
else
return "12 Mb/s";
@ -745,8 +744,20 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
!(portstatus & USB_PORT_STAT_CONNECTION) ||
!udev ||
udev->state == USB_STATE_NOTATTACHED)) {
clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
portstatus &= ~USB_PORT_STAT_ENABLE;
/*
* USB3 protocol ports will automatically transition
* to Enabled state when detect an USB3.0 device attach.
* Do not disable USB3 protocol ports.
* FIXME: USB3 root hub and external hubs are treated
* differently here.
*/
if (hdev->descriptor.bDeviceProtocol != 3 ||
(!hdev->parent &&
!(portstatus & USB_PORT_STAT_SUPER_SPEED))) {
clear_port_feature(hdev, port1,
USB_PORT_FEAT_ENABLE);
portstatus &= ~USB_PORT_STAT_ENABLE;
}
}
/* Clear status-change flags; we'll debounce later */
@ -1784,7 +1795,6 @@ int usb_new_device(struct usb_device *udev)
* sysfs power/wakeup controls wakeup enabled/disabled
*/
device_init_wakeup(&udev->dev, 0);
device_set_wakeup_enable(&udev->dev, 1);
}
/* Tell the runtime-PM framework the device is active */
@ -3038,7 +3048,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
/* maybe switch power back on (e.g. root hub was reset) */
if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
&& !(portstatus & (1 << USB_PORT_FEAT_POWER)))
&& !(portstatus & USB_PORT_STAT_POWER))
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
if (portstatus & USB_PORT_STAT_ENABLE)
@ -3076,7 +3086,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if (!(hcd->driver->flags & HCD_USB3))
udev->speed = USB_SPEED_UNKNOWN;
else if ((hdev->parent == NULL) &&
(portstatus & (1 << USB_PORT_FEAT_SUPERSPEED)))
(portstatus & USB_PORT_STAT_SUPER_SPEED))
udev->speed = USB_SPEED_SUPER;
else
udev->speed = USB_SPEED_UNKNOWN;

View file

@ -1,205 +0,0 @@
#ifndef __LINUX_HUB_H
#define __LINUX_HUB_H
/*
* Hub protocol and driver data structures.
*
* Some of these are known to the "virtual root hub" code
* in host controller drivers.
*/
#include <linux/list.h>
#include <linux/workqueue.h>
#include <linux/compiler.h> /* likely()/unlikely() */
/*
* Hub request types
*/
#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
/*
* Hub class requests
* See USB 2.0 spec Table 11-16
*/
#define HUB_CLEAR_TT_BUFFER 8
#define HUB_RESET_TT 9
#define HUB_GET_TT_STATE 10
#define HUB_STOP_TT 11
/*
* Hub Class feature numbers
* See USB 2.0 spec Table 11-17
*/
#define C_HUB_LOCAL_POWER 0
#define C_HUB_OVER_CURRENT 1
/*
* Port feature numbers
* See USB 2.0 spec Table 11-17
*/
#define USB_PORT_FEAT_CONNECTION 0
#define USB_PORT_FEAT_ENABLE 1
#define USB_PORT_FEAT_SUSPEND 2 /* L2 suspend */
#define USB_PORT_FEAT_OVER_CURRENT 3
#define USB_PORT_FEAT_RESET 4
#define USB_PORT_FEAT_L1 5 /* L1 suspend */
#define USB_PORT_FEAT_POWER 8
#define USB_PORT_FEAT_LOWSPEED 9
/* This value was never in Table 11-17 */
#define USB_PORT_FEAT_HIGHSPEED 10
/* This value is also fake */
#define USB_PORT_FEAT_SUPERSPEED 11
#define USB_PORT_FEAT_C_CONNECTION 16
#define USB_PORT_FEAT_C_ENABLE 17
#define USB_PORT_FEAT_C_SUSPEND 18
#define USB_PORT_FEAT_C_OVER_CURRENT 19
#define USB_PORT_FEAT_C_RESET 20
#define USB_PORT_FEAT_TEST 21
#define USB_PORT_FEAT_INDICATOR 22
#define USB_PORT_FEAT_C_PORT_L1 23
/*
* Hub Status and Hub Change results
* See USB 2.0 spec Table 11-19 and Table 11-20
*/
struct usb_port_status {
__le16 wPortStatus;
__le16 wPortChange;
} __attribute__ ((packed));
/*
* wPortStatus bit field
* See USB 2.0 spec Table 11-21
*/
#define USB_PORT_STAT_CONNECTION 0x0001
#define USB_PORT_STAT_ENABLE 0x0002
#define USB_PORT_STAT_SUSPEND 0x0004
#define USB_PORT_STAT_OVERCURRENT 0x0008
#define USB_PORT_STAT_RESET 0x0010
#define USB_PORT_STAT_L1 0x0020
/* bits 6 to 7 are reserved */
#define USB_PORT_STAT_POWER 0x0100
#define USB_PORT_STAT_LOW_SPEED 0x0200
#define USB_PORT_STAT_HIGH_SPEED 0x0400
#define USB_PORT_STAT_TEST 0x0800
#define USB_PORT_STAT_INDICATOR 0x1000
/* bits 13 to 15 are reserved */
/*
* wPortChange bit field
* See USB 2.0 spec Table 11-22
* Bits 0 to 4 shown, bits 5 to 15 are reserved
*/
#define USB_PORT_STAT_C_CONNECTION 0x0001
#define USB_PORT_STAT_C_ENABLE 0x0002
#define USB_PORT_STAT_C_SUSPEND 0x0004
#define USB_PORT_STAT_C_OVERCURRENT 0x0008
#define USB_PORT_STAT_C_RESET 0x0010
#define USB_PORT_STAT_C_L1 0x0020
/*
* wHubCharacteristics (masks)
* See USB 2.0 spec Table 11-13, offset 3
*/
#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */
#define HUB_CHAR_COMPOUND 0x0004 /* D2 */
#define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */
#define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */
#define HUB_CHAR_PORTIND 0x0080 /* D7 */
struct usb_hub_status {
__le16 wHubStatus;
__le16 wHubChange;
} __attribute__ ((packed));
/*
* Hub Status & Hub Change bit masks
* See USB 2.0 spec Table 11-19 and Table 11-20
* Bits 0 and 1 for wHubStatus and wHubChange
* Bits 2 to 15 are reserved for both
*/
#define HUB_STATUS_LOCAL_POWER 0x0001
#define HUB_STATUS_OVERCURRENT 0x0002
#define HUB_CHANGE_LOCAL_POWER 0x0001
#define HUB_CHANGE_OVERCURRENT 0x0002
/*
* Hub descriptor
* See USB 2.0 spec Table 11-13
*/
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
#define USB_DT_HUB_NONVAR_SIZE 7
struct usb_hub_descriptor {
__u8 bDescLength;
__u8 bDescriptorType;
__u8 bNbrPorts;
__le16 wHubCharacteristics;
__u8 bPwrOn2PwrGood;
__u8 bHubContrCurrent;
/* add 1 bit for hub status change; round to bytes */
__u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
__u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
} __attribute__ ((packed));
/* port indicator status selectors, tables 11-7 and 11-25 */
#define HUB_LED_AUTO 0
#define HUB_LED_AMBER 1
#define HUB_LED_GREEN 2
#define HUB_LED_OFF 3
enum hub_led_mode {
INDICATOR_AUTO = 0,
INDICATOR_CYCLE,
/* software blinks for attention: software, hardware, reserved */
INDICATOR_GREEN_BLINK, INDICATOR_GREEN_BLINK_OFF,
INDICATOR_AMBER_BLINK, INDICATOR_AMBER_BLINK_OFF,
INDICATOR_ALT_BLINK, INDICATOR_ALT_BLINK_OFF
} __attribute__ ((packed));
struct usb_device;
/* Transaction Translator Think Times, in bits */
#define HUB_TTTT_8_BITS 0x00
#define HUB_TTTT_16_BITS 0x20
#define HUB_TTTT_24_BITS 0x40
#define HUB_TTTT_32_BITS 0x60
/*
* As of USB 2.0, full/low speed devices are segregated into trees.
* One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
* The other type grows from high speed hubs when they connect to
* full/low speed devices using "Transaction Translators" (TTs).
*
* TTs should only be known to the hub driver, and high speed bus
* drivers (only EHCI for now). They affect periodic scheduling and
* sometimes control/bulk error recovery.
*/
struct usb_tt {
struct usb_device *hub; /* upstream highspeed hub */
int multi; /* true means one TT per port */
unsigned think_time; /* think time in ns */
/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
spinlock_t lock;
struct list_head clear_list; /* of usb_tt_clear */
struct work_struct clear_work;
};
struct usb_tt_clear {
struct list_head clear_list;
unsigned tt;
u16 devinfo;
struct usb_hcd *hcd;
struct usb_host_endpoint *ep;
};
extern int usb_hub_clear_tt_buffer(struct urb *urb);
extern void usb_ep0_reinit(struct usb_device *);
#endif /* __LINUX_HUB_H */

View file

@ -40,9 +40,9 @@
#include <linux/notifier.h>
#include <linux/seq_file.h>
#include <linux/smp_lock.h>
#include <linux/usb/hcd.h>
#include <asm/byteorder.h>
#include "usb.h"
#include "hcd.h"
#define USBFS_DEFAULT_DEVMODE (S_IWUSR | S_IRUGO)
#define USBFS_DEFAULT_BUSMODE (S_IXUGO | S_IRUGO)

View file

@ -14,9 +14,9 @@
#include <linux/device.h>
#include <linux/scatterlist.h>
#include <linux/usb/quirks.h>
#include <linux/usb/hcd.h> /* for usbcore internals */
#include <asm/byteorder.h>
#include "hcd.h" /* for usbcore internals */
#include "usb.h"
static void cancel_async_set_config(struct usb_device *udev);
@ -226,8 +226,7 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
struct urb *urb;
struct usb_host_endpoint *ep;
ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)
[usb_pipeendpoint(pipe)];
ep = usb_pipe_endpoint(usb_dev, pipe);
if (!ep || len < 0)
return -EINVAL;
@ -259,9 +258,6 @@ static void sg_clean(struct usb_sg_request *io)
kfree(io->urbs);
io->urbs = NULL;
}
if (io->dev->dev.dma_mask != NULL)
usb_buffer_unmap_sg(io->dev, usb_pipein(io->pipe),
io->sg, io->nents);
io->dev = NULL;
}
@ -364,7 +360,6 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
{
int i;
int urb_flags;
int dma;
int use_sg;
if (!io || !dev || !sg
@ -376,114 +371,76 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
spin_lock_init(&io->lock);
io->dev = dev;
io->pipe = pipe;
io->sg = sg;
io->nents = nents;
/* not all host controllers use DMA (like the mainstream pci ones);
* they can use PIO (sl811) or be software over another transport.
*/
dma = (dev->dev.dma_mask != NULL);
if (dma)
io->entries = usb_buffer_map_sg(dev, usb_pipein(pipe),
sg, nents);
else
io->entries = nents;
/* initialize all the urbs we'll use */
if (io->entries <= 0)
return io->entries;
if (dev->bus->sg_tablesize > 0) {
io->urbs = kmalloc(sizeof *io->urbs, mem_flags);
use_sg = true;
io->entries = 1;
} else {
io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags);
use_sg = false;
io->entries = nents;
}
/* initialize all the urbs we'll use */
io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags);
if (!io->urbs)
goto nomem;
urb_flags = 0;
if (dma)
urb_flags |= URB_NO_TRANSFER_DMA_MAP;
urb_flags = URB_NO_INTERRUPT;
if (usb_pipein(pipe))
urb_flags |= URB_SHORT_NOT_OK;
if (use_sg) {
io->urbs[0] = usb_alloc_urb(0, mem_flags);
if (!io->urbs[0]) {
io->entries = 0;
for_each_sg(sg, sg, io->entries, i) {
struct urb *urb;
unsigned len;
urb = usb_alloc_urb(0, mem_flags);
if (!urb) {
io->entries = i;
goto nomem;
}
io->urbs[i] = urb;
io->urbs[0]->dev = NULL;
io->urbs[0]->pipe = pipe;
io->urbs[0]->interval = period;
io->urbs[0]->transfer_flags = urb_flags;
urb->dev = NULL;
urb->pipe = pipe;
urb->interval = period;
urb->transfer_flags = urb_flags;
urb->complete = sg_complete;
urb->context = io;
urb->sg = sg;
io->urbs[0]->complete = sg_complete;
io->urbs[0]->context = io;
/* A length of zero means transfer the whole sg list */
io->urbs[0]->transfer_buffer_length = length;
if (length == 0) {
for_each_sg(sg, sg, io->entries, i) {
io->urbs[0]->transfer_buffer_length +=
sg_dma_len(sg);
if (use_sg) {
/* There is no single transfer buffer */
urb->transfer_buffer = NULL;
urb->num_sgs = nents;
/* A length of zero means transfer the whole sg list */
len = length;
if (len == 0) {
for_each_sg(sg, sg, nents, i)
len += sg->length;
}
}
io->urbs[0]->sg = io;
io->urbs[0]->num_sgs = io->entries;
io->entries = 1;
} else {
urb_flags |= URB_NO_INTERRUPT;
for_each_sg(sg, sg, io->entries, i) {
unsigned len;
io->urbs[i] = usb_alloc_urb(0, mem_flags);
if (!io->urbs[i]) {
io->entries = i;
goto nomem;
}
io->urbs[i]->dev = NULL;
io->urbs[i]->pipe = pipe;
io->urbs[i]->interval = period;
io->urbs[i]->transfer_flags = urb_flags;
io->urbs[i]->complete = sg_complete;
io->urbs[i]->context = io;
} else {
/*
* Some systems need to revert to PIO when DMA is temporarily
* unavailable. For their sakes, both transfer_buffer and
* transfer_dma are set when possible.
*
* Note that if IOMMU coalescing occurred, we cannot
* trust sg_page anymore, so check if S/G list shrunk.
* Some systems can't use DMA; they use PIO instead.
* For their sakes, transfer_buffer is set whenever
* possible.
*/
if (io->nents == io->entries && !PageHighMem(sg_page(sg)))
io->urbs[i]->transfer_buffer = sg_virt(sg);
if (!PageHighMem(sg_page(sg)))
urb->transfer_buffer = sg_virt(sg);
else
io->urbs[i]->transfer_buffer = NULL;
if (dma) {
io->urbs[i]->transfer_dma = sg_dma_address(sg);
len = sg_dma_len(sg);
} else {
/* hc may use _only_ transfer_buffer */
len = sg->length;
}
urb->transfer_buffer = NULL;
len = sg->length;
if (length) {
len = min_t(unsigned, len, length);
length -= len;
if (length == 0)
io->entries = i + 1;
}
io->urbs[i]->transfer_buffer_length = len;
}
io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
urb->transfer_buffer_length = len;
}
io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
/* transaction state */
io->count = io->entries;

View file

@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* SKYMEDI USB_DRIVE */
{ USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },
/* BUILDWIN Photo Frame */
{ USB_DEVICE(0x1908, 0x1315), .driver_info =
USB_QUIRK_HONOR_BNUMINTERFACES },
/* INTEL VALUE SSD */
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },

View file

@ -383,13 +383,24 @@ static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
static const char on_string[] = "on";
static const char auto_string[] = "auto";
static void warn_level(void) {
static int level_warned;
if (!level_warned) {
level_warned = 1;
printk(KERN_WARNING "WARNING! power/level is deprecated; "
"use power/control instead\n");
}
}
static ssize_t
show_level(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_device *udev = to_usb_device(dev);
const char *p = auto_string;
if (udev->state != USB_STATE_SUSPENDED && udev->autosuspend_disabled)
warn_level();
if (udev->state != USB_STATE_SUSPENDED && !udev->dev.power.runtime_auto)
p = on_string;
return sprintf(buf, "%s\n", p);
}
@ -401,8 +412,9 @@ set_level(struct device *dev, struct device_attribute *attr,
struct usb_device *udev = to_usb_device(dev);
int len = count;
char *cp;
int rc;
int rc = count;
warn_level();
cp = memchr(buf, '\n', count);
if (cp)
len = cp - buf;
@ -411,17 +423,17 @@ set_level(struct device *dev, struct device_attribute *attr,
if (len == sizeof on_string - 1 &&
strncmp(buf, on_string, len) == 0)
rc = usb_disable_autosuspend(udev);
usb_disable_autosuspend(udev);
else if (len == sizeof auto_string - 1 &&
strncmp(buf, auto_string, len) == 0)
rc = usb_enable_autosuspend(udev);
usb_enable_autosuspend(udev);
else
rc = -EINVAL;
usb_unlock_device(udev);
return (rc < 0 ? rc : count);
return rc;
}
static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);

View file

@ -6,7 +6,7 @@
#include <linux/log2.h>
#include <linux/usb.h>
#include <linux/wait.h>
#include "hcd.h"
#include <linux/usb/hcd.h>
#define to_urb(d) container_of(d, struct urb, kref)
@ -308,8 +308,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
* will be required to set urb->ep directly and we will eliminate
* urb->pipe.
*/
ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out)
[usb_pipeendpoint(urb->pipe)];
ep = usb_pipe_endpoint(dev, urb->pipe);
if (!ep)
return -ENOENT;
@ -333,9 +332,12 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
is_out = usb_endpoint_dir_out(&ep->desc);
}
/* Cache the direction for later use */
urb->transfer_flags = (urb->transfer_flags & ~URB_DIR_MASK) |
(is_out ? URB_DIR_OUT : URB_DIR_IN);
/* Clear the internal flags and cache the direction for later use */
urb->transfer_flags &= ~(URB_DIR_MASK | URB_DMA_MAP_SINGLE |
URB_DMA_MAP_PAGE | URB_DMA_MAP_SG | URB_MAP_LOCAL |
URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
URB_DMA_SG_COMBINED);
urb->transfer_flags |= (is_out ? URB_DIR_OUT : URB_DIR_IN);
if (xfertype != USB_ENDPOINT_XFER_CONTROL &&
dev->state < USB_STATE_CONFIGURED)
@ -396,8 +398,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
return -EPIPE; /* The most suitable error code :-) */
/* enforce simple/standard policy */
allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
URB_NO_INTERRUPT | URB_DIR_MASK | URB_FREE_BUFFER);
allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK |
URB_FREE_BUFFER);
switch (xfertype) {
case USB_ENDPOINT_XFER_BULK:
if (is_out)

View file

@ -32,6 +32,7 @@
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <linux/debugfs.h>
@ -41,7 +42,6 @@
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include "hcd.h"
#include "usb.h"
@ -593,76 +593,6 @@ int usb_lock_device_for_reset(struct usb_device *udev,
}
EXPORT_SYMBOL_GPL(usb_lock_device_for_reset);
static struct usb_device *match_device(struct usb_device *dev,
u16 vendor_id, u16 product_id)
{
struct usb_device *ret_dev = NULL;
int child;
dev_dbg(&dev->dev, "check for vendor %04x, product %04x ...\n",
le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
/* see if this device matches */
if ((vendor_id == le16_to_cpu(dev->descriptor.idVendor)) &&
(product_id == le16_to_cpu(dev->descriptor.idProduct))) {
dev_dbg(&dev->dev, "matched this device!\n");
ret_dev = usb_get_dev(dev);
goto exit;
}
/* look through all of the children of this device */
for (child = 0; child < dev->maxchild; ++child) {
if (dev->children[child]) {
usb_lock_device(dev->children[child]);
ret_dev = match_device(dev->children[child],
vendor_id, product_id);
usb_unlock_device(dev->children[child]);
if (ret_dev)
goto exit;
}
}
exit:
return ret_dev;
}
/**
* usb_find_device - find a specific usb device in the system
* @vendor_id: the vendor id of the device to find
* @product_id: the product id of the device to find
*
* Returns a pointer to a struct usb_device if such a specified usb
* device is present in the system currently. The usage count of the
* device will be incremented if a device is found. Make sure to call
* usb_put_dev() when the caller is finished with the device.
*
* If a device with the specified vendor and product id is not found,
* NULL is returned.
*/
struct usb_device *usb_find_device(u16 vendor_id, u16 product_id)
{
struct list_head *buslist;
struct usb_bus *bus;
struct usb_device *dev = NULL;
mutex_lock(&usb_bus_list_lock);
for (buslist = usb_bus_list.next;
buslist != &usb_bus_list;
buslist = buslist->next) {
bus = container_of(buslist, struct usb_bus, bus_list);
if (!bus->root_hub)
continue;
usb_lock_device(bus->root_hub);
dev = match_device(bus->root_hub, vendor_id, product_id);
usb_unlock_device(bus->root_hub);
if (dev)
goto exit;
}
exit:
mutex_unlock(&usb_bus_list_lock);
return dev;
}
/**
* usb_get_current_frame_number - return current bus frame number
* @dev: the device whose bus is being queried
@ -775,7 +705,7 @@ EXPORT_SYMBOL_GPL(usb_free_coherent);
* @urb: urb whose transfer_buffer/setup_packet will be mapped
*
* Return value is either null (indicating no buffer could be mapped), or
* the parameter. URB_NO_TRANSFER_DMA_MAP and URB_NO_SETUP_DMA_MAP are
* the parameter. URB_NO_TRANSFER_DMA_MAP is
* added to urb->transfer_flags if the operation succeeds. If the device
* is connected to this system through a non-DMA controller, this operation
* always succeeds.
@ -803,17 +733,11 @@ struct urb *usb_buffer_map(struct urb *urb)
urb->transfer_buffer, urb->transfer_buffer_length,
usb_pipein(urb->pipe)
? DMA_FROM_DEVICE : DMA_TO_DEVICE);
if (usb_pipecontrol(urb->pipe))
urb->setup_dma = dma_map_single(controller,
urb->setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
/* FIXME generic api broken like pci, can't report errors */
/* if (urb->transfer_dma == DMA_ADDR_INVALID) return 0; */
} else
urb->transfer_dma = ~0;
urb->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
| URB_NO_SETUP_DMA_MAP);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
return urb;
}
EXPORT_SYMBOL_GPL(usb_buffer_map);
@ -881,18 +805,13 @@ void usb_buffer_unmap(struct urb *urb)
urb->transfer_dma, urb->transfer_buffer_length,
usb_pipein(urb->pipe)
? DMA_FROM_DEVICE : DMA_TO_DEVICE);
if (usb_pipecontrol(urb->pipe))
dma_unmap_single(controller,
urb->setup_dma,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
}
urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP
| URB_NO_SETUP_DMA_MAP);
urb->transfer_flags &= ~URB_NO_TRANSFER_DMA_MAP;
}
EXPORT_SYMBOL_GPL(usb_buffer_unmap);
#endif /* 0 */
#if 0
/**
* usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint
* @dev: device to which the scatterlist will be mapped
@ -936,6 +855,7 @@ int usb_buffer_map_sg(const struct usb_device *dev, int is_in,
is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE) ? : -ENOMEM;
}
EXPORT_SYMBOL_GPL(usb_buffer_map_sg);
#endif
/* XXX DISABLED, no users currently. If you wish to re-enable this
* XXX please determine whether the sync is to transfer ownership of
@ -972,6 +892,7 @@ void usb_buffer_dmasync_sg(const struct usb_device *dev, int is_in,
EXPORT_SYMBOL_GPL(usb_buffer_dmasync_sg);
#endif
#if 0
/**
* usb_buffer_unmap_sg - free DMA mapping(s) for a scatterlist
* @dev: device to which the scatterlist will be mapped
@ -997,6 +918,7 @@ void usb_buffer_unmap_sg(const struct usb_device *dev, int is_in,
is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
}
EXPORT_SYMBOL_GPL(usb_buffer_unmap_sg);
#endif
/* To disable USB, kernel command line is 'nousb' not 'usbcore.nousb' */
#ifdef MODULE

View file

@ -710,6 +710,43 @@ config USB_GADGETFS
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "gadgetfs".
config USB_FUNCTIONFS
tristate "Function Filesystem (EXPERIMENTAL)"
depends on EXPERIMENTAL
help
The Function Filesystem (FunctioFS) lets one create USB
composite functions in user space in the same way as GadgetFS
lets one create USB gadgets in user space. This allows creation
of composite gadgets such that some of the functions are
implemented in kernel space (for instance Ethernet, serial or
mass storage) and other are implemented in user space.
Say "y" to link the driver statically, or "m" to build
a dynamically linked module called "g_ffs".
config USB_FUNCTIONFS_ETH
bool "Include CDC ECM (Ethernet) function"
depends on USB_FUNCTIONFS && NET
help
Include an CDC ECM (Ethernet) funcion in the CDC ECM (Funcion)
Filesystem. If you also say "y" to the RNDIS query below the
gadget will have two configurations.
config USB_FUNCTIONFS_RNDIS
bool "Include RNDIS (Ethernet) function"
depends on USB_FUNCTIONFS && NET
help
Include an RNDIS (Ethernet) funcion in the Funcion Filesystem.
If you also say "y" to the CDC ECM query above the gadget will
have two configurations.
config USB_FUNCTIONFS_GENERIC
bool "Include 'pure' configuration"
depends on USB_FUNCTIONFS && (USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
help
Include a configuration with FunctionFS and no Ethernet
configuration.
config USB_FILE_STORAGE
tristate "File-backed Storage Gadget"
depends on BLOCK
@ -863,11 +900,30 @@ config USB_G_MULTI_CDC
If unsure, say "y".
config USB_G_HID
tristate "HID Gadget"
help
The HID gadget driver provides generic emulation of USB
Human Interface Devices (HID).
For more information, see Documentation/usb/gadget_hid.txt which
includes sample code for accessing the device files.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_hid".
# put drivers that need isochronous transfer support (for audio
# or video class gadget drivers), or specific hardware, here.
config USB_G_WEBCAM
tristate "USB Webcam Gadget"
depends on VIDEO_DEV
help
The Webcam Gadget acts as a composite USB Audio and Video Class
device. It provides a userspace API to process UVC control requests
and stream video data to the host.
# - none yet
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_webcam".
endchoice

View file

@ -20,7 +20,7 @@ obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
fsl_usb2_udc-objs := fsl_udc_core.o
ifeq ($(CONFIG_ARCH_MXC),y)
fsl_usb2_udc-objs += fsl_mx3_udc.o
fsl_usb2_udc-objs += fsl_mxc_udc.o
endif
obj-$(CONFIG_USB_M66592) += m66592-udc.o
obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o
@ -43,18 +43,24 @@ g_mass_storage-objs := mass_storage.o
g_printer-objs := printer.o
g_cdc-objs := cdc2.o
g_multi-objs := multi.o
g_hid-objs := hid.o
g_nokia-objs := nokia.o
g_webcam-objs := webcam.o
obj-$(CONFIG_USB_ZERO) += g_zero.o
obj-$(CONFIG_USB_AUDIO) += g_audio.o
obj-$(CONFIG_USB_ETH) += g_ether.o
obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
obj-$(CONFIG_USB_FUNCTIONFS) += g_ffs.o
obj-$(CONFIG_USB_ETH_FUNCTIONFS) += g_eth_ffs.o
obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
obj-$(CONFIG_USB_MASS_STORAGE) += g_mass_storage.o
obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
obj-$(CONFIG_USB_G_PRINTER) += g_printer.o
obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o
obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
obj-$(CONFIG_USB_G_HID) += g_hid.o
obj-$(CONFIG_USB_G_MULTI) += g_multi.o
obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o
obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o

View file

@ -48,10 +48,9 @@ static int queue_dbg_open(struct inode *inode, struct file *file)
spin_lock_irq(&ep->udc->lock);
list_for_each_entry(req, &ep->queue, queue) {
req_copy = kmalloc(sizeof(*req_copy), GFP_ATOMIC);
req_copy = kmemdup(req, sizeof(*req_copy), GFP_ATOMIC);
if (!req_copy)
goto fail;
memcpy(req_copy, req, sizeof(*req_copy));
list_add_tail(&req_copy->queue, queue_data);
}
spin_unlock_irq(&ep->udc->lock);

View file

@ -36,7 +36,7 @@
*/
/* big enough to hold our biggest descriptor */
#define USB_BUFSIZ 512
#define USB_BUFSIZ 1024
static struct usb_composite_driver *composite;
@ -85,7 +85,7 @@ MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
* This function returns the value of the function's bind(), which is
* zero for success else a negative errno value.
*/
int __init usb_add_function(struct usb_configuration *config,
int usb_add_function(struct usb_configuration *config,
struct usb_function *function)
{
int value = -EINVAL;
@ -215,7 +215,7 @@ int usb_function_activate(struct usb_function *function)
* Returns the interface ID which was allocated; or -ENODEV if no
* more interface IDs can be allocated.
*/
int __init usb_interface_id(struct usb_configuration *config,
int usb_interface_id(struct usb_configuration *config,
struct usb_function *function)
{
unsigned id = config->next_interface_id;
@ -480,7 +480,7 @@ done:
* assigns global resources including string IDs, and per-configuration
* resources such as interface IDs and endpoints.
*/
int __init usb_add_config(struct usb_composite_dev *cdev,
int usb_add_config(struct usb_composite_dev *cdev,
struct usb_configuration *config)
{
int status = -EINVAL;
@ -677,7 +677,7 @@ static int get_string(struct usb_composite_dev *cdev,
* ensure that for example different functions don't wrongly assign
* different meanings to the same identifier.
*/
int __init usb_string_id(struct usb_composite_dev *cdev)
int usb_string_id(struct usb_composite_dev *cdev)
{
if (cdev->next_string_id < 254) {
/* string id 0 is reserved */
@ -898,7 +898,19 @@ static void composite_disconnect(struct usb_gadget *gadget)
/*-------------------------------------------------------------------------*/
static void /* __init_or_exit */
static ssize_t composite_show_suspended(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct usb_gadget *gadget = dev_to_usb_gadget(dev);
struct usb_composite_dev *cdev = get_gadget_data(gadget);
return sprintf(buf, "%d\n", cdev->suspended);
}
static DEVICE_ATTR(suspended, 0444, composite_show_suspended, NULL);
static void
composite_unbind(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev = get_gadget_data(gadget);
@ -944,10 +956,11 @@ composite_unbind(struct usb_gadget *gadget)
}
kfree(cdev);
set_gadget_data(gadget, NULL);
device_remove_file(&gadget->dev, &dev_attr_suspended);
composite = NULL;
}
static void __init
static void
string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s)
{
struct usb_string *str = tab->strings;
@ -960,7 +973,7 @@ string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s)
}
}
static void __init
static void
string_override(struct usb_gadget_strings **tab, u8 id, const char *s)
{
while (*tab) {
@ -969,7 +982,7 @@ string_override(struct usb_gadget_strings **tab, u8 id, const char *s)
}
}
static int __init composite_bind(struct usb_gadget *gadget)
static int composite_bind(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev;
int status = -ENOMEM;
@ -1004,6 +1017,14 @@ static int __init composite_bind(struct usb_gadget *gadget)
*/
usb_ep_autoconfig_reset(cdev->gadget);
/* standardized runtime overrides for device ID data */
if (idVendor)
cdev->desc.idVendor = cpu_to_le16(idVendor);
if (idProduct)
cdev->desc.idProduct = cpu_to_le16(idProduct);
if (bcdDevice)
cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
/* composite gadget needs to assign strings for whole device (like
* serial number), register function drivers, potentially update
* power state and consumption, etc
@ -1015,14 +1036,6 @@ static int __init composite_bind(struct usb_gadget *gadget)
cdev->desc = *composite->dev;
cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
/* standardized runtime overrides for device ID data */
if (idVendor)
cdev->desc.idVendor = cpu_to_le16(idVendor);
if (idProduct)
cdev->desc.idProduct = cpu_to_le16(idProduct);
if (bcdDevice)
cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
/* strings can't be assigned before bind() allocates the
* releavnt identifiers
*/
@ -1036,6 +1049,10 @@ static int __init composite_bind(struct usb_gadget *gadget)
string_override(composite->strings,
cdev->desc.iSerialNumber, iSerialNumber);
status = device_create_file(&gadget->dev, &dev_attr_suspended);
if (status)
goto fail;
INFO(cdev, "%s ready\n", composite->name);
return 0;
@ -1064,6 +1081,8 @@ composite_suspend(struct usb_gadget *gadget)
}
if (composite->suspend)
composite->suspend(cdev);
cdev->suspended = 1;
}
static void
@ -1084,6 +1103,8 @@ composite_resume(struct usb_gadget *gadget)
f->resume(f);
}
}
cdev->suspended = 0;
}
/*-------------------------------------------------------------------------*/
@ -1092,7 +1113,6 @@ static struct usb_gadget_driver composite_driver = {
.speed = USB_SPEED_HIGH,
.bind = composite_bind,
/* .unbind = __exit_p(composite_unbind), */
.unbind = composite_unbind,
.setup = composite_setup,
@ -1121,7 +1141,7 @@ static struct usb_gadget_driver composite_driver = {
* while it was binding. That would usually be done in order to wait for
* some userspace participation.
*/
int __init usb_composite_register(struct usb_composite_driver *driver)
int usb_composite_register(struct usb_composite_driver *driver)
{
if (!driver || !driver->dev || !driver->bind || composite)
return -EINVAL;
@ -1142,7 +1162,7 @@ int __init usb_composite_register(struct usb_composite_driver *driver)
* This function is used to unregister drivers using the composite
* driver framework.
*/
void /* __exit */ usb_composite_unregister(struct usb_composite_driver *driver)
void usb_composite_unregister(struct usb_composite_driver *driver)
{
if (composite != driver)
return;

View file

@ -128,7 +128,7 @@ int usb_gadget_config_buf(
* with identifiers (for interfaces, strings, endpoints, and more)
* as needed by a given function instance.
*/
struct usb_descriptor_header **__init
struct usb_descriptor_header **
usb_copy_descriptors(struct usb_descriptor_header **src)
{
struct usb_descriptor_header **tmp;
@ -175,7 +175,7 @@ usb_copy_descriptors(struct usb_descriptor_header **src)
* intended use is to help remembering the endpoint descriptor to use
* when enabling a given endpoint.
*/
struct usb_endpoint_descriptor *__init
struct usb_endpoint_descriptor *
usb_find_endpoint(
struct usb_descriptor_header **src,
struct usb_descriptor_header **copy,

View file

@ -47,6 +47,7 @@
#include <linux/platform_device.h>
#include <linux/usb.h>
#include <linux/usb/gadget.h>
#include <linux/usb/hcd.h>
#include <asm/byteorder.h>
#include <asm/io.h>
@ -55,9 +56,6 @@
#include <asm/unaligned.h>
#include "../core/hcd.h"
#define DRIVER_DESC "USB Host+Gadget Emulator"
#define DRIVER_VERSION "02 May 2005"

View file

@ -34,12 +34,12 @@
/* we must assign addresses for configurable endpoints (like net2280) */
static __initdata unsigned epnum;
static unsigned epnum;
// #define MANY_ENDPOINTS
#ifdef MANY_ENDPOINTS
/* more than 15 configurable endpoints */
static __initdata unsigned in_epnum;
static unsigned in_epnum;
#endif
@ -59,7 +59,7 @@ static __initdata unsigned in_epnum;
* NOTE: each endpoint is unidirectional, as specified by its USB
* descriptor; and isn't specific to a configuration or altsetting.
*/
static int __init
static int
ep_matches (
struct usb_gadget *gadget,
struct usb_ep *ep,
@ -187,7 +187,7 @@ ep_matches (
return 1;
}
static struct usb_ep * __init
static struct usb_ep *
find_ep (struct usb_gadget *gadget, const char *name)
{
struct usb_ep *ep;
@ -229,7 +229,7 @@ find_ep (struct usb_gadget *gadget, const char *name)
*
* On failure, this returns a null endpoint descriptor.
*/
struct usb_ep * __init usb_ep_autoconfig (
struct usb_ep *usb_ep_autoconfig (
struct usb_gadget *gadget,
struct usb_endpoint_descriptor *desc
)
@ -304,7 +304,7 @@ struct usb_ep * __init usb_ep_autoconfig (
* state such as ep->driver_data and the record of assigned endpoints
* used by usb_ep_autoconfig().
*/
void __init usb_ep_autoconfig_reset (struct usb_gadget *gadget)
void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
{
struct usb_ep *ep;

View file

@ -116,7 +116,7 @@ acm_iad_descriptor = {
};
static struct usb_interface_descriptor acm_control_interface_desc __initdata = {
static struct usb_interface_descriptor acm_control_interface_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
@ -127,7 +127,7 @@ static struct usb_interface_descriptor acm_control_interface_desc __initdata = {
/* .iInterface = DYNAMIC */
};
static struct usb_interface_descriptor acm_data_interface_desc __initdata = {
static struct usb_interface_descriptor acm_data_interface_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
@ -138,7 +138,7 @@ static struct usb_interface_descriptor acm_data_interface_desc __initdata = {
/* .iInterface = DYNAMIC */
};
static struct usb_cdc_header_desc acm_header_desc __initdata = {
static struct usb_cdc_header_desc acm_header_desc = {
.bLength = sizeof(acm_header_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
@ -146,7 +146,7 @@ static struct usb_cdc_header_desc acm_header_desc __initdata = {
};
static struct usb_cdc_call_mgmt_descriptor
acm_call_mgmt_descriptor __initdata = {
acm_call_mgmt_descriptor = {
.bLength = sizeof(acm_call_mgmt_descriptor),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
@ -154,14 +154,14 @@ acm_call_mgmt_descriptor __initdata = {
/* .bDataInterface = DYNAMIC */
};
static struct usb_cdc_acm_descriptor acm_descriptor __initdata = {
static struct usb_cdc_acm_descriptor acm_descriptor = {
.bLength = sizeof(acm_descriptor),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_ACM_TYPE,
.bmCapabilities = USB_CDC_CAP_LINE,
};
static struct usb_cdc_union_desc acm_union_desc __initdata = {
static struct usb_cdc_union_desc acm_union_desc = {
.bLength = sizeof(acm_union_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_UNION_TYPE,
@ -171,7 +171,7 @@ static struct usb_cdc_union_desc acm_union_desc __initdata = {
/* full speed support: */
static struct usb_endpoint_descriptor acm_fs_notify_desc __initdata = {
static struct usb_endpoint_descriptor acm_fs_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
@ -180,21 +180,21 @@ static struct usb_endpoint_descriptor acm_fs_notify_desc __initdata = {
.bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
};
static struct usb_endpoint_descriptor acm_fs_in_desc __initdata = {
static struct usb_endpoint_descriptor acm_fs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_endpoint_descriptor acm_fs_out_desc __initdata = {
static struct usb_endpoint_descriptor acm_fs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_descriptor_header *acm_fs_function[] __initdata = {
static struct usb_descriptor_header *acm_fs_function[] = {
(struct usb_descriptor_header *) &acm_iad_descriptor,
(struct usb_descriptor_header *) &acm_control_interface_desc,
(struct usb_descriptor_header *) &acm_header_desc,
@ -210,7 +210,7 @@ static struct usb_descriptor_header *acm_fs_function[] __initdata = {
/* high speed support: */
static struct usb_endpoint_descriptor acm_hs_notify_desc __initdata = {
static struct usb_endpoint_descriptor acm_hs_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
@ -219,21 +219,21 @@ static struct usb_endpoint_descriptor acm_hs_notify_desc __initdata = {
.bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
};
static struct usb_endpoint_descriptor acm_hs_in_desc __initdata = {
static struct usb_endpoint_descriptor acm_hs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = {
static struct usb_endpoint_descriptor acm_hs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *acm_hs_function[] __initdata = {
static struct usb_descriptor_header *acm_hs_function[] = {
(struct usb_descriptor_header *) &acm_iad_descriptor,
(struct usb_descriptor_header *) &acm_control_interface_desc,
(struct usb_descriptor_header *) &acm_header_desc,
@ -571,7 +571,7 @@ static int acm_send_break(struct gserial *port, int duration)
/*-------------------------------------------------------------------------*/
/* ACM function driver setup/binding */
static int __init
static int
acm_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
@ -719,7 +719,7 @@ static inline bool can_support_cdc(struct usb_configuration *c)
* handle all the ones it binds. Caller is also responsible
* for calling @gserial_cleanup() before module unload.
*/
int __init acm_bind_config(struct usb_configuration *c, u8 port_num)
int acm_bind_config(struct usb_configuration *c, u8 port_num)
{
struct f_acm *acm;
int status;

View file

@ -113,7 +113,7 @@ static inline unsigned ecm_bitrate(struct usb_gadget *g)
/* interface descriptor: */
static struct usb_interface_descriptor ecm_control_intf __initdata = {
static struct usb_interface_descriptor ecm_control_intf = {
.bLength = sizeof ecm_control_intf,
.bDescriptorType = USB_DT_INTERFACE,
@ -126,7 +126,7 @@ static struct usb_interface_descriptor ecm_control_intf __initdata = {
/* .iInterface = DYNAMIC */
};
static struct usb_cdc_header_desc ecm_header_desc __initdata = {
static struct usb_cdc_header_desc ecm_header_desc = {
.bLength = sizeof ecm_header_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
@ -134,7 +134,7 @@ static struct usb_cdc_header_desc ecm_header_desc __initdata = {
.bcdCDC = cpu_to_le16(0x0110),
};
static struct usb_cdc_union_desc ecm_union_desc __initdata = {
static struct usb_cdc_union_desc ecm_union_desc = {
.bLength = sizeof(ecm_union_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_UNION_TYPE,
@ -142,7 +142,7 @@ static struct usb_cdc_union_desc ecm_union_desc __initdata = {
/* .bSlaveInterface0 = DYNAMIC */
};
static struct usb_cdc_ether_desc ecm_desc __initdata = {
static struct usb_cdc_ether_desc ecm_desc = {
.bLength = sizeof ecm_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_ETHERNET_TYPE,
@ -157,7 +157,7 @@ static struct usb_cdc_ether_desc ecm_desc __initdata = {
/* the default data interface has no endpoints ... */
static struct usb_interface_descriptor ecm_data_nop_intf __initdata = {
static struct usb_interface_descriptor ecm_data_nop_intf = {
.bLength = sizeof ecm_data_nop_intf,
.bDescriptorType = USB_DT_INTERFACE,
@ -172,7 +172,7 @@ static struct usb_interface_descriptor ecm_data_nop_intf __initdata = {
/* ... but the "real" data interface has two bulk endpoints */
static struct usb_interface_descriptor ecm_data_intf __initdata = {
static struct usb_interface_descriptor ecm_data_intf = {
.bLength = sizeof ecm_data_intf,
.bDescriptorType = USB_DT_INTERFACE,
@ -187,7 +187,7 @@ static struct usb_interface_descriptor ecm_data_intf __initdata = {
/* full speed support: */
static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = {
static struct usb_endpoint_descriptor fs_ecm_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -197,7 +197,7 @@ static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = {
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
};
static struct usb_endpoint_descriptor fs_ecm_in_desc __initdata = {
static struct usb_endpoint_descriptor fs_ecm_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -205,7 +205,7 @@ static struct usb_endpoint_descriptor fs_ecm_in_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_endpoint_descriptor fs_ecm_out_desc __initdata = {
static struct usb_endpoint_descriptor fs_ecm_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -213,7 +213,7 @@ static struct usb_endpoint_descriptor fs_ecm_out_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_descriptor_header *ecm_fs_function[] __initdata = {
static struct usb_descriptor_header *ecm_fs_function[] = {
/* CDC ECM control descriptors */
(struct usb_descriptor_header *) &ecm_control_intf,
(struct usb_descriptor_header *) &ecm_header_desc,
@ -231,7 +231,7 @@ static struct usb_descriptor_header *ecm_fs_function[] __initdata = {
/* high speed support: */
static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = {
static struct usb_endpoint_descriptor hs_ecm_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -240,7 +240,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};
static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = {
static struct usb_endpoint_descriptor hs_ecm_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -249,7 +249,7 @@ static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = {
static struct usb_endpoint_descriptor hs_ecm_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -258,7 +258,7 @@ static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *ecm_hs_function[] __initdata = {
static struct usb_descriptor_header *ecm_hs_function[] = {
/* CDC ECM control descriptors */
(struct usb_descriptor_header *) &ecm_control_intf,
(struct usb_descriptor_header *) &ecm_header_desc,
@ -597,7 +597,7 @@ static void ecm_close(struct gether *geth)
/* ethernet function driver setup/binding */
static int __init
static int
ecm_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
@ -763,7 +763,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
* Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload.
*/
int __init ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
int
ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
{
struct f_ecm *ecm;
int status;

2442
drivers/usb/gadget/f_fs.c Normal file

File diff suppressed because it is too large Load diff

673
drivers/usb/gadget/f_hid.c Normal file
View file

@ -0,0 +1,673 @@
/*
* f_hid.c -- USB HID function driver
*
* Copyright (C) 2010 Fabien Chouteau <fabien.chouteau@barco.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/utsname.h>
#include <linux/module.h>
#include <linux/hid.h>
#include <linux/cdev.h>
#include <linux/mutex.h>
#include <linux/poll.h>
#include <linux/smp_lock.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
#include <linux/usb/g_hid.h>
static int major, minors;
static struct class *hidg_class;
/*-------------------------------------------------------------------------*/
/* HID gadget struct */
struct f_hidg {
/* configuration */
unsigned char bInterfaceSubClass;
unsigned char bInterfaceProtocol;
unsigned short report_desc_length;
char *report_desc;
unsigned short report_length;
/* recv report */
char *set_report_buff;
unsigned short set_report_length;
spinlock_t spinlock;
wait_queue_head_t read_queue;
/* send report */
struct mutex lock;
bool write_pending;
wait_queue_head_t write_queue;
struct usb_request *req;
int minor;
struct cdev cdev;
struct usb_function func;
struct usb_ep *in_ep;
struct usb_endpoint_descriptor *fs_in_ep_desc;
struct usb_endpoint_descriptor *hs_in_ep_desc;
};
static inline struct f_hidg *func_to_hidg(struct usb_function *f)
{
return container_of(f, struct f_hidg, func);
}
/*-------------------------------------------------------------------------*/
/* Static descriptors */
static struct usb_interface_descriptor hidg_interface_desc = {
.bLength = sizeof hidg_interface_desc,
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_HID,
/* .bInterfaceSubClass = DYNAMIC */
/* .bInterfaceProtocol = DYNAMIC */
/* .iInterface = DYNAMIC */
};
static struct hid_descriptor hidg_desc = {
.bLength = sizeof hidg_desc,
.bDescriptorType = HID_DT_HID,
.bcdHID = 0x0101,
.bCountryCode = 0x00,
.bNumDescriptors = 0x1,
/*.desc[0].bDescriptorType = DYNAMIC */
/*.desc[0].wDescriptorLenght = DYNAMIC */
};
/* High-Speed Support */
static struct usb_endpoint_descriptor hidg_hs_in_ep_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
/*.wMaxPacketSize = DYNAMIC */
.bInterval = 4, /* FIXME: Add this field in the
* HID gadget configuration?
* (struct hidg_func_descriptor)
*/
};
static struct usb_descriptor_header *hidg_hs_descriptors[] = {
(struct usb_descriptor_header *)&hidg_interface_desc,
(struct usb_descriptor_header *)&hidg_desc,
(struct usb_descriptor_header *)&hidg_hs_in_ep_desc,
NULL,
};
/* Full-Speed Support */
static struct usb_endpoint_descriptor hidg_fs_in_ep_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
/*.wMaxPacketSize = DYNAMIC */
.bInterval = 10, /* FIXME: Add this field in the
* HID gadget configuration?
* (struct hidg_func_descriptor)
*/
};
static struct usb_descriptor_header *hidg_fs_descriptors[] = {
(struct usb_descriptor_header *)&hidg_interface_desc,
(struct usb_descriptor_header *)&hidg_desc,
(struct usb_descriptor_header *)&hidg_fs_in_ep_desc,
NULL,
};
/*-------------------------------------------------------------------------*/
/* Char Device */
static ssize_t f_hidg_read(struct file *file, char __user *buffer,
size_t count, loff_t *ptr)
{
struct f_hidg *hidg = (struct f_hidg *)file->private_data;
char *tmp_buff = NULL;
unsigned long flags;
if (!count)
return 0;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
spin_lock_irqsave(&hidg->spinlock, flags);
#define READ_COND (hidg->set_report_buff != NULL)
while (!READ_COND) {
spin_unlock_irqrestore(&hidg->spinlock, flags);
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
if (wait_event_interruptible(hidg->read_queue, READ_COND))
return -ERESTARTSYS;
spin_lock_irqsave(&hidg->spinlock, flags);
}
count = min_t(unsigned, count, hidg->set_report_length);
tmp_buff = hidg->set_report_buff;
hidg->set_report_buff = NULL;
spin_unlock_irqrestore(&hidg->spinlock, flags);
if (tmp_buff != NULL) {
/* copy to user outside spinlock */
count -= copy_to_user(buffer, tmp_buff, count);
kfree(tmp_buff);
} else
count = -ENOMEM;
return count;
}
static void f_hidg_req_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_hidg *hidg = (struct f_hidg *)ep->driver_data;
if (req->status != 0) {
ERROR(hidg->func.config->cdev,
"End Point Request ERROR: %d\n", req->status);
}
hidg->write_pending = 0;
wake_up(&hidg->write_queue);
}
static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
size_t count, loff_t *offp)
{
struct f_hidg *hidg = (struct f_hidg *)file->private_data;
ssize_t status = -ENOMEM;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
mutex_lock(&hidg->lock);
#define WRITE_COND (!hidg->write_pending)
/* write queue */
while (!WRITE_COND) {
mutex_unlock(&hidg->lock);
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
if (wait_event_interruptible_exclusive(
hidg->write_queue, WRITE_COND))
return -ERESTARTSYS;
mutex_lock(&hidg->lock);
}
count = min_t(unsigned, count, hidg->report_length);
status = copy_from_user(hidg->req->buf, buffer, count);
if (status != 0) {
ERROR(hidg->func.config->cdev,
"copy_from_user error\n");
mutex_unlock(&hidg->lock);
return -EINVAL;
}
hidg->req->status = 0;
hidg->req->zero = 0;
hidg->req->length = count;
hidg->req->complete = f_hidg_req_complete;
hidg->req->context = hidg;
hidg->write_pending = 1;
status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC);
if (status < 0) {
ERROR(hidg->func.config->cdev,
"usb_ep_queue error on int endpoint %zd\n", status);
hidg->write_pending = 0;
wake_up(&hidg->write_queue);
} else {
status = count;
}
mutex_unlock(&hidg->lock);
return status;
}
static unsigned int f_hidg_poll(struct file *file, poll_table *wait)
{
struct f_hidg *hidg = (struct f_hidg *)file->private_data;
unsigned int ret = 0;
poll_wait(file, &hidg->read_queue, wait);
poll_wait(file, &hidg->write_queue, wait);
if (WRITE_COND)
ret |= POLLOUT | POLLWRNORM;
if (READ_COND)
ret |= POLLIN | POLLRDNORM;
return ret;
}
#undef WRITE_COND
#undef READ_COND
static int f_hidg_release(struct inode *inode, struct file *fd)
{
fd->private_data = NULL;
return 0;
}
static int f_hidg_open(struct inode *inode, struct file *fd)
{
struct f_hidg *hidg =
container_of(inode->i_cdev, struct f_hidg, cdev);
fd->private_data = hidg;
return 0;
}
/*-------------------------------------------------------------------------*/
/* usb_function */
static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_hidg *hidg = (struct f_hidg *)req->context;
if (req->status != 0 || req->buf == NULL || req->actual == 0) {
ERROR(hidg->func.config->cdev, "%s FAILED\n", __func__);
return;
}
spin_lock(&hidg->spinlock);
hidg->set_report_buff = krealloc(hidg->set_report_buff,
req->actual, GFP_ATOMIC);
if (hidg->set_report_buff == NULL) {
spin_unlock(&hidg->spinlock);
return;
}
hidg->set_report_length = req->actual;
memcpy(hidg->set_report_buff, req->buf, req->actual);
spin_unlock(&hidg->spinlock);
wake_up(&hidg->read_queue);
return;
}
static int hidg_setup(struct usb_function *f,
const struct usb_ctrlrequest *ctrl)
{
struct f_hidg *hidg = func_to_hidg(f);
struct usb_composite_dev *cdev = f->config->cdev;
struct usb_request *req = cdev->req;
int status = 0;
__u16 value, length;
value = __le16_to_cpu(ctrl->wValue);
length = __le16_to_cpu(ctrl->wLength);
VDBG(cdev, "hid_setup crtl_request : bRequestType:0x%x bRequest:0x%x "
"Value:0x%x\n", ctrl->bRequestType, ctrl->bRequest, value);
switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_GET_REPORT):
VDBG(cdev, "get_report\n");
/* send an empty report */
length = min_t(unsigned, length, hidg->report_length);
memset(req->buf, 0x0, length);
goto respond;
break;
case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_GET_PROTOCOL):
VDBG(cdev, "get_protocol\n");
goto stall;
break;
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_SET_REPORT):
VDBG(cdev, "set_report | wLenght=%d\n", ctrl->wLength);
req->context = hidg;
req->complete = hidg_set_report_complete;
goto respond;
break;
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_SET_PROTOCOL):
VDBG(cdev, "set_protocol\n");
goto stall;
break;
case ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8
| USB_REQ_GET_DESCRIPTOR):
switch (value >> 8) {
case HID_DT_REPORT:
VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: REPORT\n");
length = min_t(unsigned short, length,
hidg->report_desc_length);
memcpy(req->buf, hidg->report_desc, length);
goto respond;
break;
default:
VDBG(cdev, "Unknown decriptor request 0x%x\n",
value >> 8);
goto stall;
break;
}
break;
default:
VDBG(cdev, "Unknown request 0x%x\n",
ctrl->bRequest);
goto stall;
break;
}
stall:
return -EOPNOTSUPP;
respond:
req->zero = 0;
req->length = length;
status = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
if (status < 0)
ERROR(cdev, "usb_ep_queue error on ep0 %d\n", value);
return status;
}
static void hidg_disable(struct usb_function *f)
{
struct f_hidg *hidg = func_to_hidg(f);
usb_ep_disable(hidg->in_ep);
hidg->in_ep->driver_data = NULL;
return;
}
static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct usb_composite_dev *cdev = f->config->cdev;
struct f_hidg *hidg = func_to_hidg(f);
const struct usb_endpoint_descriptor *ep_desc;
int status = 0;
VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt);
if (hidg->in_ep != NULL) {
/* restart endpoint */
if (hidg->in_ep->driver_data != NULL)
usb_ep_disable(hidg->in_ep);
ep_desc = ep_choose(f->config->cdev->gadget,
hidg->hs_in_ep_desc, hidg->fs_in_ep_desc);
status = usb_ep_enable(hidg->in_ep, ep_desc);
if (status < 0) {
ERROR(cdev, "Enable endpoint FAILED!\n");
goto fail;
}
hidg->in_ep->driver_data = hidg;
}
fail:
return status;
}
const struct file_operations f_hidg_fops = {
.owner = THIS_MODULE,
.open = f_hidg_open,
.release = f_hidg_release,
.write = f_hidg_write,
.read = f_hidg_read,
.poll = f_hidg_poll,
};
static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_ep *ep;
struct f_hidg *hidg = func_to_hidg(f);
int status;
dev_t dev;
/* allocate instance-specific interface IDs, and patch descriptors */
status = usb_interface_id(c, f);
if (status < 0)
goto fail;
hidg_interface_desc.bInterfaceNumber = status;
/* allocate instance-specific endpoints */
status = -ENODEV;
ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc);
if (!ep)
goto fail;
ep->driver_data = c->cdev; /* claim */
hidg->in_ep = ep;
/* preallocate request and buffer */
status = -ENOMEM;
hidg->req = usb_ep_alloc_request(hidg->in_ep, GFP_KERNEL);
if (!hidg->req)
goto fail;
hidg->req->buf = kmalloc(hidg->report_length, GFP_KERNEL);
if (!hidg->req->buf)
goto fail;
/* set descriptor dynamic values */
hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass;
hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT;
hidg_desc.desc[0].wDescriptorLength =
cpu_to_le16(hidg->report_desc_length);
hidg->set_report_buff = NULL;
/* copy descriptors */
f->descriptors = usb_copy_descriptors(hidg_fs_descriptors);
if (!f->descriptors)
goto fail;
hidg->fs_in_ep_desc = usb_find_endpoint(hidg_fs_descriptors,
f->descriptors,
&hidg_fs_in_ep_desc);
if (gadget_is_dualspeed(c->cdev->gadget)) {
hidg_hs_in_ep_desc.bEndpointAddress =
hidg_fs_in_ep_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors);
if (!f->hs_descriptors)
goto fail;
hidg->hs_in_ep_desc = usb_find_endpoint(hidg_hs_descriptors,
f->hs_descriptors,
&hidg_hs_in_ep_desc);
} else {
hidg->hs_in_ep_desc = NULL;
}
mutex_init(&hidg->lock);
spin_lock_init(&hidg->spinlock);
init_waitqueue_head(&hidg->write_queue);
init_waitqueue_head(&hidg->read_queue);
/* create char device */
cdev_init(&hidg->cdev, &f_hidg_fops);
dev = MKDEV(major, hidg->minor);
status = cdev_add(&hidg->cdev, dev, 1);
if (status)
goto fail;
device_create(hidg_class, NULL, dev, NULL, "%s%d", "hidg", hidg->minor);
return 0;
fail:
ERROR(f->config->cdev, "hidg_bind FAILED\n");
if (hidg->req != NULL) {
kfree(hidg->req->buf);
if (hidg->in_ep != NULL)
usb_ep_free_request(hidg->in_ep, hidg->req);
}
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
return status;
}
static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_hidg *hidg = func_to_hidg(f);
device_destroy(hidg_class, MKDEV(major, hidg->minor));
cdev_del(&hidg->cdev);
/* disable/free request and end point */
usb_ep_disable(hidg->in_ep);
usb_ep_dequeue(hidg->in_ep, hidg->req);
kfree(hidg->req->buf);
usb_ep_free_request(hidg->in_ep, hidg->req);
/* free descriptors copies */
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
kfree(hidg->report_desc);
kfree(hidg->set_report_buff);
kfree(hidg);
}
/*-------------------------------------------------------------------------*/
/* Strings */
#define CT_FUNC_HID_IDX 0
static struct usb_string ct_func_string_defs[] = {
[CT_FUNC_HID_IDX].s = "HID Interface",
{}, /* end of list */
};
static struct usb_gadget_strings ct_func_string_table = {
.language = 0x0409, /* en-US */
.strings = ct_func_string_defs,
};
static struct usb_gadget_strings *ct_func_strings[] = {
&ct_func_string_table,
NULL,
};
/*-------------------------------------------------------------------------*/
/* usb_configuration */
int __init hidg_bind_config(struct usb_configuration *c,
struct hidg_func_descriptor *fdesc, int index)
{
struct f_hidg *hidg;
int status;
if (index >= minors)
return -ENOENT;
/* maybe allocate device-global string IDs, and patch descriptors */
if (ct_func_string_defs[CT_FUNC_HID_IDX].id == 0) {
status = usb_string_id(c->cdev);
if (status < 0)
return status;
ct_func_string_defs[CT_FUNC_HID_IDX].id = status;
hidg_interface_desc.iInterface = status;
}
/* allocate and initialize one new instance */
hidg = kzalloc(sizeof *hidg, GFP_KERNEL);
if (!hidg)
return -ENOMEM;
hidg->minor = index;
hidg->bInterfaceSubClass = fdesc->subclass;
hidg->bInterfaceProtocol = fdesc->protocol;
hidg->report_length = fdesc->report_length;
hidg->report_desc_length = fdesc->report_desc_length;
hidg->report_desc = kmemdup(fdesc->report_desc,
fdesc->report_desc_length,
GFP_KERNEL);
if (!hidg->report_desc) {
kfree(hidg);
return -ENOMEM;
}
hidg->func.name = "hid";
hidg->func.strings = ct_func_strings;
hidg->func.bind = hidg_bind;
hidg->func.unbind = hidg_unbind;
hidg->func.set_alt = hidg_set_alt;
hidg->func.disable = hidg_disable;
hidg->func.setup = hidg_setup;
status = usb_add_function(c, &hidg->func);
if (status)
kfree(hidg);
return status;
}
int __init ghid_setup(struct usb_gadget *g, int count)
{
int status;
dev_t dev;
hidg_class = class_create(THIS_MODULE, "hidg");
status = alloc_chrdev_region(&dev, 0, count, "hidg");
if (!status) {
major = MAJOR(dev);
minors = count;
}
return status;
}
void ghid_cleanup(void)
{
if (major) {
unregister_chrdev_region(MKDEV(major, 0), minors);
major = minors = 0;
}
class_destroy(hidg_class);
hidg_class = NULL;
}

View file

@ -163,6 +163,10 @@
* ro setting are not allowed when the medium is loaded or if CD-ROM
* emulation is being used.
*
* When a LUN receive an "eject" SCSI request (Start/Stop Unit),
* if the LUN is removable, the backing file is released to simulate
* ejection.
*
*
* This function is heavily based on "File-backed Storage Gadget" by
* Alan Stern which in turn is heavily based on "Gadget Zero" by David
@ -302,7 +306,6 @@ static const char fsg_string_interface[] = "Mass Storage";
#define FSG_NO_INTR_EP 1
#define FSG_BUFFHD_STATIC_BUFFER 1
#define FSG_NO_DEVICE_STRINGS 1
#define FSG_NO_OTG 1
#define FSG_NO_INTR_EP 1
@ -1385,12 +1388,50 @@ static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh)
static int do_start_stop(struct fsg_common *common)
{
if (!common->curlun) {
struct fsg_lun *curlun = common->curlun;
int loej, start;
if (!curlun) {
return -EINVAL;
} else if (!common->curlun->removable) {
common->curlun->sense_data = SS_INVALID_COMMAND;
} else if (!curlun->removable) {
curlun->sense_data = SS_INVALID_COMMAND;
return -EINVAL;
}
loej = common->cmnd[4] & 0x02;
start = common->cmnd[4] & 0x01;
/* eject code from file_storage.c:do_start_stop() */
if ((common->cmnd[1] & ~0x01) != 0 || /* Mask away Immed */
(common->cmnd[4] & ~0x03) != 0) { /* Mask LoEj, Start */
curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL;
}
if (!start) {
/* Are we allowed to unload the media? */
if (curlun->prevent_medium_removal) {
LDBG(curlun, "unload attempt prevented\n");
curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
return -EINVAL;
}
if (loej) { /* Simulate an unload/eject */
up_read(&common->filesem);
down_write(&common->filesem);
fsg_lun_close(curlun);
up_write(&common->filesem);
down_read(&common->filesem);
}
} else {
/* Our emulation doesn't support mounting; the medium is
* available for use as soon as it is loaded. */
if (!fsg_lun_is_open(curlun)) {
curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
return -EINVAL;
}
}
return 0;
}
@ -2701,10 +2742,8 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
/* Maybe allocate device-global string IDs, and patch descriptors */
if (fsg_strings[FSG_STRING_INTERFACE].id == 0) {
rc = usb_string_id(cdev);
if (rc < 0) {
kfree(common);
return ERR_PTR(rc);
}
if (unlikely(rc < 0))
goto error_release;
fsg_strings[FSG_STRING_INTERFACE].id = rc;
fsg_intf_desc.iInterface = rc;
}
@ -2712,9 +2751,9 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
/* Create the LUNs, open their backing files, and register the
* LUN devices in sysfs. */
curlun = kzalloc(nluns * sizeof *curlun, GFP_KERNEL);
if (!curlun) {
kfree(common);
return ERR_PTR(-ENOMEM);
if (unlikely(!curlun)) {
rc = -ENOMEM;
goto error_release;
}
common->luns = curlun;
@ -2762,13 +2801,19 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
/* Data buffers cyclic list */
/* Buffers in buffhds are static -- no need for additional
* allocation. */
bh = common->buffhds;
i = FSG_NUM_BUFFERS - 1;
i = FSG_NUM_BUFFERS;
goto buffhds_first_it;
do {
bh->next = bh + 1;
} while (++bh, --i);
++bh;
buffhds_first_it:
bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL);
if (unlikely(!bh->buf)) {
rc = -ENOMEM;
goto error_release;
}
} while (--i);
bh->next = common->buffhds;
@ -2867,10 +2912,7 @@ error_release:
static void fsg_common_release(struct kref *ref)
{
struct fsg_common *common =
container_of(ref, struct fsg_common, ref);
unsigned i = common->nluns;
struct fsg_lun *lun = common->luns;
struct fsg_common *common = container_of(ref, struct fsg_common, ref);
/* If the thread isn't already dead, tell it to exit now */
if (common->state != FSG_STATE_TERMINATED) {
@ -2881,17 +2923,29 @@ static void fsg_common_release(struct kref *ref)
complete(&common->thread_notifier);
}
/* Beware tempting for -> do-while optimization: when in error
* recovery nluns may be zero. */
if (likely(common->luns)) {
struct fsg_lun *lun = common->luns;
unsigned i = common->nluns;
for (; i; --i, ++lun) {
device_remove_file(&lun->dev, &dev_attr_ro);
device_remove_file(&lun->dev, &dev_attr_file);
fsg_lun_close(lun);
device_unregister(&lun->dev);
/* In error recovery common->nluns may be zero. */
for (; i; --i, ++lun) {
device_remove_file(&lun->dev, &dev_attr_ro);
device_remove_file(&lun->dev, &dev_attr_file);
fsg_lun_close(lun);
device_unregister(&lun->dev);
}
kfree(common->luns);
}
{
struct fsg_buffhd *bh = common->buffhds;
unsigned i = FSG_NUM_BUFFERS;
do {
kfree(bh->buf);
} while (++bh, --i);
}
kfree(common->luns);
if (common->free_storage_on_release)
kfree(common);
}
@ -2906,11 +2960,13 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(fsg, "unbind\n");
fsg_common_put(fsg->common);
usb_free_descriptors(fsg->function.descriptors);
usb_free_descriptors(fsg->function.hs_descriptors);
kfree(fsg);
}
static int __init fsg_bind(struct usb_configuration *c, struct usb_function *f)
static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
struct usb_gadget *gadget = c->cdev->gadget;
@ -2946,7 +3002,9 @@ static int __init fsg_bind(struct usb_configuration *c, struct usb_function *f)
fsg_fs_bulk_in_desc.bEndpointAddress;
fsg_hs_bulk_out_desc.bEndpointAddress =
fsg_fs_bulk_out_desc.bEndpointAddress;
f->hs_descriptors = fsg_hs_function;
f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
if (unlikely(!f->hs_descriptors))
return -ENOMEM;
}
return 0;
@ -2978,7 +3036,11 @@ static int fsg_add(struct usb_composite_dev *cdev,
fsg->function.name = FSG_DRIVER_DESC;
fsg->function.strings = fsg_strings_array;
fsg->function.descriptors = fsg_fs_function;
fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function);
if (unlikely(!fsg->function.descriptors)) {
rc = -ENOMEM;
goto error_free_fsg;
}
fsg->function.bind = fsg_bind;
fsg->function.unbind = fsg_unbind;
fsg->function.setup = fsg_setup;
@ -2993,11 +3055,19 @@ static int fsg_add(struct usb_composite_dev *cdev,
* call to usb_add_function() was successful. */
rc = usb_add_function(c, &fsg->function);
if (unlikely(rc))
goto error_free_all;
if (likely(rc == 0))
fsg_common_get(fsg->common);
else
kfree(fsg);
fsg_common_get(fsg->common);
return 0;
error_free_all:
usb_free_descriptors(fsg->function.descriptors);
/* fsg_bind() might have copied those; or maybe not? who cares
* -- free it just in case. */
usb_free_descriptors(fsg->function.hs_descriptors);
error_free_fsg:
kfree(fsg);
return rc;
}

View file

@ -122,7 +122,7 @@ static unsigned int bitrate(struct usb_gadget *g)
/* interface descriptor: */
static struct usb_interface_descriptor rndis_control_intf __initdata = {
static struct usb_interface_descriptor rndis_control_intf = {
.bLength = sizeof rndis_control_intf,
.bDescriptorType = USB_DT_INTERFACE,
@ -135,7 +135,7 @@ static struct usb_interface_descriptor rndis_control_intf __initdata = {
/* .iInterface = DYNAMIC */
};
static struct usb_cdc_header_desc header_desc __initdata = {
static struct usb_cdc_header_desc header_desc = {
.bLength = sizeof header_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
@ -143,7 +143,7 @@ static struct usb_cdc_header_desc header_desc __initdata = {
.bcdCDC = cpu_to_le16(0x0110),
};
static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = {
static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = {
.bLength = sizeof call_mgmt_descriptor,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
@ -152,7 +152,7 @@ static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = {
.bDataInterface = 0x01,
};
static struct usb_cdc_acm_descriptor rndis_acm_descriptor __initdata = {
static struct usb_cdc_acm_descriptor rndis_acm_descriptor = {
.bLength = sizeof rndis_acm_descriptor,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_ACM_TYPE,
@ -160,7 +160,7 @@ static struct usb_cdc_acm_descriptor rndis_acm_descriptor __initdata = {
.bmCapabilities = 0x00,
};
static struct usb_cdc_union_desc rndis_union_desc __initdata = {
static struct usb_cdc_union_desc rndis_union_desc = {
.bLength = sizeof(rndis_union_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_UNION_TYPE,
@ -170,7 +170,7 @@ static struct usb_cdc_union_desc rndis_union_desc __initdata = {
/* the data interface has two bulk endpoints */
static struct usb_interface_descriptor rndis_data_intf __initdata = {
static struct usb_interface_descriptor rndis_data_intf = {
.bLength = sizeof rndis_data_intf,
.bDescriptorType = USB_DT_INTERFACE,
@ -198,7 +198,7 @@ rndis_iad_descriptor = {
/* full speed support: */
static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
static struct usb_endpoint_descriptor fs_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -208,7 +208,7 @@ static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
};
static struct usb_endpoint_descriptor fs_in_desc __initdata = {
static struct usb_endpoint_descriptor fs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -216,7 +216,7 @@ static struct usb_endpoint_descriptor fs_in_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_endpoint_descriptor fs_out_desc __initdata = {
static struct usb_endpoint_descriptor fs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -224,7 +224,7 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_descriptor_header *eth_fs_function[] __initdata = {
static struct usb_descriptor_header *eth_fs_function[] = {
(struct usb_descriptor_header *) &rndis_iad_descriptor,
/* control interface matches ACM, not Ethernet */
(struct usb_descriptor_header *) &rndis_control_intf,
@ -242,7 +242,7 @@ static struct usb_descriptor_header *eth_fs_function[] __initdata = {
/* high speed support: */
static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
static struct usb_endpoint_descriptor hs_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -251,7 +251,7 @@ static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};
static struct usb_endpoint_descriptor hs_in_desc __initdata = {
static struct usb_endpoint_descriptor hs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -260,7 +260,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor hs_out_desc __initdata = {
static struct usb_endpoint_descriptor hs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -269,7 +269,7 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *eth_hs_function[] __initdata = {
static struct usb_descriptor_header *eth_hs_function[] = {
(struct usb_descriptor_header *) &rndis_iad_descriptor,
/* control interface matches ACM, not Ethernet */
(struct usb_descriptor_header *) &rndis_control_intf,
@ -594,7 +594,7 @@ static void rndis_close(struct gether *geth)
/* ethernet function driver setup/binding */
static int __init
static int
rndis_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
@ -786,7 +786,8 @@ static inline bool can_support_rndis(struct usb_configuration *c)
* Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload.
*/
int __init rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
int
rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
{
struct f_rndis *rndis;
int status;

661
drivers/usb/gadget/f_uvc.c Normal file
View file

@ -0,0 +1,661 @@
/*
* uvc_gadget.c -- USB Video Class Gadget driver
*
* Copyright (C) 2009-2010
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/video.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-event.h>
#include "uvc.h"
unsigned int uvc_trace_param;
/* --------------------------------------------------------------------------
* Function descriptors
*/
/* string IDs are assigned dynamically */
#define UVC_STRING_ASSOCIATION_IDX 0
#define UVC_STRING_CONTROL_IDX 1
#define UVC_STRING_STREAMING_IDX 2
static struct usb_string uvc_en_us_strings[] = {
[UVC_STRING_ASSOCIATION_IDX].s = "UVC Camera",
[UVC_STRING_CONTROL_IDX].s = "Video Control",
[UVC_STRING_STREAMING_IDX].s = "Video Streaming",
{ }
};
static struct usb_gadget_strings uvc_stringtab = {
.language = 0x0409, /* en-us */
.strings = uvc_en_us_strings,
};
static struct usb_gadget_strings *uvc_function_strings[] = {
&uvc_stringtab,
NULL,
};
#define UVC_INTF_VIDEO_CONTROL 0
#define UVC_INTF_VIDEO_STREAMING 1
static struct usb_interface_assoc_descriptor uvc_iad __initdata = {
.bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
.bFirstInterface = 0,
.bInterfaceCount = 2,
.bFunctionClass = USB_CLASS_VIDEO,
.bFunctionSubClass = 0x03,
.bFunctionProtocol = 0x00,
.iFunction = 0,
};
static struct usb_interface_descriptor uvc_control_intf __initdata = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = UVC_INTF_VIDEO_CONTROL,
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x00,
.iInterface = 0,
};
static struct usb_endpoint_descriptor uvc_control_ep __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(16),
.bInterval = 8,
};
static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = {
.bLength = UVC_DT_CONTROL_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_CS_ENDPOINT,
.bDescriptorSubType = UVC_EP_INTERRUPT,
.wMaxTransferSize = cpu_to_le16(16),
};
static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = UVC_INTF_VIDEO_STREAMING,
.bAlternateSetting = 0,
.bNumEndpoints = 0,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 0x02,
.bInterfaceProtocol = 0x00,
.iInterface = 0,
};
static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = UVC_INTF_VIDEO_STREAMING,
.bAlternateSetting = 1,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 0x02,
.bInterfaceProtocol = 0x00,
.iInterface = 0,
};
static struct usb_endpoint_descriptor uvc_streaming_ep = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = cpu_to_le16(512),
.bInterval = 1,
};
static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
(struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
(struct usb_descriptor_header *) &uvc_streaming_ep,
NULL,
};
static const struct usb_descriptor_header * const uvc_hs_streaming[] = {
(struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
(struct usb_descriptor_header *) &uvc_streaming_ep,
NULL,
};
/* --------------------------------------------------------------------------
* Control requests
*/
static void
uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req)
{
struct uvc_device *uvc = req->context;
struct v4l2_event v4l2_event;
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
if (uvc->event_setup_out) {
uvc->event_setup_out = 0;
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_DATA;
uvc_event->data.length = req->actual;
memcpy(&uvc_event->data.data, req->buf, req->actual);
v4l2_event_queue(uvc->vdev, &v4l2_event);
}
}
static int
uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
{
struct uvc_device *uvc = to_uvc(f);
struct v4l2_event v4l2_event;
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
/* printk(KERN_INFO "setup request %02x %02x value %04x index %04x %04x\n",
* ctrl->bRequestType, ctrl->bRequest, le16_to_cpu(ctrl->wValue),
* le16_to_cpu(ctrl->wIndex), le16_to_cpu(ctrl->wLength));
*/
if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) {
INFO(f->config->cdev, "invalid request type\n");
return -EINVAL;
}
/* Stall too big requests. */
if (le16_to_cpu(ctrl->wLength) > UVC_MAX_REQUEST_SIZE)
return -EINVAL;
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_SETUP;
memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req));
v4l2_event_queue(uvc->vdev, &v4l2_event);
return 0;
}
static int
uvc_function_get_alt(struct usb_function *f, unsigned interface)
{
struct uvc_device *uvc = to_uvc(f);
INFO(f->config->cdev, "uvc_function_get_alt(%u)\n", interface);
if (interface == uvc->control_intf)
return 0;
else if (interface != uvc->streaming_intf)
return -EINVAL;
else
return uvc->state == UVC_STATE_STREAMING ? 1 : 0;
}
static int
uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
{
struct uvc_device *uvc = to_uvc(f);
struct v4l2_event v4l2_event;
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
if (interface == uvc->control_intf) {
if (alt)
return -EINVAL;
if (uvc->state == UVC_STATE_DISCONNECTED) {
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_CONNECT;
uvc_event->speed = f->config->cdev->gadget->speed;
v4l2_event_queue(uvc->vdev, &v4l2_event);
uvc->state = UVC_STATE_CONNECTED;
}
return 0;
}
if (interface != uvc->streaming_intf)
return -EINVAL;
/* TODO
if (usb_endpoint_xfer_bulk(&uvc->desc.vs_ep))
return alt ? -EINVAL : 0;
*/
switch (alt) {
case 0:
if (uvc->state != UVC_STATE_STREAMING)
return 0;
if (uvc->video.ep)
usb_ep_disable(uvc->video.ep);
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMOFF;
v4l2_event_queue(uvc->vdev, &v4l2_event);
uvc->state = UVC_STATE_CONNECTED;
break;
case 1:
if (uvc->state != UVC_STATE_CONNECTED)
return 0;
if (uvc->video.ep)
usb_ep_enable(uvc->video.ep, &uvc_streaming_ep);
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMON;
v4l2_event_queue(uvc->vdev, &v4l2_event);
uvc->state = UVC_STATE_STREAMING;
break;
default:
return -EINVAL;
}
return 0;
}
static void
uvc_function_disable(struct usb_function *f)
{
struct uvc_device *uvc = to_uvc(f);
struct v4l2_event v4l2_event;
INFO(f->config->cdev, "uvc_function_disable\n");
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_DISCONNECT;
v4l2_event_queue(uvc->vdev, &v4l2_event);
uvc->state = UVC_STATE_DISCONNECTED;
}
/* --------------------------------------------------------------------------
* Connection / disconnection
*/
void
uvc_function_connect(struct uvc_device *uvc)
{
struct usb_composite_dev *cdev = uvc->func.config->cdev;
int ret;
if ((ret = usb_function_activate(&uvc->func)) < 0)
INFO(cdev, "UVC connect failed with %d\n", ret);
}
void
uvc_function_disconnect(struct uvc_device *uvc)
{
struct usb_composite_dev *cdev = uvc->func.config->cdev;
int ret;
if ((ret = usb_function_deactivate(&uvc->func)) < 0)
INFO(cdev, "UVC disconnect failed with %d\n", ret);
}
/* --------------------------------------------------------------------------
* USB probe and disconnect
*/
static int
uvc_register_video(struct uvc_device *uvc)
{
struct usb_composite_dev *cdev = uvc->func.config->cdev;
struct video_device *video;
/* TODO reference counting. */
video = video_device_alloc();
if (video == NULL)
return -ENOMEM;
video->parent = &cdev->gadget->dev;
video->minor = -1;
video->fops = &uvc_v4l2_fops;
video->release = video_device_release;
strncpy(video->name, cdev->gadget->name, sizeof(video->name));
uvc->vdev = video;
video_set_drvdata(video, uvc);
return video_register_device(video, VFL_TYPE_GRABBER, -1);
}
#define UVC_COPY_DESCRIPTOR(mem, dst, desc) \
do { \
memcpy(mem, desc, (desc)->bLength); \
*(dst)++ = mem; \
mem += (desc)->bLength; \
} while (0);
#define UVC_COPY_DESCRIPTORS(mem, dst, src) \
do { \
const struct usb_descriptor_header * const *__src; \
for (__src = src; *__src; ++__src) { \
memcpy(mem, *__src, (*__src)->bLength); \
*dst++ = mem; \
mem += (*__src)->bLength; \
} \
} while (0)
static struct usb_descriptor_header ** __init
uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
{
struct uvc_input_header_descriptor *uvc_streaming_header;
struct uvc_header_descriptor *uvc_control_header;
const struct uvc_descriptor_header * const *uvc_streaming_cls;
const struct usb_descriptor_header * const *uvc_streaming_std;
const struct usb_descriptor_header * const *src;
struct usb_descriptor_header **dst;
struct usb_descriptor_header **hdr;
unsigned int control_size;
unsigned int streaming_size;
unsigned int n_desc;
unsigned int bytes;
void *mem;
uvc_streaming_cls = (speed == USB_SPEED_FULL)
? uvc->desc.fs_streaming : uvc->desc.hs_streaming;
uvc_streaming_std = (speed == USB_SPEED_FULL)
? uvc_fs_streaming : uvc_hs_streaming;
/* Descriptors layout
*
* uvc_iad
* uvc_control_intf
* Class-specific UVC control descriptors
* uvc_control_ep
* uvc_control_cs_ep
* uvc_streaming_intf_alt0
* Class-specific UVC streaming descriptors
* uvc_{fs|hs}_streaming
*/
/* Count descriptors and compute their size. */
control_size = 0;
streaming_size = 0;
bytes = uvc_iad.bLength + uvc_control_intf.bLength
+ uvc_control_ep.bLength + uvc_control_cs_ep.bLength
+ uvc_streaming_intf_alt0.bLength;
n_desc = 5;
for (src = (const struct usb_descriptor_header**)uvc->desc.control; *src; ++src) {
control_size += (*src)->bLength;
bytes += (*src)->bLength;
n_desc++;
}
for (src = (const struct usb_descriptor_header**)uvc_streaming_cls; *src; ++src) {
streaming_size += (*src)->bLength;
bytes += (*src)->bLength;
n_desc++;
}
for (src = uvc_streaming_std; *src; ++src) {
bytes += (*src)->bLength;
n_desc++;
}
mem = kmalloc((n_desc + 1) * sizeof(*src) + bytes, GFP_KERNEL);
if (mem == NULL)
return NULL;
hdr = mem;
dst = mem;
mem += (n_desc + 1) * sizeof(*src);
/* Copy the descriptors. */
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_iad);
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_intf);
uvc_control_header = mem;
UVC_COPY_DESCRIPTORS(mem, dst,
(const struct usb_descriptor_header**)uvc->desc.control);
uvc_control_header->wTotalLength = cpu_to_le16(control_size);
uvc_control_header->bInCollection = 1;
uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep);
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_cs_ep);
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_streaming_intf_alt0);
uvc_streaming_header = mem;
UVC_COPY_DESCRIPTORS(mem, dst,
(const struct usb_descriptor_header**)uvc_streaming_cls);
uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
uvc_streaming_header->bEndpointAddress = uvc_streaming_ep.bEndpointAddress;
UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
*dst = NULL;
return hdr;
}
static void
uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct uvc_device *uvc = to_uvc(f);
INFO(cdev, "uvc_function_unbind\n");
if (uvc->vdev) {
if (uvc->vdev->minor == -1)
video_device_release(uvc->vdev);
else
video_unregister_device(uvc->vdev);
uvc->vdev = NULL;
}
if (uvc->control_ep)
uvc->control_ep->driver_data = NULL;
if (uvc->video.ep)
uvc->video.ep->driver_data = NULL;
if (uvc->control_req) {
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
kfree(uvc->control_buf);
}
kfree(f->descriptors);
kfree(f->hs_descriptors);
kfree(uvc);
}
static int __init
uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct uvc_device *uvc = to_uvc(f);
struct usb_ep *ep;
int ret = -EINVAL;
INFO(cdev, "uvc_function_bind\n");
/* Allocate endpoints. */
ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
if (!ep) {
INFO(cdev, "Unable to allocate control EP\n");
goto error;
}
uvc->control_ep = ep;
ep->driver_data = uvc;
ep = usb_ep_autoconfig(cdev->gadget, &uvc_streaming_ep);
if (!ep) {
INFO(cdev, "Unable to allocate streaming EP\n");
goto error;
}
uvc->video.ep = ep;
ep->driver_data = uvc;
/* Allocate interface IDs. */
if ((ret = usb_interface_id(c, f)) < 0)
goto error;
uvc_iad.bFirstInterface = ret;
uvc_control_intf.bInterfaceNumber = ret;
uvc->control_intf = ret;
if ((ret = usb_interface_id(c, f)) < 0)
goto error;
uvc_streaming_intf_alt0.bInterfaceNumber = ret;
uvc_streaming_intf_alt1.bInterfaceNumber = ret;
uvc->streaming_intf = ret;
/* Copy descriptors. */
f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
/* Preallocate control endpoint request. */
uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL);
if (uvc->control_req == NULL || uvc->control_buf == NULL) {
ret = -ENOMEM;
goto error;
}
uvc->control_req->buf = uvc->control_buf;
uvc->control_req->complete = uvc_function_ep0_complete;
uvc->control_req->context = uvc;
/* Avoid letting this gadget enumerate until the userspace server is
* active.
*/
if ((ret = usb_function_deactivate(f)) < 0)
goto error;
/* Initialise video. */
ret = uvc_video_init(&uvc->video);
if (ret < 0)
goto error;
/* Register a V4L2 device. */
ret = uvc_register_video(uvc);
if (ret < 0) {
printk(KERN_INFO "Unable to register video device\n");
goto error;
}
return 0;
error:
uvc_function_unbind(c, f);
return ret;
}
/* --------------------------------------------------------------------------
* USB gadget function
*/
/**
* uvc_bind_config - add a UVC function to a configuration
* @c: the configuration to support the UVC instance
* Context: single threaded during gadget setup
*
* Returns zero on success, else negative errno.
*
* Caller must have called @uvc_setup(). Caller is also responsible for
* calling @uvc_cleanup() before module unload.
*/
int __init
uvc_bind_config(struct usb_configuration *c,
const struct uvc_descriptor_header * const *control,
const struct uvc_descriptor_header * const *fs_streaming,
const struct uvc_descriptor_header * const *hs_streaming)
{
struct uvc_device *uvc;
int ret = 0;
/* TODO Check if the USB device controller supports the required
* features.
*/
if (!gadget_is_dualspeed(c->cdev->gadget))
return -EINVAL;
uvc = kzalloc(sizeof(*uvc), GFP_KERNEL);
if (uvc == NULL)
return -ENOMEM;
uvc->state = UVC_STATE_DISCONNECTED;
/* Validate the descriptors. */
if (control == NULL || control[0] == NULL ||
control[0]->bDescriptorSubType != UVC_DT_HEADER)
goto error;
if (fs_streaming == NULL || fs_streaming[0] == NULL ||
fs_streaming[0]->bDescriptorSubType != UVC_DT_INPUT_HEADER)
goto error;
if (hs_streaming == NULL || hs_streaming[0] == NULL ||
hs_streaming[0]->bDescriptorSubType != UVC_DT_INPUT_HEADER)
goto error;
uvc->desc.control = control;
uvc->desc.fs_streaming = fs_streaming;
uvc->desc.hs_streaming = hs_streaming;
/* Allocate string descriptor numbers. */
if ((ret = usb_string_id(c->cdev)) < 0)
goto error;
uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret;
uvc_iad.iFunction = ret;
if ((ret = usb_string_id(c->cdev)) < 0)
goto error;
uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret;
uvc_control_intf.iInterface = ret;
if ((ret = usb_string_id(c->cdev)) < 0)
goto error;
uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret;
uvc_streaming_intf_alt0.iInterface = ret;
uvc_streaming_intf_alt1.iInterface = ret;
/* Register the function. */
uvc->func.name = "uvc";
uvc->func.strings = uvc_function_strings;
uvc->func.bind = uvc_function_bind;
uvc->func.unbind = uvc_function_unbind;
uvc->func.get_alt = uvc_function_get_alt;
uvc->func.set_alt = uvc_function_set_alt;
uvc->func.disable = uvc_function_disable;
uvc->func.setup = uvc_function_setup;
ret = usb_add_function(c, &uvc->func);
if (ret)
kfree(uvc);
return 0;
error:
kfree(uvc);
return ret;
}
module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(trace, "Trace level bitmask");

376
drivers/usb/gadget/f_uvc.h Normal file
View file

@ -0,0 +1,376 @@
/*
* f_uvc.h -- USB Video Class Gadget driver
*
* Copyright (C) 2009-2010
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#ifndef _F_UVC_H_
#define _F_UVC_H_
#include <linux/usb/composite.h>
#define USB_CLASS_VIDEO_CONTROL 1
#define USB_CLASS_VIDEO_STREAMING 2
struct uvc_descriptor_header {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
} __attribute__ ((packed));
struct uvc_header_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u16 bcdUVC;
__u16 wTotalLength;
__u32 dwClockFrequency;
__u8 bInCollection;
__u8 baInterfaceNr[];
} __attribute__((__packed__));
#define UVC_HEADER_DESCRIPTOR(n) uvc_header_descriptor_##n
#define DECLARE_UVC_HEADER_DESCRIPTOR(n) \
struct UVC_HEADER_DESCRIPTOR(n) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u16 bcdUVC; \
__u16 wTotalLength; \
__u32 dwClockFrequency; \
__u8 bInCollection; \
__u8 baInterfaceNr[n]; \
} __attribute__ ((packed))
struct uvc_input_terminal_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bTerminalID;
__u16 wTerminalType;
__u8 bAssocTerminal;
__u8 iTerminal;
} __attribute__((__packed__));
struct uvc_output_terminal_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bTerminalID;
__u16 wTerminalType;
__u8 bAssocTerminal;
__u8 bSourceID;
__u8 iTerminal;
} __attribute__((__packed__));
struct uvc_camera_terminal_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bTerminalID;
__u16 wTerminalType;
__u8 bAssocTerminal;
__u8 iTerminal;
__u16 wObjectiveFocalLengthMin;
__u16 wObjectiveFocalLengthMax;
__u16 wOcularFocalLength;
__u8 bControlSize;
__u8 bmControls[3];
} __attribute__((__packed__));
struct uvc_selector_unit_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bUnitID;
__u8 bNrInPins;
__u8 baSourceID[0];
__u8 iSelector;
} __attribute__((__packed__));
#define UVC_SELECTOR_UNIT_DESCRIPTOR(n) \
uvc_selector_unit_descriptor_##n
#define DECLARE_UVC_SELECTOR_UNIT_DESCRIPTOR(n) \
struct UVC_SELECTOR_UNIT_DESCRIPTOR(n) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u8 bUnitID; \
__u8 bNrInPins; \
__u8 baSourceID[n]; \
__u8 iSelector; \
} __attribute__ ((packed))
struct uvc_processing_unit_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bUnitID;
__u8 bSourceID;
__u16 wMaxMultiplier;
__u8 bControlSize;
__u8 bmControls[2];
__u8 iProcessing;
} __attribute__((__packed__));
struct uvc_extension_unit_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bUnitID;
__u8 guidExtensionCode[16];
__u8 bNumControls;
__u8 bNrInPins;
__u8 baSourceID[0];
__u8 bControlSize;
__u8 bmControls[0];
__u8 iExtension;
} __attribute__((__packed__));
#define UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \
uvc_extension_unit_descriptor_##p_##n
#define DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \
struct UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u8 bUnitID; \
__u8 guidExtensionCode[16]; \
__u8 bNumControls; \
__u8 bNrInPins; \
__u8 baSourceID[p]; \
__u8 bControlSize; \
__u8 bmControls[n]; \
__u8 iExtension; \
} __attribute__ ((packed))
struct uvc_control_endpoint_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u16 wMaxTransferSize;
} __attribute__((__packed__));
#define UVC_DT_HEADER 1
#define UVC_DT_INPUT_TERMINAL 2
#define UVC_DT_OUTPUT_TERMINAL 3
#define UVC_DT_SELECTOR_UNIT 4
#define UVC_DT_PROCESSING_UNIT 5
#define UVC_DT_EXTENSION_UNIT 6
#define UVC_DT_HEADER_SIZE(n) (12+(n))
#define UVC_DT_INPUT_TERMINAL_SIZE 8
#define UVC_DT_OUTPUT_TERMINAL_SIZE 9
#define UVC_DT_CAMERA_TERMINAL_SIZE(n) (15+(n))
#define UVC_DT_SELECTOR_UNIT_SIZE(n) (6+(n))
#define UVC_DT_PROCESSING_UNIT_SIZE(n) (9+(n))
#define UVC_DT_EXTENSION_UNIT_SIZE(p,n) (24+(p)+(n))
#define UVC_DT_CONTROL_ENDPOINT_SIZE 5
struct uvc_input_header_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bNumFormats;
__u16 wTotalLength;
__u8 bEndpointAddress;
__u8 bmInfo;
__u8 bTerminalLink;
__u8 bStillCaptureMethod;
__u8 bTriggerSupport;
__u8 bTriggerUsage;
__u8 bControlSize;
__u8 bmaControls[];
} __attribute__((__packed__));
#define UVC_INPUT_HEADER_DESCRIPTOR(n, p) \
uvc_input_header_descriptor_##n_##p
#define DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(n, p) \
struct UVC_INPUT_HEADER_DESCRIPTOR(n, p) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u8 bNumFormats; \
__u16 wTotalLength; \
__u8 bEndpointAddress; \
__u8 bmInfo; \
__u8 bTerminalLink; \
__u8 bStillCaptureMethod; \
__u8 bTriggerSupport; \
__u8 bTriggerUsage; \
__u8 bControlSize; \
__u8 bmaControls[p][n]; \
} __attribute__ ((packed))
struct uvc_output_header_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bNumFormats;
__u16 wTotalLength;
__u8 bEndpointAddress;
__u8 bTerminalLink;
__u8 bControlSize;
__u8 bmaControls[];
} __attribute__((__packed__));
#define UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \
uvc_output_header_descriptor_##n_##p
#define DECLARE_UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \
struct UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u8 bNumFormats; \
__u16 wTotalLength; \
__u8 bEndpointAddress; \
__u8 bTerminalLink; \
__u8 bControlSize; \
__u8 bmaControls[p][n]; \
} __attribute__ ((packed))
struct uvc_format_uncompressed {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bFormatIndex;
__u8 bNumFrameDescriptors;
__u8 guidFormat[16];
__u8 bBitsPerPixel;
__u8 bDefaultFrameIndex;
__u8 bAspectRatioX;
__u8 bAspectRatioY;
__u8 bmInterfaceFlags;
__u8 bCopyProtect;
} __attribute__((__packed__));
struct uvc_frame_uncompressed {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bFrameIndex;
__u8 bmCapabilities;
__u16 wWidth;
__u16 wHeight;
__u32 dwMinBitRate;
__u32 dwMaxBitRate;
__u32 dwMaxVideoFrameBufferSize;
__u32 dwDefaultFrameInterval;
__u8 bFrameIntervalType;
__u32 dwFrameInterval[];
} __attribute__((__packed__));
#define UVC_FRAME_UNCOMPRESSED(n) \
uvc_frame_uncompressed_##n
#define DECLARE_UVC_FRAME_UNCOMPRESSED(n) \
struct UVC_FRAME_UNCOMPRESSED(n) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u8 bFrameIndex; \
__u8 bmCapabilities; \
__u16 wWidth; \
__u16 wHeight; \
__u32 dwMinBitRate; \
__u32 dwMaxBitRate; \
__u32 dwMaxVideoFrameBufferSize; \
__u32 dwDefaultFrameInterval; \
__u8 bFrameIntervalType; \
__u32 dwFrameInterval[n]; \
} __attribute__ ((packed))
struct uvc_format_mjpeg {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bFormatIndex;
__u8 bNumFrameDescriptors;
__u8 bmFlags;
__u8 bDefaultFrameIndex;
__u8 bAspectRatioX;
__u8 bAspectRatioY;
__u8 bmInterfaceFlags;
__u8 bCopyProtect;
} __attribute__((__packed__));
struct uvc_frame_mjpeg {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bFrameIndex;
__u8 bmCapabilities;
__u16 wWidth;
__u16 wHeight;
__u32 dwMinBitRate;
__u32 dwMaxBitRate;
__u32 dwMaxVideoFrameBufferSize;
__u32 dwDefaultFrameInterval;
__u8 bFrameIntervalType;
__u32 dwFrameInterval[];
} __attribute__((__packed__));
#define UVC_FRAME_MJPEG(n) \
uvc_frame_mjpeg_##n
#define DECLARE_UVC_FRAME_MJPEG(n) \
struct UVC_FRAME_MJPEG(n) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u8 bFrameIndex; \
__u8 bmCapabilities; \
__u16 wWidth; \
__u16 wHeight; \
__u32 dwMinBitRate; \
__u32 dwMaxBitRate; \
__u32 dwMaxVideoFrameBufferSize; \
__u32 dwDefaultFrameInterval; \
__u8 bFrameIntervalType; \
__u32 dwFrameInterval[n]; \
} __attribute__ ((packed))
struct uvc_color_matching_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bColorPrimaries;
__u8 bTransferCharacteristics;
__u8 bMatrixCoefficients;
} __attribute__((__packed__));
#define UVC_DT_INPUT_HEADER 1
#define UVC_DT_OUTPUT_HEADER 2
#define UVC_DT_FORMAT_UNCOMPRESSED 4
#define UVC_DT_FRAME_UNCOMPRESSED 5
#define UVC_DT_FORMAT_MJPEG 6
#define UVC_DT_FRAME_MJPEG 7
#define UVC_DT_COLOR_MATCHING 13
#define UVC_DT_INPUT_HEADER_SIZE(n, p) (13+(n*p))
#define UVC_DT_OUTPUT_HEADER_SIZE(n, p) (9+(n*p))
#define UVC_DT_FORMAT_UNCOMPRESSED_SIZE 27
#define UVC_DT_FRAME_UNCOMPRESSED_SIZE(n) (26+4*(n))
#define UVC_DT_FORMAT_MJPEG_SIZE 11
#define UVC_DT_FRAME_MJPEG_SIZE(n) (26+4*(n))
#define UVC_DT_COLOR_MATCHING_SIZE 6
extern int uvc_bind_config(struct usb_configuration *c,
const struct uvc_descriptor_header * const *control,
const struct uvc_descriptor_header * const *fs_streaming,
const struct uvc_descriptor_header * const *hs_streaming);
#endif /* _F_UVC_H_ */

View file

@ -50,12 +50,14 @@ int fsl_udc_clk_init(struct platform_device *pdev)
goto egusb;
}
freq = clk_get_rate(mxc_usb_clk);
if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
(freq < 59999000 || freq > 60001000)) {
dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq);
ret = -EINVAL;
goto eclkrate;
if (!cpu_is_mx51()) {
freq = clk_get_rate(mxc_usb_clk);
if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
(freq < 59999000 || freq > 60001000)) {
dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq);
ret = -EINVAL;
goto eclkrate;
}
}
ret = clk_enable(mxc_usb_clk);

View file

@ -489,7 +489,7 @@ static int fsl_ep_enable(struct usb_ep *_ep,
case USB_ENDPOINT_XFER_ISOC:
/* Calculate transactions needed for high bandwidth iso */
mult = (unsigned char)(1 + ((max >> 11) & 0x03));
max = max & 0x8ff; /* bit 0~10 */
max = max & 0x7ff; /* bit 0~10 */
/* 3 transactions at most */
if (mult > 3)
goto en_done;

426
drivers/usb/gadget/g_ffs.c Normal file
View file

@ -0,0 +1,426 @@
#include <linux/module.h>
#include <linux/utsname.h>
/*
* kbuild is not very cooperative with respect to linking separately
* compiled library objects into one module. So for now we won't use
* separate compilation ... ensuring init/exit sections work to shrink
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#include "composite.c"
#include "usbstring.c"
#include "config.c"
#include "epautoconf.c"
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
# if defined USB_ETH_RNDIS
# undef USB_ETH_RNDIS
# endif
# ifdef CONFIG_USB_FUNCTIONFS_RNDIS
# define USB_ETH_RNDIS y
# endif
# include "f_ecm.c"
# include "f_subset.c"
# ifdef USB_ETH_RNDIS
# include "f_rndis.c"
# include "rndis.c"
# endif
# include "u_ether.c"
static u8 gfs_hostaddr[ETH_ALEN];
#else
# if !defined CONFIG_USB_FUNCTIONFS_GENERIC
# define CONFIG_USB_FUNCTIONFS_GENERIC
# endif
# define gether_cleanup() do { } while (0)
# define gether_setup(gadget, hostaddr) ((int)0)
#endif
#include "f_fs.c"
#define DRIVER_NAME "g_ffs"
#define DRIVER_DESC "USB Function Filesystem"
#define DRIVER_VERSION "24 Aug 2004"
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Michal Nazarewicz");
MODULE_LICENSE("GPL");
static unsigned short gfs_vendor_id = 0x0525; /* XXX NetChip */
static unsigned short gfs_product_id = 0xa4ac; /* XXX */
static struct usb_device_descriptor gfs_dev_desc = {
.bLength = sizeof gfs_dev_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE,
/* Vendor and product id can be overridden by module parameters. */
/* .idVendor = cpu_to_le16(gfs_vendor_id), */
/* .idProduct = cpu_to_le16(gfs_product_id), */
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
/* NO SERIAL NUMBER */
.bNumConfigurations = 1,
};
#define GFS_MODULE_PARAM_DESC(name, field) \
MODULE_PARM_DESC(name, "Value of the " #field " field of the device descriptor sent to the host. Takes effect only prior to the user-space driver registering to the FunctionFS.")
module_param_named(usb_class, gfs_dev_desc.bDeviceClass, byte, 0644);
GFS_MODULE_PARAM_DESC(usb_class, bDeviceClass);
module_param_named(usb_subclass, gfs_dev_desc.bDeviceSubClass, byte, 0644);
GFS_MODULE_PARAM_DESC(usb_subclass, bDeviceSubClass);
module_param_named(usb_protocol, gfs_dev_desc.bDeviceProtocol, byte, 0644);
GFS_MODULE_PARAM_DESC(usb_protocol, bDeviceProtocol);
module_param_named(usb_vendor, gfs_vendor_id, ushort, 0644);
GFS_MODULE_PARAM_DESC(usb_vendor, idVendor);
module_param_named(usb_product, gfs_product_id, ushort, 0644);
GFS_MODULE_PARAM_DESC(usb_product, idProduct);
static const struct usb_descriptor_header *gfs_otg_desc[] = {
(const struct usb_descriptor_header *)
&(const struct usb_otg_descriptor) {
.bLength = sizeof(struct usb_otg_descriptor),
.bDescriptorType = USB_DT_OTG,
/* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ... */
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
},
NULL
};
/* string IDs are assigned dynamically */
enum {
GFS_STRING_MANUFACTURER_IDX,
GFS_STRING_PRODUCT_IDX,
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
GFS_STRING_RNDIS_CONFIG_IDX,
#endif
#ifdef CONFIG_USB_FUNCTIONFS_ETH
GFS_STRING_ECM_CONFIG_IDX,
#endif
#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
GFS_STRING_GENERIC_CONFIG_IDX,
#endif
};
static char gfs_manufacturer[50];
static const char gfs_driver_desc[] = DRIVER_DESC;
static const char gfs_short_name[] = DRIVER_NAME;
static struct usb_string gfs_strings[] = {
[GFS_STRING_MANUFACTURER_IDX].s = gfs_manufacturer,
[GFS_STRING_PRODUCT_IDX].s = gfs_driver_desc,
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
[GFS_STRING_RNDIS_CONFIG_IDX].s = "FunctionFS + RNDIS",
#endif
#ifdef CONFIG_USB_FUNCTIONFS_ETH
[GFS_STRING_ECM_CONFIG_IDX].s = "FunctionFS + ECM",
#endif
#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
[GFS_STRING_GENERIC_CONFIG_IDX].s = "FunctionFS",
#endif
{ } /* end of list */
};
static struct usb_gadget_strings *gfs_dev_strings[] = {
&(struct usb_gadget_strings) {
.language = 0x0409, /* en-us */
.strings = gfs_strings,
},
NULL,
};
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
static int gfs_do_rndis_config(struct usb_configuration *c);
static struct usb_configuration gfs_rndis_config_driver = {
.label = "FunctionFS + RNDIS",
.bind = gfs_do_rndis_config,
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
# define gfs_add_rndis_config(cdev) \
usb_add_config(cdev, &gfs_rndis_config_driver)
#else
# define gfs_add_rndis_config(cdev) 0
#endif
#ifdef CONFIG_USB_FUNCTIONFS_ETH
static int gfs_do_ecm_config(struct usb_configuration *c);
static struct usb_configuration gfs_ecm_config_driver = {
.label = "FunctionFS + ECM",
.bind = gfs_do_ecm_config,
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
# define gfs_add_ecm_config(cdev) \
usb_add_config(cdev, &gfs_ecm_config_driver)
#else
# define gfs_add_ecm_config(cdev) 0
#endif
#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
static int gfs_do_generic_config(struct usb_configuration *c);
static struct usb_configuration gfs_generic_config_driver = {
.label = "FunctionFS",
.bind = gfs_do_generic_config,
.bConfigurationValue = 2,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
# define gfs_add_generic_config(cdev) \
usb_add_config(cdev, &gfs_generic_config_driver)
#else
# define gfs_add_generic_config(cdev) 0
#endif
static int gfs_bind(struct usb_composite_dev *cdev);
static int gfs_unbind(struct usb_composite_dev *cdev);
static struct usb_composite_driver gfs_driver = {
.name = gfs_short_name,
.dev = &gfs_dev_desc,
.strings = gfs_dev_strings,
.bind = gfs_bind,
.unbind = gfs_unbind,
};
static struct ffs_data *gfs_ffs_data;
static unsigned long gfs_registered;
static int gfs_init(void)
{
ENTER();
return functionfs_init();
}
module_init(gfs_init);
static void gfs_exit(void)
{
ENTER();
if (test_and_clear_bit(0, &gfs_registered))
usb_composite_unregister(&gfs_driver);
functionfs_cleanup();
}
module_exit(gfs_exit);
static int functionfs_ready_callback(struct ffs_data *ffs)
{
int ret;
ENTER();
if (WARN_ON(test_and_set_bit(0, &gfs_registered)))
return -EBUSY;
gfs_ffs_data = ffs;
ret = usb_composite_register(&gfs_driver);
if (unlikely(ret < 0))
clear_bit(0, &gfs_registered);
return ret;
}
static void functionfs_closed_callback(struct ffs_data *ffs)
{
ENTER();
if (test_and_clear_bit(0, &gfs_registered))
usb_composite_unregister(&gfs_driver);
}
static int functionfs_check_dev_callback(const char *dev_name)
{
return 0;
}
static int gfs_bind(struct usb_composite_dev *cdev)
{
int ret;
ENTER();
if (WARN_ON(!gfs_ffs_data))
return -ENODEV;
ret = gether_setup(cdev->gadget, gfs_hostaddr);
if (unlikely(ret < 0))
goto error_quick;
gfs_dev_desc.idVendor = cpu_to_le16(gfs_vendor_id);
gfs_dev_desc.idProduct = cpu_to_le16(gfs_product_id);
snprintf(gfs_manufacturer, sizeof gfs_manufacturer, "%s %s with %s",
init_utsname()->sysname, init_utsname()->release,
cdev->gadget->name);
ret = usb_string_id(cdev);
if (unlikely(ret < 0))
goto error;
gfs_strings[GFS_STRING_MANUFACTURER_IDX].id = ret;
gfs_dev_desc.iManufacturer = ret;
ret = usb_string_id(cdev);
if (unlikely(ret < 0))
goto error;
gfs_strings[GFS_STRING_PRODUCT_IDX].id = ret;
gfs_dev_desc.iProduct = ret;
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
ret = usb_string_id(cdev);
if (unlikely(ret < 0))
goto error;
gfs_strings[GFS_STRING_RNDIS_CONFIG_IDX].id = ret;
gfs_rndis_config_driver.iConfiguration = ret;
#endif
#ifdef CONFIG_USB_FUNCTIONFS_ETH
ret = usb_string_id(cdev);
if (unlikely(ret < 0))
goto error;
gfs_strings[GFS_STRING_ECM_CONFIG_IDX].id = ret;
gfs_ecm_config_driver.iConfiguration = ret;
#endif
#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
ret = usb_string_id(cdev);
if (unlikely(ret < 0))
goto error;
gfs_strings[GFS_STRING_GENERIC_CONFIG_IDX].id = ret;
gfs_generic_config_driver.iConfiguration = ret;
#endif
ret = functionfs_bind(gfs_ffs_data, cdev);
if (unlikely(ret < 0))
goto error;
ret = gfs_add_rndis_config(cdev);
if (unlikely(ret < 0))
goto error_unbind;
ret = gfs_add_ecm_config(cdev);
if (unlikely(ret < 0))
goto error_unbind;
ret = gfs_add_generic_config(cdev);
if (unlikely(ret < 0))
goto error_unbind;
return 0;
error_unbind:
functionfs_unbind(gfs_ffs_data);
error:
gether_cleanup();
error_quick:
gfs_ffs_data = NULL;
return ret;
}
static int gfs_unbind(struct usb_composite_dev *cdev)
{
ENTER();
/* We may have been called in an error recovery frem
* composite_bind() after gfs_unbind() failure so we need to
* check if gfs_ffs_data is not NULL since gfs_bind() handles
* all error recovery itself. I'd rather we werent called
* from composite on orror recovery, but what you're gonna
* do...? */
if (gfs_ffs_data) {
gether_cleanup();
functionfs_unbind(gfs_ffs_data);
gfs_ffs_data = NULL;
}
return 0;
}
static int __gfs_do_config(struct usb_configuration *c,
int (*eth)(struct usb_configuration *c, u8 *ethaddr),
u8 *ethaddr)
{
int ret;
if (WARN_ON(!gfs_ffs_data))
return -ENODEV;
if (gadget_is_otg(c->cdev->gadget)) {
c->descriptors = gfs_otg_desc;
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
if (eth) {
ret = eth(c, ethaddr);
if (unlikely(ret < 0))
return ret;
}
ret = functionfs_add(c->cdev, c, gfs_ffs_data);
if (unlikely(ret < 0))
return ret;
return 0;
}
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
static int gfs_do_rndis_config(struct usb_configuration *c)
{
ENTER();
return __gfs_do_config(c, rndis_bind_config, gfs_hostaddr);
}
#endif
#ifdef CONFIG_USB_FUNCTIONFS_ETH
static int gfs_do_ecm_config(struct usb_configuration *c)
{
ENTER();
return __gfs_do_config(c,
can_support_ecm(c->cdev->gadget)
? ecm_bind_config : geth_bind_config,
gfs_hostaddr);
}
#endif
#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
static int gfs_do_generic_config(struct usb_configuration *c)
{
ENTER();
return __gfs_do_config(c, NULL, NULL);
}
#endif

298
drivers/usb/gadget/hid.c Normal file
View file

@ -0,0 +1,298 @@
/*
* hid.c -- HID Composite driver
*
* Based on multi.c
*
* Copyright (C) 2010 Fabien Chouteau <fabien.chouteau@barco.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/list.h>
#define DRIVER_DESC "HID Gadget"
#define DRIVER_VERSION "2010/03/16"
/*-------------------------------------------------------------------------*/
#define HIDG_VENDOR_NUM 0x0525 /* XXX NetChip */
#define HIDG_PRODUCT_NUM 0xa4ac /* Linux-USB HID gadget */
/*-------------------------------------------------------------------------*/
/*
* kbuild is not very cooperative with respect to linking separately
* compiled library objects into one module. So for now we won't use
* separate compilation ... ensuring init/exit sections work to shrink
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#include "composite.c"
#include "usbstring.c"
#include "config.c"
#include "epautoconf.c"
#include "f_hid.c"
struct hidg_func_node {
struct list_head node;
struct hidg_func_descriptor *func;
};
static LIST_HEAD(hidg_func_list);
/*-------------------------------------------------------------------------*/
static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = cpu_to_le16(0x0200),
/* .bDeviceClass = USB_CLASS_COMM, */
/* .bDeviceSubClass = 0, */
/* .bDeviceProtocol = 0, */
.bDeviceClass = 0xEF,
.bDeviceSubClass = 2,
.bDeviceProtocol = 1,
/* .bMaxPacketSize0 = f(hardware) */
/* Vendor and product id can be overridden by module parameters. */
.idVendor = cpu_to_le16(HIDG_VENDOR_NUM),
.idProduct = cpu_to_le16(HIDG_PRODUCT_NUM),
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
/* NO SERIAL NUMBER */
.bNumConfigurations = 1,
};
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
/* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
/* string IDs are assigned dynamically */
#define STRING_MANUFACTURER_IDX 0
#define STRING_PRODUCT_IDX 1
static char manufacturer[50];
static struct usb_string strings_dev[] = {
[STRING_MANUFACTURER_IDX].s = manufacturer,
[STRING_PRODUCT_IDX].s = DRIVER_DESC,
{ } /* end of list */
};
static struct usb_gadget_strings stringtab_dev = {
.language = 0x0409, /* en-us */
.strings = strings_dev,
};
static struct usb_gadget_strings *dev_strings[] = {
&stringtab_dev,
NULL,
};
/****************************** Configurations ******************************/
static int __init do_config(struct usb_configuration *c)
{
struct hidg_func_node *e;
int func = 0, status = 0;
if (gadget_is_otg(c->cdev->gadget)) {
c->descriptors = otg_desc;
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
list_for_each_entry(e, &hidg_func_list, node) {
status = hidg_bind_config(c, e->func, func++);
if (status)
break;
}
return status;
}
static struct usb_configuration config_driver = {
.label = "HID Gadget",
.bind = do_config,
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
/****************************** Gadget Bind ******************************/
static int __init hid_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
struct list_head *tmp;
int status, gcnum, funcs = 0;
list_for_each(tmp, &hidg_func_list)
funcs++;
if (!funcs)
return -ENODEV;
/* set up HID */
status = ghid_setup(cdev->gadget, funcs);
if (status < 0)
return status;
gcnum = usb_gadget_controller_number(gadget);
if (gcnum >= 0)
device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
else
device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099);
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.
*/
/* device descriptor strings: manufacturer, product */
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
init_utsname()->sysname, init_utsname()->release,
gadget->name);
status = usb_string_id(cdev);
if (status < 0)
return status;
strings_dev[STRING_MANUFACTURER_IDX].id = status;
device_desc.iManufacturer = status;
status = usb_string_id(cdev);
if (status < 0)
return status;
strings_dev[STRING_PRODUCT_IDX].id = status;
device_desc.iProduct = status;
/* register our configuration */
status = usb_add_config(cdev, &config_driver);
if (status < 0)
return status;
dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
return 0;
}
static int __exit hid_unbind(struct usb_composite_dev *cdev)
{
ghid_cleanup();
return 0;
}
static int __init hidg_plat_driver_probe(struct platform_device *pdev)
{
struct hidg_func_descriptor *func = pdev->dev.platform_data;
struct hidg_func_node *entry;
if (!func) {
dev_err(&pdev->dev, "Platform data missing\n");
return -ENODEV;
}
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
entry->func = func;
list_add_tail(&entry->node, &hidg_func_list);
return 0;
}
static int __devexit hidg_plat_driver_remove(struct platform_device *pdev)
{
struct hidg_func_node *e, *n;
list_for_each_entry_safe(e, n, &hidg_func_list, node) {
list_del(&e->node);
kfree(e);
}
return 0;
}
/****************************** Some noise ******************************/
static struct usb_composite_driver hidg_driver = {
.name = "g_hid",
.dev = &device_desc,
.strings = dev_strings,
.bind = hid_bind,
.unbind = __exit_p(hid_unbind),
};
static struct platform_driver hidg_plat_driver = {
.remove = __devexit_p(hidg_plat_driver_remove),
.driver = {
.owner = THIS_MODULE,
.name = "hidg",
},
};
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Fabien Chouteau, Peter Korsgaard");
MODULE_LICENSE("GPL");
static int __init hidg_init(void)
{
int status;
status = platform_driver_probe(&hidg_plat_driver,
hidg_plat_driver_probe);
if (status < 0)
return status;
status = usb_composite_register(&hidg_driver);
if (status < 0)
platform_driver_unregister(&hidg_plat_driver);
return status;
}
module_init(hidg_init);
static void __exit hidg_cleanup(void)
{
platform_driver_unregister(&hidg_plat_driver);
usb_composite_unregister(&hidg_driver);
}
module_exit(hidg_cleanup);

View file

@ -360,7 +360,7 @@ struct pxa_ep {
* Specific pxa endpoint data, needed for hardware initialization
*/
unsigned dir_in:1;
unsigned addr:3;
unsigned addr:4;
unsigned config:2;
unsigned interface:3;
unsigned alternate:3;

View file

@ -715,7 +715,7 @@ static u8 __init nibble(unsigned char c)
return 0;
}
static int __init get_ether_addr(const char *str, u8 *dev_addr)
static int get_ether_addr(const char *str, u8 *dev_addr)
{
if (str) {
unsigned i;
@ -764,7 +764,7 @@ static struct device_type gadget_type = {
*
* Returns negative errno, or zero on success
*/
int __init gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
{
struct eth_dev *dev;
struct net_device *net;

241
drivers/usb/gadget/uvc.h Normal file
View file

@ -0,0 +1,241 @@
/*
* uvc_gadget.h -- USB Video Class Gadget driver
*
* Copyright (C) 2009-2010
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#ifndef _UVC_GADGET_H_
#define _UVC_GADGET_H_
#include <linux/ioctl.h>
#include <linux/types.h>
#include <linux/usb/ch9.h>
#define UVC_EVENT_FIRST (V4L2_EVENT_PRIVATE_START + 0)
#define UVC_EVENT_CONNECT (V4L2_EVENT_PRIVATE_START + 0)
#define UVC_EVENT_DISCONNECT (V4L2_EVENT_PRIVATE_START + 1)
#define UVC_EVENT_STREAMON (V4L2_EVENT_PRIVATE_START + 2)
#define UVC_EVENT_STREAMOFF (V4L2_EVENT_PRIVATE_START + 3)
#define UVC_EVENT_SETUP (V4L2_EVENT_PRIVATE_START + 4)
#define UVC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5)
#define UVC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 5)
struct uvc_request_data
{
unsigned int length;
__u8 data[60];
};
struct uvc_event
{
union {
enum usb_device_speed speed;
struct usb_ctrlrequest req;
struct uvc_request_data data;
};
};
#define UVCIOC_SEND_RESPONSE _IOW('U', 1, struct uvc_request_data)
#define UVC_INTF_CONTROL 0
#define UVC_INTF_STREAMING 1
/* ------------------------------------------------------------------------
* UVC constants & structures
*/
/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
#define UVC_STREAM_EOH (1 << 7)
#define UVC_STREAM_ERR (1 << 6)
#define UVC_STREAM_STI (1 << 5)
#define UVC_STREAM_RES (1 << 4)
#define UVC_STREAM_SCR (1 << 3)
#define UVC_STREAM_PTS (1 << 2)
#define UVC_STREAM_EOF (1 << 1)
#define UVC_STREAM_FID (1 << 0)
struct uvc_streaming_control {
__u16 bmHint;
__u8 bFormatIndex;
__u8 bFrameIndex;
__u32 dwFrameInterval;
__u16 wKeyFrameRate;
__u16 wPFrameRate;
__u16 wCompQuality;
__u16 wCompWindowSize;
__u16 wDelay;
__u32 dwMaxVideoFrameSize;
__u32 dwMaxPayloadTransferSize;
__u32 dwClockFrequency;
__u8 bmFramingInfo;
__u8 bPreferedVersion;
__u8 bMinVersion;
__u8 bMaxVersion;
} __attribute__((__packed__));
/* ------------------------------------------------------------------------
* Debugging, printing and logging
*/
#ifdef __KERNEL__
#include <linux/usb.h> /* For usb_endpoint_* */
#include <linux/usb/gadget.h>
#include <linux/videodev2.h>
#include <media/v4l2-fh.h>
#include "uvc_queue.h"
#define UVC_TRACE_PROBE (1 << 0)
#define UVC_TRACE_DESCR (1 << 1)
#define UVC_TRACE_CONTROL (1 << 2)
#define UVC_TRACE_FORMAT (1 << 3)
#define UVC_TRACE_CAPTURE (1 << 4)
#define UVC_TRACE_CALLS (1 << 5)
#define UVC_TRACE_IOCTL (1 << 6)
#define UVC_TRACE_FRAME (1 << 7)
#define UVC_TRACE_SUSPEND (1 << 8)
#define UVC_TRACE_STATUS (1 << 9)
#define UVC_WARN_MINMAX 0
#define UVC_WARN_PROBE_DEF 1
extern unsigned int uvc_trace_param;
#define uvc_trace(flag, msg...) \
do { \
if (uvc_trace_param & flag) \
printk(KERN_DEBUG "uvcvideo: " msg); \
} while (0)
#define uvc_warn_once(dev, warn, msg...) \
do { \
if (!test_and_set_bit(warn, &dev->warnings)) \
printk(KERN_INFO "uvcvideo: " msg); \
} while (0)
#define uvc_printk(level, msg...) \
printk(level "uvcvideo: " msg)
/* ------------------------------------------------------------------------
* Driver specific constants
*/
#define DRIVER_VERSION "0.1.0"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 0)
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define UVC_NUM_REQUESTS 4
#define UVC_MAX_REQUEST_SIZE 64
#define UVC_MAX_EVENTS 4
#define USB_DT_INTERFACE_ASSOCIATION_SIZE 8
#define USB_CLASS_MISC 0xef
/* ------------------------------------------------------------------------
* Structures
*/
struct uvc_video
{
struct usb_ep *ep;
/* Frame parameters */
u8 bpp;
u32 fcc;
unsigned int width;
unsigned int height;
unsigned int imagesize;
/* Requests */
unsigned int req_size;
struct usb_request *req[UVC_NUM_REQUESTS];
__u8 *req_buffer[UVC_NUM_REQUESTS];
struct list_head req_free;
spinlock_t req_lock;
void (*encode) (struct usb_request *req, struct uvc_video *video,
struct uvc_buffer *buf);
/* Context data used by the completion handler */
__u32 payload_size;
__u32 max_payload_size;
struct uvc_video_queue queue;
unsigned int fid;
};
enum uvc_state
{
UVC_STATE_DISCONNECTED,
UVC_STATE_CONNECTED,
UVC_STATE_STREAMING,
};
struct uvc_device
{
struct video_device *vdev;
enum uvc_state state;
struct usb_function func;
struct uvc_video video;
/* Descriptors */
struct {
const struct uvc_descriptor_header * const *control;
const struct uvc_descriptor_header * const *fs_streaming;
const struct uvc_descriptor_header * const *hs_streaming;
} desc;
unsigned int control_intf;
struct usb_ep *control_ep;
struct usb_request *control_req;
void *control_buf;
unsigned int streaming_intf;
/* Events */
unsigned int event_length;
unsigned int event_setup_out : 1;
};
static inline struct uvc_device *to_uvc(struct usb_function *f)
{
return container_of(f, struct uvc_device, func);
}
struct uvc_file_handle
{
struct v4l2_fh vfh;
struct uvc_video *device;
};
#define to_uvc_file_handle(handle) \
container_of(handle, struct uvc_file_handle, vfh)
extern struct v4l2_file_operations uvc_v4l2_fops;
/* ------------------------------------------------------------------------
* Functions
*/
extern int uvc_video_enable(struct uvc_video *video, int enable);
extern int uvc_video_init(struct uvc_video *video);
extern int uvc_video_pump(struct uvc_video *video);
extern void uvc_endpoint_stream(struct uvc_device *dev);
extern void uvc_function_connect(struct uvc_device *uvc);
extern void uvc_function_disconnect(struct uvc_device *uvc);
#endif /* __KERNEL__ */
#endif /* _UVC_GADGET_H_ */

View file

@ -0,0 +1,583 @@
/*
* uvc_queue.c -- USB Video Class driver - Buffers management
*
* Copyright (C) 2005-2010
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <asm/atomic.h>
#include "uvc.h"
/* ------------------------------------------------------------------------
* Video buffers queue management.
*
* Video queues is initialized by uvc_queue_init(). The function performs
* basic initialization of the uvc_video_queue struct and never fails.
*
* Video buffer allocation and freeing are performed by uvc_alloc_buffers and
* uvc_free_buffers respectively. The former acquires the video queue lock,
* while the later must be called with the lock held (so that allocation can
* free previously allocated buffers). Trying to free buffers that are mapped
* to user space will return -EBUSY.
*
* Video buffers are managed using two queues. However, unlike most USB video
* drivers that use an in queue and an out queue, we use a main queue to hold
* all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
* hold empty buffers. This design (copied from video-buf) minimizes locking
* in interrupt, as only one queue is shared between interrupt and user
* contexts.
*
* Use cases
* ---------
*
* Unless stated otherwise, all operations that modify the irq buffers queue
* are protected by the irq spinlock.
*
* 1. The user queues the buffers, starts streaming and dequeues a buffer.
*
* The buffers are added to the main and irq queues. Both operations are
* protected by the queue lock, and the later is protected by the irq
* spinlock as well.
*
* The completion handler fetches a buffer from the irq queue and fills it
* with video data. If no buffer is available (irq queue empty), the handler
* returns immediately.
*
* When the buffer is full, the completion handler removes it from the irq
* queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue.
* At that point, any process waiting on the buffer will be woken up. If a
* process tries to dequeue a buffer after it has been marked ready, the
* dequeing will succeed immediately.
*
* 2. Buffers are queued, user is waiting on a buffer and the device gets
* disconnected.
*
* When the device is disconnected, the kernel calls the completion handler
* with an appropriate status code. The handler marks all buffers in the
* irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so
* that any process waiting on a buffer gets woken up.
*
* Waking up up the first buffer on the irq list is not enough, as the
* process waiting on the buffer might restart the dequeue operation
* immediately.
*
*/
void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
{
mutex_init(&queue->mutex);
spin_lock_init(&queue->irqlock);
INIT_LIST_HEAD(&queue->mainqueue);
INIT_LIST_HEAD(&queue->irqqueue);
queue->type = type;
}
/*
* Allocate the video buffers.
*
* Pages are reserved to make sure they will not be swapped, as they will be
* filled in the URB completion handler.
*
* Buffers will be individually mapped, so they must all be page aligned.
*/
int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
unsigned int buflength)
{
unsigned int bufsize = PAGE_ALIGN(buflength);
unsigned int i;
void *mem = NULL;
int ret;
if (nbuffers > UVC_MAX_VIDEO_BUFFERS)
nbuffers = UVC_MAX_VIDEO_BUFFERS;
mutex_lock(&queue->mutex);
if ((ret = uvc_free_buffers(queue)) < 0)
goto done;
/* Bail out if no buffers should be allocated. */
if (nbuffers == 0)
goto done;
/* Decrement the number of buffers until allocation succeeds. */
for (; nbuffers > 0; --nbuffers) {
mem = vmalloc_32(nbuffers * bufsize);
if (mem != NULL)
break;
}
if (mem == NULL) {
ret = -ENOMEM;
goto done;
}
for (i = 0; i < nbuffers; ++i) {
memset(&queue->buffer[i], 0, sizeof queue->buffer[i]);
queue->buffer[i].buf.index = i;
queue->buffer[i].buf.m.offset = i * bufsize;
queue->buffer[i].buf.length = buflength;
queue->buffer[i].buf.type = queue->type;
queue->buffer[i].buf.sequence = 0;
queue->buffer[i].buf.field = V4L2_FIELD_NONE;
queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;
queue->buffer[i].buf.flags = 0;
init_waitqueue_head(&queue->buffer[i].wait);
}
queue->mem = mem;
queue->count = nbuffers;
queue->buf_size = bufsize;
ret = nbuffers;
done:
mutex_unlock(&queue->mutex);
return ret;
}
/*
* Free the video buffers.
*
* This function must be called with the queue lock held.
*/
int uvc_free_buffers(struct uvc_video_queue *queue)
{
unsigned int i;
for (i = 0; i < queue->count; ++i) {
if (queue->buffer[i].vma_use_count != 0)
return -EBUSY;
}
if (queue->count) {
vfree(queue->mem);
queue->count = 0;
}
return 0;
}
static void __uvc_query_buffer(struct uvc_buffer *buf,
struct v4l2_buffer *v4l2_buf)
{
memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
if (buf->vma_use_count)
v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;
switch (buf->state) {
case UVC_BUF_STATE_ERROR:
case UVC_BUF_STATE_DONE:
v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
break;
case UVC_BUF_STATE_QUEUED:
case UVC_BUF_STATE_ACTIVE:
v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
break;
case UVC_BUF_STATE_IDLE:
default:
break;
}
}
int uvc_query_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf)
{
int ret = 0;
mutex_lock(&queue->mutex);
if (v4l2_buf->index >= queue->count) {
ret = -EINVAL;
goto done;
}
__uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
done:
mutex_unlock(&queue->mutex);
return ret;
}
/*
* Queue a video buffer. Attempting to queue a buffer that has already been
* queued will return -EINVAL.
*/
int uvc_queue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf)
{
struct uvc_buffer *buf;
unsigned long flags;
int ret = 0;
uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index);
if (v4l2_buf->type != queue->type ||
v4l2_buf->memory != V4L2_MEMORY_MMAP) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
"and/or memory (%u).\n", v4l2_buf->type,
v4l2_buf->memory);
return -EINVAL;
}
mutex_lock(&queue->mutex);
if (v4l2_buf->index >= queue->count) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
ret = -EINVAL;
goto done;
}
buf = &queue->buffer[v4l2_buf->index];
if (buf->state != UVC_BUF_STATE_IDLE) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state "
"(%u).\n", buf->state);
ret = -EINVAL;
goto done;
}
if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
v4l2_buf->bytesused > buf->buf.length) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
ret = -EINVAL;
goto done;
}
if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
buf->buf.bytesused = 0;
else
buf->buf.bytesused = v4l2_buf->bytesused;
spin_lock_irqsave(&queue->irqlock, flags);
if (queue->flags & UVC_QUEUE_DISCONNECTED) {
spin_unlock_irqrestore(&queue->irqlock, flags);
ret = -ENODEV;
goto done;
}
buf->state = UVC_BUF_STATE_QUEUED;
ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
queue->flags &= ~UVC_QUEUE_PAUSED;
list_add_tail(&buf->stream, &queue->mainqueue);
list_add_tail(&buf->queue, &queue->irqqueue);
spin_unlock_irqrestore(&queue->irqlock, flags);
done:
mutex_unlock(&queue->mutex);
return ret;
}
static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
{
if (nonblocking) {
return (buf->state != UVC_BUF_STATE_QUEUED &&
buf->state != UVC_BUF_STATE_ACTIVE)
? 0 : -EAGAIN;
}
return wait_event_interruptible(buf->wait,
buf->state != UVC_BUF_STATE_QUEUED &&
buf->state != UVC_BUF_STATE_ACTIVE);
}
/*
* Dequeue a video buffer. If nonblocking is false, block until a buffer is
* available.
*/
int uvc_dequeue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf, int nonblocking)
{
struct uvc_buffer *buf;
int ret = 0;
if (v4l2_buf->type != queue->type ||
v4l2_buf->memory != V4L2_MEMORY_MMAP) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
"and/or memory (%u).\n", v4l2_buf->type,
v4l2_buf->memory);
return -EINVAL;
}
mutex_lock(&queue->mutex);
if (list_empty(&queue->mainqueue)) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n");
ret = -EINVAL;
goto done;
}
buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
goto done;
uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
buf->buf.index, buf->state, buf->buf.bytesused);
switch (buf->state) {
case UVC_BUF_STATE_ERROR:
uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
"(transmission error).\n");
ret = -EIO;
case UVC_BUF_STATE_DONE:
buf->state = UVC_BUF_STATE_IDLE;
break;
case UVC_BUF_STATE_IDLE:
case UVC_BUF_STATE_QUEUED:
case UVC_BUF_STATE_ACTIVE:
default:
uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u "
"(driver bug?).\n", buf->state);
ret = -EINVAL;
goto done;
}
list_del(&buf->stream);
__uvc_query_buffer(buf, v4l2_buf);
done:
mutex_unlock(&queue->mutex);
return ret;
}
/*
* Poll the video queue.
*
* This function implements video queue polling and is intended to be used by
* the device poll handler.
*/
unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
poll_table *wait)
{
struct uvc_buffer *buf;
unsigned int mask = 0;
mutex_lock(&queue->mutex);
if (list_empty(&queue->mainqueue))
goto done;
buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
poll_wait(file, &buf->wait, wait);
if (buf->state == UVC_BUF_STATE_DONE ||
buf->state == UVC_BUF_STATE_ERROR)
mask |= POLLOUT | POLLWRNORM;
done:
mutex_unlock(&queue->mutex);
return mask;
}
/*
* VMA operations.
*/
static void uvc_vm_open(struct vm_area_struct *vma)
{
struct uvc_buffer *buffer = vma->vm_private_data;
buffer->vma_use_count++;
}
static void uvc_vm_close(struct vm_area_struct *vma)
{
struct uvc_buffer *buffer = vma->vm_private_data;
buffer->vma_use_count--;
}
static struct vm_operations_struct uvc_vm_ops = {
.open = uvc_vm_open,
.close = uvc_vm_close,
};
/*
* Memory-map a buffer.
*
* This function implements video buffer memory mapping and is intended to be
* used by the device mmap handler.
*/
int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
{
struct uvc_buffer *uninitialized_var(buffer);
struct page *page;
unsigned long addr, start, size;
unsigned int i;
int ret = 0;
start = vma->vm_start;
size = vma->vm_end - vma->vm_start;
mutex_lock(&queue->mutex);
for (i = 0; i < queue->count; ++i) {
buffer = &queue->buffer[i];
if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
break;
}
if (i == queue->count || size != queue->buf_size) {
ret = -EINVAL;
goto done;
}
/*
* VM_IO marks the area as being an mmaped region for I/O to a
* device. It also prevents the region from being core dumped.
*/
vma->vm_flags |= VM_IO;
addr = (unsigned long)queue->mem + buffer->buf.m.offset;
while (size > 0) {
page = vmalloc_to_page((void *)addr);
if ((ret = vm_insert_page(vma, start, page)) < 0)
goto done;
start += PAGE_SIZE;
addr += PAGE_SIZE;
size -= PAGE_SIZE;
}
vma->vm_ops = &uvc_vm_ops;
vma->vm_private_data = buffer;
uvc_vm_open(vma);
done:
mutex_unlock(&queue->mutex);
return ret;
}
/*
* Enable or disable the video buffers queue.
*
* The queue must be enabled before starting video acquisition and must be
* disabled after stopping it. This ensures that the video buffers queue
* state can be properly initialized before buffers are accessed from the
* interrupt handler.
*
* Enabling the video queue initializes parameters (such as sequence number,
* sync pattern, ...). If the queue is already enabled, return -EBUSY.
*
* Disabling the video queue cancels the queue and removes all buffers from
* the main queue.
*
* This function can't be called from interrupt context. Use
* uvc_queue_cancel() instead.
*/
int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
{
unsigned int i;
int ret = 0;
mutex_lock(&queue->mutex);
if (enable) {
if (uvc_queue_streaming(queue)) {
ret = -EBUSY;
goto done;
}
queue->sequence = 0;
queue->flags |= UVC_QUEUE_STREAMING;
queue->buf_used = 0;
} else {
uvc_queue_cancel(queue, 0);
INIT_LIST_HEAD(&queue->mainqueue);
for (i = 0; i < queue->count; ++i)
queue->buffer[i].state = UVC_BUF_STATE_IDLE;
queue->flags &= ~UVC_QUEUE_STREAMING;
}
done:
mutex_unlock(&queue->mutex);
return ret;
}
/*
* Cancel the video buffers queue.
*
* Cancelling the queue marks all buffers on the irq queue as erroneous,
* wakes them up and removes them from the queue.
*
* If the disconnect parameter is set, further calls to uvc_queue_buffer will
* fail with -ENODEV.
*
* This function acquires the irq spinlock and can be called from interrupt
* context.
*/
void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
{
struct uvc_buffer *buf;
unsigned long flags;
spin_lock_irqsave(&queue->irqlock, flags);
while (!list_empty(&queue->irqqueue)) {
buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
list_del(&buf->queue);
buf->state = UVC_BUF_STATE_ERROR;
wake_up(&buf->wait);
}
/* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_queue_buffer and the disconnection event that
* could result in an interruptible wait in uvc_dequeue_buffer. Do not
* blindly replace this logic by checking for the UVC_DEV_DISCONNECTED
* state outside the queue code.
*/
if (disconnect)
queue->flags |= UVC_QUEUE_DISCONNECTED;
spin_unlock_irqrestore(&queue->irqlock, flags);
}
struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf)
{
struct uvc_buffer *nextbuf;
unsigned long flags;
if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
buf->buf.length != buf->buf.bytesused) {
buf->state = UVC_BUF_STATE_QUEUED;
buf->buf.bytesused = 0;
return buf;
}
spin_lock_irqsave(&queue->irqlock, flags);
list_del(&buf->queue);
if (!list_empty(&queue->irqqueue))
nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
else
nextbuf = NULL;
spin_unlock_irqrestore(&queue->irqlock, flags);
buf->buf.sequence = queue->sequence++;
do_gettimeofday(&buf->buf.timestamp);
wake_up(&buf->wait);
return nextbuf;
}
struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue)
{
struct uvc_buffer *buf = NULL;
if (!list_empty(&queue->irqqueue))
buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
else
queue->flags |= UVC_QUEUE_PAUSED;
return buf;
}

View file

@ -0,0 +1,89 @@
#ifndef _UVC_QUEUE_H_
#define _UVC_QUEUE_H_
#ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/videodev2.h>
/* Maximum frame size in bytes, for sanity checking. */
#define UVC_MAX_FRAME_SIZE (16*1024*1024)
/* Maximum number of video buffers. */
#define UVC_MAX_VIDEO_BUFFERS 32
/* ------------------------------------------------------------------------
* Structures.
*/
enum uvc_buffer_state {
UVC_BUF_STATE_IDLE = 0,
UVC_BUF_STATE_QUEUED = 1,
UVC_BUF_STATE_ACTIVE = 2,
UVC_BUF_STATE_DONE = 3,
UVC_BUF_STATE_ERROR = 4,
};
struct uvc_buffer {
unsigned long vma_use_count;
struct list_head stream;
/* Touched by interrupt handler. */
struct v4l2_buffer buf;
struct list_head queue;
wait_queue_head_t wait;
enum uvc_buffer_state state;
};
#define UVC_QUEUE_STREAMING (1 << 0)
#define UVC_QUEUE_DISCONNECTED (1 << 1)
#define UVC_QUEUE_DROP_INCOMPLETE (1 << 2)
#define UVC_QUEUE_PAUSED (1 << 3)
struct uvc_video_queue {
enum v4l2_buf_type type;
void *mem;
unsigned int flags;
__u32 sequence;
unsigned int count;
unsigned int buf_size;
unsigned int buf_used;
struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
struct mutex mutex; /* protects buffers and mainqueue */
spinlock_t irqlock; /* protects irqqueue */
struct list_head mainqueue;
struct list_head irqqueue;
};
extern void uvc_queue_init(struct uvc_video_queue *queue,
enum v4l2_buf_type type);
extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
unsigned int nbuffers, unsigned int buflength);
extern int uvc_free_buffers(struct uvc_video_queue *queue);
extern int uvc_query_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf);
extern int uvc_queue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf);
extern int uvc_dequeue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf, int nonblocking);
extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf);
extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
struct file *file, poll_table *wait);
extern int uvc_queue_mmap(struct uvc_video_queue *queue,
struct vm_area_struct *vma);
static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
{
return queue->flags & UVC_QUEUE_STREAMING;
}
extern struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue);
#endif /* __KERNEL__ */
#endif /* _UVC_QUEUE_H_ */

View file

@ -0,0 +1,374 @@
/*
* uvc_v4l2.c -- USB Video Class Gadget driver
*
* Copyright (C) 2009-2010
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/version.h>
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
#include "uvc.h"
#include "uvc_queue.h"
/* --------------------------------------------------------------------------
* Requests handling
*/
static int
uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
{
struct usb_composite_dev *cdev = uvc->func.config->cdev;
struct usb_request *req = uvc->control_req;
if (data->length < 0)
return usb_ep_set_halt(cdev->gadget->ep0);
req->length = min(uvc->event_length, data->length);
req->zero = data->length < uvc->event_length;
req->dma = DMA_ADDR_INVALID;
memcpy(req->buf, data->data, data->length);
return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
}
/* --------------------------------------------------------------------------
* V4L2
*/
struct uvc_format
{
u8 bpp;
u32 fcc;
};
static struct uvc_format uvc_formats[] = {
{ 16, V4L2_PIX_FMT_YUYV },
{ 0, V4L2_PIX_FMT_MJPEG },
};
static int
uvc_v4l2_get_format(struct uvc_video *video, struct v4l2_format *fmt)
{
fmt->fmt.pix.pixelformat = video->fcc;
fmt->fmt.pix.width = video->width;
fmt->fmt.pix.height = video->height;
fmt->fmt.pix.field = V4L2_FIELD_NONE;
fmt->fmt.pix.bytesperline = video->bpp * video->width / 8;
fmt->fmt.pix.sizeimage = video->imagesize;
fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
fmt->fmt.pix.priv = 0;
return 0;
}
static int
uvc_v4l2_set_format(struct uvc_video *video, struct v4l2_format *fmt)
{
struct uvc_format *format;
unsigned int imagesize;
unsigned int bpl;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(uvc_formats); ++i) {
format = &uvc_formats[i];
if (format->fcc == fmt->fmt.pix.pixelformat)
break;
}
if (format == NULL || format->fcc != fmt->fmt.pix.pixelformat) {
printk(KERN_INFO "Unsupported format 0x%08x.\n",
fmt->fmt.pix.pixelformat);
return -EINVAL;
}
bpl = format->bpp * fmt->fmt.pix.width / 8;
imagesize = bpl ? bpl * fmt->fmt.pix.height : fmt->fmt.pix.sizeimage;
video->fcc = format->fcc;
video->bpp = format->bpp;
video->width = fmt->fmt.pix.width;
video->height = fmt->fmt.pix.height;
video->imagesize = imagesize;
fmt->fmt.pix.field = V4L2_FIELD_NONE;
fmt->fmt.pix.bytesperline = bpl;
fmt->fmt.pix.sizeimage = imagesize;
fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
fmt->fmt.pix.priv = 0;
return 0;
}
static int
uvc_v4l2_open(struct file *file)
{
struct video_device *vdev = video_devdata(file);
struct uvc_device *uvc = video_get_drvdata(vdev);
struct uvc_file_handle *handle;
int ret;
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
if (handle == NULL)
return -ENOMEM;
ret = v4l2_fh_init(&handle->vfh, vdev);
if (ret < 0)
goto error;
ret = v4l2_event_init(&handle->vfh);
if (ret < 0)
goto error;
ret = v4l2_event_alloc(&handle->vfh, 8);
if (ret < 0)
goto error;
v4l2_fh_add(&handle->vfh);
handle->device = &uvc->video;
file->private_data = &handle->vfh;
uvc_function_connect(uvc);
return 0;
error:
v4l2_fh_exit(&handle->vfh);
return ret;
}
static int
uvc_v4l2_release(struct file *file)
{
struct video_device *vdev = video_devdata(file);
struct uvc_device *uvc = video_get_drvdata(vdev);
struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
struct uvc_video *video = handle->device;
uvc_function_disconnect(uvc);
uvc_video_enable(video, 0);
mutex_lock(&video->queue.mutex);
if (uvc_free_buffers(&video->queue) < 0)
printk(KERN_ERR "uvc_v4l2_release: Unable to free "
"buffers.\n");
mutex_unlock(&video->queue.mutex);
file->private_data = NULL;
v4l2_fh_del(&handle->vfh);
v4l2_fh_exit(&handle->vfh);
kfree(handle);
return 0;
}
static long
uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
struct uvc_device *uvc = video_get_drvdata(vdev);
struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
struct usb_composite_dev *cdev = uvc->func.config->cdev;
struct uvc_video *video = &uvc->video;
int ret = 0;
switch (cmd) {
/* Query capabilities */
case VIDIOC_QUERYCAP:
{
struct v4l2_capability *cap = arg;
memset(cap, 0, sizeof *cap);
strncpy(cap->driver, "g_uvc", sizeof(cap->driver));
strncpy(cap->card, cdev->gadget->name, sizeof(cap->card));
strncpy(cap->bus_info, dev_name(&cdev->gadget->dev),
sizeof cap->bus_info);
cap->version = DRIVER_VERSION_NUMBER;
cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
break;
}
/* Get & Set format */
case VIDIOC_G_FMT:
{
struct v4l2_format *fmt = arg;
if (fmt->type != video->queue.type)
return -EINVAL;
return uvc_v4l2_get_format(video, fmt);
}
case VIDIOC_S_FMT:
{
struct v4l2_format *fmt = arg;
if (fmt->type != video->queue.type)
return -EINVAL;
return uvc_v4l2_set_format(video, fmt);
}
/* Buffers & streaming */
case VIDIOC_REQBUFS:
{
struct v4l2_requestbuffers *rb = arg;
if (rb->type != video->queue.type ||
rb->memory != V4L2_MEMORY_MMAP)
return -EINVAL;
ret = uvc_alloc_buffers(&video->queue, rb->count,
video->imagesize);
if (ret < 0)
return ret;
rb->count = ret;
ret = 0;
break;
}
case VIDIOC_QUERYBUF:
{
struct v4l2_buffer *buf = arg;
if (buf->type != video->queue.type)
return -EINVAL;
return uvc_query_buffer(&video->queue, buf);
}
case VIDIOC_QBUF:
if ((ret = uvc_queue_buffer(&video->queue, arg)) < 0)
return ret;
return uvc_video_pump(video);
case VIDIOC_DQBUF:
return uvc_dequeue_buffer(&video->queue, arg,
file->f_flags & O_NONBLOCK);
case VIDIOC_STREAMON:
{
int *type = arg;
if (*type != video->queue.type)
return -EINVAL;
return uvc_video_enable(video, 1);
}
case VIDIOC_STREAMOFF:
{
int *type = arg;
if (*type != video->queue.type)
return -EINVAL;
return uvc_video_enable(video, 0);
}
/* Events */
case VIDIOC_DQEVENT:
{
struct v4l2_event *event = arg;
ret = v4l2_event_dequeue(&handle->vfh, event,
file->f_flags & O_NONBLOCK);
if (ret == 0 && event->type == UVC_EVENT_SETUP) {
struct uvc_event *uvc_event = (void *)&event->u.data;
/* Tell the complete callback to generate an event for
* the next request that will be enqueued by
* uvc_event_write.
*/
uvc->event_setup_out =
!(uvc_event->req.bRequestType & USB_DIR_IN);
uvc->event_length = uvc_event->req.wLength;
}
return ret;
}
case VIDIOC_SUBSCRIBE_EVENT:
{
struct v4l2_event_subscription *sub = arg;
if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST)
return -EINVAL;
return v4l2_event_subscribe(&handle->vfh, arg);
}
case VIDIOC_UNSUBSCRIBE_EVENT:
return v4l2_event_unsubscribe(&handle->vfh, arg);
case UVCIOC_SEND_RESPONSE:
ret = uvc_send_response(uvc, arg);
break;
default:
return -ENOIOCTLCMD;
}
return ret;
}
static long
uvc_v4l2_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl);
}
static int
uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
{
struct video_device *vdev = video_devdata(file);
struct uvc_device *uvc = video_get_drvdata(vdev);
return uvc_queue_mmap(&uvc->video.queue, vma);
}
static unsigned int
uvc_v4l2_poll(struct file *file, poll_table *wait)
{
struct video_device *vdev = video_devdata(file);
struct uvc_device *uvc = video_get_drvdata(vdev);
struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
unsigned int mask = 0;
poll_wait(file, &handle->vfh.events->wait, wait);
if (v4l2_event_pending(&handle->vfh))
mask |= POLLPRI;
mask |= uvc_queue_poll(&uvc->video.queue, file, wait);
return mask;
}
struct v4l2_file_operations uvc_v4l2_fops = {
.owner = THIS_MODULE,
.open = uvc_v4l2_open,
.release = uvc_v4l2_release,
.ioctl = uvc_v4l2_ioctl,
.mmap = uvc_v4l2_mmap,
.poll = uvc_v4l2_poll,
};

View file

@ -0,0 +1,386 @@
/*
* uvc_video.c -- USB Video Class Gadget driver
*
* Copyright (C) 2009-2010
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <media/v4l2-dev.h>
#include "uvc.h"
#include "uvc_queue.h"
/* --------------------------------------------------------------------------
* Video codecs
*/
static int
uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,
u8 *data, int len)
{
data[0] = 2;
data[1] = UVC_STREAM_EOH | video->fid;
if (buf->buf.bytesused - video->queue.buf_used <= len - 2)
data[1] |= UVC_STREAM_EOF;
return 2;
}
static int
uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf,
u8 *data, int len)
{
struct uvc_video_queue *queue = &video->queue;
unsigned int nbytes;
void *mem;
/* Copy video data to the USB buffer. */
mem = queue->mem + buf->buf.m.offset + queue->buf_used;
nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used);
memcpy(data, mem, nbytes);
queue->buf_used += nbytes;
return nbytes;
}
static void
uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
struct uvc_buffer *buf)
{
void *mem = req->buf;
int len = video->req_size;
int ret;
/* Add a header at the beginning of the payload. */
if (video->payload_size == 0) {
ret = uvc_video_encode_header(video, buf, mem, len);
video->payload_size += ret;
mem += ret;
len -= ret;
}
/* Process video data. */
len = min((int)(video->max_payload_size - video->payload_size), len);
ret = uvc_video_encode_data(video, buf, mem, len);
video->payload_size += ret;
len -= ret;
req->length = video->req_size - len;
req->zero = video->payload_size == video->max_payload_size;
if (buf->buf.bytesused == video->queue.buf_used) {
video->queue.buf_used = 0;
buf->state = UVC_BUF_STATE_DONE;
uvc_queue_next_buffer(&video->queue, buf);
video->fid ^= UVC_STREAM_FID;
video->payload_size = 0;
}
if (video->payload_size == video->max_payload_size ||
buf->buf.bytesused == video->queue.buf_used)
video->payload_size = 0;
}
static void
uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
struct uvc_buffer *buf)
{
void *mem = req->buf;
int len = video->req_size;
int ret;
/* Add the header. */
ret = uvc_video_encode_header(video, buf, mem, len);
mem += ret;
len -= ret;
/* Process video data. */
ret = uvc_video_encode_data(video, buf, mem, len);
len -= ret;
req->length = video->req_size - len;
if (buf->buf.bytesused == video->queue.buf_used) {
video->queue.buf_used = 0;
buf->state = UVC_BUF_STATE_DONE;
uvc_queue_next_buffer(&video->queue, buf);
video->fid ^= UVC_STREAM_FID;
}
}
/* --------------------------------------------------------------------------
* Request handling
*/
/*
* I somehow feel that synchronisation won't be easy to achieve here. We have
* three events that control USB requests submission:
*
* - USB request completion: the completion handler will resubmit the request
* if a video buffer is available.
*
* - USB interface setting selection: in response to a SET_INTERFACE request,
* the handler will start streaming if a video buffer is available and if
* video is not currently streaming.
*
* - V4L2 buffer queueing: the driver will start streaming if video is not
* currently streaming.
*
* Race conditions between those 3 events might lead to deadlocks or other
* nasty side effects.
*
* The "video currently streaming" condition can't be detected by the irqqueue
* being empty, as a request can still be in flight. A separate "queue paused"
* flag is thus needed.
*
* The paused flag will be set when we try to retrieve the irqqueue head if the
* queue is empty, and cleared when we queue a buffer.
*
* The USB request completion handler will get the buffer at the irqqueue head
* under protection of the queue spinlock. If the queue is empty, the streaming
* paused flag will be set. Right after releasing the spinlock a userspace
* application can queue a buffer. The flag will then cleared, and the ioctl
* handler will restart the video stream.
*/
static void
uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
{
struct uvc_video *video = req->context;
struct uvc_buffer *buf;
unsigned long flags;
int ret;
switch (req->status) {
case 0:
break;
case -ESHUTDOWN:
printk(KERN_INFO "VS request cancelled.\n");
goto requeue;
default:
printk(KERN_INFO "VS request completed with status %d.\n",
req->status);
goto requeue;
}
spin_lock_irqsave(&video->queue.irqlock, flags);
buf = uvc_queue_head(&video->queue);
if (buf == NULL) {
spin_unlock_irqrestore(&video->queue.irqlock, flags);
goto requeue;
}
video->encode(req, video, buf);
if ((ret = usb_ep_queue(ep, req, GFP_ATOMIC)) < 0) {
printk(KERN_INFO "Failed to queue request (%d).\n", ret);
usb_ep_set_halt(ep);
spin_unlock_irqrestore(&video->queue.irqlock, flags);
goto requeue;
}
spin_unlock_irqrestore(&video->queue.irqlock, flags);
return;
requeue:
spin_lock_irqsave(&video->req_lock, flags);
list_add_tail(&req->list, &video->req_free);
spin_unlock_irqrestore(&video->req_lock, flags);
}
static int
uvc_video_free_requests(struct uvc_video *video)
{
unsigned int i;
for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
if (video->req[i]) {
usb_ep_free_request(video->ep, video->req[i]);
video->req[i] = NULL;
}
if (video->req_buffer[i]) {
kfree(video->req_buffer[i]);
video->req_buffer[i] = NULL;
}
}
INIT_LIST_HEAD(&video->req_free);
video->req_size = 0;
return 0;
}
static int
uvc_video_alloc_requests(struct uvc_video *video)
{
unsigned int i;
int ret = -ENOMEM;
BUG_ON(video->req_size);
for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
video->req_buffer[i] = kmalloc(video->ep->maxpacket, GFP_KERNEL);
if (video->req_buffer[i] == NULL)
goto error;
video->req[i] = usb_ep_alloc_request(video->ep, GFP_KERNEL);
if (video->req[i] == NULL)
goto error;
video->req[i]->buf = video->req_buffer[i];
video->req[i]->length = 0;
video->req[i]->dma = DMA_ADDR_INVALID;
video->req[i]->complete = uvc_video_complete;
video->req[i]->context = video;
list_add_tail(&video->req[i]->list, &video->req_free);
}
video->req_size = video->ep->maxpacket;
return 0;
error:
uvc_video_free_requests(video);
return ret;
}
/* --------------------------------------------------------------------------
* Video streaming
*/
/*
* uvc_video_pump - Pump video data into the USB requests
*
* This function fills the available USB requests (listed in req_free) with
* video data from the queued buffers.
*/
int
uvc_video_pump(struct uvc_video *video)
{
struct usb_request *req;
struct uvc_buffer *buf;
unsigned long flags;
int ret;
/* FIXME TODO Race between uvc_video_pump and requests completion
* handler ???
*/
while (1) {
/* Retrieve the first available USB request, protected by the
* request lock.
*/
spin_lock_irqsave(&video->req_lock, flags);
if (list_empty(&video->req_free)) {
spin_unlock_irqrestore(&video->req_lock, flags);
return 0;
}
req = list_first_entry(&video->req_free, struct usb_request,
list);
list_del(&req->list);
spin_unlock_irqrestore(&video->req_lock, flags);
/* Retrieve the first available video buffer and fill the
* request, protected by the video queue irqlock.
*/
spin_lock_irqsave(&video->queue.irqlock, flags);
buf = uvc_queue_head(&video->queue);
if (buf == NULL) {
spin_unlock_irqrestore(&video->queue.irqlock, flags);
break;
}
video->encode(req, video, buf);
/* Queue the USB request */
if ((ret = usb_ep_queue(video->ep, req, GFP_KERNEL)) < 0) {
printk(KERN_INFO "Failed to queue request (%d)\n", ret);
usb_ep_set_halt(video->ep);
spin_unlock_irqrestore(&video->queue.irqlock, flags);
break;
}
spin_unlock_irqrestore(&video->queue.irqlock, flags);
}
spin_lock_irqsave(&video->req_lock, flags);
list_add_tail(&req->list, &video->req_free);
spin_unlock_irqrestore(&video->req_lock, flags);
return 0;
}
/*
* Enable or disable the video stream.
*/
int
uvc_video_enable(struct uvc_video *video, int enable)
{
unsigned int i;
int ret;
if (video->ep == NULL) {
printk(KERN_INFO "Video enable failed, device is "
"uninitialized.\n");
return -ENODEV;
}
if (!enable) {
for (i = 0; i < UVC_NUM_REQUESTS; ++i)
usb_ep_dequeue(video->ep, video->req[i]);
uvc_video_free_requests(video);
uvc_queue_enable(&video->queue, 0);
return 0;
}
if ((ret = uvc_queue_enable(&video->queue, 1)) < 0)
return ret;
if ((ret = uvc_video_alloc_requests(video)) < 0)
return ret;
if (video->max_payload_size) {
video->encode = uvc_video_encode_bulk;
video->payload_size = 0;
} else
video->encode = uvc_video_encode_isoc;
return uvc_video_pump(video);
}
/*
* Initialize the UVC video stream.
*/
int
uvc_video_init(struct uvc_video *video)
{
INIT_LIST_HEAD(&video->req_free);
spin_lock_init(&video->req_lock);
video->fcc = V4L2_PIX_FMT_YUYV;
video->bpp = 16;
video->width = 320;
video->height = 240;
video->imagesize = 320 * 240 * 2;
/* Initialize the video buffers queue. */
uvc_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT);
return 0;
}

399
drivers/usb/gadget/webcam.c Normal file
View file

@ -0,0 +1,399 @@
/*
* webcam.c -- USB webcam gadget driver
*
* Copyright (C) 2009-2010
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/usb/video.h>
#include "f_uvc.h"
/*
* Kbuild is not very cooperative with respect to linking separately
* compiled library objects into one module. So for now we won't use
* separate compilation ... ensuring init/exit sections work to shrink
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#include "composite.c"
#include "usbstring.c"
#include "config.c"
#include "epautoconf.c"
#include "f_uvc.c"
#include "uvc_queue.c"
#include "uvc_v4l2.c"
#include "uvc_video.c"
/* --------------------------------------------------------------------------
* Device descriptor
*/
#define WEBCAM_VENDOR_ID 0x1d6b /* Linux Foundation */
#define WEBCAM_PRODUCT_ID 0x0102 /* Webcam A/V gadget */
#define WEBCAM_DEVICE_BCD 0x0010 /* 0.10 */
static char webcam_vendor_label[] = "Linux Foundation";
static char webcam_product_label[] = "Webcam gadget";
static char webcam_config_label[] = "Video";
/* string IDs are assigned dynamically */
#define STRING_MANUFACTURER_IDX 0
#define STRING_PRODUCT_IDX 1
#define STRING_DESCRIPTION_IDX 2
static struct usb_string webcam_strings[] = {
[STRING_MANUFACTURER_IDX].s = webcam_vendor_label,
[STRING_PRODUCT_IDX].s = webcam_product_label,
[STRING_DESCRIPTION_IDX].s = webcam_config_label,
{ }
};
static struct usb_gadget_strings webcam_stringtab = {
.language = 0x0409, /* en-us */
.strings = webcam_strings,
};
static struct usb_gadget_strings *webcam_device_strings[] = {
&webcam_stringtab,
NULL,
};
static struct usb_device_descriptor webcam_device_descriptor = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_MISC,
.bDeviceSubClass = 0x02,
.bDeviceProtocol = 0x01,
.bMaxPacketSize0 = 0, /* dynamic */
.idVendor = cpu_to_le16(WEBCAM_VENDOR_ID),
.idProduct = cpu_to_le16(WEBCAM_PRODUCT_ID),
.bcdDevice = cpu_to_le16(WEBCAM_DEVICE_BCD),
.iManufacturer = 0, /* dynamic */
.iProduct = 0, /* dynamic */
.iSerialNumber = 0, /* dynamic */
.bNumConfigurations = 0, /* dynamic */
};
DECLARE_UVC_HEADER_DESCRIPTOR(1);
static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = {
.bLength = UVC_DT_HEADER_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_DT_HEADER,
.bcdUVC = cpu_to_le16(0x0100),
.wTotalLength = 0, /* dynamic */
.dwClockFrequency = cpu_to_le32(48000000),
.bInCollection = 0, /* dynamic */
.baInterfaceNr[0] = 0, /* dynamic */
};
static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = {
.bLength = UVC_DT_CAMERA_TERMINAL_SIZE(3),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_DT_INPUT_TERMINAL,
.bTerminalID = 1,
.wTerminalType = cpu_to_le16(0x0201),
.bAssocTerminal = 0,
.iTerminal = 0,
.wObjectiveFocalLengthMin = cpu_to_le16(0),
.wObjectiveFocalLengthMax = cpu_to_le16(0),
.wOcularFocalLength = cpu_to_le16(0),
.bControlSize = 3,
.bmControls[0] = 2,
.bmControls[1] = 0,
.bmControls[2] = 0,
};
static const struct uvc_processing_unit_descriptor uvc_processing = {
.bLength = UVC_DT_PROCESSING_UNIT_SIZE(2),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_DT_PROCESSING_UNIT,
.bUnitID = 2,
.bSourceID = 1,
.wMaxMultiplier = cpu_to_le16(16*1024),
.bControlSize = 2,
.bmControls[0] = 1,
.bmControls[1] = 0,
.iProcessing = 0,
};
static const struct uvc_output_terminal_descriptor uvc_output_terminal = {
.bLength = UVC_DT_OUTPUT_TERMINAL_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_DT_OUTPUT_TERMINAL,
.bTerminalID = 3,
.wTerminalType = cpu_to_le16(0x0101),
.bAssocTerminal = 0,
.bSourceID = 2,
.iTerminal = 0,
};
DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2);
static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header = {
.bLength = UVC_DT_INPUT_HEADER_SIZE(1, 2),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_DT_INPUT_HEADER,
.bNumFormats = 2,
.wTotalLength = 0, /* dynamic */
.bEndpointAddress = 0, /* dynamic */
.bmInfo = 0,
.bTerminalLink = 3,
.bStillCaptureMethod = 0,
.bTriggerSupport = 0,
.bTriggerUsage = 0,
.bControlSize = 1,
.bmaControls[0][0] = 0,
.bmaControls[1][0] = 4,
};
static const struct uvc_format_uncompressed uvc_format_yuv = {
.bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_DT_FORMAT_UNCOMPRESSED,
.bFormatIndex = 1,
.bNumFrameDescriptors = 2,
.guidFormat =
{ 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
.bBitsPerPixel = 16,
.bDefaultFrameIndex = 1,
.bAspectRatioX = 0,
.bAspectRatioY = 0,
.bmInterfaceFlags = 0,
.bCopyProtect = 0,
};
DECLARE_UVC_FRAME_UNCOMPRESSED(1);
DECLARE_UVC_FRAME_UNCOMPRESSED(3);
static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = {
.bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_DT_FRAME_UNCOMPRESSED,
.bFrameIndex = 1,
.bmCapabilities = 0,
.wWidth = cpu_to_le16(640),
.wHeight = cpu_to_le16(360),
.dwMinBitRate = cpu_to_le32(18432000),
.dwMaxBitRate = cpu_to_le32(55296000),
.dwMaxVideoFrameBufferSize = cpu_to_le32(460800),
.dwDefaultFrameInterval = cpu_to_le32(666666),
.bFrameIntervalType = 3,
.dwFrameInterval[0] = cpu_to_le32(666666),
.dwFrameInterval[1] = cpu_to_le32(1000000),
.dwFrameInterval[2] = cpu_to_le32(5000000),
};
static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = {
.bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_DT_FRAME_UNCOMPRESSED,
.bFrameIndex = 2,
.bmCapabilities = 0,
.wWidth = cpu_to_le16(1280),
.wHeight = cpu_to_le16(720),
.dwMinBitRate = cpu_to_le32(29491200),
.dwMaxBitRate = cpu_to_le32(29491200),
.dwMaxVideoFrameBufferSize = cpu_to_le32(1843200),
.dwDefaultFrameInterval = cpu_to_le32(5000000),
.bFrameIntervalType = 1,
.dwFrameInterval[0] = cpu_to_le32(5000000),
};
static const struct uvc_format_mjpeg uvc_format_mjpg = {
.bLength = UVC_DT_FORMAT_MJPEG_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_DT_FORMAT_MJPEG,
.bFormatIndex = 2,
.bNumFrameDescriptors = 2,
.bmFlags = 0,
.bDefaultFrameIndex = 1,
.bAspectRatioX = 0,
.bAspectRatioY = 0,
.bmInterfaceFlags = 0,
.bCopyProtect = 0,
};
DECLARE_UVC_FRAME_MJPEG(1);
DECLARE_UVC_FRAME_MJPEG(3);
static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = {
.bLength = UVC_DT_FRAME_MJPEG_SIZE(3),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_DT_FRAME_MJPEG,
.bFrameIndex = 1,
.bmCapabilities = 0,
.wWidth = cpu_to_le16(640),
.wHeight = cpu_to_le16(360),
.dwMinBitRate = cpu_to_le32(18432000),
.dwMaxBitRate = cpu_to_le32(55296000),
.dwMaxVideoFrameBufferSize = cpu_to_le32(460800),
.dwDefaultFrameInterval = cpu_to_le32(666666),
.bFrameIntervalType = 3,
.dwFrameInterval[0] = cpu_to_le32(666666),
.dwFrameInterval[1] = cpu_to_le32(1000000),
.dwFrameInterval[2] = cpu_to_le32(5000000),
};
static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = {
.bLength = UVC_DT_FRAME_MJPEG_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_DT_FRAME_MJPEG,
.bFrameIndex = 2,
.bmCapabilities = 0,
.wWidth = cpu_to_le16(1280),
.wHeight = cpu_to_le16(720),
.dwMinBitRate = cpu_to_le32(29491200),
.dwMaxBitRate = cpu_to_le32(29491200),
.dwMaxVideoFrameBufferSize = cpu_to_le32(1843200),
.dwDefaultFrameInterval = cpu_to_le32(5000000),
.bFrameIntervalType = 1,
.dwFrameInterval[0] = cpu_to_le32(5000000),
};
static const struct uvc_color_matching_descriptor uvc_color_matching = {
.bLength = UVC_DT_COLOR_MATCHING_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_DT_COLOR_MATCHING,
.bColorPrimaries = 1,
.bTransferCharacteristics = 1,
.bMatrixCoefficients = 4,
};
static const struct uvc_descriptor_header * const uvc_control_cls[] = {
(const struct uvc_descriptor_header *) &uvc_control_header,
(const struct uvc_descriptor_header *) &uvc_camera_terminal,
(const struct uvc_descriptor_header *) &uvc_processing,
(const struct uvc_descriptor_header *) &uvc_output_terminal,
NULL,
};
static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = {
(const struct uvc_descriptor_header *) &uvc_input_header,
(const struct uvc_descriptor_header *) &uvc_format_yuv,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
(const struct uvc_descriptor_header *) &uvc_format_mjpg,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
(const struct uvc_descriptor_header *) &uvc_color_matching,
NULL,
};
static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = {
(const struct uvc_descriptor_header *) &uvc_input_header,
(const struct uvc_descriptor_header *) &uvc_format_yuv,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
(const struct uvc_descriptor_header *) &uvc_format_mjpg,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
(const struct uvc_descriptor_header *) &uvc_color_matching,
NULL,
};
/* --------------------------------------------------------------------------
* USB configuration
*/
static int __init
webcam_config_bind(struct usb_configuration *c)
{
return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls,
uvc_hs_streaming_cls);
}
static struct usb_configuration webcam_config_driver = {
.label = webcam_config_label,
.bind = webcam_config_bind,
.bConfigurationValue = 1,
.iConfiguration = 0, /* dynamic */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
.bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2,
};
static int /* __init_or_exit */
webcam_unbind(struct usb_composite_dev *cdev)
{
return 0;
}
static int __init
webcam_bind(struct usb_composite_dev *cdev)
{
int ret;
/* Allocate string descriptor numbers ... note that string contents
* can be overridden by the composite_dev glue.
*/
if ((ret = usb_string_id(cdev)) < 0)
goto error;
webcam_strings[STRING_MANUFACTURER_IDX].id = ret;
webcam_device_descriptor.iManufacturer = ret;
if ((ret = usb_string_id(cdev)) < 0)
goto error;
webcam_strings[STRING_PRODUCT_IDX].id = ret;
webcam_device_descriptor.iProduct = ret;
if ((ret = usb_string_id(cdev)) < 0)
goto error;
webcam_strings[STRING_DESCRIPTION_IDX].id = ret;
webcam_config_driver.iConfiguration = ret;
/* Register our configuration. */
if ((ret = usb_add_config(cdev, &webcam_config_driver)) < 0)
goto error;
INFO(cdev, "Webcam Video Gadget\n");
return 0;
error:
webcam_unbind(cdev);
return ret;
}
/* --------------------------------------------------------------------------
* Driver
*/
static struct usb_composite_driver webcam_driver = {
.name = "g_webcam",
.dev = &webcam_device_descriptor,
.strings = webcam_device_strings,
.bind = webcam_bind,
.unbind = webcam_unbind,
};
static int __init
webcam_init(void)
{
return usb_composite_register(&webcam_driver);
}
static void __exit
webcam_cleanup(void)
{
usb_composite_unregister(&webcam_driver);
}
module_init(webcam_init);
module_exit(webcam_cleanup);
MODULE_AUTHOR("Laurent Pinchart");
MODULE_DESCRIPTION("Webcam Video Gadget");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1.0");

View file

@ -207,6 +207,21 @@ config USB_OHCI_HCD
To compile this driver as a module, choose M here: the
module will be called ohci-hcd.
config USB_OHCI_HCD_OMAP1
bool "OHCI support for OMAP1/2 chips"
depends on USB_OHCI_HCD && (ARCH_OMAP1 || ARCH_OMAP2)
default y
---help---
Enables support for the OHCI controller on OMAP1/2 chips.
config USB_OHCI_HCD_OMAP3
bool "OHCI support for OMAP3 and later chips"
depends on USB_OHCI_HCD && (ARCH_OMAP3 || ARCH_OMAP4)
default y
---help---
Enables support for the on-chip OHCI controller on
OMAP3 and later chips.
config USB_OHCI_HCD_PPC_SOC
bool "OHCI support for on-chip PPC USB controller"
depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx)

View file

@ -69,6 +69,15 @@ static void au1xxx_stop_ehc(void)
au_sync();
}
static int au1xxx_ehci_setup(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
int ret = ehci_init(hcd);
ehci->need_io_watchdog = 0;
return ret;
}
static const struct hc_driver ehci_au1xxx_hc_driver = {
.description = hcd_name,
.product_desc = "Au1xxx EHCI",
@ -86,7 +95,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
* FIXME -- ehci_init() doesn't do enough here.
* See ehci-ppc-soc for a complete implementation.
*/
.reset = ehci_init,
.reset = au1xxx_ehci_setup,
.start = ehci_run,
.stop = ehci_stop,
.shutdown = ehci_shutdown,
@ -215,26 +224,17 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
msleep(10);
/* Root hub was already suspended. Disable irq emission and
* mark HW unaccessible, bail out if RH has been resumed. Use
* the spinlock to properly synchronize with possible pending
* RH suspend or resume activity.
*
* This is still racy as hcd->state is manipulated outside of
* any locks =P But that will be a different fix.
* mark HW unaccessible. The PM and USB cores make sure that
* the root hub is either suspended or stopped.
*/
spin_lock_irqsave(&ehci->lock, flags);
if (hcd->state != HC_STATE_SUSPENDED) {
rc = -EINVAL;
goto bail;
}
ehci_prepare_ports_for_controller_suspend(ehci);
ehci_writel(ehci, 0, &ehci->regs->intr_enable);
(void)ehci_readl(ehci, &ehci->regs->intr_enable);
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
au1xxx_stop_ehc();
bail:
spin_unlock_irqrestore(&ehci->lock, flags);
// could save FLADJ in case of Vaux power loss
@ -264,6 +264,7 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
int mask = INTR_MASK;
ehci_prepare_ports_for_controller_resume(ehci);
if (!hcd->self.root_hub->do_remote_wakeup)
mask &= ~STS_PCD;
ehci_writel(ehci, mask, &ehci->regs->intr_enable);

View file

@ -313,6 +313,7 @@ static int ehci_fsl_drv_suspend(struct device *dev)
struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
void __iomem *non_ehci = hcd->regs;
ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd));
if (!fsl_deep_sleep())
return 0;
@ -327,6 +328,7 @@ static int ehci_fsl_drv_resume(struct device *dev)
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
void __iomem *non_ehci = hcd->regs;
ehci_prepare_ports_for_controller_resume(ehci);
if (!fsl_deep_sleep())
return 0;

View file

@ -31,13 +31,12 @@
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/moduleparam.h>
#include <linux/dma-mapping.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
#include "../core/hcd.h"
#include <asm/byteorder.h>
#include <asm/io.h>
#include <asm/irq.h>

View file

@ -106,12 +106,75 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
ehci->owned_ports = 0;
}
static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
bool suspending)
{
int port;
u32 temp;
/* If remote wakeup is enabled for the root hub but disabled
* for the controller, we must adjust all the port wakeup flags
* when the controller is suspended or resumed. In all other
* cases they don't need to be changed.
*/
if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup ||
device_may_wakeup(ehci_to_hcd(ehci)->self.controller))
return;
/* clear phy low-power mode before changing wakeup flags */
if (ehci->has_hostpc) {
port = HCS_N_PORTS(ehci->hcs_params);
while (port--) {
u32 __iomem *hostpc_reg;
hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
+ HOSTPC0 + 4 * port);
temp = ehci_readl(ehci, hostpc_reg);
ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg);
}
msleep(5);
}
port = HCS_N_PORTS(ehci->hcs_params);
while (port--) {
u32 __iomem *reg = &ehci->regs->port_status[port];
u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
u32 t2 = t1 & ~PORT_WAKE_BITS;
/* If we are suspending the controller, clear the flags.
* If we are resuming the controller, set the wakeup flags.
*/
if (!suspending) {
if (t1 & PORT_CONNECT)
t2 |= PORT_WKOC_E | PORT_WKDISC_E;
else
t2 |= PORT_WKOC_E | PORT_WKCONN_E;
}
ehci_vdbg(ehci, "port %d, %08x -> %08x\n",
port + 1, t1, t2);
ehci_writel(ehci, t2, reg);
}
/* enter phy low-power mode again */
if (ehci->has_hostpc) {
port = HCS_N_PORTS(ehci->hcs_params);
while (port--) {
u32 __iomem *hostpc_reg;
hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
+ HOSTPC0 + 4 * port);
temp = ehci_readl(ehci, hostpc_reg);
ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
}
}
}
static int ehci_bus_suspend (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
int port;
int mask;
u32 __iomem *hostpc_reg = NULL;
int changed;
ehci_dbg(ehci, "suspend root hub\n");
@ -155,15 +218,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
*/
ehci->bus_suspended = 0;
ehci->owned_ports = 0;
changed = 0;
port = HCS_N_PORTS(ehci->hcs_params);
while (port--) {
u32 __iomem *reg = &ehci->regs->port_status [port];
u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
u32 t2 = t1;
u32 t2 = t1 & ~PORT_WAKE_BITS;
if (ehci->has_hostpc)
hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs
+ HOSTPC0 + 4 * (port & 0xff));
/* keep track of which ports we suspend */
if (t1 & PORT_OWNER)
set_bit(port, &ehci->owned_ports);
@ -172,40 +233,45 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
set_bit(port, &ehci->bus_suspended);
}
/* enable remote wakeup on all ports */
/* enable remote wakeup on all ports, if told to do so */
if (hcd->self.root_hub->do_remote_wakeup) {
/* only enable appropriate wake bits, otherwise the
* hardware can not go phy low power mode. If a race
* condition happens here(connection change during bits
* set), the port change detection will finally fix it.
*/
if (t1 & PORT_CONNECT) {
if (t1 & PORT_CONNECT)
t2 |= PORT_WKOC_E | PORT_WKDISC_E;
t2 &= ~PORT_WKCONN_E;
} else {
else
t2 |= PORT_WKOC_E | PORT_WKCONN_E;
t2 &= ~PORT_WKDISC_E;
}
} else
t2 &= ~PORT_WAKE_BITS;
}
if (t1 != t2) {
ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
port + 1, t1, t2);
ehci_writel(ehci, t2, reg);
if (hostpc_reg) {
u32 t3;
changed = 1;
}
}
spin_unlock_irq(&ehci->lock);
msleep(5);/* 5ms for HCD enter low pwr mode */
spin_lock_irq(&ehci->lock);
t3 = ehci_readl(ehci, hostpc_reg);
ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg);
t3 = ehci_readl(ehci, hostpc_reg);
ehci_dbg(ehci, "Port%d phy low pwr mode %s\n",
if (changed && ehci->has_hostpc) {
spin_unlock_irq(&ehci->lock);
msleep(5); /* 5 ms for HCD to enter low-power mode */
spin_lock_irq(&ehci->lock);
port = HCS_N_PORTS(ehci->hcs_params);
while (port--) {
u32 __iomem *hostpc_reg;
u32 t3;
hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
+ HOSTPC0 + 4 * port);
t3 = ehci_readl(ehci, hostpc_reg);
ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg);
t3 = ehci_readl(ehci, hostpc_reg);
ehci_dbg(ehci, "Port %d phy low-power mode %s\n",
port, (t3 & HOSTPC_PHCD) ?
"succeeded" : "failed");
}
}
}
@ -291,6 +357,25 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
msleep(8);
spin_lock_irq(&ehci->lock);
/* clear phy low-power mode before resume */
if (ehci->bus_suspended && ehci->has_hostpc) {
i = HCS_N_PORTS(ehci->hcs_params);
while (i--) {
if (test_bit(i, &ehci->bus_suspended)) {
u32 __iomem *hostpc_reg;
hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
+ HOSTPC0 + 4 * i);
temp = ehci_readl(ehci, hostpc_reg);
ehci_writel(ehci, temp & ~HOSTPC_PHCD,
hostpc_reg);
}
}
spin_unlock_irq(&ehci->lock);
msleep(5);
spin_lock_irq(&ehci->lock);
}
/* manually resume the ports we suspended during bus_suspend() */
i = HCS_N_PORTS (ehci->hcs_params);
while (i--) {
@ -659,7 +744,7 @@ static int ehci_hub_control (
* Even if OWNER is set, so the port is owned by the
* companion controller, khubd needs to be able to clear
* the port-change status bits (especially
* USB_PORT_FEAT_C_CONNECTION).
* USB_PORT_STAT_C_CONNECTION).
*/
switch (wValue) {
@ -675,16 +760,25 @@ static int ehci_hub_control (
goto error;
if (ehci->no_selective_suspend)
break;
if (temp & PORT_SUSPEND) {
if ((temp & PORT_PE) == 0)
goto error;
/* resume signaling for 20 msec */
temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
ehci_writel(ehci, temp | PORT_RESUME,
status_reg);
ehci->reset_done [wIndex] = jiffies
+ msecs_to_jiffies (20);
if (!(temp & PORT_SUSPEND))
break;
if ((temp & PORT_PE) == 0)
goto error;
/* clear phy low-power mode before resume */
if (hostpc_reg) {
temp1 = ehci_readl(ehci, hostpc_reg);
ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
hostpc_reg);
spin_unlock_irqrestore(&ehci->lock, flags);
msleep(5);/* wait to leave low-power mode */
spin_lock_irqsave(&ehci->lock, flags);
}
/* resume signaling for 20 msec */
temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
ehci_writel(ehci, temp | PORT_RESUME, status_reg);
ehci->reset_done[wIndex] = jiffies
+ msecs_to_jiffies(20);
break;
case USB_PORT_FEAT_C_SUSPEND:
clear_bit(wIndex, &ehci->port_c_suspend);
@ -729,12 +823,12 @@ static int ehci_hub_control (
// wPortChange bits
if (temp & PORT_CSC)
status |= 1 << USB_PORT_FEAT_C_CONNECTION;
status |= USB_PORT_STAT_C_CONNECTION << 16;
if (temp & PORT_PEC)
status |= 1 << USB_PORT_FEAT_C_ENABLE;
status |= USB_PORT_STAT_C_ENABLE << 16;
if ((temp & PORT_OCC) && !ignore_oc){
status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
/*
* Hubs should disable port power on over-current.
@ -791,7 +885,7 @@ static int ehci_hub_control (
if ((temp & PORT_RESET)
&& time_after_eq(jiffies,
ehci->reset_done[wIndex])) {
status |= 1 << USB_PORT_FEAT_C_RESET;
status |= USB_PORT_STAT_C_RESET << 16;
ehci->reset_done [wIndex] = 0;
/* force reset to complete */
@ -833,7 +927,7 @@ static int ehci_hub_control (
*/
if (temp & PORT_CONNECT) {
status |= 1 << USB_PORT_FEAT_CONNECTION;
status |= USB_PORT_STAT_CONNECTION;
// status may be from integrated TT
if (ehci->has_hostpc) {
temp1 = ehci_readl(ehci, hostpc_reg);
@ -842,11 +936,11 @@ static int ehci_hub_control (
status |= ehci_port_speed(ehci, temp);
}
if (temp & PORT_PE)
status |= 1 << USB_PORT_FEAT_ENABLE;
status |= USB_PORT_STAT_ENABLE;
/* maybe the port was unsuspended without our knowledge */
if (temp & (PORT_SUSPEND|PORT_RESUME)) {
status |= 1 << USB_PORT_FEAT_SUSPEND;
status |= USB_PORT_STAT_SUSPEND;
} else if (test_bit(wIndex, &ehci->suspended_ports)) {
clear_bit(wIndex, &ehci->suspended_ports);
ehci->reset_done[wIndex] = 0;
@ -855,13 +949,13 @@ static int ehci_hub_control (
}
if (temp & PORT_OC)
status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
status |= USB_PORT_STAT_OVERCURRENT;
if (temp & PORT_RESET)
status |= 1 << USB_PORT_FEAT_RESET;
status |= USB_PORT_STAT_RESET;
if (temp & PORT_POWER)
status |= 1 << USB_PORT_FEAT_POWER;
status |= USB_PORT_STAT_POWER;
if (test_bit(wIndex, &ehci->port_c_suspend))
status |= 1 << USB_PORT_FEAT_C_SUSPEND;
status |= USB_PORT_STAT_C_SUSPEND << 16;
#ifndef VERBOSE_DEBUG
if (status & ~0xffff) /* only if wPortChange is interesting */

View file

@ -116,6 +116,8 @@
#define OMAP_UHH_DEBUG_CSR (0x44)
/* EHCI Register Set */
#define EHCI_INSNREG04 (0xA0)
#define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5)
#define EHCI_INSNREG05_ULPI (0xA4)
#define EHCI_INSNREG05_ULPI_CONTROL_SHIFT 31
#define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT 24
@ -352,8 +354,8 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
/* Bypass the TLL module for PHY mode operation */
if (omap_rev() <= OMAP3430_REV_ES2_1) {
dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1 \n");
if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) {
dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n");
if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) ||
(omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) ||
(omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY))
@ -382,6 +384,18 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
/*
* An undocumented "feature" in the OMAP3 EHCI controller,
* causes suspended ports to be taken out of suspend when
* the USBCMD.Run/Stop bit is cleared (for example when
* we do ehci_bus_suspend).
* This breaks suspend-resume if the root-hub is allowed
* to suspend. Writing 1 to this undocumented register bit
* disables this feature and restores normal behavior.
*/
ehci_omap_writel(omap->ehci_base, EHCI_INSNREG04,
EHCI_INSNREG04_DISABLE_UNSUSPEND);
if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ||
(omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ||
(omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) {
@ -659,6 +673,9 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
goto err_add_hcd;
}
/* root ports should always stay powered */
ehci_port_power(omap->ehci, 1);
return 0;
err_add_hcd:

View file

@ -109,6 +109,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
return retval;
switch (pdev->vendor) {
case PCI_VENDOR_ID_NEC:
ehci->need_io_watchdog = 0;
break;
case PCI_VENDOR_ID_INTEL:
ehci->need_io_watchdog = 0;
if (pdev->device == 0x27cc) {
@ -284,23 +287,15 @@ static int ehci_pci_suspend(struct usb_hcd *hcd)
msleep(10);
/* Root hub was already suspended. Disable irq emission and
* mark HW unaccessible, bail out if RH has been resumed. Use
* the spinlock to properly synchronize with possible pending
* RH suspend or resume activity.
*
* This is still racy as hcd->state is manipulated outside of
* any locks =P But that will be a different fix.
* mark HW unaccessible. The PM and USB cores make sure that
* the root hub is either suspended or stopped.
*/
spin_lock_irqsave (&ehci->lock, flags);
if (hcd->state != HC_STATE_SUSPENDED) {
rc = -EINVAL;
goto bail;
}
ehci_prepare_ports_for_controller_suspend(ehci);
ehci_writel(ehci, 0, &ehci->regs->intr_enable);
(void)ehci_readl(ehci, &ehci->regs->intr_enable);
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
bail:
spin_unlock_irqrestore (&ehci->lock, flags);
// could save FLADJ in case of Vaux power loss
@ -330,6 +325,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
!hibernated) {
int mask = INTR_MASK;
ehci_prepare_ports_for_controller_resume(ehci);
if (!hcd->self.root_hub->do_remote_wakeup)
mask &= ~STS_PCD;
ehci_writel(ehci, mask, &ehci->regs->intr_enable);

View file

@ -663,7 +663,7 @@ qh_urb_transaction (
*/
i = urb->num_sgs;
if (len > 0 && i > 0) {
sg = urb->sg->sg;
sg = urb->sg;
buf = sg_dma_address(sg);
/* urb->transfer_buffer_length may be smaller than the

Some files were not shown because too many files have changed in this diff Show more