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

gadget_printer.rst (11066B)


      1===============================
      2Linux USB Printer Gadget Driver
      3===============================
      4
      506/04/2007
      6
      7Copyright (C) 2007 Craig W. Nadler <craig@nadler.us>
      8
      9
     10
     11General
     12=======
     13
     14This driver may be used if you are writing printer firmware using Linux as
     15the embedded OS. This driver has nothing to do with using a printer with
     16your Linux host system.
     17
     18You will need a USB device controller and a Linux driver for it that accepts
     19a gadget / "device class" driver using the Linux USB Gadget API. After the
     20USB device controller driver is loaded then load the printer gadget driver.
     21This will present a printer interface to the USB Host that your USB Device
     22port is connected to.
     23
     24This driver is structured for printer firmware that runs in user mode. The
     25user mode printer firmware will read and write data from the kernel mode
     26printer gadget driver using a device file. The printer returns a printer status
     27byte when the USB HOST sends a device request to get the printer status.  The
     28user space firmware can read or write this status byte using a device file
     29/dev/g_printer . Both blocking and non-blocking read/write calls are supported.
     30
     31
     32
     33
     34Howto Use This Driver
     35=====================
     36
     37To load the USB device controller driver and the printer gadget driver. The
     38following example uses the Netchip 2280 USB device controller driver::
     39
     40	modprobe net2280
     41	modprobe g_printer
     42
     43
     44The follow command line parameter can be used when loading the printer gadget
     45(ex: modprobe g_printer idVendor=0x0525 idProduct=0xa4a8 ):
     46
     47idVendor
     48	This is the Vendor ID used in the device descriptor. The default is
     49	the Netchip vendor id 0x0525. YOU MUST CHANGE TO YOUR OWN VENDOR ID
     50	BEFORE RELEASING A PRODUCT. If you plan to release a product and don't
     51	already have a Vendor ID please see www.usb.org for details on how to
     52	get one.
     53
     54idProduct
     55	This is the Product ID used in the device descriptor. The default
     56	is 0xa4a8, you should change this to an ID that's not used by any of
     57	your other USB products if you have any. It would be a good idea to
     58	start numbering your products starting with say 0x0001.
     59
     60bcdDevice
     61	This is the version number of your product. It would be a good idea
     62	to put your firmware version here.
     63
     64iManufacturer
     65	A string containing the name of the Vendor.
     66
     67iProduct
     68	A string containing the Product Name.
     69
     70iSerialNum
     71	A string containing the Serial Number. This should be changed for
     72	each unit of your product.
     73
     74iPNPstring
     75	The PNP ID string used for this printer. You will want to set
     76	either on the command line or hard code the PNP ID string used for
     77	your printer product.
     78
     79qlen
     80	The number of 8k buffers to use per endpoint. The default is 10, you
     81	should tune this for your product. You may also want to tune the
     82	size of each buffer for your product.
     83
     84
     85
     86
     87Using The Example Code
     88======================
     89
     90This example code talks to stdout, instead of a print engine.
     91
     92To compile the test code below:
     93
     941) save it to a file called prn_example.c
     952) compile the code with the follow command::
     96
     97	 gcc prn_example.c -o prn_example
     98
     99
    100
    101To read printer data from the host to stdout::
    102
    103	# prn_example -read_data
    104
    105
    106To write printer data from a file (data_file) to the host::
    107
    108	# cat data_file | prn_example -write_data
    109
    110
    111To get the current printer status for the gadget driver:::
    112
    113	# prn_example -get_status
    114
    115	Printer status is:
    116	     Printer is NOT Selected
    117	     Paper is Out
    118	     Printer OK
    119
    120
    121To set printer to Selected/On-line::
    122
    123	# prn_example -selected
    124
    125
    126To set printer to Not Selected/Off-line::
    127
    128	# prn_example -not_selected
    129
    130
    131To set paper status to paper out::
    132
    133	# prn_example -paper_out
    134
    135
    136To set paper status to paper loaded::
    137
    138	# prn_example -paper_loaded
    139
    140
    141To set error status to printer OK::
    142
    143	# prn_example -no_error
    144
    145
    146To set error status to ERROR::
    147
    148	# prn_example -error
    149
    150
    151
    152
    153Example Code
    154============
    155
    156::
    157
    158
    159  #include <stdio.h>
    160  #include <stdlib.h>
    161  #include <fcntl.h>
    162  #include <linux/poll.h>
    163  #include <sys/ioctl.h>
    164  #include <linux/usb/g_printer.h>
    165
    166  #define PRINTER_FILE			"/dev/g_printer"
    167  #define BUF_SIZE			512
    168
    169
    170  /*
    171   * 'usage()' - Show program usage.
    172   */
    173
    174  static void
    175  usage(const char *option)		/* I - Option string or NULL */
    176  {
    177	if (option) {
    178		fprintf(stderr,"prn_example: Unknown option \"%s\"!\n",
    179				option);
    180	}
    181
    182	fputs("\n", stderr);
    183	fputs("Usage: prn_example -[options]\n", stderr);
    184	fputs("Options:\n", stderr);
    185	fputs("\n", stderr);
    186	fputs("-get_status    Get the current printer status.\n", stderr);
    187	fputs("-selected      Set the selected status to selected.\n", stderr);
    188	fputs("-not_selected  Set the selected status to NOT selected.\n",
    189			stderr);
    190	fputs("-error         Set the error status to error.\n", stderr);
    191	fputs("-no_error      Set the error status to NO error.\n", stderr);
    192	fputs("-paper_out     Set the paper status to paper out.\n", stderr);
    193	fputs("-paper_loaded  Set the paper status to paper loaded.\n",
    194			stderr);
    195	fputs("-read_data     Read printer data from driver.\n", stderr);
    196	fputs("-write_data    Write printer sata to driver.\n", stderr);
    197	fputs("-NB_read_data  (Non-Blocking) Read printer data from driver.\n",
    198			stderr);
    199	fputs("\n\n", stderr);
    200
    201	exit(1);
    202  }
    203
    204
    205  static int
    206  read_printer_data()
    207  {
    208	struct pollfd	fd[1];
    209
    210	/* Open device file for printer gadget. */
    211	fd[0].fd = open(PRINTER_FILE, O_RDWR);
    212	if (fd[0].fd < 0) {
    213		printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
    214		close(fd[0].fd);
    215		return(-1);
    216	}
    217
    218	fd[0].events = POLLIN | POLLRDNORM;
    219
    220	while (1) {
    221		static char buf[BUF_SIZE];
    222		int bytes_read;
    223		int retval;
    224
    225		/* Wait for up to 1 second for data. */
    226		retval = poll(fd, 1, 1000);
    227
    228		if (retval && (fd[0].revents & POLLRDNORM)) {
    229
    230			/* Read data from printer gadget driver. */
    231			bytes_read = read(fd[0].fd, buf, BUF_SIZE);
    232
    233			if (bytes_read < 0) {
    234				printf("Error %d reading from %s\n",
    235						fd[0].fd, PRINTER_FILE);
    236				close(fd[0].fd);
    237				return(-1);
    238			} else if (bytes_read > 0) {
    239				/* Write data to standard OUTPUT (stdout). */
    240				fwrite(buf, 1, bytes_read, stdout);
    241				fflush(stdout);
    242			}
    243
    244		}
    245
    246	}
    247
    248	/* Close the device file. */
    249	close(fd[0].fd);
    250
    251	return 0;
    252  }
    253
    254
    255  static int
    256  write_printer_data()
    257  {
    258	struct pollfd	fd[1];
    259
    260	/* Open device file for printer gadget. */
    261	fd[0].fd = open (PRINTER_FILE, O_RDWR);
    262	if (fd[0].fd < 0) {
    263		printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
    264		close(fd[0].fd);
    265		return(-1);
    266	}
    267
    268	fd[0].events = POLLOUT | POLLWRNORM;
    269
    270	while (1) {
    271		int retval;
    272		static char buf[BUF_SIZE];
    273		/* Read data from standard INPUT (stdin). */
    274		int bytes_read = fread(buf, 1, BUF_SIZE, stdin);
    275
    276		if (!bytes_read) {
    277			break;
    278		}
    279
    280		while (bytes_read) {
    281
    282			/* Wait for up to 1 second to sent data. */
    283			retval = poll(fd, 1, 1000);
    284
    285			/* Write data to printer gadget driver. */
    286			if (retval && (fd[0].revents & POLLWRNORM)) {
    287				retval = write(fd[0].fd, buf, bytes_read);
    288				if (retval < 0) {
    289					printf("Error %d writing to %s\n",
    290							fd[0].fd,
    291							PRINTER_FILE);
    292					close(fd[0].fd);
    293					return(-1);
    294				} else {
    295					bytes_read -= retval;
    296				}
    297
    298			}
    299
    300		}
    301
    302	}
    303
    304	/* Wait until the data has been sent. */
    305	fsync(fd[0].fd);
    306
    307	/* Close the device file. */
    308	close(fd[0].fd);
    309
    310	return 0;
    311  }
    312
    313
    314  static int
    315  read_NB_printer_data()
    316  {
    317	int		fd;
    318	static char	buf[BUF_SIZE];
    319	int		bytes_read;
    320
    321	/* Open device file for printer gadget. */
    322	fd = open(PRINTER_FILE, O_RDWR|O_NONBLOCK);
    323	if (fd < 0) {
    324		printf("Error %d opening %s\n", fd, PRINTER_FILE);
    325		close(fd);
    326		return(-1);
    327	}
    328
    329	while (1) {
    330		/* Read data from printer gadget driver. */
    331		bytes_read = read(fd, buf, BUF_SIZE);
    332		if (bytes_read <= 0) {
    333			break;
    334		}
    335
    336		/* Write data to standard OUTPUT (stdout). */
    337		fwrite(buf, 1, bytes_read, stdout);
    338		fflush(stdout);
    339	}
    340
    341	/* Close the device file. */
    342	close(fd);
    343
    344	return 0;
    345  }
    346
    347
    348  static int
    349  get_printer_status()
    350  {
    351	int	retval;
    352	int	fd;
    353
    354	/* Open device file for printer gadget. */
    355	fd = open(PRINTER_FILE, O_RDWR);
    356	if (fd < 0) {
    357		printf("Error %d opening %s\n", fd, PRINTER_FILE);
    358		close(fd);
    359		return(-1);
    360	}
    361
    362	/* Make the IOCTL call. */
    363	retval = ioctl(fd, GADGET_GET_PRINTER_STATUS);
    364	if (retval < 0) {
    365		fprintf(stderr, "ERROR: Failed to set printer status\n");
    366		return(-1);
    367	}
    368
    369	/* Close the device file. */
    370	close(fd);
    371
    372	return(retval);
    373  }
    374
    375
    376  static int
    377  set_printer_status(unsigned char buf, int clear_printer_status_bit)
    378  {
    379	int	retval;
    380	int	fd;
    381
    382	retval = get_printer_status();
    383	if (retval < 0) {
    384		fprintf(stderr, "ERROR: Failed to get printer status\n");
    385		return(-1);
    386	}
    387
    388	/* Open device file for printer gadget. */
    389	fd = open(PRINTER_FILE, O_RDWR);
    390
    391	if (fd < 0) {
    392		printf("Error %d opening %s\n", fd, PRINTER_FILE);
    393		close(fd);
    394		return(-1);
    395	}
    396
    397	if (clear_printer_status_bit) {
    398		retval &= ~buf;
    399	} else {
    400		retval |= buf;
    401	}
    402
    403	/* Make the IOCTL call. */
    404	if (ioctl(fd, GADGET_SET_PRINTER_STATUS, (unsigned char)retval)) {
    405		fprintf(stderr, "ERROR: Failed to set printer status\n");
    406		return(-1);
    407	}
    408
    409	/* Close the device file. */
    410	close(fd);
    411
    412	return 0;
    413  }
    414
    415
    416  static int
    417  display_printer_status()
    418  {
    419	char	printer_status;
    420
    421	printer_status = get_printer_status();
    422	if (printer_status < 0) {
    423		fprintf(stderr, "ERROR: Failed to get printer status\n");
    424		return(-1);
    425	}
    426
    427	printf("Printer status is:\n");
    428	if (printer_status & PRINTER_SELECTED) {
    429		printf("     Printer is Selected\n");
    430	} else {
    431		printf("     Printer is NOT Selected\n");
    432	}
    433	if (printer_status & PRINTER_PAPER_EMPTY) {
    434		printf("     Paper is Out\n");
    435	} else {
    436		printf("     Paper is Loaded\n");
    437	}
    438	if (printer_status & PRINTER_NOT_ERROR) {
    439		printf("     Printer OK\n");
    440	} else {
    441		printf("     Printer ERROR\n");
    442	}
    443
    444	return(0);
    445  }
    446
    447
    448  int
    449  main(int  argc, char *argv[])
    450  {
    451	int	i;		/* Looping var */
    452	int	retval = 0;
    453
    454	/* No Args */
    455	if (argc == 1) {
    456		usage(0);
    457		exit(0);
    458	}
    459
    460	for (i = 1; i < argc && !retval; i ++) {
    461
    462		if (argv[i][0] != '-') {
    463			continue;
    464		}
    465
    466		if (!strcmp(argv[i], "-get_status")) {
    467			if (display_printer_status()) {
    468				retval = 1;
    469			}
    470
    471		} else if (!strcmp(argv[i], "-paper_loaded")) {
    472			if (set_printer_status(PRINTER_PAPER_EMPTY, 1)) {
    473				retval = 1;
    474			}
    475
    476		} else if (!strcmp(argv[i], "-paper_out")) {
    477			if (set_printer_status(PRINTER_PAPER_EMPTY, 0)) {
    478				retval = 1;
    479			}
    480
    481		} else if (!strcmp(argv[i], "-selected")) {
    482			if (set_printer_status(PRINTER_SELECTED, 0)) {
    483				retval = 1;
    484			}
    485
    486		} else if (!strcmp(argv[i], "-not_selected")) {
    487			if (set_printer_status(PRINTER_SELECTED, 1)) {
    488				retval = 1;
    489			}
    490
    491		} else if (!strcmp(argv[i], "-error")) {
    492			if (set_printer_status(PRINTER_NOT_ERROR, 1)) {
    493				retval = 1;
    494			}
    495
    496		} else if (!strcmp(argv[i], "-no_error")) {
    497			if (set_printer_status(PRINTER_NOT_ERROR, 0)) {
    498				retval = 1;
    499			}
    500
    501		} else if (!strcmp(argv[i], "-read_data")) {
    502			if (read_printer_data()) {
    503				retval = 1;
    504			}
    505
    506		} else if (!strcmp(argv[i], "-write_data")) {
    507			if (write_printer_data()) {
    508				retval = 1;
    509			}
    510
    511		} else if (!strcmp(argv[i], "-NB_read_data")) {
    512			if (read_NB_printer_data()) {
    513				retval = 1;
    514			}
    515
    516		} else {
    517			usage(argv[i]);
    518			retval = 1;
    519		}
    520	}
    521
    522	exit(retval);
    523  }