summaryrefslogtreecommitdiff
path: root/backend/avision.h
blob: 9017bf22dcb67b1c61d2693dc2074a969008f299 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
/*******************************************************************************
 * SANE - Scanner Access Now Easy.

   avision.h

   This file is part of the SANE package.

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
   MA 02111-1307, USA.

   As a special exception, the authors of SANE give permission for
   additional uses of the libraries contained in this release of SANE.

   The exception is that, if you link a SANE library with other files
   to produce an executable, this does not by itself cause the
   resulting executable to be covered by the GNU General Public
   License.  Your use of that executable is in no way restricted on
   account of linking the SANE library code into it.

   This exception does not, however, invalidate any other reasons why
   the executable file might be covered by the GNU General Public
   License.

   If you submit changes to SANE to the maintainers to be included in
   a subsequent release, you agree by submitting the changes that
   those changes may be distributed with this exception intact.

   *****************************************************************************

   This backend is based upon the Tamarack backend and adapted to the Avision
   scanners by René Rebe and Meino Cramer.

   Check the avision.c file for detailed copyright and change-log
   information.

********************************************************************************/

#ifndef avision_h
#define avision_h

#ifdef HAVE_STDINT_H
# include <stdint.h>            /* available in ISO C99 */
#else
# include <sys/types.h>
typedef uint8_t uint8_t;
typedef uint16_t uint16_t;
typedef uint32_t uint32_t;
#endif /* HAVE_STDINT_H */

#ifndef PATH_MAX
# define PATH_MAX 1024
#endif

typedef enum Avision_ConnectionType {
  AV_SCSI,
  AV_USB
} Avision_ConnectionType;

/* information needed for device access */
typedef struct Avision_Connection {
  Avision_ConnectionType connection_type;
  int scsi_fd;			/* SCSI filedescriptor */
  SANE_Int usb_dn;		/* USB (libusb or scanner.c) device number */
  enum {
    AVISION_USB_UNTESTED_STATUS, /* status type untested */
    AVISION_USB_INT_STATUS,      /* interrupt endp. (USB 1.x device) status */
    AVISION_USB_BULK_STATUS      /* bulk endp. (USB 2.0 device) status */
  } usb_status;

} Avision_Connection;

/* structure for ADF offsets in mm */
typedef struct mm_offset {
  double top;
  double bottom;
} mm_offset;

