1 /* sane - Scanner Access Now Easy.
2 Copyright (C) 2007 Ilia Sotnikov <hostcc@gmail.com>
3 This file is part of the SANE package.
4
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
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
17
18 As a special exception, the authors of SANE give permission for
19 additional uses of the libraries contained in this release of SANE.
20
21 The exception is that, if you link a SANE library with other files
22 to produce an executable, this does not by itself cause the
23 resulting executable to be covered by the GNU General Public
24 License. Your use of that executable is in no way restricted on
25 account of linking the SANE library code into it.
26
27 This exception does not, however, invalidate any other reasons why
28 the executable file might be covered by the GNU General Public
29 License.
30
31 If you submit changes to SANE to the maintainers to be included in
32 a subsequent release, you agree by submitting the changes that
33 those changes may be distributed with this exception intact.
34
35 If you write modifications of your own for SANE, it is your choice
36 whether to permit this exception to apply to your modifications.
37 If you do not wish that, delete this exception notice.
38
39 This file is part of a SANE backend for
40 HP ScanJet 4500C/4570C/5500C/5550C/5590/7650 Scanners
41 */
42
43 #include "../include/sane/config.h"
44
45 #include <stdio.h>
46 #include <string.h>
47 #include <errno.h>
48 #ifdef HAVE_NETINET_IN_H
49 # include <netinet/in.h>
50 #endif /* HAVE_NETINET_IN_H */
51
52 #include "byteorder.h"
53
54 #include "../include/sane/sanei_debug.h"
55 #include "../include/sane/sanei_usb.h"
56 #include "../include/_stdint.h"
57 #include "hp5590_low.h"
58
59 /* Debug levels */
60 #define DBG_err 0
61 #define DBG_proc 10
62 #define DBG_usb 50
63
64 /* Custom assert() macro */
65 #define hp5590_low_assert(exp) if(!(exp)) { \
66 DBG (DBG_err, "Assertion '%s' failed at %s:%u\n", #exp, __FILE__, __LINE__);\
67 return SANE_STATUS_INVAL; \
68 }
69
70 /* Structure describing bulk transfer size */
71 struct bulk_size
72 {
73 uint16_t size;
74 uint8_t unused;
75 } __attribute__ ((packed));
76
77 /* Structure describing bulk URB */
78 /* FIXME: Verify according to USB standard */
79 struct usb_in_usb_bulk_setup
80 {
81 uint8_t bRequestType;
82 uint8_t bRequest;
83 uint8_t bEndpoint;
84 uint16_t unknown;
85 uint16_t wLength; /* MSB first */
86 uint8_t pad;
87 } __attribute__ ((packed));
88
89 /* Structure describing control URB */
90 struct usb_in_usb_ctrl_setup {
91 uint8_t bRequestType;
92 uint8_t bRequest;
93 uint16_t wValue; /* MSB first */
94 uint16_t wIndex; /* MSB first */
95 uint16_t wLength; /* LSB first */
96 } __attribute__ ((packed));
97
98 /* CORE status flag - ready or not */
99 #define CORE_FLAG_NOT_READY 1 << 1
100
101 /* Bulk transfers are done in pages, below their respective sizes */
102 #define BULK_WRITE_PAGE_SIZE 0x0f000
103 #define BULK_READ_PAGE_SIZE 0x10000
104 #define ALLOCATE_BULK_READ_PAGES 16 /* 16 * 65536 = 1Mb */
105
106 /* Structure describing bulk read state, because bulk reads will be done in
107 * pages, but function caller uses its own buffer, whose size is certainly
108 * different. Also, each bulk read page is ACK'ed by special command
109 * so total pages received should be tracked as well
110 */
111 struct bulk_read_state
112 {
113 unsigned char *buffer;
114 unsigned int buffer_size;
115 unsigned int bytes_available;
116 unsigned char *buffer_out_ptr;
117 unsigned char *buffer_in_ptr;
118 unsigned int total_pages;
119 unsigned char *buffer_end_ptr;
120 unsigned int initialized;
121 };
122
123 /*******************************************************************************
124 * USB-in-USB: get acknowledge for last USB-in-USB operation
125 *
126 * Parameters
127 * dn - sanei_usb device descriptor
128 *
129 * Returns
130 * SANE_STATUS_GOOD - if correct acknowledge was received
131 * SANE_STATUS_DEVICE_BUSY - otherwise
132 */
133 static SANE_Status
hp5590_get_ack(SANE_Int dn, enum proto_flags proto_flags)134 hp5590_get_ack (SANE_Int dn,
135 enum proto_flags proto_flags)
136 {
137 uint8_t status;
138 SANE_Status ret;
139
140 /* Bypass reading acknowledge if the device doesn't need it */
141 if (proto_flags & PF_NO_USB_IN_USB_ACK)
142 return SANE_STATUS_GOOD;
143
144 DBG (DBG_proc, "%s\n", __func__);
145
146 /* Check if USB-in-USB operation was accepted */
147 ret = sanei_usb_control_msg (dn, USB_DIR_IN | USB_TYPE_VENDOR,
148 0x0c, 0x8e, 0x20,
149 sizeof (status), &status);
150 if (ret != SANE_STATUS_GOOD)
151 {
152 DBG (DBG_err, "%s: USB-in-USB: error getting acknowledge\n",
153 __func__);
154 return ret;
155 }
156
157 DBG (DBG_usb, "%s: USB-in-USB: accepted\n", __func__);
158
159 /* Check if we received correct acknowledgment */
160 if (status != 0x01)
161 {
162 DBG (DBG_err, "%s: USB-in-USB: not accepted (status %u)\n",
163 __func__, status);
164 return SANE_STATUS_DEVICE_BUSY;
165 }
166
167 return SANE_STATUS_GOOD;
168 }
169
170 /*******************************************************************************
171 * USB-in-USB: get device status
172 *
173 * Parameters
174 * dn - sanei_usb device descriptor
175 *
176 * Returns
177 * SANE_STATUS_GOOD - if correct status was received
178 * SANE_STATUS_DEVICE_BUSY - otherwise
179 */
180 static SANE_Status
hp5590_get_status(SANE_Int dn, __sane_unused__ enum proto_flags proto_flags)181 hp5590_get_status (SANE_Int dn,
182 __sane_unused__ enum proto_flags proto_flags)
183 {
184 uint8_t status;
185 SANE_Status ret;
186
187 DBG (DBG_proc, "%s\n", __func__);
188
189 ret = sanei_usb_control_msg (dn, USB_DIR_IN | USB_TYPE_VENDOR,
190 0x0c, 0x8e, 0x00,
191 sizeof (status), &status);
192 if (ret != SANE_STATUS_GOOD)
193 {
194 DBG (DBG_err, "%s: USB-in-USB: error getting device status\n",
195 __func__);
196 return ret;
197 }
198
199 /* Check if we received correct status */
200 if (status != 0x00)
201 {
202 DBG (DBG_err, "%s: USB-in-USB: got non-zero device status (status %u)\n",
203 __func__, status);
204 return SANE_STATUS_DEVICE_BUSY;
205 }
206
207 return SANE_STATUS_GOOD;
208 }
209
210 /*******************************************************************************
211 * USB-in-USB: sends control message for IN or OUT operation
212 *
213 * Parameters
214 * dn - sanei_usb device descriptor
215 * requesttype, request, value, index - their meanings are similar to
216 * sanei_control_msg()
217 * bytes - pointer to data buffer
218 * size - size of data
219 * core_flags -
220 * CORE_NONE - no CORE operation will be performed
221 * CORE_DATA - operation on CORE data will be performed
222 * CORE_BULK_IN - preparation for bulk IN transfer (not used yet)
223 * CORE_BULK_OUT - preparation for bulk OUT transfer
224 *
225 * Returns
226 * SANE_STATUS_GOOD - control message was sent w/o any errors
227 * all other SANE_Status values - otherwise
228 */
229 static SANE_Status
hp5590_control_msg(SANE_Int dn, enum proto_flags proto_flags, int requesttype, int request, int value, int index, unsigned char *bytes, int size, int core_flags)230 hp5590_control_msg (SANE_Int dn,
231 enum proto_flags proto_flags,
232 int requesttype, int request,
233 int value, int index, unsigned char *bytes,
234 int size, int core_flags)
235 {
236 struct usb_in_usb_ctrl_setup ctrl;
237 SANE_Status ret;
238 unsigned int len;
239 unsigned char *ptr;
240 uint8_t ack;
241 uint8_t response;
242 unsigned int needed_response;
243
244 DBG (DBG_proc, "%s: USB-in-USB: core data: %s\n",
245 __func__, core_flags & CORE_DATA ? "yes" : "no");
246
247 hp5590_low_assert (bytes != NULL);
248
249 /* IN (read) operation will be performed */
250 if (requesttype & USB_DIR_IN)
251 {
252 /* Prepare USB-in-USB control message */
253 memset (&ctrl, 0, sizeof (ctrl));
254 ctrl.bRequestType = 0xc0;
255 ctrl.bRequest = request;
256 ctrl.wValue = htons (value);
257 ctrl.wIndex = htons (index);
258 ctrl.wLength = htole16 (size);
259
260 DBG (DBG_usb, "%s: USB-in-USB: sending control msg\n", __func__);
261 /* Send USB-in-USB control message */
262 ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
263 0x04, 0x8f, 0x00,
264 sizeof (ctrl), (unsigned char *) &ctrl);
265 if (ret != SANE_STATUS_GOOD)
266 {
267 DBG (DBG_err, "%s: USB-in-USB: error sending control message\n",
268 __func__);
269 return ret;
270 }
271
272 /* USB-in-USB: checking acknowledge for control message */
273 ret = hp5590_get_ack (dn, proto_flags);
274 if (ret != SANE_STATUS_GOOD)
275 return ret;
276
277 len = size;
278 ptr = bytes;
279 /* Data is read in 8 byte portions */
280 while (len)
281 {
282 unsigned int next_packet_size;
283 next_packet_size = 8;
284 if (len < 8)
285 next_packet_size = len;
286
287 /* Read USB-in-USB data */
288 ret = sanei_usb_control_msg (dn, USB_DIR_IN | USB_TYPE_VENDOR,
289 core_flags & CORE_DATA ? 0x0c : 0x04,
290 0x90, 0x00, next_packet_size, ptr);
291 if (ret != SANE_STATUS_GOOD)
292 {
293 DBG (DBG_err, "%s: USB-in-USB: error reading data\n", __func__);
294 return ret;
295 }
296
297 ptr += next_packet_size;
298 len -= next_packet_size;
299 }
300
301 /* Confirm data reception */
302 ack = 0;
303 ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
304 0x0c, 0x8f, 0x00,
305 sizeof (ack), &ack);
306 if (ret != SANE_STATUS_GOOD)
307 {
308 DBG (DBG_err, "%s: USB-in-USB: error confirming data reception\n",
309 __func__);
310 return -1;
311 }
312
313 /* USB-in-USB: checking if confirmation was acknowledged */
314 ret = hp5590_get_ack (dn, proto_flags);
315 if (ret != SANE_STATUS_GOOD)
316 return ret;
317 }
318
319 /* OUT (write) operation will be performed */
320 if (!(requesttype & USB_DIR_IN))
321 {
322 /* Prepare USB-in-USB control message */
323 memset (&ctrl, 0, sizeof (ctrl));
324 ctrl.bRequestType = 0x40;
325 ctrl.bRequest = request;
326 ctrl.wValue = htons (value);
327 ctrl.wIndex = htons (index);
328 ctrl.wLength = htole16 (size);
329
330 DBG (DBG_usb, "%s: USB-in-USB: sending control msg\n", __func__);
331 /* Send USB-in-USB control message */
332 ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
333 0x04, 0x8f, 0x00,
334 sizeof (ctrl), (unsigned char *) &ctrl);
335 if (ret != SANE_STATUS_GOOD)
336 {
337 DBG (DBG_err, "%s: USB-in-USB: error sending control message\n",
338 __func__);
339 return ret;
340 }
341
342 /* USB-in-USB: checking acknowledge for control message */
343 ret = hp5590_get_ack (dn, proto_flags);
344 if (ret != SANE_STATUS_GOOD)
345 return ret;
346
347 len = size;
348 ptr = bytes;
349 /* Data is sent in 8 byte portions */
350 while (len)
351 {
352 unsigned int next_packet_size;
353 next_packet_size = 8;
354 if (len < 8)
355 next_packet_size = len;
356
357 /* Send USB-in-USB data */
358 ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
359 core_flags & CORE_DATA ? 0x04 : 0x0c,
360 0x8f, 0x00, next_packet_size, ptr);
361 if (ret != SANE_STATUS_GOOD)
362 {
363 DBG (DBG_err, "%s: USB-in-USB: error sending data\n", __func__);
364 return ret;
365 }
366
367 /* CORE data is acknowledged packet by packet */
368 if (core_flags & CORE_DATA)
369 {
370 /* USB-in-USB: checking if data was accepted */
371 ret = hp5590_get_ack (dn, proto_flags);
372 if (ret != SANE_STATUS_GOOD)
373 return ret;
374 }
375
376 ptr += next_packet_size;
377 len -= next_packet_size;
378 }
379
380 /* Normal (non-CORE) data is acknowledged after its full transmission */
381 if (!(core_flags & CORE_DATA))
382 {
383 /* USB-in-USB: checking if data was accepted */
384 ret = hp5590_get_ack (dn, proto_flags);
385 if (ret != SANE_STATUS_GOOD)
386 return ret;
387 }
388
389 /* Getting response after data transmission */
390 DBG (DBG_usb, "%s: USB-in-USB: getting response\n", __func__);
391 ret = sanei_usb_control_msg (dn, USB_DIR_IN | USB_TYPE_VENDOR,
392 0x0c, 0x90, 0x00,
393 sizeof (response), &response);
394 if (ret != SANE_STATUS_GOOD)
395 {
396 DBG (DBG_err, "%s: USB-in-USB: error getting response\n", __func__);
397 return ret;
398 }
399
400 /* Necessary response after normal (non-CORE) data is 0x00,
401 * after bulk OUT preparation - 0x24
402 */
403 needed_response = core_flags & CORE_BULK_OUT ? 0x24 : 0x00;
404 if (response == needed_response)
405 DBG (DBG_usb, "%s: USB-in-USB: got correct response\n",
406 __func__);
407
408 if (response != needed_response)
409 {
410 DBG (DBG_err,
411 "%s: USB-in-USB: invalid response received "
412 "(needed %04x, got %04x)\n",
413 __func__, needed_response, response);
414 return SANE_STATUS_IO_ERROR;
415 }
416
417 /* Send bulk OUT flags is bulk OUT preparation is performed */
418 if (core_flags & CORE_BULK_OUT)
419 {
420 uint8_t bulk_flags = 0x24;
421 DBG (DBG_usb, "%s: USB-in-USB: sending bulk flags\n",
422 __func__);
423
424 ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
425 0x0c, 0x83, 0x00,
426 sizeof (bulk_flags), &bulk_flags);
427 if (ret != SANE_STATUS_GOOD)
428 {
429 DBG (DBG_err, "%s: USB-in-USB: error sending bulk flags\n",
430 __func__);
431 return ret;
432 }
433
434 /* USB-in-USB: checking confirmation for bulk flags */
435 ret = hp5590_get_ack (dn, proto_flags);
436 if (ret != SANE_STATUS_GOOD)
437 return ret;
438 }
439 }
440
441 return SANE_STATUS_GOOD;
442 }
443
444 /*******************************************************************************
445 * USB-in-USB: verifies last command
446 *
447 * Parameters
448 * dn - sanei_usb device descriptor
449 * cmd - command to verify
450 *
451 * Returns
452 * SANE_STATUS_GOOD - command verified successfully and CORE is ready
453 * SANE_STATUS_IO_ERROR - command verification failed
454 * SANE_STATUS_DEVICE_BUSY - command verified successfully but CORE isn't ready
455 * all other SANE_Status values - otherwise
456 */
457 static SANE_Status
hp5590_verify_last_cmd(SANE_Int dn, enum proto_flags proto_flags, unsigned int cmd)458 hp5590_verify_last_cmd (SANE_Int dn,
459 enum proto_flags proto_flags,
460 unsigned int cmd)
461 {
462 uint16_t verify_cmd;
463 unsigned int last_cmd;
464 unsigned int core_status;
465 SANE_Status ret;
466
467 DBG (3, "%s: USB-in-USB: command verification requested\n",
468 __func__);
469
470 /* Read last command along with CORE status */
471 ret = hp5590_control_msg (dn,
472 proto_flags,
473 USB_DIR_IN,
474 0x04, 0xc5, 0x00,
475 (unsigned char *) &verify_cmd,
476 sizeof (verify_cmd), CORE_NONE);
477 if (ret != SANE_STATUS_GOOD)
478 return ret;
479
480 verify_cmd = le16toh (verify_cmd); /* Response is LSB first */
481
482 /* Last command - minor byte */
483 last_cmd = verify_cmd & 0xff;
484 /* CORE status - major byte */
485 core_status = (verify_cmd & 0xff00) >> 8;
486
487 /* Verify last command */
488 DBG (DBG_usb, "%s: USB-in-USB: command verification %04x, "
489 "last command: %04x, core status: %04x\n",
490 __func__, verify_cmd, last_cmd, core_status);
491 if ((cmd & 0x00ff) != last_cmd)
492 {
493 DBG (DBG_err, "%s: USB-in-USB: command verification failed: "
494 "expected 0x%04x, got 0x%04x\n",
495 __func__, cmd, last_cmd);
496 return SANE_STATUS_IO_ERROR;
497 }
498
499 DBG (DBG_usb, "%s: USB-in-USB: command verified successfully\n",
500 __func__);
501
502 /* Return value depends on CORE status */
503 return core_status & CORE_FLAG_NOT_READY ?
504 SANE_STATUS_DEVICE_BUSY : SANE_STATUS_GOOD;
505 }
506
507 /*******************************************************************************
508 * USB-in-USB: send command (convenience wrapper around hp5590_control_msg())
509 *
510 * Parameters
511 * dn - sanei_usb device descriptor
512 * requesttype, request, value, index - their meanings are similar to
513 * sanei_control_msg()
514 * bytes - pointer to data buffer
515 * size - size of data
516 * core_flags -
517 * CORE_NONE - no CORE operation will be performed
518 * CORE_DATA - operation on CORE data will be performed
519 * CORE_BULK_IN - preparation for bulk IN transfer (not used yet)
520 * CORE_BULK_OUT - preparation for bulk OUT transfer
521 *
522 * Returns
523 * SANE_STATUS_GOOD - command was sent (and possible verified) w/o any errors
524 * all other SANE_Status values - otherwise
525 */
526 static SANE_Status
hp5590_cmd(SANE_Int dn, enum proto_flags proto_flags, unsigned int flags, unsigned int cmd, unsigned char *data, unsigned int size, unsigned int core_flags)527 hp5590_cmd (SANE_Int dn,
528 enum proto_flags proto_flags,
529 unsigned int flags,
530 unsigned int cmd, unsigned char *data, unsigned int size,
531 unsigned int core_flags)
532 {
533 SANE_Status ret;
534
535 DBG (3, "%s: USB-in-USB: command : %04x\n", __func__, cmd);
536
537 ret = hp5590_control_msg (dn,
538 proto_flags,
539 flags & CMD_IN ? USB_DIR_IN : USB_DIR_OUT,
540 0x04, cmd, 0x00, data, size, core_flags);
541 if (ret != SANE_STATUS_GOOD)
542 return ret;
543
544 ret = SANE_STATUS_GOOD;
545 /* Verify last command if requested */
546 if (flags & CMD_VERIFY)
547 {
548 ret = hp5590_verify_last_cmd (dn, proto_flags, cmd);
549 }
550
551 return ret;
552 }
553
554 /*******************************************************************************
555 * USB-in-USB: initialized bulk read state
556 *
557 * Parameters
558 * state - pointer to a pointer for initialized state
559 *
560 * Returns
561 * SANE_STATUS_GOOD - if state was initialized successfully
562 * SANE_STATUS_NO_MEM - memory allocation failed
563 */
564 static SANE_Status
hp5590_low_init_bulk_read_state(void **state)565 hp5590_low_init_bulk_read_state (void **state)
566 {
567 struct bulk_read_state *bulk_read_state;
568
569 DBG (3, "%s: USB-in-USB: initializing bulk read state\n", __func__);
570
571 hp5590_low_assert (state != NULL);
572
573 bulk_read_state = malloc (sizeof (struct bulk_read_state));
574 if (!bulk_read_state)
575 return SANE_STATUS_NO_MEM;
576 memset (bulk_read_state, 0, sizeof (struct bulk_read_state));
577
578 bulk_read_state->buffer = malloc (ALLOCATE_BULK_READ_PAGES
579 * BULK_READ_PAGE_SIZE);
580 if (!bulk_read_state->buffer)
581 {
582 DBG (DBG_err, "%s: Memory allocation failed for %u bytes\n",
583 __func__, ALLOCATE_BULK_READ_PAGES * BULK_READ_PAGE_SIZE);
584 return SANE_STATUS_NO_MEM;
585 }
586 bulk_read_state->buffer_size = ALLOCATE_BULK_READ_PAGES
587 * BULK_READ_PAGE_SIZE;
588 bulk_read_state->bytes_available = 0;
589 bulk_read_state->buffer_out_ptr = bulk_read_state->buffer;
590 bulk_read_state->buffer_in_ptr = bulk_read_state->buffer;
591 bulk_read_state->total_pages = 0;
592 bulk_read_state->buffer_end_ptr = bulk_read_state->buffer
593 + bulk_read_state->buffer_size;
594 bulk_read_state->initialized = 1;
595
596 *state = bulk_read_state;
597 return SANE_STATUS_GOOD;
598 }
599
600 /*******************************************************************************
601 * USB-in-USB: free bulk read state
602 *
603 * Parameters
604 * state - pointer to a pointer to bulk read state
605 *
606 * Returns
607 * SANE_STATUS_GOOD - bulk read state freed successfully
608 */
609 static SANE_Status
hp5590_low_free_bulk_read_state(void **state)610 hp5590_low_free_bulk_read_state (void **state)
611 {
612 struct bulk_read_state *bulk_read_state;
613
614 DBG (3, "%s\n", __func__);
615
616 hp5590_low_assert (state != NULL);
617 /* Just return if NULL bulk read state was given */
618 if (*state == NULL)
619 return SANE_STATUS_GOOD;
620
621 bulk_read_state = *state;
622
623 DBG (3, "%s: USB-in-USB: freeing bulk read state\n", __func__);
624
625 free (bulk_read_state->buffer);
626 bulk_read_state->buffer = NULL;
627 free (bulk_read_state);
628 *state = NULL;
629
630 return SANE_STATUS_GOOD;
631 }
632
633 /* FIXME: perhaps needs to be converted to use hp5590_control_msg() */
634 /*******************************************************************************
635 * USB-in-USB: bulk read
636 *
637 * Parameters
638 * dn - sanei_usb device descriptor
639 * bytes - pointer to data buffer
640 * size - size of data to read
641 * state - pointer to initialized bulk read state structure
642 */
643 static SANE_Status
hp5590_bulk_read(SANE_Int dn, enum proto_flags proto_flags, unsigned char *bytes, unsigned int size, void *state)644 hp5590_bulk_read (SANE_Int dn,
645 enum proto_flags proto_flags,
646 unsigned char *bytes, unsigned int size,
647 void *state)
648 {
649 struct usb_in_usb_bulk_setup ctrl;
650 SANE_Status ret;
651 unsigned int next_pages;
652 uint8_t bulk_flags;
653 size_t next_portion;
654 struct bulk_read_state *bulk_read_state;
655 unsigned int bytes_until_buffer_end;
656
657 DBG (3, "%s\n", __func__);
658
659 hp5590_low_assert (state != NULL);
660 hp5590_low_assert (bytes != NULL);
661
662 bulk_read_state = state;
663 if (bulk_read_state->initialized == 0)
664 {
665 DBG (DBG_err, "%s: USB-in-USB: bulk read state not initialized\n",
666 __func__);
667 return SANE_STATUS_INVAL;
668 }
669
670 memset (bytes, 0, size);
671
672 /* Check if requested data would fit into the buffer */
673 if (size > bulk_read_state->buffer_size)
674 {
675 DBG (DBG_err, "Data requested won't fit in the bulk read buffer "
676 "(requested: %u, buffer size: %u\n", size,
677 bulk_read_state->buffer_size);
678 return SANE_STATUS_NO_MEM;
679 }
680
681 /* Read data until requested size of data will be received */
682 while (bulk_read_state->bytes_available < size)
683 {
684 DBG (DBG_usb, "%s: USB-in-USB: not enough data in buffer available "
685 "(available: %u, requested: %u)\n",
686 __func__, bulk_read_state->bytes_available, size);
687
688 /* IMPORTANT! 'next_pages' means 'request and receive next_pages pages in
689 * one bulk transfer request '. Windows driver uses 4 pages between each
690 * request. The more pages are received between requests the less the
691 * scanner does scan head re-positioning thus improving scanning speed.
692 * On the other hand, scanner expects that all of the requested pages
693 * will be received immediately after the request. In case when a
694 * frontend will have a delay between reads we will get bulk transfer
695 * timeout sooner or later.
696 * Having next_pages = 1 is the most safe case.
697 */
698 next_pages = 1;
699 /* Count all received pages to calculate when we will need to send
700 * another bulk request
701 */
702 bulk_read_state->total_pages++;
703 DBG (DBG_usb, "%s: USB-in-USB: total pages done: %u\n",
704 __func__, bulk_read_state->total_pages);
705
706 /* Send another bulk request for 'next_pages' before first
707 * page or next necessary one
708 */
709 if ( bulk_read_state->total_pages == 1
710 || bulk_read_state->total_pages % next_pages == 0)
711 {
712 /* Send bulk flags */
713 DBG (DBG_usb, "%s: USB-in-USB: sending USB-in-USB bulk flags\n",
714 __func__);
715 bulk_flags = 0x24;
716 ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
717 0x0c, 0x83, 0x00,
718 sizeof (bulk_flags), &bulk_flags);
719 if (ret != SANE_STATUS_GOOD)
720 {
721 DBG (DBG_err, "%s: USB-in-USB: error sending bulk flags\n",
722 __func__);
723 return ret;
724 }
725
726 /* USB-in-USB: checking confirmation for bulk flags\n" */
727 ret = hp5590_get_ack (dn, proto_flags);
728 if (ret != SANE_STATUS_GOOD)
729 return ret;
730
731 /* Prepare bulk read request */
732 memset (&ctrl, 0, sizeof (ctrl));
733 ctrl.bRequestType = 0x00;
734 ctrl.bEndpoint = 0x82;
735 ctrl.wLength = htons (next_pages);
736
737 /* Send bulk read request */
738 DBG (DBG_usb, "%s: USB-in-USB: sending control msg for bulk\n",
739 __func__);
740 ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
741 0x04, 0x82, 0x00,
742 sizeof (ctrl),
743 (unsigned char *) &ctrl);
744 if (ret != SANE_STATUS_GOOD)
745 {
746 DBG (DBG_err, "%s: USB-in-USB: error sending control msg\n",
747 __func__);
748 return ret;
749 }
750
751 /* USB-in-USB: checking if control msg was accepted */
752 ret = hp5590_get_ack (dn, proto_flags);
753 if (ret != SANE_STATUS_GOOD)
754 return ret;
755 }
756
757 next_portion = BULK_READ_PAGE_SIZE;
758 /* Check if next page will fit into the buffer */
759 if (bulk_read_state->buffer_size
760 - bulk_read_state->bytes_available < next_portion)
761 {
762 DBG (DBG_err, "%s: USB-in-USB: buffer too small\n", __func__);
763 return SANE_STATUS_NO_MEM;
764 }
765
766 /* Bulk read next page */
767 DBG (DBG_usb, "%s: USB-in-USB: bulk reading %lu bytes\n",
768 __func__, (u_long) next_portion);
769 ret = sanei_usb_read_bulk (dn,
770 bulk_read_state->buffer_in_ptr,
771 &next_portion);
772 if (ret != SANE_STATUS_GOOD)
773 {
774 if (ret == SANE_STATUS_EOF)
775 return ret;
776 DBG (DBG_err, "%s: USB-in-USB: error during bulk read: %s\n",
777 __func__, sane_strstatus (ret));
778 return ret;
779 }
780
781 /* Check if we received the same amount of data as requested */
782 if (next_portion != BULK_READ_PAGE_SIZE)
783 {
784 DBG (DBG_err, "%s: USB-in-USB: incomplete bulk read "
785 "(requested %u bytes, got %lu bytes)\n",
786 __func__, BULK_READ_PAGE_SIZE, (u_long) next_portion);
787 return SANE_STATUS_IO_ERROR;
788 }
789
790 /* Move pointers to the next position */
791 bulk_read_state->buffer_in_ptr += next_portion;
792
793 /* Check for the end of the buffer */
794 if (bulk_read_state->buffer_in_ptr > bulk_read_state->buffer_end_ptr)
795 {
796 DBG (DBG_err,
797 "%s: USB-in-USB: attempted to access over the end of buffer "
798 "(in_ptr: %p, end_ptr: %p, ptr: %p, buffer size: %u\n",
799 __func__, (void *) bulk_read_state->buffer_in_ptr,
800 (void *) bulk_read_state->buffer_end_ptr,
801 (void *) bulk_read_state->buffer,
802 bulk_read_state->buffer_size);
803 return SANE_STATUS_NO_MEM;
804 }
805
806 /* Check for buffer pointer wrapping */
807 if (bulk_read_state->buffer_in_ptr == bulk_read_state->buffer_end_ptr)
808 {
809 DBG (DBG_usb, "%s: USB-in-USB: buffer wrapped while writing\n",
810 __func__);
811 bulk_read_state->buffer_in_ptr = bulk_read_state->buffer;
812 }
813
814 /* Count the amount of data we read */
815 bulk_read_state->bytes_available += next_portion;
816 }
817
818 /* Transfer requested amount of data to the caller */
819 DBG (DBG_usb, "%s: USB-in-USB: data in bulk buffer is available "
820 "(requested %u bytes, available %u bytes)\n",
821 __func__, size, bulk_read_state->bytes_available);
822
823 /* Check for buffer pointer wrapping */
824 bytes_until_buffer_end = bulk_read_state->buffer_end_ptr
825 - bulk_read_state->buffer_out_ptr;
826 if (bytes_until_buffer_end <= size)
827 {
828 /* First buffer part */
829 DBG (DBG_usb, "%s: USB-in-USB: reached bulk read buffer end\n", __func__);
830 memcpy (bytes, bulk_read_state->buffer_out_ptr, bytes_until_buffer_end);
831 bulk_read_state->buffer_out_ptr = bulk_read_state->buffer;
832 /* And second part (if any) */
833 if (bytes_until_buffer_end < size)
834 {
835 DBG (DBG_usb, "%s: USB-in-USB: giving 2nd buffer part\n", __func__);
836 memcpy (bytes + bytes_until_buffer_end,
837 bulk_read_state->buffer_out_ptr,
838 size - bytes_until_buffer_end);
839 bulk_read_state->buffer_out_ptr += size - bytes_until_buffer_end;
840 }
841 }
842 else
843 {
844 /* The data is in one buffer part (w/o wrapping) */
845 memcpy (bytes, bulk_read_state->buffer_out_ptr, size);
846 bulk_read_state->buffer_out_ptr += size;
847 if (bulk_read_state->buffer_out_ptr == bulk_read_state->buffer_end_ptr)
848 {
849 DBG (DBG_usb, "%s: USB-in-USB: buffer wrapped while reading\n",
850 __func__);
851 bulk_read_state->buffer_out_ptr = bulk_read_state->buffer;
852 }
853 }
854
855 /* Count the amount of data transferred to the caller */
856 bulk_read_state->bytes_available -= size;
857
858 return SANE_STATUS_GOOD;
859 }
860
861 /*******************************************************************************
862 * USB-in-USB: bulk write
863 *
864 * Parameters
865 * dn - sanei_usb device descriptor
866 * cmd - command for bulk write operation
867 * bytes - pointer to data buffer
868 * size - size of data
869 *
870 * Returns
871 * SANE_STATUS_GOOD - all data transferred successfully
872 * all other SANE_Status value - otherwise
873 */
874 static SANE_Status
hp5590_bulk_write(SANE_Int dn, enum proto_flags proto_flags, int cmd, unsigned char *bytes, unsigned int size)875 hp5590_bulk_write (SANE_Int dn,
876 enum proto_flags proto_flags,
877 int cmd, unsigned char *bytes,
878 unsigned int size)
879 {
880 struct usb_in_usb_bulk_setup ctrl;
881 SANE_Status ret;
882 struct bulk_size bulk_size;
883
884 unsigned int len;
885 unsigned char *ptr;
886 size_t next_portion;
887
888 DBG (3, "%s: USB-in-USB: command: %04x, size %u\n", __func__, cmd,
889 size);
890
891 hp5590_low_assert (bytes != NULL);
892
893 /* Prepare bulk write request */
894 memset (&bulk_size, 0, sizeof (bulk_size));
895 /* Counted in page size */
896 bulk_size.size = size / BULK_WRITE_PAGE_SIZE;
897
898 /* Send bulk write request */
899 DBG (3, "%s: USB-in-USB: total %u pages (each of %u bytes)\n",
900 __func__, bulk_size.size, BULK_WRITE_PAGE_SIZE);
901 ret = hp5590_control_msg (dn,
902 proto_flags,
903 USB_DIR_OUT,
904 0x04, cmd, 0,
905 (unsigned char *) &bulk_size, sizeof (bulk_size),
906 CORE_DATA | CORE_BULK_OUT);
907 if (ret != SANE_STATUS_GOOD)
908 return ret;
909
910 len = size;
911 ptr = bytes;
912
913 /* Send all data in pages */
914 while (len)
915 {
916 next_portion = BULK_WRITE_PAGE_SIZE;
917 if (len < next_portion)
918 next_portion = len;
919
920 DBG (3, "%s: USB-in-USB: next portion %lu bytes\n",
921 __func__, (u_long) next_portion);
922
923 /* Prepare bulk write request */
924 memset (&ctrl, 0, sizeof (ctrl));
925 ctrl.bRequestType = 0x01;
926 ctrl.bEndpoint = 0x82;
927 ctrl.wLength = htons (next_portion);
928
929 /* Send bulk write request */
930 ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
931 0x04, 0x82, 0,
932 sizeof (ctrl), (unsigned char *) &ctrl);
933 if (ret != SANE_STATUS_GOOD)
934 return ret;
935
936 /* USB-in-USB: checking if command was accepted */
937 ret = hp5590_get_ack (dn, proto_flags);
938 if (ret != SANE_STATUS_GOOD)
939 return ret;
940
941 /* Write bulk data */
942 DBG (3, "%s: USB-in-USB: bulk writing %lu bytes\n",
943 __func__, (u_long) next_portion);
944 ret = sanei_usb_write_bulk (dn, ptr, &next_portion);
945 if (ret != SANE_STATUS_GOOD)
946 {
947 /* Treast EOF as successful result */
948 if (ret == SANE_STATUS_EOF)
949 break;
950 DBG (DBG_err, "%s: USB-in-USB: error during bulk write: %s\n",
951 __func__, sane_strstatus (ret));
952 return ret;
953 }
954
955 /* Move to the next page */
956 len -= next_portion;
957 ptr += next_portion;
958 }
959
960 /* Verify bulk command */
961 return hp5590_verify_last_cmd (dn, proto_flags, cmd);
962 }
963 /* vim: sw=2 ts=8
964 */
965