• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2    Copyright (C) 2008, Panasonic Russia Ltd.
3    Copyright (C) 2010-2011, m. allan noah
4 */
5 /* sane - Scanner Access Now Easy.
6    Panasonic KV-S1020C / KV-S1025C USB scanners.
7 */
8 
9 #define DEBUG_NOT_STATIC
10 
11 #include "../include/sane/config.h"
12 
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <limits.h>
16 #include <signal.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/types.h>
21 #include <sys/wait.h>
22 #include <unistd.h>
23 
24 #include "../include/sane/sane.h"
25 #include "../include/sane/saneopts.h"
26 #include "../include/sane/sanei.h"
27 #include "../include/sane/sanei_usb.h"
28 #include "../include/sane/sanei_backend.h"
29 #include "../include/sane/sanei_config.h"
30 #include "../include/lassert.h"
31 
32 #include "kvs1025.h"
33 #include "kvs1025_low.h"
34 
35 #include "../include/sane/sanei_debug.h"
36 
37 /* SANE backend operations, see SANE Standard for details
38    https://sane-project.gitlab.io/standard/ */
39 
40 /* Init the KV-S1025 SANE backend. This function must be called before any other
41    SANE function can be called. */
42 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback __sane_unused__ authorize)43 sane_init (SANE_Int * version_code,
44 	   SANE_Auth_Callback __sane_unused__ authorize)
45 {
46   SANE_Status status;
47 
48   DBG_INIT ();
49 
50   DBG (DBG_sane_init, "sane_init\n");
51 
52   DBG (DBG_error,
53        "This is panasonic KV-S1020C / KV-S1025C version %d.%d build %d\n",
54        SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, V_BUILD);
55 
56   if (version_code)
57     {
58       *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, V_BUILD);
59     }
60 
61   /* Initialize USB */
62   sanei_usb_init ();
63 
64   status = kv_enum_devices ();
65   if (status)
66     return status;
67 
68   DBG (DBG_proc, "sane_init: leave\n");
69   return SANE_STATUS_GOOD;
70 }
71 
72 /* Terminate the KV-S1025 SANE backend */
73 void
sane_exit(void)74 sane_exit (void)
75 {
76   DBG (DBG_proc, "sane_exit: enter\n");
77 
78   kv_exit ();
79 
80   DBG (DBG_proc, "sane_exit: exit\n");
81 }
82 
83 /* Get device list */
84 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool __sane_unused__ local_only)85 sane_get_devices (const SANE_Device *** device_list,
86 		  SANE_Bool __sane_unused__ local_only)
87 {
88   DBG (DBG_proc, "sane_get_devices: enter\n");
89   kv_get_devices_list (device_list);
90   DBG (DBG_proc, "sane_get_devices: leave\n");
91   return SANE_STATUS_GOOD;
92 }
93 
94 /* Open device, return the device handle */
95 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)96 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
97 {
98   return kv_open_by_name (devicename, handle);
99 }
100 
101 /* Close device */
102 void
sane_close(SANE_Handle handle)103 sane_close (SANE_Handle handle)
104 {
105   DBG (DBG_proc, "sane_close: enter\n");
106   kv_close ((PKV_DEV) handle);
107   DBG (DBG_proc, "sane_close: leave\n");
108 }
109 
110 /* Get option descriptor */
111 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)112 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
113 {
114   return kv_get_option_descriptor ((PKV_DEV) handle, option);
115 }
116 
117 /* Control option */
118 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * val,SANE_Int * info)119 sane_control_option (SANE_Handle handle, SANE_Int option,
120 		     SANE_Action action, void *val, SANE_Int * info)
121 {
122   return kv_control_option ((PKV_DEV) handle, option, action, val, info);
123 }
124 
125 /* Get scan parameters */
126 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)127 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
128 {
129   PKV_DEV dev = (PKV_DEV) handle;
130 
131   int side = dev->current_side == SIDE_FRONT ? 0 : 1;
132 
133   DBG (DBG_proc, "sane_get_parameters: enter\n");
134 
135   if (!(dev->scanning))
136     {
137       /* Setup the parameters for the scan. (guessed value) */
138       int resolution = dev->val[OPT_RESOLUTION].w;
139       int width, length, depth = kv_get_depth (kv_get_mode (dev));;
140 
141       DBG (DBG_proc, "sane_get_parameters: initial settings\n");
142       kv_calc_paper_size (dev, &width, &length);
143 
144       DBG (DBG_error, "Resolution = %d\n", resolution);
145       DBG (DBG_error, "Paper width = %d, height = %d\n", width, length);
146 
147       /* Prepare the parameters for the caller. */
148       dev->params[0].format = kv_get_mode (dev) == SM_COLOR ?
149 	SANE_FRAME_RGB : SANE_FRAME_GRAY;
150 
151       dev->params[0].last_frame = SANE_TRUE;
152       dev->params[0].pixels_per_line = ((width * resolution) / 1200) & (~0xf);
153 
154       dev->params[0].depth = depth > 8 ? 8 : depth;
155 
156       dev->params[0].bytes_per_line =
157 	(dev->params[0].pixels_per_line / 8) * depth;
158       dev->params[0].lines = (length * resolution) / 1200;
159 
160       memcpy (&dev->params[1], &dev->params[0], sizeof (SANE_Parameters));
161     }
162 
163   /* Return the current values. */
164   if (params)
165     *params = (dev->params[side]);
166 
167   DBG (DBG_proc, "sane_get_parameters: exit\n");
168   return SANE_STATUS_GOOD;
169 }
170 
171 /* Start scanning */
172 SANE_Status
sane_start(SANE_Handle handle)173 sane_start (SANE_Handle handle)
174 {
175   SANE_Status status;
176   PKV_DEV dev = (PKV_DEV) handle;
177   SANE_Bool dev_ready;
178   KV_CMD_RESPONSE rs;
179 
180   DBG (DBG_proc, "sane_start: enter\n");
181   if (!dev->scanning)
182     {
183       /* open device */
184       if (!kv_already_open (dev))
185 	{
186 	  DBG (DBG_proc, "sane_start: need to open device\n");
187 	  status = kv_open (dev);
188 	  if (status)
189 	    {
190 	      return status;
191 	    }
192 	}
193       /* Begin scan */
194       DBG (DBG_proc, "sane_start: begin scan\n");
195 
196       /* Get necessary parameters */
197       sane_get_parameters (dev, NULL);
198 
199       dev->current_page = 0;
200       dev->current_side = SIDE_FRONT;
201 
202       /* The scanner must be ready. */
203       status = CMD_test_unit_ready (dev, &dev_ready);
204       if (status || !dev_ready)
205 	{
206 	  return SANE_STATUS_DEVICE_BUSY;
207 	}
208 
209       if (!strcmp (dev->val[OPT_MANUALFEED].s, "off"))
210 	{
211 	  status = CMD_get_document_existanse (dev);
212 	  if (status)
213 	    {
214 	      DBG (DBG_proc, "sane_start: exit with no more docs\n");
215 	      return status;
216 	    }
217 	}
218 
219       /* Set window */
220       status = CMD_reset_window (dev);
221       if (status)
222 	{
223 	  return status;
224 	}
225 
226       status = CMD_set_window (dev, SIDE_FRONT, &rs);
227       if (status)
228 	{
229 	  DBG (DBG_proc, "sane_start: error setting window\n");
230 	  return status;
231 	}
232 
233       if (rs.status)
234 	{
235 	  DBG (DBG_proc, "sane_start: error setting window\n");
236 	  DBG (DBG_proc,
237 	       "sane_start: sense_key=0x%x, ASC=0x%x, ASCQ=0x%x\n",
238 	       get_RS_sense_key (rs.sense),
239 	       get_RS_ASC (rs.sense), get_RS_ASCQ (rs.sense));
240 	  return SANE_STATUS_DEVICE_BUSY;
241 	}
242 
243       if (IS_DUPLEX (dev))
244 	{
245 	  status = CMD_set_window (dev, SIDE_BACK, &rs);
246 
247 	  if (status)
248 	    {
249 	      DBG (DBG_proc, "sane_start: error setting window\n");
250 	      return status;
251 	    }
252 	  if (rs.status)
253 	    {
254 	      DBG (DBG_proc, "sane_start: error setting window\n");
255 	      DBG (DBG_proc,
256 		   "sane_start: sense_key=0x%x, "
257 		   "ASC=0x%x, ASCQ=0x%x\n",
258 		   get_RS_sense_key (rs.sense),
259 		   get_RS_ASC (rs.sense), get_RS_ASCQ (rs.sense));
260 	      return SANE_STATUS_INVAL;
261 	    }
262 	}
263 
264       /* Scan */
265       status = CMD_scan (dev);
266       if (status)
267 	{
268 	  return status;
269 	}
270 
271       status = AllocateImageBuffer (dev);
272       if (status)
273 	{
274 	  return status;
275 	}
276       dev->scanning = 1;
277     }
278   else
279     {
280       /* renew page */
281       if (IS_DUPLEX (dev))
282 	{
283 	  if (dev->current_side == SIDE_FRONT)
284 	    {
285 	      /* back image data already read, so just return */
286 	      dev->current_side = SIDE_BACK;
287 	      DBG (DBG_proc, "sane_start: duplex back\n");
288 	      status = SANE_STATUS_GOOD;
289               goto cleanup;
290 	    }
291 	  else
292 	    {
293 	      dev->current_side = SIDE_FRONT;
294 	      dev->current_page++;
295 	    }
296 	}
297       else
298 	{
299 	  dev->current_page++;
300 	}
301     }
302   DBG (DBG_proc, "sane_start: NOW SCANNING page\n");
303 
304   /* Read image data */
305   status = ReadImageData (dev, dev->current_page);
306   if (status)
307     {
308       dev->scanning = 0;
309       return status;
310     }
311 
312   /* Get picture element size */
313   {
314     int width, height;
315     status = CMD_read_pic_elements (dev, dev->current_page,
316 				    SIDE_FRONT, &width, &height);
317     if (status)
318       return status;
319   }
320 
321   if (IS_DUPLEX (dev))
322     {
323       int width, height;
324       status = CMD_read_pic_elements (dev, dev->current_page,
325 				      SIDE_BACK, &width, &height);
326       if (status)
327 	return status;
328     }
329 
330   /* software based enhancement functions from sanei_magic */
331   /* these will modify the image, and adjust the params */
332   /* at this point, we are only looking at the front image */
333   /* of simplex or duplex data, back side has already exited */
334   /* so, we do both sides now, if required */
335   if (dev->val[OPT_SWDESKEW].w){
336     buffer_deskew(dev,SIDE_FRONT);
337   }
338   if (dev->val[OPT_SWCROP].w){
339     buffer_crop(dev,SIDE_FRONT);
340   }
341   if (dev->val[OPT_SWDESPECK].w){
342     buffer_despeck(dev,SIDE_FRONT);
343   }
344   if (dev->val[OPT_SWDEROTATE].w || dev->val[OPT_ROTATE].w){
345     buffer_rotate(dev,SIDE_FRONT);
346   }
347 
348   if (IS_DUPLEX (dev)){
349     if (dev->val[OPT_SWDESKEW].w){
350       buffer_deskew(dev,SIDE_BACK);
351     }
352     if (dev->val[OPT_SWCROP].w){
353       buffer_crop(dev,SIDE_BACK);
354     }
355     if (dev->val[OPT_SWDESPECK].w){
356       buffer_despeck(dev,SIDE_BACK);
357     }
358     if (dev->val[OPT_SWDEROTATE].w || dev->val[OPT_ROTATE].w){
359       buffer_rotate(dev,SIDE_BACK);
360     }
361   }
362 
363   cleanup:
364 
365   /* check if we need to skip this page */
366   if (dev->val[OPT_SWSKIP].w && buffer_isblank(dev,dev->current_side)){
367     DBG (DBG_proc, "sane_start: blank page, recurse\n");
368     return sane_start(handle);
369   }
370 
371   DBG (DBG_proc, "sane_start: exit\n");
372   return status;
373 }
374 
375 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * buf,SANE_Int max_len,SANE_Int * len)376 sane_read (SANE_Handle handle, SANE_Byte * buf,
377 	   SANE_Int max_len, SANE_Int * len)
378 {
379   PKV_DEV dev = (PKV_DEV) handle;
380   int side = dev->current_side == SIDE_FRONT ? 0 : 1;
381 
382   int size = max_len;
383   if (!dev->scanning)
384     return SANE_STATUS_EOF;
385 
386   if (size > dev->img_size[side])
387     size = dev->img_size[side];
388 
389   if (size == 0)
390     {
391       *len = size;
392       return SANE_STATUS_EOF;
393     }
394 
395   if (dev->val[OPT_INVERSE].w &&
396       (kv_get_mode (dev) == SM_BINARY || kv_get_mode (dev) == SM_DITHER))
397     {
398       int i;
399       unsigned char *p = dev->img_pt[side];
400       for (i = 0; i < size; i++)
401 	{
402 	  buf[i] = ~p[i];
403 	}
404     }
405   else
406     {
407       memcpy (buf, dev->img_pt[side], size);
408     }
409 
410   /*hexdump(DBG_error, "img data", buf, 128); */
411 
412   dev->img_pt[side] += size;
413   dev->img_size[side] -= size;
414 
415   DBG (DBG_proc, "sane_read: %d bytes to read, "
416        "%d bytes read, EOF=%s  %d\n",
417        max_len, size, dev->img_size[side] == 0 ? "True" : "False", side);
418 
419   if (len)
420     {
421       *len = size;
422     }
423   if (dev->img_size[side] == 0)
424     {
425       if (!strcmp (dev->val[OPT_FEEDER_MODE].s, "single"))
426 	if ((IS_DUPLEX (dev) && side) || !IS_DUPLEX (dev))
427 	  dev->scanning = 0;
428     }
429   return SANE_STATUS_GOOD;
430 }
431 
432 void
sane_cancel(SANE_Handle handle)433 sane_cancel (SANE_Handle handle)
434 {
435   PKV_DEV dev = (PKV_DEV) handle;
436   DBG (DBG_proc, "sane_cancel: scan canceled.\n");
437   dev->scanning = 0;
438 
439   kv_close (dev);
440 }
441 
442 SANE_Status
sane_set_io_mode(SANE_Handle h,SANE_Bool m)443 sane_set_io_mode (SANE_Handle h, SANE_Bool m)
444 {
445   (void) h;
446   (void) m;
447   return SANE_STATUS_UNSUPPORTED;
448 }
449 
450 SANE_Status
sane_get_select_fd(SANE_Handle h,SANE_Int * fd)451 sane_get_select_fd (SANE_Handle h, SANE_Int * fd)
452 {
453   (void) h;
454   (void) fd;
455   return SANE_STATUS_UNSUPPORTED;
456 }
457