1 /*
2   Snapscan 1212U modifications for the Snapscan SANE backend
3 
4   Copyright (C) 2000 Henrik Johansson
5 
6   Henrik Johansson (henrikjo@post.urfors.se)
7 
8   This program is free software; you can redistribute it and/or
9   modify it under the terms of the GNU General Public License as
10   published by the Free Software Foundation; either version 2 of the
11   License, or (at your option) any later version.
12 
13   This program is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   General Public License for more details.
17 
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <https://www.gnu.org/licenses/>.
20 
21   As a special exception, the authors of SANE give permission for
22   additional uses of the libraries contained in this release of SANE.
23 
24   The exception is that, if you link a SANE library with other files
25   to produce an executable, this does not by itself cause the
26   resulting executable to be covered by the GNU General Public
27   License.  Your use of that executable is in no way restricted on
28   account of linking the SANE library code into it.
29 
30   This exception does not, however, invalidate any other reasons why
31   the executable file might be covered by the GNU General Public
32   License.
33 
34   If you submit changes to SANE to the maintainers to be included in
35   a subsequent release, you agree by submitting the changes that
36   those changes may be distributed with this exception intact.
37 
38   If you write modifications of your own for SANE, it is your choice
39   whether to permit this exception to apply to your modifications.
40   If you do not wish that, delete this exception notice.
41 
42   This file implements USB equivalents to the SCSI routines used by the Snapscan
43   backend.
44 
45   History
46 
47   0.1        2000-02-01
48 
49      First version released
50 
51   0.2   2000-02-12
52 
53      The Send Diagnostics SCSI command seems to hang some 1212U scanners.
54      Bypassing this command fixes the problem. This bug was reported by
55      Dmitri (dmitri@advantrix.com).
56 
57   0.3   2000-02-13
58 
59      The "Set window" command returns with status "Device busy" when the
60      scanner is busy. One consequence is that some frontends exits with an
61      error message if it's started when the scanner is warming up.
62      A solution was suggested by Dmitri (dmitri@advantrix.com)
63      The idea is that a SCSI command which returns "device busy" is stored
64      in a "TODO" queue. The send command function is modified to first send
65      commands in the queue before the intended command.
66      So far this strategy has worked flawlessly. Thanks Dmitri!
67 */
68 
69 /*
70    SnapScan backend scan data sources
71 */
72 
73 #include "snapscan-usb.h"
74 #include "snapscan-mutex.c"
75 
76 #ifndef SHM_R
77 #define SHM_R 0
78 #endif
79 
80 #ifndef SHM_W
81 #define SHM_W 0
82 #endif
83 
84 /* Global variables */
85 
86 static snapscan_mutex_t snapscan_mutex;
87 static sense_handler_type usb_sense_handler;
88 static void* usb_pss;
89 
90 struct urb_counters_t {
91     unsigned long read_urbs;
92     unsigned long write_urbs;
93 };
94 
95 static struct urb_counters_t* urb_counters = NULL;
96 
97 /* Forward declarations */
98 static SANE_Status usb_request_sense(SnapScan_Scanner *pss);
99 
snapscani_usb_cmd(int fd,const void * src,size_t src_size,void * dst,size_t * dst_size)100 static SANE_Status snapscani_usb_cmd(int fd, const void *src, size_t src_size,
101                     void *dst, size_t * dst_size)
102 {
103     static const char me[] = "snapscani_usb_cmd";
104     int status;
105 
106     DBG (DL_CALL_TRACE, "%s(%d,0x%lx,%lu,0x%lx,0x%lx (%lu))\n", me,
107          fd, (u_long) src,(u_long) src_size,(u_long) dst, (u_long) dst_size,(u_long) (dst_size ? *dst_size : 0));
108 
109     while(bqhead) {
110         status = atomic_usb_cmd(fd, bqhead->src, bqhead->src_size, NULL, NULL);
111         if(status == SANE_STATUS_DEVICE_BUSY) {
112             if(is_queueable(src)) {
113                 enqueue_bq(fd,src,src_size);
114                 return SANE_STATUS_GOOD;
115             } else {
116                 sleep(1);
117                 continue;
118             }
119         }
120         dequeue_bq();
121     }
122 
123     status = atomic_usb_cmd(fd,src,src_size,dst,dst_size);
124 
125     if ((status == SANE_STATUS_DEVICE_BUSY) && is_queueable(src) ) {
126         enqueue_bq(fd,src,src_size);
127         return SANE_STATUS_GOOD;
128     }
129 
130     return status;
131 }
132 
atomic_usb_cmd(int fd,const void * src,size_t src_size,void * dst,size_t * dst_size)133 static SANE_Status atomic_usb_cmd(int fd, const void *src, size_t src_size,
134                     void *dst, size_t * dst_size)
135 {
136     static const char me[] = "atomic_usb_cmd";
137 
138     int status;
139     sigset_t all,oldset;
140 
141     DBG (DL_CALL_TRACE, "%s(%d,0x%lx,%lu,0x%lx,0x%lx (%lu))\n", me,
142          fd, (u_long) src,(u_long) src_size,(u_long) dst, (u_long) dst_size,(u_long) (dst_size ? *dst_size : 0));
143 
144     /* Prevent the calling process from being killed */
145     sigfillset(&all);
146     sigprocmask(SIG_BLOCK, &all, &oldset);
147 
148     /* Make sure we are alone */
149     snapscani_mutex_lock(&snapscan_mutex);
150 
151     status = usb_cmd(fd,src,src_size,dst,dst_size);
152 
153     snapscani_mutex_unlock(&snapscan_mutex);
154 
155     /* Now it is ok to be killed */
156     sigprocmask(SIG_SETMASK, &oldset, NULL);
157 
158     return status;
159 
160 }
161 
snapscani_usb_open(const char * dev,int * fdp,sense_handler_type sense_handler,void * pss)162 static SANE_Status snapscani_usb_open(const char *dev, int *fdp,
163     sense_handler_type sense_handler, void* pss)
164 {
165     static const char me[] = "snapscani_usb_open";
166 
167     DBG (DL_CALL_TRACE, "%s(%s)\n", me, dev);
168 
169     if(!snapscani_mutex_open(&snapscan_mutex, dev)) {
170         DBG (DL_MAJOR_ERROR, "%s: Can't get semaphore\n", me);
171         return SANE_STATUS_INVAL;
172     }
173     usb_sense_handler=sense_handler;
174     usb_pss = pss;
175     urb_counters->read_urbs = 0;
176     urb_counters->write_urbs = 0;
177     return sanei_usb_open(dev, fdp);
178 }
179 
180 
snapscani_usb_close(int fd)181 static void snapscani_usb_close(int fd) {
182     static const char me[] = "snapscani_usb_close";
183     SANE_Word vendor_id, product_id;
184 
185     DBG (DL_CALL_TRACE, "%s(%d)\n", me, fd);
186     DBG (DL_DATA_TRACE,"1st read %ld write %ld\n", urb_counters->read_urbs, urb_counters->write_urbs);
187 
188     /* Check if URB counting is needed. If yes, ensure the number of sent and
189        received URBs is even.
190        Odd number of URBs only cause problems with libusb and certain
191        scanner models. On other scanner models, sending additional commands
192        seems to cause problems (e.g. 1212u_2).
193        If sanei_usb_get_vendor_product returns an error there's probably no
194        libusb, so everything's fine.
195     */
196     if (sanei_usb_get_vendor_product(fd, &vendor_id, &product_id) == SANE_STATUS_GOOD)
197     {
198         /* Exclude 1212u_2 */
199         if (!((vendor_id == USB_VENDOR_AGFA) && (product_id == USB_PRODUCT_1212U2)))
200         {
201             if ((urb_counters->read_urbs & 0x01) && (urb_counters->write_urbs & 0x01))
202             {
203                 char cmd[] = {TEST_UNIT_READY, 0, 0, 0, 0, 0};
204 
205                 snapscani_usb_cmd (fd, cmd, sizeof (cmd), NULL, 0);
206             }
207             else if (urb_counters->read_urbs & 0x01)
208             {
209                 size_t read_bytes;
210                 char cmd[] = {TEST_UNIT_READY, 0, 0, 0, 0, 0};
211                 char cmd2[] = {INQUIRY, 0, 0, 0, 120, 0};
212                 char data[120];
213 
214                 read_bytes = 120;
215                 snapscani_usb_cmd (fd, cmd2, sizeof (cmd2), data, &read_bytes);
216                 snapscani_usb_cmd (fd, cmd, sizeof (cmd), NULL, 0);
217             }
218             else if (urb_counters->write_urbs & 0x01)
219             {
220                 size_t read_bytes;
221                 char cmd[] = {INQUIRY, 0, 0, 0, 120, 0};
222                 char data[120];
223 
224                 read_bytes = 120;
225                 snapscani_usb_cmd (fd, cmd, sizeof (cmd), data, &read_bytes);
226             }
227             DBG (DL_DATA_TRACE,"2nd read %ld write %ld\n", urb_counters->read_urbs,
228                 urb_counters->write_urbs);
229         }
230     }
231     urb_counters->read_urbs = 0;
232     urb_counters->write_urbs = 0;
233     snapscani_mutex_close(&snapscan_mutex);
234     sanei_usb_close(fd);
235 }
236 
usb_cmdlen(int cmd)237 static int usb_cmdlen(int cmd)
238 {
239     switch(cmd) {
240     case TEST_UNIT_READY:
241     case INQUIRY:
242     case SCAN:
243     case REQUEST_SENSE:
244     case RESERVE_UNIT:
245     case RELEASE_UNIT:
246     case SEND_DIAGNOSTIC:
247         return 6;
248     case SEND:
249     case SET_WINDOW:
250     case READ:
251     case GET_DATA_BUFFER_STATUS:
252         return 10;
253     }
254     return 0;
255 }
256 
usb_debug_data(char * str,const char * data,int len)257 static char *usb_debug_data(char *str,const char *data, int len) {
258     char tmpstr[10];
259     int i;
260 
261     str[0]=0;
262     for(i=0; i < (len < 10 ? len : 10); i++) {
263         sprintf(tmpstr," 0x%02x",((int)data[i]) & 0xff);
264         if(i%16 == 0 && i != 0)
265             strcat(str,"\n");
266         strcat(str,tmpstr);
267     }
268     if(i < len)
269         strcat(str," ...");
270     return str;
271 }
272 
273 #define RETURN_ON_FAILURE(x) if((status = x) != SANE_STATUS_GOOD) return status;
274 
usb_write(int fd,const void * buf,size_t n)275 static SANE_Status usb_write(int fd, const void *buf, size_t n) {
276     char dbgmsg[16384];
277     SANE_Status status;
278     size_t bytes_written = n;
279 
280     static const char me[] = "usb_write";
281     DBG(DL_DATA_TRACE, "%s: writing: %s\n",me,usb_debug_data(dbgmsg,buf,n));
282 
283     status = sanei_usb_write_bulk(fd, (const SANE_Byte*)buf, &bytes_written);
284     if(bytes_written != n) {
285       DBG (DL_MAJOR_ERROR, "%s Only %lu bytes written\n",me, (u_long) bytes_written);
286         status = SANE_STATUS_IO_ERROR;
287     }
288     urb_counters->write_urbs += (bytes_written + 7) / 8;
289     DBG (DL_DATA_TRACE, "Written %lu bytes\n", (u_long) bytes_written);
290     return status;
291 }
292 
usb_read(SANE_Int fd,void * buf,size_t n)293 static SANE_Status usb_read(SANE_Int fd, void *buf, size_t n) {
294     char dbgmsg[16384];
295     static const char me[] = "usb_read";
296     SANE_Status status;
297     size_t bytes_read = n;
298 
299     status = sanei_usb_read_bulk(fd, (SANE_Byte*)buf, &bytes_read);
300     if (bytes_read != n) {
301         DBG (DL_MAJOR_ERROR, "%s Only %lu bytes read\n",me, (u_long) bytes_read);
302         status = SANE_STATUS_IO_ERROR;
303     }
304     urb_counters->read_urbs += ((63 + bytes_read) / 64);
305     DBG(DL_DATA_TRACE, "%s: reading: %s\n",me,usb_debug_data(dbgmsg,buf,n));
306     DBG(DL_DATA_TRACE, "Read %lu bytes\n", (u_long) bytes_read);
307     return status;
308 }
309 
usb_read_status(int fd,int * scsistatus,int * transaction_status,char command)310 static SANE_Status usb_read_status(int fd, int *scsistatus, int *transaction_status,
311                                    char command)
312 {
313     static const char me[] = "usb_read_status";
314     unsigned char status_buf[8];
315     int scsistat;
316     int status;
317 
318     RETURN_ON_FAILURE(usb_read(fd,status_buf,8));
319 
320     if(transaction_status)
321         *transaction_status = status_buf[0];
322 
323     scsistat = (status_buf[1] & STATUS_MASK) >> 1;
324 
325     if(scsistatus)
326         *scsistatus = scsistat;
327 
328     switch(scsistat) {
329     case GOOD:
330         return SANE_STATUS_GOOD;
331     case CHECK_CONDITION:
332         if (usb_pss != NULL) {
333             if (command != REQUEST_SENSE) {
334                 return usb_request_sense(usb_pss);
335             }
336             else {
337                 /* Avoid recursive calls of usb_request_sense */
338                 return SANE_STATUS_GOOD;
339             }
340         } else {
341             DBG (DL_MAJOR_ERROR, "%s: scanner structure not set, returning default error\n",
342                 me);
343             return SANE_STATUS_DEVICE_BUSY;
344         }
345         break;
346     case BUSY:
347         return SANE_STATUS_DEVICE_BUSY;
348     default:
349         return SANE_STATUS_IO_ERROR;
350     }
351 }
352 
353 
usb_cmd(int fd,const void * src,size_t src_size,void * dst,size_t * dst_size)354 static SANE_Status usb_cmd(int fd, const void *src, size_t src_size,
355                     void *dst, size_t * dst_size)
356 {
357   static const char me[] = "usb_cmd";
358   int status,tstatus;
359   int cmdlen,datalen;
360   char command;
361 
362   DBG (DL_CALL_TRACE, "%s(%d,0x%lx,%lu,0x%lx,0x%lx (%lu))\n", me,
363        fd, (u_long) src,(u_long) src_size,(u_long) dst, (u_long) dst_size,(u_long) (dst_size ? *dst_size : 0));
364 
365   /* Since the  "Send Diagnostic" command isn't supported by
366      all Snapscan USB-scanners it's disabled .
367   */
368   command = ((const char *)src)[0];
369   if(command == SEND_DIAGNOSTIC)
370       return(SANE_STATUS_GOOD);
371 
372   cmdlen = usb_cmdlen(*((const char *)src));
373   datalen = src_size - cmdlen;
374 
375   DBG(DL_DATA_TRACE, "%s: cmdlen=%d, datalen=%d\n",me,cmdlen,datalen);
376 
377   /* Send command to scanner */
378   RETURN_ON_FAILURE( usb_write(fd,src,cmdlen) );
379 
380   /* Read status */
381   RETURN_ON_FAILURE( usb_read_status(fd, NULL, &tstatus, command) );
382 
383   /* Send data only if the scanner is expecting it */
384   if(datalen > 0 && (tstatus == TRANSACTION_WRITE)) {
385       /* Send data to scanner */
386       RETURN_ON_FAILURE( usb_write(fd, ((const SANE_Byte *) src) + cmdlen, datalen) );
387 
388       /* Read status */
389       RETURN_ON_FAILURE( usb_read_status(fd, NULL, &tstatus, command) );
390   }
391 
392   /* Receive data only when new data is waiting */
393   if(dst_size && *dst_size && (tstatus == TRANSACTION_READ)) {
394       RETURN_ON_FAILURE( usb_read(fd,dst,*dst_size) );
395 
396       /* Read status */
397       RETURN_ON_FAILURE( usb_read_status(fd, NULL, &tstatus, command) );
398   }
399 
400   if(tstatus != TRANSACTION_COMPLETED) {
401       if(tstatus == TRANSACTION_WRITE)
402           DBG(DL_MAJOR_ERROR,
403               "%s: The transaction should now be completed, but the scanner is expecting more data" ,me);
404       else
405           DBG(DL_MAJOR_ERROR,
406               "%s: The transaction should now be completed, but the scanner has more data to send" ,me);
407       return SANE_STATUS_IO_ERROR;
408   }
409 
410   return status;
411 }
412 
413 /* Busy queue data structures and function implementations*/
414 
is_queueable(const char * src)415 static int is_queueable(const char *src)
416 {
417     switch(src[0]) {
418     case SEND:
419     case SET_WINDOW:
420     case SEND_DIAGNOSTIC:
421         return 1;
422     default:
423         return 0;
424     }
425 }
426 
427 static struct usb_busy_queue *bqhead=NULL,*bqtail=NULL;
428 static int bqelements=0;
429 
enqueue_bq(int fd,const void * src,size_t src_size)430 static int enqueue_bq(int fd,const void *src, size_t src_size)
431 {
432     static const char me[] = "enqueue_bq";
433     struct usb_busy_queue *bqe;
434 
435     DBG (DL_CALL_TRACE, "%s(%d,%p,%lu)\n", me, fd,src, (u_long) src_size);
436 
437     if((bqe = malloc(sizeof(struct usb_busy_queue))) == NULL)
438         return -1;
439 
440     if((bqe->src = malloc(src_size)) == NULL)
441         return -1;
442 
443     memcpy(bqe->src,src,src_size);
444     bqe->src_size=src_size;
445 
446     bqe->next=NULL;
447 
448     if(bqtail) {
449         bqtail->next=bqe;
450         bqtail = bqe;
451     } else
452         bqhead = bqtail = bqe;
453 
454     bqelements++;
455     DBG(DL_DATA_TRACE, "%s: Busy queue: elements=%d, bqhead=%p, bqtail=%p\n",
456         me,bqelements,(void*)bqhead,(void*)bqtail);
457     return 0;
458 }
459 
dequeue_bq()460 static void dequeue_bq()
461 {
462     static const char me[] = "dequeue_bq";
463     struct usb_busy_queue *tbqe;
464 
465     DBG (DL_CALL_TRACE, "%s()\n", me);
466 
467     if(!bqhead)
468         return;
469 
470     tbqe = bqhead;
471     bqhead = bqhead->next;
472     if(!bqhead)
473         bqtail=NULL;
474 
475     if(tbqe->src)
476         free(tbqe->src);
477     free(tbqe);
478 
479     bqelements--;
480     DBG(DL_DATA_TRACE, "%s: Busy queue: elements=%d, bqhead=%p, bqtail=%p\n",
481         me,bqelements,(void*)bqhead,(void*)bqtail);
482 }
483 
usb_request_sense(SnapScan_Scanner * pss)484 static SANE_Status usb_request_sense(SnapScan_Scanner *pss) {
485     static const char *me = "usb_request_sense";
486     size_t read_bytes = 0;
487     u_char cmd[] = {REQUEST_SENSE, 0, 0, 0, 20, 0};
488     u_char data[20];
489     SANE_Status status;
490 
491     read_bytes = 20;
492 
493     DBG (DL_CALL_TRACE, "%s\n", me);
494     status = usb_cmd (pss->fd, cmd, sizeof (cmd), data, &read_bytes);
495     if (status != SANE_STATUS_GOOD)
496     {
497         DBG (DL_MAJOR_ERROR, "%s: usb command error: %s\n",
498              me, sane_strstatus (status));
499     }
500     else
501     {
502         if (usb_sense_handler) {
503             status = usb_sense_handler (pss->fd, data, (void *) pss);
504         } else {
505             DBG (DL_MAJOR_ERROR, "%s: No sense handler for USB\n", me);
506             status = SANE_STATUS_UNSUPPORTED;
507         }
508     }
509     return status;
510 }
511 
512 #if defined USE_PTHREAD || defined HAVE_OS2_H || defined __BEOS__
snapscani_usb_shm_init(void)513 static SANE_Status snapscani_usb_shm_init(void)
514 {
515     unsigned int shm_size = sizeof(struct urb_counters_t);
516     urb_counters = (struct urb_counters_t*) malloc(shm_size);
517     if (urb_counters == NULL)
518     {
519         return SANE_STATUS_NO_MEM;
520     }
521     memset(urb_counters, 0, shm_size);
522     return SANE_STATUS_GOOD;
523 
524 }
525 
snapscani_usb_shm_exit(void)526 static void snapscani_usb_shm_exit(void)
527 {
528     if (urb_counters)
529     {
530         free ((void*)urb_counters);
531         urb_counters = NULL;
532     }
533 }
534 #else
535 #include <sys/ipc.h>
536 #include <sys/shm.h>
snapscani_usb_shm_init(void)537 static SANE_Status snapscani_usb_shm_init(void)
538 {
539     unsigned int shm_size = sizeof(struct urb_counters_t);
540     void* shm_area = NULL;
541     int shm_id = shmget (IPC_PRIVATE, shm_size, IPC_CREAT | SHM_R | SHM_W);
542     if (shm_id == -1)
543     {
544         DBG (DL_MAJOR_ERROR, "snapscani_usb_shm_init: cannot create shared memory segment: %s\n",
545             strerror (errno));
546         return SANE_STATUS_NO_MEM;
547     }
548 
549     shm_area = shmat (shm_id, NULL, 0);
550     if (shm_area == (void *) -1)
551     {
552         DBG (DL_MAJOR_ERROR, "snapscani_usb_shm_init: cannot attach to shared memory segment: %s\n",
553             strerror (errno));
554         shmctl (shm_id, IPC_RMID, NULL);
555         return SANE_STATUS_NO_MEM;
556     }
557 
558     if (shmctl (shm_id, IPC_RMID, NULL) == -1)
559     {
560         DBG (DL_MAJOR_ERROR, "snapscani_usb_shm_init: cannot remove shared memory segment id: %s\n",
561             strerror (errno));
562         shmdt (shm_area);
563         shmctl (shm_id, IPC_RMID, NULL);
564         return SANE_STATUS_NO_MEM;
565     }
566     urb_counters = (struct urb_counters_t*) shm_area;
567     memset(urb_counters, 0, shm_size);
568     return SANE_STATUS_GOOD;
569 }
570 
snapscani_usb_shm_exit(void)571 static void snapscani_usb_shm_exit(void)
572 {
573     if (urb_counters)
574     {
575         shmdt (urb_counters);
576         urb_counters = NULL;
577     }
578 }
579 #endif
580 /*
581  * Revision 1.22  2006/01/26 17:42:30  hmg-guest
582  * Added #defines for SHM_R/W for cygwin (patch from Philip Aston <philipa@mail.com>).
583  *
584  * Revision 1.21  2005/11/02 19:22:06  oliver-guest
585  * Fixes for Benq 5000
586  *
587  * Revision 1.20  2005/07/18 17:37:37  oliver-guest
588  * ZETA changes for SnapScan backend
589  *
590  * Revision 1.19  2004/10/03 17:34:36  hmg-guest
591  * 64 bit platform fixes (bug #300799).
592  *
593  * Revision 1.18  2004/06/16 19:52:26  oliver-guest
594  * Don't enforce even number of URB packages on 1212u_2. Fixes bug #300753.
595  *
596  * Revision 1.17  2004/06/06 14:50:36  oliver-guest
597  * Use shared memory functions only when needed
598  *
599  * Revision 1.16  2004/05/26 22:37:01  oliver-guest
600  * Use shared memory for urb counters in snapscan backend
601  *
602  * Revision 1.15  2004/04/09 11:59:02  oliver-guest
603  * Fixes for pthread implementation
604  *
605  * Revision 1.14  2004/04/08 22:48:13  oliver-guest
606  * Use URB counting in snapscan-usb.c (thanks to Jose Alberto Reguero)
607  *
608  * Revision 1.13  2003/11/08 09:50:27  oliver-guest
609  * Fix TPO scanning range for Epson 1670
610  *
611  * Revision 1.12  2003/07/26 17:16:55  oliverschwartz
612  * Changed licence to GPL + SANE exception for snapscan-usb.[ch]
613  *
614  * Revision 1.11  2002/07/12 23:29:06  oliverschwartz
615  * SnapScan backend 1.4.15
616  *
617  * Revision 1.21  2002/07/12 22:52:42  oliverschwartz
618  * use sanei_usb_read_bulk() and sanei_usb_write_bulk()
619  *
620  * Revision 1.20  2002/04/27 14:36:25  oliverschwartz
621  * Pass a char as 'proj' argument for ftok()
622  *
623  * Revision 1.19  2002/04/10 21:00:33  oliverschwartz
624  * Make bqelements static
625  *
626  * Revision 1.18  2002/03/24 12:16:09  oliverschwartz
627  * Better error report in usb_read
628  *
629  * Revision 1.17  2002/02/05 19:32:39  oliverschwartz
630  * Only define union semun if not already defined in <sys/sem.h>. Fixes
631  * compilation bugs on Irix and FreeBSD. Fixed by Henning Meier-Geinitz.
632  *
633  * Revision 1.16  2002/01/14 21:11:56  oliverschwartz
634  * Add workaround for bug semctl() call in libc for PPC
635  *
636  * Revision 1.15  2001/12/09 23:06:44  oliverschwartz
637  * - use sense handler for USB if scanner reports CHECK_CONDITION
638  *
639  * Revision 1.14  2001/11/16 20:23:16  oliverschwartz
640  * Merge with sane-1.0.6
641  *   - Check USB vendor IDs to avoid hanging scanners
642  *   - fix bug in dither matrix computation
643  *
644  * Revision 1.13  2001/10/09 22:34:23  oliverschwartz
645  * fix compiler warnings
646  *
647  * Revision 1.12  2001/09/18 15:01:07  oliverschwartz
648  * - Read scanner id string again after firmware upload
649  *   to identify correct model
650  * - Make firmware upload work for AGFA scanners
651  * - Change copyright notice
652  *
653  * */
654