About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog

Documentation / usb / gadget_printer.txt


Based on kernel version 4.16.1. Page generated on 2018-04-09 11:53 EST.

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


About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog