Merge tag 'linux-kselftest-kunit-fixes-5.11-rc3' of git://git.kernel.org/pub/scm...
[linux/fpc-iii.git] / Documentation / usb / gadget_printer.rst
blob5e5516c69075f323cfbe3ba2600296ab9e3e4da6
1 ===============================
2 Linux USB Printer Gadget Driver
3 ===============================
5 06/04/2007
7 Copyright (C) 2007 Craig W. Nadler <craig@nadler.us>
11 General
12 =======
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
22 port is connected to.
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.
34 Howto Use This Driver
35 =====================
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::
40         modprobe net2280
41         modprobe g_printer
44 The follow command line parameter can be used when loading the printer gadget
45 (ex: modprobe g_printer idVendor=0x0525 idProduct=0xa4a8 ):
47 idVendor
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.
54 idProduct
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.
60 bcdDevice
61         This is the version number of your product. It would be a good idea
62         to put your firmware version here.
64 iManufacturer
65         A string containing the name of the Vendor.
67 iProduct
68         A string containing the Product Name.
70 iSerialNum
71         A string containing the Serial Number. This should be changed for
72         each unit of your product.
74 iPNPstring
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.
79 qlen
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
115         Printer status is:
116              Printer is NOT Selected
117              Paper is Out
118              Printer OK
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::
148         # prn_example -error
153 Example Code
154 ============
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>
166   #define PRINTER_FILE                  "/dev/g_printer"
167   #define BUF_SIZE                      512
170   /*
171    * 'usage()' - Show program usage.
172    */
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         }
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);
201         exit(1);
202   }
205   static int
206   read_printer_data()
207   {
208         struct pollfd   fd[1];
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         }
218         fd[0].events = POLLIN | POLLRDNORM;
220         while (1) {
221                 static char buf[BUF_SIZE];
222                 int bytes_read;
223                 int retval;
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);
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                         }
244                 }
246         }
248         /* Close the device file. */
249         close(fd[0].fd);
251         return 0;
252   }
255   static int
256   write_printer_data()
257   {
258         struct pollfd   fd[1];
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         }
268         fd[0].events = POLLOUT | POLLWRNORM;
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);
276                 if (!bytes_read) {
277                         break;
278                 }
280                 while (bytes_read) {
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);
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                                 }
298                         }
300                 }
302         }
304         /* Wait until the data has been sent. */
305         fsync(fd[0].fd);
307         /* Close the device file. */
308         close(fd[0].fd);
310         return 0;
311   }
314   static int
315   read_NB_printer_data()
316   {
317         int             fd;
318         static char     buf[BUF_SIZE];
319         int             bytes_read;
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         }
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                 }
336                 /* Write data to standard OUTPUT (stdout). */
337                 fwrite(buf, 1, bytes_read, stdout);
338                 fflush(stdout);
339         }
341         /* Close the device file. */
342         close(fd);
344         return 0;
345   }
348   static int
349   get_printer_status()
350   {
351         int     retval;
352         int     fd;
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         }
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         }
369         /* Close the device file. */
370         close(fd);
372         return(retval);
373   }
376   static int
377   set_printer_status(unsigned char buf, int clear_printer_status_bit)
378   {
379         int     retval;
380         int     fd;
382         retval = get_printer_status();
383         if (retval < 0) {
384                 fprintf(stderr, "ERROR: Failed to get printer status\n");
385                 return(-1);
386         }
388         /* Open device file for printer gadget. */
389         fd = open(PRINTER_FILE, O_RDWR);
391         if (fd < 0) {
392                 printf("Error %d opening %s\n", fd, PRINTER_FILE);
393                 close(fd);
394                 return(-1);
395         }
397         if (clear_printer_status_bit) {
398                 retval &= ~buf;
399         } else {
400                 retval |= buf;
401         }
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         }
409         /* Close the device file. */
410         close(fd);
412         return 0;
413   }
416   static int
417   display_printer_status()
418   {
419         char    printer_status;
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         }
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         }
444         return(0);
445   }
448   int
449   main(int  argc, char *argv[])
450   {
451         int     i;              /* Looping var */
452         int     retval = 0;
454         /* No Args */
455         if (argc == 1) {
456                 usage(0);
457                 exit(0);
458         }
460         for (i = 1; i < argc && !retval; i ++) {
462                 if (argv[i][0] != '-') {
463                         continue;
464                 }
466                 if (!strcmp(argv[i], "-get_status")) {
467                         if (display_printer_status()) {
468                                 retval = 1;
469                         }
471                 } else if (!strcmp(argv[i], "-paper_loaded")) {
472                         if (set_printer_status(PRINTER_PAPER_EMPTY, 1)) {
473                                 retval = 1;
474                         }
476                 } else if (!strcmp(argv[i], "-paper_out")) {
477                         if (set_printer_status(PRINTER_PAPER_EMPTY, 0)) {
478                                 retval = 1;
479                         }
481                 } else if (!strcmp(argv[i], "-selected")) {
482                         if (set_printer_status(PRINTER_SELECTED, 0)) {
483                                 retval = 1;
484                         }
486                 } else if (!strcmp(argv[i], "-not_selected")) {
487                         if (set_printer_status(PRINTER_SELECTED, 1)) {
488                                 retval = 1;
489                         }
491                 } else if (!strcmp(argv[i], "-error")) {
492                         if (set_printer_status(PRINTER_NOT_ERROR, 1)) {
493                                 retval = 1;
494                         }
496                 } else if (!strcmp(argv[i], "-no_error")) {
497                         if (set_printer_status(PRINTER_NOT_ERROR, 0)) {
498                                 retval = 1;
499                         }
501                 } else if (!strcmp(argv[i], "-read_data")) {
502                         if (read_printer_data()) {
503                                 retval = 1;
504                         }
506                 } else if (!strcmp(argv[i], "-write_data")) {
507                         if (write_printer_data()) {
508                                 retval = 1;
509                         }
511                 } else if (!strcmp(argv[i], "-NB_read_data")) {
512                         if (read_NB_printer_data()) {
513                                 retval = 1;
514                         }
516                 } else {
517                         usage(argv[i]);
518                         retval = 1;
519                 }
520         }
522         exit(retval);
523   }