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

Reply via email to