typedef struct Avision_HWEntry {
  const char* scsi_mfg;
  const char* scsi_model;

  int   usb_vendor;
  int   usb_product;

  const char* real_mfg;
  const char* real_model;

  /* feature overwrites - as embedded CPUs have 16bit enums - this
     would need a change ... */
    /* force no calibration */
  #define AV_NO_CALIB ((uint64_t)1<<0)

    /* force all in one command calibration */
  #define AV_ONE_CALIB_CMD ((uint64_t)1<<1)

    /* no gamma table */
  #define AV_NO_GAMMA ((uint64_t)1<<2)

    /* light check is bogus */
  #define AV_LIGHT_CHECK_BOGUS ((uint64_t)1<<3)

    /* no button though the device advertise it */
  #define AV_NO_BUTTON ((uint64_t)1<<4)

    /* if the scan area needs to be forced to A3 */
  #define AV_FORCE_A3 ((uint64_t)1<<5)

    /* if the scan area and resolution needs to be forced for films */
  #define AV_FORCE_FILM ((uint64_t)1<<6)

    /* does not suport, or very broken background (added for AV610C2) */
  #define AV_NO_BACKGROUND ((uint64_t)1<<7)

    /* is film scanner - no detection yet */
  #define AV_FILMSCANNER ((uint64_t)1<<8)

    /* fujitsu adaption */
  #define AV_FUJITSU ((uint64_t)1<<9)

    /* gray calibration data has to be uploaded on the blue channel ... ? */
  #define AV_GRAY_CALIB_BLUE ((uint64_t)1<<10)

    /* Interrupt endpoint button readout (so far AV220) */
  #define AV_INT_BUTTON ((uint64_t)1<<11)

    /* send acceleration table ... */
  #define AV_ACCEL_TABLE ((uint64_t)1<<12)

    /* non-interlaced scanns up to 300 dpi (AV32xx / AV83xx) */
  #define AV_NON_INTERLACED_DUPLEX_300 ((uint64_t)1<<13)

    /* do not read multiples of 64 bytes - stalls the USB chip */
  #define AV_NO_64BYTE_ALIGN ((uint64_t)1<<14)

    /* force channel-by-channel calibration */
  #define AV_MULTI_CALIB_CMD ((uint64_t)1<<15)

    /* non color scans are faster with a filter applied (AV32xx) */
  #define AV_FASTER_WITH_FILTER ((uint64_t)1<<16)

    /* interlaced data with 1 line distance */
  #define AV_2ND_LINE_INTERLACED ((uint64_t)1<<17)

    /* does not keep the window though it advertices so */
  #define AV_DOES_NOT_KEEP_WINDOW ((uint64_t)1<<18)

    /* does not keep the gamma though it advertices so */
  #define AV_DOES_NOT_KEEP_GAMMA ((uint64_t)1<<19)

    /* advertises ADF is BGR order, but isn't (or vice versa) */
  #define AV_ADF_BGR_ORDER_INVERT ((uint64_t)1<<20)

    /* allows 12bit mode, though not flagged */
  #define AV_12_BIT_MODE ((uint64_t)1<<21)

    /* very broken background raster */
  #define AV_BACKGROUND_QUIRK ((uint64_t)1<<22)

    /* though marked as GRAY only the scanner can do GRAY modes */
  #define AV_GRAY_MODES ((uint64_t)1<<23)

    /* no seperate, single REAR scan (AV122, DM152, ...) */
  #define AV_NO_REAR ((uint64_t)1<<24)

    /* only scan with some known good hardware resolutions, as the
       scanner fails to properly interpoloate in between (e.g.  AV121,
       DM152 on duplex scans - but also the AV600), software scale and
       interpolate to all the others */
  #define AV_SOFT_SCALE ((uint64_t)1<<25)

    /* does keep window though it does not advertice it - the AV122/DM152
       mess up image data if window is resend between ADF pages */
  #define AV_DOES_KEEP_WINDOW ((uint64_t)1<<26)

    /* does keep gamma though it does not advertice it */
  #define AV_DOES_KEEP_GAMMA ((uint64_t)1<<27)

    /* does the scanner contain a Cancel button? */
  #define AV_CANCEL_BUTTON ((uint64_t)1<<28)

    /* some devices do not need a START_SCAN, even hang with it */
  #define AV_NO_START_SCAN ((uint64_t)1<<30)

  #define AV_INT_STATUS ((uint64_t)1<<31)

    /* force no calibration */
  #define AV_NO_TUNE_SCAN_LENGTH ((uint64_t)1<<32)

    /* for gray scans, set grey filter */
  #define AV_USE_GRAY_FILTER ((uint64_t)1<<33)

    /* For (HP) scanners with flipping duplexers */
  #define AV_ADF_FLIPPING_DUPLEX ((uint64_t)1<<34)

    /* For scanners which need to have their firmware read to properly function. */
  #define AV_FIRMWARE ((uint64_t)1<<35)

  /* at least Kodak i1120 claims no calibration needed but windows driver does it anyways */
  #define AV_FORCE_CALIB ((uint64_t)1<<36)

  /* at least Kodak i1120 does not have an explicit "quality-scan" mode */
  #define AV_NO_QSCAN_MODE ((uint64_t)1<<37)

  /* at least Kodak i1120 optical DPI is used for overscan calculation */
  #define AV_OVERSCAN_OPTDPI ((uint64_t)1<<38)

  /* some scanners support fast feed-out of the sheet when cancelling a running scan */
  #define AV_FASTFEED_ON_CANCEL ((uint64_t)1<<39)

  /* at least Kodak i1120 does not have an explicit "quality-calibration" mode */
  #define AV_NO_QCALIB_MODE ((uint64_t)1<<40)

  /* Kodak i1120 needs gamma = 1.0 to give decent results */
  #define AV_GAMMA_10 ((uint64_t)1<<41)

  /* Kodak i1120 has a different gamma table format (like a uint16/double array) */
  #define AV_GAMMA_UINT16 ((uint64_t)1<<42)

  /* Kodak i1120 has single-sheet and multi-sheet scan modes. This option sets
     bitset3[7] which enables multi-sheet scan by default so there is no pause
     of 1s between two sheets in ADF scan mode. This also fixes some offsets
     when scanning multiple sheets. */
  #define AV_MULTI_SHEET_SCAN ((uint64_t)1<<43)

    /* maybe more ...*/
  uint64_t feature_type;

  /* ADF offsets in mm */
  struct {
    float first; /* offset difference first sheet */
    mm_offset front; /* front-only */
    struct {
      mm_offset front;
      mm_offset rear;
    } duplex;
  } offset;

} Avision_HWEntry;

