1 ===============================
2 Linux USB Printer Gadget Driver
3 ===============================
7 Copyright (C) 2007 Craig W. Nadler <craig@nadler.us>
14 This driver may be used if you are writing printer firmware using Linux as
15 the embedded OS. This driver has nothing to do with using a printer with
16 your Linux host system.
18 You will need a USB device controller and a Linux driver for it that accepts
19 a gadget / "device class" driver using the Linux USB Gadget API. After the
20 USB device controller driver is loaded then load the printer gadget driver.
21 This will present a printer interface to the USB Host that your USB Device
24 This driver is structured for printer firmware that runs in user mode. The
25 user mode printer firmware will read and write data from the kernel mode
26 printer gadget driver using a device file. The printer returns a printer status
27 byte when the USB HOST sends a device request to get the printer status. The
28 user 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.
37 To load the USB device controller driver and the printer gadget driver. The
38 following example uses the Netchip 2280 USB device controller driver::
44 The follow command line parameter can be used when loading the printer gadget
45 (ex: modprobe g_printer idVendor=0x0525 idProduct=0xa4a8 ):
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
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.
61 This is the version number of your product. It would be a good idea
62 to put your firmware version here.
65 A string containing the name of the Vendor.
68 A string containing the Product Name.
71 A string containing the Serial Number. This should be changed for
72 each unit of your product.
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
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.
87 Using The Example Code
88 ======================
90 This example code talks to stdout, instead of a print engine.
92 To compile the test code below:
94 1) save it to a file called prn_example.c
95 2) compile the code with the follow command::
97 gcc prn_example.c -o prn_example
101 To read printer data from the host to stdout::
103 # prn_example -read_data
106 To write printer data from a file (data_file) to the host::
108 # cat data_file | prn_example -write_data
111 To get the current printer status for the gadget driver:::
113 # prn_example -get_status
116 Printer is NOT Selected
121 To set printer to Selected/On-line::
123 # prn_example -selected
126 To set printer to Not Selected/Off-line::
128 # prn_example -not_selected
131 To set paper status to paper out::
133 # prn_example -paper_out
136 To set paper status to paper loaded::
138 # prn_example -paper_loaded
141 To set error status to printer OK::
143 # prn_example -no_error
146 To set error status to ERROR::
162 #include <linux/poll.h>
163 #include <sys/ioctl.h>
164 #include <linux/usb/g_printer.h>
166 #define PRINTER_FILE "/dev/g_printer"
171 * 'usage()' - Show program usage.
175 usage(const char *option) /* I - Option string or NULL */
178 fprintf(stderr,"prn_example: Unknown option \"%s\"!\n",
183 fputs("Usage: prn_example -[options]\n", stderr);
184 fputs("Options:\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",
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",
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",
199 fputs("\n\n", stderr);
210 /* Open device file for printer gadget. */
211 fd[0].fd = open(PRINTER_FILE, O_RDWR);
213 printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
218 fd[0].events = POLLIN | POLLRDNORM;
221 static char buf[BUF_SIZE];
225 /* Wait for up to 1 second for data. */
226 retval = poll(fd, 1, 1000);
228 if (retval && (fd[0].revents & POLLRDNORM)) {
230 /* Read data from printer gadget driver. */
231 bytes_read = read(fd[0].fd, buf, BUF_SIZE);
233 if (bytes_read < 0) {
234 printf("Error %d reading from %s\n",
235 fd[0].fd, PRINTER_FILE);
238 } else if (bytes_read > 0) {
239 /* Write data to standard OUTPUT (stdout). */
240 fwrite(buf, 1, bytes_read, stdout);
248 /* Close the device file. */
260 /* Open device file for printer gadget. */
261 fd[0].fd = open (PRINTER_FILE, O_RDWR);
263 printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
268 fd[0].events = POLLOUT | POLLWRNORM;
272 static char buf[BUF_SIZE];
273 /* Read data from standard INPUT (stdin). */
274 int bytes_read = fread(buf, 1, BUF_SIZE, stdin);
282 /* Wait for up to 1 second to sent data. */
283 retval = poll(fd, 1, 1000);
285 /* Write data to printer gadget driver. */
286 if (retval && (fd[0].revents & POLLWRNORM)) {
287 retval = write(fd[0].fd, buf, bytes_read);
289 printf("Error %d writing to %s\n",
295 bytes_read -= retval;
304 /* Wait until the data has been sent. */
307 /* Close the device file. */
315 read_NB_printer_data()
318 static char buf[BUF_SIZE];
321 /* Open device file for printer gadget. */
322 fd = open(PRINTER_FILE, O_RDWR|O_NONBLOCK);
324 printf("Error %d opening %s\n", fd, PRINTER_FILE);
330 /* Read data from printer gadget driver. */
331 bytes_read = read(fd, buf, BUF_SIZE);
332 if (bytes_read <= 0) {
336 /* Write data to standard OUTPUT (stdout). */
337 fwrite(buf, 1, bytes_read, stdout);
341 /* Close the device file. */
354 /* Open device file for printer gadget. */
355 fd = open(PRINTER_FILE, O_RDWR);
357 printf("Error %d opening %s\n", fd, PRINTER_FILE);
362 /* Make the IOCTL call. */
363 retval = ioctl(fd, GADGET_GET_PRINTER_STATUS);
365 fprintf(stderr, "ERROR: Failed to set printer status\n");
369 /* Close the device file. */
377 set_printer_status(unsigned char buf, int clear_printer_status_bit)
382 retval = get_printer_status();
384 fprintf(stderr, "ERROR: Failed to get printer status\n");
388 /* Open device file for printer gadget. */
389 fd = open(PRINTER_FILE, O_RDWR);
392 printf("Error %d opening %s\n", fd, PRINTER_FILE);
397 if (clear_printer_status_bit) {
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");
409 /* Close the device file. */
417 display_printer_status()
421 printer_status = get_printer_status();
422 if (printer_status < 0) {
423 fprintf(stderr, "ERROR: Failed to get printer status\n");
427 printf("Printer status is:\n");
428 if (printer_status & PRINTER_SELECTED) {
429 printf(" Printer is Selected\n");
431 printf(" Printer is NOT Selected\n");
433 if (printer_status & PRINTER_PAPER_EMPTY) {
434 printf(" Paper is Out\n");
436 printf(" Paper is Loaded\n");
438 if (printer_status & PRINTER_NOT_ERROR) {
439 printf(" Printer OK\n");
441 printf(" Printer ERROR\n");
449 main(int argc, char *argv[])
451 int i; /* Looping var */
460 for (i = 1; i < argc && !retval; i ++) {
462 if (argv[i][0] != '-') {
466 if (!strcmp(argv[i], "-get_status")) {
467 if (display_printer_status()) {
471 } else if (!strcmp(argv[i], "-paper_loaded")) {
472 if (set_printer_status(PRINTER_PAPER_EMPTY, 1)) {
476 } else if (!strcmp(argv[i], "-paper_out")) {
477 if (set_printer_status(PRINTER_PAPER_EMPTY, 0)) {
481 } else if (!strcmp(argv[i], "-selected")) {
482 if (set_printer_status(PRINTER_SELECTED, 0)) {
486 } else if (!strcmp(argv[i], "-not_selected")) {
487 if (set_printer_status(PRINTER_SELECTED, 1)) {
491 } else if (!strcmp(argv[i], "-error")) {
492 if (set_printer_status(PRINTER_NOT_ERROR, 1)) {
496 } else if (!strcmp(argv[i], "-no_error")) {
497 if (set_printer_status(PRINTER_NOT_ERROR, 0)) {
501 } else if (!strcmp(argv[i], "-read_data")) {
502 if (read_printer_data()) {
506 } else if (!strcmp(argv[i], "-write_data")) {
507 if (write_printer_data()) {
511 } else if (!strcmp(argv[i], "-NB_read_data")) {
512 if (read_NB_printer_data()) {