diff options
Diffstat (limited to 'drivers/usb/gadget/printer.c')
-rw-r--r-- | drivers/usb/gadget/printer.c | 173 |
1 files changed, 71 insertions, 102 deletions
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index f1f9290a2f47..e156e3f26727 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -22,7 +22,6 @@ #include <linux/timer.h> #include <linux/list.h> #include <linux/interrupt.h> -#include <linux/utsname.h> #include <linux/device.h> #include <linux/moduleparam.h> #include <linux/fs.h> @@ -38,25 +37,13 @@ #include <asm/unaligned.h> #include <linux/usb/ch9.h> +#include <linux/usb/composite.h> #include <linux/usb/gadget.h> #include <linux/usb/g_printer.h> #include "gadget_chips.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" - -/*-------------------------------------------------------------------------*/ +USB_GADGET_COMPOSITE_OPTIONS(); #define DRIVER_DESC "Printer Gadget" #define DRIVER_VERSION "2007 OCT 06" @@ -120,8 +107,7 @@ static struct printer_dev usb_printer_gadget; * parameters are in UTF-8 (superset of ASCII's 7 bit characters). */ -static char *iSerialNum; -module_param(iSerialNum, charp, S_IRUGO); +module_param_named(iSerialNum, coverwrite.serial_number, charp, S_IRUGO); MODULE_PARM_DESC(iSerialNum, "1"); static char *iPNPstring; @@ -141,18 +127,10 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR); * descriptors are built on demand. */ -#define STRING_MANUFACTURER 1 -#define STRING_PRODUCT 2 -#define STRING_SERIALNUM 3 - /* holds our biggest descriptor */ #define USB_DESC_BUFSIZE 256 #define USB_BUFSIZE 8192 -/* This device advertises one configuration. */ -#define DEV_CONFIG_VALUE 1 -#define PRINTER_INTERFACE 0 - static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, @@ -162,16 +140,12 @@ static struct usb_device_descriptor device_desc = { .bDeviceProtocol = 0, .idVendor = cpu_to_le16(PRINTER_VENDOR_NUM), .idProduct = cpu_to_le16(PRINTER_PRODUCT_NUM), - .iManufacturer = STRING_MANUFACTURER, - .iProduct = STRING_PRODUCT, - .iSerialNumber = STRING_SERIALNUM, .bNumConfigurations = 1 }; static struct usb_interface_descriptor intf_desc = { .bLength = sizeof intf_desc, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = PRINTER_INTERFACE, .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_PRINTER, .bInterfaceSubClass = 1, /* Printer Sub-Class */ @@ -252,7 +226,6 @@ static const struct usb_descriptor_header *otg_desc[] = { /* descriptors that are built on-demand */ -static char manufacturer [50]; static char product_desc [40] = DRIVER_DESC; static char serial_num [40] = "1"; static char pnp_string [1024] = @@ -260,9 +233,9 @@ static char pnp_string [1024] = /* static strings, in UTF-8 */ static struct usb_string strings [] = { - { STRING_MANUFACTURER, manufacturer, }, - { STRING_PRODUCT, product_desc, }, - { STRING_SERIALNUM, serial_num, }, + [USB_GADGET_MANUFACTURER_IDX].s = "", + [USB_GADGET_PRODUCT_IDX].s = product_desc, + [USB_GADGET_SERIAL_IDX].s = serial_num, { } /* end of list */ }; @@ -871,25 +844,13 @@ static int set_interface(struct printer_dev *dev, unsigned number) int result = 0; /* Free the current interface */ - switch (dev->interface) { - case PRINTER_INTERFACE: - printer_reset_interface(dev); - break; - } + printer_reset_interface(dev); - switch (number) { - case PRINTER_INTERFACE: - result = set_printer_interface(dev); - if (result) { - printer_reset_interface(dev); - } else { - dev->interface = PRINTER_INTERFACE; - } - break; - default: - result = -EINVAL; - /* FALL THROUGH */ - } + result = set_printer_interface(dev); + if (result) + printer_reset_interface(dev); + else + dev->interface = number; if (!result) INFO(dev, "Using interface %x\n", number); @@ -972,7 +933,7 @@ static int printer_func_setup(struct usb_function *f, switch (ctrl->bRequest) { case 0: /* Get the IEEE-1284 PNP String */ /* Only one printer interface is supported. */ - if ((wIndex>>8) != PRINTER_INTERFACE) + if ((wIndex>>8) != dev->interface) break; value = (pnp_string[0]<<8)|pnp_string[1]; @@ -983,7 +944,7 @@ static int printer_func_setup(struct usb_function *f, case 1: /* Get Port Status */ /* Only one printer interface is supported. */ - if (wIndex != PRINTER_INTERFACE) + if (wIndex != dev->interface) break; *(u8 *)req->buf = dev->printer_status; @@ -992,7 +953,7 @@ static int printer_func_setup(struct usb_function *f, case 2: /* Soft Reset */ /* Only one printer interface is supported. */ - if (wIndex != PRINTER_INTERFACE) + if (wIndex != dev->interface) break; printer_soft_reset(dev); @@ -1020,6 +981,37 @@ unknown: static int __init printer_func_bind(struct usb_configuration *c, struct usb_function *f) { + struct printer_dev *dev = container_of(f, struct printer_dev, function); + struct usb_composite_dev *cdev = c->cdev; + struct usb_ep *in_ep, *out_ep; + int id; + + id = usb_interface_id(c, f); + if (id < 0) + return id; + intf_desc.bInterfaceNumber = id; + + /* all we really need is bulk IN/OUT */ + in_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_in_desc); + if (!in_ep) { +autoconf_fail: + dev_err(&cdev->gadget->dev, "can't autoconfigure on %s\n", + cdev->gadget->name); + return -ENODEV; + } + in_ep->driver_data = in_ep; /* claim */ + + out_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_out_desc); + if (!out_ep) + goto autoconf_fail; + out_ep->driver_data = out_ep; /* claim */ + + /* assumes that all endpoints are dual-speed */ + hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress; + hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; + + dev->in_ep = in_ep; + dev->out_ep = out_ep; return 0; } @@ -1035,7 +1027,8 @@ static int printer_func_set_alt(struct usb_function *f, int ret = -ENOTSUPP; if (!alt) - ret = set_interface(dev, PRINTER_INTERFACE); + ret = set_interface(dev, intf); + return ret; } @@ -1107,13 +1100,13 @@ static int __init printer_bind_config(struct usb_configuration *c) { struct usb_gadget *gadget = c->cdev->gadget; struct printer_dev *dev; - struct usb_ep *in_ep, *out_ep; int status = -ENOMEM; - int gcnum; size_t len; u32 i; struct usb_request *req; + usb_ep_autoconfig_reset(gadget); + dev = &usb_printer_gadget; dev->function.name = shortname; @@ -1125,6 +1118,10 @@ static int __init printer_bind_config(struct usb_configuration *c) dev->function.set_alt = printer_func_set_alt; dev->function.disable = printer_func_disable; + status = usb_add_function(c, &dev->function); + if (status) + return status; + /* Setup the sysfs files for the printer gadget. */ dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno, NULL, "g_printer"); @@ -1145,23 +1142,6 @@ static int __init printer_bind_config(struct usb_configuration *c) goto fail; } - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) { - device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); - } else { - dev_warn(&gadget->dev, "controller '%s' not recognized\n", - gadget->name); - /* unrecognized, but safe unless bulk is REALLY quirky */ - device_desc.bcdDevice = - cpu_to_le16(0xFFFF); - } - snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); - - if (iSerialNum) - strlcpy(serial_num, iSerialNum, sizeof serial_num); - if (iPNPstring) strlcpy(&pnp_string[2], iPNPstring, (sizeof pnp_string)-2); @@ -1169,26 +1149,6 @@ static int __init printer_bind_config(struct usb_configuration *c) pnp_string[0] = (len >> 8) & 0xFF; pnp_string[1] = len & 0xFF; - /* all we really need is bulk IN/OUT */ - usb_ep_autoconfig_reset(gadget); - in_ep = usb_ep_autoconfig(gadget, &fs_ep_in_desc); - if (!in_ep) { -autoconf_fail: - dev_err(&gadget->dev, "can't autoconfigure on %s\n", - gadget->name); - return -ENODEV; - } - in_ep->driver_data = in_ep; /* claim */ - - out_ep = usb_ep_autoconfig(gadget, &fs_ep_out_desc); - if (!out_ep) - goto autoconf_fail; - out_ep->driver_data = out_ep; /* claim */ - - /* assumes that all endpoints are dual-speed */ - hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress; - hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; - usb_gadget_set_selfpowered(gadget); if (gadget->is_otg) { @@ -1215,9 +1175,6 @@ autoconf_fail: dev->current_rx_bytes = 0; dev->current_rx_buf = NULL; - dev->in_ep = in_ep; - dev->out_ep = out_ep; - for (i = 0; i < QLEN; i++) { req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL); if (!req) { @@ -1250,8 +1207,6 @@ autoconf_fail: dev->gadget = gadget; INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc); - INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, out_ep->name, - in_ep->name); return 0; fail: @@ -1266,14 +1221,28 @@ static int printer_unbind(struct usb_composite_dev *cdev) static int __init printer_bind(struct usb_composite_dev *cdev) { - return usb_add_config(cdev, &printer_cfg_driver, printer_bind_config); + int ret; + + ret = usb_string_ids_tab(cdev, strings); + if (ret < 0) + return ret; + device_desc.iManufacturer = strings[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings[USB_GADGET_PRODUCT_IDX].id; + device_desc.iSerialNumber = strings[USB_GADGET_SERIAL_IDX].id; + + ret = usb_add_config(cdev, &printer_cfg_driver, printer_bind_config); + if (ret) + return ret; + usb_composite_overwrite_options(cdev, &coverwrite); + return ret; } -static struct usb_composite_driver printer_driver = { +static __refdata struct usb_composite_driver printer_driver = { .name = shortname, .dev = &device_desc, .strings = dev_strings, .max_speed = USB_SPEED_HIGH, + .bind = printer_bind, .unbind = printer_unbind, }; @@ -1297,7 +1266,7 @@ init(void) return status; } - status = usb_composite_probe(&printer_driver, printer_bind); + status = usb_composite_probe(&printer_driver); if (status) { class_destroy(usb_gadget_class); unregister_chrdev_region(g_printer_devno, 1); |