diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 15:05:02 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 15:05:02 -0700 |
commit | 9895850b23886e030cd1e7241d5529a57e969c3d (patch) | |
tree | 1061626db450aeb72dcfcd247c24b33e5238c8c4 /drivers/usb/gadget/composite.c | |
parent | fc385c313275b114bc6ad36e60c5177d63250548 (diff) | |
parent | b58af4066d240b18b43f202e07b9ec7461d90b17 (diff) |
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: (148 commits)
USB: serial: fix stalled writes
USB: remove fake "address-of" expressions
USB: fix thread-unsafe anchor utiliy routines
USB: usbtest: support test device with only one iso-in or iso-out endpoint
USB: usbtest: avoid to free coherent buffer in atomic context
USB: xhci: Set DMA mask for host.
USB: xhci: Don't flush doorbell writes.
USB: xhci: Reduce reads and writes of interrupter registers.
USB: xhci: Make xhci_set_hc_event_deq() static.
USB: xhci: Minimize HW event ring dequeue pointer writes.
USB: xhci: Make xhci_handle_event() static.
USB: xhci: Remove unnecessary reads of IRQ_PENDING register.
USB: xhci: Performance - move xhci_work() into xhci_irq()
USB: xhci: Performance - move interrupt handlers into xhci-ring.c
USB: xhci: Performance - move functions that find ep ring.
USB:: fix linux/usb.h kernel-doc warnings
USB: add USB serial ssu100 driver
USB: usb-storage: implement autosuspend
USB: ehci: fix remove of ehci debugfs dir
USB: Add USB 2.0 to ssb ohci driver
...
Diffstat (limited to 'drivers/usb/gadget/composite.c')
-rw-r--r-- | drivers/usb/gadget/composite.c | 73 |
1 files changed, 69 insertions, 4 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 391d169f8d0..e483f80822d 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -673,20 +673,83 @@ static int get_string(struct usb_composite_dev *cdev, * string IDs. Drivers for functions, configurations, or gadgets will * then store that ID in the appropriate descriptors and string table. * - * All string identifier should be allocated using this routine, to - * ensure that for example different functions don't wrongly assign - * different meanings to the same identifier. + * All string identifier should be allocated using this, + * @usb_string_ids_tab() or @usb_string_ids_n() routine, to ensure + * that for example different functions don't wrongly assign different + * meanings to the same identifier. */ int usb_string_id(struct usb_composite_dev *cdev) { if (cdev->next_string_id < 254) { - /* string id 0 is reserved */ + /* string id 0 is reserved by USB spec for list of + * supported languages */ + /* 255 reserved as well? -- mina86 */ cdev->next_string_id++; return cdev->next_string_id; } return -ENODEV; } +/** + * usb_string_ids() - allocate unused string IDs in batch + * @cdev: the device whose string descriptor IDs are being allocated + * @str: an array of usb_string objects to assign numbers to + * Context: single threaded during gadget setup + * + * @usb_string_ids() is called from bind() callbacks to allocate + * string IDs. Drivers for functions, configurations, or gadgets will + * then copy IDs from the string table to the appropriate descriptors + * and string table for other languages. + * + * All string identifier should be allocated using this, + * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for + * example different functions don't wrongly assign different meanings + * to the same identifier. + */ +int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str) +{ + int next = cdev->next_string_id; + + for (; str->s; ++str) { + if (unlikely(next >= 254)) + return -ENODEV; + str->id = ++next; + } + + cdev->next_string_id = next; + + return 0; +} + +/** + * usb_string_ids_n() - allocate unused string IDs in batch + * @cdev: the device whose string descriptor IDs are being allocated + * @n: number of string IDs to allocate + * Context: single threaded during gadget setup + * + * Returns the first requested ID. This ID and next @n-1 IDs are now + * valid IDs. At least providind that @n is non zore because if it + * is, returns last requested ID which is now very useful information. + * + * @usb_string_ids_n() is called from bind() callbacks to allocate + * string IDs. Drivers for functions, configurations, or gadgets will + * then store that ID in the appropriate descriptors and string table. + * + * All string identifier should be allocated using this, + * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for + * example different functions don't wrongly assign different meanings + * to the same identifier. + */ +int usb_string_ids_n(struct usb_composite_dev *c, unsigned n) +{ + unsigned next = c->next_string_id; + if (unlikely(n > 254 || (unsigned)next + n > 254)) + return -ENODEV; + c->next_string_id += n; + return next + 1; +} + + /*-------------------------------------------------------------------------*/ static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req) @@ -893,6 +956,8 @@ static void composite_disconnect(struct usb_gadget *gadget) spin_lock_irqsave(&cdev->lock, flags); if (cdev->config) reset_config(cdev); + if (composite->disconnect) + composite->disconnect(cdev); spin_unlock_irqrestore(&cdev->lock, flags); } |