1 /* sane - Scanner Access Now Easy.
2 Copyright (C) 2003 Martijn van Oosterhout <kleptog@svana.org>
3 Copyright (C) 2003 Thomas Soumarmon <thomas.soumarmon@cogitae.net>
4 Copyright (c) 2003 Henning Meier-Geinitz, <henning@meier-geinitz.de>
5
6 Originally copied from HP3300 testtools. Original notice follows:
7
8 Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
9
10 This file is part of the SANE package.
11
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 as published by the Free Software Foundation; either version 2
15 of the License, or (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <https://www.gnu.org/licenses/>.
24
25 As a special exception, the authors of SANE give permission for
26 additional uses of the libraries contained in this release of SANE.
27
28 The exception is that, if you link a SANE library with other files
29 to produce an executable, this does not by itself cause the
30 resulting executable to be covered by the GNU General Public
31 License. Your use of that executable is in no way restricted on
32 account of linking the SANE library code into it.
33
34 This exception does not, however, invalidate any other reasons why
35 the executable file might be covered by the GNU General Public
36 License.
37
38 If you submit changes to SANE to the maintainers to be included in
39 a subsequent release, you agree by submitting the changes that
40 those changes may be distributed with this exception intact.
41
42 If you write modifications of your own for SANE, it is your choice
43 whether to permit this exception to apply to your modifications.
44 If you do not wish that, delete this exception notice.
45
46 Transport layer for communication with HP5400/5470 scanner.
47
48 Implementation using sanei_usb
49
50 Additions to support bulk data transport. Added debugging info - 19/02/2003 Martijn
51 Changed to use sanei_usb instead of direct /dev/usb/scanner access - 15/04/2003 Henning
52 */
53
54
55 #include "hp5400_xfer.h"
56 #include "hp5400_debug.h"
57 #include <stdio.h>
58 #include "../include/sane/sanei_usb.h"
59
60 #define CMD_INITBULK1 0x0087 /* send 0x14 */
61 #define CMD_INITBULK2 0x0083 /* send 0x24 */
62 #define CMD_INITBULK3 0x0082 /* transfer length 0xf000 */
63
64
65
66 static void
_UsbWriteControl(int fd,int iValue,int iIndex,void * pabData,int iSize)67 _UsbWriteControl (int fd, int iValue, int iIndex, void *pabData, int iSize)
68 {
69 int requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT;
70 int request = (iSize > 1) ? 0x04 : 0x0C;
71
72 HP5400_DBG (DBG_MSG,
73 "Write: reqtype = 0x%02X, req = 0x%02X, value = %04X, len = %d\n",
74 requesttype, request, iValue, iSize);
75
76 if (iSize > 0)
77 {
78 int i;
79 HP5400_DBG (DBG_MSG, " Data: ");
80 for (i = 0; i < iSize && i < 8; i++)
81 HP5400_DBG (DBG_MSG, "%02X ", ((unsigned char *) pabData)[i]);
82 if (iSize > 8)
83 HP5400_DBG (DBG_MSG, "...");
84 HP5400_DBG (DBG_MSG, "\n");
85 }
86
87 if (fd != -1)
88 {
89 sanei_usb_control_msg (fd, requesttype, request, iValue, iIndex, iSize,
90 pabData);
91 }
92 /* No error checking? */
93
94 }
95
96 void
hp5400_command_write_noverify(int fd,int iValue,void * pabData,int iSize)97 hp5400_command_write_noverify (int fd, int iValue, void *pabData, int iSize)
98 {
99 _UsbWriteControl (fd, iValue, 0, pabData, iSize);
100 }
101
102 static void
_UsbReadControl(int fd,int iValue,int iIndex,void * pabData,int iSize)103 _UsbReadControl (int fd, int iValue, int iIndex, void *pabData, int iSize)
104 {
105 int requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN;
106 int request = (iSize > 1) ? 0x04 : 0x0C;
107
108 HP5400_DBG (DBG_MSG, "Read: reqtype = 0x%02X, req = 0x%02X, value = %04X\n",
109 requesttype, request, iValue);
110
111 if (fd != -1)
112 {
113 sanei_usb_control_msg (fd, requesttype, request, iValue, iIndex, iSize,
114 pabData);
115 }
116 }
117
118
119 HP5400_SANE_STATIC int
hp5400_open(const char * filename)120 hp5400_open (const char *filename)
121 {
122 int fd, iVendor, iProduct;
123 SANE_Status status;
124
125 if (!filename)
126 filename = "/dev/usb/scanner0";
127
128 status = sanei_usb_open (filename, &fd);
129 if (status != SANE_STATUS_GOOD)
130 {
131 HP5400_DBG (DBG_MSG, "hp5400_open: open returned %s\n",
132 sane_strstatus (status));
133 return -1;
134 }
135
136 status = sanei_usb_get_vendor_product (fd, &iVendor, &iProduct);
137 if (status != SANE_STATUS_GOOD)
138 {
139 HP5400_DBG (DBG_MSG, "hp5400_open: can't get vendor/product ids: %s\n",
140 sane_strstatus (status));
141 sanei_usb_close (fd);
142 return -1;
143 }
144
145 if ((iVendor != 0x03F0) || ((iProduct != 0x1005) && (iProduct != 0x1105)))
146 {
147 HP5400_DBG (DBG_MSG, "hp5400_open: vendor/product 0x%04X-0x%04X is not "
148 "supported\n", iVendor, iProduct);
149 sanei_usb_close (fd);
150 return -1;
151 }
152
153 HP5400_DBG (DBG_MSG, "vendor/product 0x%04X-0x%04X opened\n", iVendor, iProduct);
154
155 return fd;
156 }
157
158
159 void
hp5400_close(int iHandle)160 hp5400_close (int iHandle)
161 {
162 sanei_usb_close (iHandle);
163 }
164
165
166 /* returns value > 0 if verify ok */
167 int
hp5400_command_verify(int iHandle,int iCmd)168 hp5400_command_verify (int iHandle, int iCmd)
169 {
170 unsigned char abData[4];
171 int fd;
172
173 if (iHandle < 0)
174 {
175 HP5400_DBG (DBG_ERR, "hp5400_command_verify: invalid handle\n");
176 return -1;
177 }
178 fd = iHandle;
179
180 /* command 0xc500: read back previous command */
181 _UsbReadControl (fd, 0xc500, 0, (char *) abData, 2);
182
183 if (abData[0] != (iCmd >> 8))
184 {
185 HP5400_DBG (DBG_ERR,
186 "hp5400_command_verify failed, expected 0x%02X%02X, got 0x%02X%02X\n",
187 (int) (iCmd >> 8), (int) (iCmd & 0xff), (int) abData[0],
188 (int) abData[1]);
189
190 return -1;
191 }
192
193 if (abData[1] != 0) /* Error code non-zero */
194 {
195 _UsbReadControl (fd, 0x0300, 0, (char *) abData, 3);
196 HP5400_DBG (DBG_ERR, " error response is: %02X %02X %02X\n", abData[0],
197 abData[1], abData[2]);
198
199 return -1;
200 }
201
202 HP5400_DBG (DBG_MSG, "Command %02X verified\n", abData[0]);
203 return 1;
204 }
205
206
207 /* returns > 0 if command OK */
208 int
hp5400_command_read_noverify(int iHandle,int iCmd,int iLen,void * pbData)209 hp5400_command_read_noverify (int iHandle, int iCmd, int iLen, void *pbData)
210 {
211 int fd;
212
213 if (iHandle < 0)
214 {
215 HP5400_DBG (DBG_ERR, "hp5400_command_read: invalid handle\n");
216 return -1;
217 }
218 fd = iHandle;
219
220 _UsbReadControl (fd, iCmd, 0, pbData, iLen);
221
222 return 1;
223 }
224
225 /* returns > 0 if command OK */
226 int
hp5400_command_read(int iHandle,int iCmd,int iLen,void * pbData)227 hp5400_command_read (int iHandle, int iCmd, int iLen, void *pbData)
228 {
229 hp5400_command_read_noverify (iHandle, iCmd, iLen, pbData);
230
231 return hp5400_command_verify (iHandle, iCmd);
232 }
233
234
235 /* returns >0 if command OK */
236 int
hp5400_command_write(int iHandle,int iCmd,int iLen,void * pbData)237 hp5400_command_write (int iHandle, int iCmd, int iLen, void *pbData)
238 {
239 int fd;
240
241 if (iHandle < 0)
242 {
243 HP5400_DBG (DBG_ERR, "hp5400_command_write: invalid handle\n");
244 return -1;
245 }
246 fd = iHandle;
247
248 _UsbWriteControl (fd, iCmd, 0, (char *) pbData, iLen);
249
250 return hp5400_command_verify (iHandle, iCmd);
251 }
252
253 #ifdef STANDALONE
254 /* returns >0 if command OK */
255 int
hp5400_bulk_read(int iHandle,size_t len,int block,FILE * file)256 hp5400_bulk_read (int iHandle, size_t len, int block, FILE * file)
257 {
258 SANE_Int fd;
259 char x1 = 0x14, x2 = 0x24;
260 short buf[4] = { 0, 0, 0, 0 };
261 SANE_Byte *buffer;
262 size_t res = 0;
263
264 buf[2] = block;
265
266 if (iHandle < 0)
267 {
268 HP5400_DBG (DBG_ERR, "hp5400_command_read: invalid handle\n");
269 return -1;
270 }
271 fd = iHandle;
272
273 buffer = (unsigned char*) malloc (block);
274
275 _UsbWriteControl (fd, CMD_INITBULK1, 0, &x1, 1);
276 _UsbWriteControl (fd, CMD_INITBULK2, 0, &x2, 1);
277
278 while (len > 0)
279 {
280 _UsbWriteControl (fd, CMD_INITBULK3, 0, (unsigned char *) &buf,
281 sizeof (buf));
282 res = block;
283 sanei_usb_read_bulk (fd, buffer, &res);
284 HP5400_DBG (DBG_MSG, "Read bulk returned %lu, %lu remain\n",
285 (u_long) res, (u_long) len);
286 if (res > 0)
287 {
288 fwrite (buffer, (len < res) ? len : res, 1, file);
289 }
290 len -= block;
291 }
292 /* error handling? */
293 return 0;
294 }
295 #endif
296
297 /* returns >0 if command OK */
298 int
hp5400_bulk_read_block(int iHandle,int iCmd,void * cmd,int cmdlen,void * buffer,int len)299 hp5400_bulk_read_block (int iHandle, int iCmd, void *cmd, int cmdlen,
300 void *buffer, int len)
301 {
302 SANE_Int fd;
303 size_t res = 0;
304
305 if (iHandle < 0)
306 {
307 HP5400_DBG (DBG_ERR, "hp5400_command_read_block: invalid handle\n");
308 return -1;
309 }
310 fd = iHandle;
311
312 _UsbWriteControl (fd, iCmd, 0, cmd, cmdlen);
313 res = len;
314 sanei_usb_read_bulk (fd, (SANE_Byte *) buffer, &res);
315 HP5400_DBG (DBG_MSG, "Read block returned %lu when reading %d\n",
316 (u_long) res, len);
317 return res;
318 }
319
320 /* returns >0 if command OK */
321 int
hp5400_bulk_command_write(int iHandle,int iCmd,void * cmd,int cmdlen,int datalen,int block,char * data)322 hp5400_bulk_command_write (int iHandle, int iCmd, void *cmd, int cmdlen,
323 int datalen, int block, char *data)
324 {
325 SANE_Int fd;
326 size_t res = 0, offset = 0;
327
328 if (iHandle < 0)
329 {
330 HP5400_DBG (DBG_ERR, "hp5400_bulk_command_write: invalid handle\n");
331 return -1;
332 }
333 fd = iHandle;
334
335 HP5400_DBG (DBG_MSG, "bulk_command_write(%04X,<%d bytes>,<%d bytes>)\n", iCmd,
336 cmdlen, datalen);
337
338 _UsbWriteControl (fd, iCmd, 0, cmd, cmdlen);
339
340 while (datalen > 0)
341 {
342 {
343 int i;
344 HP5400_DBG (DBG_MSG, " Data: ");
345 for (i = 0; i < datalen && i < block && i < 8; i++)
346 HP5400_DBG (DBG_MSG, "%02X ", ((unsigned char *) data + offset)[i]);
347 if (i >= 8)
348 HP5400_DBG (DBG_MSG, "...");
349 HP5400_DBG (DBG_MSG, "\n");
350 }
351 res = (datalen < block) ? datalen : block;
352 sanei_usb_write_bulk (fd, (SANE_Byte *) (data + offset), &res);
353 HP5400_DBG (DBG_MSG, "Write returned %lu, %d remain\n", (u_long) res, datalen);
354 datalen -= block;
355 offset += block;
356 }
357
358 return hp5400_command_verify (iHandle, iCmd);
359 }
360
361 #ifdef STANDALONE
362 /**
363 ScannerIsOn
364 retrieve on/off status from scanner
365 @return 1 if is on 0 if is off -1 if is not reachable
366 */
367 int
hp5400_isOn(int iHandle)368 hp5400_isOn (int iHandle)
369 {
370 unsigned char text2400[3];
371
372 hp5400_command_read (iHandle, 0x2400, 0x03, text2400);
373
374 /* byte 0 indicates if is on or off if 0x02 */
375 /* byte 1 indicates time since is on */
376 /* byte 2 indicates time since is power plugged */
377
378 if (text2400[0] & 0x02)
379 {
380 return 1; /* is on */
381 }
382
383 return 0; /* is off */
384 }
385 #endif
386