typedef enum {
  AV_ASIC_Cx = 0,
  AV_ASIC_C1 = 1,
  AV_ASIC_W1 = 2,
  AV_ASIC_C2 = 3,
  AV_ASIC_C5 = 5,
  AV_ASIC_C6 = 6,
  AV_ASIC_C7 = 7,
  AV_ASIC_OA980 = 128,
  AV_ASIC_OA982 = 129
} asic_type;

typedef enum {
  AV_THRESHOLDED,
  AV_DITHERED,
  AV_GRAYSCALE,       /* all gray needs to be before color for is_color() */
  AV_GRAYSCALE12,
  AV_GRAYSCALE16,
  AV_TRUECOLOR,
  AV_TRUECOLOR12,
  AV_TRUECOLOR16,
  AV_COLOR_MODE_LAST
} color_mode;

typedef enum {
  AV_NORMAL,
  AV_TRANSPARENT,
  AV_ADF,
  AV_ADF_REAR,
  AV_ADF_DUPLEX,
  AV_SOURCE_MODE_LAST
} source_mode;

typedef enum {
  AV_NORMAL_DIM,
  AV_TRANSPARENT_DIM,
  AV_ADF_DIM,
  AV_SOURCE_MODE_DIM_LAST
} source_mode_dim;

enum Avision_Option
{
  OPT_NUM_OPTS = 0,      /* must come first */

  OPT_MODE_GROUP,
  OPT_MODE,
  OPT_RESOLUTION,
#define OPT_RESOLUTION_DEFAULT 150
  OPT_SPEED,
  OPT_PREVIEW,

  OPT_SOURCE,            /* scan source normal, transparency, ADF */

  OPT_GEOMETRY_GROUP,
  OPT_TL_X,	         /* top-left x */
  OPT_TL_Y,	         /* top-left y */
  OPT_BR_X,	         /* bottom-right x */
  OPT_BR_Y,		 /* bottom-right y */

  OPT_OVERSCAN_TOP,      /* overscan for auto-crop/deskew, if supported */
  OPT_OVERSCAN_BOTTOM,
  OPT_BACKGROUND,        /* background raster lines to read out */

  OPT_ENHANCEMENT_GROUP,
  OPT_BRIGHTNESS,
  OPT_CONTRAST,
  OPT_QSCAN,
  OPT_QCALIB,

  OPT_GAMMA_VECTOR,      /* first must be gray */
  OPT_GAMMA_VECTOR_R,    /* then r g b vector */
  OPT_GAMMA_VECTOR_G,
  OPT_GAMMA_VECTOR_B,

  OPT_EXPOSURE,          /* film exposure adjustment */
  OPT_IR,                /* infra-red */
  OPT_MULTISAMPLE,       /* multi-sample */

  OPT_MISC_GROUP,
  OPT_FRAME,             /* Film holder control */

  OPT_POWER_SAVE_TIME,   /* set power save time to the scanner */

  OPT_MESSAGE,           /* optional message from the scanner display */
  OPT_NVRAM,             /* retrieve NVRAM values as pretty printed text */

  OPT_PAPERLEN,          /* Use paper_length field to detect double feeds */
  OPT_ADF_FLIP,          /* For flipping duplex, reflip the document */

