1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci
3141cc406Sopenharmony_ci   This file is part of the SANE package.
4141cc406Sopenharmony_ci
5141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
6141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
7141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
8141cc406Sopenharmony_ci   License, or (at your option) any later version.
9141cc406Sopenharmony_ci
10141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
11141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
12141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13141cc406Sopenharmony_ci   General Public License for more details.
14141cc406Sopenharmony_ci
15141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
16141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17141cc406Sopenharmony_ci
18141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
19141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
20141cc406Sopenharmony_ci
21141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
22141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
23141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
24141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
25141cc406Sopenharmony_ci   account of linking the SANE library code into it.
26141cc406Sopenharmony_ci
27141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
28141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
29141cc406Sopenharmony_ci   License.
30141cc406Sopenharmony_ci
31141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
32141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
33141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
34141cc406Sopenharmony_ci
35141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
36141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
37141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice. */
38141cc406Sopenharmony_ci
39141cc406Sopenharmony_ci/*
40141cc406Sopenharmony_ci*/
41141cc406Sopenharmony_ci
42141cc406Sopenharmony_ci#include <time.h>
43141cc406Sopenharmony_ci
44141cc406Sopenharmony_ci
45141cc406Sopenharmony_ci/* SCSI commands that the Ibm scanners understand: */
46141cc406Sopenharmony_ci#define IBM_SCSI_TEST_UNIT_READY	0x00
47141cc406Sopenharmony_ci#define IBM_SCSI_SET_WINDOW	        0x24
48141cc406Sopenharmony_ci#define IBM_SCSI_GET_WINDOW	        0x25
49141cc406Sopenharmony_ci#define IBM_SCSI_READ_SCANNED_DATA	0x28
50141cc406Sopenharmony_ci#define IBM_SCSI_INQUIRY		0x12
51141cc406Sopenharmony_ci#define IBM_SCSI_MODE_SELECT		0x15
52141cc406Sopenharmony_ci#define IBM_SCSI_START_SCAN		0x1b
53141cc406Sopenharmony_ci#define IBM_SCSI_MODE_SENSE		0x1a
54141cc406Sopenharmony_ci#define IBM_SCSI_GET_BUFFER_STATUS	0x34
55141cc406Sopenharmony_ci#define IBM_SCSI_OBJECT_POSITION      0x31
56141cc406Sopenharmony_ci
57141cc406Sopenharmony_ci/* How long do we wait for scanner to have data for us */
58141cc406Sopenharmony_ci#define MAX_WAITING_TIME       15
59141cc406Sopenharmony_ci
60141cc406Sopenharmony_ci/* for object_position command */
61141cc406Sopenharmony_ci#define OBJECT_POSITION_UNLOAD 0
62141cc406Sopenharmony_ci#define OBJECT_POSITION_LOAD   1
63141cc406Sopenharmony_ci
64141cc406Sopenharmony_cistruct scsi_window_cmd {
65141cc406Sopenharmony_ci        SANE_Byte opcode;
66141cc406Sopenharmony_ci        SANE_Byte byte2;
67141cc406Sopenharmony_ci        SANE_Byte reserved[4];
68141cc406Sopenharmony_ci        SANE_Byte len[3];
69141cc406Sopenharmony_ci        SANE_Byte control;
70141cc406Sopenharmony_ci};
71141cc406Sopenharmony_ci
72141cc406Sopenharmony_cistruct scsi_mode_select_cmd {
73141cc406Sopenharmony_ci        SANE_Byte opcode;
74141cc406Sopenharmony_ci        SANE_Byte byte2;
75141cc406Sopenharmony_ci#define SMS_SP  0x01
76141cc406Sopenharmony_ci#define SMS_PF  0x10
77141cc406Sopenharmony_ci        SANE_Byte page_code; /* for mode_sense, reserved for mode_select */
78141cc406Sopenharmony_ci        SANE_Byte unused[1];
79141cc406Sopenharmony_ci        SANE_Byte len;
80141cc406Sopenharmony_ci        SANE_Byte control;
81141cc406Sopenharmony_ci};
82141cc406Sopenharmony_ci
83141cc406Sopenharmony_cistruct scsi_mode_header {
84141cc406Sopenharmony_ci         SANE_Byte data_length;   /* Sense data length */
85141cc406Sopenharmony_ci         SANE_Byte medium_type;
86141cc406Sopenharmony_ci         SANE_Byte dev_spec;
87141cc406Sopenharmony_ci         SANE_Byte blk_desc_len;
88141cc406Sopenharmony_ci};
89141cc406Sopenharmony_ci
90141cc406Sopenharmony_ci/* next struct introduced by mf */
91141cc406Sopenharmony_cistruct scsi_object_position_cmd {
92141cc406Sopenharmony_ci	SANE_Byte opcode;
93141cc406Sopenharmony_ci	SANE_Byte position_func;
94141cc406Sopenharmony_ci	SANE_Byte count[3];
95141cc406Sopenharmony_ci	SANE_Byte res[3];
96141cc406Sopenharmony_ci	SANE_Byte control;
97141cc406Sopenharmony_ci	SANE_Byte res2;
98141cc406Sopenharmony_ci};
99141cc406Sopenharmony_ci
100141cc406Sopenharmony_cistruct scsi_get_buffer_status_cmd {
101141cc406Sopenharmony_ci        SANE_Byte opcode;
102141cc406Sopenharmony_ci        SANE_Byte byte2;
103141cc406Sopenharmony_ci        SANE_Byte res[5];
104141cc406Sopenharmony_ci        SANE_Byte len[2];
105141cc406Sopenharmony_ci        SANE_Byte control;
106141cc406Sopenharmony_ci};
107141cc406Sopenharmony_ci
108141cc406Sopenharmony_cistruct scsi_status_desc {
109141cc406Sopenharmony_ci        SANE_Byte window_id;
110141cc406Sopenharmony_ci        SANE_Byte byte2;
111141cc406Sopenharmony_ci        SANE_Byte available[3];
112141cc406Sopenharmony_ci        SANE_Byte filled[3];
113141cc406Sopenharmony_ci};
114141cc406Sopenharmony_ci
115141cc406Sopenharmony_cistruct scsi_status_data {
116141cc406Sopenharmony_ci        SANE_Byte len[3];
117141cc406Sopenharmony_ci        SANE_Byte byte4;
118141cc406Sopenharmony_ci        struct scsi_status_desc desc;
119141cc406Sopenharmony_ci};
120141cc406Sopenharmony_ci
121141cc406Sopenharmony_cistruct scsi_start_scan_cmd {
122141cc406Sopenharmony_ci        SANE_Byte opcode;
123141cc406Sopenharmony_ci        SANE_Byte byte2;
124141cc406Sopenharmony_ci        SANE_Byte unused[2];
125141cc406Sopenharmony_ci        SANE_Byte len;
126141cc406Sopenharmony_ci        SANE_Byte control;
127141cc406Sopenharmony_ci};
128141cc406Sopenharmony_ci
129141cc406Sopenharmony_cistruct scsi_read_scanner_cmd {
130141cc406Sopenharmony_ci        SANE_Byte opcode;
131141cc406Sopenharmony_ci        SANE_Byte byte2;
132141cc406Sopenharmony_ci        SANE_Byte data_type;
133141cc406Sopenharmony_ci        SANE_Byte byte3;
134141cc406Sopenharmony_ci        SANE_Byte data_type_qualifier[2];
135141cc406Sopenharmony_ci        SANE_Byte len[3];
136141cc406Sopenharmony_ci        SANE_Byte control;
137141cc406Sopenharmony_ci};
138141cc406Sopenharmony_ci
139141cc406Sopenharmony_cistatic SANE_Status
140141cc406Sopenharmony_citest_unit_ready (int fd)
141141cc406Sopenharmony_ci{
142141cc406Sopenharmony_ci  static SANE_Byte cmd[6];
143141cc406Sopenharmony_ci  SANE_Status status;
144141cc406Sopenharmony_ci  DBG (11, ">> test_unit_ready\n");
145141cc406Sopenharmony_ci
146141cc406Sopenharmony_ci  cmd[0] = IBM_SCSI_TEST_UNIT_READY;
147141cc406Sopenharmony_ci  memset (cmd, 0, sizeof (cmd));
148141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
149141cc406Sopenharmony_ci
150141cc406Sopenharmony_ci  DBG (11, "<< test_unit_ready\n");
151141cc406Sopenharmony_ci  return (status);
152141cc406Sopenharmony_ci}
153141cc406Sopenharmony_ci
154141cc406Sopenharmony_cistatic SANE_Status
155141cc406Sopenharmony_ciinquiry (int fd, void *buf, size_t  * buf_size)
156141cc406Sopenharmony_ci{
157141cc406Sopenharmony_ci  static SANE_Byte cmd[6];
158141cc406Sopenharmony_ci  SANE_Status status;
159141cc406Sopenharmony_ci  DBG (11, ">> inquiry\n");
160141cc406Sopenharmony_ci
161141cc406Sopenharmony_ci  memset (cmd, 0, sizeof (cmd));
162141cc406Sopenharmony_ci  cmd[0] = IBM_SCSI_INQUIRY;
163141cc406Sopenharmony_ci  cmd[4] = *buf_size;
164141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size);
165141cc406Sopenharmony_ci
166141cc406Sopenharmony_ci  DBG (11, "<< inquiry\n");
167141cc406Sopenharmony_ci  return (status);
168141cc406Sopenharmony_ci}
169141cc406Sopenharmony_ci
170141cc406Sopenharmony_cistatic SANE_Status
171141cc406Sopenharmony_cimode_select (int fd, struct mode_pages *mp)
172141cc406Sopenharmony_ci{
173141cc406Sopenharmony_ci  static struct {
174141cc406Sopenharmony_ci    struct scsi_mode_select_cmd cmd;
175141cc406Sopenharmony_ci    struct scsi_mode_header smh;
176141cc406Sopenharmony_ci    struct mode_pages mp;
177141cc406Sopenharmony_ci  } select_cmd;
178141cc406Sopenharmony_ci  SANE_Status status;
179141cc406Sopenharmony_ci  DBG (11, ">> mode_select\n");
180141cc406Sopenharmony_ci
181141cc406Sopenharmony_ci  memset (&select_cmd, 0, sizeof (select_cmd));
182141cc406Sopenharmony_ci  select_cmd.cmd.opcode = IBM_SCSI_MODE_SELECT;
183141cc406Sopenharmony_ci  select_cmd.cmd.byte2 |= SMS_PF;
184141cc406Sopenharmony_ci  select_cmd.cmd.len = sizeof(select_cmd.smh) + sizeof(select_cmd.mp);
185141cc406Sopenharmony_ci/* next line by mf */
186141cc406Sopenharmony_ci/*  select_cmd.cmd.page_code= 20; */
187141cc406Sopenharmony_ci  memcpy (&select_cmd.mp, mp, sizeof(*mp));
188141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, &select_cmd, sizeof (select_cmd), 0, 0);
189141cc406Sopenharmony_ci
190141cc406Sopenharmony_ci  DBG (11, "<< mode_select\n");
191141cc406Sopenharmony_ci  return (status);
192141cc406Sopenharmony_ci}
193141cc406Sopenharmony_ci
194141cc406Sopenharmony_ci#if 0
195141cc406Sopenharmony_cistatic SANE_Status
196141cc406Sopenharmony_cimode_sense (int fd, struct mode_pages *mp, SANE_Byte page_code)
197141cc406Sopenharmony_ci{
198141cc406Sopenharmony_ci  static struct scsi_mode_select_cmd cmd; /* no type, we can reuse it for sensing */
199141cc406Sopenharmony_ci  static struct {
200141cc406Sopenharmony_ci    struct scsi_mode_header smh;
201141cc406Sopenharmony_ci    struct mode_pages mp;
202141cc406Sopenharmony_ci  } select_data;
203141cc406Sopenharmony_ci  static size_t select_size = sizeof(select_data);
204141cc406Sopenharmony_ci  SANE_Status status;
205141cc406Sopenharmony_ci  DBG (11, ">> mode_sense\n");
206141cc406Sopenharmony_ci
207141cc406Sopenharmony_ci  memset (&cmd, 0, sizeof (cmd));
208141cc406Sopenharmony_ci  cmd.opcode = IBM_SCSI_MODE_SENSE;
209141cc406Sopenharmony_ci  cmd.page_code = page_code;
210141cc406Sopenharmony_ci  cmd.len = sizeof(select_data);
211141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), &select_data, &select_size);
212141cc406Sopenharmony_ci  memcpy (mp, &select_data.mp, sizeof(*mp));
213141cc406Sopenharmony_ci
214141cc406Sopenharmony_ci  DBG (11, "<< mode_sense\n");
215141cc406Sopenharmony_ci  return (status);
216141cc406Sopenharmony_ci}
217141cc406Sopenharmony_ci#endif
218141cc406Sopenharmony_ci
219141cc406Sopenharmony_cistatic SANE_Status
220141cc406Sopenharmony_citrigger_scan (int fd)
221141cc406Sopenharmony_ci{
222141cc406Sopenharmony_ci  static struct scsi_start_scan_cmd cmd;
223141cc406Sopenharmony_ci  static char   window_id_list[1] = { '\0' }; /* scan start data out */
224141cc406Sopenharmony_ci  static size_t wl_size = 1;
225141cc406Sopenharmony_ci  SANE_Status status;
226141cc406Sopenharmony_ci  DBG (11, ">> trigger scan\n");
227141cc406Sopenharmony_ci
228141cc406Sopenharmony_ci  memset (&cmd, 0, sizeof (cmd));
229141cc406Sopenharmony_ci  cmd.opcode = IBM_SCSI_START_SCAN;
230141cc406Sopenharmony_ci  cmd.len = wl_size;
231141cc406Sopenharmony_ci/* next line by mf */
232141cc406Sopenharmony_ci/* cmd.unused[0] = 1; */
233141cc406Sopenharmony_ci  if (wl_size)
234141cc406Sopenharmony_ci    status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), &window_id_list, &wl_size);
235141cc406Sopenharmony_ci  else
236141cc406Sopenharmony_ci    status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), 0, 0);
237141cc406Sopenharmony_ci
238141cc406Sopenharmony_ci  DBG (11, "<< trigger scan\n");
239141cc406Sopenharmony_ci  return (status);
240141cc406Sopenharmony_ci}
241141cc406Sopenharmony_ci
242141cc406Sopenharmony_cistatic SANE_Status
243141cc406Sopenharmony_ciset_window (int fd, struct ibm_window_data *iwd)
244141cc406Sopenharmony_ci{
245141cc406Sopenharmony_ci
246141cc406Sopenharmony_ci  static struct {
247141cc406Sopenharmony_ci    struct scsi_window_cmd cmd;
248141cc406Sopenharmony_ci    struct ibm_window_data iwd;
249141cc406Sopenharmony_ci  } win;
250141cc406Sopenharmony_ci
251141cc406Sopenharmony_ci  SANE_Status status;
252141cc406Sopenharmony_ci  DBG (11, ">> set_window\n");
253141cc406Sopenharmony_ci
254141cc406Sopenharmony_ci  memset (&win, 0, sizeof (win));
255141cc406Sopenharmony_ci  win.cmd.opcode = IBM_SCSI_SET_WINDOW;
256141cc406Sopenharmony_ci  _lto3b(sizeof(*iwd), win.cmd.len);
257141cc406Sopenharmony_ci  memcpy (&win.iwd, iwd, sizeof(*iwd));
258141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, &win, sizeof (win), 0, 0);
259141cc406Sopenharmony_ci
260141cc406Sopenharmony_ci  DBG (11, "<< set_window\n");
261141cc406Sopenharmony_ci  return (status);
262141cc406Sopenharmony_ci}
263141cc406Sopenharmony_ci
264141cc406Sopenharmony_cistatic SANE_Status
265141cc406Sopenharmony_ciget_window (int fd, struct ibm_window_data *iwd)
266141cc406Sopenharmony_ci{
267141cc406Sopenharmony_ci
268141cc406Sopenharmony_ci  static struct scsi_window_cmd cmd;
269141cc406Sopenharmony_ci  static size_t iwd_size;
270141cc406Sopenharmony_ci  SANE_Status status;
271141cc406Sopenharmony_ci
272141cc406Sopenharmony_ci  iwd_size = sizeof(*iwd);
273141cc406Sopenharmony_ci  DBG (11, ">> get_window datalen = %lu\n", (unsigned long) iwd_size);
274141cc406Sopenharmony_ci
275141cc406Sopenharmony_ci  memset (&cmd, 0, sizeof (cmd));
276141cc406Sopenharmony_ci  cmd.opcode = IBM_SCSI_GET_WINDOW;
277141cc406Sopenharmony_ci#if 1  /* it was if 0 */
278141cc406Sopenharmony_ci  cmd.byte2 |= (SANE_Byte)0x01; /* set Single bit to get one window desc. */
279141cc406Sopenharmony_ci#endif
280141cc406Sopenharmony_ci  _lto3b(iwd_size, cmd.len);
281141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), iwd, &iwd_size);
282141cc406Sopenharmony_ci
283141cc406Sopenharmony_ci  DBG (11, "<< get_window, datalen = %lu\n", (unsigned long) iwd_size);
284141cc406Sopenharmony_ci  return (status);
285141cc406Sopenharmony_ci}
286141cc406Sopenharmony_ci
287141cc406Sopenharmony_cistatic SANE_Status
288141cc406Sopenharmony_ciread_data (int fd, void *buf, size_t * buf_size)
289141cc406Sopenharmony_ci{
290141cc406Sopenharmony_ci  static struct scsi_read_scanner_cmd cmd;
291141cc406Sopenharmony_ci  SANE_Status status;
292141cc406Sopenharmony_ci  DBG (11, ">> read_data %lu\n", (unsigned long) *buf_size);
293141cc406Sopenharmony_ci
294141cc406Sopenharmony_ci  memset (&cmd, 0, sizeof (cmd));
295141cc406Sopenharmony_ci  cmd.opcode = IBM_SCSI_READ_SCANNED_DATA;
296141cc406Sopenharmony_ci  _lto3b(*buf_size, cmd.len);
297141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), buf, buf_size);
298141cc406Sopenharmony_ci
299141cc406Sopenharmony_ci  DBG (11, "<< read_data %lu\n", (unsigned long) *buf_size);
300141cc406Sopenharmony_ci  return (status);
301141cc406Sopenharmony_ci}
302141cc406Sopenharmony_ci
303141cc406Sopenharmony_cistatic SANE_Status
304141cc406Sopenharmony_ciobject_position (int fd, int load)
305141cc406Sopenharmony_ci{
306141cc406Sopenharmony_ci  static struct scsi_object_position_cmd cmd;
307141cc406Sopenharmony_ci  SANE_Status status;
308141cc406Sopenharmony_ci  DBG (11, ">> object_position\n");
309141cc406Sopenharmony_ci
310141cc406Sopenharmony_ci#if 0
311141cc406Sopenharmony_ci  /* At least the Ricoh 420 doesn't like that command */
312141cc406Sopenharmony_ci  DBG (11, "object_position: ignored\n");
313141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
314141cc406Sopenharmony_ci#endif
315141cc406Sopenharmony_ci
316141cc406Sopenharmony_ci  memset (&cmd, 0, sizeof (cmd));
317141cc406Sopenharmony_ci  cmd.opcode = IBM_SCSI_OBJECT_POSITION;
318141cc406Sopenharmony_ci  if (load)
319141cc406Sopenharmony_ci    cmd.position_func = OBJECT_POSITION_LOAD;
320141cc406Sopenharmony_ci  else
321141cc406Sopenharmony_ci    cmd.position_func = OBJECT_POSITION_UNLOAD;
322141cc406Sopenharmony_ci  _lto3b(1, cmd.count);
323141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), 0, 0);
324141cc406Sopenharmony_ci
325141cc406Sopenharmony_ci  DBG (11, "<< object_position\n");
326141cc406Sopenharmony_ci  return (status);
327141cc406Sopenharmony_ci}
328141cc406Sopenharmony_ci
329141cc406Sopenharmony_cistatic SANE_Status
330141cc406Sopenharmony_ciget_data_status (int fd, struct scsi_status_desc *dbs)
331141cc406Sopenharmony_ci{
332141cc406Sopenharmony_ci  static struct scsi_get_buffer_status_cmd cmd;
333141cc406Sopenharmony_ci  static struct scsi_status_data ssd;
334141cc406Sopenharmony_ci  size_t ssd_size = sizeof(ssd);
335141cc406Sopenharmony_ci  SANE_Status status;
336141cc406Sopenharmony_ci  DBG (11, ">> get_data_status %lu\n", (unsigned long) ssd_size);
337141cc406Sopenharmony_ci
338141cc406Sopenharmony_ci  memset (&cmd, 0, sizeof (cmd));
339141cc406Sopenharmony_ci  cmd.opcode = IBM_SCSI_GET_BUFFER_STATUS;
340141cc406Sopenharmony_ci  _lto2b(ssd_size, cmd.len);
341141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), &ssd, &ssd_size);
342141cc406Sopenharmony_ci
343141cc406Sopenharmony_ci  memcpy (dbs, &ssd.desc, sizeof(*dbs));
344141cc406Sopenharmony_ci  if (status == SANE_STATUS_GOOD &&
345141cc406Sopenharmony_ci      ((unsigned int) _3btol(ssd.len) <= sizeof(*dbs) || _3btol(ssd.desc.filled) == 0)) {
346141cc406Sopenharmony_ci    DBG (11, "get_data_status: busy\n");
347141cc406Sopenharmony_ci    status = SANE_STATUS_DEVICE_BUSY;
348141cc406Sopenharmony_ci  }
349141cc406Sopenharmony_ci
350141cc406Sopenharmony_ci  DBG (11, "<< get_data_status %lu\n", (unsigned long) ssd_size);
351141cc406Sopenharmony_ci  return (status);
352141cc406Sopenharmony_ci}
353141cc406Sopenharmony_ci
354141cc406Sopenharmony_ci#if 0
355141cc406Sopenharmony_cistatic SANE_Status
356141cc406Sopenharmony_ciibm_wait_ready_tur (int fd)
357141cc406Sopenharmony_ci{
358141cc406Sopenharmony_ci  struct timeval now, start;
359141cc406Sopenharmony_ci  SANE_Status status;
360141cc406Sopenharmony_ci
361141cc406Sopenharmony_ci  gettimeofday (&start, 0);
362141cc406Sopenharmony_ci
363141cc406Sopenharmony_ci  while (1)
364141cc406Sopenharmony_ci    {
365141cc406Sopenharmony_ci      DBG(3, "scsi_wait_ready: sending TEST_UNIT_READY\n");
366141cc406Sopenharmony_ci
367141cc406Sopenharmony_ci      status = sanei_scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready),
368141cc406Sopenharmony_ci                               0, 0);
369141cc406Sopenharmony_ci      switch (status)
370141cc406Sopenharmony_ci        {
371141cc406Sopenharmony_ci        default:
372141cc406Sopenharmony_ci          /* Ignore errors while waiting for scanner to become ready.
373141cc406Sopenharmony_ci             Some SCSI drivers return EIO while the scanner is
374141cc406Sopenharmony_ci             returning to the home position.  */
375141cc406Sopenharmony_ci          DBG(1, "scsi_wait_ready: test unit ready failed (%s)\n",
376141cc406Sopenharmony_ci              sane_strstatus (status));
377141cc406Sopenharmony_ci          /* fall through */
378141cc406Sopenharmony_ci        case SANE_STATUS_DEVICE_BUSY:
379141cc406Sopenharmony_ci          gettimeofday (&now, 0);
380141cc406Sopenharmony_ci          if (now.tv_sec - start.tv_sec >= MAX_WAITING_TIME)
381141cc406Sopenharmony_ci            {
382141cc406Sopenharmony_ci              DBG(1, "ibm_wait_ready: timed out after %lu seconds\n",
383141cc406Sopenharmony_ci                  (u_long) (now.tv_sec - start.tv_sec));
384141cc406Sopenharmony_ci              return SANE_STATUS_INVAL;
385141cc406Sopenharmony_ci            }
386141cc406Sopenharmony_ci          usleep (100000);      /* retry after 100ms */
387141cc406Sopenharmony_ci          break;
388141cc406Sopenharmony_ci
389141cc406Sopenharmony_ci        case SANE_STATUS_GOOD:
390141cc406Sopenharmony_ci          return status;
391141cc406Sopenharmony_ci        }
392141cc406Sopenharmony_ci    }
393141cc406Sopenharmony_ci  return SANE_STATUS_INVAL;
394141cc406Sopenharmony_ci}
395141cc406Sopenharmony_ci#endif
396141cc406Sopenharmony_ci
397141cc406Sopenharmony_cistatic SANE_Status
398141cc406Sopenharmony_ciibm_wait_ready (Ibm_Scanner * s)
399141cc406Sopenharmony_ci{
400141cc406Sopenharmony_ci  struct scsi_status_desc dbs;
401141cc406Sopenharmony_ci  time_t now, start;
402141cc406Sopenharmony_ci  SANE_Status status;
403141cc406Sopenharmony_ci
404141cc406Sopenharmony_ci  start = time(NULL);
405141cc406Sopenharmony_ci
406141cc406Sopenharmony_ci  while (1)
407141cc406Sopenharmony_ci    {
408141cc406Sopenharmony_ci      status = get_data_status (s->fd, &dbs);
409141cc406Sopenharmony_ci
410141cc406Sopenharmony_ci      switch (status)
411141cc406Sopenharmony_ci        {
412141cc406Sopenharmony_ci        default:
413141cc406Sopenharmony_ci          /* Ignore errors while waiting for scanner to become ready.
414141cc406Sopenharmony_ci             Some SCSI drivers return EIO while the scanner is
415141cc406Sopenharmony_ci             returning to the home position.  */
416141cc406Sopenharmony_ci          DBG(1, "scsi_wait_ready: get datat status failed (%s)\n",
417141cc406Sopenharmony_ci              sane_strstatus (status));
418141cc406Sopenharmony_ci          /* fall through */
419141cc406Sopenharmony_ci        case SANE_STATUS_DEVICE_BUSY:
420141cc406Sopenharmony_ci          now = time(NULL);
421141cc406Sopenharmony_ci          if (now - start >= MAX_WAITING_TIME)
422141cc406Sopenharmony_ci            {
423141cc406Sopenharmony_ci              DBG(1, "ibm_wait_ready: timed out after %lu seconds\n",
424141cc406Sopenharmony_ci                  (u_long) (now - start));
425141cc406Sopenharmony_ci              return SANE_STATUS_INVAL;
426141cc406Sopenharmony_ci            }
427141cc406Sopenharmony_ci          break;
428141cc406Sopenharmony_ci
429141cc406Sopenharmony_ci        case SANE_STATUS_GOOD:
430141cc406Sopenharmony_ci	  DBG(11, "ibm_wait_ready: %d bytes ready\n", _3btol(dbs.filled));
431141cc406Sopenharmony_ci	  return status;
432141cc406Sopenharmony_ci	  break;
433141cc406Sopenharmony_ci	}
434141cc406Sopenharmony_ci      usleep (1000000);      /* retry after 100ms */
435141cc406Sopenharmony_ci    }
436141cc406Sopenharmony_ci  return SANE_STATUS_INVAL;
437141cc406Sopenharmony_ci}
438