Merge tag 'mips_5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux
[sfrench/cifs-2.6.git] / Documentation / usb / gadget_printer.txt
1 ===============================
2 Linux USB Printer Gadget Driver
3 ===============================
4
5 06/04/2007
6
7 Copyright (C) 2007 Craig W. Nadler <craig@nadler.us>
8
9
10
11 General
12 =======
13
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.
17
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.
23
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.
30
31
32
33
34 Howto Use This Driver
35 =====================
36
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::
39
40         modprobe net2280
41         modprobe g_printer
42
43
44 The follow command line parameter can be used when loading the printer gadget
45 (ex: modprobe g_printer idVendor=0x0525 idProduct=0xa4a8 ):
46
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.
53
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.
59
60 bcdDevice
61         This is the version number of your product. It would be a good idea
62         to put your firmware version here.
63
64 iManufacturer
65         A string containing the name of the Vendor.
66
67 iProduct
68         A string containing the Product Name.
69
70 iSerialNum
71         A string containing the Serial Number. This should be changed for
72         each unit of your product.
73
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.
78
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.
83
84
85
86
87 Using The Example Code
88 ======================
89
90 This example code talks to stdout, instead of a print engine.
91
92 To compile the test code below:
93
94 1) save it to a file called prn_example.c
95 2) compile the code with the follow command::
96
97          gcc prn_example.c -o prn_example
98
99
100
101 To read printer data from the host to stdout::
102
103         # prn_example -read_data
104
105
106 To write printer data from a file (data_file) to the host::
107
108         # cat data_file | prn_example -write_data
109
110
111 To 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
121 To set printer to Selected/On-line::
122
123         # prn_example -selected
124
125
126 To set printer to Not Selected/Off-line::
127
128         # prn_example -not_selected
129
130
131 To set paper status to paper out::
132
133         # prn_example -paper_out
134
135
136 To set paper status to paper loaded::
137
138         # prn_example -paper_loaded
139
140
141 To set error status to printer OK::
142
143         # prn_example -no_error
144
145
146 To set error status to ERROR::
147
148         # prn_example -error
149
150
151
152
153 Example 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   }