summaryrefslogtreecommitdiff
path: root/backend/hs2p-scsi.h
blob: 25122d58b6c38c6fd8d8151583287df3dd2c537a (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
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
/* sane - Scanner Access Now Easy.
   Copyright (C) 2007 Jeremy Johnson
   This file is part of a SANE backend for Ricoh IS450
   and IS420 family of HS2P Scanners using the SCSI controller.

   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, see <https://www.gnu.org/licenses/>.

   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.

   If you write modifications of your own for SANE, it is your choice
   whether to permit this exception to apply to your modifications.
   If you do not wish that, delete this exception notice. */

#include <time.h>
#include "../include/sane/sane.h"
#include "../include/sane/saneopts.h"
#include "../include/sane/sanei_scsi.h"
#include "../include/sane/sanei_config.h"
#include "../include/sane/sanei_thread.h"

/* 1-2 SCSI STATUS BYTE KEYS                      */
#define HS2P_SCSI_STATUS_GOOD			0x00
#define HS2P_SCSI_STATUS_CHECK			0x02
#define HS2P_SCSI_STATUS_BUSY			0x08
#define HS2P_SCSI_STATUS_RESERVATION CONFLICT	0x18
/* All other status byte keys are reserved        */

/*
 * SCSI Command List for Command Descriptor Block
 * All reserved bit and fields in the CDB must be zero
 * Values in the CDB described as "Reserved" must no be specified
 * The FLAG and LINK bits in the CONTROL byte must be zero
 * Any values in the Vendor Unique field are ignored
 * The Logical Unit Number in the CDB must always be zero
 * All Reserved bit and fields in the data fields must be zero
 * Values of parameters in the data fields described as
 *   "Reserved" or "Not supported" must not be specified
*/

/* 1-3 SCSI COMMANDS				  */
#define HS2P_SCSI_TEST_UNIT_READY       	0x00
#define HS2P_SCSI_REQUEST_SENSE         	0x03
#define HS2P_SCSI_INQUIRY               	0x12
#define HS2P_SCSI_MODE_SELECT           	0x15
#define HS2P_SCSI_RESERVE_UNIT          	0x16
#define HS2P_SCSI_RELEASE_UNIT          	0x17
#define HS2P_SCSI_MODE_SENSE            	0x1a
#define HS2P_SCSI_START_SCAN            	0x1b
#define HS2P_SCSI_RECEIVE_DIAGNOSTICS   	0x1c
#define HS2P_SCSI_SEND_DIAGNOSTICS      	0x1d
#define HS2P_SCSI_SET_WINDOW            	0x24
#define HS2P_SCSI_GET_WINDOW            	0x25
#define HS2P_SCSI_READ_DATA             	0x28
#define HS2P_SCSI_SEND_DATA             	0x2a
#define HS2P_SCSI_OBJECT_POSITION       	0x31
#define HS2P_SCSI_GET_BUFFER_STATUS     	0x34

/* Sense Key Defines                      */
#define HS2P_SK_NO_SENSE		0x00
#define HS2P_SK_RECOVERED_ERROR		0x01
#define HS2P_SK_NOT_READY		0x02
#define HS2P_SK_MEDIUM_ERROR		0x03
#define HS2P_SK_HARDWARE_ERROR		0x04
#define HS2P_SK_ILLEGAL_REQUEST		0x05
#define HS2P_SK_UNIT_ATTENTION		0x06
#define HS2P_SK_DATA_PROJECT		0x07
#define HS2P_SK_BLANK_CHECK		0x08
#define HS2P_SK_VENDOR_UNIQUE		0x09
#define HS2P_SK_COPY_ABORTED		0x0a
#define HS2P_SK_ABORTED_COMMAND		0x0b
#define HS2P_SK_EQUAL			0x0c
#define HS2P_SK_VOLUME_OVERFLOW		0x0d
#define HS2P_SK_MISCOMPARE		0x0e
#define HS2P_SK_RESERVED		0x0f

struct sense_key
{
  int key;
  char *meaning;
  char *description;
};
static struct sense_key sensekey_errmsg[16] = {
  {0x00, "NO SENSE", "Indicates that there is no Sense Key information"},
  {0x01, "RECOVERED ERROR", "Invalid"},
  {0x02, "NOT READY",
   "Indicates that the scanner is not ready, e.g. ADF cover not closed"},
  {0x03, "MEDIUM ERROR", "Error regarding document such as paper jam"},
  {0x04, "HARDWARE ERROR",
   "Error relating to hardware, e.g. CCD line clock error"},
  {0x05, "ILLEGAL REQUEST",
   "Used such as when illegal parameter exists in data or command"},
  {0x06, "UNIT ATTENTION",
   "Used when power on, BUS DEVICE RESET message or hardware reset"},
  {0x07, "DATA PROJECT", "Invalid"},
  {0x08, "BLANK CHECK", "Invalid"},
  {0x09, "VENDOR UNIQUE", "Invalid"},
  {0x0a, "COPY ABORTED", "Invalid"},
  {0x0b, "ABORTED COMMAND", "Used when scanner aborts a command execution"},
  {0x0c, "EQUAL", "Invalid"},
  {0x0d, "VOLUME OVERFLOW", "Invalid"},
  {0x0e, "MISCOMPARE", "Invalid"},
  {0x0f, "RESERVED", "Invalid"}
};

/* When Error_Code = 0x70 more detailed information is available:
 * code, qualifier, description
*/
struct ASCQ
{				/* ADDITIONAL SENSE CODE QUALIFIER */
  unsigned int codequalifier;
  char *description;
};
static struct ASCQ ascq_errmsg[74] = {
  {0x0000, "No additional sense information"},
  {0x0002, "End of Medium detected"},
  {0x0005, "End of Data detected"},
  {0x0400, "Logical unit not ready. Don't know why."},
  {0x0401, "Logical unit is in process of becoming ready."},
  {0x0403, "Logical unit not ready. Manual intervention required."},
  {0x0500, "Logical unit does not respond to selection."},
  {0x0700, "Multiple peripheral devices selected."},
  {0x1100, "Unrecovered read error."},
  {0x1101, "Read retries exhausted."},
  {0x1501, "Mechanical positioning error."},
  {0x1a00, "Parameter list length error."},
  {0x2000, "Invalid command operation mode."},
  {0x2400, "Invalid field in CDB (check field pointer)."},
  {0x2500, "Logical unit not supported."},
  {0x2600, "Invalid field in parameter list (check field pointer)."},
  {0x2900, "Power on, reset, or BUS DEVICE RESET occurred."},
  {0x2a01, "(MODE parameter changed.)"},
  {0x2c00, "Command sequence error."},
  {0x2c01, "(Too many windows specified."},
  {0x2c02, "(Invalid combination of windows specified."},
  {0x3700, "(Rounded parameter.)"},
  {0x3900, "(Saving parameters not supported.)"},
  {0x3a00, "Medium not present."},
  {0x3b09, "(Read past end of medium.)"},
  {0x3b0b, "(Position past end of medium.)"},
  {0x3d00, "Invalid bits in IDENTIFY message."},
  {0x4300, "Message error."},
  {0x4500, "Select/Reselect failure."},
  {0x4700, "(SCSI parity error)"},
  {0x4800, "Initiator detected error message received."},
  {0x4900, "Invalid message error."},
  {0x4a00, "Command phase error."},
  {0x4b00, "Data phase error."},
  {0x5300, "(Media Load/Eject failed)"},
  {0x6000, "Lamp failure"},
  {0x6001, "(Shading Error)"},
  {0x6002, "White adjustment error"},
  {0x6010, "Reverse Side Lamp Failure"},
  {0x6200, "Scan head positioning error"},
  {0x6300, "Document Waiting Cancel"},
  {0x8000, "(PSU overheat)"},
  {0x8001, "(PSU 24V fuse down)"},
  {0x8002, "(ADF 24V fuse down)"},
  {0x8003, "(5V fuse down)"},
  {0x8004, "(-12V fuse down)"},
  {0x8100, "(ADF 24V power off)"},
  {0x8101, "(Base 12V power off)"},
  {0x8102, "(SCSI 5V power off)"},
  {0x8103, "Lamp cover open (Lamp 24V power off)"},
  {0x8104, "(-12V power off)"},
  {0x8105, "(Endorser 6V power off)"},
  {0x8106, "SCU 3.3V power down error"},
  {0x8107, "RCU 3.3V power down error"},
  {0x8108, "OIPU 3.3V power down error"},
  {0x8200, "Memory Error (Bus error)"},
  {0x8210, "Reverse-side memory error (Bus error)"},
  {0x8300, "(Image data processing LSI error)"},
  {0x8301, "(Interfac LSI error)"},
  {0x8302, "(SCSI controller error)"},
  {0x8303, "(Compression unit error)"},
  {0x8304, "(Marker detect unit error)"},
  {0x8400, "Endorser error"},
  {0x8500, "(Origin Positioning error)"},
  {0x8600, "Mechanical Time Out error (Pick Up Roller error)"},
  {0x8700, "(Heater error)"},
  {0x8800, "(Thermistor error)"},
  {0x8900, "ADF cover open"},
  {0x8901, "(ADF lift up)"},
  {0x8902, "Document jam error for ADF"},
  {0x8903, "Document misfeed for ADF"},
  {0x8a00, "(Interlock open)"},
  {0x8b00, "(Not enough memory)"},
  {0x8c00, "Size detection failed"}
};

typedef struct sense_data
{				/* HS2P_REQUEST_SENSE_DATA  */
  /* bit7:valid is 1 if information byte is valid,
     bits6:0 error_code */
  SANE_Byte error_code;

  /* not used, set to 0 */
  SANE_Byte segment_number;

  /* bit7 file-mark (unused, set to 0),
     bit6 EOM is 1 if end of document detected before completing scan
     bit5 ILI (incorrect length indicator) is 1 when data length mismatch occurs on READ
     bits3:0 sense_key indicates error conditions.  */
  SANE_Byte sense_key;

  SANE_Byte information[4];

  /* fixed at 6 */
  SANE_Byte sense_length;

  /* not used and set to 0 */
  SANE_Byte command_specific_information[4];
  SANE_Byte sense_code;
  SANE_Byte sense_code_qualifier;
} SENSE_DATA;

/* page codes used with HS2P_SCSI_INQUIRY */
#define HS2P_INQUIRY_STANDARD_PAGE_CODE 0x00
#define HS2P_INQUIRY_VPD_PAGE_CODE      0xC0
#define HS2P_INQUIRY_JIS_PAGE_CODE      0xF0

/*
 * The EVPD and Page Code are used in pair. When the EVPD bit is 0, INQUIRY data
 * in the standard format is returned to the initiator. When the EVPD bit is 1,
 * the EVPD information specified by each Page Code is returned in each Page Code
 * data format.
 *
 * EVPD=0x00, Page_Code=0x00      => Standard Data Format
 *
 * EVPD=0x01, PAGE_CODE=0x00      => Return list of supported Page Codes
 * EVPD=0x01, PAGE_CODE=0x01~0x7F => Not Supported
 * EVPD=0x01, PAGE_CODE=0x80~0x82 => Not Supported
 * EVPD=0x01, PAGE_CODE=0x83~0xBF => Reserved
 * EVPD=0x01, PAGE_CODE=0xC0      => RICOH Scanner VPD information
 * EVPD=0x01, PAGE_CODE=0xF0      => JIS Version VPD information
*/
struct inquiry_standard_data
{
  /* bits7-5 peripheral qualifier
   * bits4-0 peripheral device
   * Peripheral Qualifier and Peripheral Devide Type are not supported on logical unit
   * Therefore LUN=0 and this field indicates scanner and is set to 0x06
   * When LUN!=0 this field becomes 0x1F and means undefined data
   */
  SANE_Byte devtype;		/* must be 0x06 */

  /* bit7: repaceable media bit is set to 0
   * bits6-1: reserved
   * bit0: EVPD
   */
  SANE_Byte rmb_evpd;

  /* bits7-6: ISO Version  is set to 0
   * bits5-3: ECMA Version is set to 0
   * bits2-0: ANSI Version is set to 2
   */
  SANE_Byte version;

  /* bit7: AENC (asynchronous event notification capability) is set to 0
   * bit6: TrmIOP (terminate I/O process) is set to 0
   * bits5-4: reserved
   * bits3-0: Response Data Format is set to 2
   */
  SANE_Byte response_data_format;

  /* Additional Length indicate number of bytes which follows, set to 31
   */
  SANE_Byte length;

  SANE_Byte reserved[2];

  /* bit7: RelAdr (relative addressing) is set to 0
   * bit6: Wbus32 is set to 0
   * bit5: Wbus16 is set to 0
   * bit4: Sync   is set to 0
   * bit3: Linked is set to 0
   * bit2: reserved
   * bit1: CmdQue is set to 0
   * bit0: SftRe  is set to 0
   * Sync is set to 1 with this scanner to support synchronous data transfer
   * When DIPSW2 is on, Sync is set to 0 for asynchronous data transfer
   */
  SANE_Byte byte7;

  SANE_Byte vendor[8];		/* vendor_id="RICOH   " */
  SANE_Byte product[16];	/* product_id="IS450           " */
  SANE_Byte revision[4];	/* product_revision_level="xRxx" where x indicate firmware version number */
};

/* VPD Information [EVPD=0x01, PageCode=0xC0] */
struct inquiry_vpd_data
{
  SANE_Byte devtype;		/* bits7-5: Peripheral Qualifier
				 * bits4-0: Peripheral Device Type */
  SANE_Byte pagecode;		/* Page Code  => 0xC0 */
  SANE_Byte byte2;		/* Reserved */
  SANE_Byte pagelength;		/* Page Length => 12 (0x0C) */
  SANE_Byte adf_id;		/* ADF Identification
				 * 0: No ADF is mounted
				 * 1: Single sided ADF is mounted
				 * 2: Double sided ADF is mounted
				 * 3: ARDF is mounted. (Reverse double side scanning available)
				 * 4: Reserved
				 * It should be 1 or 2 with this scanner.
				 */
  SANE_Byte end_id;		/* Endorser Identification
				 * 0: No endorser
				 * 1: Endorser mounted
				 * 2: Reserved
				 * It should be 0 or 1 with this scanner
				 */
  SANE_Byte ipu_id;		/* Image Processing Unit Identification
				 * bits 7:2   Reserved
				 * bit 1    0:Extended board not mounted
				 *          1:Extended board is mounted
				 * bit 0    0:IPU is not mounted
				 *          1:IPU is mounted
				 * It should always be 0 with this scanner
				 */
  SANE_Byte imagecomposition;	/* indicates supported image data type.
				 * This is set to 0x37
				 * bit0 => Line art          supported ? 1:0
				 * bit1 => Dither            supported ? 1:0
				 * bit2 => Error Diffusion   supported ? 1:0
				 * bit3 => Color             supported ? 1:0
				 * bit4 => 4bits gray scale  supported ? 1:0
				 * bit5 => 5-8bit gray scale supported ? 1:0
				 * bit6 => 5-8bit gray scale supported ? 1:0
				 * bit7 => Reserved
				 */
  SANE_Byte imagedataprocessing[2];	/* Image Data Processing Method
					 * IPU installed ? 0x18 : 0x00
					 * Byte8  => White Framing   ? 1:0
					 * Byte9  => Black Framing   ? 1:0
					 * Byte10 => Edge Extraction ? 1:0
					 * Byte11 => Noise Removal   ? 1:0
					 * Byte12 => Smoothing       ? 1:0
					 * Byte13 => Line Bolding    ? 0:1
					 * Byte14 => Reserved
					 * Byte15 => Reserved
					 */
  SANE_Byte compression;	/* Compression Method is set to 0x00
				 * bit0 => MH                 supported ? 1:0
				 * bit1 => MR                 supported ? 1:0
				 * bit2 => MMR                supported ? 1:0
				 * bit3 => MH (byte boundary) supported ? 1:0
				 * bit4 => Reserved
				 */
  SANE_Byte markerrecognition;	/* Marker Recognition Method is set to 0x00
				 * bit0    => Marker Recognition supported ? 1:0
				 * bits1-7 => Reserved
				 */
  SANE_Byte sizerecognition;	/* Size Detection
				 * bit0    => Size Detection Supported ? 1:0
				 * bits1-7 => Reserved
				 */
  SANE_Byte byte13;		/* Reserved */
  SANE_Byte xmaxoutputpixels[2];	/* X Maximum Output Pixel is set to 4960 (0x1360)
					 * indicates maximum number of pixels in the main
					 * scanning direction that can be output by scanner
					 */

};

struct inquiry_jis_data
{				/* JIS INFORMATION  VPD_IDENTIFIER_F0H */
  SANE_Byte devtype;		/* 7-5: peripheral qualifier, 4-0: peripheral device type */
  SANE_Byte pagecode;
  SANE_Byte jisversion;
  SANE_Byte reserved1;
  SANE_Byte alloclen;		/* page length: Set to 25 (19H)  */
  struct
  {
    SANE_Byte x[2];		/* Basic X Resolution: Set to 400 (01H,90H) */
    SANE_Byte y[2];		/* Basic Y Resolution: Set to 400 (01H,90H) */
  } BasicRes;
  SANE_Byte resolutionstep;	/* 7-4: xstep, 3-0 ystep: Both set to 1 (11H) */
  struct
  {
    SANE_Byte x[2];		/* Maximum X resolution: Set to 800 (03H,20H) */
    SANE_Byte y[2];		/* Maximum Y resolution: Set to 800 (03H,20H) */
  } MaxRes;
  struct
  {
    SANE_Byte x[2];		/* Minimum X resolution: Set to 100 (00H,64H) */
    SANE_Byte y[2];		/* Minimum Y resolution */
  } MinRes;
  SANE_Byte standardres[2];	/* Standard Resolution: bits 7-0:
				 * byte18:  60, 75,100,120,150,160,180, 200
				 * byte19: 240,300,320,400,480,600,800,1200
				 */
  struct
  {
    SANE_Byte width[4];		/* in pixels based on basic resolution. Set to 4787 (12B3H) */
    SANE_Byte length[4];	/* maximum number of scan lines based on basic resolution. Set to 6803 (1A93H) */
  } Window;
  SANE_Byte functions;		/* This is set to 0EH: 0001110
				 * bit0:    data overflow possible
				 * bit1:    line art support
				 * bit2:    dither support
				 * bit3:    gray scale support
				 * bits7-4: reserved
				 */
  SANE_Byte reserved2;
};



#define SMS_SP  0x01		/* Mask for Bit0                                       */
#define SMS_PF  0x10		/* Mask for Bit4                                       */
typedef struct scsi_mode_select_cmd
{
  SANE_Byte opcode;		/* 15H                                                 */
  SANE_Byte byte1;		/* 7-5:LUN; 4:PF; 2:Reserved; 1:SP
				 * Save Page Bit must be 0 since pages cannot be saved
				 * Page Format Bit must be 1                           */
  SANE_Byte reserved[2];
  SANE_Byte len;		/* Parameter List Length                               */
  SANE_Byte control;		/* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link     */
} SELECT;

/* MODE SELECT PARAMETERS:
 * 0-n Mode Parameter Header
 * 0-n mode Block Descriptor (not used)
 * 0-n mode Page
*/
typedef struct scsi_mode_parameter_header
{
  SANE_Byte data_len;		/* Mode Data Length          NOT USED so must be 0 */
  SANE_Byte medium_type;	/* Medium Type               NOT USED so must be 0 */
  SANE_Byte dev_spec;		/* Device Specific Parameter NOT USED so must be 0 */
  SANE_Byte blk_desc_len;	/* Block Descriptor Length             is set to 0 */
} MPHdr;

typedef struct page
{
  SANE_Byte code;		/* 7:PS; 6:Reserved; 5-0:Page Code            */
  SANE_Byte len;		/* set to 14 when MPC=02H and 6 otherwise     */
  SANE_Byte parameter[14];	/* either 14 or 6, so let's allow room for 14 */
} MPP;				/* Mode Page Parameters */
typedef struct mode_pages
{
  MPHdr hdr;			/* Mode Page Header      */
  MPP page;			/* Mode Page Parameters  */
} MP;
					     /* MODE PAGE CODES  (MPC)                    */
					     /* 00H Reserved (Vendor Unique)              */
					     /* 01H Reserved                              */
#define PAGE_CODE_CONNECTION            0x02	/* 02H Disconnect/Reconnect Parameters       */
#define PAGE_CODE_SCANNING_MEASUREMENTS 0x03	/* 03H Scanning Measurement Parameters       */
					     /* 04H-08H Reserved                          */
					     /* 09H-0AH Reserved (Not supported)          */
					     /* 0BH-1FH Reserved                          */
#define PAGE_CODE_WHITE_BALANCE        0x20	/* 20H White Balance                         */
					     /* 21H Reserved (Vendor Unique)              */
#define PAGE_CODE_LAMP_TIMER_SET       0x22	/* 22H Lamp Timer Set                        */
#define PAGE_CODE_SCANNING_SPEED       0x23	/* 23H Reserved (Scanning speed select)      */
					     /* 24H Reserved (Vendor Unique)              */
					     /* 25H Reserved (Vendor Unique)              */
#define PAGE_CODE_ADF_CONTROL          0x26	/* 26H ADF Control                           */
#define PAGE_CODE_ENDORSER_CONTROL     0x27	/* 27H Endorser Control                      */
					     /* 28H Reserved (Marker Area Data Processing) */
					     /* 29H-2AH Reserved (Vendor Unique)          */
#define PAGE_CODE_SCAN_WAIT_MODE       0x2B	/* 2BH Scan Wait Mode (Medium Wait Mode)     */
					     /* 2CH-3DH Reserved (Vendor Unique)          */
#define PAGE_CODE_SERVICE_MODE_SELECT  0x3E	/* 3EH Service Mode Select                   */
					     /* 3FH Reserved (Not Supported)              */

typedef struct mode_page_connect
{
  MPHdr hdr;			/* Mode Page Header: 4 bytes            */
  SANE_Byte code;		/* 7-6:Reserved; 5-0: 02H  */
  SANE_Byte len;		/* Parameter Length 0EH    */
  SANE_Byte buffer_full_ratio;	/* Ignored                 */
  SANE_Byte buffer_empty_ratio;	/* Ignored                 */
  SANE_Byte bus_inactive_limit[2];	/* Ignored                 */
  SANE_Byte disconnect_time_limit[2];	/* indicates minimum time to disconnect SCSI bus until reconnection.
					 * It is expressed in 100msec increments; i.e. "1" for 100msec, "2" for 200msec
					 * The maximum time is 2sec */
  SANE_Byte connect_time_limit[2];	/* Ignored                  */
  SANE_Byte maximum_burst_size[2];	/* expressed in 512 increments, i.e. "1" for 512 bytes, "2" for 1024 bytes
					 * "0" indicates unlimited amount of data */
  SANE_Byte dtdc;		/* 7-2:Reserved; 1-0:DTDC indicates limitations of disconnection (bit1,bit0):
				 * 00 (DEFAULT) Controlled by the other field in this page
				 * 01 Once the command data transfer starts, the target never disconnects until
				 *    the whole data transfer completes
				 * 10 Reserved
				 * 11 Once the command data transfer starts, the target never disconnects until
				 *    the completion of the command
				 */
  SANE_Byte reserved[3];
} MP_CXN;

/* 1 inch = 6 picas = 72 points = 25.4 mm */
#define DEFAULT_MUD 1200	/* WHY ? */
/* BASIC MEASUREMENT UNIT
 * 00H INCH
 * 01H MILLIMETER
 * 02H POINT
 * 03H-FFH Reserved
*/
enum BMU
{ INCHES = 0, MILLIMETERS, POINTS };	/* Basic Measurement Unit */

typedef struct mode_page_scanning_measurement
{
  MPHdr hdr;			/* Mode Page Header: 4 bytes         */
  SANE_Byte code;		/* 7-6:Reserved; 5-0:Page Code (03H) */
  SANE_Byte len;		/* Parameter Length (06H)            */
  SANE_Byte bmu;		/* Basic Measurement Unit            */
  SANE_Byte reserved0;
  SANE_Byte mud[2];		/* Measurement Unit Divisor
				 * produces an error if 0
				 * mud is fixed to 1 for millimeter or point
				 * point is default when scanner powers on */
  SANE_Byte reserved1[2];
} MP_SMU;			/* Scanning Measurement Units */

typedef struct mode_page_white_balance
{
  MPHdr hdr;			/* Mode Page Header: 4 bytes         */
  SANE_Byte code;		/* 7-6:Reserved; 5-0:Page Code (03H) */
  SANE_Byte len;		/* Parameter Length (06H)            */
  SANE_Byte white_balance;	/* "0" selects relative white mode (DEFAULT when power on)
				 * "1" selects absolute white mode */
  SANE_Byte reserved[5];
} MP_WhiteBal;			/* White Balance */

typedef struct mode_page_lamp_timer_set
{
  MPHdr hdr;			/* Mode Page Header: 4 bytes            */
  SANE_Byte code;		/* 7-6:Reserved; 5-0:Page Code (22H)    */
  SANE_Byte len;		/* Parameter Length (06H)               */
  SANE_Byte time_on;		/* indicates the time of lamp turned on */
  SANE_Byte ignored[5];
} MP_LampTimer;			/* Lamp Timer Set (Not supported ) */

typedef struct mode_page_adf_control
{
  MPHdr hdr;			/* Mode Page Header: 4 bytes            */
  SANE_Byte code;		/* 7-6:Reserved; 5-0:Page Code (26H)    */
  SANE_Byte len;		/* Parameter Length (06H)               */
  SANE_Byte adf_control;	/* 7-2:Reserved; 1-0:ADF selection:
				 * 00H Book Mode (DEFAULT when power on)
				 * 01H Simplex ADF
				 * 02H Duplex ADF
				 * 03H-FFH Reserved                     */
  SANE_Byte adf_mode_control;	/* 7-3:Reserved; 2:Prefeed Mode Validity 1-0:Ignored
				 * Prefeed Mode "0" means invalid, "1" means valid */
  SANE_Byte medium_wait_timer;	/* indicates time for scanner to wait for media. Scanner
				 * will send CHECK on timeout. NOT SUPPORTED */
  SANE_Byte ignored[3];
} MP_ADF;			/* ADF Control */

typedef struct mode_page_endorser_control
{
  MPHdr hdr;			/* Mode Page Header: 4 bytes            */
  SANE_Byte code;		/* 7-6:Reserved; 5-0:Page Code (27H)    */
  SANE_Byte len;		/* Parameter Length (06H)               */
  SANE_Byte endorser_control;	/* 7-3:Reserved; 2-0:Endorser Control:
				 * 0H Disable Endorser (DEFAULT)
				 * 1H Enable Endorser
				 * 3H-7H Reserved                       */
  SANE_Byte ignored[5];
} MP_EndCtrl;			/* Endorser Control */

typedef struct mode_page_scan_wait
{
  MPHdr hdr;			/* Mode Page Header: 4 bytes            */
  SANE_Byte code;		/* 7-6:Reserved; 5-0:Page Code (2BH)    */
  SANE_Byte len;		/* Parameter Length (06H)               */
  SANE_Byte swm;		/* 7-1:Reserved; 0:Scan Wait Mode
				 * 0H Disable Medium wait mode
				 * 1H Enable  Medium wait mode
				 * In Medium wait mode, when SCAN, READ, or LOAD (in ADF mode) is issued,
				 * the scanner waits until start button is pressed on operation panel
				 * When abort button is pressed, the command is cancelled
				 * In ADF mode, when there are no originals on ADF, CHECK condition is
				 * not given unless start button is pressed. */
  SANE_Byte ignored[5];
} MP_SWM;			/* Scan Wait */

typedef struct mode_page_service
{				/* Selectable when Send Diagnostic command is performed */
  MPHdr hdr;			/* Mode Page Header: 4 bytes            */
  SANE_Byte code;		/* 7-6:Reserved; 5-0:Page Code (3EH)    */
  SANE_Byte len;		/* Parameter Length (06H)               */
  SANE_Byte service;		/* 7-1:Reserved; 0:Service Mode
				 * "0" selects Self Diagnostics mode (DEFAULT when power on )
				 * "1" selects Optical Adjustment mode  */
  SANE_Byte ignored[5];
} MP_SRV;			/* Service */

typedef struct scsi_mode_sense_cmd
{
  SANE_Byte opcode;		/* 1AH */
  SANE_Byte dbd;		/* 7-5:LUN; 4:Reserved; 3:DBD (Disable Block Description) set to "0"; 2-0:Reserved */
  SANE_Byte pc;			/* 7-6:PC; 5-0:Page Code
				 * PC field indicates the type of data to be returned (bit7,bit6):
				 * 00 Current Value   (THIS IS THE ONLY VALUE WHICH WORKS!)
				 * 01 Changeable Value
				 * 10 Default Value
				 * 11 Saved Value
				 *
				 * Page Code indicates requested page. (See PAGE_CODE defines) */
  SANE_Byte reserved;
  SANE_Byte len;		/* Allocation length */
  SANE_Byte control;		/* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link */
} SENSE;
/* MODE SENSE DATA FORMAT --
 * The format of Sense Data to be returned is Mode Parameter Header + Page
 * see struct scsi_mode_parameter_header
 *     struct mode_pages
*/

/* 1-3-8 SCAN command */
typedef struct scsi_start_scan_cmd
{
  SANE_Byte opcode;		/* 1BH                   */
  SANE_Byte byte1;		/* 7-5:LUN; 4-0:Reserved */
  SANE_Byte page_code;
  SANE_Byte reserved;
  SANE_Byte len;		/* Transfer Length
				 * Length of Window List in bytes
				 * Since scanner supports up to 2 windows, len is 1 or 2
				 */
  SANE_Byte control;		/* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link */
} START_SCAN;

/* 1-3-9 RECEIVE DIAGNOSTIC
 * 1-3-10 SEND DIAGNOSTIC */

/* BinaryFilter Byte
 * bit7: Noise Removal '1':removal
 * bit6: Smoothing     '1':smoothing
 * bits5-2: ignored
 * bits1-0: Noise Removal Matrix
 * 00:3x3    01:4x4
 * 10:5x5    11:Reserved
*/
struct val_id
{
  SANE_Byte val;
  SANE_Byte id;
};
static SANE_String_Const noisematrix_list[] = {
  "None", "3x3", "4x4", "5x5", NULL
};
struct val_id noisematrix[] = {
  {0x03, 0},			/* dummy <reserved> value for "None" */
  {0x00, 1},
  {0x01, 2},
  {0x02, 3}
};
static SANE_String_Const grayfilter_list[] = {
  "none", "averaging", "MTF correction", NULL
};
struct val_id grayfilter[] = {
  {0x00, 0},
  {0x01, 1},
  {0x03, 2}
};

static SANE_String_Const paddingtype_list[] = {
  "Pad with 0's to byte boundary",
  "Pad with 1's to byte boundary",
  "Truncate to byte boundary",
  NULL
};
enum paddingtypes
{ PAD_WITH_ZEROS = 0x01, PAD_WITH_ONES, TRUNCATE };
struct val_id paddingtype[] = {
  {PAD_WITH_ZEROS, 0},
  {PAD_WITH_ONES, 1},
  {TRUNCATE, 2}
};

#define NPADDINGTYPES 3
#define PADDINGTYPE_DEFAULT 2
static SANE_String_Const auto_separation_list[] = {
  "Off", "On", "User", NULL
};
struct val_id auto_separation[] = {
  {0x00, 0},
  {0x01, 1},
  {0x80, 2}
};
static SANE_String_Const auto_binarization_list[] = {
  "Off",
  "On",
  "Enhancement of light characters",
  "Removal of background color",
  "User",
  NULL
};
struct val_id auto_binarization[] = {
  {0x00, 0},
  {0x01, 1},
  {0x02, 2},
  {0x03, 3},
  {0x80, 4}
};
enum imagecomposition
{ LINEART = 0x00, HALFTONE, GRAYSCALE };
enum halftonecode
{ DITHER = 0x02, ERROR_DIFFUSION };
static SANE_String_Const halftone_code[] = {
  "Dither", "Error Diffusion", NULL
};
static SANE_String_Const halftone_pattern_list[] = {
  "8x4, 45 degree",
  "6x6, 90 degree",
  "4x4, spiral",
  "8x8, 90 degree",
  "70 lines",
  "95 lines",
  "180 lines",
  "16x8, 45 degree",
  "16x16, 90 degree",
  "8x8, Bayer",
  "User #1",
  "User #2",
  NULL
};
struct val_id halftone[] = {
  {0x01, 1},
  {0x02, 2},
  {0x03, 3},
  {0x04, 4},
  {0x05, 5},
  {0x06, 6},
  {0x07, 7},
  {0x08, 9},
  {0x09, 9},
  {0x0A, 10},
  {0x80, 11},
  {0x81, 12}
};

#if 0
static struct
{
  SANE_Byte code;
  char *type;
} compression_types[] =
{
  {
  0x00, "No compression"},
  {
  0x01, "CCITT G3, 1-dimensional (MH)"},
  {
  0x02, "CCITT G3, 2-dimensional (MR)"},
  {
  0x03, "CCITT G4, 2-dimensional (MMR)"},
    /* 04H-0FH Reserved
     * 10H Reserved (not supported)
     * 11H-7FH Reserved
     */
  {
  0x80, "CCITT G3, 1-dimensional (MH) Padding with 0's to byte boundary"}
  /* 80H-FFH Reserved (Vendor Unique) */
};
static struct
{
  SANE_Byte code;
  char *argument;
} compression_argument[] =
{
  /* 00H Reserved */
  /* 01H Reserved */
  {
  0x02, "K factor-0~255"}
  /* 03H Reserved */
  /* 04H-0FH Reserved */
  /* 10H Reserved */
  /* 11H-7FH Reserved */
  /* 80H Reserved */
  /* 80H-FFH Reserved */
};
#endif
#define GAMMA_NORMAL  0x00
#define GAMMA_SOFT    0x01
#define GAMMA_SHARP   0x02
#define GAMMA_LINEAR  0x03
#define GAMMA_USER    0x08
/* 04H-07H Reserved */
/* 09H-0FH Reserved */
static SANE_String gamma_list[6] = {
  "Normal", "Soft", "Sharp", "Linear", "User", NULL
};

/* 1-3-11 SET WINDOW command */

struct window_section
{				/* 32 bytes */
  SANE_Byte sef;		/*byte1 7-2:ignored 1:SEF '0'-invalid section; '1'-valid section */
  SANE_Byte ignored0;
  SANE_Byte ulx[4];
  SANE_Byte uly[4];
  SANE_Byte width[4];
  SANE_Byte length[4];
  SANE_Byte binary_filtering;
  SANE_Byte ignored1;
  SANE_Byte threshold;
  SANE_Byte ignored2;
  SANE_Byte image_composition;
  SANE_Byte halftone_id;
  SANE_Byte halftone_code;
  SANE_Byte ignored3[7];
};
/* 1-3-11 SET WINDOW COMMAND
 * Byte0: 24H
 * Byte1: 7-5: LUN; 4-0: Reserved
 * Byte2-5: Reserved
 * Byte6-8: Transfer Length
 * Byte9: 7-6: Vendor Unique; 5-2: Reserved; 1: Flag; 0: Link
 *
 * Transfer length indicates the byte length of Window Parameters (Set Window Data Header +
 * Window Descriptor Bytes transferred from the initiator in the DATA OUT PHASE
 * The scanner supports 2 windows, so Transfer Length is 648 bytes:
 * Set Window Header 8 bytes + Window Descriptor Bytes 640 (320*2) bytes).
 * If data length is longer than 648 bytes only the first 648 bytes are valid, The remainng data is ignored.
 * If data length is shorter than 648 only the specified byte length is valid data.
 *
 *
 * WINDOW DATA HEADER
 * Byte0-5: Reserved
 * Byte6-7: Window Descriptor Length (WDL)
 *          WDL indicates the number of bytes of one Window Descriptor Bytes which follows.
 *          In this scanner, this value is 640 since it supports 2 windows.
 *
 * WINDOW DESCRIPTOR BYTES
*/
#define HS2P_WINDOW_DATA_SIZE 640
struct hs2p_window_data
{				/* HS2P_WINDOW_DATA_FORMAT       */
  SANE_Byte window_id;		/*     0: Window Identifier      */
  SANE_Byte auto_bit;		/*     1: 1-1:Reserved; 0:Auto   */
  SANE_Byte xres[2];		/*   2-3: X-Axis Resolution      100-800dpi in 1dpi steps */
  SANE_Byte yres[2];		/*   4-5: Y-Axis Resolution      100-800dpi in 1dpi steps */
  SANE_Byte ulx[4];		/*   6-9: X-Axis Upper Left      */
  SANE_Byte uly[4];		/* 10-13: Y-Axis Upper Left      */
  SANE_Byte width[4];		/* 14-17: Window Width           */
  SANE_Byte length[4];		/* 18-21: Window Length          */
  SANE_Byte brightness;		/*    22: Brightness  [0-255] dark-light 0 means default value of 128 */
  SANE_Byte threshold;		/*    23: Threshold   [0-255] 0 means default value of 128            */
  SANE_Byte contrast;		/*    24: Contrast    [0-255] low-high   0 means default value of 128 */
  SANE_Byte image_composition;	/*    25: Image Composition
				 *        00H Lineart
				 *        01H Dithered Halftone
				 *        02H Gray scale
				 */
  SANE_Byte bpp;		/*    26: Bits Per Pixel         */
  SANE_Byte halftone_code;	/*    27: Halftone Code
				 *        00H-01H Reserved
				 *        02H Dither (partial Dot)
				 *        03H Error Diffusion
				 *        04H-07H Reserved
				 */
  SANE_Byte halftone_id;	/*    28: Halftone ID
				 *        00H Reserved
				 *        01H 8x4, 45 degree
				 *        02H 6x6, 90 degree
				 *        03H 4x4, Spiral
				 *        04H 8x8, 90 degree
				 *        05H 70 lines
				 *        06H 95 lines
				 *        07H 180 lines
				 *        08H 16x8, 45 degree
				 *        09H 16x16, 90 degree
				 *        0AH 8x8, Bayer
				 *        0Bh-7FH Reserved
				 *        80H Download #1
				 *        81H Download #2
				 *        82H-FFH Reserved
				 */
  SANE_Byte byte29;		/*    29:   7: RIF (Reverse Image Format) bit inversion
				 *             Image Composition field must be lineart or dithered halftone
				 *             RIF=0: White=0 Black=1
				 *             RIF=1: White=1 Black=0
				 *        6-3: Reserved;
				 *        2-0: Padding Type:
				 *             00H Reserved
				 *             01H Pad with 0's to byte boundary
				 *             02H Pad with 1's to byte boundary
				 *             03H Truncate to byte boundary
				 *             04H-FFH Reserved
				 */
  SANE_Byte bit_ordering[2];	/* 30-31: Bit Ordering: Default 0xF8
				 *        0: 0=>output from bit0 of each byte; 1=>output from bit7
				 *        1: 0=>output from LSB; 1=>output from MSB
				 *        2: 0=>unpacked 4 bits gray; 1=>Packed 4 bits gray
				 *        3: 1=>Bits arrangement from LSB in grayscale; 0=>from MSB
				 *      4-6: reserved
				 *        7: 1=>Mirroring; 0=>Normal output
				 *     8-15: reserved
				 */
  SANE_Byte compression_type;	/*    32: Compression Type:     Unsupported in IS450   */
  SANE_Byte compression_arg;	/*    33: Compression Argument: Unsupported in IS450   */
  SANE_Byte reserved2[6];	/* 34-39: Reserved               */
  SANE_Byte ignored1;		/*    40: Ignored                */
  SANE_Byte ignored2;		/*    41: Ignored                */
  SANE_Byte byte42;		/*    42:   7: MRIF: Grayscale Reverse Image Format
				 *             MRIF=0: White=0 Black=1
				 *             MRIF=1: White=1 Black=0
				 *        6-4: Filtering: for Grayscale
				 *             000 No filter
				 *             001 Averaging
				 *             010 Reserved
				 *             011 MTF Correction
				 *             100 Reserved
				 *             110 Reserved
				 *             111 Reserved
				 *        3-0: Gamma ID
				 *             00H Normal
				 *             01H Soft
				 *             02H Sharp
				 *             03H Linear
				 *             04H-07H Reserved
				 *             08H Download table
				 *             09H-0FH Reserved
				 */
  SANE_Byte ignored3;		/*    43: Ignored                */
  SANE_Byte ignored4;		/*    44: Ignored                */
  SANE_Byte binary_filtering;	/*    45: Binary Filtering
				 *        0-1: Noise Removal Matrix:
				 *             00: 3x3
				 *             01: 4x4
				 *             10: 5x5
				 *             11: Reserved
				 *        5-2: Ignored
				 *          6: Smoothing Flag
				 *          7: Noise Removal Flag
				 *
				 *          Smoothing and Noise removal can be set when option IPU is installed
				 *          Setting is ignored for reverse side because optional IPU is not valid
				 *          for reverse side scanning
				 */
  /*
   *  The following is only available when IPU is installed:
   *  SECTION, Automatic Separation, Automatic Binarization
   *  46-319 is ignored for Window 2
   */
  SANE_Byte ignored5;		/*    46: Ignored                       */
  SANE_Byte ignored6;		/*    47: Ignored                       */
  SANE_Byte automatic_separation;	/*    48: Automatic Separation
					 *            00H OFF
					 *            01H Default
					 *        02H-7FH Reserved
					 *            80H Download table
					 *        91H-FFH Reserved
					 */
  SANE_Byte ignored7;		/*    49: Ignored                       */
  SANE_Byte automatic_binarization;	/*    50: Automatic Binarization
					 *            00H OFF
					 *            01H Default
					 *            02H Enhancement of light characters
					 *            03H Removal of background color
					 *        04H-7FH Reserved
					 *            80H Download table
					 *        81H-FFH Reserved
					 */
  SANE_Byte ignored8[13];	/* 51-63: Ignored                       */
  struct window_section sec[8];	/* Each window can have multiple sections, each of 32 bytes long
				 * 53-319: = 256 bytes = 8 sections of 32 bytes
				 * IS450 supports up to 4 sections,
				 * IS420 supports up to 6 sections
				 */
};
struct set_window_cmd
{
  SANE_Byte opcode;		/* 24H */
  SANE_Byte byte2;		/* 7-5:LUN 4-0:Reserve */
  SANE_Byte reserved[4];	/* Reserved */
  SANE_Byte len[3];		/* Transfer Length */
  SANE_Byte control;		/* 76543210
				 * XX       Vendor Unique
				 *   XXXX   Reserved
				 *       X  Flag
				 *        X Link
				 */
};
struct set_window_data_hdr
{
  SANE_Byte reserved[6];
  SANE_Byte len[2];
};
typedef struct set_window_data
{
  struct set_window_data_hdr hdr;
  struct hs2p_window_data data[2];
} SWD;

/* 1-3-12 GET WINDOW command */
struct get_window_cmd
{
  SANE_Byte opcode;
  SANE_Byte byte1;		/* 7-5: LUN; * 4-1:Reserved; *   0:Single bit is 0 */
  SANE_Byte reserved[3];
  SANE_Byte win_id;		/* Window ID is either 0 or 1 */
  SANE_Byte len[3];		/* Transfer Length */
  SANE_Byte control;		/* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link */
};
/* The data format to be returned is Get Window Data header + Window Descriptor Bytes
 * The format of Window Descriptor Bytes is the same as that for SET WINDOW
*/
struct get_window_data_hdr
{
  SANE_Byte data_len[2];	/* Window Data Length indicates byte len of data which follows less its own 2 bytes */
  SANE_Byte reserved[4];
  SANE_Byte desc_len[2];	/* Window Descriptor Length indicates byte length of one Window Descriptor which is 640 */
};
typedef struct get_window_data
{
  struct get_window_data_hdr hdr;
  struct hs2p_window_data data[2];
} GWD;

/* READ/SEND DATA TYPE CODES  */
/* DATA TYPE CODES (DTC):                       */
#define DATA_TYPE_IMAGE                      0x00
/* 01H Reserved (Vendor Unique)                 */
#define DATA_TYPE_HALFTONE                   0x02
#define DATA_TYPE_GAMMA                      0x03
/*04H-7FH Reserved                              */
#define DATA_TYPE_ENDORSER                   0x80
#define DATA_TYPE_SIZE                       0x81
/* 82H Reserved                                 */
/* 83H Reserved (Vendor Unique)                 */
#define DATA_TYPE_PAGE_LEN                   0x84
#define DATA_TYPE_MAINTENANCE                0x85
#define DATA_TYPE_ADF_STATUS                 0x86
/* 87H Reserved (Skew Data)                     */
/* 88H-91H Reserved (Vendor Unique)             */
/* 92H Reserved (Scanner Extension I/O Access)  */
/* 93H Reserved (Vendor Unique)                 */
/* 94H-FFH Reserved (Vendor Unique)             */
#define DATA_TYPE_EOL			     -1	/* va_end */

/* DATA TYPE QUALIFIER CODES when DTC=93H       */
#define DTQ				     0x00	/* ignored */
#define DTQ_AUTO_PHOTOLETTER                 0x00	/* default */
#define DTQ_DYNAMIC_THRESHOLDING             0x01	/* default */
#define DTQ_LIGHT_CHARS_ENHANCEMENT          0x02
#define DTQ_BACKGROUND_REMOVAL               0x03
/* 04H-7FH Reserved                             */
#define DTQ_AUTO_PHOTOLETTER_DOWNLOAD_TABLE  0x80
#define DTQ_DYNAMIC_THRESHOLD_DOWNLOAD_TABLE 0x81
/* 82H-FFH Reserved                             */

/* 1-3-13 READ command */
/* 1-3-14 SEND command */
struct scsi_rs_scanner_cmd
{
  SANE_Byte opcode;		/* READ=28H  SEND=2AH                    */
  SANE_Byte byte1;		/* 7-5:LUN; 4-0:Reserved                 */
  SANE_Byte dtc;		/* Data Type Code: See DTC DEFINES above */
  SANE_Byte reserved;
  SANE_Byte dtq[2];		/* Data Type Qualifier valid only for DTC 02H,03H,93H */
  SANE_Byte len[3];		/* Transfer Length */
  SANE_Byte control;		/* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link */
};
/*
 * Data Format for Image Data
 * Non-compressed: {first_line, second_line, ... nth_line}
 * MH/MR Compression: {EOL, 1st_line_compressed, EOL, 2nd_line_compressed,..., EOL, last_line_compressed, EOL,EOL,EOL,EOL,EOL,EOL
 *       where EOL = 000000000001
 * MMR Compression: = {1st_line_compressed, 2nd_line_compressed,...,last_line_compressed, EOL,EOL}
 *
 * Normal Binary Output: MSB-LSB 1stbytes,2nd,3rd...Last
 * Mirror Binary Output: MSB-LSB Last,...2nd,1st
 *
 * Normal Gray Output MSB-LSB: 1st,2nd,3rd...Last
 *       4 bit/pixel gray: [32103210]
 *       8 bit/pixel gray: [76543210]
 * Mirror Gray Output MSB-LSB Last,...2nd,1st
 *
 *
 * HALFTONE MASK DATA: 1byte(row,col) ={2,3,4,6,8,16}
 *   (r0,c0), (r0,c1), (r0,c2)...(r1,c0),(r1,c2)...(rn,cn)
 *
 * GAMMA FUNCTION TABLE Output (D) vs. Input (I)(0,0)=(Black,Black) (255,255)=(White,White)
 * The number of gray scale M = 8
 * 2^8 = 256 total table data
 * D0 = D(I=0), D1=D(I=1)...D255=D(I=255)
 * DATA= [1st byte ID],[2nd byte M],[D0],[D1],...[D255]
 *
 * ENDORSER DATA: 1st_char, 2nd_char,...last_char
 *
 * SIZE DATA: 1byte: 4bits-Start Position; 4bits-Width Info
 *
 * PAGE LENGTH: 5bytes: 1st byte is MSB, Last byte is LSB
*/

typedef struct maintenance_data
{
  SANE_Byte nregx_adf;		/* number of registers of main-scanning in ADF mode */
  SANE_Byte nregy_adf;		/* number of registers of sub-scanning  in ADF mode */
  SANE_Byte nregx_book;		/* number of registers of main-scanning in Book mode */
  SANE_Byte nregy_book;		/* number of registers of sub-scanning  in Book mode */
  SANE_Byte nscans_adf[4];	/* Number of scanned pages in ADF mode */
  SANE_Byte nscans_book[4];	/* Number of scanned pages in Book mode */
  SANE_Byte lamp_time[4];	/* Lamp Time */
  SANE_Byte eo_odd;		/* Adjustment data of E/O balance in black level (ODD) */
  SANE_Byte eo_even;		/* Adjustment data of E/O balance in black level (EVEN) */
  SANE_Byte black_level_odd;	/* The adjustment data in black level (ODD) */
  SANE_Byte black_level_even;	/* The adjustment data in black level (EVEN) */
  SANE_Byte white_level_odd[2];	/* The adjustment data in white level (ODD) */
  SANE_Byte white_level_even[2];	/* The adjustment data in white level (EVEN) */
  SANE_Byte first_adj_white_odd[2];	/* First adjustment data in white level (ODD) */
  SANE_Byte first_adj_white_even[2];	/* First adjustment data in white level (EVEN) */
  SANE_Byte density_adj;	/* Density adjustment */
  SANE_Byte nregx_reverse;	/* The number of registers of main-scanning of the reverse-side ADF */
  SANE_Byte nregy_reverse;	/* The number of registers of sub-scanning of the reverse-side ADF */
  SANE_Byte nscans_reverse_adf[4];	/* Number of scanned pages of the reverse side ADF */
  SANE_Byte reverse_time[4];	/* The period of lamp turn on of the reverse side */
  SANE_Byte nchars[4];		/* The number of endorser characters */
  SANE_Byte reserved0;
  SANE_Byte reserved1;
  SANE_Byte reserved2;
  SANE_Byte zero[2];		/* All set as 0 */
} MAINTENANCE_DATA;
/* ADF status 1byte:
 * 7-3:Reserved;
 *   2:Reserved;
 *   1: '0'-ADF cover closed; '1'-ADF cover open
 *   0: '0'-Document on ADF; '1'-No document on ADF
 *
*/

struct IPU
{
  SANE_Byte byte0;		/* 7-4:Reserved; 3:White mode; 2:Reserved; 1-0: Gamma Table Select */
  SANE_Byte byte1;		/* 7-2:Reserved; 1-0: MTF Filter Select */
};
struct IPU_Auto_PhotoLetter
{
  /* Halftone Separations for each level
   * 256 steps of relative value with 0 the sharpest and 255 the softest
   * The relation of strength is Strength2 > Strength3 > Strength4 ...
   */
  struct
  {
    SANE_Byte level[6];
  } halftone_separation[2];

  /* 7-2:Reversed 1-0:Halftone
   * 00 Default
   * 01 Peak Detection Soft
   * 10 Peak Detection Sharp
   * 11 Don't Use
   */
  SANE_Byte byte12;

  SANE_Byte black_correction;	/* Black correction strength: 0-255 sharpest-softest */
  SANE_Byte edge_sep[4];	/* Edge Separation strengths: 0-255 sharpest-softest 1-4 */
  SANE_Byte white_background_sep_strength;	/* 0-255 sharpest-softest */
  SANE_Byte byte19;		/* 7-1:Reversed; 0:White mode    '0'-Default;    '1'-Sharp */
  SANE_Byte byte20;		/* 7-1:Reversed; 0:Halftone mode '0'-widen dots; '1'-Default */
  SANE_Byte halftone_sep_levela;
  SANE_Byte halftone_sep_levelb;
  SANE_Byte byte23;		/* 7-4:Reversed; 3-0:Adjustment of separation level: usually fixed to 0 */

  /* 7-4:Reversed; 3-0:Judge Conditions Select
   *  0XXX Black Correction OFF      1XXX Black Correction ON
   *  X0XX Halftone Separation OFF   X1XX Halftone Separation ON
   *  XX0X White Separation OFF      XX1X White Separation ON
   *  XXX0 Edge Separation OFF       XXX1 Edge Separation ON
   */
  SANE_Byte byte24;

  /* 7-4:Filter A; 3-0:Filter B
   *  FilterA: 16 types are valid from 0000 to 1111
   *  FilterB: 0000 to 1110 are valid; 1111 is not valid
   */
  SANE_Byte MTF_correction;

  /* 7-4:Filter A; 3-0:Filter B
   *  0000(soft) to 0111(sharp) are valid; 1000 to 1111 are invalid
   */
  SANE_Byte MTF_strength;

  /* 7-4:Filter A; 3-0:Filter B
   * slightly adjusts the strength of the filters
   */
  SANE_Byte MTF_adjustment;

  /* 7-4:Reserved; 3-0: smoothing filter select
   * 14 kinds are valid from 0000 to 1101; 1110 to 1111 are invalid
   */
  SANE_Byte smoothing;

  /* 7-2:Reversed; 1-0: Filter Select
   *  10 MTF Correction Select
   *  11 Smoothing Select
   *  from 00 to 01 are not valid and basically it is set as 10
   */
  SANE_Byte byte29;

  /* 7-4:Reserved; 3-0: MTF Correction Filter C
   * 16 kinds are valid from 0000 to 1111
   */
  SANE_Byte MTF_correction_c;

  /* 7-3:Reserved; 2-0: MTF Correction Filter strength C
   *  000(soft) to 111(sharp) are valid
   */
  SANE_Byte MTF_strength_c;
};
/*
struct IPU_Dynamic {
  to be implemented
};
sensor data
*/

/* for object_position command */
#define OBJECT_POSITION_UNLOAD 0
#define OBJECT_POSITION_LOAD   1

/* 1-3-15 OBJECT POSITION */
typedef struct scsi_object_position_cmd
{
  SANE_Byte opcode;		/* 31H */
  SANE_Byte position_func;	/* 7-5:LUN; 4-3:Reserved; 2-0:Position Function (bit2,bit1,bit0):
				 * 000 Unload Object  (NO CHECK ERROR even though no document on ADF)
				 * 001 Load Object    (NO CHECK ERROR even though document already fed to start position)
				 * 010 Absolute Positioning in Y-axis. Not Supported in this scanner
				 * 3H-7H Reserved */
  SANE_Byte count[3];		/* Reserved */
  SANE_Byte reserved[4];
  SANE_Byte control;		/* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link */
} POSITION;

/* 1-3-16 GET DATA BUFFER STATUS */
typedef struct scsi_get_data_buffer_status_cmd
{
  SANE_Byte opcode;		/* 34H */
  SANE_Byte wait;		/* 7-5:LUN; 4-1:Reserved; 0: Wait bit is "0" */
  SANE_Byte reserved[5];
  SANE_Byte len[2];		/* Allocation Length */
  SANE_Byte control;		/* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link */
} GET_DBS_CMD;
typedef struct scsi_status_hdr
{
  SANE_Byte len[3];		/* Data Buffer Status Length */
  SANE_Byte block;		/* 7-1:Reserved; 0:Block bit is 0 */
} STATUS_HDR;
typedef struct scsi_status_data
{
  SANE_Byte wid;		/* window identifier is 0 or 1 */
  SANE_Byte reserved;
  SANE_Byte free[3];		/* Available Space Data `Buffer */
  SANE_Byte filled[3];		/* Scan Data Available (Filled Data Bufferj) */
} STATUS_DATA;
/* BUFFER STATUS DATA FORMAT */
typedef struct scsi_buffer_status
{
  STATUS_HDR hdr;
  STATUS_DATA data;
} STATUS_BUFFER;