Back to home page

OSCL-LXR

 
 

    


0001 ===============================
0002 Linux USB Printer Gadget Driver
0003 ===============================
0004 
0005 06/04/2007
0006 
0007 Copyright (C) 2007 Craig W. Nadler <craig@nadler.us>
0008 
0009 
0010 
0011 General
0012 =======
0013 
0014 This driver may be used if you are writing printer firmware using Linux as
0015 the embedded OS. This driver has nothing to do with using a printer with
0016 your Linux host system.
0017 
0018 You will need a USB device controller and a Linux driver for it that accepts
0019 a gadget / "device class" driver using the Linux USB Gadget API. After the
0020 USB device controller driver is loaded then load the printer gadget driver.
0021 This will present a printer interface to the USB Host that your USB Device
0022 port is connected to.
0023 
0024 This driver is structured for printer firmware that runs in user mode. The
0025 user mode printer firmware will read and write data from the kernel mode
0026 printer gadget driver using a device file. The printer returns a printer status
0027 byte when the USB HOST sends a device request to get the printer status.  The
0028 user space firmware can read or write this status byte using a device file
0029 /dev/g_printer . Both blocking and non-blocking read/write calls are supported.
0030 
0031 
0032 
0033 
0034 Howto Use This Driver
0035 =====================
0036 
0037 To load the USB device controller driver and the printer gadget driver. The
0038 following example uses the Netchip 2280 USB device controller driver::
0039 
0040         modprobe net2280
0041         modprobe g_printer
0042 
0043 
0044 The follow command line parameter can be used when loading the printer gadget
0045 (ex: modprobe g_printer idVendor=0x0525 idProduct=0xa4a8 ):
0046 
0047 idVendor
0048         This is the Vendor ID used in the device descriptor. The default is
0049         the Netchip vendor id 0x0525. YOU MUST CHANGE TO YOUR OWN VENDOR ID
0050         BEFORE RELEASING A PRODUCT. If you plan to release a product and don't
0051         already have a Vendor ID please see www.usb.org for details on how to
0052         get one.
0053 
0054 idProduct
0055         This is the Product ID used in the device descriptor. The default
0056         is 0xa4a8, you should change this to an ID that's not used by any of
0057         your other USB products if you have any. It would be a good idea to
0058         start numbering your products starting with say 0x0001.
0059 
0060 bcdDevice
0061         This is the version number of your product. It would be a good idea
0062         to put your firmware version here.
0063 
0064 iManufacturer
0065         A string containing the name of the Vendor.
0066 
0067 iProduct
0068         A string containing the Product Name.
0069 
0070 iSerialNum
0071         A string containing the Serial Number. This should be changed for
0072         each unit of your product.
0073 
0074 iPNPstring
0075         The PNP ID string used for this printer. You will want to set
0076         either on the command line or hard code the PNP ID string used for
0077         your printer product.
0078 
0079 qlen
0080         The number of 8k buffers to use per endpoint. The default is 10, you
0081         should tune this for your product. You may also want to tune the
0082         size of each buffer for your product.
0083 
0084 
0085 
0086 
0087 Using The Example Code
0088 ======================
0089 
0090 This example code talks to stdout, instead of a print engine.
0091 
0092 To compile the test code below:
0093 
0094 1) save it to a file called prn_example.c
0095 2) compile the code with the follow command::
0096 
0097          gcc prn_example.c -o prn_example
0098 
0099 
0100 
0101 To read printer data from the host to stdout::
0102 
0103         # prn_example -read_data
0104 
0105 
0106 To write printer data from a file (data_file) to the host::
0107 
0108         # cat data_file | prn_example -write_data
0109 
0110 
0111 To get the current printer status for the gadget driver:::
0112 
0113         # prn_example -get_status
0114 
0115         Printer status is:
0116              Printer is NOT Selected
0117              Paper is Out
0118              Printer OK
0119 
0120 
0121 To set printer to Selected/On-line::
0122 
0123         # prn_example -selected
0124 
0125 
0126 To set printer to Not Selected/Off-line::
0127 
0128         # prn_example -not_selected
0129 
0130 
0131 To set paper status to paper out::
0132 
0133         # prn_example -paper_out
0134 
0135 
0136 To set paper status to paper loaded::
0137 
0138         # prn_example -paper_loaded
0139 
0140 
0141 To set error status to printer OK::
0142 
0143         # prn_example -no_error
0144 
0145 
0146 To set error status to ERROR::
0147 
0148         # prn_example -error
0149 
0150 
0151 
0152 
0153 Example Code
0154 ============
0155 
0156 ::
0157 
0158 
0159   #include <stdio.h>
0160   #include <stdlib.h>
0161   #include <fcntl.h>
0162   #include <linux/poll.h>
0163   #include <sys/ioctl.h>
0164   #include <linux/usb/g_printer.h>
0165 
0166   #define PRINTER_FILE                  "/dev/g_printer"
0167   #define BUF_SIZE                      512
0168 
0169 
0170   /*
0171    * 'usage()' - Show program usage.
0172    */
0173 
0174   static void
0175   usage(const char *option)             /* I - Option string or NULL */
0176   {
0177         if (option) {
0178                 fprintf(stderr,"prn_example: Unknown option \"%s\"!\n",
0179                                 option);
0180         }
0181 
0182         fputs("\n", stderr);
0183         fputs("Usage: prn_example -[options]\n", stderr);
0184         fputs("Options:\n", stderr);
0185         fputs("\n", stderr);
0186         fputs("-get_status    Get the current printer status.\n", stderr);
0187         fputs("-selected      Set the selected status to selected.\n", stderr);
0188         fputs("-not_selected  Set the selected status to NOT selected.\n",
0189                         stderr);
0190         fputs("-error         Set the error status to error.\n", stderr);
0191         fputs("-no_error      Set the error status to NO error.\n", stderr);
0192         fputs("-paper_out     Set the paper status to paper out.\n", stderr);
0193         fputs("-paper_loaded  Set the paper status to paper loaded.\n",
0194                         stderr);
0195         fputs("-read_data     Read printer data from driver.\n", stderr);
0196         fputs("-write_data    Write printer sata to driver.\n", stderr);
0197         fputs("-NB_read_data  (Non-Blocking) Read printer data from driver.\n",
0198                         stderr);
0199         fputs("\n\n", stderr);
0200 
0201         exit(1);
0202   }
0203 
0204 
0205   static int
0206   read_printer_data()
0207   {
0208         struct pollfd   fd[1];
0209 
0210         /* Open device file for printer gadget. */
0211         fd[0].fd = open(PRINTER_FILE, O_RDWR);
0212         if (fd[0].fd < 0) {
0213                 printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
0214                 close(fd[0].fd);
0215                 return(-1);
0216         }
0217 
0218         fd[0].events = POLLIN | POLLRDNORM;
0219 
0220         while (1) {
0221                 static char buf[BUF_SIZE];
0222                 int bytes_read;
0223                 int retval;
0224 
0225                 /* Wait for up to 1 second for data. */
0226                 retval = poll(fd, 1, 1000);
0227 
0228                 if (retval && (fd[0].revents & POLLRDNORM)) {
0229 
0230                         /* Read data from printer gadget driver. */
0231                         bytes_read = read(fd[0].fd, buf, BUF_SIZE);
0232 
0233                         if (bytes_read < 0) {
0234                                 printf("Error %d reading from %s\n",
0235                                                 fd[0].fd, PRINTER_FILE);
0236                                 close(fd[0].fd);
0237                                 return(-1);
0238                         } else if (bytes_read > 0) {
0239                                 /* Write data to standard OUTPUT (stdout). */
0240                                 fwrite(buf, 1, bytes_read, stdout);
0241                                 fflush(stdout);
0242                         }
0243 
0244                 }
0245 
0246         }
0247 
0248         /* Close the device file. */
0249         close(fd[0].fd);
0250 
0251         return 0;
0252   }
0253 
0254 
0255   static int
0256   write_printer_data()
0257   {
0258         struct pollfd   fd[1];
0259 
0260         /* Open device file for printer gadget. */
0261         fd[0].fd = open (PRINTER_FILE, O_RDWR);
0262         if (fd[0].fd < 0) {
0263                 printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
0264                 close(fd[0].fd);
0265                 return(-1);
0266         }
0267 
0268         fd[0].events = POLLOUT | POLLWRNORM;
0269 
0270         while (1) {
0271                 int retval;
0272                 static char buf[BUF_SIZE];
0273                 /* Read data from standard INPUT (stdin). */
0274                 int bytes_read = fread(buf, 1, BUF_SIZE, stdin);
0275 
0276                 if (!bytes_read) {
0277                         break;
0278                 }
0279 
0280                 while (bytes_read) {
0281 
0282                         /* Wait for up to 1 second to sent data. */
0283                         retval = poll(fd, 1, 1000);
0284 
0285                         /* Write data to printer gadget driver. */
0286                         if (retval && (fd[0].revents & POLLWRNORM)) {
0287                                 retval = write(fd[0].fd, buf, bytes_read);
0288                                 if (retval < 0) {
0289                                         printf("Error %d writing to %s\n",
0290                                                         fd[0].fd,
0291                                                         PRINTER_FILE);
0292                                         close(fd[0].fd);
0293                                         return(-1);
0294                                 } else {
0295                                         bytes_read -= retval;
0296                                 }
0297 
0298                         }
0299 
0300                 }
0301 
0302         }
0303 
0304         /* Wait until the data has been sent. */
0305         fsync(fd[0].fd);
0306 
0307         /* Close the device file. */
0308         close(fd[0].fd);
0309 
0310         return 0;
0311   }
0312 
0313 
0314   static int
0315   read_NB_printer_data()
0316   {
0317         int             fd;
0318         static char     buf[BUF_SIZE];
0319         int             bytes_read;
0320 
0321         /* Open device file for printer gadget. */
0322         fd = open(PRINTER_FILE, O_RDWR|O_NONBLOCK);
0323         if (fd < 0) {
0324                 printf("Error %d opening %s\n", fd, PRINTER_FILE);
0325                 close(fd);
0326                 return(-1);
0327         }
0328 
0329         while (1) {
0330                 /* Read data from printer gadget driver. */
0331                 bytes_read = read(fd, buf, BUF_SIZE);
0332                 if (bytes_read <= 0) {
0333                         break;
0334                 }
0335 
0336                 /* Write data to standard OUTPUT (stdout). */
0337                 fwrite(buf, 1, bytes_read, stdout);
0338                 fflush(stdout);
0339         }
0340 
0341         /* Close the device file. */
0342         close(fd);
0343 
0344         return 0;
0345   }
0346 
0347 
0348   static int
0349   get_printer_status()
0350   {
0351         int     retval;
0352         int     fd;
0353 
0354         /* Open device file for printer gadget. */
0355         fd = open(PRINTER_FILE, O_RDWR);
0356         if (fd < 0) {
0357                 printf("Error %d opening %s\n", fd, PRINTER_FILE);
0358                 close(fd);
0359                 return(-1);
0360         }
0361 
0362         /* Make the IOCTL call. */
0363         retval = ioctl(fd, GADGET_GET_PRINTER_STATUS);
0364         if (retval < 0) {
0365                 fprintf(stderr, "ERROR: Failed to set printer status\n");
0366                 return(-1);
0367         }
0368 
0369         /* Close the device file. */
0370         close(fd);
0371 
0372         return(retval);
0373   }
0374 
0375 
0376   static int
0377   set_printer_status(unsigned char buf, int clear_printer_status_bit)
0378   {
0379         int     retval;
0380         int     fd;
0381 
0382         retval = get_printer_status();
0383         if (retval < 0) {
0384                 fprintf(stderr, "ERROR: Failed to get printer status\n");
0385                 return(-1);
0386         }
0387 
0388         /* Open device file for printer gadget. */
0389         fd = open(PRINTER_FILE, O_RDWR);
0390 
0391         if (fd < 0) {
0392                 printf("Error %d opening %s\n", fd, PRINTER_FILE);
0393                 close(fd);
0394                 return(-1);
0395         }
0396 
0397         if (clear_printer_status_bit) {
0398                 retval &= ~buf;
0399         } else {
0400                 retval |= buf;
0401         }
0402 
0403         /* Make the IOCTL call. */
0404         if (ioctl(fd, GADGET_SET_PRINTER_STATUS, (unsigned char)retval)) {
0405                 fprintf(stderr, "ERROR: Failed to set printer status\n");
0406                 return(-1);
0407         }
0408 
0409         /* Close the device file. */
0410         close(fd);
0411 
0412         return 0;
0413   }
0414 
0415 
0416   static int
0417   display_printer_status()
0418   {
0419         char    printer_status;
0420 
0421         printer_status = get_printer_status();
0422         if (printer_status < 0) {
0423                 fprintf(stderr, "ERROR: Failed to get printer status\n");
0424                 return(-1);
0425         }
0426 
0427         printf("Printer status is:\n");
0428         if (printer_status & PRINTER_SELECTED) {
0429                 printf("     Printer is Selected\n");
0430         } else {
0431                 printf("     Printer is NOT Selected\n");
0432         }
0433         if (printer_status & PRINTER_PAPER_EMPTY) {
0434                 printf("     Paper is Out\n");
0435         } else {
0436                 printf("     Paper is Loaded\n");
0437         }
0438         if (printer_status & PRINTER_NOT_ERROR) {
0439                 printf("     Printer OK\n");
0440         } else {
0441                 printf("     Printer ERROR\n");
0442         }
0443 
0444         return(0);
0445   }
0446 
0447 
0448   int
0449   main(int  argc, char *argv[])
0450   {
0451         int     i;              /* Looping var */
0452         int     retval = 0;
0453 
0454         /* No Args */
0455         if (argc == 1) {
0456                 usage(0);
0457                 exit(0);
0458         }
0459 
0460         for (i = 1; i < argc && !retval; i ++) {
0461 
0462                 if (argv[i][0] != '-') {
0463                         continue;
0464                 }
0465 
0466                 if (!strcmp(argv[i], "-get_status")) {
0467                         if (display_printer_status()) {
0468                                 retval = 1;
0469                         }
0470 
0471                 } else if (!strcmp(argv[i], "-paper_loaded")) {
0472                         if (set_printer_status(PRINTER_PAPER_EMPTY, 1)) {
0473                                 retval = 1;
0474                         }
0475 
0476                 } else if (!strcmp(argv[i], "-paper_out")) {
0477                         if (set_printer_status(PRINTER_PAPER_EMPTY, 0)) {
0478                                 retval = 1;
0479                         }
0480 
0481                 } else if (!strcmp(argv[i], "-selected")) {
0482                         if (set_printer_status(PRINTER_SELECTED, 0)) {
0483                                 retval = 1;
0484                         }
0485 
0486                 } else if (!strcmp(argv[i], "-not_selected")) {
0487                         if (set_printer_status(PRINTER_SELECTED, 1)) {
0488                                 retval = 1;
0489                         }
0490 
0491                 } else if (!strcmp(argv[i], "-error")) {
0492                         if (set_printer_status(PRINTER_NOT_ERROR, 1)) {
0493                                 retval = 1;
0494                         }
0495 
0496                 } else if (!strcmp(argv[i], "-no_error")) {
0497                         if (set_printer_status(PRINTER_NOT_ERROR, 0)) {
0498                                 retval = 1;
0499                         }
0500 
0501                 } else if (!strcmp(argv[i], "-read_data")) {
0502                         if (read_printer_data()) {
0503                                 retval = 1;
0504                         }
0505 
0506                 } else if (!strcmp(argv[i], "-write_data")) {
0507                         if (write_printer_data()) {
0508                                 retval = 1;
0509                         }
0510 
0511                 } else if (!strcmp(argv[i], "-NB_read_data")) {
0512                         if (read_NB_printer_data()) {
0513                                 retval = 1;
0514                         }
0515 
0516                 } else {
0517                         usage(argv[i]);
0518                         retval = 1;
0519                 }
0520         }
0521 
0522         exit(retval);
0523   }