1141cc406Sopenharmony_ci/*
2141cc406Sopenharmony_ci   Copyright (C) 2008, Panasonic Russia Ltd.
3141cc406Sopenharmony_ci*/
4141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
5141cc406Sopenharmony_ci   Panasonic KV-S1020C / KV-S1025C USB scanners.
6141cc406Sopenharmony_ci*/
7141cc406Sopenharmony_ci
8141cc406Sopenharmony_ci#define DEBUG_DECLARE_ONLY
9141cc406Sopenharmony_ci
10141cc406Sopenharmony_ci#include "../include/sane/config.h"
11141cc406Sopenharmony_ci
12141cc406Sopenharmony_ci#include <errno.h>
13141cc406Sopenharmony_ci#include <fcntl.h>
14141cc406Sopenharmony_ci#include <limits.h>
15141cc406Sopenharmony_ci#include <signal.h>
16141cc406Sopenharmony_ci#include <stdio.h>
17141cc406Sopenharmony_ci#include <stdlib.h>
18141cc406Sopenharmony_ci#include <string.h>
19141cc406Sopenharmony_ci#include <sys/types.h>
20141cc406Sopenharmony_ci#include <sys/wait.h>
21141cc406Sopenharmony_ci#include <unistd.h>
22141cc406Sopenharmony_ci
23141cc406Sopenharmony_ci#include "../include/sane/sane.h"
24141cc406Sopenharmony_ci#include "../include/sane/saneopts.h"
25141cc406Sopenharmony_ci#include "../include/sane/sanei.h"
26141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h"
27141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h"
28141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h"
29141cc406Sopenharmony_ci#include "../include/lassert.h"
30141cc406Sopenharmony_ci#include "../include/sane/sanei_magic.h"
31141cc406Sopenharmony_ci
32141cc406Sopenharmony_ci#include "kvs1025.h"
33141cc406Sopenharmony_ci#include "kvs1025_low.h"
34141cc406Sopenharmony_ci#include "kvs1025_usb.h"
35141cc406Sopenharmony_ci
36141cc406Sopenharmony_ci#include "../include/sane/sanei_debug.h"
37141cc406Sopenharmony_ci
38141cc406Sopenharmony_ci/* Global storage */
39141cc406Sopenharmony_ci
40141cc406Sopenharmony_ciPKV_DEV g_devices = NULL;	/* Chain of devices */
41141cc406Sopenharmony_ciconst SANE_Device **g_devlist = NULL;
42141cc406Sopenharmony_ci
43141cc406Sopenharmony_ci/* Static functions */
44141cc406Sopenharmony_ci
45141cc406Sopenharmony_ci/* Free one device */
46141cc406Sopenharmony_cistatic void
47141cc406Sopenharmony_cikv_free (KV_DEV ** pdev)
48141cc406Sopenharmony_ci{
49141cc406Sopenharmony_ci  KV_DEV *dev;
50141cc406Sopenharmony_ci
51141cc406Sopenharmony_ci  dev = *pdev;
52141cc406Sopenharmony_ci
53141cc406Sopenharmony_ci  if (dev == NULL)
54141cc406Sopenharmony_ci    return;
55141cc406Sopenharmony_ci
56141cc406Sopenharmony_ci  DBG (DBG_proc, "kv_free : enter\n");
57141cc406Sopenharmony_ci
58141cc406Sopenharmony_ci  kv_close (dev);
59141cc406Sopenharmony_ci
60141cc406Sopenharmony_ci  DBG (DBG_proc, "kv_free : free image buffer 0 \n");
61141cc406Sopenharmony_ci  if (dev->img_buffers[0])
62141cc406Sopenharmony_ci    free (dev->img_buffers[0]);
63141cc406Sopenharmony_ci  DBG (DBG_proc, "kv_free : free image buffer 1 \n");
64141cc406Sopenharmony_ci  if (dev->img_buffers[1])
65141cc406Sopenharmony_ci    free (dev->img_buffers[1]);
66141cc406Sopenharmony_ci  DBG (DBG_proc, "kv_free : free scsi device name\n");
67141cc406Sopenharmony_ci  if (dev->scsi_device_name)
68141cc406Sopenharmony_ci    free (dev->scsi_device_name);
69141cc406Sopenharmony_ci
70141cc406Sopenharmony_ci  DBG (DBG_proc, "kv_free : free SCSI buffer\n");
71141cc406Sopenharmony_ci  if (dev->buffer0)
72141cc406Sopenharmony_ci    free (dev->buffer0);
73141cc406Sopenharmony_ci
74141cc406Sopenharmony_ci  DBG (DBG_proc, "kv_free : free dev \n");
75141cc406Sopenharmony_ci  free (dev);
76141cc406Sopenharmony_ci
77141cc406Sopenharmony_ci  *pdev = NULL;
78141cc406Sopenharmony_ci
79141cc406Sopenharmony_ci  DBG (DBG_proc, "kv_free : exit\n");
80141cc406Sopenharmony_ci}
81141cc406Sopenharmony_ci
82141cc406Sopenharmony_ci/* Free all devices */
83141cc406Sopenharmony_cistatic void
84141cc406Sopenharmony_cikv_free_devices (void)
85141cc406Sopenharmony_ci{
86141cc406Sopenharmony_ci  PKV_DEV dev;
87141cc406Sopenharmony_ci  while (g_devices)
88141cc406Sopenharmony_ci    {
89141cc406Sopenharmony_ci      dev = g_devices;
90141cc406Sopenharmony_ci      g_devices = dev->next;
91141cc406Sopenharmony_ci      kv_free (&dev);
92141cc406Sopenharmony_ci    }
93141cc406Sopenharmony_ci  if (g_devlist)
94141cc406Sopenharmony_ci    {
95141cc406Sopenharmony_ci      free (g_devlist);
96141cc406Sopenharmony_ci      g_devlist = NULL;
97141cc406Sopenharmony_ci    }
98141cc406Sopenharmony_ci}
99141cc406Sopenharmony_ci
100141cc406Sopenharmony_ci/* Get all supported scanners, and store into g_scanners_supported */
101141cc406Sopenharmony_ciSANE_Status
102141cc406Sopenharmony_cikv_enum_devices (void)
103141cc406Sopenharmony_ci{
104141cc406Sopenharmony_ci  SANE_Status status;
105141cc406Sopenharmony_ci  kv_free_devices ();
106141cc406Sopenharmony_ci  status = kv_usb_enum_devices ();
107141cc406Sopenharmony_ci  if (status)
108141cc406Sopenharmony_ci    {
109141cc406Sopenharmony_ci      kv_free_devices ();
110141cc406Sopenharmony_ci    }
111141cc406Sopenharmony_ci
112141cc406Sopenharmony_ci  return status;
113141cc406Sopenharmony_ci}
114141cc406Sopenharmony_ci
115141cc406Sopenharmony_ci/* Return devices list to the front end */
116141cc406Sopenharmony_civoid
117141cc406Sopenharmony_cikv_get_devices_list (const SANE_Device *** devices_list)
118141cc406Sopenharmony_ci{
119141cc406Sopenharmony_ci  *devices_list = g_devlist;
120141cc406Sopenharmony_ci}
121141cc406Sopenharmony_ci
122141cc406Sopenharmony_ci/* Close all open handles and clean up global storage */
123141cc406Sopenharmony_civoid
124141cc406Sopenharmony_cikv_exit (void)
125141cc406Sopenharmony_ci{
126141cc406Sopenharmony_ci  kv_free_devices ();		/* Free all devices */
127141cc406Sopenharmony_ci  kv_usb_cleanup ();		/* Clean USB bus */
128141cc406Sopenharmony_ci}
129141cc406Sopenharmony_ci
130141cc406Sopenharmony_ci/* Open device by name */
131141cc406Sopenharmony_ciSANE_Status
132141cc406Sopenharmony_cikv_open_by_name (SANE_String_Const devicename, SANE_Handle * handle)
133141cc406Sopenharmony_ci{
134141cc406Sopenharmony_ci
135141cc406Sopenharmony_ci  PKV_DEV pd = g_devices;
136141cc406Sopenharmony_ci  DBG (DBG_proc, "sane_open: enter (dev_name=%s)\n", devicename);
137141cc406Sopenharmony_ci  while (pd)
138141cc406Sopenharmony_ci    {
139141cc406Sopenharmony_ci      if (strcmp (pd->sane.name, devicename) == 0)
140141cc406Sopenharmony_ci	{
141141cc406Sopenharmony_ci	  if (kv_open (pd) == 0)
142141cc406Sopenharmony_ci	    {
143141cc406Sopenharmony_ci	      *handle = (SANE_Handle) pd;
144141cc406Sopenharmony_ci	      DBG (DBG_proc, "sane_open: leave\n");
145141cc406Sopenharmony_ci	      return SANE_STATUS_GOOD;
146141cc406Sopenharmony_ci	    }
147141cc406Sopenharmony_ci	}
148141cc406Sopenharmony_ci      pd = pd->next;
149141cc406Sopenharmony_ci    }
150141cc406Sopenharmony_ci  DBG (DBG_proc, "sane_open: leave -- no device found\n");
151141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
152141cc406Sopenharmony_ci}
153141cc406Sopenharmony_ci
154141cc406Sopenharmony_ci/* Open a device */
155141cc406Sopenharmony_ciSANE_Status
156141cc406Sopenharmony_cikv_open (PKV_DEV dev)
157141cc406Sopenharmony_ci{
158141cc406Sopenharmony_ci  SANE_Status status = SANE_STATUS_UNSUPPORTED;
159141cc406Sopenharmony_ci  int i;
160141cc406Sopenharmony_ci#define RETRAY_NUM 3
161141cc406Sopenharmony_ci
162141cc406Sopenharmony_ci
163141cc406Sopenharmony_ci  if (dev->bus_mode == KV_USB_BUS)
164141cc406Sopenharmony_ci    {
165141cc406Sopenharmony_ci      status = kv_usb_open (dev);
166141cc406Sopenharmony_ci    }
167141cc406Sopenharmony_ci  if (status)
168141cc406Sopenharmony_ci    return status;
169141cc406Sopenharmony_ci  for (i = 0; i < RETRAY_NUM; i++)
170141cc406Sopenharmony_ci    {
171141cc406Sopenharmony_ci      SANE_Bool dev_ready;
172141cc406Sopenharmony_ci      status = CMD_test_unit_ready (dev, &dev_ready);
173141cc406Sopenharmony_ci      if (!status && dev_ready)
174141cc406Sopenharmony_ci	break;
175141cc406Sopenharmony_ci    }
176141cc406Sopenharmony_ci
177141cc406Sopenharmony_ci  if (status == 0)
178141cc406Sopenharmony_ci    {
179141cc406Sopenharmony_ci      /* Read device support info */
180141cc406Sopenharmony_ci      status = CMD_read_support_info (dev);
181141cc406Sopenharmony_ci
182141cc406Sopenharmony_ci      if (status == 0)
183141cc406Sopenharmony_ci	{
184141cc406Sopenharmony_ci	  /* Init options */
185141cc406Sopenharmony_ci	  kv_init_options (dev);
186141cc406Sopenharmony_ci	  status = CMD_set_timeout (dev, dev->val[OPT_FEED_TIMEOUT].w);
187141cc406Sopenharmony_ci	}
188141cc406Sopenharmony_ci    }
189141cc406Sopenharmony_ci  dev->scanning = 0;
190141cc406Sopenharmony_ci  return status;
191141cc406Sopenharmony_ci}
192141cc406Sopenharmony_ci
193141cc406Sopenharmony_ci/* Check if device is already open */
194141cc406Sopenharmony_ci
195141cc406Sopenharmony_ciSANE_Bool
196141cc406Sopenharmony_cikv_already_open (PKV_DEV dev)
197141cc406Sopenharmony_ci{
198141cc406Sopenharmony_ci  SANE_Bool status = 0;
199141cc406Sopenharmony_ci
200141cc406Sopenharmony_ci  if (dev->bus_mode == KV_USB_BUS)
201141cc406Sopenharmony_ci    {
202141cc406Sopenharmony_ci      status = kv_usb_already_open (dev);
203141cc406Sopenharmony_ci    }
204141cc406Sopenharmony_ci
205141cc406Sopenharmony_ci  return status;
206141cc406Sopenharmony_ci}
207141cc406Sopenharmony_ci
208141cc406Sopenharmony_ci/* Close a device */
209141cc406Sopenharmony_civoid
210141cc406Sopenharmony_cikv_close (PKV_DEV dev)
211141cc406Sopenharmony_ci{
212141cc406Sopenharmony_ci  if (dev->bus_mode == KV_USB_BUS)
213141cc406Sopenharmony_ci    {
214141cc406Sopenharmony_ci      kv_usb_close (dev);
215141cc406Sopenharmony_ci    }
216141cc406Sopenharmony_ci  dev->scanning = 0;
217141cc406Sopenharmony_ci}
218141cc406Sopenharmony_ci
219141cc406Sopenharmony_ci/* Send command to a device */
220141cc406Sopenharmony_ciSANE_Status
221141cc406Sopenharmony_cikv_send_command (PKV_DEV dev,
222141cc406Sopenharmony_ci		 PKV_CMD_HEADER header, PKV_CMD_RESPONSE response)
223141cc406Sopenharmony_ci{
224141cc406Sopenharmony_ci  SANE_Status status = SANE_STATUS_UNSUPPORTED;
225141cc406Sopenharmony_ci  if (dev->bus_mode == KV_USB_BUS)
226141cc406Sopenharmony_ci    {
227141cc406Sopenharmony_ci      if (!kv_usb_already_open(dev))
228141cc406Sopenharmony_ci	{
229141cc406Sopenharmony_ci	  DBG (DBG_error, "kv_send_command error: device not open.\n");
230141cc406Sopenharmony_ci	  return SANE_STATUS_IO_ERROR;
231141cc406Sopenharmony_ci	}
232141cc406Sopenharmony_ci
233141cc406Sopenharmony_ci      status = kv_usb_send_command (dev, header, response);
234141cc406Sopenharmony_ci    }
235141cc406Sopenharmony_ci
236141cc406Sopenharmony_ci  return status;
237141cc406Sopenharmony_ci}
238141cc406Sopenharmony_ci
239141cc406Sopenharmony_ci/* Commands */
240141cc406Sopenharmony_ci
241141cc406Sopenharmony_ciSANE_Status
242141cc406Sopenharmony_ciCMD_test_unit_ready (PKV_DEV dev, SANE_Bool * ready)
243141cc406Sopenharmony_ci{
244141cc406Sopenharmony_ci  SANE_Status status;
245141cc406Sopenharmony_ci  KV_CMD_HEADER hdr;
246141cc406Sopenharmony_ci  KV_CMD_RESPONSE rs;
247141cc406Sopenharmony_ci
248141cc406Sopenharmony_ci  DBG (DBG_proc, "CMD_test_unit_ready\n");
249141cc406Sopenharmony_ci
250141cc406Sopenharmony_ci  memset (&hdr, 0, sizeof (hdr));
251141cc406Sopenharmony_ci
252141cc406Sopenharmony_ci  hdr.direction = KV_CMD_NONE;
253141cc406Sopenharmony_ci  hdr.cdb[0] = SCSI_TEST_UNIT_READY;
254141cc406Sopenharmony_ci  hdr.cdb_size = 6;
255141cc406Sopenharmony_ci
256141cc406Sopenharmony_ci  status = kv_send_command (dev, &hdr, &rs);
257141cc406Sopenharmony_ci
258141cc406Sopenharmony_ci  if (status == 0)
259141cc406Sopenharmony_ci    {
260141cc406Sopenharmony_ci      *ready = (rs.status == KV_SUCCESS ? 1 : 0);
261141cc406Sopenharmony_ci    }
262141cc406Sopenharmony_ci
263141cc406Sopenharmony_ci  return status;
264141cc406Sopenharmony_ci}
265141cc406Sopenharmony_ci
266141cc406Sopenharmony_ciSANE_Status
267141cc406Sopenharmony_ciCMD_set_timeout (PKV_DEV dev, SANE_Word timeout)
268141cc406Sopenharmony_ci{
269141cc406Sopenharmony_ci  SANE_Status status;
270141cc406Sopenharmony_ci  KV_CMD_HEADER hdr;
271141cc406Sopenharmony_ci  KV_CMD_RESPONSE rs;
272141cc406Sopenharmony_ci
273141cc406Sopenharmony_ci  DBG (DBG_proc, "CMD_set_timeout\n");
274141cc406Sopenharmony_ci
275141cc406Sopenharmony_ci  memset (&hdr, 0, sizeof (hdr));
276141cc406Sopenharmony_ci
277141cc406Sopenharmony_ci  hdr.direction = KV_CMD_OUT;
278141cc406Sopenharmony_ci  hdr.cdb[0] = SCSI_SET_TIMEOUT;
279141cc406Sopenharmony_ci  hdr.cdb[2] = 0x8D;
280141cc406Sopenharmony_ci  hdr.cdb[8] = 0x2;
281141cc406Sopenharmony_ci  hdr.cdb_size = 10;
282141cc406Sopenharmony_ci  hdr.data = dev->buffer;
283141cc406Sopenharmony_ci  dev->buffer[0] = 0;
284141cc406Sopenharmony_ci  dev->buffer[1] = (SANE_Byte) timeout;
285141cc406Sopenharmony_ci  hdr.data_size = 2;
286141cc406Sopenharmony_ci
287141cc406Sopenharmony_ci  status = kv_send_command (dev, &hdr, &rs);
288141cc406Sopenharmony_ci
289141cc406Sopenharmony_ci  return status;
290141cc406Sopenharmony_ci}
291141cc406Sopenharmony_ci
292141cc406Sopenharmony_ciSANE_Status
293141cc406Sopenharmony_ciCMD_read_support_info (PKV_DEV dev)
294141cc406Sopenharmony_ci{
295141cc406Sopenharmony_ci  SANE_Status status;
296141cc406Sopenharmony_ci  KV_CMD_HEADER hdr;
297141cc406Sopenharmony_ci  KV_CMD_RESPONSE rs;
298141cc406Sopenharmony_ci
299141cc406Sopenharmony_ci  DBG (DBG_proc, "CMD_read_support_info\n");
300141cc406Sopenharmony_ci
301141cc406Sopenharmony_ci  memset (&hdr, 0, sizeof (hdr));
302141cc406Sopenharmony_ci
303141cc406Sopenharmony_ci  hdr.direction = KV_CMD_IN;
304141cc406Sopenharmony_ci  hdr.cdb_size = 10;
305141cc406Sopenharmony_ci  hdr.cdb[0] = SCSI_READ_10;
306141cc406Sopenharmony_ci  hdr.cdb[2] = 0x93;
307141cc406Sopenharmony_ci  Ito24 (32, &hdr.cdb[6]);
308141cc406Sopenharmony_ci  hdr.data = dev->buffer;
309141cc406Sopenharmony_ci  hdr.data_size = 32;
310141cc406Sopenharmony_ci
311141cc406Sopenharmony_ci  status = kv_send_command (dev, &hdr, &rs);
312141cc406Sopenharmony_ci
313141cc406Sopenharmony_ci  DBG (DBG_error, "test.\n");
314141cc406Sopenharmony_ci
315141cc406Sopenharmony_ci  if (status == 0)
316141cc406Sopenharmony_ci    {
317141cc406Sopenharmony_ci      if (rs.status == 0)
318141cc406Sopenharmony_ci	{
319141cc406Sopenharmony_ci	  int min_x_res, min_y_res, max_x_res, max_y_res;
320141cc406Sopenharmony_ci	  int step_x_res, step_y_res;
321141cc406Sopenharmony_ci
322141cc406Sopenharmony_ci	  dev->support_info.memory_size
323141cc406Sopenharmony_ci	    = (dev->buffer[2] << 8 | dev->buffer[3]);
324141cc406Sopenharmony_ci	  min_x_res = (dev->buffer[4] << 8) | dev->buffer[5];
325141cc406Sopenharmony_ci	  min_y_res = (dev->buffer[6] << 8) | dev->buffer[7];
326141cc406Sopenharmony_ci	  max_x_res = (dev->buffer[8] << 8) | dev->buffer[9];
327141cc406Sopenharmony_ci	  max_y_res = (dev->buffer[10] << 8) | dev->buffer[11];
328141cc406Sopenharmony_ci	  step_x_res = (dev->buffer[12] << 8) | dev->buffer[13];
329141cc406Sopenharmony_ci	  step_y_res = (dev->buffer[14] << 8) | dev->buffer[15];
330141cc406Sopenharmony_ci
331141cc406Sopenharmony_ci	  dev->support_info.min_resolution =
332141cc406Sopenharmony_ci	    min_x_res > min_y_res ? min_x_res : min_y_res;
333141cc406Sopenharmony_ci	  dev->support_info.max_resolution =
334141cc406Sopenharmony_ci	    max_x_res < max_y_res ? max_x_res : max_y_res;
335141cc406Sopenharmony_ci	  dev->support_info.step_resolution =
336141cc406Sopenharmony_ci	    step_x_res > step_y_res ? step_x_res : step_y_res;
337141cc406Sopenharmony_ci	  dev->support_info.support_duplex =
338141cc406Sopenharmony_ci	    ((dev->buffer[0] & 0x08) == 0) ? 1 : 0;
339141cc406Sopenharmony_ci	  dev->support_info.support_lamp =
340141cc406Sopenharmony_ci	    ((dev->buffer[23] & 0x80) != 0) ? 1 : 0;
341141cc406Sopenharmony_ci
342141cc406Sopenharmony_ci	  dev->support_info.max_x_range = KV_MAX_X_RANGE;
343141cc406Sopenharmony_ci	  dev->support_info.max_y_range = KV_MAX_Y_RANGE;
344141cc406Sopenharmony_ci
345141cc406Sopenharmony_ci	  dev->x_range.min = dev->y_range.min = 0;
346141cc406Sopenharmony_ci	  dev->x_range.max = SANE_FIX (dev->support_info.max_x_range);
347141cc406Sopenharmony_ci	  dev->y_range.max = SANE_FIX (dev->support_info.max_y_range);
348141cc406Sopenharmony_ci	  dev->x_range.quant = dev->y_range.quant = 0;
349141cc406Sopenharmony_ci
350141cc406Sopenharmony_ci	  DBG (DBG_error,
351141cc406Sopenharmony_ci	       "support_info.memory_size = %d (MB)\n",
352141cc406Sopenharmony_ci	       dev->support_info.memory_size);
353141cc406Sopenharmony_ci	  DBG (DBG_error,
354141cc406Sopenharmony_ci	       "support_info.min_resolution = %d (DPI)\n",
355141cc406Sopenharmony_ci	       dev->support_info.min_resolution);
356141cc406Sopenharmony_ci	  DBG (DBG_error,
357141cc406Sopenharmony_ci	       "support_info.max_resolution = %d (DPI)\n",
358141cc406Sopenharmony_ci	       dev->support_info.max_resolution);
359141cc406Sopenharmony_ci	  DBG (DBG_error,
360141cc406Sopenharmony_ci	       "support_info.step_resolution = %d (DPI)\n",
361141cc406Sopenharmony_ci	       dev->support_info.step_resolution);
362141cc406Sopenharmony_ci	  DBG (DBG_error,
363141cc406Sopenharmony_ci	       "support_info.support_duplex = %s\n",
364141cc406Sopenharmony_ci	       dev->support_info.support_duplex ? "TRUE" : "FALSE");
365141cc406Sopenharmony_ci	  DBG (DBG_error, "support_info.support_lamp = %s\n",
366141cc406Sopenharmony_ci	       dev->support_info.support_lamp ? "TRUE" : "FALSE");
367141cc406Sopenharmony_ci	}
368141cc406Sopenharmony_ci      else
369141cc406Sopenharmony_ci	{
370141cc406Sopenharmony_ci	  DBG (DBG_error, "Error in CMD_get_support_info, "
371141cc406Sopenharmony_ci	       "sense_key=%d, ASC=%d, ASCQ=%d\n",
372141cc406Sopenharmony_ci	       get_RS_sense_key (rs.sense),
373141cc406Sopenharmony_ci	       get_RS_ASC (rs.sense), get_RS_ASCQ (rs.sense));
374141cc406Sopenharmony_ci
375141cc406Sopenharmony_ci	}
376141cc406Sopenharmony_ci    }
377141cc406Sopenharmony_ci
378141cc406Sopenharmony_ci  return status;
379141cc406Sopenharmony_ci}
380141cc406Sopenharmony_ci
381141cc406Sopenharmony_ciSANE_Status
382141cc406Sopenharmony_ciCMD_scan (PKV_DEV dev)
383141cc406Sopenharmony_ci{
384141cc406Sopenharmony_ci  SANE_Status status;
385141cc406Sopenharmony_ci  KV_CMD_HEADER hdr;
386141cc406Sopenharmony_ci  KV_CMD_RESPONSE rs;
387141cc406Sopenharmony_ci
388141cc406Sopenharmony_ci  DBG (DBG_proc, "CMD_scan\n");
389141cc406Sopenharmony_ci
390141cc406Sopenharmony_ci  memset (&hdr, 0, sizeof (hdr));
391141cc406Sopenharmony_ci
392141cc406Sopenharmony_ci  hdr.direction = KV_CMD_NONE;
393141cc406Sopenharmony_ci  hdr.cdb[0] = SCSI_SCAN;
394141cc406Sopenharmony_ci  hdr.cdb_size = 6;
395141cc406Sopenharmony_ci
396141cc406Sopenharmony_ci  status = kv_send_command (dev, &hdr, &rs);
397141cc406Sopenharmony_ci
398141cc406Sopenharmony_ci  if (status == 0 && rs.status != 0)
399141cc406Sopenharmony_ci    {
400141cc406Sopenharmony_ci      DBG (DBG_error,
401141cc406Sopenharmony_ci	   "Error in CMD_scan, sense_key=%d, ASC=%d, ASCQ=%d\n",
402141cc406Sopenharmony_ci	   get_RS_sense_key (rs.sense), get_RS_ASC (rs.sense),
403141cc406Sopenharmony_ci	   get_RS_ASCQ (rs.sense));
404141cc406Sopenharmony_ci    }
405141cc406Sopenharmony_ci
406141cc406Sopenharmony_ci  return status;
407141cc406Sopenharmony_ci}
408141cc406Sopenharmony_ci
409141cc406Sopenharmony_ciSANE_Status
410141cc406Sopenharmony_ciCMD_set_window (PKV_DEV dev, int side, PKV_CMD_RESPONSE rs)
411141cc406Sopenharmony_ci{
412141cc406Sopenharmony_ci  unsigned char *window;
413141cc406Sopenharmony_ci  unsigned char *windowdata;
414141cc406Sopenharmony_ci  int size = 74;
415141cc406Sopenharmony_ci  KV_SCAN_MODE scan_mode;
416141cc406Sopenharmony_ci  KV_CMD_HEADER hdr;
417141cc406Sopenharmony_ci
418141cc406Sopenharmony_ci  DBG (DBG_proc, "CMD_set_window\n");
419141cc406Sopenharmony_ci
420141cc406Sopenharmony_ci  window = (unsigned char *) dev->buffer;
421141cc406Sopenharmony_ci  windowdata = window + 8;
422141cc406Sopenharmony_ci
423141cc406Sopenharmony_ci  memset (&hdr, 0, sizeof (hdr));
424141cc406Sopenharmony_ci  memset (window, 0, size);
425141cc406Sopenharmony_ci
426141cc406Sopenharmony_ci  Ito16 (66, &window[6]);	/* Window descriptor block length */
427141cc406Sopenharmony_ci
428141cc406Sopenharmony_ci  /* Set window data */
429141cc406Sopenharmony_ci
430141cc406Sopenharmony_ci  scan_mode = kv_get_mode (dev);
431141cc406Sopenharmony_ci
432141cc406Sopenharmony_ci  kv_set_window_data (dev, scan_mode, side, windowdata);
433141cc406Sopenharmony_ci
434141cc406Sopenharmony_ci  hdr.direction = KV_CMD_OUT;
435141cc406Sopenharmony_ci  hdr.cdb_size = 10;
436141cc406Sopenharmony_ci  hdr.cdb[0] = SCSI_SET_WINDOW;
437141cc406Sopenharmony_ci  Ito24 (size, &hdr.cdb[6]);
438141cc406Sopenharmony_ci  hdr.data = window;
439141cc406Sopenharmony_ci  hdr.data_size = size;
440141cc406Sopenharmony_ci
441141cc406Sopenharmony_ci  hexdump (DBG_error, "window", window, size);
442141cc406Sopenharmony_ci
443141cc406Sopenharmony_ci  return kv_send_command (dev, &hdr, rs);
444141cc406Sopenharmony_ci}
445141cc406Sopenharmony_ci
446141cc406Sopenharmony_ciSANE_Status
447141cc406Sopenharmony_ciCMD_reset_window (PKV_DEV dev)
448141cc406Sopenharmony_ci{
449141cc406Sopenharmony_ci  KV_CMD_HEADER hdr;
450141cc406Sopenharmony_ci  KV_CMD_RESPONSE rs;
451141cc406Sopenharmony_ci  SANE_Status status;
452141cc406Sopenharmony_ci
453141cc406Sopenharmony_ci  DBG (DBG_proc, "CMD_reset_window\n");
454141cc406Sopenharmony_ci
455141cc406Sopenharmony_ci  memset (&hdr, 0, sizeof (hdr));
456141cc406Sopenharmony_ci
457141cc406Sopenharmony_ci  hdr.direction = KV_CMD_NONE;
458141cc406Sopenharmony_ci  hdr.cdb_size = 10;
459141cc406Sopenharmony_ci  hdr.cdb[0] = SCSI_SET_WINDOW;
460141cc406Sopenharmony_ci
461141cc406Sopenharmony_ci  status = kv_send_command (dev, &hdr, &rs);
462141cc406Sopenharmony_ci  if (rs.status != 0)
463141cc406Sopenharmony_ci    status = SANE_STATUS_INVAL;
464141cc406Sopenharmony_ci
465141cc406Sopenharmony_ci  return status;
466141cc406Sopenharmony_ci}
467141cc406Sopenharmony_ci
468141cc406Sopenharmony_ciSANE_Status
469141cc406Sopenharmony_ciCMD_get_buff_status (PKV_DEV dev, int *front_size, int *back_size)
470141cc406Sopenharmony_ci{
471141cc406Sopenharmony_ci  KV_CMD_HEADER hdr;
472141cc406Sopenharmony_ci  KV_CMD_RESPONSE rs;
473141cc406Sopenharmony_ci  SANE_Status status;
474141cc406Sopenharmony_ci  unsigned char *data = (unsigned char *) dev->buffer;
475141cc406Sopenharmony_ci  int size = 12;
476141cc406Sopenharmony_ci  memset (&hdr, 0, sizeof (hdr));
477141cc406Sopenharmony_ci  memset (data, 0, size);
478141cc406Sopenharmony_ci
479141cc406Sopenharmony_ci  hdr.direction = KV_CMD_IN;
480141cc406Sopenharmony_ci  hdr.cdb_size = 10;
481141cc406Sopenharmony_ci  hdr.cdb[0] = SCSI_GET_BUFFER_STATUS;
482141cc406Sopenharmony_ci  hdr.cdb[8] = size;
483141cc406Sopenharmony_ci  hdr.data = data;
484141cc406Sopenharmony_ci  hdr.data_size = size;
485141cc406Sopenharmony_ci
486141cc406Sopenharmony_ci  status = kv_send_command (dev, &hdr, &rs);
487141cc406Sopenharmony_ci  if (status == 0)
488141cc406Sopenharmony_ci    {
489141cc406Sopenharmony_ci      if (rs.status == KV_CHK_CONDITION)
490141cc406Sopenharmony_ci	return SANE_STATUS_NO_DOCS;
491141cc406Sopenharmony_ci      else
492141cc406Sopenharmony_ci	{
493141cc406Sopenharmony_ci	  unsigned char *p = data + 4;
494141cc406Sopenharmony_ci	  if (p[0] == SIDE_FRONT)
495141cc406Sopenharmony_ci	    {
496141cc406Sopenharmony_ci	      *front_size = (p[5] << 16) | (p[6] << 8) | p[7];
497141cc406Sopenharmony_ci	    }
498141cc406Sopenharmony_ci	  else
499141cc406Sopenharmony_ci	    {
500141cc406Sopenharmony_ci	      *back_size = (p[5] << 16) | (p[6] << 8) | p[7];
501141cc406Sopenharmony_ci	    }
502141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
503141cc406Sopenharmony_ci	}
504141cc406Sopenharmony_ci    }
505141cc406Sopenharmony_ci  return status;
506141cc406Sopenharmony_ci}
507141cc406Sopenharmony_ci
508141cc406Sopenharmony_ciSANE_Status
509141cc406Sopenharmony_ciCMD_wait_buff_status (PKV_DEV dev, int *front_size, int *back_size)
510141cc406Sopenharmony_ci{
511141cc406Sopenharmony_ci  SANE_Status status = SANE_STATUS_GOOD;
512141cc406Sopenharmony_ci  int cnt = 0;
513141cc406Sopenharmony_ci  *front_size = 0;
514141cc406Sopenharmony_ci  *back_size = 0;
515141cc406Sopenharmony_ci
516141cc406Sopenharmony_ci  DBG (DBG_proc, "CMD_wait_buff_status: enter feed %s\n",
517141cc406Sopenharmony_ci       dev->val[OPT_MANUALFEED].s);
518141cc406Sopenharmony_ci
519141cc406Sopenharmony_ci  do
520141cc406Sopenharmony_ci    {
521141cc406Sopenharmony_ci      DBG (DBG_proc, "CMD_wait_buff_status: tray #%d of %d\n", cnt,
522141cc406Sopenharmony_ci	   dev->val[OPT_FEED_TIMEOUT].w);
523141cc406Sopenharmony_ci      status = CMD_get_buff_status (dev, front_size, back_size);
524141cc406Sopenharmony_ci      sleep (1);
525141cc406Sopenharmony_ci    }
526141cc406Sopenharmony_ci  while (status == SANE_STATUS_GOOD && (*front_size == 0)
527141cc406Sopenharmony_ci	 && (*back_size == 0) && cnt++ < dev->val[OPT_FEED_TIMEOUT].w);
528141cc406Sopenharmony_ci
529141cc406Sopenharmony_ci  if (cnt > dev->val[OPT_FEED_TIMEOUT].w)
530141cc406Sopenharmony_ci    status = SANE_STATUS_NO_DOCS;
531141cc406Sopenharmony_ci
532141cc406Sopenharmony_ci  if (status == 0)
533141cc406Sopenharmony_ci    DBG (DBG_proc, "CMD_wait_buff_status: exit "
534141cc406Sopenharmony_ci	 "front_size %d, back_size %d\n", *front_size, *back_size);
535141cc406Sopenharmony_ci  else
536141cc406Sopenharmony_ci    DBG (DBG_proc, "CMD_wait_buff_status: exit with no docs\n");
537141cc406Sopenharmony_ci  return status;
538141cc406Sopenharmony_ci}
539141cc406Sopenharmony_ci
540141cc406Sopenharmony_ci
541141cc406Sopenharmony_ciSANE_Status
542141cc406Sopenharmony_ciCMD_read_pic_elements (PKV_DEV dev, int page, int side,
543141cc406Sopenharmony_ci		       int *width, int *height)
544141cc406Sopenharmony_ci{
545141cc406Sopenharmony_ci  SANE_Status status;
546141cc406Sopenharmony_ci  KV_CMD_HEADER hdr;
547141cc406Sopenharmony_ci  KV_CMD_RESPONSE rs;
548141cc406Sopenharmony_ci
549141cc406Sopenharmony_ci  DBG (DBG_proc, "CMD_read_pic_elements\n");
550141cc406Sopenharmony_ci
551141cc406Sopenharmony_ci  memset (&hdr, 0, sizeof (hdr));
552141cc406Sopenharmony_ci
553141cc406Sopenharmony_ci  hdr.direction = KV_CMD_IN;
554141cc406Sopenharmony_ci  hdr.cdb_size = 10;
555141cc406Sopenharmony_ci  hdr.cdb[0] = SCSI_READ_10;
556141cc406Sopenharmony_ci  hdr.cdb[2] = 0x80;
557141cc406Sopenharmony_ci  hdr.cdb[4] = page;
558141cc406Sopenharmony_ci  hdr.cdb[5] = side;
559141cc406Sopenharmony_ci  Ito24 (16, &hdr.cdb[6]);
560141cc406Sopenharmony_ci  hdr.data = dev->buffer;
561141cc406Sopenharmony_ci  hdr.data_size = 16;
562141cc406Sopenharmony_ci
563141cc406Sopenharmony_ci  status = kv_send_command (dev, &hdr, &rs);
564141cc406Sopenharmony_ci  if (status == 0)
565141cc406Sopenharmony_ci    {
566141cc406Sopenharmony_ci      if (rs.status == 0)
567141cc406Sopenharmony_ci	{
568141cc406Sopenharmony_ci	  int s = side == SIDE_FRONT ? 0 : 1;
569141cc406Sopenharmony_ci	  int depth = kv_get_depth (kv_get_mode (dev));
570141cc406Sopenharmony_ci	  *width = B32TOI (dev->buffer);
571141cc406Sopenharmony_ci	  *height = B32TOI (&dev->buffer[4]);
572141cc406Sopenharmony_ci
573141cc406Sopenharmony_ci	  assert ((*width) % 8 == 0);
574141cc406Sopenharmony_ci
575141cc406Sopenharmony_ci	  DBG (DBG_proc, "CMD_read_pic_elements: "
576141cc406Sopenharmony_ci	       "Page %d, Side %s, W=%d, H=%d\n",
577141cc406Sopenharmony_ci	       page, side == SIDE_FRONT ? "F" : "B", *width, *height);
578141cc406Sopenharmony_ci
579141cc406Sopenharmony_ci	  dev->params[s].format = kv_get_mode (dev) == SM_COLOR ?
580141cc406Sopenharmony_ci	    SANE_FRAME_RGB : SANE_FRAME_GRAY;
581141cc406Sopenharmony_ci	  dev->params[s].last_frame = SANE_TRUE;
582141cc406Sopenharmony_ci	  dev->params[s].depth = depth > 8 ? 8 : depth;
583141cc406Sopenharmony_ci	  dev->params[s].lines = *height ? *height
584141cc406Sopenharmony_ci	    : dev->val[OPT_LANDSCAPE].w ? (*width * 3) / 4 : (*width * 4) / 3;
585141cc406Sopenharmony_ci	  dev->params[s].pixels_per_line = *width;
586141cc406Sopenharmony_ci	  dev->params[s].bytes_per_line =
587141cc406Sopenharmony_ci	    (dev->params[s].pixels_per_line / 8) * depth;
588141cc406Sopenharmony_ci	}
589141cc406Sopenharmony_ci      else
590141cc406Sopenharmony_ci	{
591141cc406Sopenharmony_ci	  DBG (DBG_proc, "CMD_read_pic_elements: failed\n");
592141cc406Sopenharmony_ci	  status = SANE_STATUS_INVAL;
593141cc406Sopenharmony_ci	}
594141cc406Sopenharmony_ci    }
595141cc406Sopenharmony_ci
596141cc406Sopenharmony_ci  return status;
597141cc406Sopenharmony_ci}
598141cc406Sopenharmony_ci
599141cc406Sopenharmony_ciSANE_Status
600141cc406Sopenharmony_ciCMD_read_image (PKV_DEV dev, int page, int side,
601141cc406Sopenharmony_ci		unsigned char *buffer, int *psize, KV_CMD_RESPONSE * rs)
602141cc406Sopenharmony_ci{
603141cc406Sopenharmony_ci  SANE_Status status;
604141cc406Sopenharmony_ci  KV_CMD_HEADER hdr;
605141cc406Sopenharmony_ci  int size = *psize;
606141cc406Sopenharmony_ci
607141cc406Sopenharmony_ci  DBG (DBG_proc, "CMD_read_image\n");
608141cc406Sopenharmony_ci
609141cc406Sopenharmony_ci  memset (&hdr, 0, sizeof (hdr));
610141cc406Sopenharmony_ci
611141cc406Sopenharmony_ci  hdr.direction = KV_CMD_IN;
612141cc406Sopenharmony_ci  hdr.cdb_size = 10;
613141cc406Sopenharmony_ci  hdr.cdb[0] = SCSI_READ_10;
614141cc406Sopenharmony_ci  hdr.cdb[4] = page;
615141cc406Sopenharmony_ci  hdr.cdb[5] = side;
616141cc406Sopenharmony_ci  Ito24 (size, &hdr.cdb[6]);
617141cc406Sopenharmony_ci  hdr.data = buffer;
618141cc406Sopenharmony_ci  hdr.data_size = size;
619141cc406Sopenharmony_ci
620141cc406Sopenharmony_ci  *psize = 0;
621141cc406Sopenharmony_ci
622141cc406Sopenharmony_ci  status = kv_send_command (dev, &hdr, rs);
623141cc406Sopenharmony_ci
624141cc406Sopenharmony_ci  if (status)
625141cc406Sopenharmony_ci    return status;
626141cc406Sopenharmony_ci
627141cc406Sopenharmony_ci  *psize = size;
628141cc406Sopenharmony_ci
629141cc406Sopenharmony_ci  if (rs->status == KV_CHK_CONDITION && get_RS_ILI (rs->sense))
630141cc406Sopenharmony_ci    {
631141cc406Sopenharmony_ci      int delta = B32TOI (&rs->sense[3]);
632141cc406Sopenharmony_ci      DBG (DBG_error, "size=%d, delta=0x%x (%d)\n", size, delta, delta);
633141cc406Sopenharmony_ci      *psize = size - delta;
634141cc406Sopenharmony_ci    }
635141cc406Sopenharmony_ci
636141cc406Sopenharmony_ci  DBG (DBG_error, "CMD_read_image: bytes requested=%d, read=%d\n",
637141cc406Sopenharmony_ci       size, *psize);
638141cc406Sopenharmony_ci  DBG (DBG_error, "CMD_read_image: ILI=%d, EOM=%d\n",
639141cc406Sopenharmony_ci       get_RS_ILI (rs->sense), get_RS_EOM (rs->sense));
640141cc406Sopenharmony_ci
641141cc406Sopenharmony_ci  return status;
642141cc406Sopenharmony_ci}
643141cc406Sopenharmony_ci
644141cc406Sopenharmony_ciSANE_Status
645141cc406Sopenharmony_ciCMD_get_document_existanse (PKV_DEV dev)
646141cc406Sopenharmony_ci{
647141cc406Sopenharmony_ci  SANE_Status status;
648141cc406Sopenharmony_ci  KV_CMD_HEADER hdr;
649141cc406Sopenharmony_ci  KV_CMD_RESPONSE rs;
650141cc406Sopenharmony_ci
651141cc406Sopenharmony_ci  DBG (DBG_proc, "CMD_get_document_existanse\n");
652141cc406Sopenharmony_ci
653141cc406Sopenharmony_ci  memset (&hdr, 0, sizeof (hdr));
654141cc406Sopenharmony_ci
655141cc406Sopenharmony_ci  hdr.direction = KV_CMD_IN;
656141cc406Sopenharmony_ci  hdr.cdb_size = 10;
657141cc406Sopenharmony_ci  hdr.cdb[0] = SCSI_READ_10;
658141cc406Sopenharmony_ci  hdr.cdb[2] = 0x81;
659141cc406Sopenharmony_ci  Ito24 (6, &hdr.cdb[6]);
660141cc406Sopenharmony_ci  hdr.data = dev->buffer;
661141cc406Sopenharmony_ci  hdr.data_size = 6;
662141cc406Sopenharmony_ci
663141cc406Sopenharmony_ci  status = kv_send_command (dev, &hdr, &rs);
664141cc406Sopenharmony_ci  if (status)
665141cc406Sopenharmony_ci    return status;
666141cc406Sopenharmony_ci  if (rs.status)
667141cc406Sopenharmony_ci    return SANE_STATUS_NO_DOCS;
668141cc406Sopenharmony_ci  if ((dev->buffer[0] & 0x20) != 0)
669141cc406Sopenharmony_ci    {
670141cc406Sopenharmony_ci      return SANE_STATUS_GOOD;
671141cc406Sopenharmony_ci    }
672141cc406Sopenharmony_ci
673141cc406Sopenharmony_ci  return SANE_STATUS_NO_DOCS;
674141cc406Sopenharmony_ci}
675141cc406Sopenharmony_ci
676141cc406Sopenharmony_ciSANE_Status
677141cc406Sopenharmony_ciCMD_wait_document_existanse (PKV_DEV dev)
678141cc406Sopenharmony_ci{
679141cc406Sopenharmony_ci  SANE_Status status;
680141cc406Sopenharmony_ci  KV_CMD_HEADER hdr;
681141cc406Sopenharmony_ci  KV_CMD_RESPONSE rs;
682141cc406Sopenharmony_ci  int cnt;
683141cc406Sopenharmony_ci
684141cc406Sopenharmony_ci  DBG (DBG_proc, "CMD_wait_document_existanse\n");
685141cc406Sopenharmony_ci
686141cc406Sopenharmony_ci  memset (&hdr, 0, sizeof (hdr));
687141cc406Sopenharmony_ci
688141cc406Sopenharmony_ci  hdr.direction = KV_CMD_IN;
689141cc406Sopenharmony_ci  hdr.cdb_size = 10;
690141cc406Sopenharmony_ci  hdr.cdb[0] = SCSI_READ_10;
691141cc406Sopenharmony_ci  hdr.cdb[2] = 0x81;
692141cc406Sopenharmony_ci  Ito24 (6, &hdr.cdb[6]);
693141cc406Sopenharmony_ci  hdr.data = dev->buffer;
694141cc406Sopenharmony_ci  hdr.data_size = 6;
695141cc406Sopenharmony_ci
696141cc406Sopenharmony_ci  for (cnt = 0; cnt < dev->val[OPT_FEED_TIMEOUT].w; cnt++)
697141cc406Sopenharmony_ci    {
698141cc406Sopenharmony_ci      DBG (DBG_proc, "CMD_wait_document_existanse: tray #%d of %d\n", cnt,
699141cc406Sopenharmony_ci	   dev->val[OPT_FEED_TIMEOUT].w);
700141cc406Sopenharmony_ci      status = kv_send_command (dev, &hdr, &rs);
701141cc406Sopenharmony_ci      if (status)
702141cc406Sopenharmony_ci	return status;
703141cc406Sopenharmony_ci      if (rs.status)
704141cc406Sopenharmony_ci	return SANE_STATUS_NO_DOCS;
705141cc406Sopenharmony_ci      if ((dev->buffer[0] & 0x20) != 0)
706141cc406Sopenharmony_ci	{
707141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
708141cc406Sopenharmony_ci	}
709141cc406Sopenharmony_ci      else if (strcmp (dev->val[OPT_MANUALFEED].s, "off") == 0)
710141cc406Sopenharmony_ci	{
711141cc406Sopenharmony_ci	  return SANE_STATUS_NO_DOCS;
712141cc406Sopenharmony_ci	}
713141cc406Sopenharmony_ci      sleep (1);
714141cc406Sopenharmony_ci    }
715141cc406Sopenharmony_ci
716141cc406Sopenharmony_ci  return SANE_STATUS_NO_DOCS;
717141cc406Sopenharmony_ci}
718141cc406Sopenharmony_ci
719141cc406Sopenharmony_ciSANE_Status
720141cc406Sopenharmony_ciCMD_request_sense (PKV_DEV dev)
721141cc406Sopenharmony_ci{
722141cc406Sopenharmony_ci  KV_CMD_HEADER hdr;
723141cc406Sopenharmony_ci  KV_CMD_RESPONSE rs;
724141cc406Sopenharmony_ci
725141cc406Sopenharmony_ci  DBG (DBG_proc, "CMD_request_sense\n");
726141cc406Sopenharmony_ci  memset (&hdr, 0, sizeof (hdr));
727141cc406Sopenharmony_ci  hdr.direction = KV_CMD_IN;
728141cc406Sopenharmony_ci  hdr.cdb[0] = SCSI_REQUEST_SENSE;
729141cc406Sopenharmony_ci  hdr.cdb[4] = 0x12;
730141cc406Sopenharmony_ci  hdr.cdb_size = 6;
731141cc406Sopenharmony_ci  hdr.data_size = 0x12;
732141cc406Sopenharmony_ci  hdr.data = dev->buffer;
733141cc406Sopenharmony_ci
734141cc406Sopenharmony_ci  return kv_send_command (dev, &hdr, &rs);
735141cc406Sopenharmony_ci}
736141cc406Sopenharmony_ci
737141cc406Sopenharmony_ci/* Scan routines */
738141cc406Sopenharmony_ci
739141cc406Sopenharmony_ci/* Allocate image buffer for one page (1 or 2 sides) */
740141cc406Sopenharmony_ci
741141cc406Sopenharmony_ciSANE_Status
742141cc406Sopenharmony_ciAllocateImageBuffer (PKV_DEV dev)
743141cc406Sopenharmony_ci{
744141cc406Sopenharmony_ci  int *size = dev->bytes_to_read;
745141cc406Sopenharmony_ci  int sides = IS_DUPLEX (dev) ? 2 : 1;
746141cc406Sopenharmony_ci  int i;
747141cc406Sopenharmony_ci  size[0] = dev->params[0].bytes_per_line * dev->params[0].lines;
748141cc406Sopenharmony_ci  size[1] = dev->params[1].bytes_per_line * dev->params[1].lines;
749141cc406Sopenharmony_ci
750141cc406Sopenharmony_ci  DBG (DBG_proc, "AllocateImageBuffer: enter\n");
751141cc406Sopenharmony_ci
752141cc406Sopenharmony_ci  for (i = 0; i < sides; i++)
753141cc406Sopenharmony_ci    {
754141cc406Sopenharmony_ci      SANE_Byte *p;
755141cc406Sopenharmony_ci      DBG (DBG_proc, "AllocateImageBuffer: size(%c)=%d\n",
756141cc406Sopenharmony_ci	   i ? 'B' : 'F', size[i]);
757141cc406Sopenharmony_ci
758141cc406Sopenharmony_ci      if (dev->img_buffers[i] == NULL)
759141cc406Sopenharmony_ci	{
760141cc406Sopenharmony_ci	  p = (SANE_Byte *) malloc (size[i]);
761141cc406Sopenharmony_ci	  if (p == NULL)
762141cc406Sopenharmony_ci	    {
763141cc406Sopenharmony_ci	      return SANE_STATUS_NO_MEM;
764141cc406Sopenharmony_ci	    }
765141cc406Sopenharmony_ci	  dev->img_buffers[i] = p;
766141cc406Sopenharmony_ci	}
767141cc406Sopenharmony_ci      else
768141cc406Sopenharmony_ci	{
769141cc406Sopenharmony_ci	  p = (SANE_Byte *) realloc (dev->img_buffers[i], size[i]);
770141cc406Sopenharmony_ci	  if (p == NULL)
771141cc406Sopenharmony_ci	    {
772141cc406Sopenharmony_ci	      return SANE_STATUS_NO_MEM;
773141cc406Sopenharmony_ci	    }
774141cc406Sopenharmony_ci	  else
775141cc406Sopenharmony_ci	    {
776141cc406Sopenharmony_ci	      dev->img_buffers[i] = p;
777141cc406Sopenharmony_ci	    }
778141cc406Sopenharmony_ci	}
779141cc406Sopenharmony_ci    }
780141cc406Sopenharmony_ci  DBG (DBG_proc, "AllocateImageBuffer: exit\n");
781141cc406Sopenharmony_ci
782141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
783141cc406Sopenharmony_ci}
784141cc406Sopenharmony_ci
785141cc406Sopenharmony_ci/* Read image data from scanner dev->img_buffers[0],
786141cc406Sopenharmony_ci   for the simplex page */
787141cc406Sopenharmony_ciSANE_Status
788141cc406Sopenharmony_ciReadImageDataSimplex (PKV_DEV dev, int page)
789141cc406Sopenharmony_ci{
790141cc406Sopenharmony_ci  int bytes_to_read = dev->bytes_to_read[0];
791141cc406Sopenharmony_ci  SANE_Byte *buffer = (SANE_Byte *) dev->buffer;
792141cc406Sopenharmony_ci  int buff_size = SCSI_BUFFER_SIZE;
793141cc406Sopenharmony_ci  SANE_Byte *pt = dev->img_buffers[0];
794141cc406Sopenharmony_ci  KV_CMD_RESPONSE rs;
795141cc406Sopenharmony_ci  dev->img_size[0] = 0;
796141cc406Sopenharmony_ci  dev->img_size[1] = 0;
797141cc406Sopenharmony_ci
798141cc406Sopenharmony_ci  /* read loop */
799141cc406Sopenharmony_ci  do
800141cc406Sopenharmony_ci    {
801141cc406Sopenharmony_ci      int size = buff_size;
802141cc406Sopenharmony_ci      SANE_Status status;
803141cc406Sopenharmony_ci      DBG (DBG_error, "Bytes left = %d\n", bytes_to_read);
804141cc406Sopenharmony_ci      status = CMD_read_image (dev, page, SIDE_FRONT, buffer, &size, &rs);
805141cc406Sopenharmony_ci      if (status)
806141cc406Sopenharmony_ci	{
807141cc406Sopenharmony_ci	  return status;
808141cc406Sopenharmony_ci	}
809141cc406Sopenharmony_ci      if (rs.status)
810141cc406Sopenharmony_ci	{
811141cc406Sopenharmony_ci	  if (get_RS_sense_key (rs.sense))
812141cc406Sopenharmony_ci	    {
813141cc406Sopenharmony_ci	      DBG (DBG_error, "Error reading image data, "
814141cc406Sopenharmony_ci		   "sense_key=%d, ASC=%d, ASCQ=%d",
815141cc406Sopenharmony_ci		   get_RS_sense_key (rs.sense),
816141cc406Sopenharmony_ci		   get_RS_ASC (rs.sense), get_RS_ASCQ (rs.sense));
817141cc406Sopenharmony_ci
818141cc406Sopenharmony_ci	      if (get_RS_sense_key (rs.sense) == 3)
819141cc406Sopenharmony_ci		{
820141cc406Sopenharmony_ci		  if (!get_RS_ASCQ (rs.sense))
821141cc406Sopenharmony_ci		    return SANE_STATUS_NO_DOCS;
822141cc406Sopenharmony_ci		  return SANE_STATUS_JAMMED;
823141cc406Sopenharmony_ci		}
824141cc406Sopenharmony_ci	      return SANE_STATUS_IO_ERROR;
825141cc406Sopenharmony_ci	    }
826141cc406Sopenharmony_ci
827141cc406Sopenharmony_ci	}
828141cc406Sopenharmony_ci      /* copy data to image buffer */
829141cc406Sopenharmony_ci      if (size > bytes_to_read)
830141cc406Sopenharmony_ci	{
831141cc406Sopenharmony_ci	  size = bytes_to_read;
832141cc406Sopenharmony_ci	}
833141cc406Sopenharmony_ci      if (size > 0)
834141cc406Sopenharmony_ci	{
835141cc406Sopenharmony_ci	  memcpy (pt, buffer, size);
836141cc406Sopenharmony_ci	  bytes_to_read -= size;
837141cc406Sopenharmony_ci	  pt += size;
838141cc406Sopenharmony_ci	  dev->img_size[0] += size;
839141cc406Sopenharmony_ci	}
840141cc406Sopenharmony_ci    }
841141cc406Sopenharmony_ci  while (!get_RS_EOM (rs.sense));
842141cc406Sopenharmony_ci
843141cc406Sopenharmony_ci  assert (pt == dev->img_buffers[0] + dev->img_size[0]);
844141cc406Sopenharmony_ci  DBG (DBG_error, "Image size = %d\n", dev->img_size[0]);
845141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
846141cc406Sopenharmony_ci}
847141cc406Sopenharmony_ci
848141cc406Sopenharmony_ci/* Read image data from scanner dev->img_buffers[0],
849141cc406Sopenharmony_ci   for the duplex page */
850141cc406Sopenharmony_ciSANE_Status
851141cc406Sopenharmony_ciReadImageDataDuplex (PKV_DEV dev, int page)
852141cc406Sopenharmony_ci{
853141cc406Sopenharmony_ci  int bytes_to_read[2];
854141cc406Sopenharmony_ci  SANE_Byte *buffer = (SANE_Byte *) dev->buffer;
855141cc406Sopenharmony_ci  int buff_size[2];
856141cc406Sopenharmony_ci  SANE_Byte *pt[2];
857141cc406Sopenharmony_ci  KV_CMD_RESPONSE rs;
858141cc406Sopenharmony_ci  int sides[2];
859141cc406Sopenharmony_ci  SANE_Bool eoms[2];
860141cc406Sopenharmony_ci  int current_side = 1;
861141cc406Sopenharmony_ci
862141cc406Sopenharmony_ci  bytes_to_read[0] = dev->bytes_to_read[0];
863141cc406Sopenharmony_ci  bytes_to_read[1] = dev->bytes_to_read[1];
864141cc406Sopenharmony_ci
865141cc406Sopenharmony_ci  pt[0] = dev->img_buffers[0];
866141cc406Sopenharmony_ci  pt[1] = dev->img_buffers[1];
867141cc406Sopenharmony_ci
868141cc406Sopenharmony_ci  sides[0] = SIDE_FRONT;
869141cc406Sopenharmony_ci  sides[1] = SIDE_BACK;
870141cc406Sopenharmony_ci  eoms[0] = eoms[1] = 0;
871141cc406Sopenharmony_ci
872141cc406Sopenharmony_ci  buff_size[0] = SCSI_BUFFER_SIZE;
873141cc406Sopenharmony_ci  buff_size[1] = SCSI_BUFFER_SIZE;
874141cc406Sopenharmony_ci  dev->img_size[0] = 0;
875141cc406Sopenharmony_ci  dev->img_size[1] = 0;
876141cc406Sopenharmony_ci
877141cc406Sopenharmony_ci  /* read loop */
878141cc406Sopenharmony_ci  do
879141cc406Sopenharmony_ci    {
880141cc406Sopenharmony_ci      int size = buff_size[current_side];
881141cc406Sopenharmony_ci      SANE_Status status;
882141cc406Sopenharmony_ci      DBG (DBG_error, "Bytes left (F) = %d\n", bytes_to_read[0]);
883141cc406Sopenharmony_ci      DBG (DBG_error, "Bytes left (B) = %d\n", bytes_to_read[1]);
884141cc406Sopenharmony_ci
885141cc406Sopenharmony_ci      status = CMD_read_image (dev, page, sides[current_side],
886141cc406Sopenharmony_ci			       buffer, &size, &rs);
887141cc406Sopenharmony_ci      if (status)
888141cc406Sopenharmony_ci	{
889141cc406Sopenharmony_ci	  return status;
890141cc406Sopenharmony_ci	}
891141cc406Sopenharmony_ci      if (rs.status)
892141cc406Sopenharmony_ci	{
893141cc406Sopenharmony_ci	  if (get_RS_sense_key (rs.sense))
894141cc406Sopenharmony_ci	    {
895141cc406Sopenharmony_ci	      DBG (DBG_error, "Error reading image data, "
896141cc406Sopenharmony_ci		   "sense_key=%d, ASC=%d, ASCQ=%d",
897141cc406Sopenharmony_ci		   get_RS_sense_key (rs.sense),
898141cc406Sopenharmony_ci		   get_RS_ASC (rs.sense), get_RS_ASCQ (rs.sense));
899141cc406Sopenharmony_ci
900141cc406Sopenharmony_ci	      if (get_RS_sense_key (rs.sense) == 3)
901141cc406Sopenharmony_ci		{
902141cc406Sopenharmony_ci		  if (!get_RS_ASCQ (rs.sense))
903141cc406Sopenharmony_ci		    return SANE_STATUS_NO_DOCS;
904141cc406Sopenharmony_ci		  return SANE_STATUS_JAMMED;
905141cc406Sopenharmony_ci		}
906141cc406Sopenharmony_ci	      return SANE_STATUS_IO_ERROR;
907141cc406Sopenharmony_ci	    }
908141cc406Sopenharmony_ci	}
909141cc406Sopenharmony_ci
910141cc406Sopenharmony_ci      /* copy data to image buffer */
911141cc406Sopenharmony_ci      if (size > bytes_to_read[current_side])
912141cc406Sopenharmony_ci	{
913141cc406Sopenharmony_ci	  size = bytes_to_read[current_side];
914141cc406Sopenharmony_ci	}
915141cc406Sopenharmony_ci      if (size > 0)
916141cc406Sopenharmony_ci	{
917141cc406Sopenharmony_ci	  memcpy (pt[current_side], buffer, size);
918141cc406Sopenharmony_ci	  bytes_to_read[current_side] -= size;
919141cc406Sopenharmony_ci	  pt[current_side] += size;
920141cc406Sopenharmony_ci	  dev->img_size[current_side] += size;
921141cc406Sopenharmony_ci	}
922141cc406Sopenharmony_ci      if (rs.status)
923141cc406Sopenharmony_ci	{
924141cc406Sopenharmony_ci	  if (get_RS_EOM (rs.sense))
925141cc406Sopenharmony_ci	    {
926141cc406Sopenharmony_ci	      eoms[current_side] = 1;
927141cc406Sopenharmony_ci	    }
928141cc406Sopenharmony_ci	  if (get_RS_ILI (rs.sense))
929141cc406Sopenharmony_ci	    {
930141cc406Sopenharmony_ci	      current_side++;
931141cc406Sopenharmony_ci	      current_side &= 1;
932141cc406Sopenharmony_ci	    }
933141cc406Sopenharmony_ci	}
934141cc406Sopenharmony_ci    }
935141cc406Sopenharmony_ci  while (eoms[0] == 0 || eoms[1] == 0);
936141cc406Sopenharmony_ci
937141cc406Sopenharmony_ci  DBG (DBG_error, "Image size (F) = %d\n", dev->img_size[0]);
938141cc406Sopenharmony_ci  DBG (DBG_error, "Image size (B) = %d\n", dev->img_size[1]);
939141cc406Sopenharmony_ci
940141cc406Sopenharmony_ci  assert (pt[0] == dev->img_buffers[0] + dev->img_size[0]);
941141cc406Sopenharmony_ci  assert (pt[1] == dev->img_buffers[1] + dev->img_size[1]);
942141cc406Sopenharmony_ci
943141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
944141cc406Sopenharmony_ci}
945141cc406Sopenharmony_ci
946141cc406Sopenharmony_ci/* Read image data for one page */
947141cc406Sopenharmony_ciSANE_Status
948141cc406Sopenharmony_ciReadImageData (PKV_DEV dev, int page)
949141cc406Sopenharmony_ci{
950141cc406Sopenharmony_ci  SANE_Status status;
951141cc406Sopenharmony_ci  DBG (DBG_proc, "Reading image data for page %d\n", page);
952141cc406Sopenharmony_ci
953141cc406Sopenharmony_ci  if (IS_DUPLEX (dev))
954141cc406Sopenharmony_ci    {
955141cc406Sopenharmony_ci      DBG (DBG_proc, "ReadImageData: Duplex %d\n", page);
956141cc406Sopenharmony_ci      status = ReadImageDataDuplex (dev, page);
957141cc406Sopenharmony_ci    }
958141cc406Sopenharmony_ci  else
959141cc406Sopenharmony_ci    {
960141cc406Sopenharmony_ci      DBG (DBG_proc, "ReadImageData: Simplex %d\n", page);
961141cc406Sopenharmony_ci      status = ReadImageDataSimplex (dev, page);
962141cc406Sopenharmony_ci    }
963141cc406Sopenharmony_ci  dev->img_pt[0] = dev->img_buffers[0];
964141cc406Sopenharmony_ci  dev->img_pt[1] = dev->img_buffers[1];
965141cc406Sopenharmony_ci
966141cc406Sopenharmony_ci  DBG (DBG_proc, "Reading image data for page %d, finished\n", page);
967141cc406Sopenharmony_ci
968141cc406Sopenharmony_ci  return status;
969141cc406Sopenharmony_ci}
970141cc406Sopenharmony_ci
971141cc406Sopenharmony_ci/* Look in image for likely upper and left paper edges, then rotate
972141cc406Sopenharmony_ci * image so that upper left corner of paper is upper left of image.
973141cc406Sopenharmony_ci * FIXME: should we do this before we binarize instead of after? */
974141cc406Sopenharmony_ciSANE_Status
975141cc406Sopenharmony_cibuffer_deskew(PKV_DEV s, int side)
976141cc406Sopenharmony_ci{
977141cc406Sopenharmony_ci  SANE_Status ret = SANE_STATUS_GOOD;
978141cc406Sopenharmony_ci  int bg_color = 0xd6;
979141cc406Sopenharmony_ci  int side_index = (side == SIDE_FRONT)?0:1;
980141cc406Sopenharmony_ci  int resolution = s->val[OPT_RESOLUTION].w;
981141cc406Sopenharmony_ci
982141cc406Sopenharmony_ci  DBG (10, "buffer_deskew: start\n");
983141cc406Sopenharmony_ci
984141cc406Sopenharmony_ci  /*only find skew on first image from a page, or if first image had error */
985141cc406Sopenharmony_ci  if(side == SIDE_FRONT || s->deskew_stat){
986141cc406Sopenharmony_ci
987141cc406Sopenharmony_ci    s->deskew_stat = sanei_magic_findSkew(
988141cc406Sopenharmony_ci      &s->params[side_index],s->img_buffers[side_index],
989141cc406Sopenharmony_ci      resolution,resolution,
990141cc406Sopenharmony_ci      &s->deskew_vals[0],&s->deskew_vals[1],&s->deskew_slope);
991141cc406Sopenharmony_ci
992141cc406Sopenharmony_ci    if(s->deskew_stat){
993141cc406Sopenharmony_ci      DBG (5, "buffer_despeck: bad findSkew, bailing\n");
994141cc406Sopenharmony_ci      goto cleanup;
995141cc406Sopenharmony_ci    }
996141cc406Sopenharmony_ci  }
997141cc406Sopenharmony_ci  /* backside images can use a 'flipped' version of frontside data */
998141cc406Sopenharmony_ci  else{
999141cc406Sopenharmony_ci    s->deskew_slope *= -1;
1000141cc406Sopenharmony_ci    s->deskew_vals[0]
1001141cc406Sopenharmony_ci      = s->params[side_index].pixels_per_line - s->deskew_vals[0];
1002141cc406Sopenharmony_ci  }
1003141cc406Sopenharmony_ci
1004141cc406Sopenharmony_ci  ret = sanei_magic_rotate(&s->params[side_index],s->img_buffers[side_index],
1005141cc406Sopenharmony_ci    s->deskew_vals[0],s->deskew_vals[1],s->deskew_slope,bg_color);
1006141cc406Sopenharmony_ci
1007141cc406Sopenharmony_ci  if(ret){
1008141cc406Sopenharmony_ci    DBG(5,"buffer_deskew: rotate error: %d",ret);
1009141cc406Sopenharmony_ci    ret = SANE_STATUS_GOOD;
1010141cc406Sopenharmony_ci    goto cleanup;
1011141cc406Sopenharmony_ci  }
1012141cc406Sopenharmony_ci
1013141cc406Sopenharmony_ci  cleanup:
1014141cc406Sopenharmony_ci  DBG (10, "buffer_deskew: finish\n");
1015141cc406Sopenharmony_ci  return ret;
1016141cc406Sopenharmony_ci}
1017141cc406Sopenharmony_ci
1018141cc406Sopenharmony_ci/* Look in image for likely left/right/bottom paper edges, then crop image.
1019141cc406Sopenharmony_ci * Does not attempt to rotate the image, that should be done first.
1020141cc406Sopenharmony_ci * FIXME: should we do this before we binarize instead of after? */
1021141cc406Sopenharmony_ciSANE_Status
1022141cc406Sopenharmony_cibuffer_crop(PKV_DEV s, int side)
1023141cc406Sopenharmony_ci{
1024141cc406Sopenharmony_ci  SANE_Status ret = SANE_STATUS_GOOD;
1025141cc406Sopenharmony_ci  int side_index = (side == SIDE_FRONT)?0:1;
1026141cc406Sopenharmony_ci  int resolution = s->val[OPT_RESOLUTION].w;
1027141cc406Sopenharmony_ci
1028141cc406Sopenharmony_ci  DBG (10, "buffer_crop: start\n");
1029141cc406Sopenharmony_ci
1030141cc406Sopenharmony_ci  /*only find edges on first image from a page, or if first image had error */
1031141cc406Sopenharmony_ci  if(side == SIDE_FRONT || s->crop_stat){
1032141cc406Sopenharmony_ci
1033141cc406Sopenharmony_ci    s->crop_stat = sanei_magic_findEdges(
1034141cc406Sopenharmony_ci      &s->params[side_index],s->img_buffers[side_index],
1035141cc406Sopenharmony_ci      resolution,resolution,
1036141cc406Sopenharmony_ci      &s->crop_vals[0],&s->crop_vals[1],&s->crop_vals[2],&s->crop_vals[3]);
1037141cc406Sopenharmony_ci
1038141cc406Sopenharmony_ci    if(s->crop_stat){
1039141cc406Sopenharmony_ci      DBG (5, "buffer_crop: bad edges, bailing\n");
1040141cc406Sopenharmony_ci      goto cleanup;
1041141cc406Sopenharmony_ci    }
1042141cc406Sopenharmony_ci
1043141cc406Sopenharmony_ci    DBG (15, "buffer_crop: t:%d b:%d l:%d r:%d\n",
1044141cc406Sopenharmony_ci      s->crop_vals[0],s->crop_vals[1],s->crop_vals[2],s->crop_vals[3]);
1045141cc406Sopenharmony_ci
1046141cc406Sopenharmony_ci    /* we don't listen to the 'top' value, since the top is not padded */
1047141cc406Sopenharmony_ci    /*s->crop_vals[0] = 0;*/
1048141cc406Sopenharmony_ci  }
1049141cc406Sopenharmony_ci  /* backside images can use a 'flipped' version of frontside data */
1050141cc406Sopenharmony_ci  else{
1051141cc406Sopenharmony_ci    int left  = s->crop_vals[2];
1052141cc406Sopenharmony_ci    int right = s->crop_vals[3];
1053141cc406Sopenharmony_ci
1054141cc406Sopenharmony_ci    s->crop_vals[2] = s->params[side_index].pixels_per_line - right;
1055141cc406Sopenharmony_ci    s->crop_vals[3] = s->params[side_index].pixels_per_line - left;
1056141cc406Sopenharmony_ci  }
1057141cc406Sopenharmony_ci
1058141cc406Sopenharmony_ci  /* now crop the image */
1059141cc406Sopenharmony_ci  ret = sanei_magic_crop(&s->params[side_index],s->img_buffers[side_index],
1060141cc406Sopenharmony_ci      s->crop_vals[0],s->crop_vals[1],s->crop_vals[2],s->crop_vals[3]);
1061141cc406Sopenharmony_ci
1062141cc406Sopenharmony_ci  if(ret){
1063141cc406Sopenharmony_ci    DBG (5, "buffer_crop: bad crop, bailing\n");
1064141cc406Sopenharmony_ci    ret = SANE_STATUS_GOOD;
1065141cc406Sopenharmony_ci    goto cleanup;
1066141cc406Sopenharmony_ci  }
1067141cc406Sopenharmony_ci
1068141cc406Sopenharmony_ci  /* update image size counter to new, smaller size */
1069141cc406Sopenharmony_ci  s->img_size[side_index]
1070141cc406Sopenharmony_ci    = s->params[side_index].lines * s->params[side_index].bytes_per_line;
1071141cc406Sopenharmony_ci
1072141cc406Sopenharmony_ci  cleanup:
1073141cc406Sopenharmony_ci  DBG (10, "buffer_crop: finish\n");
1074141cc406Sopenharmony_ci  return ret;
1075141cc406Sopenharmony_ci}
1076141cc406Sopenharmony_ci
1077141cc406Sopenharmony_ci/* Look in image for disconnected 'spots' of the requested size.
1078141cc406Sopenharmony_ci * Replace the spots with the average color of the surrounding pixels.
1079141cc406Sopenharmony_ci * FIXME: should we do this before we binarize instead of after? */
1080141cc406Sopenharmony_ciSANE_Status
1081141cc406Sopenharmony_cibuffer_despeck(PKV_DEV s, int side)
1082141cc406Sopenharmony_ci{
1083141cc406Sopenharmony_ci  SANE_Status ret = SANE_STATUS_GOOD;
1084141cc406Sopenharmony_ci  int side_index = (side == SIDE_FRONT)?0:1;
1085141cc406Sopenharmony_ci
1086141cc406Sopenharmony_ci  DBG (10, "buffer_despeck: start\n");
1087141cc406Sopenharmony_ci
1088141cc406Sopenharmony_ci  ret = sanei_magic_despeck(
1089141cc406Sopenharmony_ci    &s->params[side_index],s->img_buffers[side_index],s->val[OPT_SWDESPECK].w
1090141cc406Sopenharmony_ci  );
1091141cc406Sopenharmony_ci  if(ret){
1092141cc406Sopenharmony_ci    DBG (5, "buffer_despeck: bad despeck, bailing\n");
1093141cc406Sopenharmony_ci    ret = SANE_STATUS_GOOD;
1094141cc406Sopenharmony_ci    goto cleanup;
1095141cc406Sopenharmony_ci  }
1096141cc406Sopenharmony_ci
1097141cc406Sopenharmony_ci  cleanup:
1098141cc406Sopenharmony_ci  DBG (10, "buffer_despeck: finish\n");
1099141cc406Sopenharmony_ci  return ret;
1100141cc406Sopenharmony_ci}
1101141cc406Sopenharmony_ci
1102141cc406Sopenharmony_ci/* Look if image has too few dark pixels.
1103141cc406Sopenharmony_ci * FIXME: should we do this before we binarize instead of after? */
1104141cc406Sopenharmony_ciint
1105141cc406Sopenharmony_cibuffer_isblank(PKV_DEV s, int side)
1106141cc406Sopenharmony_ci{
1107141cc406Sopenharmony_ci  SANE_Status ret = SANE_STATUS_GOOD;
1108141cc406Sopenharmony_ci  int side_index = (side == SIDE_FRONT)?0:1;
1109141cc406Sopenharmony_ci  int status = 0;
1110141cc406Sopenharmony_ci
1111141cc406Sopenharmony_ci  DBG (10, "buffer_isblank: start\n");
1112141cc406Sopenharmony_ci
1113141cc406Sopenharmony_ci  ret = sanei_magic_isBlank(
1114141cc406Sopenharmony_ci    &s->params[side_index],s->img_buffers[side_index],
1115141cc406Sopenharmony_ci    SANE_UNFIX(s->val[OPT_SWSKIP].w)
1116141cc406Sopenharmony_ci  );
1117141cc406Sopenharmony_ci
1118141cc406Sopenharmony_ci  if(ret == SANE_STATUS_NO_DOCS){
1119141cc406Sopenharmony_ci    DBG (5, "buffer_isblank: blank!\n");
1120141cc406Sopenharmony_ci    status = 1;
1121141cc406Sopenharmony_ci  }
1122141cc406Sopenharmony_ci  else if(ret){
1123141cc406Sopenharmony_ci    DBG (5, "buffer_isblank: error %d\n",ret);
1124141cc406Sopenharmony_ci  }
1125141cc406Sopenharmony_ci
1126141cc406Sopenharmony_ci  DBG (10, "buffer_isblank: finished\n");
1127141cc406Sopenharmony_ci  return status;
1128141cc406Sopenharmony_ci}
1129141cc406Sopenharmony_ci
1130141cc406Sopenharmony_ci/* Look if image needs rotation
1131141cc406Sopenharmony_ci * FIXME: should we do this before we binarize instead of after? */
1132141cc406Sopenharmony_ciSANE_Status
1133141cc406Sopenharmony_cibuffer_rotate(PKV_DEV s, int side)
1134141cc406Sopenharmony_ci{
1135141cc406Sopenharmony_ci  SANE_Status ret = SANE_STATUS_GOOD;
1136141cc406Sopenharmony_ci  int angle = 0;
1137141cc406Sopenharmony_ci  int side_index = (side == SIDE_FRONT)?0:1;
1138141cc406Sopenharmony_ci  int resolution = s->val[OPT_RESOLUTION].w;
1139141cc406Sopenharmony_ci
1140141cc406Sopenharmony_ci  DBG (10, "buffer_rotate: start\n");
1141141cc406Sopenharmony_ci
1142141cc406Sopenharmony_ci  if(s->val[OPT_SWDEROTATE].w){
1143141cc406Sopenharmony_ci    ret = sanei_magic_findTurn(
1144141cc406Sopenharmony_ci      &s->params[side_index],s->img_buffers[side_index],
1145141cc406Sopenharmony_ci      resolution,resolution,&angle);
1146141cc406Sopenharmony_ci
1147141cc406Sopenharmony_ci    if(ret){
1148141cc406Sopenharmony_ci      DBG (5, "buffer_rotate: error %d\n",ret);
1149141cc406Sopenharmony_ci      ret = SANE_STATUS_GOOD;
1150141cc406Sopenharmony_ci      goto cleanup;
1151141cc406Sopenharmony_ci    }
1152141cc406Sopenharmony_ci  }
1153141cc406Sopenharmony_ci
1154141cc406Sopenharmony_ci  angle += s->val[OPT_ROTATE].w;
1155141cc406Sopenharmony_ci
1156141cc406Sopenharmony_ci  /*90 or 270 degree rotations are reversed on back side*/
1157141cc406Sopenharmony_ci  if(side == SIDE_BACK && s->val[OPT_ROTATE].w % 180){
1158141cc406Sopenharmony_ci    angle += 180;
1159141cc406Sopenharmony_ci  }
1160141cc406Sopenharmony_ci
1161141cc406Sopenharmony_ci  ret = sanei_magic_turn(
1162141cc406Sopenharmony_ci    &s->params[side_index],s->img_buffers[side_index],
1163141cc406Sopenharmony_ci    angle);
1164141cc406Sopenharmony_ci
1165141cc406Sopenharmony_ci  if(ret){
1166141cc406Sopenharmony_ci    DBG (5, "buffer_rotate: error %d\n",ret);
1167141cc406Sopenharmony_ci    ret = SANE_STATUS_GOOD;
1168141cc406Sopenharmony_ci    goto cleanup;
1169141cc406Sopenharmony_ci  }
1170141cc406Sopenharmony_ci
1171141cc406Sopenharmony_ci  /* update image size counter to new, smaller size */
1172141cc406Sopenharmony_ci  s->img_size[side_index]
1173141cc406Sopenharmony_ci    = s->params[side_index].lines * s->params[side_index].bytes_per_line;
1174141cc406Sopenharmony_ci
1175141cc406Sopenharmony_ci  cleanup:
1176141cc406Sopenharmony_ci  DBG (10, "buffer_rotate: finished\n");
1177141cc406Sopenharmony_ci  return ret;
1178141cc406Sopenharmony_ci}
1179