Thanks for refreshing that, Craig. I was cleaning out some mail and found previous versions. Maybe it's finally time to merge. :)
On Monday 23 April 2007, Craig W. Nadler wrote: > diff -Nru a/Documentation/usb/gadget_printer.txt > b/Documentation/usb/gadget_printer.txt > --- a/Documentation/usb/gadget_printer.txt 1969-12-31 19:00:00.000000000 > -0500 > +++ b/Documentation/usb/gadget_printer.txt 2007-03-05 14:42:48.000000000 > -0500 > +GENERAL > +======= > + > ... > + > +This driver is structured for printer firmware that runs in user mode. The > +user mode printer firmware will read and write data from the kernel mode > +printer gadget driver using a device file. The printer returns a printer > status > +byte when the USB HOST sends a device request to get the printer status. The > +user space firmware can read or write this status byte using a device file. > +All the read and write calls for this printer gadget driver are non-blocking. > +If there is no room to write more data or no more data to read the system > calls > +with return 0. It's more conventional to require O_NONBLOCK and support a bunch of other conventions. ISTR that a nonblocking read without data should report -EAGAIN, not zero ... one expects poll() and select() to work too, also SIGIO and friends. > +HOWTO USE THIS DRIVER > +===================== > + > +To create the device files for the USB printer gadget > + > +mknod /dev/glp0 c 300 0 > +mknod /dev/glp0_status c 300 1 That part should be automated by udev/mdev ... is there any reason the old manual style mknod would be required? And where does major 300 come from? > + > +EXAMPLE CODE > +============ > + > + The following is an example of how to read data from the printer gadget > +from a user space application. > + > + > +********************************* CUT HERE ********************************** > +#include <stdio.h> > +#include <fcntl.h> > + > +#define PRINTER_DATA_FILE "/dev/glp0" > +#define BUF_SIZE 512 > + > +main () > +{ > + int fd = open(PRINTER_DATA_FILE, O_RDWR); Presumably the printer status reported will be on the order of "not ready" until the read() below is posted? > + if (fd < 0) { > + printf("Error %d opening %s\n", fd, PRINTER_DATA_FILE); > + close (fd); > + return; > + } > + while (1) { > + static char buf[BUF_SIZE]; > + int bytes_read; > + > + bytes_read = read (fd, buf, BUF_SIZE); > + if (bytes_read) { > + fwrite (buf, 1, bytes_read, stdout); > + fflush (stdout); > + } else { > + usleep (10000); Much better would be just blocking the read, or a poll() or select()... waiting ten seconds between reads is excessive! I'd expect to be able to spit several short jobs at the printer without delays. > + } > + } > + > + close(fd); > +} > +********************************* CUT HERE ********************************** > + > + > + > + > + > + The following is an example of how to write data to the printer gadget > +from a user space application. > + > +********************************* CUT HERE ********************************** > +#include <stdio.h> > +#include <fcntl.h> > + > +#define PRINTER_DATA_FILE "/dev/glp0" > +#define BUF_SIZE 512 > + > +main () > +{ > + int fd = open(PRINTER_DATA_FILE, O_RDWR); > + > + if (fd < 0) { > + printf("Error %d opening %s\n", fd, PRINTER_DATA_FILE); > + close (fd); > + return; > + } > + while (1) { > + static char buf[BUF_SIZE]; > + int bytes_read = fread (buf, 1, BUF_SIZE, stdin); > + > + if (!bytes_read) break; > + > + while (bytes_read) { > + bytes_read -= write (fd, buf, bytes_read); > + } > + } > + > + close(fd); > +} > +********************************* CUT HERE ********************************** > + > + > + > + > + > + The following is an example of how to get the printer status from a user > +space application. See the USB Printer Class Spec. for the get printer status > +device request. > + > +********************************* CUT HERE ********************************** > +#include <stdio.h> > +#include <fcntl.h> > + > +#define PRINTER_DATA_FILE "/dev/glp0_status" > + > +main () > +{ > + char buf; > + int bytes_read; > + int fd = open(PRINTER_DATA_FILE, O_RDWR); > + > + if (fd < 0) { > + printf("Error %d opening %s\n", fd, PRINTER_DATA_FILE); > + close (fd); > + return; > + } > + > + bytes_read = read (fd, &buf, 1); > + if (bytes_read == 1) { > + fwrite (&buf, 1, 1, stdout); > + fflush (stdout); > + } > + > + close(fd); > +} > +********************************* CUT HERE ********************************** > + > + > + > + > + > + The following is an example of how to set the printer status from a user > +space application. See the USB Printer Class Spec. for the get printer > status > +device request. > + > +********************************* CUT HERE ********************************** > +#include <stdio.h> > +#include <fcntl.h> > + > +#define PRINTER_DATA_FILE "/dev/glp0_status" > + > +main () > +{ > + char buf; > + int bytes_read; > + int fd = open(PRINTER_DATA_FILE, O_RDWR); > + > + if (fd < 0) { > + printf("Error %d opening %s\n", fd, PRINTER_DATA_FILE); > + close (fd); > + return; > + } > + > + bytes_read = fread (&buf, 1, 1, stdin); > + if (bytes_read == 1) > + write (fd, &buf, 1); > + > + close(fd); > +} > +********************************* CUT HERE ********************************** Hmm, I'd much rather have one integrated program than all those small examples. That may well be my personal taste -- unit test cases are also handy! -- but I'd sure rather see something at the level of "collect print job and report status" as an example. (Right, that may not be meaningful here; my point is more about a meaningful highlevel task, vs. a toolkit.) > diff -Nru a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig > --- a/drivers/usb/gadget/Kconfig 2007-02-20 01:34:32.000000000 -0500 > +++ b/drivers/usb/gadget/Kconfig 2007-03-05 14:42:48.000000000 -0500 > @@ -418,6 +418,17 @@ > Say "y" to link the driver statically, or "m" to build a > dynamically linked module called "g_midi". > > +config USB_G_PRINTER > + tristate "Printer Gadget" > + help > + The Printer Gadget channels data between it's USB printer interface ... "between its" ... What's missing in this description is: where's the printer hardware. I think you mean to say that the gadget channels data between the host and a userspace program driving the print engine. > + and a device file. A user space program can be used to read and > + write this device file to receive or send printer data. If you'd > + perfer to handle the printer data in Kernel space there is a "prefer". > + compile time option for using an API instead of device files. Hmm, the docs didn't mention that in-kernel API. I've seen maybe three different printer gadget drivers at various times. This is the only one with an in-kernel option. (Of the two others, one has been turned into a large-format printer from HP, and I forget about the other one.) > + > + Say "y" to link the driver statically, or "m" to build a > + dynamically linked module called "g_printer". > > # put drivers that need isochronous transfer support (for audio > # or video class gadget drivers), or specific hardware, here. > diff -Nru a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile > --- a/drivers/usb/gadget/Makefile 2007-02-20 01:34:32.000000000 -0500 > +++ b/drivers/usb/gadget/Makefile 2007-03-05 14:47:18.000000000 -0500 > @@ -19,6 +19,8 @@ > gadgetfs-objs := inode.o > g_file_storage-objs := file_storage.o usbstring.o config.o \ > epautoconf.o > +g_printer-objs := printer.o usbstring.o config.o \ > + epautoconf.o > > ifeq ($(CONFIG_USB_ETH_RNDIS),y) > g_ether-objs += rndis.o > @@ -29,5 +31,6 @@ > obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o > obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o > obj-$(CONFIG_USB_G_SERIAL) += g_serial.o > +obj-$(CONFIG_USB_G_PRINTER) += g_printer.o > obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o > OK, so far so good. I'll stop my review right there, at least for now, since it's late and the rest would require more time. I did a refresh against 2.6.21-rc7, and quilt told me this file has LOTS of end-of-line whitespace to remove, though. :) - Dave ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/ _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel