• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* sane - Scanner Access Now Easy.
2    Copyright (C) 1997 Andreas Czechanowski and David Mosberger
3    This file is part of the SANE package.
4 
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 
18    As a special exception, the authors of SANE give permission for
19    additional uses of the libraries contained in this release of SANE.
20 
21    The exception is that, if you link a SANE library with other files
22    to produce an executable, this does not by itself cause the
23    resulting executable to be covered by the GNU General Public
24    License.  Your use of that executable is in no way restricted on
25    account of linking the SANE library code into it.
26 
27    This exception does not, however, invalidate any other reasons why
28    the executable file might be covered by the GNU General Public
29    License.
30 
31    If you submit changes to SANE to the maintainers to be included in
32    a subsequent release, you agree by submitting the changes that
33    those changes may be distributed with this exception intact.
34 
35    If you write modifications of your own for SANE, it is your choice
36    whether to permit this exception to apply to your modifications.
37    If you do not wish that, delete this exception notice.
38 
39    This file implements the Mustek-proprietary SCSI-over-parallel-port
40    interface.  */
41 
42 #include "../include/sane/config.h"
43 
44 #ifdef HAVE_UNISTD_H
45 # include <unistd.h>
46 #endif
47 
48 #include <sys/types.h>
49 
50 #include "../include/sane/sanei_directio.h"
51 
52 #include "../include/sane/sane.h"
53 #include "../include/sane/sanei.h"
54 #include "../include/sane/sanei_ab306.h"
55 
56 #if (defined(HAVE_IOPERM) || defined(__FreeBSD__) || defined(__DragonFly__)) && !defined(IO_SUPPORT_MISSING)
57 
58 #include <errno.h>
59 #include <fcntl.h>
60 #include <limits.h>
61 #include <signal.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <sys/types.h>
66 #include <sys/wait.h>
67 #include <unistd.h>
68 
69 #include "../include/sane/saneopts.h"
70 
71 #define BACKEND_NAME sanei_ab306
72 #include "../include/sane/sanei_debug.h"
73 
74 #define PORT_DEV	"/dev/port"
75 #define AB306_CIO	0x379		/* control i/o port */
76 
77 #if defined(__FreeBSD__) || defined(__DragonFly__)
78 static int dev_io_fd = 0;
79 #endif
80 
81 typedef struct port
82   {
83     u_long	base;			/* i/o base address */
84     int		port_fd;		/* >= 0 when using /dev/port */
85     u_int	lstat;
86     u_int	in_use	      : 1,	/* port in use? */
87 		active	      : 1;	/* port was active at some point */
88   }
89 Port;
90 
91 static Port port[] =
92   {
93     {0x26b, -1, 0, 0, 0},
94     {0x2ab, -1, 0, 0, 0},
95     {0x2eb, -1, 0, 0, 0},
96     {0x22b, -1, 0, 0, 0},
97     {0x32b, -1, 0, 0, 0},
98     {0x36b, -1, 0, 0, 0},
99     {0x3ab, -1, 0, 0, 0},
100     {0x3eb, -1, 0, 0, 0}
101   };
102 
103 static const SANE_Byte wakeup[] =
104   {
105     0x47, 0x55, 0x54, 0x53, 0x02, 0x01, 0x80
106   };
107 
108 static u_char cdb_sizes[8] =
109   {
110     6, 10, 10, 12, 12, 12, 10, 10
111   };
112 #define CDB_SIZE(opcode)	cdb_sizes[(((opcode) >> 5) & 7)]
113 
114 static void
ab306_outb(Port * p,u_long addr,u_char val)115 ab306_outb (Port *p, u_long addr, u_char val)
116 {
117 
118   if (p->port_fd >= 0)
119     {
120       if ((u_long) lseek (p->port_fd, addr, SEEK_SET) != addr)
121 	return;
122       if (write (p->port_fd, &val, 1) != 1)
123 	return;
124     }
125   else
126     sanei_outb (addr, val);
127 }
128 
129 static int
ab306_inb(Port * p,u_long addr)130 ab306_inb (Port *p, u_long addr)
131 {
132   u_char ch;
133 
134   if (p->port_fd >= 0)
135     {
136       if ((u_long) lseek (p->port_fd, addr, SEEK_SET) != addr)
137 	return -1;
138       if (read (p->port_fd, &ch, 1) != 1)
139 	return -1;
140       return ch;
141     }
142   else
143     return sanei_inb (addr);
144 }
145 
146 /* Send a single command-byte over the AB306N-interface.  */
147 static void
ab306_cout(Port * p,int val)148 ab306_cout (Port *p, int val)
149 {
150   u_long base = p->base;
151 
152   while ((ab306_inb (p, base + 1) & 0x80));	/* wait for dir flag */
153   ab306_outb (p, base, val);
154   ab306_outb (p, base + 1, 0xe0);
155   while ((ab306_inb (p, base + 1) & 0x80) == 0);	/* wait for ack */
156   ab306_outb (p, base + 1, 0x60);
157 }
158 
159 /* Read a single response-byte from the SANEI_AB306N-interface.  */
160 static int
ab306_cin(Port * p)161 ab306_cin (Port *p)
162 {
163   u_long base = p->base;
164   u_char val;
165 
166   while ((ab306_inb (p, base + 1) & 0x80) == 0);	/* wait for dir flag */
167   val = ab306_inb (p, base);
168   ab306_outb (p, base + 1, 0xe0);			/* ack received byte */
169   while (ab306_inb (p, base + 1) & 0x80);
170   ab306_outb (p, base + 1, 0x60);			/* reset ack */
171   return val;
172 }
173 
174 static SANE_Status
ab306_write(Port * p,const void * buf,size_t len)175 ab306_write (Port *p, const void *buf, size_t len)
176 {
177   u_long base = p->base;
178   u_int i;
179   int cksum = 0;
180 
181   DBG(3, "ab306_write: waiting for scanner to be ready %02x\n",
182       ab306_inb (p, base + 1));
183   while ((ab306_inb (p, base + 1) & 0x20) == 0);
184   usleep (10000);
185 
186   DBG(4, "ab306_write: writing data\n");
187   for (i = 0; i < len; ++i)
188     {
189       ab306_cout (p, ((const u_char *) buf)[i]);
190       cksum += ((const u_char *) buf)[i];
191     }
192 
193   DBG(4, "ab306_write: writing checksum\n");
194   ab306_cout (p, -cksum & 0xff);
195 
196   DBG(3, "ab306_write: waiting for scanner to be NOT ready %02x\n",
197       ab306_inb (p, base + 1));
198   while ((ab306_inb (p, base + 1) & 0x20) != 0);
199   usleep (10000);
200 
201   DBG(4, "ab306_write: reading ack\n");
202   cksum = ab306_cin (p);
203   if (cksum != 0xa5)
204     {
205       DBG(0, "ab306_write: checksum error (%02x!=a5) when sending command!\n",
206 	  cksum);
207       return SANE_STATUS_IO_ERROR;
208     }
209   return SANE_STATUS_GOOD;
210 }
211 
212 /* Abort a running scan by pulling C6 low for a while.  */
213 static void
ab306_abort(Port * p)214 ab306_abort (Port *p)
215 {
216   ab306_outb (p, p->base + 1, 0x20);
217   while ((ab306_inb (p, p->base + 1) & 0x80));
218   ab306_outb (p, p->base + 1, 0x60);
219 }
220 
221 /* Open the device, <dev> must contain a valid port number (as string)
222    returns port number and I/O method in <*fdp> (not a file
223    descriptor) turns the scanner on setting C5 and C6.  */
224 SANE_Status
sanei_ab306_open(const char * dev,int * fdp)225 sanei_ab306_open (const char *dev, int *fdp)
226 {
227   static int first_time = 1;
228   SANE_Status status;
229   u_char byte;
230   u_long base;
231   char *end;
232   int i, j;
233 
234   if (first_time)
235     {
236       first_time = 0;
237       DBG_INIT();
238     }
239 
240   base = strtol (dev, &end, 0);
241   if (end == dev || *end)
242     {
243       DBG(1, "sanei_ab306_open: `%s' is not a valid port number\n", dev);
244       return SANE_STATUS_INVAL;
245     }
246 
247   for (i = 0; i < NELEMS(port); ++i)
248     if (port[i].base == base)
249       break;
250 
251   if (i >= NELEMS(port))
252     {
253       DBG(1, "sanei_ab306_open: %lx is not a valid base address\n", base);
254       return SANE_STATUS_INVAL;
255     }
256 
257   if (port[i].in_use)
258     {
259       DBG(1, "sanei_ab306_open: port %lx is already in use\n", base);
260       return SANE_STATUS_DEVICE_BUSY;
261     }
262 
263   status = sanei_ab306_get_io_privilege (i);
264 
265 #if defined(__FreeBSD__) || defined(__DragonFly__)
266   status = sanei_ab306_get_io_privilege (i);
267   if (status != SANE_STATUS_GOOD)
268     return status;
269 
270   DBG(1, "sanei_ab306_ioport: using inb/outb access\n");
271   for (j = 0; j < NELEMS(wakeup); ++j)
272     {
273       byte = wakeup[j];
274       if (j == NELEMS(wakeup) - 1)
275 	byte |= i;
276       sanei_outb (AB306_CIO, byte);
277     }
278 
279 #else /* !defined(__FreeBSD__) */
280   if (sanei_ioperm (AB306_CIO, 1, 1) != 0)
281     {
282       DBG(1, "sanei_ab306_ioport: using /dev/port access\n");
283       if (port[i].port_fd < 0)
284 	port[i].port_fd = open (PORT_DEV, O_RDWR);
285       if (port[i].port_fd < 0)
286 	return SANE_STATUS_IO_ERROR;
287       for (j = 0; j < NELEMS(wakeup); ++j)
288 	{
289 	  if (lseek (port[i].port_fd, AB306_CIO, SEEK_SET) != AB306_CIO)
290 	    return SANE_STATUS_IO_ERROR;
291 	  byte = wakeup[j];
292 	  if (j == NELEMS(wakeup) - 1)
293 	    byte |= i;
294 	  if (write (port[i].port_fd, &byte, 1) != 1)
295 	    return SANE_STATUS_IO_ERROR;
296 	}
297     }
298   else
299     {
300       DBG(1, "sanei_ab306_ioport: using inb/outb access\n");
301       for (j = 0; j < NELEMS(wakeup); ++j)
302 	{
303 	  byte = wakeup[j];
304 	  if (j == NELEMS(wakeup) - 1)
305 	    byte |= i;
306 	  sanei_outb (AB306_CIO, byte);
307 	}
308       status = sanei_ab306_get_io_privilege (i);
309       if (status != SANE_STATUS_GOOD)
310 	return status;
311     }
312 #endif /* !defined(__FreeBSD__) */
313 
314   ab306_outb (port + i, port[i].base + 1, 0x60);
315   port[i].in_use = 1;
316   port[i].active = 1;
317   *fdp = i;
318   return SANE_STATUS_GOOD;
319 }
320 
321 void
sanei_ab306_close(int fd)322 sanei_ab306_close (int fd)
323 {
324   Port *p = port + fd;
325 
326   if (p->in_use)
327     {
328       if (p->port_fd >= 0)
329 	{
330 	  close (p->port_fd);
331 	  p->port_fd = -1;
332 	}
333       p->in_use = 0;
334     }
335 }
336 
337 /* Get I/O permission to the configuration port and the desired
338    operating ports.  */
339 SANE_Status
sanei_ab306_get_io_privilege(int fd)340 sanei_ab306_get_io_privilege (int fd)
341 {
342   if (port[fd].port_fd < 0)
343     {
344 #if defined(__FreeBSD__) || defined(__DragonFly__)
345       if (dev_io_fd == 0)
346 	dev_io_fd = open ("/dev/io", O_RDONLY);
347       if (dev_io_fd < 0)
348         return SANE_STATUS_IO_ERROR;
349 #else /* !defined(__FreeBSD__) */
350       if (sanei_ioperm (port[fd].base, 3, 1) != 0)
351 	return SANE_STATUS_IO_ERROR;
352 #endif /* !defined(__FreeBSD__) */
353     }
354   return SANE_STATUS_GOOD;
355 }
356 
357 /* Send a command via the SANEI_AB306N-interface, get response when
358    <dst_size> is > 0.  */
359 SANE_Status
sanei_ab306_cmd(int fd,const void * src,size_t src_size,void * dst,size_t * dst_size)360 sanei_ab306_cmd (int fd, const void *src, size_t src_size,
361 		 void *dst, size_t * dst_size)
362 {
363   Port *p = port + fd;
364   const u_char *cp = src;
365   size_t cdb_size = CDB_SIZE(cp[0]);
366   SANE_Status status;
367   u_char byte;
368 
369   /* If this is a READ_SCANNED_DATA command, reset lstat: */
370   switch (cp[0])
371     {
372     case 0x08:	/* scsi READ_SCANNED_DATA command */
373       /* Initialize lstat to the current status, because we need bit 4
374 	 (0x10) as toggle bit for reading lines.  */
375       p->lstat = 0x34;
376       break;
377 
378     case 0x1b:	/* scsi START_STOP command */
379       if (!cp[4])
380 	{
381 	  /* it's a STOP */
382 	  ab306_abort (p);
383 	  return SANE_STATUS_GOOD;
384 	}
385       break;
386 
387     default:
388       break;
389     }
390 
391   status = ab306_write (p, src, 6);
392   if (status != SANE_STATUS_GOOD)
393     return status;
394 
395   if (src_size > cdb_size)
396     {
397       status = ab306_write (p, cp + cdb_size, src_size - cdb_size);
398       if (status != SANE_STATUS_GOOD)
399 	return status;
400     }
401 
402   if (dst && *dst_size > 0)
403     {
404       u_int i, cksum = 0;
405 
406       DBG(3, "sanei_ab306_cmd: waiting for scanner to be NOT ready %02x\n",
407 	  ab306_inb (p, p->base + 1));
408       while ((ab306_inb (p, p->base + 1) & 0x20) != 0);
409 
410       for (i = 0; i < *dst_size; i++)
411 	{
412 	  byte = ab306_cin (p);
413 	  cksum += byte;
414 	  ((u_char *) dst)[i] = byte;
415 	}
416       cksum += ab306_cin (p);		/* add in checksum */
417 
418       if ((cksum & 0xff) != 0)
419 	{
420 	  DBG(0, "sanei_ab306_cmd: checksum error (%2x!=0) when receiving "
421 	      "after command!\n", cksum);
422 	  return SANE_STATUS_IO_ERROR;
423 	}
424       ab306_cout (p, 0);		/* dummy byte (will be discarded) */
425     }
426   return SANE_STATUS_GOOD;
427 }
428 
429 /* Read scan-data from the AB306N-device. Read <lines> lines, of which
430    every one has <bpl> bytes.  */
431 SANE_Status
sanei_ab306_rdata(int fd,int planes,SANE_Byte * buf,int lines,int bpl)432 sanei_ab306_rdata (int fd, int planes, SANE_Byte * buf, int lines, int bpl)
433 {
434   Port *p = port + fd;
435   int lcnt, pcnt, bcnt, xmax;
436   int nstat;
437 
438   DBG(2, "sanei_ab306_rdata: start\n");
439 
440   /* lstat should be set by a call to sanei_ab306_init_toggle before ! */
441   while ((ab306_inb (p, p->base + 1) & 0x80) == 0);
442   /* the lines-loop: */
443   for (lcnt = 0; lcnt < lines; ++lcnt)
444     {
445       /* the planes-loop: */
446       for (pcnt = 0; pcnt < planes; ++pcnt)
447 	{
448 	  xmax = bpl / planes;
449 	  do
450 	    nstat = ab306_inb (p, p->base + 1);
451 	  while (((p->lstat ^ nstat) & 0x10) == 0);
452 
453 	  if (p->port_fd >= 0)
454 	    {
455 	      /* the pixel-loop: */
456 	      for (bcnt = 0; bcnt < xmax; bcnt++)
457 		{
458 		  if ((u_long) lseek (p->port_fd, p->base, SEEK_SET) != p->base)
459 		    return SANE_STATUS_IO_ERROR;
460 		  if (read (p->port_fd, buf, 1) != 1)
461 		    return SANE_STATUS_IO_ERROR;
462 		  ++buf;
463 		}
464 	    }
465 	  else
466 	    {
467 	      /* the pixel-loop: */
468 	      for (bcnt = 0; bcnt < xmax; bcnt++)
469 		{
470 		  *(u_char *) buf = sanei_inb (p->base);
471 		  ++buf;
472 		}
473 	    }
474 	  p->lstat = nstat;
475 	}
476     }
477   DBG(2, "sanei_ab306_rdata: done\n");
478   return SANE_STATUS_GOOD;
479 }
480 
481 void
sanei_ab306_exit(void)482 sanei_ab306_exit (void)
483 {
484   int i;
485 
486   for (i = 0; i < NELEMS(port); ++i)
487     if (port[i].active)
488       {
489 	port[i].active = 0;
490 	/* power off the scanner: */
491 	ab306_outb (port + i, port[i].base + 1, 0x00);
492       }
493 #if defined(__FreeBSD) || defined(__DragonFly__)
494   if (dev_io_fd >0)
495     close (dev_io_fd);
496 #endif /* defined(__FreeBSD__) */
497 }
498 
499 SANE_Status
sanei_ab306_test_ready(int fd)500 sanei_ab306_test_ready (int fd)
501 {
502   Port *p = port + fd;
503   u_char byte;
504 
505   byte = ab306_inb (p, p->base + 1);
506   if (byte & 0x20)
507     return SANE_STATUS_GOOD;
508 
509   return SANE_STATUS_DEVICE_BUSY;
510 }
511 
512 #else /* !HAVE_IOPERM */
513 
514 SANE_Status
sanei_ab306_open(const char * devname,int * fdp)515 sanei_ab306_open (const char *devname, int *fdp)
516 {
517   *fdp = -1;
518   return SANE_STATUS_INVAL;
519 }
520 
521 void
sanei_ab306_close(int fd)522 sanei_ab306_close (int fd)
523 {
524 }
525 
526 void
sanei_ab306_exit(void)527 sanei_ab306_exit (void)
528 {
529 }
530 
531 SANE_Status
sanei_ab306_get_io_privilege(int fd)532 sanei_ab306_get_io_privilege (int fd)
533 {
534   return SANE_STATUS_INVAL;
535 }
536 
537 SANE_Status
sanei_ab306_test_ready(int fd)538 sanei_ab306_test_ready (int fd)
539 {
540   return SANE_STATUS_GOOD;	/* non-existent device is always ready... */
541 }
542 
543 SANE_Status
sanei_ab306_cmd(int fd,const void * src,size_t src_size,void * dst,size_t * dst_size)544 sanei_ab306_cmd (int fd, const void *src, size_t src_size,
545 		 void *dst, size_t *dst_size)
546 {
547   return SANE_STATUS_INVAL;
548 }
549 
550 SANE_Status
sanei_ab306_rdata(int fd,int planes,SANE_Byte * buf,int lines,int bpl)551 sanei_ab306_rdata (int fd, int planes, SANE_Byte *buf, int lines, int bpl)
552 {
553   return SANE_STATUS_INVAL;
554 }
555 
556 #endif /* !HAVE_IOPERM */
557