linux/Documentation/usb/gadget_printer.txt
<<
>>
Prefs
   1
   2                       Linux USB Printer Gadget Driver
   3                                 06/04/2007
   4
   5              Copyright (C) 2007 Craig W. Nadler <craig@nadler.us>
   6
   7
   8
   9GENERAL
  10=======
  11
  12This driver may be used if you are writing printer firmware using Linux as
  13the embedded OS. This driver has nothing to do with using a printer with
  14your Linux host system.
  15
  16You will need a USB device controller and a Linux driver for it that accepts
  17a gadget / "device class" driver using the Linux USB Gadget API. After the
  18USB device controller driver is loaded then load the printer gadget driver.
  19This will present a printer interface to the USB Host that your USB Device
  20port is connected to.
  21
  22This driver is structured for printer firmware that runs in user mode. The
  23user mode printer firmware will read and write data from the kernel mode
  24printer gadget driver using a device file. The printer returns a printer status
  25byte when the USB HOST sends a device request to get the printer status.  The
  26user space firmware can read or write this status byte using a device file
  27/dev/g_printer . Both blocking and non-blocking read/write calls are supported.
  28
  29
  30
  31
  32HOWTO USE THIS DRIVER
  33=====================
  34
  35To load the USB device controller driver and the printer gadget driver. The
  36following example uses the Netchip 2280 USB device controller driver:
  37
  38modprobe net2280
  39modprobe g_printer
  40
  41
  42The follow command line parameter can be used when loading the printer gadget
  43(ex: modprobe g_printer idVendor=0x0525 idProduct=0xa4a8 ):
  44
  45idVendor - This is the Vendor ID used in the device descriptor. The default is
  46        the Netchip vendor id 0x0525. YOU MUST CHANGE TO YOUR OWN VENDOR ID
  47        BEFORE RELEASING A PRODUCT. If you plan to release a product and don't
  48        already have a Vendor ID please see www.usb.org for details on how to
  49        get one.
  50
  51idProduct - This is the Product ID used in the device descriptor. The default
  52        is 0xa4a8, you should change this to an ID that's not used by any of
  53        your other USB products if you have any. It would be a good idea to
  54        start numbering your products starting with say 0x0001.
  55
  56bcdDevice - This is the version number of your product. It would be a good idea
  57        to put your firmware version here.
  58
  59iManufacturer - A string containing the name of the Vendor.
  60
  61iProduct - A string containing the Product Name.
  62
  63iSerialNum - A string containing the Serial Number. This should be changed for
  64        each unit of your product.
  65
  66iPNPstring -  The PNP ID string used for this printer. You will want to set
  67        either on the command line or hard code the PNP ID string used for
  68        your printer product.
  69
  70qlen - The number of 8k buffers to use per endpoint. The default is 10, you
  71        should tune this for your product. You may also want to tune the
  72        size of each buffer for your product.
  73
  74
  75
  76
  77USING THE EXAMPLE CODE
  78======================
  79
  80This example code talks to stdout, instead of a print engine.
  81
  82To compile the test code below:
  83
  841) save it to a file called prn_example.c
  852) compile the code with the follow command:
  86         gcc prn_example.c -o prn_example
  87
  88
  89
  90To read printer data from the host to stdout:
  91
  92        # prn_example -read_data
  93
  94
  95To write printer data from a file (data_file) to the host:
  96
  97        # cat data_file | prn_example -write_data
  98
  99
 100To get the current printer status for the gadget driver:
 101
 102        # prn_example -get_status
 103
 104        Printer status is:
 105             Printer is NOT Selected
 106             Paper is Out
 107             Printer OK
 108
 109
 110To set printer to Selected/On-line:
 111
 112        # prn_example -selected
 113
 114
 115To set printer to Not Selected/Off-line:
 116
 117        # prn_example -not_selected
 118
 119
 120To set paper status to paper out:
 121
 122        # prn_example -paper_out
 123
 124
 125To set paper status to paper loaded:
 126
 127        # prn_example -paper_loaded
 128
 129
 130To set error status to printer OK:
 131
 132        # prn_example -no_error
 133
 134
 135To set error status to ERROR:
 136
 137        # prn_example -error
 138
 139
 140
 141
 142EXAMPLE CODE
 143============
 144
 145
 146#include <stdio.h>
 147#include <stdlib.h>
 148#include <fcntl.h>
 149#include <linux/poll.h>
 150#include <sys/ioctl.h>
 151#include <linux/usb/g_printer.h>
 152
 153#define PRINTER_FILE                    "/dev/g_printer"
 154#define BUF_SIZE                        512
 155
 156
 157/*
 158 * 'usage()' - Show program usage.
 159 */
 160
 161static void
 162usage(const char *option)               /* I - Option string or NULL */
 163{
 164        if (option) {
 165                fprintf(stderr,"prn_example: Unknown option \"%s\"!\n",
 166                                option);
 167        }
 168
 169        fputs("\n", stderr);
 170        fputs("Usage: prn_example -[options]\n", stderr);
 171        fputs("Options:\n", stderr);
 172        fputs("\n", stderr);
 173        fputs("-get_status    Get the current printer status.\n", stderr);
 174        fputs("-selected      Set the selected status to selected.\n", stderr);
 175        fputs("-not_selected  Set the selected status to NOT selected.\n",
 176                        stderr);
 177        fputs("-error         Set the error status to error.\n", stderr);
 178        fputs("-no_error      Set the error status to NO error.\n", stderr);
 179        fputs("-paper_out     Set the paper status to paper out.\n", stderr);
 180        fputs("-paper_loaded  Set the paper status to paper loaded.\n",
 181                        stderr);
 182        fputs("-read_data     Read printer data from driver.\n", stderr);
 183        fputs("-write_data    Write printer sata to driver.\n", stderr);
 184        fputs("-NB_read_data  (Non-Blocking) Read printer data from driver.\n",
 185                        stderr);
 186        fputs("\n\n", stderr);
 187
 188        exit(1);
 189}
 190
 191
 192static int
 193read_printer_data()
 194{
 195        struct pollfd   fd[1];
 196
 197        /* Open device file for printer gadget. */
 198        fd[0].fd = open(PRINTER_FILE, O_RDWR);
 199        if (fd[0].fd < 0) {
 200                printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
 201                close(fd[0].fd);
 202                return(-1);
 203        }
 204
 205        fd[0].events = POLLIN | POLLRDNORM;
 206
 207        while (1) {
 208                static char buf[BUF_SIZE];
 209                int bytes_read;
 210                int retval;
 211
 212                /* Wait for up to 1 second for data. */
 213                retval = poll(fd, 1, 1000);
 214
 215                if (retval && (fd[0].revents & POLLRDNORM)) {
 216
 217                        /* Read data from printer gadget driver. */
 218                        bytes_read = read(fd[0].fd, buf, BUF_SIZE);
 219
 220                        if (bytes_read < 0) {
 221                                printf("Error %d reading from %s\n",
 222                                                fd[0].fd, PRINTER_FILE);
 223                                close(fd[0].fd);
 224                                return(-1);
 225                        } else if (bytes_read > 0) {
 226                                /* Write data to standard OUTPUT (stdout). */
 227                                fwrite(buf, 1, bytes_read, stdout);
 228                                fflush(stdout);
 229                        }
 230
 231                }
 232
 233        }
 234
 235        /* Close the device file. */
 236        close(fd[0].fd);
 237
 238        return 0;
 239}
 240
 241
 242static int
 243write_printer_data()
 244{
 245        struct pollfd   fd[1];
 246
 247        /* Open device file for printer gadget. */
 248        fd[0].fd = open (PRINTER_FILE, O_RDWR);
 249        if (fd[0].fd < 0) {
 250                printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
 251                close(fd[0].fd);
 252                return(-1);
 253        }
 254
 255        fd[0].events = POLLOUT | POLLWRNORM;
 256
 257        while (1) {
 258                int retval;
 259                static char buf[BUF_SIZE];
 260                /* Read data from standard INPUT (stdin). */
 261                int bytes_read = fread(buf, 1, BUF_SIZE, stdin);
 262
 263                if (!bytes_read) {
 264                        break;
 265                }
 266
 267                while (bytes_read) {
 268
 269                        /* Wait for up to 1 second to sent data. */
 270                        retval = poll(fd, 1, 1000);
 271
 272                        /* Write data to printer gadget driver. */
 273                        if (retval && (fd[0].revents & POLLWRNORM)) {
 274                                retval = write(fd[0].fd, buf, bytes_read);
 275                                if (retval < 0) {
 276                                        printf("Error %d writing to %s\n",
 277                                                        fd[0].fd,
 278                                                        PRINTER_FILE);
 279                                        close(fd[0].fd);
 280                                        return(-1);
 281                                } else {
 282                                        bytes_read -= retval;
 283                                }
 284
 285                        }
 286
 287                }
 288
 289        }
 290
 291        /* Wait until the data has been sent. */
 292        fsync(fd[0].fd);
 293
 294        /* Close the device file. */
 295        close(fd[0].fd);
 296
 297        return 0;
 298}
 299
 300
 301static int
 302read_NB_printer_data()
 303{
 304        int             fd;
 305        static char     buf[BUF_SIZE];
 306        int             bytes_read;
 307
 308        /* Open device file for printer gadget. */
 309        fd = open(PRINTER_FILE, O_RDWR|O_NONBLOCK);
 310        if (fd < 0) {
 311                printf("Error %d opening %s\n", fd, PRINTER_FILE);
 312                close(fd);
 313                return(-1);
 314        }
 315
 316        while (1) {
 317                /* Read data from printer gadget driver. */
 318                bytes_read = read(fd, buf, BUF_SIZE);
 319                if (bytes_read <= 0) {
 320                        break;
 321                }
 322
 323                /* Write data to standard OUTPUT (stdout). */
 324                fwrite(buf, 1, bytes_read, stdout);
 325                fflush(stdout);
 326        }
 327
 328        /* Close the device file. */
 329        close(fd);
 330
 331        return 0;
 332}
 333
 334
 335static int
 336get_printer_status()
 337{
 338        int     retval;
 339        int     fd;
 340
 341        /* Open device file for printer gadget. */
 342        fd = open(PRINTER_FILE, O_RDWR);
 343        if (fd < 0) {
 344                printf("Error %d opening %s\n", fd, PRINTER_FILE);
 345                close(fd);
 346                return(-1);
 347        }
 348
 349        /* Make the IOCTL call. */
 350        retval = ioctl(fd, GADGET_GET_PRINTER_STATUS);
 351        if (retval < 0) {
 352                fprintf(stderr, "ERROR: Failed to set printer status\n");
 353                return(-1);
 354        }
 355
 356        /* Close the device file. */
 357        close(fd);
 358
 359        return(retval);
 360}
 361
 362
 363static int
 364set_printer_status(unsigned char buf, int clear_printer_status_bit)
 365{
 366        int     retval;
 367        int     fd;
 368
 369        retval = get_printer_status();
 370        if (retval < 0) {
 371                fprintf(stderr, "ERROR: Failed to get printer status\n");
 372                return(-1);
 373        }
 374
 375        /* Open device file for printer gadget. */
 376        fd = open(PRINTER_FILE, O_RDWR);
 377
 378        if (fd < 0) {
 379                printf("Error %d opening %s\n", fd, PRINTER_FILE);
 380                close(fd);
 381                return(-1);
 382        }
 383
 384        if (clear_printer_status_bit) {
 385                retval &= ~buf;
 386        } else {
 387                retval |= buf;
 388        }
 389
 390        /* Make the IOCTL call. */
 391        if (ioctl(fd, GADGET_SET_PRINTER_STATUS, (unsigned char)retval)) {
 392                fprintf(stderr, "ERROR: Failed to set printer status\n");
 393                return(-1);
 394        }
 395
 396        /* Close the device file. */
 397        close(fd);
 398
 399        return 0;
 400}
 401
 402
 403static int
 404display_printer_status()
 405{
 406        char    printer_status;
 407
 408        printer_status = get_printer_status();
 409        if (printer_status < 0) {
 410                fprintf(stderr, "ERROR: Failed to get printer status\n");
 411                return(-1);
 412        }
 413
 414        printf("Printer status is:\n");
 415        if (printer_status & PRINTER_SELECTED) {
 416                printf("     Printer is Selected\n");
 417        } else {
 418                printf("     Printer is NOT Selected\n");
 419        }
 420        if (printer_status & PRINTER_PAPER_EMPTY) {
 421                printf("     Paper is Out\n");
 422        } else {
 423                printf("     Paper is Loaded\n");
 424        }
 425        if (printer_status & PRINTER_NOT_ERROR) {
 426                printf("     Printer OK\n");
 427        } else {
 428                printf("     Printer ERROR\n");
 429        }
 430
 431        return(0);
 432}
 433
 434
 435int
 436main(int  argc, char *argv[])
 437{
 438        int     i;              /* Looping var */
 439        int     retval = 0;
 440
 441        /* No Args */
 442        if (argc == 1) {
 443                usage(0);
 444                exit(0);
 445        }
 446
 447        for (i = 1; i < argc && !retval; i ++) {
 448
 449                if (argv[i][0] != '-') {
 450                        continue;
 451                }
 452
 453                if (!strcmp(argv[i], "-get_status")) {
 454                        if (display_printer_status()) {
 455                                retval = 1;
 456                        }
 457
 458                } else if (!strcmp(argv[i], "-paper_loaded")) {
 459                        if (set_printer_status(PRINTER_PAPER_EMPTY, 1)) {
 460                                retval = 1;
 461                        }
 462
 463                } else if (!strcmp(argv[i], "-paper_out")) {
 464                        if (set_printer_status(PRINTER_PAPER_EMPTY, 0)) {
 465                                retval = 1;
 466                        }
 467
 468                } else if (!strcmp(argv[i], "-selected")) {
 469                        if (set_printer_status(PRINTER_SELECTED, 0)) {
 470                                retval = 1;
 471                        }
 472
 473                } else if (!strcmp(argv[i], "-not_selected")) {
 474                        if (set_printer_status(PRINTER_SELECTED, 1)) {
 475                                retval = 1;
 476                        }
 477
 478                } else if (!strcmp(argv[i], "-error")) {
 479                        if (set_printer_status(PRINTER_NOT_ERROR, 1)) {
 480                                retval = 1;
 481                        }
 482
 483                } else if (!strcmp(argv[i], "-no_error")) {
 484                        if (set_printer_status(PRINTER_NOT_ERROR, 0)) {
 485                                retval = 1;
 486                        }
 487
 488                } else if (!strcmp(argv[i], "-read_data")) {
 489                        if (read_printer_data()) {
 490                                retval = 1;
 491                        }
 492
 493                } else if (!strcmp(argv[i], "-write_data")) {
 494                        if (write_printer_data()) {
 495                                retval = 1;
 496                        }
 497
 498                } else if (!strcmp(argv[i], "-NB_read_data")) {
 499                        if (read_NB_printer_data()) {
 500                                retval = 1;
 501                        }
 502
 503                } else {
 504                        usage(argv[i]);
 505                        retval = 1;
 506                }
 507        }
 508
 509        exit(retval);
 510}
 511