• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* sane - Scanner Access Now Easy.
2    Copyright (C) 1998 Christian Bucher
3    Copyright (C) 1998 Kling & Hautzinger GmbH
4    This file is part of the SANE package.
5 
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <https://www.gnu.org/licenses/>.
18 
19    As a special exception, the authors of SANE give permission for
20    additional uses of the libraries contained in this release of SANE.
21 
22    The exception is that, if you link a SANE library with other files
23    to produce an executable, this does not by itself cause the
24    resulting executable to be covered by the GNU General Public
25    License.  Your use of that executable is in no way restricted on
26    account of linking the SANE library code into it.
27 
28    This exception does not, however, invalidate any other reasons why
29    the executable file might be covered by the GNU General Public
30    License.
31 
32    If you submit changes to SANE to the maintainers to be included in
33    a subsequent release, you agree by submitting the changes that
34    those changes may be distributed with this exception intact.
35 
36    If you write modifications of your own for SANE, it is your choice
37    whether to permit this exception to apply to your modifications.
38    If you do not wish that, delete this exception notice.
39 
40    This file implements the bi-directional parallel-port
41    interface.  */
42 
43 /*
44   RESTRICTIONS:
45 
46   - This interface is very timing sensitive, be careful with setting
47     debug levels.
48  */
49 
50 #include "../include/sane/config.h"
51 #include "../include/sane/sanei_directio.h"
52 /* pick up compatibility defs */
53 
54 #define BACKEND_NAME sanei_pio
55 #include "../include/sane/sanei_backend.h"		/* pick up compatibility defs */
56 
57 #ifdef HAVE_UNISTD_H
58 # include <unistd.h>
59 #endif
60 #include <sys/types.h>
61 
62 #include "../include/sane/sane.h"
63 #include "../include/sane/sanei.h"
64 #include "../include/sane/sanei_pio.h"
65 
66 #include <errno.h>
67 #include <fcntl.h>
68 #include <limits.h>
69 #include <signal.h>
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <string.h>
73 #include <sys/types.h>
74 #include <sys/wait.h>
75 #include <unistd.h>
76 #include <time.h>
77 
78 #include "../include/sane/saneopts.h"
79 
80 #define PORT_DEV	"/dev/port"
81 
82 /*    base    278 (lpt2)
83 
84               ioport  stat    ctrl
85       offs    0       1       2
86       len     1       1       1     */
87 
88 /* Port definitions (`N' at end begin of label means negated signal) */
89 
90 #define PIO_IOPORT		0	/* rel. addr io port      */
91 
92 #define PIO_STAT		1	/* rel. addr status port  */
93 #define PIO_STAT_BUSY		(1<<7)	/*  BUSY   Pin            */
94 #define PIO_STAT_NACKNLG	(1<<6)	/* ~ACKNLG Pin            */
95 
96 #define PIO_CTRL		2	/* rel. addr control port */
97 #define PIO_CTRL_IE		(1<<5)	/* Input enable           */
98 #define PIO_CTRL_IRQE		(1<<4)	/* enable IRQ             */
99 #define PIO_CTRL_DIR		(1<<3)	/* DIR pin, DIR=1 => out */
100 #define PIO_CTRL_NINIT		(1<<2)	/* reset output           */
101 #define PIO_CTRL_FDXT		(1<<1)	/* Paper FEED (unused)    */
102 #define PIO_CTRL_NSTROBE	(1<<0)	/* strobe pin             */
103 
104 #define PIO_APPLYRESET		2000	/* reset in 10us at init time  */
105 
106 #define DL40	 6
107 #define DL50	 7
108 #define DL60	 8
109 #define DL61	 9
110 #define DL70	10
111 #define DL71	11
112 
113 #ifdef NDEBUG
114 # define DBG_INIT()
115 #endif
116 
117 typedef struct
118   {
119     u_long base;		/* i/o base address */
120     int fd;			/* >= 0 when using /dev/port */
121     int max_time_seconds;/* forever if <= 0 */
122     u_int in_use;		/* port in use? */
123   }
124 PortRec, *Port;
125 
126 static PortRec port[] =
127   {
128     {0x378, -1, 0, 0},
129     {0x278, -1, 0, 0}
130   };
131 
132 extern int setuid (uid_t);
133 
134 static inline int pio_wait (const Port port, u_char val, u_char mask);
135 static inline void pio_ctrl (const Port port, u_char val);
136 static inline void pio_delay (const Port port);
137 static inline void pio_init (const Port port);
138 static void pio_reset (const Port port);
139 static int pio_write (const Port port, const u_char * buf, int n);
140 static int pio_read (const Port port, u_char * buf, int n);
141 static int pio_open (const char *dev, SANE_Status * status);
142 
143 static inline int
pio_wait(const Port port,u_char val,u_char mask)144 pio_wait (const Port port, u_char val, u_char mask)
145 {
146   int stat = 0;
147   long poll_count = 0;
148   time_t start = time(NULL);
149 
150   DBG (DL60, "wait on port 0x%03lx for %02x mask %02x\n",
151        port->base, (int) val, (int) mask);
152   DBG (DL61, "   BUSY    %s\n", (mask & PIO_STAT_BUSY) ?
153        (val & PIO_STAT_BUSY ? "on" : "off") : "-");
154   DBG (DL61, "   NACKNLG %s\n",
155        (mask & PIO_STAT_NACKNLG) ? (val & PIO_STAT_NACKNLG ? "on" : "off")
156        : "-");
157   for (;;)
158     {
159       ++poll_count;
160       stat = sanei_inb (port->base + PIO_STAT);
161       if ((stat & mask) == (val & mask))
162 	{
163 	  DBG (DL60, "got %02x after %ld tries\n", stat, poll_count);
164 	  DBG (DL61, "   BUSY    %s\n", stat & PIO_STAT_BUSY ? "on" : "off");
165 	  DBG (DL61, "   NACKNLG %s\n",
166 	       stat & PIO_STAT_NACKNLG ? "on" : "off");
167 
168 	  return stat;
169 	}
170       if(poll_count>1000)
171         {
172           if ((port->max_time_seconds>0) && (time(NULL)-start >= port->max_time_seconds))
173 	    break;
174           usleep(1);
175         }
176 
177     }
178   DBG (DL60, "got %02x aborting after %ld\n", stat, poll_count);
179   DBG (DL61, "   BUSY    %s\n", stat & PIO_STAT_BUSY ? "on" : "off");
180   DBG (DL61, "   NACKNLG %s\n", stat & PIO_STAT_NACKNLG ? "on" : "off");
181   DBG (1, "polling time out, abort\n");
182   exit (-1);
183 }
184 
185 static inline void
pio_ctrl(const Port port,u_char val)186 pio_ctrl (const Port port, u_char val)
187 {
188   DBG (DL60, "ctrl on port 0x%03lx %02x %02x\n",
189        port->base, (int) val, (int) val ^ PIO_CTRL_NINIT);
190 
191   val ^= PIO_CTRL_NINIT;
192 
193   DBG (DL61, "   IE      %s\n", val & PIO_CTRL_IE ? "on" : "off");
194   DBG (DL61, "   IRQE    %s\n", val & PIO_CTRL_IRQE ? "on" : "off");
195   DBG (DL61, "   DIR     %s\n", val & PIO_CTRL_DIR ? "on" : "off");
196   DBG (DL61, "   NINIT   %s\n", val & PIO_CTRL_NINIT ? "on" : "off");
197   DBG (DL61, "   FDXT    %s\n", val & PIO_CTRL_FDXT ? "on" : "off");
198   DBG (DL61, "   NSTROBE %s\n", val & PIO_CTRL_NSTROBE ? "on" : "off");
199 
200   sanei_outb (port->base + PIO_CTRL, val);
201 
202   return;
203 }
204 
205 static inline void
pio_delay(const Port port)206 pio_delay (const Port port)
207 {
208   sanei_inb (port->base + PIO_STAT);	/* delay */
209 
210   return;
211 }
212 
213 static inline void
pio_init(const Port port)214 pio_init (const Port port)
215 {
216   pio_ctrl (port, PIO_CTRL_IE);
217   return;
218 }
219 
220 static void
pio_reset(const Port port)221 pio_reset (const Port port)
222 {
223   int n;
224 
225   DBG (DL40, "reset\n");
226 
227   for (n = PIO_APPLYRESET; --n >= 0;)
228     {
229       sanei_outb (port->base + PIO_CTRL,
230 		 (PIO_CTRL_IE | PIO_CTRL_NINIT) ^ PIO_CTRL_NINIT);
231     }
232   pio_init (port);
233 
234   DBG (DL40, "end reset\n");
235 
236   return;
237 }
238 
239 static int
pio_write(const Port port,const u_char * buf,int n)240 pio_write (const Port port, const u_char * buf, int n)
241 {
242   int k;
243 
244   DBG (DL40, "write\n");
245 
246   pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
247   pio_ctrl (port, PIO_CTRL_DIR | PIO_CTRL_IE);		/* praeoutput */
248   pio_wait (port, PIO_STAT_NACKNLG, PIO_STAT_NACKNLG);	/* acknlg */
249   pio_ctrl (port, PIO_CTRL_DIR);			/* output */
250 
251   for (k = 0; k < n; k++, buf++)
252     {
253       DBG (DL40, "write byte\n");
254 #ifdef HANDSHAKE_BUSY
255       pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
256 #else
257       pio_wait (port, PIO_STAT_BUSY | PIO_STAT_NACKNLG,
258 		PIO_STAT_BUSY | PIO_STAT_NACKNLG);	/* busyack */
259 #endif
260       DBG (DL60, "out  %02x\n", (int) *buf);
261 
262       sanei_outb (port->base + PIO_IOPORT, *buf);
263 
264       pio_delay (port);
265       pio_delay (port);
266       pio_delay (port);
267       pio_ctrl (port, PIO_CTRL_DIR | PIO_CTRL_NSTROBE);	/* outputstrobe */
268 
269       pio_delay (port);
270       pio_delay (port);
271       pio_delay (port);
272       pio_ctrl (port, PIO_CTRL_DIR);	/* output */
273 
274       pio_delay (port);
275       pio_delay (port);
276       pio_delay (port);
277 
278       DBG (DL40, "end write byte\n");
279     }
280 
281 #ifdef HANDSHAKE_BUSY
282   pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
283 #else
284   pio_wait (port, PIO_STAT_BUSY | PIO_STAT_NACKNLG,
285 	    PIO_STAT_BUSY | PIO_STAT_NACKNLG);	/* busyack */
286 #endif
287 
288   pio_ctrl (port, PIO_CTRL_DIR | PIO_CTRL_IE);	/* praeoutput */
289   DBG (DL40, "end write\n");
290   return k;
291 }
292 
293 static int
pio_read(const Port port,u_char * buf,int n)294 pio_read (const Port port, u_char * buf, int n)
295 {
296   int k;
297 
298   DBG (DL40, "read\n");
299 
300   pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
301   pio_ctrl (port, PIO_CTRL_IE);	/* input */
302 
303   for (k = 0; k < n; k++, buf++)
304     {
305       DBG (DL40, "read byte\n");
306 
307 #ifdef HANDSHAKE_BUSY
308       pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
309 #else
310       pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY | PIO_STAT_NACKNLG);
311       /* busynack */
312 #endif
313       pio_ctrl (port, PIO_CTRL_IE | PIO_CTRL_NSTROBE);	/* inputstrobe */
314 
315       pio_delay (port);
316       pio_delay (port);
317       pio_delay (port);
318       pio_ctrl (port, PIO_CTRL_IE);	/* input */
319 #ifdef HANDSHAKE_BUSY
320       pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
321 #else
322       pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY | PIO_STAT_NACKNLG);
323       /* busynack */
324 #endif
325 
326       *buf = sanei_inb (port->base + PIO_IOPORT);
327       DBG (DL60, "in   %02x\n", (int) *buf);
328       DBG (DL40, "end read byte\n");
329     }
330 
331   pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
332   pio_ctrl (port, PIO_CTRL_IE);	/* input */
333   DBG (DL40, "end read\n");
334   return k;
335 }
336 
337 /*
338      Open the device, <dev> must contain a valid port number (as string).
339  */
340 
341 static int
pio_open(const char * dev,SANE_Status * status)342 pio_open (const char *dev, SANE_Status * status)
343 {
344   static int first_time = 1;
345   u_long base;
346   int n;
347 
348   if (first_time)
349     {
350       first_time = 0;
351 
352       DBG_INIT ();
353       /* set root uid */
354       if (0 > setuid (0))
355 	{
356 	  DBG (1, "sanei_pio_open: setuid failed: errno = %d\n", errno);
357 	  *status = SANE_STATUS_INVAL;
358 	  return -1;
359 	}
360     }
361   /* read port number */
362   {
363     char *end;
364 
365     base = strtol (dev, &end, 0);
366 
367     if ((end == dev) || *end)
368       {
369 	DBG (1, "sanei_pio_open: `%s' is not a valid port number\n", dev);
370 	*status = SANE_STATUS_INVAL;
371 	return -1;
372       }
373   }
374 
375   if (0 == base)
376     {
377       DBG (1, "sanei_pio_open: 0x%03lx is not a valid base address\n", base);
378       *status = SANE_STATUS_INVAL;
379       return -1;
380     }
381 
382   for (n = 0; n < NELEMS (port); n++)
383     if (port[n].base == base)
384       break;
385 
386   if (NELEMS (port) <= n)
387     {
388       DBG (1, "sanei_pio_open: 0x%03lx is not a valid base address\n", base);
389       *status = SANE_STATUS_INVAL;
390       return -1;
391     }
392 
393   if (port[n].in_use)
394     {
395       DBG (1, "sanei_pio_open: port 0x%03lx is already in use\n", base);
396       *status = SANE_STATUS_DEVICE_BUSY;
397       return -1;
398     }
399   port[n].base = base;
400   port[n].fd = -1;
401   port[n].max_time_seconds = 10;
402   port[n].in_use = 1;
403 
404   if (sanei_ioperm (port[n].base, 3, 1))
405     {
406       DBG (1, "sanei_pio_open: cannot get io privilege for port 0x%03lx\n",
407 	   port[n].base);
408       *status = SANE_STATUS_IO_ERROR;
409       return -1;
410     }
411 
412   pio_reset (&port[n]);
413 
414   *status = SANE_STATUS_GOOD;
415   return n;
416 }
417 
418 SANE_Status
sanei_pio_open(const char * dev,int * fdp)419 sanei_pio_open (const char *dev, int *fdp)
420 {
421   SANE_Status status;
422 
423   *fdp = pio_open (dev, &status);
424   return status;
425 }
426 
427 void
sanei_pio_close(int fd)428 sanei_pio_close (int fd)
429 {
430   Port p = port + fd;
431 
432   if ((0 > fd) || (NELEMS (port) <= fd))
433     return;
434 
435   if (!p->in_use)
436     return;
437 
438   if (-1 != p->fd)
439     {
440       close (p->fd);
441       p->fd = -1;
442     }
443 
444   p->in_use = 0;
445 
446   return;
447 }
448 
449 int
sanei_pio_read(int fd,u_char * buf,int n)450 sanei_pio_read (int fd, u_char * buf, int n)
451 {
452   if ((0 > fd) || (NELEMS (port) <= fd))
453     return -1;
454 
455   if (!port[fd].in_use)
456     return -1;
457 
458   return pio_read (&port[fd], buf, n);
459 }
460 
461 int
sanei_pio_write(int fd,const u_char * buf,int n)462 sanei_pio_write (int fd, const u_char * buf, int n)
463 {
464   if ((0 > fd) || (NELEMS (port) <= fd))
465     return -1;
466 
467   if (!port[fd].in_use)
468     return -1;
469 
470   return pio_write (&port[fd], buf, n);
471 }
472