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