1 /*
2 Copyright (C) 2008, Panasonic Russia Ltd.
3 Copyright (C) 2010, m. allan noah
4 */
5 /*
6 Panasonic KV-S20xx USB-SCSI scanners.
7 */
8
9 #include "../include/sane/config.h"
10
11 #include <string.h>
12 /*#include <unistd.h>*/
13
14 #define DEBUG_DECLARE_ONLY
15 #define BACKEND_NAME kvs20xx
16
17 #include "../include/sane/sanei_backend.h"
18 #include "../include/sane/sanei_scsi.h"
19 #include "../include/sane/sanei_usb.h"
20
21 #include "kvs20xx.h"
22 #include "kvs20xx_cmd.h"
23
24 static SANE_Status
usb_send_command(struct scanner * s,struct cmd * c,struct response * r,void * buf)25 usb_send_command (struct scanner *s, struct cmd *c, struct response *r,
26 void *buf)
27 {
28 SANE_Status st;
29 struct bulk_header *h = (struct bulk_header *) buf;
30 u8 resp[sizeof (*h) + STATUS_SIZE];
31 size_t sz = sizeof (*h) + MAX_CMD_SIZE;
32 memset (h, 0, sz);
33 h->length = cpu2be32 (sz);
34 h->type = cpu2be16 (COMMAND_BLOCK);
35 h->code = cpu2be16 (COMMAND_CODE);
36 memcpy (h + 1, c->cmd, c->cmd_size);
37
38 st = sanei_usb_write_bulk (s->file, (const SANE_Byte *) h, &sz);
39 if (st)
40 return st;
41 if (sz != sizeof (*h) + MAX_CMD_SIZE)
42 return SANE_STATUS_IO_ERROR;
43 if (c->dir == CMD_IN)
44 {
45 sz = sizeof (*h) + c->data_size;
46 st = sanei_usb_read_bulk (s->file, (SANE_Byte *) h, &sz);
47 c->data = h + 1;
48 c->data_size = sz - sizeof (*h);
49
50 if (st || sz < sizeof (*h))
51 {
52 st = sanei_usb_release_interface (s->file, 0);
53 if (st)
54 return st;
55 st = sanei_usb_claim_interface (s->file, 0);
56 if (st)
57 return st;
58 r->status = CHECK_CONDITION;
59 return SANE_STATUS_GOOD;
60 }
61
62 }
63 else if (c->dir == CMD_OUT)
64 {
65 sz = sizeof (*h) + c->data_size;
66 memset (h, 0, sizeof (*h));
67 h->length = cpu2be32 (sizeof (*h) + c->data_size);
68 h->type = cpu2be16 (DATA_BLOCK);
69 h->code = cpu2be16 (DATA_CODE);
70 memcpy (h + 1, c->data, c->data_size);
71 st = sanei_usb_write_bulk (s->file, (const SANE_Byte *) h, &sz);
72 if (st)
73 return st;
74 }
75 sz = sizeof (resp);
76 st = sanei_usb_read_bulk (s->file, resp, &sz);
77 if (st || sz != sizeof (resp))
78 return SANE_STATUS_IO_ERROR;
79 r->status = be2cpu32 (*((u32 *) (resp + sizeof (*h))));
80 return st;
81 }
82
83 SANE_Status
kvs20xx_sense_handler(int __sane_unused__ fd,u_char * sense_buffer,void __sane_unused__ * arg)84 kvs20xx_sense_handler (int __sane_unused__ fd,
85 u_char * sense_buffer, void __sane_unused__ * arg)
86 {
87 unsigned i;
88 SANE_Status st = SANE_STATUS_GOOD;
89 for (i = 0; i < sizeof (s_errors) / sizeof (s_errors[0]); i++)
90 if ((sense_buffer[2] & 0xf) == s_errors[i].sense
91 && sense_buffer[12] == s_errors[i].asc
92 && sense_buffer[13] == s_errors[i].ascq)
93 {
94 st = s_errors[i].st;
95 break;
96 }
97 if (st == SANE_STATUS_GOOD && sense_buffer[2] & END_OF_MEDIUM)
98 st = SANE_STATUS_EOF;
99 if (i == sizeof (s_errors) / sizeof (s_errors[0]))
100 st = SANE_STATUS_IO_ERROR;
101 DBG (DBG_ERR,
102 "send_command: CHECK_CONDITION: sense:0x%x ASC:0x%x ASCQ:0x%x\n",
103 sense_buffer[2], sense_buffer[12], sense_buffer[13]);
104
105 return st;
106 }
107
108 static SANE_Status
send_command(struct scanner * s,struct cmd * c)109 send_command (struct scanner * s, struct cmd * c)
110 {
111 SANE_Status st = SANE_STATUS_GOOD;
112 if (s->bus == USB)
113 {
114 struct response r;
115 memset (&r, 0, sizeof (r));
116 st = usb_send_command (s, c, &r, s->buffer);
117 if (st)
118 return st;
119 if (r.status)
120 {
121 u8 b[sizeof (struct bulk_header) + RESPONSE_SIZE];
122 struct cmd c2 = {
123 {0},
124 6,
125 0,
126 RESPONSE_SIZE,
127 CMD_IN
128 };
129 c2.cmd[0] = REQUEST_SENSE;
130 c2.cmd[4] = RESPONSE_SIZE;
131 st = usb_send_command (s, &c2, &r, b);
132 if (st)
133 return st;
134 st = kvs20xx_sense_handler (0, b + sizeof (struct bulk_header), NULL);
135 }
136 }
137 else
138 {
139 if (c->dir == CMD_OUT)
140 {
141 memcpy (s->buffer, c->cmd, c->cmd_size);
142 memcpy (s->buffer + c->cmd_size, c->data, c->data_size);
143 st = sanei_scsi_cmd (s->file, s->buffer, c->cmd_size + c->data_size,
144 NULL, NULL);
145 }
146 else if (c->dir == CMD_IN)
147 {
148 c->data = s->buffer;
149 st = sanei_scsi_cmd (s->file, c->cmd, c->cmd_size,
150 c->data, (size_t *) & c->data_size);
151 }
152 else
153 {
154 st = sanei_scsi_cmd (s->file, c->cmd, c->cmd_size, NULL, NULL);
155 }
156 }
157 return st;
158 }
159
160 SANE_Status
kvs20xx_test_unit_ready(struct scanner * s)161 kvs20xx_test_unit_ready (struct scanner * s)
162 {
163 struct cmd c = {
164 {0},
165 6,
166 0,
167 0,
168 CMD_NONE
169 };
170 c.cmd[0] = TEST_UNIT_READY;
171 if (send_command (s, &c))
172 return SANE_STATUS_DEVICE_BUSY;
173
174 return SANE_STATUS_GOOD;
175 }
176
177 SANE_Status
kvs20xx_set_timeout(struct scanner * s,int timeout)178 kvs20xx_set_timeout (struct scanner * s, int timeout)
179 {
180 u16 t = cpu2be16 ((u16) timeout);
181 struct cmd c = {
182 {0},
183 10,
184 0,
185 0,
186 CMD_OUT
187 };
188 c.cmd[0] = SET_TIMEOUT;
189 c.cmd[2] = 0x8d;
190 copy16 (c.cmd + 7, cpu2be16 (sizeof (t)));
191
192 c.data = &t;
193 c.data_size = sizeof (t);
194
195 if (s->bus == USB)
196 sanei_usb_set_timeout (timeout * 1000);
197
198 return send_command (s, &c);
199 }
200
201 SANE_Status
kvs20xx_set_window(struct scanner * s,int wnd_id)202 kvs20xx_set_window (struct scanner * s, int wnd_id)
203 {
204 struct window wnd;
205 struct cmd c = {
206 {0},
207 10,
208 0,
209 0,
210 CMD_OUT
211 };
212 c.cmd[0] = SET_WINDOW;
213 copy16 (c.cmd + 7, cpu2be16 (sizeof (wnd)));
214
215 c.data = &wnd;
216 c.data_size = sizeof (wnd);
217
218 kvs20xx_init_window (s, &wnd, wnd_id);
219
220 return send_command (s, &c);
221 }
222
223 SANE_Status
kvs20xx_reset_window(struct scanner * s)224 kvs20xx_reset_window (struct scanner * s)
225 {
226 struct cmd c = {
227 {0},
228 10,
229 0,
230 0,
231 CMD_NONE
232 };
233 c.cmd[0] = SET_WINDOW;
234
235 return send_command (s, &c);
236 }
237
238 SANE_Status
kvs20xx_scan(struct scanner * s)239 kvs20xx_scan (struct scanner * s)
240 {
241 struct cmd c = {
242 {0},
243 6,
244 0,
245 0,
246 CMD_NONE
247 };
248 c.cmd[0] = SCAN;
249 return send_command (s, &c);
250 }
251
252 SANE_Status
kvs20xx_document_exist(struct scanner * s)253 kvs20xx_document_exist (struct scanner * s)
254 {
255 SANE_Status status;
256 struct cmd c = {
257 {0},
258 10,
259 0,
260 6,
261 CMD_IN,
262 };
263 u8 *d;
264 c.cmd[0] = READ_10;
265 c.cmd[2] = 0x81;
266 set24 (c.cmd + 6, c.data_size);
267 status = send_command (s, &c);
268 if (status)
269 return status;
270 d = c.data;
271 if (d[0] & 0x20)
272 return SANE_STATUS_GOOD;
273
274 return SANE_STATUS_NO_DOCS;
275 }
276
277 SANE_Status
kvs20xx_read_picture_element(struct scanner * s,unsigned side,SANE_Parameters * p)278 kvs20xx_read_picture_element (struct scanner * s, unsigned side,
279 SANE_Parameters * p)
280 {
281 SANE_Status status;
282 struct cmd c = {
283 {0},
284 10,
285 0,
286 16,
287 CMD_IN
288 };
289 u32 *data;
290 c.cmd[0] = READ_10;
291 c.cmd[2] = 0x80;
292 c.cmd[5] = side;
293 set24 (c.cmd + 6, c.data_size);
294
295 status = send_command (s, &c);
296 if (status)
297 return status;
298 data = (u32 *) c.data;
299 p->pixels_per_line = be2cpu32 (data[0]);
300 p->lines = be2cpu32 (data[1]);
301 return SANE_STATUS_GOOD;
302 }
303
304 SANE_Status
kvs20xx_read_image_data(struct scanner * s,unsigned page,unsigned side,void * buf,unsigned max_size,unsigned * size)305 kvs20xx_read_image_data (struct scanner * s, unsigned page, unsigned side,
306 void *buf, unsigned max_size, unsigned *size)
307 {
308 SANE_Status status;
309 struct cmd c = {
310 {0},
311 10,
312 0,
313 0,
314 CMD_IN
315 };
316 c.cmd[0] = READ_10;
317 c.cmd[4] = page;
318 c.cmd[5] = side;
319
320 c.data_size = max_size < MAX_READ_DATA_SIZE ? max_size : MAX_READ_DATA_SIZE;
321
322 set24 (c.cmd + 6, c.data_size);
323 status = send_command (s, &c);
324
325 if (status && status != SANE_STATUS_EOF)
326 return status;
327
328 *size = c.data_size;
329 DBG (DBG_INFO, "kvs20xx_read_image_data: read %d, status %d\n", *size, status);
330 memcpy (buf, c.data, *size);
331 return status;
332 }
333
334 SANE_Status
get_adjust_data(struct scanner * s,unsigned * dummy_length)335 get_adjust_data (struct scanner * s, unsigned *dummy_length)
336 {
337 SANE_Status status;
338 struct cmd c = {
339 {0},
340 10,
341 0,
342 40,
343 CMD_IN
344 };
345 u16 *data;
346
347 c.cmd[0] = GET_ADJUST_DATA;
348 c.cmd[2] = 0x9b;
349 c.cmd[8] = 40;
350 status = send_command (s, &c);
351 if (status)
352 return status;
353 data = (u16 *) c.data;
354 *dummy_length = be2cpu16 (data[0]);
355 return SANE_STATUS_GOOD;
356 }
357