2 Linux USB Printer Gadget Driver
5 Copyright (C) 2007 Craig W. Nadler <craig@nadler.us>
12 This driver may be used if you are writing printer firmware using Linux as
13 the embedded OS. This driver has nothing to do with using a printer with
14 your Linux host system.
16 You will need a USB device controller and a Linux driver for it that accepts
17 a gadget / "device class" driver using the Linux USB Gadget API. After the
18 USB device controller driver is loaded then load the printer gadget driver.
19 This will present a printer interface to the USB Host that your USB Device
22 This driver is structured for printer firmware that runs in user mode. The
23 user mode printer firmware will read and write data from the kernel mode
24 printer gadget driver using a device file. The printer returns a printer status
25 byte when the USB HOST sends a device request to get the printer status. The
26 user space firmware can read or write this status byte using a device file
27 /dev/g_printer . Both blocking and non-blocking read/write calls are supported.
35 To load the USB device controller driver and the printer gadget driver. The
36 following example uses the Netchip 2280 USB device controller driver:
42 The follow command line parameter can be used when loading the printer gadget
43 (ex: modprobe g_printer idVendor=0x0525 idProduct=0xa4a8 ):
45 idVendor - This is the Vendor ID used in the device descriptor. The default is
46 the Netchip vendor id 0x0525. YOU MUST CHANGE TO YOUR OWN VENDOR ID
47 BEFORE RELEASING A PRODUCT. If you plan to release a product and don't
48 already have a Vendor ID please see www.usb.org for details on how to
51 idProduct - This is the Product ID used in the device descriptor. The default
52 is 0xa4a8, you should change this to an ID that's not used by any of
53 your other USB products if you have any. It would be a good idea to
54 start numbering your products starting with say 0x0001.
56 bcdDevice - This is the version number of your product. It would be a good idea
57 to put your firmware version here.
59 iManufacturer - A string containing the name of the Vendor.
61 iProduct - A string containing the Product Name.
63 iSerialNum - A string containing the Serial Number. This should be changed for
64 each unit of your product.
66 iPNPstring - The PNP ID string used for this printer. You will want to set
67 either on the command line or hard code the PNP ID string used for
70 qlen - The number of 8k buffers to use per endpoint. The default is 10, you
71 should tune this for your product. You may also want to tune the
72 size of each buffer for your product.
77 USING THE EXAMPLE CODE
78 ======================
80 This example code talks to stdout, instead of a print engine.
82 To compile the test code below:
84 1) save it to a file called prn_example.c
85 2) compile the code with the follow command:
86 gcc prn_example.c -o prn_example
90 To read printer data from the host to stdout:
92 # prn_example -read_data
95 To write printer data from a file (data_file) to the host:
97 # cat data_file | prn_example -write_data
100 To get the current printer status for the gadget driver:
102 # prn_example -get_status
105 Printer is NOT Selected
110 To set printer to Selected/On-line:
112 # prn_example -selected
115 To set printer to Not Selected/Off-line:
117 # prn_example -not_selected
120 To set paper status to paper out:
122 # prn_example -paper_out
125 To set paper status to paper loaded:
127 # prn_example -paper_loaded
130 To set error status to printer OK:
132 # prn_example -no_error
135 To set error status to ERROR:
149 #include <linux/poll.h>
150 #include <sys/ioctl.h>
151 #include <linux/usb/g_printer.h>
153 #define PRINTER_FILE "/dev/g_printer"
158 * 'usage()' - Show program usage.
162 usage(const char *option) /* I - Option string or NULL */
165 fprintf(stderr,"prn_example: Unknown option \"%s\"!\n",
170 fputs("Usage: prn_example -[options]\n", stderr);
171 fputs("Options:\n", stderr);
173 fputs("-get_status Get the current printer status.\n", stderr);
174 fputs("-selected Set the selected status to selected.\n", stderr);
175 fputs("-not_selected Set the selected status to NOT selected.\n",
177 fputs("-error Set the error status to error.\n", stderr);
178 fputs("-no_error Set the error status to NO error.\n", stderr);
179 fputs("-paper_out Set the paper status to paper out.\n", stderr);
180 fputs("-paper_loaded Set the paper status to paper loaded.\n",
182 fputs("-read_data Read printer data from driver.\n", stderr);
183 fputs("-write_data Write printer sata to driver.\n", stderr);
184 fputs("-NB_read_data (Non-Blocking) Read printer data from driver.\n",
186 fputs("\n\n", stderr);
197 /* Open device file for printer gadget. */
198 fd[0].fd = open(PRINTER_FILE, O_RDWR);
200 printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
205 fd[0].events = POLLIN | POLLRDNORM;
208 static char buf[BUF_SIZE];
212 /* Wait for up to 1 second for data. */
213 retval = poll(fd, 1, 1000);
215 if (retval && (fd[0].revents & POLLRDNORM)) {
217 /* Read data from printer gadget driver. */
218 bytes_read = read(fd[0].fd, buf, BUF_SIZE);
220 if (bytes_read < 0) {
221 printf("Error %d reading from %s\n",
222 fd[0].fd, PRINTER_FILE);
225 } else if (bytes_read > 0) {
226 /* Write data to standard OUTPUT (stdout). */
227 fwrite(buf, 1, bytes_read, stdout);
235 /* Close the device file. */
247 /* Open device file for printer gadget. */
248 fd[0].fd = open (PRINTER_FILE, O_RDWR);
250 printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
255 fd[0].events = POLLOUT | POLLWRNORM;
259 static char buf[BUF_SIZE];
260 /* Read data from standard INPUT (stdin). */
261 int bytes_read = fread(buf, 1, BUF_SIZE, stdin);
269 /* Wait for up to 1 second to sent data. */
270 retval = poll(fd, 1, 1000);
272 /* Write data to printer gadget driver. */
273 if (retval && (fd[0].revents & POLLWRNORM)) {
274 retval = write(fd[0].fd, buf, bytes_read);
276 printf("Error %d writing to %s\n",
282 bytes_read -= retval;
291 /* Wait until the data has been sent. */
294 /* Close the device file. */
302 read_NB_printer_data()
305 static char buf[BUF_SIZE];
308 /* Open device file for printer gadget. */
309 fd = open(PRINTER_FILE, O_RDWR|O_NONBLOCK);
311 printf("Error %d opening %s\n", fd, PRINTER_FILE);
317 /* Read data from printer gadget driver. */
318 bytes_read = read(fd, buf, BUF_SIZE);
319 if (bytes_read <= 0) {
323 /* Write data to standard OUTPUT (stdout). */
324 fwrite(buf, 1, bytes_read, stdout);
328 /* Close the device file. */
341 /* Open device file for printer gadget. */
342 fd = open(PRINTER_FILE, O_RDWR);
344 printf("Error %d opening %s\n", fd, PRINTER_FILE);
349 /* Make the IOCTL call. */
350 retval = ioctl(fd, GADGET_GET_PRINTER_STATUS);
352 fprintf(stderr, "ERROR: Failed to set printer status\n");
356 /* Close the device file. */
364 set_printer_status(unsigned char buf, int clear_printer_status_bit)
369 retval = get_printer_status();
371 fprintf(stderr, "ERROR: Failed to get printer status\n");
375 /* Open device file for printer gadget. */
376 fd = open(PRINTER_FILE, O_RDWR);
379 printf("Error %d opening %s\n", fd, PRINTER_FILE);
384 if (clear_printer_status_bit) {
390 /* Make the IOCTL call. */
391 if (ioctl(fd, GADGET_SET_PRINTER_STATUS, (unsigned char)retval)) {
392 fprintf(stderr, "ERROR: Failed to set printer status\n");
396 /* Close the device file. */
404 display_printer_status()
408 printer_status = get_printer_status();
409 if (printer_status < 0) {
410 fprintf(stderr, "ERROR: Failed to get printer status\n");
414 printf("Printer status is:\n");
415 if (printer_status & PRINTER_SELECTED) {
416 printf(" Printer is Selected\n");
418 printf(" Printer is NOT Selected\n");
420 if (printer_status & PRINTER_PAPER_EMPTY) {
421 printf(" Paper is Out\n");
423 printf(" Paper is Loaded\n");
425 if (printer_status & PRINTER_NOT_ERROR) {
426 printf(" Printer OK\n");
428 printf(" Printer ERROR\n");
436 main(int argc, char *argv[])
438 int i; /* Looping var */
447 for (i = 1; i < argc && !retval; i ++) {
449 if (argv[i][0] != '-') {
453 if (!strcmp(argv[i], "-get_status")) {
454 if (display_printer_status()) {
458 } else if (!strcmp(argv[i], "-paper_loaded")) {
459 if (set_printer_status(PRINTER_PAPER_EMPTY, 1)) {
463 } else if (!strcmp(argv[i], "-paper_out")) {
464 if (set_printer_status(PRINTER_PAPER_EMPTY, 0)) {
468 } else if (!strcmp(argv[i], "-selected")) {
469 if (set_printer_status(PRINTER_SELECTED, 0)) {
473 } else if (!strcmp(argv[i], "-not_selected")) {
474 if (set_printer_status(PRINTER_SELECTED, 1)) {
478 } else if (!strcmp(argv[i], "-error")) {
479 if (set_printer_status(PRINTER_NOT_ERROR, 1)) {
483 } else if (!strcmp(argv[i], "-no_error")) {
484 if (set_printer_status(PRINTER_NOT_ERROR, 0)) {
488 } else if (!strcmp(argv[i], "-read_data")) {
489 if (read_printer_data()) {
493 } else if (!strcmp(argv[i], "-write_data")) {
494 if (write_printer_data()) {
498 } else if (!strcmp(argv[i], "-NB_read_data")) {
499 if (read_NB_printer_data()) {