PageRenderTime 77ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 2ms

/backend/avision.c

https://bitbucket.org/fhunleth/sane-backends-pl68xx
C | 8384 lines | 6077 code | 1415 blank | 892 comment | 1112 complexity | 5ce31aefcf994cdcea16ab127327f55a MD5 | raw file
Possible License(s): GPL-2.0, Unlicense

Large files files are truncated, but you can click here to view the full file

  1. /*******************************************************************************
  2. * SANE - Scanner Access Now Easy.
  3. avision.c
  4. This file is part of the SANE package.
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the
  8. License, or (at your option) any later version.
  9. This program is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16. MA 02111-1307, USA.
  17. As a special exception, the authors of SANE give permission for
  18. additional uses of the libraries contained in this release of SANE.
  19. The exception is that, if you link a SANE library with other files
  20. to produce an executable, this does not by itself cause the
  21. resulting executable to be covered by the GNU General Public
  22. License. Your use of that executable is in no way restricted on
  23. account of linking the SANE library code into it.
  24. This exception does not, however, invalidate any other reasons why
  25. the executable file might be covered by the GNU General Public
  26. License.
  27. If you submit changes to SANE to the maintainers to be included in
  28. a subsequent release, you agree by submitting the changes that
  29. those changes may be distributed with this exception intact.
  30. *****************************************************************************
  31. This backend is based upon the Tamarack backend and adapted to the Avision
  32. scanners by René Rebe and Meino Cramer.
  33. This file implements a SANE backend for the Avision SCSI Scanners (like the
  34. AV 630 / 620 (CS) ...) and some Avision (OEM) USB scanners (like the HP 53xx,
  35. 74xx, Minolta FS-V1 ...) or Fujitsu ScanPartner with the AVISION SCSI-2/3
  36. or USB command set.
  37. Copyright 1999, 2000, 2001 by
  38. "René Rebe" <rene@exactcode.de>
  39. "Meino Christian Cramer" <mccramer@s.netic.de>
  40. Copyright 2002 by
  41. "René Rebe" <rene@exactcode.de>
  42. "Jose Paulo Moitinho de Almeida" <moitinho@civil.ist.utl.pt>
  43. Copyright 2003, 2004, 2005, 2006, 2007 by
  44. "René Rebe" <rene@exactcode.de>
  45. Additional Contributers:
  46. "Gunter Wagner"
  47. (some fixes and the transparency option)
  48. "Martin Jelínek" <mates@sirrah.troja.mff.cuni.cz>
  49. nice attach debug output
  50. "Marcin Siennicki" <m.siennicki@cloos.pl>
  51. found some typos and contributed fixes for the HP 7400
  52. "Frank Zago" <fzago@greshamstorage.com>
  53. Mitsubishi IDs and report
  54. Avision INC
  55. example code to handle calibration and C5 ASIC specifics
  56. "Franz Bakan" <fbakan@gmx.net>
  57. OS/2 threading support
  58. "Falk Rohsiepe"
  59. Spelling and whitespace as well as HP5370 quirks
  60. Many additinoal special thanks to:
  61. Avision INC for providing protocol documentation.
  62. Avision INC for sponsoring an AV 8000S with ADF.
  63. Avision Europe and BHS Binkert for sponsoring several more scanners.
  64. Archivista GmbH, Switzerland, for sponsoring several features
  65. Roberto Di Cosmo who sponsored a HP 5370 scanner.
  66. Oliver Neukum who sponsored a HP 5300 USB scanner.
  67. Matthias Wiedemann for lending his HP 7450C for some weeks.
  68. Compusoft, C.A. Caracas / Venezuela for sponsoring a
  69. HP 7450 scanner and so enhanced ADF support.
  70. Chris Komatsu for the nice ADF scanning observartion.
  71. All the many other beta-tester and debug-log sender!
  72. Thanks to all the people and companies above. Without you
  73. the Avision backend would not be in the shape it is today! ;-)
  74. ********************************************************************************/
  75. /* SANE-FLOW-DIAGRAMM (from umax.c)
  76. *
  77. * - sane_init() : initialize backend, attach scanners(devicename,0)
  78. * . - sane_get_devices() : query list of scanner-devices
  79. * . - sane_open() : open a particular scanner-device and attach_scanner(devicename,&dev)
  80. * . . - sane_set_io_mode : set blocking-mode
  81. * . . - sane_get_select_fd : get scanner-fd
  82. * . . - sane_get_option_descriptor() : get option information
  83. * . . - sane_control_option() : change option values
  84. * . .
  85. * . . - sane_start() : start image aquisition
  86. * . . - sane_get_parameters() : returns actual scan-parameters
  87. * . . - sane_read() : read image-data (from pipe)
  88. *
  89. * in ADF mode this is done often:
  90. * . . - sane_start() : start image aquisition
  91. * . . - sane_get_parameters() : returns actual scan-parameters
  92. * . . - sane_read() : read image-data (from pipe)
  93. *
  94. * . . - sane_cancel() : cancel operation, kill reader_process
  95. *
  96. * . - sane_close() : close opened scanner-device, do_cancel, free buffer and handle
  97. * - sane_exit() : terminate use of backend, free devicename and device-struture
  98. */
  99. #include "../include/sane/config.h"
  100. #include <errno.h>
  101. #include <fcntl.h>
  102. #include <limits.h>
  103. #include <signal.h>
  104. #include <stdio.h>
  105. #include <stdlib.h>
  106. #include <string.h>
  107. #include <sys/types.h>
  108. #include <unistd.h>
  109. #include <sys/time.h>
  110. #include <math.h>
  111. #define BACKEND_NAME avision
  112. #define BACKEND_BUILD 290 /* avision backend BUILD version */
  113. #include <sane/sane.h>
  114. #include <sane/sanei.h>
  115. #include <sane/saneopts.h>
  116. #include <sane/sanei_thread.h>
  117. #include <sane/sanei_scsi.h>
  118. #include <sane/sanei_usb.h>
  119. #include <sane/sanei_config.h>
  120. #include <sane/sanei_backend.h>
  121. #include <avision.h>
  122. /* For timeval... */
  123. #ifdef DEBUG
  124. #include <sys/time.h>
  125. #endif
  126. /* Attention: The comments must stay as they are - they are automatially parsed
  127. to generate the SANE avision.desc file, as well as HTML online content! */
  128. /* Attention2: This device table is part of the source code and as such
  129. licensed under the terms of the license as listed above (GPL2+). By
  130. using this data you obviously create derived work! -ReneR */
  131. static Avision_HWEntry Avision_Device_List [] =
  132. {
  133. { "AVISION", "AV100CS",
  134. 0, 0,
  135. "Avision", "AV100CS",
  136. 0},
  137. /* status="untested" */
  138. { "AVISION", "AV100IIICS",
  139. 0, 0,
  140. "Avision", "AV100IIICS",
  141. 0},
  142. /* status="untested" */
  143. { "AVISION", "AV100S",
  144. 0, 0,
  145. "Avision", "AV100S",
  146. 0},
  147. /* status="untested" */
  148. { NULL, NULL,
  149. 0x0638, 0x0A27,
  150. "Avision", "AV120",
  151. AV_INT_STATUS},
  152. /* comment="sheetfed scanner" */
  153. /* status="complete" */
  154. { NULL, NULL,
  155. 0x0638, 0x0A3C,
  156. "Avision", "AV121",
  157. AV_INT_BUTTON | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA},
  158. /* comment="sheetfed scanner" */
  159. /* status="good" */
  160. { NULL, NULL,
  161. 0x0638, 0x0A33,
  162. "Avision", "AV122",
  163. AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET},
  164. /* comment="sheetfed duplex scanner" */
  165. /* status="good" */
  166. { NULL, NULL,
  167. 0x0638, 0x0A93,
  168. "Avision", "AV122 C2",
  169. AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET},
  170. /* comment="sheetfed duplex scanner" */
  171. /* status="good" */
  172. { NULL, NULL,
  173. 0x0638, 0x0A24,
  174. "Avision", "AV210",
  175. AV_INT_BUTTON | AV_ACCEL_TABLE},
  176. /* comment="sheetfed scanner" */
  177. /* status="complete" */
  178. { NULL, NULL,
  179. 0x0638, 0x0A25,
  180. "Avision", "AV210",
  181. AV_INT_BUTTON | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN},
  182. /* comment="sheetfed scanner" */
  183. /* status="complete" */
  184. { NULL, NULL,
  185. 0x0638, 0x0A3A,
  186. "Avision", "AV210C2",
  187. AV_INT_BUTTON | AV_GRAY_MODES},
  188. /* comment="sheetfed scanner" */
  189. /* status="complete" */
  190. { NULL, NULL,
  191. 0x0638, 0x0A2F,
  192. "Avision", "AV210C2-G",
  193. AV_INT_BUTTON | AV_GRAY_MODES},
  194. /* comment="sheetfed scanner" */
  195. /* status="complete" */
  196. { NULL, NULL,
  197. 0x0638, 0x0A3A,
  198. "Avision", "AV210C2",
  199. AV_INT_BUTTON | AV_GRAY_MODES},
  200. /* comment="sheetfed scanner" */
  201. /* status="complete" */
  202. { NULL, NULL,
  203. 0x0638, 0x0A23,
  204. "Avision", "AV220",
  205. AV_INT_BUTTON},
  206. /* comment="duplex! sheetfed scanner" */
  207. /* status="complete" */
  208. { NULL, NULL,
  209. 0x0638, 0x0A2A,
  210. "Avision", "AV220C2",
  211. AV_INT_BUTTON | AV_CANCEL_BUTTON},
  212. /* comment="duplex! sheetfed scanner" */
  213. /* status="complete" */
  214. { NULL, NULL,
  215. 0x0638, 0x0A2B,
  216. "Avision", "AV220D2",
  217. AV_INT_BUTTON | AV_CANCEL_BUTTON},
  218. /* comment="duplex! sheetfed scanner" */
  219. /* status="complete" */
  220. { NULL, NULL,
  221. 0x0638, 0x0A2C,
  222. "Avision", "AV220+",
  223. AV_INT_BUTTON | AV_CANCEL_BUTTON},
  224. /* comment="duplex! sheetfed scanner" */
  225. /* status="complete" */
  226. { NULL, NULL,
  227. 0x0638, 0x0A2D,
  228. "Avision", "AV220C2-G",
  229. AV_INT_BUTTON | AV_CANCEL_BUTTON},
  230. /* comment="duplex! sheetfed scanner" */
  231. /* status="complete" */
  232. { NULL, NULL,
  233. 0x0638, 0x0A2E,
  234. "Avision", "AV220C2-B",
  235. AV_INT_BUTTON | AV_CANCEL_BUTTON},
  236. /* comment="duplex! sheetfed scanner" */
  237. /* status="complete" */
  238. { NULL, NULL,
  239. 0x0638, 0x0A94,
  240. "Avision", "AV220-G",
  241. AV_INT_BUTTON},
  242. /* comment="duplex! sheetfed scanner" */
  243. /* status="complete" */
  244. { "AVISION", "AV240SC",
  245. 0, 0,
  246. "Avision", "AV240SC",
  247. 0},
  248. /* status="untested" */
  249. { "AVISION", "AV260CS",
  250. 0, 0,
  251. "Avision", "AV260CS",
  252. 0},
  253. /* status="untested" */
  254. { "AVISION", "AV360CS",
  255. 0, 0,
  256. "Avision", "AV360CS",
  257. 0},
  258. /* status="untested" */
  259. { "AVISION", "AV363CS",
  260. 0, 0,
  261. "Avision", "AV363CS",
  262. 0},
  263. /* status="untested" */
  264. { "AVISION", "AV420CS",
  265. 0, 0,
  266. "Avision", "AV420CS",
  267. 0},
  268. /* status="untested" */
  269. { "AVISION", "AV6120",
  270. 0, 0,
  271. "Avision", "AV6120",
  272. 0},
  273. /* status="untested" */
  274. { NULL, "AV610",
  275. 0x0638, 0x0a18,
  276. "Avision", "AV610",
  277. AV_GRAY_CALIB_BLUE | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN | AV_INT_STATUS | AV_INT_BUTTON},
  278. /* status="good" */
  279. { NULL, NULL,
  280. 0x0638, 0x0a18,
  281. "Avision", "AV600U Plus",
  282. AV_GRAY_CALIB_BLUE | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN | AV_INT_STATUS | AV_INT_BUTTON},
  283. /* status="good" */
  284. { NULL, NULL,
  285. 0x0638, 0x0a5e,
  286. "Avision", "AV610C2",
  287. AV_NO_BACKGROUND | AV_INT_BUTTON}, /* cancel button -> sense abort! */
  288. /* status="good" */
  289. { NULL, NULL,
  290. 0x0638, 0x0a41,
  291. "Avision", "AM3000 Series",
  292. 0},
  293. /* comment="MFD" */
  294. /* status="basic" */
  295. { NULL, NULL,
  296. 0x0638, 0x0a16,
  297. "Avision", "DS610CU Scancopier",
  298. AV_INT_STATUS},
  299. /* comment="1 pass, 600 dpi, A4" */
  300. /* status="good" */
  301. { "AVISION", "AV620CS",
  302. 0, 0,
  303. "Avision", "AV620CS",
  304. 0},
  305. /* comment="1 pass, 600 dpi" */
  306. /* status="complete" */
  307. { "AVISION", "AV620CS Plus",
  308. 0, 0,
  309. "Avision", "AV620CS Plus",
  310. 0},
  311. /* comment="1 pass, 1200 dpi" */
  312. /* status="complete" */
  313. { "AVISION", "AV630CS",
  314. 0, 0,
  315. "Avision", "AV630CS",
  316. 0},
  317. /* comment="1 pass, 1200 dpi - regularly tested" */
  318. /* status="complete" */
  319. { "AVISION", "AV630CSL",
  320. 0, 0,
  321. "Avision", "AV630CSL",
  322. 0},
  323. /* comment="1 pass, 1200 dpi" */
  324. /* status="untested" */
  325. { "AVISION", "AV6240",
  326. 0, 0,
  327. "Avision", "AV6240",
  328. 0},
  329. /* comment="1 pass, ??? dpi" */
  330. /* status="complete" */
  331. { NULL, NULL,
  332. 0x0638, 0x0A13,
  333. "Avision", "AV600U",
  334. AV_MULTI_CALIB_CMD | AV_ADF_BGR_ORDER_INVERT | AV_SOFT_SCALE | AV_INT_STATUS | AV_NO_BUTTON},
  335. /* comment="1 pass, 600 dpi" */
  336. /* status="good" */
  337. { "AVISION", "AV660S",
  338. 0, 0,
  339. "Avision", "AV660S",
  340. 0},
  341. /* comment="1 pass, ??? dpi" */
  342. /* status="untested" */
  343. { "AVISION", "AV680S",
  344. 0, 0,
  345. "Avision", "AV680S",
  346. 0},
  347. /* comment="1 pass, ??? dpi" */
  348. /* status="untested" */
  349. { "AVISION", "AV690U",
  350. 0, 0,
  351. "Avision", "AV690U",
  352. 0},
  353. /* comment="1 pass, 2400 dpi" */
  354. /* status="untested" */
  355. { "AVISION", "AV800S",
  356. 0, 0,
  357. "Avision", "AV800S",
  358. 0},
  359. /* comment="1 pass, ??? dpi" */
  360. /* status="untested" */
  361. { "AVISION", "AV810C",
  362. 0, 0,
  363. "Avision", "AV810C",
  364. 0},
  365. /* comment="1 pass, ??? dpi" */
  366. /* status="untested" */
  367. { "AVISION", "AV820",
  368. 0, 0,
  369. "Avision", "AV820",
  370. 0},
  371. /* comment="1 pass, ??? dpi" */
  372. /* status="untested" */
  373. { "AVISION", "AV820C",
  374. 0, 0,
  375. "Avision", "AV820C",
  376. 0},
  377. /* comment="1 pass, ??? dpi" */
  378. /* status="complete" */
  379. { "AVISION", "AV820C Plus",
  380. 0, 0,
  381. "Avision", "AV820C Plus",
  382. 0},
  383. /* comment="1 pass, ??? dpi" */
  384. /* status="complete" */
  385. { "AVISION", "AV830C",
  386. 0, 0,
  387. "Avision", "AV830C",
  388. 0},
  389. /* comment="1 pass, ??? dpi" */
  390. /* status="complete" */
  391. { "AVISION", "AV830C Plus",
  392. 0, 0,
  393. "Avision", "AV830C Plus",
  394. 0},
  395. /* comment="1 pass, ??? dpi" */
  396. /* status="untested" */
  397. { "AVISION", "AV880",
  398. 0, 0,
  399. "Avision", "AV880",
  400. 0},
  401. /* comment="1 pass, ??? dpi" */
  402. /* status="untested" */
  403. { "AVISION", "AV880C",
  404. 0, 0,
  405. "Avision", "AV880C",
  406. 0},
  407. /* comment="1 pass, ??? dpi" */
  408. /* status="untested" */
  409. { "AVISION", "AV3200C",
  410. 0, 0,
  411. "Avision", "AV3200C",
  412. AV_NON_INTERLACED_DUPLEX_300 | AV_FASTER_WITH_FILTER},
  413. /* comment="1 pass, ??? dpi" */
  414. /* status="complete" */
  415. { "AVISION", "AV3200SU",
  416. 0x0638, 0x0A4E,
  417. "Avision", "AV3200SU",
  418. 0},
  419. /* comment="1 pass, ??? dpi" */
  420. /* status="complete" */
  421. { "AVISION", "AV3730SU",
  422. 0x0638, 0x0A4F,
  423. "Avision", "AV3730SU",
  424. 0},
  425. /* comment="1 pass, ??? dpi" */
  426. /* status="complete" */
  427. { "AVISION", "AV3750SU",
  428. 0x0638, 0x0A65,
  429. "Avision", "AV3750SU",
  430. 0},
  431. /* comment="1 pass, ??? dpi" */
  432. /* status="complete" */
  433. { "AVISION", "AV3800C",
  434. 0, 0,
  435. "Avision", "AV3800C",
  436. 0},
  437. /* comment="1 pass, ??? dpi" */
  438. /* status="complete" */
  439. { "AVISION", "AV3850SU",
  440. 0x0638, 0x0a66,
  441. "Avision", "AV3850SU",
  442. 0},
  443. /* comment="1 pass, ??? dpi" */
  444. /* status="complete" */
  445. { "AVISION", "FB6000E",
  446. 0, 0,
  447. "Avision", "FB6000E",
  448. AV_NON_INTERLACED_DUPLEX_300},
  449. /* comment="1 pass, 1200 dpi, A3 - duplex! - zero edge!" */
  450. /* status="complete" */
  451. { NULL, NULL,
  452. 0x0638, 0x0a82,
  453. "Avision", "FB6080E",
  454. AV_NON_INTERLACED_DUPLEX_300},
  455. /* comment="1 pass, 1200 dpi, A3 - duplex! - zero edge!" */
  456. /* status="complete" */
  457. { NULL, NULL,
  458. 0x0638, 0xa84,
  459. "Avision", "FB2080E",
  460. 0},
  461. /* comment="1 pass, 600 dpi, zero-edge" ASIC 7 */
  462. /* status="basic" */
  463. { "AVISION", "AV8000S",
  464. 0, 0,
  465. "Avision", "AV8000S",
  466. AV_DOES_NOT_KEEP_WINDOW},
  467. /* comment="1 pass, 1200 dpi, A3 - regularly tested" */
  468. /* status="complete" */
  469. { NULL, NULL,
  470. 0x0638, 0x0a4d,
  471. "Avision", "AV8050U",
  472. AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA},
  473. /* comment="1 pass, 1200 dpi, A3 - duplex!" */
  474. /* status="complete" */
  475. { "AVISION", "AV8300",
  476. 0x0638, 0x0A40,
  477. "Avision", "AV8300",
  478. AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA},
  479. /* comment="1 pass, 1200 dpi, A3 - duplex!" */
  480. /* status="complete" */
  481. { "AVISION", "AV8350",
  482. 0x0638, 0x0A68,
  483. "Avision", "AV8350",
  484. AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA},
  485. /* comment="1 pass, 1200 dpi, A3 - duplex!" */
  486. /* status="complete" */
  487. { NULL, NULL,
  488. 0x0638, 0x0A61,
  489. "Avision", "IT8300",
  490. AV_NON_INTERLACED_DUPLEX_300 | AV_ACCEL_TABLE},
  491. /* comment="1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors" */
  492. /* status="good" */
  493. { NULL, NULL,
  494. 0x0638, 0x0AA1,
  495. "Avision", "@V2500",
  496. 0},
  497. /* comment="" */
  498. /* status="untested" */
  499. { NULL, NULL,
  500. 0x0638, 0x0A45,
  501. "Avision", "@V5100",
  502. 0},
  503. /* comment="" */
  504. /* status="good" */
  505. { "AVISION", "AVA3",
  506. 0, 0,
  507. "Avision", "AVA3",
  508. AV_FORCE_A3},
  509. /* comment="1 pass, 600 dpi, A3" */
  510. /* status="basic" */
  511. /* and possibly more avisions ;-) */
  512. { "HP", "ScanJet 5300C",
  513. 0x03f0, 0x0701,
  514. "Hewlett-Packard", "ScanJet 5300C",
  515. AV_INT_STATUS},
  516. /* comment="1 pass, 2400 dpi - regularly tested - some FW revisions have x-axis image scaling problems over 1200 dpi" */
  517. /* status="complete" */
  518. { "HP", "ScanJet 5370C",
  519. 0x03f0, 0x0701,
  520. "Hewlett-Packard", "ScanJet 5370C",
  521. AV_MULTI_CALIB_CMD | AV_INT_STATUS},
  522. /* comment="1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi" */
  523. /* status="good" */
  524. { "hp", "scanjet 7400c",
  525. 0x03f0, 0x0801,
  526. "Hewlett-Packard", "ScanJet 7400c",
  527. AV_LIGHT_CHECK_BOGUS | AV_NO_64BYTE_ALIGN | AV_INT_STATUS},
  528. /* comment="1 pass, 2400 dpi - dual USB/SCSI interface" */
  529. /* status="good" */
  530. #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
  531. { "hp", "scanjet 7450c",
  532. 0x03f0, 0x0801,
  533. "Hewlett-Packard", "ScanJet 7450c",
  534. AV_NO_64BYTE_ALIGN | AV_INT_STATUS},
  535. /* comment="1 pass, 2400 dpi - dual USB/SCSI interface - regularly tested" */
  536. /* status="good" */
  537. { "hp", "scanjet 7490c",
  538. 0x03f0, 0x0801,
  539. "Hewlett-Packard", "ScanJet 7490c",
  540. AV_NO_64BYTE_ALIGN | AV_INT_STATUS},
  541. /* comment="1 pass, 1200 dpi - dual USB/SCSI interface" */
  542. /* status="good" */
  543. #endif
  544. { "HP", "C9930A",
  545. 0x03f0, 0x0b01,
  546. "Hewlett-Packard", "ScanJet 8200",
  547. 0},
  548. /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
  549. /* status="good" */
  550. #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
  551. { "HP", "C9930A",
  552. 0x03f0, 0x0b01,
  553. "Hewlett-Packard", "ScanJet 8250",
  554. 0},
  555. /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
  556. /* status="good" */
  557. #endif
  558. { "HP", "C9930A",
  559. 0x03f0, 0x3905,
  560. "Hewlett-Packard", "ScanJet 8270",
  561. 0},
  562. /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
  563. /* status="good" */
  564. #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
  565. { "HP", "C9930A",
  566. 0x03f0, 0x0b01,
  567. "Hewlett-Packard", "ScanJet 8290",
  568. 0},
  569. /* comment="1 pass, 4800 (?) dpi - USB 2.0 and SCSI - only SCSI tested so far" */
  570. /* status="good" */
  571. #endif
  572. { "HP", "C9930A",
  573. 0x03f0, 0x3805,
  574. "Hewlett-Packard", "ScanJet 8390",
  575. 0},
  576. /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
  577. /* status="good" */
  578. { "Minolta", "#2882",
  579. 0, 0,
  580. "Minolta", "Dimage Scan Dual I",
  581. AV_FORCE_FILM | AV_NO_START_SCAN}, /* not AV_FILMSCANNER (no frame control) */
  582. /* status="basic" */
  583. { "Minolta", "#2887",
  584. 0, 0,
  585. "Minolta", "Scan Multi Pro",
  586. AV_FORCE_FILM | AV_NO_START_SCAN}, /* AV_FILMSCANNER (rame control)? */
  587. /* status="untested" */
  588. { "MINOLTA", "FS-V1",
  589. 0x0638, 0x026a,
  590. "Minolta", "Dimage Scan Dual II",
  591. AV_FILMSCANNER | AV_ONE_CALIB_CMD | AV_12_BIT_MODE},
  592. /* comment="1 pass, film-scanner" */
  593. /* status="good" */
  594. { "MINOLTA", "Elite II",
  595. 0x0686, 0x4004,
  596. "Minolta", "Elite II",
  597. AV_FILMSCANNER | AV_ONE_CALIB_CMD},
  598. /* comment="1 pass, film-scanner" */
  599. /* status="untested" */
  600. { "MINOLTA", "FS-V3",
  601. 0x0686, 0x400d,
  602. "Minolta", "Dimage Scan Dual III",
  603. AV_FILMSCANNER | AV_ONE_CALIB_CMD | AV_ACCEL_TABLE },
  604. /* comment="1 pass, film-scanner" */
  605. /* status="good" */
  606. { "MINOLTA", "FS-V4",
  607. 0x0686, 0x400e,
  608. "Minolta", "Dimage Scan Elite 5400",
  609. AV_FILMSCANNER | AV_ONE_CALIB_CMD | /*AV_ACCEL_TABLE |*/ AV_NO_START_SCAN},
  610. /* comment="1 pass, film-scanner" */
  611. /* status="good" */
  612. { "QMS", "SC-110",
  613. 0x0638, 0x0a15,
  614. "Minolta-QMS", "SC-110",
  615. 0},
  616. /* comment="" */
  617. /* status="untested" */
  618. { "QMS", "SC-215",
  619. 0x0638, 0x0a16,
  620. "Minolta-QMS", "SC-215",
  621. 0},
  622. /* comment="" */
  623. /* status="good" */
  624. { "MITSBISH", "MCA-ADFC",
  625. 0, 0,
  626. "Mitsubishi", "MCA-ADFC",
  627. 0},
  628. /* status="untested" */
  629. { "MITSBISH", "MCA-S1200C",
  630. 0, 0,
  631. "Mitsubishi", "S1200C",
  632. 0},
  633. /* status="untested" */
  634. { "MITSBISH", "MCA-S600C",
  635. 0, 0,
  636. "Mitsubishi", "S600C",
  637. 0},
  638. /* status="untested" */
  639. { "MITSBISH", "SS600",
  640. 0, 0,
  641. "Mitsubishi", "SS600",
  642. 0},
  643. /* status="good" */
  644. /* The next are all untested ... */
  645. { "FCPA", "ScanPartner",
  646. 0, 0,
  647. "Fujitsu", "ScanPartner",
  648. AV_FUJITSU},
  649. /* status="untested" */
  650. { "FCPA", "ScanPartner 10",
  651. 0, 0,
  652. "Fujitsu", "ScanPartner 10",
  653. AV_FUJITSU},
  654. /* status="untested" */
  655. { "FCPA", "ScanPartner 10C",
  656. 0, 0,
  657. "Fujitsu", "ScanPartner 10C",
  658. AV_FUJITSU},
  659. /* status="untested" */
  660. { "FCPA", "ScanPartner 15C",
  661. 0, 0,
  662. "Fujitsu", "ScanPartner 15C",
  663. AV_FUJITSU},
  664. /* status="untested" */
  665. { "FCPA", "ScanPartner 300C",
  666. 0, 0,
  667. "Fujitsu", "ScanPartner 300C",
  668. 0},
  669. /* status="untested" */
  670. { "FCPA", "ScanPartner 600C",
  671. 0, 0,
  672. "Fujitsu", "ScanPartner 600C",
  673. 0},
  674. /* status="untested" */
  675. { "FCPA", "ScanPartner 620C",
  676. 0, 0,
  677. "Fujitsu", "ScanPartner 620C",
  678. 0},
  679. /* status="good" */
  680. { "FCPA", "ScanPartner Jr",
  681. 0, 0,
  682. "Fujitsu", "ScanPartner Jr",
  683. 0},
  684. /* status="untested" */
  685. { "FCPA", "ScanStation",
  686. 0, 0,
  687. "Fujitsu", "ScanStation",
  688. 0},
  689. /* status="untested" */
  690. { NULL, NULL,
  691. 0x04c5, 0x1029,
  692. "Fujitsu", "fi-4010CU",
  693. 0},
  694. /* status="untested" */
  695. { NULL, NULL,
  696. 0x040a, 0x6001,
  697. "Kodak", "i30",
  698. AV_INT_BUTTON},
  699. /* status="untested" */
  700. { NULL, NULL,
  701. 0x040a, 0x6002,
  702. "Kodak", "i40",
  703. AV_INT_BUTTON},
  704. /* status="basic" */
  705. { NULL, NULL,
  706. 0x040a, 0x6003,
  707. "Kodak", "i50",
  708. AV_INT_BUTTON},
  709. /* status="untested" */
  710. { NULL, NULL,
  711. 0x040a, 0x6003,
  712. "Kodak", "i55",
  713. AV_INT_BUTTON},
  714. /* status="untested" */
  715. { NULL, NULL,
  716. 0x040a, 0x6004,
  717. "Kodak", "i60",
  718. AV_INT_BUTTON},
  719. /* status="untested" */
  720. { NULL, NULL,
  721. 0x040a, 0x6004,
  722. "Kodak", "i65",
  723. AV_INT_BUTTON},
  724. /* status="untested" */
  725. { NULL, NULL,
  726. 0x040a, 0x6005,
  727. "Kodak", "i80",
  728. AV_INT_BUTTON},
  729. /* status="good" */
  730. { "iVina", "1200U",
  731. 0x0638, 0x0268,
  732. "iVina", "1200U",
  733. 0},
  734. /* status="untested" */
  735. { NULL, NULL,
  736. 0x04a7, 0x0424,
  737. "Visioneer", "Strobe XP 450",
  738. AV_INT_BUTTON | AV_ACCEL_TABLE},
  739. /* comment="sheetfed scanner" */
  740. /* status="complete" */
  741. { NULL, NULL,
  742. 0x04a7, 0x0491,
  743. "Visioneer", "Strobe XP 450-G",
  744. AV_INT_BUTTON | AV_ACCEL_TABLE},
  745. /* comment="sheetfed scanner" */
  746. /* status="complete" */
  747. { NULL, NULL,
  748. 0x04a7, 0x0479,
  749. "Visioneer", "Strobe XP 470",
  750. AV_INT_BUTTON | AV_ACCEL_TABLE},
  751. /* comment="sheetfed scanner" */
  752. /* status="complete" */
  753. { NULL, NULL,
  754. 0x04a7, 0x048F,
  755. "Visioneer", "Strobe XP 470-G",
  756. AV_INT_BUTTON | AV_ACCEL_TABLE},
  757. /* comment="sheetfed scanner" */
  758. /* status="complete" */
  759. { NULL, NULL,
  760. 0x04a7, 0x0420,
  761. "Visioneer", "9320",
  762. 0},
  763. /* comment="sheetfed scanner" */
  764. /* status="complete" */
  765. { NULL, NULL,
  766. 0x04a7, 0x0421,
  767. "Visioneer", "9450",
  768. 0},
  769. /* comment="sheetfed scanner" */
  770. /* status="complete" */
  771. { NULL, NULL,
  772. 0x04a7, 0x047A,
  773. "Visioneer", "9450-G",
  774. 0},
  775. /* comment="sheetfed scanner" */
  776. /* status="complete" */
  777. { NULL, NULL,
  778. 0x04a7, 0x0422,
  779. "Visioneer", "9550",
  780. 0},
  781. /* comment="sheetfed scanner" */
  782. /* status="complete" */
  783. { NULL, NULL,
  784. 0x04a7, 0x0390,
  785. "Visioneer", "9650",
  786. 0},
  787. /* comment="sheetfed scanner" */
  788. /* status="complete" */
  789. { NULL, NULL,
  790. 0x04a7, 0x047B,
  791. "Visioneer", "9650-G",
  792. 0},
  793. /* comment="sheetfed scanner" */
  794. /* status="complete" */
  795. { NULL, NULL,
  796. 0x04a7, 0x0423,
  797. "Visioneer", "9750",
  798. AV_INT_BUTTON},
  799. /* comment="sheetfed scanner" */
  800. /* status="complete" */
  801. { NULL, NULL,
  802. 0x04a7, 0x0493,
  803. "Visioneer", "9750-G",
  804. AV_INT_BUTTON},
  805. /* comment="sheetfed scanner" */
  806. /* status="complete" */
  807. { NULL, NULL,
  808. 0x04a7, 0x0497,
  809. "Visioneer", "Patriot 430",
  810. AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET},
  811. /* comment="sheetfed scanner" */
  812. /* status="complete" */
  813. { NULL, NULL,
  814. 0x04a7, 0x048F,
  815. "Visioneer", "Patriot 470",
  816. AV_INT_BUTTON},
  817. /* comment="sheetfed scanner" */
  818. /* status="complete" */
  819. { NULL, NULL,
  820. 0x04a7, 0x0498,
  821. "Visioneer", "Patriot 680",
  822. AV_INT_BUTTON},
  823. /* comment="sheetfed scanner" */
  824. /* status="complete" */
  825. { NULL, NULL,
  826. 0x04a7, 0x0499,
  827. "Visioneer", "Patriot 780",
  828. AV_INT_BUTTON},
  829. /* comment="sheetfed scanner" */
  830. /* status="complete" */
  831. { NULL, NULL,
  832. 0x04a7, 0x049C,
  833. "Xerox", "DocuMate150",
  834. AV_INT_BUTTON | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_BACKGROUND_QUIRK},
  835. /* status="good" */
  836. { NULL, NULL,
  837. 0x04a7, 0x0477,
  838. "Xerox", "DocuMate152",
  839. AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET | AV_BACKGROUND_QUIRK},
  840. /* status="good" */
  841. { NULL, NULL,
  842. 0x04a7, 0x049D,
  843. "Xerox", "DocuMate162",
  844. AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET | AV_BACKGROUND_QUIRK},
  845. /* status="good" */
  846. { NULL, NULL,
  847. 0x04a7, 0x0448,
  848. "Xerox", "DocuMate250",
  849. AV_INT_BUTTON},
  850. /* status="good" */
  851. { NULL, NULL,
  852. 0x04a7, 0x0490,
  853. "Xerox", "DocuMate250-G",
  854. AV_INT_BUTTON},
  855. /* status="good" */
  856. { NULL, NULL,
  857. 0x04a7, 0x0449,
  858. "Xerox", "DocuMate252",
  859. AV_INT_BUTTON},
  860. /* status="good" */
  861. { NULL, NULL,
  862. 0x04a7, 0x048C,
  863. "Xerox", "DocuMate252-G",
  864. AV_INT_BUTTON},
  865. /* status="good" */
  866. { NULL, NULL,
  867. 0x04a7, 0x044c,
  868. "Xerox", "DocuMate262",
  869. AV_INT_BUTTON},
  870. /* status="good" */
  871. { NULL, NULL,
  872. 0x04a7, 0x048D,
  873. "Xerox", "DocuMate262-G",
  874. AV_INT_BUTTON},
  875. /* status="good" */
  876. { NULL, NULL,
  877. 0x04a7, 0x0475,
  878. "Xerox", "DocuMate272",
  879. AV_INT_BUTTON},
  880. /* status="untested" */
  881. { NULL, NULL,
  882. 0x04a7, 0x048E,
  883. "Xerox", "DocuMate272-G",
  884. AV_INT_BUTTON},
  885. /* status="untested" */
  886. { NULL, NULL,
  887. 0x04a7, 0x0446,
  888. "Xerox", "DocuMate510",
  889. AV_INT_BUTTON},
  890. /* status="untested" */
  891. { NULL, NULL,
  892. 0x04a7, 0x0495,
  893. "Xerox", "DocuMate512",
  894. AV_INT_BUTTON},
  895. /* status="untested" */
  896. { NULL, NULL,
  897. 0x04a7, 0x047c,
  898. "Xerox", "DocuMate510-G",
  899. AV_INT_BUTTON},
  900. /* status="untested" */
  901. { NULL, NULL,
  902. 0x04a7, 0x0447,
  903. "Xerox", "DocuMate520",
  904. AV_INT_BUTTON},
  905. /* status="untested" */
  906. { NULL, NULL,
  907. 0x04a7, 0x0492,
  908. "Xerox", "DocuMate520-G",
  909. AV_INT_BUTTON},
  910. /* status="untested" */
  911. { NULL, NULL,
  912. 0x04a7, 0x0498,
  913. "Xerox", "DocuMate632",
  914. AV_INT_BUTTON},
  915. /* status="untested" */
  916. { NULL, NULL,
  917. 0x04a7, 0x0478,
  918. "Xerox", "DocuMate752",
  919. AV_INT_BUTTON},
  920. /* status="untested" */
  921. { NULL, NULL,
  922. 0x04a7, 0x049A,
  923. "Xerox", "DocuMate752",
  924. AV_INT_BUTTON},
  925. /* status="untested" */
  926. { NULL, NULL,
  927. 0x0638, 0x0a16,
  928. "OKI", "S700 Scancopier",
  929. 0},
  930. /* comment="1 pass, 600 dpi, A4" */
  931. /* status="good" */
  932. { "B+H", "2000F",
  933. 0, 0,
  934. "Bell+Howell", "2000F",
  935. 0},
  936. /* comment="1 pass, ??? dpi, A4" */
  937. /* status="basic" */
  938. { NULL, NULL,
  939. 0x0482, 0x0335,
  940. "Kyocera", "FS-1016MFP",
  941. 0},
  942. /* comment="1 pass, ??? dpi, A4" */
  943. /* status="untested" */
  944. /* More IDs from the Avision dll:
  945. ArtiScan ProA3
  946. FB1065
  947. FB1265
  948. PHI860S
  949. PSDC SCSI
  950. SCSI Scan 19200
  951. V6240 */
  952. /* Possibly:
  953. Lexmark 4600 MFP Option MFP Options
  954. Lexmark 4600 MFP Option (C772n) MFP Options
  955. Lexmark X215
  956. Lexmark Optra Image X242
  957. Lexmark X443
  958. Lexmark 3100
  959. Lexmark 3200
  960. Lexmark X340 MFP Multifunction
  961. Lexmark X342n MFP Multifunction
  962. Lexmark X522
  963. Lexmark X630
  964. Lexmark X632E
  965. Lexmark X642e MFP Multifunction
  966. Lexmark X644e MFP Multifunction
  967. Lexmark X646dte MFP Multifunction
  968. Lexmark X646e MFP Multifunction
  969. Lexmark X646ef MFP Multifunction
  970. Lexmark X772e Multifunction
  971. Lexmark X850e MFP Multifunction
  972. Lexmark X852e MFP Multifunction
  973. Lexmark X854e MFP Multifunction
  974. Lexmark X4500 MFP
  975. */
  976. /* last entry detection */
  977. { NULL, NULL,
  978. 0, 0,
  979. NULL, NULL,
  980. 0}
  981. };
  982. #if 0
  983. struct timeval tv;
  984. #define TIMING(txt) gettimeofday (&tv, NULL); \
  985. DBG (4, "%lu: " txt "\n", tv.tv_sec * 1000000 + tv.tv_usec)
  986. #else
  987. #define TIMING(txt)
  988. #endif
  989. /* used when scanner returns invalid range fields ... */
  990. #define A4_X_RANGE 8.5 /* or 8.25 ? */
  991. #define A4_Y_RANGE 11.8
  992. #define A3_X_RANGE 11.8
  993. #define A3_Y_RANGE 16.5 /* or 17 ? */
  994. #define FILM_X_RANGE 1.0 /* really ? */
  995. #define FILM_Y_RANGE 1.0
  996. #define SHEETFEED_Y_RANGE 14.0
  997. #define AVISION_CONFIG_FILE "avision.conf"
  998. #define STD_INQUIRY_SIZE 0x24
  999. #define AVISION_INQUIRY_SIZE_V1 0x60
  1000. #define AVISION_INQUIRY_SIZE_V2 0x88
  1001. #define AVISION_INQUIRY_SIZE_MAX AVISION_INQUIRY_SIZE_V2
  1002. #define MM_PER_INCH 25.4
  1003. #define AVISION_BASE_RES 300
  1004. /* calibration (shading) defines */
  1005. #define INVALID_WHITE_SHADING 0x0000
  1006. #define DEFAULT_WHITE_SHADING 0xFFF0
  1007. #define MAX_WHITE_SHADING 0xFFFF
  1008. /* originally the WHITE_MAP_RANGE was 0x4000 - but this always
  1009. * resulted in slightly too dark images - thus I have choosen
  1010. * 0x4FFF ... */
  1011. #define WHITE_MAP_RANGE 0x4FFF
  1012. #define INVALID_DARK_SHADING 0xFFFF
  1013. #define DEFAULT_DARK_SHADING 0x0000
  1014. #define read_constrains(s,var) {\
  1015. if (s->hw->hw->feature_type & AV_NO_64BYTE_ALIGN) {\
  1016. if (var % 64 == 0) var /= 2;\
  1017. if (var % 64 == 0) var += 2;\
  1018. }\
  1019. }\
  1020. static int num_devices;
  1021. static Avision_Device* first_dev;
  1022. static Avision_Scanner* first_handle;
  1023. static const SANE_Device** devlist = 0;
  1024. /* this is a bit hacky to get extra information in the attach callback */
  1025. static Avision_HWEntry* attaching_hw = 0;
  1026. /* disable the usage of a custom gamma-table */
  1027. static SANE_Bool disable_gamma_table = SANE_FALSE;
  1028. /* disable the calibration */
  1029. static SANE_Bool disable_calibration = SANE_FALSE;
  1030. static SANE_Bool force_calibration = SANE_FALSE;
  1031. /* force scanable areas to ISO(DIN) A4/A3 */
  1032. static SANE_Bool force_a4 = SANE_FALSE;
  1033. static SANE_Bool force_a3 = SANE_FALSE;
  1034. /* hardware resolutions to interpolate from */
  1035. static const int hw_res_list_c5[] =
  1036. {
  1037. /* tested on AV600U */
  1038. 75, 150, 300, 600, 1200, 2400, 4800, /* ... */ 0
  1039. };
  1040. static const int hw_res_list_generic[] =
  1041. {
  1042. 50, /* slower than 150 on the AV122/DM152, left for USB 1 host's preview */
  1043. 75, /* slower than 150 on the AV122/DM152, left for USB 1 host's */
  1044. 150, 200, 300,
  1045. /* 400,*/ /* AV122 simplex y-scaling and duplex interlacing corrupt */
  1046. 600, 1200, 2400, 4800,
  1047. /* ... */
  1048. 0
  1049. };
  1050. static SANE_Bool static_calib_list[3] =
  1051. {
  1052. SANE_FALSE, SANE_FALSE, SANE_FALSE
  1053. };
  1054. static const SANE_Range u8_range =
  1055. {
  1056. 0, /* minimum */
  1057. 255, /* maximum */
  1058. 0 /* quantization */
  1059. };
  1060. static const SANE_Range percentage_range =
  1061. {
  1062. SANE_FIX (-100), /* minimum */
  1063. SANE_FIX (100), /* maximum */
  1064. SANE_FIX (1) /* quantization */
  1065. };
  1066. static const SANE_Range abs_percentage_range =
  1067. {
  1068. SANE_FIX (0), /* minimum */
  1069. SANE_FIX (100), /* maximum */
  1070. SANE_FIX (1) /* quantization */
  1071. };
  1072. static const SANE_Range exposure_range =
  1073. {
  1074. 0, /* minimum */
  1075. 1000, /* maximum */
  1076. 1 /* quantization */
  1077. };
  1078. static const SANE_Range overscan_range =
  1079. {
  1080. SANE_FIX (0), /* minimum */
  1081. SANE_FIX (4), /* maximum */ /* 4mm, meassured on AV122, AV220C2, i40 */
  1082. 0 /* quantization */
  1083. };
  1084. /* The 0x32 is a random guess based on USB logs. Might need a
  1085. per-device value in the future - 0x32 was tested on the AV122,
  1086. DM152, AV220. */
  1087. static const SANE_Range background_range =
  1088. {
  1089. 0, /* minimum */
  1090. 0x32, /* maximum */
  1091. 0 /* quantization */
  1092. };
  1093. static const uint8_t test_unit_ready[] =
  1094. {
  1095. AVISION_SCSI_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00
  1096. };
  1097. static const uint8_t get_status[] =
  1098. {
  1099. AVISION_SCSI_GET_DATA_STATUS, 0x00, 0x00, 0x00, 0x00, 0x00,
  1100. 0x00, 0x00, 0x0c, 0x00
  1101. };
  1102. static size_t
  1103. max_string_size (const SANE_String_Const strings[])
  1104. {
  1105. size_t size, max_size = 0;
  1106. int i;
  1107. DBG (3, "max_string_size:\n");
  1108. for (i = 0; strings[i]; ++ i) {
  1109. size = strlen (strings[i]) + 1;
  1110. if (size > max_size)
  1111. max_size = size;
  1112. }
  1113. return max_size;
  1114. }
  1115. static SANE_Status
  1116. constrain_value (Avision_Scanner* s, SANE_Int option, void* value,
  1117. SANE_Int* info)
  1118. {
  1119. DBG (3, "constrain_value:\n");
  1120. return sanei_constrain_value (s->opt + option, value, info);
  1121. }
  1122. static void debug_print_raw (int dbg_level, char* info, const uint8_t* data,
  1123. size_t count)
  1124. {
  1125. size_t i;
  1126. DBG (dbg_level, info);
  1127. for (i = 0; i < count; ++ i) {
  1128. DBG (dbg_level, " [%lu] %1d%1d%1d%1d%1d%1d%1d%1db %3oo %3dd %2xx\n",
  1129. (u_long) i,
  1130. BIT(data[i],7), BIT(data[i],6), BIT(data[i],5), BIT(data[i],4),
  1131. BIT(data[i],3), BIT(data[i],2), BIT(data[i],1), BIT(data[i],0),
  1132. data[i], data[i], data[i]);
  1133. }
  1134. }
  1135. static void debug_print_hex_raw (int dbg_level, char* info, const uint8_t* data,
  1136. size_t count)
  1137. {
  1138. int address = 0;
  1139. char text [16*3+1];
  1140. DBG (dbg_level, info);
  1141. while (count) {
  1142. char* t = text;
  1143. int i = 0;
  1144. while (i < 16 && count) {
  1145. t += sprintf (t, "%02x ", *data++);
  1146. count--; i++;
  1147. }
  1148. *--t = 0;
  1149. DBG (dbg_level, " [%08x] %s\n", address, text);
  1150. address += 16;
  1151. }
  1152. }
  1153. static void debug_print_nvram_data (int dbg_level, char* func,
  1154. nvram_data* nvram)
  1155. {
  1156. DBG (dbg_level, "%s: pad scans: %d\n",
  1157. func, get_quad(nvram->pad_scans));
  1158. DBG (dbg_level, "%s: ADF simplex scans: %d\n",
  1159. func, get_quad(nvram->adf_simplex_scans));
  1160. DBG (dbg_level, "%s: ADF duplex scans: %d\n",
  1161. func, get_quad(nvram->adf_duplex_scans));
  1162. DBG (dbg_level, "%s: flatbed scans: %d\n",
  1163. func, get_quad(nvram->flatbed_scans));
  1164. DBG (dbg_level, "%s: flatbed leading edge: %d\n",
  1165. func, (int16_t)get_double(nvram->flatbed_leading_edge));
  1166. DBG (dbg_level, "%s: flatbed side edge: %d\n",
  1167. func, (int16_t)get_double(nvram->flatbed_side_edge));
  1168. DBG (dbg_level, "%s: ADF leading edge: %d\n",
  1169. func, (int16_t)get_double(nvram->adf_leading_edge));
  1170. DBG (dbg_level, "%s: ADF side edge: %d\n",
  1171. func, (int16_t)get_double(nvram->adf_side_edge));
  1172. DBG (dbg_level, "%s: ADF rear leading edge: %d\n",
  1173. func, (int16_t)get_double(nvram->adf_rear_leading_edge));
  1174. DBG (dbg_level, "%s: ADF rear side edge: %d\n",
  1175. func, (int16_t)get_double(nvram->adf_rear_side_edge));
  1176. DBG (dbg_level, "%s: born month: %d\n",
  1177. func, get_double(nvram->born_month));
  1178. DBG (dbg_level, "%s: born day: %d\n",
  1179. func, get_double(nvram->born_day));
  1180. DBG (dbg_level, "%s: born year: %d\n",
  1181. func, get_double(nvram->born_year));
  1182. DBG (dbg_level, "%s: first scan month: %d\n",
  1183. func, get_double(nvram->first_scan_month));
  1184. DBG (dbg_level, "%s: first scan day: %d\n",
  1185. func, get_double(nvram->first_scan_day));
  1186. DBG (dbg_level, "%s: first scan year: %d\n",
  1187. func, get_double(nvram->first_scan_year));
  1188. DBG (dbg_level, "%s: vert. magnification: %d\n",
  1189. func, get_double(nvram->vertical_magnification));
  1190. DBG (dbg_level, "%s: horiz. magnification: %d\n",
  1191. func, get_double(nvram->horizontal_magnification));
  1192. DBG (dbg_level, "%s: CCD type: %d\n",
  1193. func, nvram->ccd_type);
  1194. DBG (dbg_level, "%s: scan speed: %d\n",
  1195. func, nvram->scan_speed);
  1196. DBG (dbg_level, "%s: serial: '%.24s'\n", /* 24 chars max */
  1197. func, nvram->serial);
  1198. DBG (dbg_level, "%s: power saving time: %d\n",
  1199. func, get_double(nvram->power_saving_time));
  1200. DBG (dbg_level, "%s: auto feed: %d\n",
  1201. func, nvram->auto_feed);
  1202. DBG (dbg_level, "%s: roller count: %d\n",
  1203. func, get_quad(nvram->roller_count));
  1204. DBG (dbg_level, "%s: multifeed count: %d\n",
  1205. func, get_quad(nvram->multifeed_count));
  1206. DBG (dbg_level, "%s: jam count: %d\n",
  1207. func, get_quad(nvram->jam_count));
  1208. DBG (dbg_level, "%s: identify info: '%.16s'\n", /* 16 chars max */
  1209. func, nvram->identify_info);
  1210. DBG (dbg_level, "%s: formal_name: '%.16s'\n", /* 16 chars max */
  1211. func, nvram->formal_name);
  1212. }
  1213. static void debug_print_avdimen (int dbg_level, char* func,
  1214. Avision_Dimensions* avdimen)
  1215. {
  1216. DBG (dbg_level, "%s: hw_xres: %d, hw_yres: %d, line_difference: %d\n",
  1217. func, avdimen->hw_xres, avdimen->hw_yres, avdimen->line_difference);
  1218. DBG (dbg_level, "%s: tlx: %ld, tly: %ld, brx: %ld, bry: %ld\n",
  1219. func, avdimen->tlx, avdimen->tly,
  1220. avdimen->brx, avdimen->bry);
  1221. DBG (dbg_level, "%s: hw_pixel_per_line: %d, hw_lines: %d, hw_bytes_per_line: %d\n",
  1222. func, avdimen->hw_pixels_per_line, avdimen->hw_lines, avdimen->hw_bytes_per_line);
  1223. DBG (dbg_level, "%s: xres: %d, yres: %d\n",
  1224. func, avdimen->xres, avdimen->yres);
  1225. }
  1226. static void debug_print_params (int dbg_level, char* func, SANE_Parameters* params)
  1227. {
  1228. DBG (dbg_level, "%s: pixel_per_line: %d, lines: %d\n",
  1229. func, params->pixels_per_line, params->lines);
  1230. DBG (dbg_level, "%s: depth: %d, bytes_per_line: %d\n",
  1231. func, params->depth, params->bytes_per_line);
  1232. }
  1233. static void debug_print_calib_format (int dbg_level, char* func,
  1234. uint8_t* result)
  1235. {
  1236. debug_print_raw (dbg_level + 2, "debug_print_calib_format:\n", result, 32);
  1237. DBG (dbg_level, "%s: [0-1] pixels per line: %d\n",
  1238. func, get_double ( &(result[0]) ));
  1239. DBG (dbg_level, "%s: [2] bytes per channel: %d\n", func, result[2]);
  1240. DBG (dbg_level, "%s: [3] line count: %d\n", func, result[3]);
  1241. DBG (dbg_level, "%s: [4] FLAG:%s%s%s\n",
  1242. func,
  1243. result[4] == 1?" MUST_DO_CALIBRATION":"",
  1244. result[4] == 2?" SCAN_IMAGE_DOES_CALIBRATION":"",
  1245. result[4] == 3?" NEEDS_NO_CALIBRATION":"");
  1246. DBG (dbg_level, "%s: [5] Ability1:%s%s%s%s%s%s%s%s\n",
  1247. func,
  1248. BIT(result[5],7)?" NONE_PACKED":" PACKED",
  1249. BIT(result[5],6)?" INTERPOLATED":"",
  1250. BIT(result[5],5)?" SEND_REVERSED":"",
  1251. BIT(result[5],4)?" PACKED_DATA":"",
  1252. BIT(result[5],3)?" COLOR_CALIB":"",
  1253. BIT(result[5],2)?" DARK_CALIB":"",
  1254. BIT(result[5],1)?" NEEDS_WHITE_BLACK_SHADING_DATA":"",
  1255. BIT(result[5],0)?" NEEDS_CALIB_TABLE_CHANNEL_BY_CHANNEL":"");
  1256. DBG (dbg_level, "%s: [6] R gain: %d\n", func, result[6]);
  1257. DBG (dbg_level, "%s: [7] G gain: %d\n", func, result[7]);
  1258. DBG (dbg_level, "%s: [8] B gain: %d\n", func, result[8]);
  1259. DBG (dbg_level, "%s: [9-10] R shading target: %x\n",
  1260. func, get_double ( &(result[9]) ) );
  1261. DBG (dbg_level, "%s: [11-12] G shading target: %x\n",
  1262. func, get_double ( &(result[11]) ) );
  1263. DBG (dbg_level, "%s: [13-14] B shading target: %x\n",
  1264. func, get_double ( &(result[13]) ) );
  1265. DBG (dbg_level, "%s: [15-16] R dark shading target: %x\n",
  1266. func, get_double ( &(result[15]) ) );
  1267. DBG (dbg_level, "%s: [17-18] G dark shading target: %x\n",
  1268. func, get_double ( &(result[17]) ) );
  1269. DBG (dbg_level, "%s: [19-20] B dark shading target: %x\n",
  1270. func, get_double ( &(result[19]) ) );
  1271. DBG (dbg_level, "%s: [21] true-gray gain: %d\n", func, result[21]);
  1272. DBG (dbg_level, "%s: [22-23] true-gray shading target: %x\n",
  1273. func, get_double ( &(result[22]) ) );
  1274. DBG (dbg_level, "%s: [24-25] true-gray dark shading target: %x\n",
  1275. func, get_double ( &(result[24]) ) );
  1276. }
  1277. static void debug_print_accel_info (int dbg_level, char* func,
  1278. uint8_t* result)
  1279. {
  1280. debug_print_raw (dbg_level + 2, "debug_print_accel_info:\n", result, 24);
  1281. DBG (dbg_level, "%s: [0-1] acceleration step count: %d\n",
  1282. func, get_double ( &(result[0]) ));
  1283. DBG (dbg_level, "%s: [2-3] stable step count: %d\n",
  1284. func, get_double ( &(result[2]) ));
  1285. DBG (dbg_level, "%s: [4-7] table units: %d\n",
  1286. func, get_quad ( &(result[4]) ));
  1287. DBG (dbg_level, "%s: [8-11] base units: %d\n",
  1288. func, get_quad ( &(result[8]) ));
  1289. DBG (dbg_level, "%s: [12-13] start speed: %d\n",
  1290. func, get_double ( &(result[12]) ));
  1291. DBG (dbg_level, "%s: [14-15] target speed: %d\n",
  1292. func, get_double ( &(result[14]) ));
  1293. DBG (dbg_level, "%s: [16] ability:%s%s\n",
  1294. func,
  1295. BIT(result[16],0)?" TWO_BYTES_PER_ELEM":" SINGLE_BYTE_PER_ELEM",
  1296. BIT(result[16],1)?" LOW_HIGH_ORDER":" HIGH_LOW_ORDER");
  1297. DBG (dbg_level, "%s: [17] table count: %d\n", func, result[17]);
  1298. }
  1299. static void debug_print_window_descriptor (int dbg_level, char* func,
  1300. command_set_window_window* window)
  1301. {
  1302. debug_print_raw (dbg_level + 1, "window_data_header: \n",
  1303. (uint8_t*)(&window->header),
  1304. sizeof(window->header));
  1305. debug_print_raw (dbg_level + 1, "window_descriptor: \n",
  1306. (uint8_t*)(&window->descriptor),
  1307. sizeof(*window) -
  1308. sizeof(window->header));
  1309. DBG (dbg_level, "%s: [0] window_id: %d\n", func,
  1310. window->descriptor.winid);
  1311. DBG (dbg_level, "%s: [2-3] x-axis res: %d\n", func,
  1312. get_double (window->descriptor.xres));
  1313. DBG (dbg_level, "%s: [4-5] y-axis res: %d\n", func,
  1314. get_double (window->descriptor.yres));
  1315. DBG (dbg_level, "%s: [6-9] x-axis upper left: %d\n",
  1316. func, get_quad (window->descriptor.ulx));
  1317. DBG (dbg_level, "%s: [10-13] y-axis upper left: %d\n",
  1318. func, get_quad (window->descriptor.uly));
  1319. DBG (dbg_level, "%s: [14-17] window width: %d\n", func,
  1320. get_quad (window->descriptor.width));
  1321. DBG (dbg_level, "%s: [18-21] window length: %d\n", func,
  1322. get_quad (window->descriptor.length));
  1323. DBG (dbg_level, "%s: [22] brightness: %d\n", func,
  1324. window->descriptor.brightness);
  1325. DBG (dbg_level, "%s: [23] threshold: %d\n", func,
  1326. window->descriptor.threshold);
  1327. DBG (dbg_level, "%s: [24] contrast: %d\n", func,
  1328. window->descriptor.contrast);
  1329. DBG (dbg_level, "%s: [25] image composition: %x\n", func,
  1330. window->descriptor.image_comp);
  1331. DBG (dbg_level, "%s: [26] bits per channel: %d\n", func,
  1332. window->descriptor.bpc);
  1333. DBG (dbg_level, "%s: [27-28] halftone pattern: %x\n", func,
  1334. get_double (window->descriptor.halftone));
  1335. DBG (dbg_level, "%s: [29] padding_and_bitset: %x\n", func,
  1336. window->descriptor.padding_and_bitset);
  1337. DBG (dbg_level, "%s: [30-31] bit ordering: %x\n", func,
  1338. get_double (window->descriptor.bitordering));
  1339. DBG (dbg_level, "%s: [32] compression type: %x\n", func,
  1340. window->descriptor.compr_type);
  1341. DBG (dbg_level, "%s: [33] compression argument: %x\n", func,
  1342. window->descriptor.compr_arg);
  1343. DBG (dbg_level, "%s: [34-35] paper length: %x\n", func,
  1344. get_double (window->descriptor.paper_length) );
  1345. DBG (dbg_level, "%s: [40] vendor id: %x\n", func,
  1346. window->descriptor.vendor_specific);
  1347. DBG (dbg_level, "%s: [41] param lenght: %d\n", func,
  1348. window->descriptor.paralen);
  1349. DBG (dbg_level, "%s: [42] bitset1: %x\n", func,
  1350. window->avision.bitset1);
  1351. DBG (dbg_level, "%s: [43] highlight: %d\n", func,
  1352. window->avision.highlight);
  1353. DBG (dbg_level, "%s: [44] shadow: %d\n", func,
  1354. window->avision.shadow);
  1355. DBG (dbg_level, "%s: [45-46] line-width: %d\n", func,
  1356. get_double (window->avision.line_width));
  1357. DBG (dbg_level, "%s: [47-48] line-count: %d\n", func,
  1358. get_double (window->avision.line_count));
  1359. DBG (dbg_level, "%s: [49] bitset2: %x\n", func,
  1360. window->avision.type.normal.bitset2);
  1361. DBG (dbg_level, "%s: [50] ir exposure time: %x\n",
  1362. func, window->avision.type.normal.ir_exposure_time);
  1363. DBG (dbg_level, "%s: [51-52] r exposure: %x\n", func,
  1364. get_double (window->avision.type.normal.r_exposure_time));
  1365. DBG (dbg_level, "%s: [53-54] g exposure: %x\n", func,
  1366. get_double (window->avision.type.normal.g_exposure_time));
  1367. DBG (dbg_level, "%s: [55-56] b exposure: %x\n", func,
  1368. get_double (window->avision.type.normal.b_exposure_time));
  1369. DBG (dbg_level, "%s: [57] bitset3: %x\n", func,
  1370. window->avision.type.normal.bitset3);
  1371. DBG (dbg_level, "%s: [58] auto focus: %d\n", func,
  1372. window->avision.type.normal.auto_focus);
  1373. DBG (dbg_level, "%s: [59] line-width (MSB): %d\n",
  1374. func, window->avision.type.normal.line_width_msb);
  1375. DBG (dbg_level, "%s: [60] line-count (MSB): %d\n",
  1376. func, window->avision.type.normal.line_count_msb);
  1377. DBG (dbg_level, "%s: [61] background lines: %d\n",
  1378. func, window->avision.type.normal.background_lines);
  1379. }
  1380. static int write_pnm_header (FILE* f, color_mode m, int depth, int width, int height)
  1381. {
  1382. int maxval = (1 << depth) - 1;
  1383. const char* hdr_str = NULL;
  1384. /* construct PNM header */
  1385. switch (m) {
  1386. case AV_THRESHOLDED:
  1387. case AV_DITHERED:
  1388. hdr_str = "P4\n%d %d\n";
  1389. break;
  1390. case AV_GRAYSCALE:
  1391. case AV_GRAYSCALE12:
  1392. case AV_GRAYSCALE16:
  1393. hdr_str = "P5\n%d %d\n%d\n";
  1394. break;
  1395. case AV_TRUECOLOR:
  1396. case AV_TRUECOLOR12:
  1397. case AV_TRUECOLOR16:
  1398. hdr_str = "P6\n%d %d\n%d\n";
  1399. break;
  1400. case AV_COLOR_MODE_LAST:
  1401. ; /* silence compiler warning */
  1402. }
  1403. return fprintf (f, hdr_str, width, height, maxval);
  1404. }
  1405. static SANE_Status
  1406. sense_handler (int fd, u_char* sense, void* arg)
  1407. {
  1408. SANE_Status status = SANE_STATUS_IO_ERROR; /* default case */
  1409. char* text;
  1410. char textbuf[64];
  1411. uint8_t error_code = sense[0] & 0x7f;
  1412. uint8_t sense_key = sense[2] & 0xf;
  1413. uint8_t additional_sense = sense[7];
  1414. fd = fd; /* silence gcc */
  1415. arg = arg; /* silence gcc */
  1416. DBG (3, "sense_handler:\n");
  1417. switch (error_code)
  1418. {
  1419. case 0x70:
  1420. text = "standard sense";
  1421. break;
  1422. case 0x7f:
  1423. text = "Avision-specific sense";
  1424. break;
  1425. default:
  1426. text = "unknown sense";
  1427. }
  1428. debug_print_raw (1, "sense_handler: data:\n", sense, 8 + additional_sense);
  1429. /* request valid? */
  1430. if (! sense[0] & (1<<7)) {
  1431. DBG (1, "sense_handler: sense not vaild ...\n");
  1432. return status;
  1433. }
  1434. switch (sense_key)
  1435. {
  1436. case 0x00:
  1437. status = SANE_STATUS_GOOD;
  1438. text = "ok ?!?";
  1439. break;
  1440. case 0x02:
  1441. text = "NOT READY";
  1442. break;
  1443. case 0x03:
  1444. text = "MEDIUM ERROR (mostly ADF)";
  1445. status = SANE_STATUS_JAMMED;
  1446. break;
  1447. case 0x04:
  1448. text = "HARDWARE ERROR";
  1449. break;
  1450. case 0x05:
  1451. text = "ILLEGAL REQUEST";
  1452. break;
  1453. case 0x06:
  1454. text = "UNIT ATTENTION";
  1455. break;
  1456. case 0x09:
  1457. text = "VENDOR SPECIFIC";
  1458. break;
  1459. case 0x0b:
  1460. text = "ABORTED COMMAND";
  1461. status = SANE_STATUS_CANCELLED; /* AV610C2 cancel button */
  1462. break;
  1463. default:
  1464. sprintf (textbuf, "got unknown sense code 0x%02x", (int)sense_key);
  1465. text = textbuf;
  1466. }
  1467. DBG (1, "sense_handler: sense code: %s\n", text);
  1468. if (sense[2] & (1<<6))
  1469. DBG (1, "sense_handler: end of scan\n");
  1470. else
  1471. DBG (1, "sense_handler: scan has not yet been completed\n");
  1472. if (sense[2] & (1<<5))
  1473. DBG (1, "sense_handler: incorrect logical length\n");
  1474. else
  1475. DBG (1, "sense_handler: correct logical length\n");
  1476. {
  1477. uint8_t asc = sense[12];
  1478. uint8_t ascq = sense[13];
  1479. #define ADDITIONAL_SENSE(asc,ascq,txt) \
  1480. case ( (asc << 8) + ascq): text = txt; break
  1481. switch ( (asc << 8) + ascq )
  1482. {
  1483. /* normal */
  1484. ADDITIONAL_SENSE (0x00,0x00, "No additional sense information");
  1485. ADDITIONAL_SENSE (0x00,0x06, "I/O process terminated");
  1486. ADDITIONAL_SENSE (0x15,0x01, "Mechanical positioning error");
  1487. ADDITIONAL_SENSE (0x15,0x02, "Flatbed Home Sensor Error (OKI only");
  1488. ADDITIONAL_SENSE (0x15,0x03, "ADF Home Sensor Error (OKI only)");
  1489. ADDITIONAL_SENSE (0x15,0x04, "Lock Error (OKI only)");
  1490. ADDITIONAL_SENSE (0x1a,0x00, "parameter list lenght error");
  1491. ADDITIO

Large files files are truncated, but you can click here to view the full file