  NUM_OPTIONS            /* must come last */
};

/* structure for ADF offsets in pixels of HW res */
typedef struct hwpx_offset {
  int top;
  int bottom;
} hwpx_offset;


typedef struct Avision_Dimensions
{
  /* in dpi */
  int xres;
  int yres;

  /* in pixels */
  long tlx;
  long tly;
  long brx;
  long bry;

  /* in pixels */
  int line_difference;

  struct {
    hwpx_offset front;
    hwpx_offset rear;
  } offset;

  /* interlaced duplex scan */
  SANE_Bool interlaced_duplex;

  /* in dpi, likewise - different if software scaling required */
  int hw_xres;
  int hw_yres;

  int hw_pixels_per_line;
  int hw_bytes_per_line;
  int hw_lines;

} Avision_Dimensions;

/* this contains our low-level info - not relevant for the SANE interface  */
typedef struct Avision_Device
{
  struct Avision_Device* next;
  SANE_Device sane;
  Avision_Connection connection;

  /* structs used to store config options */
  SANE_Range dpi_range;
  SANE_Range x_range;
  SANE_Range y_range;
  SANE_Range speed_range;

  asic_type inquiry_asic_type;
  SANE_Bool inquiry_new_protocol;

  SANE_Bool inquiry_nvram_read;
  SANE_Bool inquiry_power_save_time;

  SANE_Bool inquiry_light_box;
  SANE_Bool inquiry_adf;
  SANE_Bool inquiry_duplex;
  SANE_Bool inquiry_duplex_interlaced;
  SANE_Bool inquiry_paper_length;
  SANE_Bool inquiry_batch_scan;
  SANE_Bool inquiry_detect_accessories;
  SANE_Bool inquiry_needs_calibration;
  SANE_Bool inquiry_needs_gamma;
  SANE_Bool inquiry_keeps_gamma;
  SANE_Bool inquiry_keeps_window;
  SANE_Bool inquiry_calibration;
  SANE_Bool inquiry_3x3_matrix;
  SANE_Bool inquiry_needs_software_colorpack;
  SANE_Bool inquiry_needs_line_pack;
  SANE_Bool inquiry_adf_need_mirror;
  SANE_Bool inquiry_adf_bgr_order;
  SANE_Bool inquiry_light_detect;
  SANE_Bool inquiry_light_control;
  SANE_Bool inquiry_exposure_control;

  int       inquiry_max_shading_target;
  SANE_Bool inquiry_button_control;
  unsigned int inquiry_buttons;
  SANE_Bool inquiry_tune_scan_length;
  SANE_Bool inquiry_background_raster;
  int       inquiry_background_raster_pixel;

  enum {AV_FLATBED,
	AV_FILM,
	AV_SHEETFEED
  } scanner_type;

  /* the list of available color modes */
  SANE_String_Const color_list[AV_COLOR_MODE_LAST + 1];
  color_mode color_list_num[AV_COLOR_MODE_LAST];
  color_mode color_list_default;

  /* the list of available source modes */
  SANE_String_Const source_list[AV_SOURCE_MODE_LAST + 1];
  source_mode source_list_num[AV_SOURCE_MODE_LAST];

  int inquiry_optical_res;        /* in dpi */
  int inquiry_max_res;            /* in dpi */

  double inquiry_x_ranges  [AV_SOURCE_MODE_DIM_LAST]; /* in mm */
  double inquiry_y_ranges  [AV_SOURCE_MODE_DIM_LAST]; /* in mm */

  int inquiry_color_boundary;
  int inquiry_gray_boundary;
  int inquiry_dithered_boundary;
  int inquiry_thresholded_boundary;
  int inquiry_line_difference; /* software color pack */

  int inquiry_channels_per_pixel;
  int inquiry_bits_per_channel;
  int inquiry_no_gray_modes;

  SANE_Bool adf_offset_compensation;

  int scsi_buffer_size; /* nice to have SCSI buffer size */
  int read_stripe_size; /* stripes to be read at-a-time */

  /* film scanner atributes - maybe these should be in the scanner struct? */
  SANE_Range frame_range;
  SANE_Word current_frame;
  SANE_Word holder_type;

  /* some versin corrections */
  uint16_t data_dq; /* was ox0A0D - but hangs some new scanners */

  Avision_HWEntry* hw;
} Avision_Device;

