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