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