/* all the state relevant for the SANE interface */
typedef struct Avision_Scanner
{
  struct Avision_Scanner* next;
  Avision_Device* hw;

  SANE_Option_Descriptor opt [NUM_OPTIONS];
  Option_Value val [NUM_OPTIONS];
  SANE_Int gamma_table [4][256];

  /* we now save the calib data because we might need it for 16bit software
     calibration :-( */
  uint8_t* dark_avg_data;
  uint8_t* white_avg_data;

  /* background raster data, if duplex first front, then rear */
  uint8_t* background_raster;

  /* Parsed option values and variables that are valid only during
     the actual scan: */
  SANE_Bool prepared;		/* first page marker */
  SANE_Bool scanning;           /* scan in progress */
  unsigned int page;            /* page counter, 0: uninitialized, 1: scanning 1st page, ... */
  int cancelled;

  SANE_Parameters params;       /* scan window */
  Avision_Dimensions avdimen;   /* scan window - detailed internals */

  /* Internal data for duplex scans */
  char duplex_rear_fname [PATH_MAX];
  char duplex_offtmp_fname [PATH_MAX];
  SANE_Bool duplex_rear_valid;

  color_mode c_mode;
  source_mode source_mode;
  source_mode_dim source_mode_dim;

  /* Avision HW Access Connection (SCSI/USB abstraction) */
  Avision_Connection av_con;

  SANE_Pid reader_pid;	/* process id of reader */
  int read_fds;		/* pipe reading end */
  int write_fds;	/* pipe writing end */

} Avision_Scanner;

/* Some Avision driver internal defines */
#define AV_WINID 0

/* Avision SCSI over USB error codes */
#define AVISION_USB_GOOD                    0x00
#define AVISION_USB_REQUEST_SENSE           0x02
#define AVISION_USB_BUSY                    0x08

/* SCSI commands that the Avision scanners understand: */

#define AVISION_SCSI_TEST_UNIT_READY        0x00
#define AVISION_SCSI_REQUEST_SENSE          0x03
#define AVISION_SCSI_MEDIA_CHECK            0x08
#define AVISION_SCSI_INQUIRY                0x12
#define AVISION_SCSI_MODE_SELECT            0x15
#define AVISION_SCSI_RESERVE_UNIT           0x16
#define AVISION_SCSI_RELEASE_UNIT           0x17
#define AVISION_SCSI_SCAN                   0x1b
#define AVISION_SCSI_SET_WINDOW             0x24
#define AVISION_SCSI_READ                   0x28
#define AVISION_SCSI_SEND                   0x2a
#define AVISION_SCSI_OBJECT_POSITION        0x31
#define AVISION_SCSI_GET_DATA_STATUS        0x34

#define AVISION_SCSI_OP_REJECT_PAPER        0x00
#define AVISION_SCSI_OP_LOAD_PAPER          0x01
#define AVISION_SCSI_OP_GO_HOME             0x02
#define AVISION_SCSI_OP_TRANS_CALIB_GRAY    0x04
#define AVISION_SCSI_OP_TRANS_CALIB_COLOR   0x05

/* These apply to bitset1.  The values are 0 to 6, shifted 3 bits to the left */
#define AVISION_FILTER_NONE	0x00
#define AVISION_FILTER_RED	0x08
#define AVISION_FILTER_GREEN	0x10
#define AVISION_FILTER_BLUE	0x18
#define AVISION_FILTER_RGB	0x20
#define AVISION_FILTER_CMYK	0x28
#define AVISION_FILTER_GRAY	0x30

/* The SCSI structures that we have to send to an avision to get it to
   do various stuff... */

typedef struct command_header
{
  uint8_t opc;
  uint8_t pad0 [3];
  uint8_t len;
  uint8_t pad1;
} command_header;

