linux/Documentation/usb/gadget_printer.rst
<<
>>
Prefs
   1===============================
   2Linux USB Printer Gadget Driver
   3===============================
   4
   506/04/2007
   6
   7Copyright (C) 2007 Craig W. Nadler <craig@nadler.us>
   8
   9
  10
  11General
  12=======
  13
  14This driver may be used if you are writing printer firmware using Linux as
  15the embedded OS. This driver has nothing to do with using a printer with
  16your Linux host system.
  17
  18You will need a USB device controller and a Linux driver for it that accepts
  19a gadget / "device class" driver using the Linux USB Gadget API. After the
  20USB device controller driver is loaded then load the printer gadget driver.
  21This will present a printer interface to the USB Host that your USB Device
  22port is connected to.
  23
  24This driver is structured for printer firmware that runs in user mode. The
  25user mode printer firmware will read and write data from the kernel mode
  26printer gadget driver using a device file. The printer returns a printer status
  27byte when the USB HOST sends a device request to get the printer status.  The
  28user 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
  34Howto Use This Driver
  35=====================
  36
  37To load the USB device controller driver and the printer gadget driver. The
  38following example uses the Netchip 2280 USB device controller driver::
  39
  40        modprobe net2280
  41        modprobe g_printer
  42
  43
  44The follow command line parameter can be used when loading the printer gadget
  45(ex: modprobe g_printer idVendor=0x0525 idProduct=0xa4a8 ):
  46
  47idVendor
  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
  54idProduct
  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
  60bcdDevice
  61        This is the version number of your product. It would be a good idea
  62        to put your firmware version here.
  63
  64iManufacturer
  65        A string containing the name of the Vendor.
  66
  67iProduct
  68        A string containing the Product Name.
  69
  70iSerialNum
  71        A string containing the Serial Number. This should be changed for
  72        each unit of your product.
  73
  74iPNPstring
  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
  79qlen
  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
  87Using The Example Code
  88======================
  89
  90This example code talks to stdout, instead of a print engine.
  91
  92To compile the test code below:
  93
  941) save it to a file called prn_example.c
  952) compile the code with the follow command::
  96
  97         gcc prn_example.c -o prn_example
  98
  99
 100
 101To read printer data from the host to stdout::
 102
 103        # prn_example -read_data
 104
 105
 106To write printer data from a file (data_file) to the host::
 107
 108        # cat data_file | prn_example -write_data
 109
 110
 111To 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
 121To set printer to Selected/On-line::
 122
 123        # prn_example -selected
 124
 125
 126To set printer to Not Selected/Off-line::
 127
 128        # prn_example -not_selected
 129
 130
 131To set paper status to paper out::
 132
 133        # prn_example -paper_out
 134
 135
 136To set paper status to paper loaded::
 137
 138        # prn_example -paper_loaded
 139
 140
 141To set error status to printer OK::
 142
 143        # prn_example -no_error
 144
 145
 146To set error status to ERROR::
 147
 148        # prn_example -error
 149
 150
 151
 152
 153Example 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  }
 524