Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 213544
b: refs/heads/master
c: ad1a810
h: refs/heads/master
v: v3
  • Loading branch information
Michal Nazarewicz authored and Greg Kroah-Hartman committed Oct 22, 2010
1 parent 55be852 commit adfb693
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 33 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fc19de61ef5c17b6e19766052c6ac85cf31de876
refs/heads/master: ad1a8102f957f4d25fc58cdc10736c5ade7557e1
96 changes: 64 additions & 32 deletions trunk/drivers/usb/gadget/composite.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/utsname.h>

#include <linux/usb/composite.h>

Expand Down Expand Up @@ -69,6 +70,8 @@ static char *iSerialNumber;
module_param(iSerialNumber, charp, 0);
MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");

static char composite_manufacturer[50];

/*-------------------------------------------------------------------------*/

/**
Expand Down Expand Up @@ -599,6 +602,7 @@ static int get_string(struct usb_composite_dev *cdev,
struct usb_configuration *c;
struct usb_function *f;
int len;
const char *str;

/* Yes, not only is USB's I18N support probably more than most
* folk will ever care about ... also, it's all supported here.
Expand Down Expand Up @@ -638,9 +642,29 @@ static int get_string(struct usb_composite_dev *cdev,
return s->bLength;
}

/* Otherwise, look up and return a specified string. String IDs
* are device-scoped, so we look up each string table we're told
* about. These lookups are infrequent; simpler-is-better here.
/* Otherwise, look up and return a specified string. First
* check if the string has not been overridden.
*/
if (cdev->manufacturer_override == id)
str = iManufacturer ?: composite->iManufacturer ?:
composite_manufacturer;
else if (cdev->product_override == id)
str = iProduct ?: composite->iProduct;
else if (cdev->serial_override == id)
str = iSerialNumber;
else
str = NULL;
if (str) {
struct usb_gadget_strings strings = {
.language = language,
.strings = &(struct usb_string) { 0xff, str }
};
return usb_gadget_get_string(&strings, 0xff, buf);
}

/* String IDs are device-scoped, so we look up each string
* table we're told about. These lookups are infrequent;
* simpler-is-better here.
*/
if (composite->strings) {
len = lookup_string(composite->strings, buf, language, id);
Expand Down Expand Up @@ -1025,26 +1049,17 @@ composite_unbind(struct usb_gadget *gadget)
composite = NULL;
}

static void
string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s)
static u8 override_id(struct usb_composite_dev *cdev, u8 *desc)
{
struct usb_string *str = tab->strings;

for (str = tab->strings; str->s; str++) {
if (str->id == id) {
str->s = s;
return;
}
if (!*desc) {
int ret = usb_string_id(cdev);
if (unlikely(ret < 0))
WARNING(cdev, "failed to override string ID\n");
else
*desc = ret;
}
}

static void
string_override(struct usb_gadget_strings **tab, u8 id, const char *s)
{
while (*tab) {
string_override_one(*tab, id, s);
tab++;
}
return *desc;
}

static int composite_bind(struct usb_gadget *gadget)
Expand Down Expand Up @@ -1107,19 +1122,34 @@ static int composite_bind(struct usb_gadget *gadget)
cdev->desc = *composite->dev;
cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;

/* strings can't be assigned before bind() allocates the
* releavnt identifiers
*/
if (cdev->desc.iManufacturer && iManufacturer)
string_override(composite->strings,
cdev->desc.iManufacturer, iManufacturer);
if (cdev->desc.iProduct && iProduct)
string_override(composite->strings,
cdev->desc.iProduct, iProduct);
if (cdev->desc.iSerialNumber && iSerialNumber)
string_override(composite->strings,
cdev->desc.iSerialNumber, iSerialNumber);
/* stirng overrides */
if (iManufacturer || !cdev->desc.iManufacturer) {
if (!iManufacturer && !composite->iManufacturer &&
!*composite_manufacturer)
snprintf(composite_manufacturer,
sizeof composite_manufacturer,
"%s %s with %s",
init_utsname()->sysname,
init_utsname()->release,
gadget->name);

cdev->manufacturer_override =
override_id(cdev, &cdev->desc.iManufacturer);
}

if (iProduct || (!cdev->desc.iProduct && composite->iProduct))
cdev->product_override =
override_id(cdev, &cdev->desc.iProduct);

if (iSerialNumber)
cdev->serial_override =
override_id(cdev, &cdev->desc.iSerialNumber);

/* has userspace failed to provide a serial number? */
if (composite->needs_serial && !cdev->desc.iSerialNumber)
WARNING(cdev, "userspace failed to provide iSerialNumber\n");

/* finish up */
status = device_create_file(&gadget->dev, &dev_attr_suspended);
if (status)
goto fail;
Expand Down Expand Up @@ -1217,6 +1247,8 @@ int usb_composite_register(struct usb_composite_driver *driver)
if (!driver || !driver->dev || !driver->bind || composite)
return -EINVAL;

if (!driver->iProduct)
driver->iProduct = driver->name;
if (!driver->name)
driver->name = "composite";
composite_driver.function = (char *) driver->name;
Expand Down
13 changes: 13 additions & 0 deletions trunk/include/linux/usb/composite.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,17 @@ int usb_add_config(struct usb_composite_dev *,
/**
* struct usb_composite_driver - groups configurations into a gadget
* @name: For diagnostics, identifies the driver.
* @iProduct: Used as iProduct override if @dev->iProduct is not set.
* If NULL value of @name is taken.
* @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is
* not set. If NULL a default "<system> <release> with <udc>" value
* will be used.
* @dev: Template descriptor for the device, including default device
* identifiers.
* @strings: tables of strings, keyed by identifiers assigned during bind()
* and language IDs provided in control requests
* @needs_serial: set to 1 if the gadget needs userspace to provide
* a serial number. If one is not provided, warning will be printed.
* @bind: (REQUIRED) Used to allocate resources that are shared across the
* whole device, such as string IDs, and add its configurations using
* @usb_add_config(). This may fail by returning a negative errno
Expand All @@ -266,8 +273,11 @@ int usb_add_config(struct usb_composite_dev *,
*/
struct usb_composite_driver {
const char *name;
const char *iProduct;
const char *iManufacturer;
const struct usb_device_descriptor *dev;
struct usb_gadget_strings **strings;
unsigned needs_serial:1;

/* REVISIT: bind() functions can be marked __init, which
* makes trouble for section mismatch analysis. See if
Expand Down Expand Up @@ -334,6 +344,9 @@ struct usb_composite_dev {
struct list_head configs;
struct usb_composite_driver *driver;
u8 next_string_id;
u8 manufacturer_override;
u8 product_override;
u8 serial_override;

/* the gadget driver won't enable the data pullup
* while the deactivation count is nonzero.
Expand Down

0 comments on commit adfb693

Please sign in to comment.