cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

printer.c (5902B)


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