typedef struct command_set_window
{
  uint8_t opc;
  uint8_t reserved0 [5];
  uint8_t transferlen [3];
  uint8_t control;
} command_set_window;

typedef struct command_read
{
  uint8_t opc;
  uint8_t bitset1;
  uint8_t datatypecode;
  uint8_t readtype;
  uint8_t datatypequal [2];
  uint8_t transferlen [3];
  uint8_t control;
} command_read;

typedef struct command_scan
{
  uint8_t opc;
  uint8_t bitset0;
  uint8_t reserved0 [2];
  uint8_t transferlen;
  uint8_t bitset1;
} command_scan;

typedef struct command_send
{
  uint8_t opc;
  uint8_t bitset1;
  uint8_t datatypecode;
  uint8_t reserved0;
  uint8_t datatypequal [2];
  uint8_t transferlen [3];
  uint8_t reserved1;
} command_send;

typedef struct firmware_status
{
  uint8_t download_firmware;
  uint8_t first_effective_pixel_flatbed [2];
  uint8_t first_effective_pixel_adf_front [2];
  uint8_t first_effective_pixel_adf_rear [2];
  uint8_t reserved;
} firmware_status;

typedef struct nvram_data
{
  uint8_t pad_scans [4];
  uint8_t adf_simplex_scans [4];
  uint8_t adf_duplex_scans [4];
  uint8_t flatbed_scans [4];

  uint8_t flatbed_leading_edge [2];
  uint8_t flatbed_side_edge [2];
  uint8_t adf_leading_edge [2];
  uint8_t adf_side_edge [2];
  uint8_t adf_rear_leading_edge [2];
  uint8_t adf_rear_side_edge [2];

  uint8_t born_month [2];
  uint8_t born_day [2];
  uint8_t born_year [2];

  uint8_t first_scan_month [2];
  uint8_t first_scan_day [2];
  uint8_t first_scan_year [2];

  uint8_t vertical_magnification [2];
  uint8_t horizontal_magnification [2];

  uint8_t ccd_type;
  uint8_t scan_speed;

  char     serial [24];

  uint8_t power_saving_time [2];

  uint8_t auto_feed;
  uint8_t roller_count [4];
  uint8_t multifeed_count [4];
  uint8_t jam_count [4];

  uint8_t reserved;
  char     identify_info[16];
  char     formal_name[16];

  uint8_t reserved2 [10];
} nvram_data;

typedef struct command_set_window_window
{
  struct {
    uint8_t reserved0 [6];
    uint8_t desclen [2];
  } header;

  struct {
    uint8_t winid;
    uint8_t reserved0;
    uint8_t xres [2];
    uint8_t yres [2];
    uint8_t ulx [4];
    uint8_t uly [4];
    uint8_t width [4];
    uint8_t length [4];
    uint8_t brightness;
    uint8_t threshold;
    uint8_t contrast;
    uint8_t image_comp;
    uint8_t bpc;
    uint8_t halftone [2];
    uint8_t padding_and_bitset;
    uint8_t bitordering [2];
    uint8_t compr_type;
    uint8_t compr_arg;
    uint8_t paper_length[2];
    uint8_t reserved1 [4];

    /* Avision specific parameters */
    uint8_t vendor_specific;
    uint8_t paralen; /* bytes following after this byte */
  } descriptor;

  struct {
    uint8_t bitset1;
    uint8_t highlight;
    uint8_t shadow;
    uint8_t line_width [2];
    uint8_t line_count [2];

    /* the tail is quite version and model specific */
    union {
      struct {
	uint8_t bitset2;
	uint8_t reserved;
      } old;

      struct {
	uint8_t bitset2;
	uint8_t ir_exposure_time;

	/* optional */
	uint8_t r_exposure_time [2];
	uint8_t g_exposure_time [2];
	uint8_t b_exposure_time [2];

	uint8_t bitset3; /* reserved in the v2 */
	uint8_t auto_focus;
	uint8_t line_width_msb;
	uint8_t line_count_msb;
	uint8_t background_lines;

	uint8_t single_sheet_scan; /* from Kodak SVT tool */
      } normal;

      struct {
	uint8_t reserved0 [4];
	uint8_t paper_size;
	uint8_t paperx [4];
	uint8_t papery [4];
	uint8_t reserved1 [2];
      } fujitsu;
    } type;
  } avision;
} command_set_window_window;

