xref: /third_party/backends/backend/kvs20xx.c (revision 141cc406)
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#define DEBUG_NOT_STATIC
10#define BUILD 2
11
12#include "../include/sane/config.h"
13
14#include <string.h>
15#include <unistd.h>
16
17#include "../include/sane/sanei_backend.h"
18#include "../include/sane/sanei_scsi.h"
19#include "../include/sane/sanei_usb.h"
20#include "../include/sane/saneopts.h"
21#include "../include/sane/sanei_config.h"
22#include "../include/lassert.h"
23
24#include "kvs20xx.h"
25#include "kvs20xx_cmd.h"
26
27struct known_device
28{
29  const SANE_Int id;
30  const SANE_Device scanner;
31};
32
33static const struct known_device known_devices[] = {
34  {
35    KV_S2025C,
36    { "", "MATSHITA", "KV-S2025C", "sheetfed scanner" },
37  },
38  {
39    KV_S2045C,
40    { "", "MATSHITA", "KV-S2045C", "sheetfed scanner" },
41  },
42  {
43    KV_S2026C,
44    { "", "MATSHITA", "KV-S2026C", "sheetfed scanner" },
45  },
46  {
47    KV_S2046C,
48    { "", "MATSHITA", "KV-S2046C", "sheetfed scanner" },
49  },
50  {
51    KV_S2028C,
52    { "", "MATSHITA", "KV-S2028C", "sheetfed scanner" },
53  },
54  {
55    KV_S2048C,
56    { "", "MATSHITA", "KV-S2048C", "sheetfed scanner" },
57  },
58};
59
60SANE_Status
61sane_init (SANE_Int __sane_unused__ * version_code,
62	   SANE_Auth_Callback __sane_unused__ authorize)
63{
64  DBG_INIT ();
65  DBG (DBG_INFO, "This is panasonic kvs20xx driver\n");
66
67  *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
68
69  /* Initialize USB */
70  sanei_usb_init ();
71
72  return SANE_STATUS_GOOD;
73}
74
75/*
76 * List of available devices, allocated by sane_get_devices, released
77 * by sane_exit()
78 */
79static SANE_Device **devlist = NULL;
80static unsigned curr_scan_dev = 0;
81
82void
83sane_exit (void)
84{
85  if (devlist)
86    {
87      int i;
88      for (i = 0; devlist[i]; i++)
89	{
90	  free ((void *) devlist[i]->name);
91	  free ((void *) devlist[i]);
92	}
93      free ((void *) devlist);
94      devlist = NULL;
95    }
96}
97
98static SANE_Status
99attach (SANE_String_Const devname)
100{
101  int i = 0;
102  if (devlist)
103    {
104      for (; devlist[i]; i++);
105      devlist = realloc (devlist, sizeof (SANE_Device *) * (i + 1));
106      if (!devlist)
107	return SANE_STATUS_NO_MEM;
108    }
109  else
110    {
111      devlist = malloc (sizeof (SANE_Device *) * 2);
112      if (!devlist)
113	return SANE_STATUS_NO_MEM;
114    }
115  devlist[i] = malloc (sizeof (SANE_Device));
116  if (!devlist[i])
117    return SANE_STATUS_NO_MEM;
118  memcpy (devlist[i], &known_devices[curr_scan_dev].scanner,
119	  sizeof (SANE_Device));
120  devlist[i]->name = strdup (devname);
121  /* terminate device list with NULL entry: */
122  devlist[i + 1] = 0;
123  DBG (DBG_INFO, "%s device attached\n", devname);
124  return SANE_STATUS_GOOD;
125}
126
127/* Get device list */
128SANE_Status
129sane_get_devices (const SANE_Device *** device_list,
130		  SANE_Bool __sane_unused__ local_only)
131{
132  if (devlist)
133    {
134      int i;
135      for (i = 0; devlist[i]; i++)
136	{
137	  free ((void *) devlist[i]->name);
138	  free ((void *) devlist[i]);
139	}
140      free ((void *) devlist);
141      devlist = NULL;
142    }
143
144  for (curr_scan_dev = 0;
145       curr_scan_dev < sizeof (known_devices) / sizeof (known_devices[0]);
146       curr_scan_dev++)
147    {
148      sanei_usb_find_devices (PANASONIC_ID,
149			      known_devices[curr_scan_dev].id, attach);
150    }
151  for (curr_scan_dev = 0;
152       curr_scan_dev < sizeof (known_devices) / sizeof (known_devices[0]);
153       curr_scan_dev++)
154    {
155      sanei_scsi_find_devices (known_devices[curr_scan_dev].scanner.vendor,
156			       known_devices[curr_scan_dev].scanner.model,
157			       NULL, -1, -1, -1, -1, attach);
158    }
159  if(device_list)
160    *device_list = (const SANE_Device **) devlist;
161  return SANE_STATUS_GOOD;
162}
163
164/* Open device, return the device handle */
165SANE_Status
166sane_open (SANE_String_Const devname, SANE_Handle * handle)
167{
168  unsigned i, j, id = 0;
169  struct scanner *s;
170  SANE_Int h, bus;
171  SANE_Status st;
172  if (!devlist)
173    {
174      st = sane_get_devices (NULL, 0);
175      if (st)
176        return st;
177    }
178  for (i = 0; devlist[i]; i++)
179    {
180      if (!strcmp (devlist[i]->name, devname))
181	break;
182    }
183  if (!devlist[i])
184    return SANE_STATUS_INVAL;
185  for (j = 0; j < sizeof (known_devices) / sizeof (known_devices[0]); j++)
186    {
187      if (!strcmp (devlist[i]->model, known_devices[j].scanner.model))
188	{
189	  id = known_devices[j].id;
190	  break;
191	}
192    }
193
194  st = sanei_usb_open (devname, &h);
195  if (st == SANE_STATUS_ACCESS_DENIED)
196    return st;
197  if (st)
198    {
199      st = sanei_scsi_open (devname, &h, kvs20xx_sense_handler, NULL);
200      if (st)
201	{
202	  return st;
203	}
204      bus = SCSI;
205    }
206  else
207    {
208      bus = USB;
209      st = sanei_usb_claim_interface (h, 0);
210      if (st)
211	{
212	  sanei_usb_close (h);
213	  return st;
214	}
215    }
216
217  s = malloc (sizeof (struct scanner));
218  if (!s)
219    return SANE_STATUS_NO_MEM;
220  memset (s, 0, sizeof (struct scanner));
221  s->buffer = malloc (MAX_READ_DATA_SIZE + BULK_HEADER_SIZE);
222  if (!s->buffer)
223    return SANE_STATUS_NO_MEM;
224  s->file = h;
225  s->bus = bus;
226  s->id = id;
227  kvs20xx_init_options (s);
228  *handle = s;
229  for (i = 0; i < 3; i++)
230    {
231      st = kvs20xx_test_unit_ready (s);
232      if (st)
233	{
234	  if (s->bus == SCSI)
235	    {
236	      sanei_scsi_close (s->file);
237	      st = sanei_scsi_open (devname, &h, kvs20xx_sense_handler, NULL);
238	      if (st)
239		return st;
240	    }
241	  else
242	    {
243	      sanei_usb_release_interface (s->file, 0);
244	      sanei_usb_close (s->file);
245	      st = sanei_usb_open (devname, &h);
246	      if (st)
247		return st;
248	      st = sanei_usb_claim_interface (h, 0);
249	      if (st)
250		{
251		  sanei_usb_close (h);
252		  return st;
253		}
254	    }
255	  s->file = h;
256	}
257      else
258	break;
259    }
260  if (i == 3)
261    return SANE_STATUS_DEVICE_BUSY;
262
263  st = kvs20xx_set_timeout (s, s->val[FEED_TIMEOUT].w);
264  if (st)
265    {
266      sane_close (s);
267      return st;
268    }
269
270  return SANE_STATUS_GOOD;
271}
272
273/* Close device */
274void
275sane_close (SANE_Handle handle)
276{
277  struct scanner *s = (struct scanner *) handle;
278  int i;
279  if (s->bus == USB)
280    {
281      sanei_usb_release_interface (s->file, 0);
282      sanei_usb_close (s->file);
283    }
284  else
285    sanei_scsi_close (s->file);
286
287  for (i = 1; i < NUM_OPTIONS; i++)
288    {
289      if (s->opt[i].type == SANE_TYPE_STRING && s->val[i].s)
290	free (s->val[i].s);
291    }
292  if (s->data)
293    free (s->data);
294  free (s->buffer);
295  free (s);
296
297}
298
299/* Get option descriptor */
300const SANE_Option_Descriptor *
301sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
302{
303  struct scanner *s = handle;
304
305  if ((unsigned) option >= NUM_OPTIONS || option < 0)
306    return NULL;
307  return s->opt + option;
308}
309
310static SANE_Status
311wait_document (struct scanner *s)
312{
313  SANE_Status st;
314  int i;
315  if (!strcmp ("off", s->val[MANUALFEED].s))
316    return kvs20xx_document_exist (s);
317
318  for (i = 0; i < s->val[FEED_TIMEOUT].w; i++)
319    {
320      st = kvs20xx_document_exist (s);
321      if (st != SANE_STATUS_NO_DOCS)
322	return st;
323      sleep (1);
324    }
325  return SANE_STATUS_NO_DOCS;
326}
327
328/* Start scanning */
329SANE_Status
330sane_start (SANE_Handle handle)
331{
332  struct scanner *s = (struct scanner *) handle;
333  SANE_Status st;
334  int duplex = s->val[DUPLEX].w;
335
336  if (!s->scanning)
337    {
338      unsigned dummy_length;
339      st = kvs20xx_test_unit_ready (s);
340      if (st)
341	return st;
342
343      st = wait_document (s);
344      if (st)
345	return st;
346
347      st = kvs20xx_reset_window (s);
348      if (st)
349	return st;
350      st = kvs20xx_set_window (s, SIDE_FRONT);
351      if (st)
352	return st;
353      if (duplex)
354	{
355	  st = kvs20xx_set_window (s, SIDE_BACK);
356	  if (st)
357	    return st;
358	}
359      st = kvs20xx_scan (s);
360      if (st)
361	return st;
362
363      st = kvs20xx_read_picture_element (s, SIDE_FRONT, &s->params);
364      if (st)
365	return st;
366      if (duplex)
367	{
368	  st = get_adjust_data (s, &dummy_length);
369	  if (st)
370	    return st;
371	}
372      else
373	{
374	  dummy_length = 0;
375	}
376      s->scanning = 1;
377      s->page = 0;
378      s->read = 0;
379      s->side = SIDE_FRONT;
380      sane_get_parameters (s, NULL);
381      s->saved_dummy_size = s->dummy_size = dummy_length
382	? (dummy_length * s->val[RESOLUTION].w / 1200 - 1)
383	* s->params.bytes_per_line : 0;
384      s->side_size = s->params.lines * s->params.bytes_per_line;
385
386      s->data = realloc (s->data, duplex ? s->side_size * 2 : s->side_size);
387      if (!s->data)
388	{
389	  s->scanning = 0;
390	  return SANE_STATUS_NO_MEM;
391	}
392    }
393
394  if (duplex)
395    {
396      unsigned side = SIDE_FRONT;
397      unsigned read, mx;
398      if (s->side == SIDE_FRONT && s->read == s->side_size - s->dummy_size)
399	{
400	  s->side = SIDE_BACK;
401	  s->read = s->dummy_size;
402	  s->dummy_size = 0;
403	  return SANE_STATUS_GOOD;
404	}
405      s->read = 0;
406      s->dummy_size = s->saved_dummy_size;
407      s->side = SIDE_FRONT;
408      st = kvs20xx_document_exist (s);
409      if (st)
410	return st;
411      for (mx = s->side_size * 2; !st; mx -= read, side ^= SIDE_BACK)
412	st = kvs20xx_read_image_data (s, s->page, side,
413				      &s->data[s->side_size * 2 - mx], mx,
414				      &read);
415    }
416  else
417    {
418      unsigned read, mx;
419      s->read = 0;
420      st = kvs20xx_document_exist (s);
421      if (st)
422	return st;
423      DBG (DBG_INFO, "start: %d\n", s->page);
424
425      for (mx = s->side_size; !st; mx -= read)
426	st = kvs20xx_read_image_data (s, s->page, SIDE_FRONT,
427				      &s->data[s->side_size - mx], mx, &read);
428    }
429  if (st && st != SANE_STATUS_EOF)
430    {
431      s->scanning = 0;
432      return st;
433    }
434  s->page++;
435  return SANE_STATUS_GOOD;
436}
437
438inline static void
439memcpy24 (u8 * dest, u8 * src, unsigned size, unsigned ls)
440{
441  unsigned i;
442  for (i = 0; i < size; i++)
443    {
444      dest[i * 3] = src[i];
445      dest[i * 3 + 1] = src[i + ls];
446      dest[i * 3 + 2] = src[i + 2 * ls];
447    }
448}
449
450SANE_Status
451sane_read (SANE_Handle handle, SANE_Byte * buf,
452	   SANE_Int max_len, SANE_Int * len)
453{
454  struct scanner *s = (struct scanner *) handle;
455  int duplex = s->val[DUPLEX].w;
456  int color = !strcmp (s->val[MODE].s, SANE_VALUE_SCAN_MODE_COLOR);
457  int rest = s->side_size - s->read - s->dummy_size;
458  *len = 0;
459
460  if (!s->scanning || !rest)
461    {
462      if (strcmp (s->val[FEEDER_MODE].s, SANE_I18N ("continuous")))
463	{
464	  if (!duplex || s->side == SIDE_BACK)
465	    s->scanning = 0;
466	}
467      return SANE_STATUS_EOF;
468    }
469
470  *len = max_len < rest ? max_len : rest;
471  if (duplex && (s->id == KV_S2025C
472		 || s->id == KV_S2026C || s->id == KV_S2028C))
473    {
474      if (color)
475	{
476	  unsigned ls = s->params.bytes_per_line;
477	  unsigned i, a = s->side == SIDE_FRONT ? 0 : ls / 3;
478	  u8 *data;
479	  *len = (*len / ls) * ls;
480	  for (i = 0, data = s->data + s->read * 2 + a;
481	       i < *len / ls; buf += ls, data += 2 * ls, i++)
482	    memcpy24 (buf, data, ls / 3, ls * 2 / 3);
483	}
484      else
485	{
486	  unsigned ls = s->params.bytes_per_line;
487	  unsigned i = s->side == SIDE_FRONT ? 0 : ls;
488	  unsigned head = ls - (s->read % ls);
489	  unsigned tail = (*len - head) % ls;
490	  unsigned lines = (*len - head) / ls;
491	  u8 *data = s->data + (s->read / ls) * ls * 2 + i + s->read % ls;
492	  assert (data <= s->data + s->side_size * 2);
493	  memcpy (buf, data, head);
494	  for (i = 0, buf += head, data += head + (head ? ls : 0);
495	       i < lines; buf += ls, data += ls * 2, i++)
496	    {
497	      assert (data <= s->data + s->side_size * 2);
498	      memcpy (buf, data, ls);
499	    }
500	  assert ((data <= s->data + s->side_size * 2) || !tail);
501	  memcpy (buf, data, tail);
502	}
503      s->read += *len;
504    }
505  else
506    {
507      if (color)
508	{
509	  unsigned i, ls = s->params.bytes_per_line;
510	  u8 *data = s->data + s->read;
511	  *len = (*len / ls) * ls;
512	  for (i = 0; i < *len / ls; buf += ls, data += ls, i++)
513	    memcpy24 (buf, data, ls / 3, ls / 3);
514	}
515      else
516	{
517	  memcpy (buf, s->data + s->read, *len);
518	}
519      s->read += *len;
520    }
521  return SANE_STATUS_GOOD;
522}
523
524void
525sane_cancel (SANE_Handle handle)
526{
527  struct scanner *s = (struct scanner *) handle;
528  s->scanning = 0;
529}
530
531SANE_Status
532sane_set_io_mode (SANE_Handle __sane_unused__ h, SANE_Bool __sane_unused__ m)
533{
534  return SANE_STATUS_UNSUPPORTED;
535}
536
537SANE_Status
538sane_get_select_fd (SANE_Handle __sane_unused__ h,
539		    SANE_Int __sane_unused__ * fd)
540{
541  return SANE_STATUS_UNSUPPORTED;
542}
543