• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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