typedef struct page_header
{
  uint8_t pad0 [4];
  uint8_t code;
  uint8_t length;
} page_header;

typedef struct avision_page
{
  uint8_t gamma;
  uint8_t thresh;
  uint8_t masks;
  uint8_t delay;
  uint8_t features;
  uint8_t pad0;
} avision_page;

typedef struct calibration_format
{
  uint16_t pixel_per_line;
  uint8_t bytes_per_channel;
  uint8_t lines;
  uint8_t flags;
  uint8_t ability1;
  uint8_t r_gain;
  uint8_t g_gain;
  uint8_t b_gain;
  uint16_t r_shading_target;
  uint16_t g_shading_target;
  uint16_t b_shading_target;
  uint16_t r_dark_shading_target;
  uint16_t g_dark_shading_target;
  uint16_t b_dark_shading_target;

  /* not returned but usefull in some places */
  uint8_t channels;
} calibration_format;

typedef struct matrix_3x3
{
  uint16_t v[9];
} matrix_3x3;

typedef struct acceleration_info
{
  uint16_t total_steps;
  uint16_t stable_steps;
  uint32_t table_units;
  uint32_t base_units;
  uint16_t start_speed;
  uint16_t target_speed;
  uint8_t ability;
  uint8_t table_count;
  uint8_t reserved[6];
} acceleration_info;

/* set/get SCSI highended (big-endian) variables. Declare them as an array
 * of chars endianness-safe, int-size safe ... */
#define set_double(var,val) var[0] = ((val) >> 8) & 0xff;  \
                            var[1] = ((val)     ) & 0xff

#define set_triple(var,val) var[0] = ((val) >> 16) & 0xff; \
                            var[1] = ((val) >> 8 ) & 0xff; \
                            var[2] = ((val)      ) & 0xff

#define set_quad(var,val)   var[0] = ((val) >> 24) & 0xff; \
                            var[1] = ((val) >> 16) & 0xff; \
                            var[2] = ((val) >> 8 ) & 0xff; \
                            var[3] = ((val)      ) & 0xff

#define get_double(var) ((*var << 8) + *(var + 1))

#define get_triple(var) ((*var << 16) + \
                         (*(var + 1) << 8) + *(var + 2))

#define get_quad(var)   ((*var << 24) + \
                         (*(var + 1) << 16) + \
                         (*(var + 2) << 8) + *(var + 3))

/* set/get Avision lowended (little-endian) shading data */
#define set_double_le(var,val) var[0] = ((val)     ) & 0xff;  \
                               var[1] = ((val) >> 8) & 0xff

#define get_double_le(var) ((*(var + 1) << 8) + *var)

#define BIT(n, p) ((n & (1 << p)) ? 1 : 0)

#define SET_BIT(n, p) (n |= (1 << p))
#define CLEAR_BIT(n, p) (n &= ~(1 << p))

/* These should be in saneopts.h */
#define SANE_NAME_FRAME "frame"
#define SANE_TITLE_FRAME SANE_I18N("Number of the frame to scan")
#define SANE_DESC_FRAME  SANE_I18N("Selects the number of the frame to scan")

#define SANE_NAME_DUPLEX "duplex"
#define SANE_TITLE_DUPLEX SANE_I18N("Duplex scan")
#define SANE_DESC_DUPLEX SANE_I18N("Duplex scan provides a scan of the front and back side of the document")

#ifdef AVISION_ENHANCED_SANE
#warning "Compiled Avision backend will violate the SANE standard"
/* Some Avision SANE extensions */
typedef enum
{
  SANE_STATUS_LAMP_WARMING = SANE_STATUS_ACCESS_DENIED + 1	/* lamp is warming up */
}
SANE_Avision_Status;

/* public API extension */

extern SANE_Status ENTRY(media_check) (SANE_Handle handle);

#endif

#endif /* avision_h */