• Linux USB Printer Gadget Driver


    通用

    如果您正在使用Linux作为嵌入式操作系统编写打印机固件,则可能使用此驱动程序。这个驱动程序与在Linux主机系统上使用打印机没有任何关系。

    您将需要一个USB设备控制器和Linux驱动程序,它接受一个使用Linux USB gadget API的gadget/“设备类”驱动程序。加载USB设备控制器驱动后,再加载printer gadget驱动。这将向USB设备端口连接的USB主机提供printer接口。

    这个驱动程序是为在用户模式下运行的printer固件而设计的。用户模式printer固件将使用设备文件从内核模式printer gadget驱动程序读取和写入数据。当USB HOST发送获取打印机(printer)状态的设备请求时,打印机返回一个打印机状态字节。用户空间固件可以使用设备文件/dev/g_printer读取或写入这个状态字节。支持阻塞和非阻塞读写调用。

    如何使用这个驱动程序

    加载USB设备控制器驱动和打印机gadget驱动。以Netchip 2280 USB设备控制器驱动为例:

    modprobe net2280
    modprobe g_printer

    可以在加载打印机gadget时使用如下命令行参数(例如:modprobe g_printer idVendor=0x0525 idProduct=0xa4a8):

    idVendor

      这是设备描述符中使用的Vendor ID。默认是Netchip厂商id 0x0525。在发布产品之前,您必须更改为您自己的供应商id。如果您计划发布产品,但还没有供应商ID,请参阅www.usb.org了解如何获得供应商ID的详细信息。
    idProduct

      这是设备描述符中使用的Product ID。默认值是0xa4a8,您应该将其更改为一个不被任何其他USB产品使用的ID(如果您有任何USB产品)。从0x0001开始为产品编号是个好主意。

    bcdDevice

      这是您产品的版本号。把你的固件版本放在这里是个好主意。

    iManufacturer

      包含供应商名称的字符串

    iProduct

      包含产品名称的字符串。

    iSerialNum

      包含序列号的字符串。这应该为每个单位的产品而改变。

    iPNPstring

      用于此打印机的PNP ID字符串。您将希望在命令行或硬编码上设置用于打印机产品的PNP ID字符串。

    qlen

      每个端点要使用的8k缓冲区的数量。默认值是10,您应该针对您的产品进行优化。您可能还想为您的产品调整每个缓冲区的大小。

    使用示例代码

    此示例代码与标准输出对话,而不是与打印引擎对话。

    编译下面的测试代码:

    1. 将其保存到一个名为prn_example.c的文件中
    2. 用下面的命令编译代码:

     gcc prn_example.c -o prn_example 

    将打印机数据从主机读取到stdout:

    # prn_example -read_data

    将打印机数据从文件(data_file)写入主机:

    # cat data_file | prn_example -write_data

    要获取gadget驱动程序的当前打印机状态:

    # prn_example -get_status
    
    Printer status is:
         Printer is NOT Selected
         Paper is Out
         Printer OK

    将打印机设置为 Selected/On-line:

    # prn_example -selected

    将打印机设置为Not Selected/Off-line:

    # prn_example -not_selected

    将纸张状态设置为纸用完:

    # prn_example -paper_out

    将纸张状态设置为已载纸:

    # prn_example -paper_loaded

    将错误状态设置为打印机OK:

    # prn_example -no_error

    设置error状态为ERROR:

    # prn_example -error

    代码示例

    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <linux/poll.h>
    #include <sys/ioctl.h>
    #include <linux/usb/g_printer.h>
    
    #define PRINTER_FILE                  "/dev/g_printer"
    #define BUF_SIZE                      512
    
    
    /*
     * 'usage()' - Show program usage.
     */
    
    static void
    usage(const char *option)             /* I - Option string or NULL */
    {
          if (option) {
                  fprintf(stderr,"prn_example: Unknown option "%s"!
    ",
                                  option);
          }
    
          fputs("
    ", stderr);
          fputs("Usage: prn_example -[options]
    ", stderr);
          fputs("Options:
    ", stderr);
          fputs("
    ", stderr);
          fputs("-get_status    Get the current printer status.
    ", stderr);
          fputs("-selected      Set the selected status to selected.
    ", stderr);
          fputs("-not_selected  Set the selected status to NOT selected.
    ",
                          stderr);
          fputs("-error         Set the error status to error.
    ", stderr);
          fputs("-no_error      Set the error status to NO error.
    ", stderr);
          fputs("-paper_out     Set the paper status to paper out.
    ", stderr);
          fputs("-paper_loaded  Set the paper status to paper loaded.
    ",
                          stderr);
          fputs("-read_data     Read printer data from driver.
    ", stderr);
          fputs("-write_data    Write printer sata to driver.
    ", stderr);
          fputs("-NB_read_data  (Non-Blocking) Read printer data from driver.
    ",
                          stderr);
          fputs("
    
    ", stderr);
    
          exit(1);
    }
    
    
    static int
    read_printer_data()
    {
          struct pollfd   fd[1];
    
          /* Open device file for printer gadget. */
          fd[0].fd = open(PRINTER_FILE, O_RDWR);
          if (fd[0].fd < 0) {
                  printf("Error %d opening %s
    ", fd[0].fd, PRINTER_FILE);
                  close(fd[0].fd);
                  return(-1);
          }
    
          fd[0].events = POLLIN | POLLRDNORM;
    
          while (1) {
                  static char buf[BUF_SIZE];
                  int bytes_read;
                  int retval;
    
                  /* Wait for up to 1 second for data. */
                  retval = poll(fd, 1, 1000);
    
                  if (retval && (fd[0].revents & POLLRDNORM)) {
    
                          /* Read data from printer gadget driver. */
                          bytes_read = read(fd[0].fd, buf, BUF_SIZE);
    
                          if (bytes_read < 0) {
                                  printf("Error %d reading from %s
    ",
                                                  fd[0].fd, PRINTER_FILE);
                                  close(fd[0].fd);
                                  return(-1);
                          } else if (bytes_read > 0) {
                                  /* Write data to standard OUTPUT (stdout). */
                                  fwrite(buf, 1, bytes_read, stdout);
                                  fflush(stdout);
                          }
    
                  }
    
          }
    
          /* Close the device file. */
          close(fd[0].fd);
    
          return 0;
    }
    
    
    static int
    write_printer_data()
    {
          struct pollfd   fd[1];
    
          /* Open device file for printer gadget. */
          fd[0].fd = open (PRINTER_FILE, O_RDWR);
          if (fd[0].fd < 0) {
                  printf("Error %d opening %s
    ", fd[0].fd, PRINTER_FILE);
                  close(fd[0].fd);
                  return(-1);
          }
    
          fd[0].events = POLLOUT | POLLWRNORM;
    
          while (1) {
                  int retval;
                  static char buf[BUF_SIZE];
                  /* Read data from standard INPUT (stdin). */
                  int bytes_read = fread(buf, 1, BUF_SIZE, stdin);
    
                  if (!bytes_read) {
                          break;
                  }
    
                  while (bytes_read) {
    
                          /* Wait for up to 1 second to sent data. */
                          retval = poll(fd, 1, 1000);
    
                          /* Write data to printer gadget driver. */
                          if (retval && (fd[0].revents & POLLWRNORM)) {
                                  retval = write(fd[0].fd, buf, bytes_read);
                                  if (retval < 0) {
                                          printf("Error %d writing to %s
    ",
                                                          fd[0].fd,
                                                          PRINTER_FILE);
                                          close(fd[0].fd);
                                          return(-1);
                                  } else {
                                          bytes_read -= retval;
                                  }
    
                          }
    
                  }
    
          }
    
          /* Wait until the data has been sent. */
          fsync(fd[0].fd);
    
          /* Close the device file. */
          close(fd[0].fd);
    
          return 0;
    }
    
    
    static int
    read_NB_printer_data()
    {
          int             fd;
          static char     buf[BUF_SIZE];
          int             bytes_read;
    
          /* Open device file for printer gadget. */
          fd = open(PRINTER_FILE, O_RDWR|O_NONBLOCK);
          if (fd < 0) {
                  printf("Error %d opening %s
    ", fd, PRINTER_FILE);
                  close(fd);
                  return(-1);
          }
    
          while (1) {
                  /* Read data from printer gadget driver. */
                  bytes_read = read(fd, buf, BUF_SIZE);
                  if (bytes_read <= 0) {
                          break;
                  }
    
                  /* Write data to standard OUTPUT (stdout). */
                  fwrite(buf, 1, bytes_read, stdout);
                  fflush(stdout);
          }
    
          /* Close the device file. */
          close(fd);
    
          return 0;
    }
    
    
    static int
    get_printer_status()
    {
          int     retval;
          int     fd;
    
          /* Open device file for printer gadget. */
          fd = open(PRINTER_FILE, O_RDWR);
          if (fd < 0) {
                  printf("Error %d opening %s
    ", fd, PRINTER_FILE);
                  close(fd);
                  return(-1);
          }
    
          /* Make the IOCTL call. */
          retval = ioctl(fd, GADGET_GET_PRINTER_STATUS);
          if (retval < 0) {
                  fprintf(stderr, "ERROR: Failed to set printer status
    ");
                  return(-1);
          }
    
          /* Close the device file. */
          close(fd);
    
          return(retval);
    }
    
    
    static int
    set_printer_status(unsigned char buf, int clear_printer_status_bit)
    {
          int     retval;
          int     fd;
    
          retval = get_printer_status();
          if (retval < 0) {
                  fprintf(stderr, "ERROR: Failed to get printer status
    ");
                  return(-1);
          }
    
          /* Open device file for printer gadget. */
          fd = open(PRINTER_FILE, O_RDWR);
    
          if (fd < 0) {
                  printf("Error %d opening %s
    ", fd, PRINTER_FILE);
                  close(fd);
                  return(-1);
          }
    
          if (clear_printer_status_bit) {
                  retval &= ~buf;
          } else {
                  retval |= buf;
          }
    
          /* Make the IOCTL call. */
          if (ioctl(fd, GADGET_SET_PRINTER_STATUS, (unsigned char)retval)) {
                  fprintf(stderr, "ERROR: Failed to set printer status
    ");
                  return(-1);
          }
    
          /* Close the device file. */
          close(fd);
    
          return 0;
    }
    
    
    static int
    display_printer_status()
    {
          char    printer_status;
    
          printer_status = get_printer_status();
          if (printer_status < 0) {
                  fprintf(stderr, "ERROR: Failed to get printer status
    ");
                  return(-1);
          }
    
          printf("Printer status is:
    ");
          if (printer_status & PRINTER_SELECTED) {
                  printf("     Printer is Selected
    ");
          } else {
                  printf("     Printer is NOT Selected
    ");
          }
          if (printer_status & PRINTER_PAPER_EMPTY) {
                  printf("     Paper is Out
    ");
          } else {
                  printf("     Paper is Loaded
    ");
          }
          if (printer_status & PRINTER_NOT_ERROR) {
                  printf("     Printer OK
    ");
          } else {
                  printf("     Printer ERROR
    ");
          }
    
          return(0);
    }
    
    
    int
    main(int  argc, char *argv[])
    {
          int     i;              /* Looping var */
          int     retval = 0;
    
          /* No Args */
          if (argc == 1) {
                  usage(0);
                  exit(0);
          }
    
          for (i = 1; i < argc && !retval; i ++) {
    
                  if (argv[i][0] != '-') {
                          continue;
                  }
    
                  if (!strcmp(argv[i], "-get_status")) {
                          if (display_printer_status()) {
                                  retval = 1;
                          }
    
                  } else if (!strcmp(argv[i], "-paper_loaded")) {
                          if (set_printer_status(PRINTER_PAPER_EMPTY, 1)) {
                                  retval = 1;
                          }
    
                  } else if (!strcmp(argv[i], "-paper_out")) {
                          if (set_printer_status(PRINTER_PAPER_EMPTY, 0)) {
                                  retval = 1;
                          }
    
                  } else if (!strcmp(argv[i], "-selected")) {
                          if (set_printer_status(PRINTER_SELECTED, 0)) {
                                  retval = 1;
                          }
    
                  } else if (!strcmp(argv[i], "-not_selected")) {
                          if (set_printer_status(PRINTER_SELECTED, 1)) {
                                  retval = 1;
                          }
    
                  } else if (!strcmp(argv[i], "-error")) {
                          if (set_printer_status(PRINTER_NOT_ERROR, 1)) {
                                  retval = 1;
                          }
    
                  } else if (!strcmp(argv[i], "-no_error")) {
                          if (set_printer_status(PRINTER_NOT_ERROR, 0)) {
                                  retval = 1;
                          }
    
                  } else if (!strcmp(argv[i], "-read_data")) {
                          if (read_printer_data()) {
                                  retval = 1;
                          }
    
                  } else if (!strcmp(argv[i], "-write_data")) {
                          if (write_printer_data()) {
                                  retval = 1;
                          }
    
                  } else if (!strcmp(argv[i], "-NB_read_data")) {
                          if (read_NB_printer_data()) {
                                  retval = 1;
                          }
    
                  } else {
                          usage(argv[i]);
                          retval = 1;
                  }
          }
    
          exit(retval);
    }

    本文来自博客园,作者:王楼小子,转载请注明原文链接:https://www.cnblogs.com/wanglouxiaozi/p/15177262.html

  • 相关阅读:
    深入理解Guava Cache的refresh和expire刷新机制
    单机、分布式、集群的区别与联系
    理解Word2Vec
    Struts2 XML配置详解
    目标检测中的数据增强方法(附详细代码讲解)
    做笔记就用印象笔记,支持录音做笔记( 附剪藏 插件下载,一键将网页内容保存笔记中进行编辑)
    教你用OpenCV 和 Python给证件照换底色(蓝底 <->红底->白底)
    一招教你如何用Word直接打开PDF进行编辑,无需下载转换软件
    小白也能弄得懂的目标检测YOLO系列之YOLOv1网络训练
    小白也能弄懂的目标检测YOLO系列之YOLOV1
  • 原文地址:https://www.cnblogs.com/wanglouxiaozi/p/15177262.html
Copyright © 2020-2023  润新知