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/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel