1/* 2 * printer.c -- Printer gadget driver 3 * 4 * Copyright (C) 2003-2005 David Brownell 5 * Copyright (C) 2006 Craig W. Nadler 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 */ 12 13#include <linux/module.h> 14#include <linux/kernel.h> 15#include <asm/byteorder.h> 16 17#include <linux/usb/ch9.h> 18#include <linux/usb/composite.h> 19#include <linux/usb/gadget.h> 20#include <linux/usb/g_printer.h> 21 22#include "gadget_chips.h" 23 24USB_GADGET_COMPOSITE_OPTIONS(); 25 26#define DRIVER_DESC "Printer Gadget" 27#define DRIVER_VERSION "2015 FEB 17" 28 29static const char shortname [] = "printer"; 30static const char driver_desc [] = DRIVER_DESC; 31 32#include "u_printer.h" 33 34/*-------------------------------------------------------------------------*/ 35 36/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! 37 * Instead: allocate your own, using normal USB-IF procedures. 38 */ 39 40/* Thanks to NetChip Technologies for donating this product ID. 41 */ 42#define PRINTER_VENDOR_NUM 0x0525 /* NetChip */ 43#define PRINTER_PRODUCT_NUM 0xa4a8 /* Linux-USB Printer Gadget */ 44 45/* Some systems will want different product identifiers published in the 46 * device descriptor, either numbers or strings or both. These string 47 * parameters are in UTF-8 (superset of ASCII's 7 bit characters). 48 */ 49 50module_param_named(iSerialNum, coverwrite.serial_number, charp, S_IRUGO); 51MODULE_PARM_DESC(iSerialNum, "1"); 52 53static char *iPNPstring; 54module_param(iPNPstring, charp, S_IRUGO); 55MODULE_PARM_DESC(iPNPstring, "MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;"); 56 57/* Number of requests to allocate per endpoint, not used for ep0. */ 58static unsigned qlen = 10; 59module_param(qlen, uint, S_IRUGO|S_IWUSR); 60 61#define QLEN qlen 62 63static struct usb_function_instance *fi_printer; 64static struct usb_function *f_printer; 65 66/*-------------------------------------------------------------------------*/ 67 68/* 69 * DESCRIPTORS ... most are static, but strings and (full) configuration 70 * descriptors are built on demand. 71 */ 72 73static struct usb_device_descriptor device_desc = { 74 .bLength = sizeof device_desc, 75 .bDescriptorType = USB_DT_DEVICE, 76 .bcdUSB = cpu_to_le16(0x0200), 77 .bDeviceClass = USB_CLASS_PER_INTERFACE, 78 .bDeviceSubClass = 0, 79 .bDeviceProtocol = 0, 80 .idVendor = cpu_to_le16(PRINTER_VENDOR_NUM), 81 .idProduct = cpu_to_le16(PRINTER_PRODUCT_NUM), 82 .bNumConfigurations = 1 83}; 84 85static struct usb_otg_descriptor otg_descriptor = { 86 .bLength = sizeof otg_descriptor, 87 .bDescriptorType = USB_DT_OTG, 88 .bmAttributes = USB_OTG_SRP, 89}; 90 91static const struct usb_descriptor_header *otg_desc[] = { 92 (struct usb_descriptor_header *) &otg_descriptor, 93 NULL, 94}; 95 96/*-------------------------------------------------------------------------*/ 97 98/* descriptors that are built on-demand */ 99 100static char product_desc [40] = DRIVER_DESC; 101static char serial_num [40] = "1"; 102static char pnp_string[PNP_STRING_LEN] = 103 "XXMFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;"; 104 105/* static strings, in UTF-8 */ 106static struct usb_string strings [] = { 107 [USB_GADGET_MANUFACTURER_IDX].s = "", 108 [USB_GADGET_PRODUCT_IDX].s = product_desc, 109 [USB_GADGET_SERIAL_IDX].s = serial_num, 110 { } /* end of list */ 111}; 112 113static struct usb_gadget_strings stringtab_dev = { 114 .language = 0x0409, /* en-us */ 115 .strings = strings, 116}; 117 118static struct usb_gadget_strings *dev_strings[] = { 119 &stringtab_dev, 120 NULL, 121}; 122 123static struct usb_configuration printer_cfg_driver = { 124 .label = "printer", 125 .bConfigurationValue = 1, 126 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, 127}; 128 129static int printer_do_config(struct usb_configuration *c) 130{ 131 struct usb_gadget *gadget = c->cdev->gadget; 132 int status = 0; 133 134 usb_ep_autoconfig_reset(gadget); 135 136 usb_gadget_set_selfpowered(gadget); 137 138 if (gadget_is_otg(gadget)) { 139 otg_descriptor.bmAttributes |= USB_OTG_HNP; 140 printer_cfg_driver.descriptors = otg_desc; 141 printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; 142 } 143 144 f_printer = usb_get_function(fi_printer); 145 if (IS_ERR(f_printer)) 146 return PTR_ERR(f_printer); 147 148 status = usb_add_function(c, f_printer); 149 if (status < 0) 150 usb_put_function(f_printer); 151 152 return status; 153} 154 155static int printer_bind(struct usb_composite_dev *cdev) 156{ 157 struct f_printer_opts *opts; 158 int ret, len; 159 160 fi_printer = usb_get_function_instance("printer"); 161 if (IS_ERR(fi_printer)) 162 return PTR_ERR(fi_printer); 163 164 if (iPNPstring) 165 strlcpy(&pnp_string[2], iPNPstring, PNP_STRING_LEN - 2); 166 167 len = strlen(pnp_string); 168 pnp_string[0] = (len >> 8) & 0xFF; 169 pnp_string[1] = len & 0xFF; 170 171 opts = container_of(fi_printer, struct f_printer_opts, func_inst); 172 opts->minor = 0; 173 memcpy(opts->pnp_string, pnp_string, PNP_STRING_LEN); 174 opts->q_len = QLEN; 175 176 ret = usb_string_ids_tab(cdev, strings); 177 if (ret < 0) { 178 usb_put_function_instance(fi_printer); 179 return ret; 180 } 181 device_desc.iManufacturer = strings[USB_GADGET_MANUFACTURER_IDX].id; 182 device_desc.iProduct = strings[USB_GADGET_PRODUCT_IDX].id; 183 device_desc.iSerialNumber = strings[USB_GADGET_SERIAL_IDX].id; 184 185 ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config); 186 if (ret) { 187 usb_put_function_instance(fi_printer); 188 return ret; 189 } 190 usb_composite_overwrite_options(cdev, &coverwrite); 191 return ret; 192} 193 194static int printer_unbind(struct usb_composite_dev *cdev) 195{ 196 usb_put_function(f_printer); 197 usb_put_function_instance(fi_printer); 198 199 return 0; 200} 201 202static struct usb_composite_driver printer_driver = { 203 .name = shortname, 204 .dev = &device_desc, 205 .strings = dev_strings, 206 .max_speed = USB_SPEED_SUPER, 207 .bind = printer_bind, 208 .unbind = printer_unbind, 209}; 210 211module_usb_composite_driver(printer_driver); 212 213MODULE_DESCRIPTION(DRIVER_DESC); 214MODULE_AUTHOR("Craig Nadler"); 215MODULE_LICENSE("GPL"); 216