kopia lustrzana https://gitlab.com/sane-project/backends
+ Added files for 'hp5590' backend which supports HP ScanJet 5550/5590/7650
scannersmerge-requests/1/head
rodzic
2441d08401
commit
bb31b94180
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,168 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
Copyright (C) 2007 Ilia Sotnikov <hostcc@gmail.com>
|
||||
This file is part of the SANE package.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
|
||||
As a special exception, the authors of SANE give permission for
|
||||
additional uses of the libraries contained in this release of SANE.
|
||||
|
||||
The exception is that, if you link a SANE library with other files
|
||||
to produce an executable, this does not by itself cause the
|
||||
resulting executable to be covered by the GNU General Public
|
||||
License. Your use of that executable is in no way restricted on
|
||||
account of linking the SANE library code into it.
|
||||
|
||||
This exception does not, however, invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public
|
||||
License.
|
||||
|
||||
If you submit changes to SANE to the maintainers to be included in
|
||||
a subsequent release, you agree by submitting the changes that
|
||||
those changes may be distributed with this exception intact.
|
||||
|
||||
If you write modifications of your own for SANE, it is your choice
|
||||
whether to permit this exception to apply to your modifications.
|
||||
If you do not wish that, delete this exception notice.
|
||||
|
||||
This file is part of a SANE backend for HP 5550/5590/7650 Scanners
|
||||
*/
|
||||
|
||||
#ifndef HP5590_H
|
||||
#define HP5590_H
|
||||
|
||||
#include "hp5590_low.h"
|
||||
|
||||
#define TMA_MAX_X_INCHES 1.69
|
||||
#define TMA_MAX_Y_INCHES 6
|
||||
|
||||
enum hp_scanner_types
|
||||
{
|
||||
SCANNER_NONE = 0,
|
||||
SCANNER_HP5550,
|
||||
SCANNER_HP5590,
|
||||
SCANNER_HP7650
|
||||
};
|
||||
|
||||
enum scan_sources
|
||||
{
|
||||
SOURCE_NONE = 1,
|
||||
SOURCE_FLATBED,
|
||||
SOURCE_ADF,
|
||||
SOURCE_ADF_DUPLEX,
|
||||
SOURCE_TMA_NEGATIVES,
|
||||
SOURCE_TMA_SLIDES
|
||||
};
|
||||
|
||||
enum scan_modes
|
||||
{
|
||||
MODE_NORMAL = 1,
|
||||
MODE_PREVIEW
|
||||
};
|
||||
|
||||
enum color_depths
|
||||
{
|
||||
DEPTH_BW = 1,
|
||||
DEPTH_GRAY,
|
||||
DEPTH_COLOR_24,
|
||||
DEPTH_COLOR_48
|
||||
};
|
||||
|
||||
enum button_status
|
||||
{
|
||||
BUTTON_NONE = 1,
|
||||
BUTTON_POWER,
|
||||
BUTTON_SCAN,
|
||||
BUTTON_COLLECT,
|
||||
BUTTON_FILE,
|
||||
BUTTON_EMAIL,
|
||||
BUTTON_COPY,
|
||||
BUTTON_UP,
|
||||
BUTTON_DOWN,
|
||||
BUTTON_MODE,
|
||||
BUTTON_CANCEL
|
||||
};
|
||||
|
||||
enum hp5590_lamp_state
|
||||
{
|
||||
LAMP_STATE_TURNOFF = 1,
|
||||
LAMP_STATE_TURNON,
|
||||
LAMP_STATE_SET_TURNOFF_TIME,
|
||||
LAMP_STATE_SET_TURNOFF_TIME_LONG
|
||||
};
|
||||
|
||||
#define FEATURE_NONE 0
|
||||
#define FEATURE_ADF 1 << 0
|
||||
#define FEATURE_TMA 1 << 1
|
||||
#define FEATURE_LCD 1 << 2
|
||||
|
||||
struct scanner_info
|
||||
{
|
||||
const char *model;
|
||||
const char *kind;
|
||||
unsigned int features;
|
||||
const char *fw_version;
|
||||
unsigned int max_dpi_x;
|
||||
unsigned int max_dpi_y;
|
||||
unsigned int max_pixels_x;
|
||||
unsigned int max_pixels_y;
|
||||
float max_size_x;
|
||||
float max_size_y;
|
||||
unsigned int max_motor_param;
|
||||
unsigned int normal_motor_param;
|
||||
};
|
||||
|
||||
static SANE_Status hp5590_vendor_product_id (enum hp_scanner_types scanner_type,
|
||||
SANE_Word * vendor_id,
|
||||
SANE_Word * product_id);
|
||||
static SANE_Status hp5590_init_scanner (SANE_Int dn,
|
||||
struct scanner_info **info,
|
||||
enum hp_scanner_types scanner_type);
|
||||
static SANE_Status hp5590_power_status (SANE_Int dn);
|
||||
static SANE_Status hp5590_read_max_scan_count (SANE_Int dn,
|
||||
unsigned int *max_count);
|
||||
static SANE_Status hp5590_select_source_and_wakeup (SANE_Int dn,
|
||||
enum scan_sources source,
|
||||
SANE_Bool extend_lamp_timeout);
|
||||
static SANE_Status hp5590_stop_scan (SANE_Int dn);
|
||||
static SANE_Status hp5590_read_scan_count (SANE_Int dn,
|
||||
unsigned int *count);
|
||||
static SANE_Status hp5590_set_scan_params (SANE_Int dn,
|
||||
struct scanner_info *scanner_info,
|
||||
unsigned int top_x, unsigned int top_y,
|
||||
unsigned int width, unsigned int height,
|
||||
unsigned int dpi,
|
||||
enum color_depths color_depth,
|
||||
enum scan_modes scan_mode,
|
||||
enum scan_sources scan_source);
|
||||
static SANE_Status hp5590_send_forward_calibration_maps (SANE_Int dn);
|
||||
static SANE_Status hp5590_send_reverse_calibration_map (SANE_Int dn);
|
||||
static SANE_Status hp5590_inc_scan_count (SANE_Int dn);
|
||||
static SANE_Status hp5590_start_scan (SANE_Int dn);
|
||||
static SANE_Status hp5590_read (SANE_Int dn,
|
||||
unsigned char *bytes,
|
||||
unsigned int size, void *state);
|
||||
static SANE_Status hp5590_read_buttons (SANE_Int dn,
|
||||
enum button_status *status);
|
||||
static SANE_Status hp5590_read_part_number (SANE_Int dn);
|
||||
static SANE_Status hp5590_calc_pixel_bits (unsigned int dpi,
|
||||
enum color_depths color_depth,
|
||||
unsigned int *pixel_bits);
|
||||
static SANE_Status hp5590_is_data_available (SANE_Int dn);
|
||||
static SANE_Status hp5590_reset_scan_head (SANE_Int dn);
|
||||
#endif /* HP5590_H */
|
||||
/* vim: sw=2 ts=8
|
||||
*/
|
|
@ -0,0 +1,948 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
Copyright (C) 2007 Ilia Sotnikov <hostcc@gmail.com>
|
||||
This file is part of the SANE package.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
|
||||
As a special exception, the authors of SANE give permission for
|
||||
additional uses of the libraries contained in this release of SANE.
|
||||
|
||||
The exception is that, if you link a SANE library with other files
|
||||
to produce an executable, this does not by itself cause the
|
||||
resulting executable to be covered by the GNU General Public
|
||||
License. Your use of that executable is in no way restricted on
|
||||
account of linking the SANE library code into it.
|
||||
|
||||
This exception does not, however, invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public
|
||||
License.
|
||||
|
||||
If you submit changes to SANE to the maintainers to be included in
|
||||
a subsequent release, you agree by submitting the changes that
|
||||
those changes may be distributed with this exception intact.
|
||||
|
||||
If you write modifications of your own for SANE, it is your choice
|
||||
whether to permit this exception to apply to your modifications.
|
||||
If you do not wish that, delete this exception notice.
|
||||
|
||||
This file is part of a SANE backend for HP 5550/5590/7650 Scanners
|
||||
*/
|
||||
|
||||
#include "sane/config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
|
||||
#include "sane/sanei_debug.h"
|
||||
#include "sane/sanei_usb.h"
|
||||
#include "hp5590_low.h"
|
||||
|
||||
/* For USB_* constants */
|
||||
#ifdef HAVE_USB_H
|
||||
# include <usb.h>
|
||||
#endif /* HAVE_USB_H */
|
||||
|
||||
/* Debug levels */
|
||||
#define DBG_err 0
|
||||
#define DBG_proc 10
|
||||
#define DBG_usb 50
|
||||
|
||||
/* Custom assert() macro */
|
||||
#define hp5590_low_assert(exp) if(!(exp)) { \
|
||||
DBG (DBG_err, "Assertion '%s' failed at %s:%u\n", #exp, __FILE__, __LINE__);\
|
||||
return SANE_STATUS_INVAL; \
|
||||
}
|
||||
|
||||
/* Structure describing bulk transfer size */
|
||||
struct bulk_size
|
||||
{
|
||||
u_int16_t size;
|
||||
u_int8_t unused;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Structure describing bulk URB */
|
||||
/* FIXME: Verify according to USB standard */
|
||||
struct usb_bulk_setup
|
||||
{
|
||||
u_int8_t bRequestType;
|
||||
u_int8_t bRequest;
|
||||
u_int8_t bEndpoint;
|
||||
u_int16_t unknown;
|
||||
u_int16_t wLength;
|
||||
u_int8_t pad;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* CORE status flag - ready or not */
|
||||
#define CORE_FLAG_NOT_READY 1 << 1
|
||||
|
||||
/* Bulk transfers are done in pages, below their respective sizes */
|
||||
#define BULK_WRITE_PAGE_SIZE 0x0f000
|
||||
#define BULK_READ_PAGE_SIZE 0x10000
|
||||
#define ALLOCATE_BULK_READ_PAGES 16 /* 16 * 65536 = 1Mb */
|
||||
|
||||
/* Structure describing bulk read state, because bulk reads will be done in
|
||||
* pages, but function caller uses its own buffer, whose size is certainly
|
||||
* different. Also, each bulk read page is ACK'ed by special command
|
||||
* so total pages received should be tracked as well
|
||||
*/
|
||||
struct bulk_read_state
|
||||
{
|
||||
unsigned char *buffer;
|
||||
unsigned int buffer_size;
|
||||
unsigned int bytes_available;
|
||||
unsigned char *buffer_out_ptr;
|
||||
unsigned char *buffer_in_ptr;
|
||||
unsigned int total_pages;
|
||||
unsigned char *buffer_end_ptr;
|
||||
unsigned int initialized;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* USB-in-USB: get acknowledge for last USB-in-USB operation
|
||||
*
|
||||
* Parameters
|
||||
* dn - sanei_usb device descriptor
|
||||
*
|
||||
* Returns
|
||||
* SANE_STATUS_GOOD - if correct acknowledge was received
|
||||
* SANE_STATUS_DEVICE_BUSY - otherwise
|
||||
*/
|
||||
static SANE_Status
|
||||
hp5590_get_ack (SANE_Int dn)
|
||||
{
|
||||
u_int8_t status;
|
||||
SANE_Status ret;
|
||||
|
||||
DBG (DBG_proc, "%s\n", __FUNCTION__);
|
||||
|
||||
/* Check if USB-in-USB operation was accepted */
|
||||
ret = sanei_usb_control_msg (dn, USB_DIR_IN | USB_TYPE_VENDOR,
|
||||
0x0c, 0x8e, 0x20,
|
||||
sizeof (status), &status);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: error getting acknowledge\n",
|
||||
__FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBG (DBG_usb, "%s: USB-in-USB: accepted\n", __FUNCTION__);
|
||||
|
||||
/* Check if we received correct acknowledgement */
|
||||
if (status != 0x01)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: not accepted (status %u)\n",
|
||||
__FUNCTION__, status);
|
||||
return SANE_STATUS_DEVICE_BUSY;
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* USB-in-USB: get device status
|
||||
*
|
||||
* Parameters
|
||||
* dn - sanei_usb device descriptor
|
||||
*
|
||||
* Returns
|
||||
* SANE_STATUS_GOOD - if correct status was received
|
||||
* SANE_STATUS_DEVICE_BUSY - otherwise
|
||||
*/
|
||||
static SANE_Status
|
||||
hp5590_get_status (SANE_Int dn)
|
||||
{
|
||||
u_int8_t status;
|
||||
SANE_Status ret;
|
||||
|
||||
DBG (DBG_proc, "%s\n", __FUNCTION__);
|
||||
|
||||
ret = sanei_usb_control_msg (dn, USB_DIR_IN | USB_TYPE_VENDOR,
|
||||
0x0c, 0x8e, 0x20,
|
||||
sizeof (status), &status);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: error getting device status\n",
|
||||
__FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check if we received correct status */
|
||||
if (status != 0x00)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: got non-zero device status (status %u)\n",
|
||||
__FUNCTION__, status);
|
||||
return SANE_STATUS_DEVICE_BUSY;
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* USB-in-USB: sends control message for IN or OUT operation
|
||||
*
|
||||
* Parameters
|
||||
* dn - sanei_usb device descriptor
|
||||
* requesttype, request, value, index - their meaninings are similar to
|
||||
* sanei_control_msg()
|
||||
* bytes - pointer to data buffer
|
||||
* size - size of data
|
||||
* core_flags -
|
||||
* CORE_NONE - no CORE operation will be performed
|
||||
* CORE_DATA - operation on CORE data will be performed
|
||||
* CORE_BULK_IN - preparation for bulk IN transfer (not used yet)
|
||||
* CORE_BULK_OUT - preparation for bulk OUT trasfer
|
||||
*
|
||||
* Returns
|
||||
* SANE_STATUS_GOOD - control message was sent w/o any errors
|
||||
* all other SANE_Status values - otherwise
|
||||
*/
|
||||
static SANE_Status
|
||||
hp5590_control_msg (SANE_Int dn,
|
||||
int requesttype, int request,
|
||||
int value, int index, unsigned char *bytes,
|
||||
int size, int core_flags)
|
||||
{
|
||||
struct usb_ctrl_setup ctrl;
|
||||
SANE_Status ret;
|
||||
unsigned int len;
|
||||
unsigned char *ptr;
|
||||
u_int8_t ack;
|
||||
u_int8_t response;
|
||||
unsigned int needed_response;
|
||||
|
||||
DBG (DBG_proc, "%s: USB-in-USB: core data: %s\n",
|
||||
__FUNCTION__, core_flags & CORE_DATA ? "yes" : "no");
|
||||
|
||||
hp5590_low_assert (bytes != NULL);
|
||||
|
||||
/* IN (read) operation will be performed */
|
||||
if (requesttype & USB_DIR_IN)
|
||||
{
|
||||
/* Prepare USB-in-USB control message */
|
||||
memset (&ctrl, 0, sizeof (ctrl));
|
||||
ctrl.bRequestType = 0xc0;
|
||||
ctrl.bRequest = request;
|
||||
ctrl.wValue = htons (value);
|
||||
ctrl.wIndex = htons (index);
|
||||
ctrl.wLength = size;
|
||||
|
||||
DBG (DBG_usb, "%s: USB-in-USB: sending control msg\n", __FUNCTION__);
|
||||
/* Send USB-in-USB control message */
|
||||
ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x04, 0x8f, 0x00,
|
||||
sizeof (ctrl), (unsigned char *) &ctrl);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: error sending control message\n",
|
||||
__FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBG (DBG_usb, "%s: USB-in-USB: checking acknowledge for control message\n",
|
||||
__FUNCTION__);
|
||||
ret = hp5590_get_ack (dn);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
return ret;
|
||||
|
||||
len = size;
|
||||
ptr = bytes;
|
||||
/* Data is read in 8 byte portions */
|
||||
while (len)
|
||||
{
|
||||
unsigned int next_packet_size;
|
||||
next_packet_size = 8;
|
||||
if (len < 8)
|
||||
next_packet_size = len;
|
||||
|
||||
/* Read USB-in-USB data */
|
||||
ret = sanei_usb_control_msg (dn, USB_DIR_IN | USB_TYPE_VENDOR,
|
||||
core_flags & CORE_DATA ? 0x0c : 0x04,
|
||||
0x90, 0x00, next_packet_size, ptr);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: error reading data\n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ptr += next_packet_size;
|
||||
len -= next_packet_size;
|
||||
}
|
||||
|
||||
/* Confirm data reception */
|
||||
ack = 0;
|
||||
ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x0c, 0x8f, 0x00,
|
||||
sizeof (ack), &ack);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: error confirming data reception\n",
|
||||
__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DBG (DBG_usb, "%s: USB-in-USB: checking if confirmation was acknowledged\n",
|
||||
__FUNCTION__);
|
||||
ret = hp5590_get_ack (dn);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* OUT (write) operation will be performed */
|
||||
if (!(requesttype & USB_DIR_IN))
|
||||
{
|
||||
/* Prepare USB-in-USB control message */
|
||||
memset (&ctrl, 0, sizeof (ctrl));
|
||||
ctrl.bRequestType = 0x40;
|
||||
ctrl.bRequest = request;
|
||||
ctrl.wValue = htons (value);
|
||||
ctrl.wIndex = htons (index);
|
||||
ctrl.wLength = size;
|
||||
|
||||
DBG (DBG_usb, "%s: USB-in-USB: sending control msg\n", __FUNCTION__);
|
||||
/* Send USB-in-USB control message */
|
||||
ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x04, 0x8f, 0x00,
|
||||
sizeof (ctrl), (unsigned char *) &ctrl);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: error sending control message\n",
|
||||
__FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBG (DBG_usb, "%s: USB-in-USB: checking acknowledge for control message\n",
|
||||
__FUNCTION__);
|
||||
ret = hp5590_get_ack (dn);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
return ret;
|
||||
|
||||
len = size;
|
||||
ptr = bytes;
|
||||
/* Data is sent in 8 byte portions */
|
||||
while (len)
|
||||
{
|
||||
unsigned int next_packet_size;
|
||||
next_packet_size = 8;
|
||||
if (len < 8)
|
||||
next_packet_size = len;
|
||||
|
||||
/* Send USB-in-USB data */
|
||||
ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
core_flags & CORE_DATA ? 0x04 : 0x0c,
|
||||
0x8f, 0x00, next_packet_size, ptr);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: error sending data\n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* CORE data is acknowledged packet by packet */
|
||||
if (core_flags & CORE_DATA)
|
||||
{
|
||||
DBG (DBG_usb, "%s: USB-in-USB: checking if data was accepted\n",
|
||||
__FUNCTION__);
|
||||
ret = hp5590_get_ack (dn);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ptr += next_packet_size;
|
||||
len -= next_packet_size;
|
||||
}
|
||||
|
||||
/* Normal (non-CORE) data is acknowledged after its full transmission */
|
||||
if (!(core_flags & CORE_DATA))
|
||||
{
|
||||
DBG (3, "%s: USB-in-USB: checking if data was accepted\n",
|
||||
__FUNCTION__);
|
||||
ret = hp5590_get_ack (dn);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Getting response after data transmission */
|
||||
DBG (DBG_usb, "%s: USB-in-USB: getting response\n", __FUNCTION__);
|
||||
ret = sanei_usb_control_msg (dn, USB_DIR_IN | USB_TYPE_VENDOR,
|
||||
0x0c, 0x90, 0x00,
|
||||
sizeof (response), &response);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: error getting response\n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Necessary response after normal (non-CORE) data is 0x00,
|
||||
* after bulk OUT preparation - 0x24
|
||||
*/
|
||||
needed_response = core_flags & CORE_BULK_OUT ? 0x24 : 0x00;
|
||||
if (response == needed_response)
|
||||
DBG (DBG_usb, "%s: USB-in-USB: got correct response\n",
|
||||
__FUNCTION__);
|
||||
|
||||
if (response != needed_response)
|
||||
{
|
||||
DBG (DBG_err,
|
||||
"%s: USB-in-USB: invalid response received "
|
||||
"(needed %04x, got %04x)\n",
|
||||
__FUNCTION__, needed_response, response);
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
|
||||
/* Send bulk OUT flags is bulk OUT preparation is performed */
|
||||
if (core_flags & CORE_BULK_OUT)
|
||||
{
|
||||
u_int8_t bulk_flags = 0x24;
|
||||
DBG (DBG_usb, "%s: USB-in-USB: sending bulk flags\n",
|
||||
__FUNCTION__);
|
||||
|
||||
ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x0c, 0x83, 0x00,
|
||||
sizeof (bulk_flags), &bulk_flags);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: error sending bulk flags\n",
|
||||
__FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check acknowledge for bulk flags transmission */
|
||||
DBG (DBG_usb, "%s: USB-in-USB: checking confirmation for bulk flags\n",
|
||||
__FUNCTION__);
|
||||
ret = hp5590_get_ack (dn);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* USB-in-USB: verifies last command
|
||||
*
|
||||
* Parameters
|
||||
* dn - sanei_usb device descriptor
|
||||
* cmd - command to verify
|
||||
*
|
||||
* Returns
|
||||
* SANE_STATUS_GOOD - command verified successfully and CORE is ready
|
||||
* SANE_STATUS_IO_ERROR - command verification failed
|
||||
* SANE_STATUS_DEVICE_BUSY - command verified successfully but CORE isn't ready
|
||||
* all other SANE_Status values - otherwise
|
||||
*/
|
||||
static SANE_Status
|
||||
hp5590_verify_last_cmd (SANE_Int dn, unsigned int cmd)
|
||||
{
|
||||
u_int16_t verify_cmd;
|
||||
unsigned int last_cmd;
|
||||
unsigned int core_status;
|
||||
SANE_Status ret;
|
||||
|
||||
DBG (3, "%s: USB-in-USB: command verification requested\n",
|
||||
__FUNCTION__);
|
||||
|
||||
/* Read last command along with CORE status */
|
||||
ret = hp5590_control_msg (dn, USB_DIR_IN,
|
||||
0x04, 0xc5, 0x00,
|
||||
(unsigned char *) &verify_cmd,
|
||||
sizeof (verify_cmd), CORE_NONE);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
return ret;
|
||||
|
||||
/* Last command - minor byte */
|
||||
last_cmd = verify_cmd & 0xff;
|
||||
/* CORE status - major byte */
|
||||
core_status = (verify_cmd & 0xff00) >> 8;
|
||||
|
||||
/* Verify last command */
|
||||
DBG (DBG_usb, "%s: USB-in-USB: command verification %04x, "
|
||||
"last command: %04x, core status: %04x\n",
|
||||
__FUNCTION__, verify_cmd, last_cmd, core_status);
|
||||
if ((cmd & 0x00ff) != last_cmd)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: command verification failed: "
|
||||
"expected 0x%04x, got 0x%04x\n",
|
||||
__FUNCTION__, cmd, last_cmd);
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
|
||||
DBG (DBG_usb, "%s: USB-in-USB: command verified successfully\n",
|
||||
__FUNCTION__);
|
||||
|
||||
/* Return value depends on CORE status */
|
||||
return core_status & CORE_FLAG_NOT_READY ?
|
||||
SANE_STATUS_DEVICE_BUSY : SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* USB-in-USB: send command (convenience wrapper around hp5590_control_msg())
|
||||
*
|
||||
* Parameters
|
||||
* dn - sanei_usb device descriptor
|
||||
* requesttype, request, value, index - their meaninings are similar to
|
||||
* sanei_control_msg()
|
||||
* bytes - pointer to data buffer
|
||||
* size - size of data
|
||||
* core_flags -
|
||||
* CORE_NONE - no CORE operation will be performed
|
||||
* CORE_DATA - operation on CORE data will be performed
|
||||
* CORE_BULK_IN - preparation for bulk IN transfer (not used yet)
|
||||
* CORE_BULK_OUT - preparation for bulk OUT trasfer
|
||||
*
|
||||
* Returns
|
||||
* SANE_STATUS_GOOD - command was sent (and possible verified) w/o any errors
|
||||
* all other SANE_Status values - otherwise
|
||||
*/
|
||||
static SANE_Status
|
||||
hp5590_cmd (SANE_Int dn, unsigned int flags,
|
||||
unsigned int cmd, unsigned char *data, unsigned int size,
|
||||
unsigned int core_flags)
|
||||
{
|
||||
SANE_Status ret;
|
||||
|
||||
DBG (3, "%s: USB-in-USB: command : %04x\n", __FUNCTION__, cmd);
|
||||
|
||||
ret = hp5590_control_msg (dn,
|
||||
flags & CMD_IN ? USB_DIR_IN : USB_DIR_OUT,
|
||||
0x04, cmd, 0x00, data, size, core_flags);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
return ret;
|
||||
|
||||
ret = SANE_STATUS_GOOD;
|
||||
/* Verify last command if requested */
|
||||
if (flags & CMD_VERIFY)
|
||||
{
|
||||
ret = hp5590_verify_last_cmd (dn, cmd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* USB-in-USB: initialized bulk read state
|
||||
*
|
||||
* Parameters
|
||||
* state - pointer to a pointer for initialized state
|
||||
*
|
||||
* Returns
|
||||
* SANE_STATUS_GOOD - if state was initialized successfully
|
||||
* SANE_STATUS_NO_MEM - memory allocation failed
|
||||
*/
|
||||
static SANE_Status
|
||||
hp5590_low_init_bulk_read_state (void **state)
|
||||
{
|
||||
struct bulk_read_state *bulk_read_state;
|
||||
|
||||
DBG (3, "%s: USB-in-USB: initializing bulk read state\n", __FUNCTION__);
|
||||
|
||||
hp5590_low_assert (state != NULL);
|
||||
|
||||
bulk_read_state = malloc (sizeof (struct bulk_read_state));
|
||||
if (!bulk_read_state)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
memset (bulk_read_state, 0, sizeof (struct bulk_read_state));
|
||||
|
||||
bulk_read_state->buffer = malloc (ALLOCATE_BULK_READ_PAGES
|
||||
* BULK_READ_PAGE_SIZE);
|
||||
if (!bulk_read_state->buffer)
|
||||
{
|
||||
DBG (DBG_err, "%s: Memory allocation failed for %u bytes\n",
|
||||
__FUNCTION__, ALLOCATE_BULK_READ_PAGES * BULK_READ_PAGE_SIZE);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
bulk_read_state->buffer_size = ALLOCATE_BULK_READ_PAGES
|
||||
* BULK_READ_PAGE_SIZE;
|
||||
bulk_read_state->bytes_available = 0;
|
||||
bulk_read_state->buffer_out_ptr = bulk_read_state->buffer;
|
||||
bulk_read_state->buffer_in_ptr = bulk_read_state->buffer;
|
||||
bulk_read_state->total_pages = 0;
|
||||
bulk_read_state->buffer_end_ptr = bulk_read_state->buffer
|
||||
+ bulk_read_state->buffer_size;
|
||||
bulk_read_state->initialized = 1;
|
||||
|
||||
*state = bulk_read_state;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* USB-in-USB: free bulk read state
|
||||
*
|
||||
* Parameters
|
||||
* state - pointer to a pointer to bulk read state
|
||||
*
|
||||
* Returns
|
||||
* SANE_STATUS_GOOD - bulk read state freed successfully
|
||||
*/
|
||||
static SANE_Status
|
||||
hp5590_low_free_bulk_read_state (void **state)
|
||||
{
|
||||
struct bulk_read_state *bulk_read_state;
|
||||
|
||||
DBG (3, "%s\n", __FUNCTION__);
|
||||
|
||||
hp5590_low_assert (state != NULL);
|
||||
/* Just return if NULL bulk read state was given */
|
||||
if (*state == NULL)
|
||||
return SANE_STATUS_GOOD;
|
||||
|
||||
bulk_read_state = *state;
|
||||
|
||||
DBG (3, "%s: USB-in-USB: freeing bulk read state\n", __FUNCTION__);
|
||||
|
||||
free (bulk_read_state->buffer);
|
||||
bulk_read_state->buffer = NULL;
|
||||
free (bulk_read_state);
|
||||
*state = NULL;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/* FIXME: perhaps needs to be converted to use hp5590_control_msg() */
|
||||
/*******************************************************************************
|
||||
* USB-in-USB: bulk read
|
||||
*
|
||||
* Parameters
|
||||
* dn - sanei_usb device descriptor
|
||||
* bytes - pointer to data buffer
|
||||
* size - size of data to read
|
||||
* state - pointer to initialized bulk read state structure
|
||||
*/
|
||||
static SANE_Status
|
||||
hp5590_bulk_read (SANE_Int dn, unsigned char *bytes, unsigned int size,
|
||||
void *state)
|
||||
{
|
||||
struct usb_bulk_setup ctrl;
|
||||
SANE_Status ret;
|
||||
unsigned int next_pages;
|
||||
u_int8_t bulk_flags;
|
||||
unsigned int next_portion;
|
||||
struct bulk_read_state *bulk_read_state;
|
||||
unsigned int bytes_until_buffer_end;
|
||||
|
||||
DBG (3, "%s\n", __FUNCTION__);
|
||||
|
||||
hp5590_low_assert (state != NULL);
|
||||
hp5590_low_assert (bytes != NULL);
|
||||
|
||||
bulk_read_state = state;
|
||||
if (bulk_read_state->initialized == 0)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: bulk read state not initialized\n",
|
||||
__FUNCTION__);
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
memset (bytes, 0, size);
|
||||
|
||||
/* Check if requested data would fit into the buffer */
|
||||
if (size > bulk_read_state->buffer_size)
|
||||
{
|
||||
DBG (DBG_err, "Data requested won't fit in the bulk read buffer "
|
||||
"(requested: %u, buffer size: %u\n", size,
|
||||
bulk_read_state->buffer_size);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
/* Read data until requested size of data will be received */
|
||||
while (bulk_read_state->bytes_available < size)
|
||||
{
|
||||
DBG (DBG_usb, "%s: USB-in-USB: not enough data in buffer available "
|
||||
"(available: %u, requested: %u)\n",
|
||||
__FUNCTION__, bulk_read_state->bytes_available, size);
|
||||
|
||||
/* IMPORTANT! 'next_pages' means 'request and receive next_pages pages in
|
||||
* one bulk transfer request '. Windows driver uses 4 pages between each
|
||||
* request. The more pages are received between requests the less the
|
||||
* scanner does scan head re-positioning thus improving scanning speed.
|
||||
* On the other hand, scanner expects that all of the requested pages
|
||||
* will be received immediately after the request. In case when a
|
||||
* frontend will have a delay between reads we will get bulk transfer
|
||||
* timeout sooner or later.
|
||||
* Having next_pages = 1 is the most safe case.
|
||||
*/
|
||||
next_pages = 1;
|
||||
/* Count all received pages to calculate when we will need to send
|
||||
* another bulk request
|
||||
*/
|
||||
bulk_read_state->total_pages++;
|
||||
DBG (DBG_usb, "%s: USB-in-USB: total pages done: %u\n",
|
||||
__FUNCTION__, bulk_read_state->total_pages);
|
||||
|
||||
/* Send another bulk request for 'next_pages' before first
|
||||
* page or next necessary one
|
||||
*/
|
||||
if ( bulk_read_state->total_pages == 1
|
||||
|| bulk_read_state->total_pages % next_pages == 0)
|
||||
{
|
||||
/* Send bulk flags */
|
||||
DBG (DBG_usb, "%s: USB-in-USB: sending USB-in-USB bulk flags\n",
|
||||
__FUNCTION__);
|
||||
bulk_flags = 0x24;
|
||||
ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x0c, 0x83, 0x00,
|
||||
sizeof (bulk_flags), &bulk_flags);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: error sending bulk flags\n",
|
||||
__FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check acknowledge for bulk flags just sent */
|
||||
DBG (DBG_usb, "%s: USB-in-USB: checking confirmation for bulk flags\n",
|
||||
__FUNCTION__);
|
||||
ret = hp5590_get_ack (dn);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
return ret;
|
||||
|
||||
/* Prepare bulk read request */
|
||||
memset (&ctrl, 0, sizeof (ctrl));
|
||||
ctrl.bRequestType = 0x00;
|
||||
ctrl.bEndpoint = 0x82;
|
||||
ctrl.wLength = htons (next_pages);
|
||||
|
||||
/* Send bulk read request */
|
||||
DBG (DBG_usb, "%s: USB-in-USB: sending control msg for bulk\n",
|
||||
__FUNCTION__);
|
||||
ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x04, 0x82, 0x00,
|
||||
sizeof (ctrl),
|
||||
(unsigned char *) &ctrl);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: error sending control msg\n",
|
||||
__FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check acknowledge for bulk read request */
|
||||
DBG (DBG_usb, "%s: USB-in-USB: checking if control msg was accepted\n",
|
||||
__FUNCTION__);
|
||||
ret = hp5590_get_ack (dn);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
return ret;
|
||||
}
|
||||
|
||||
next_portion = BULK_READ_PAGE_SIZE;
|
||||
/* Check if next page will fit into the buffer */
|
||||
if (bulk_read_state->buffer_size
|
||||
- bulk_read_state->bytes_available < next_portion)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: buffer too small\n", __FUNCTION__);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
/* Bulk read next page */
|
||||
DBG (DBG_usb, "%s: USB-in-USB: bulk reading %u bytes\n",
|
||||
__FUNCTION__, next_portion);
|
||||
ret = sanei_usb_read_bulk (dn,
|
||||
bulk_read_state->buffer_in_ptr,
|
||||
&next_portion);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
{
|
||||
if (ret == SANE_STATUS_EOF)
|
||||
return ret;
|
||||
DBG (DBG_err, "%s: USB-in-USB: error during bulk read: %s\n",
|
||||
__FUNCTION__, sane_strstatus (ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check if we received the same amount of data as requsted */
|
||||
if (next_portion != BULK_READ_PAGE_SIZE)
|
||||
{
|
||||
DBG (DBG_err, "%s: USB-in-USB: incomplete bulk read "
|
||||
"(requested %u bytes, got %u bytes)\n",
|
||||
__FUNCTION__, BULK_READ_PAGE_SIZE, next_portion);
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
|
||||
/* Move pointers to the next position */
|
||||
bulk_read_state->buffer_in_ptr += next_portion;
|
||||
|
||||
/* Check for the end of the buffer */
|
||||
if (bulk_read_state->buffer_in_ptr > bulk_read_state->buffer_end_ptr)
|
||||
{
|
||||
DBG (DBG_err,
|
||||
"%s: USB-in-USB: attempted to access over the end of buffer "
|
||||
"(in_ptr: %p, end_ptr: %p, ptr: %p, buffer size: %u\n",
|
||||
__FUNCTION__, bulk_read_state->buffer_in_ptr,
|
||||
bulk_read_state->buffer_end_ptr, bulk_read_state->buffer,
|
||||
bulk_read_state->buffer_size);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
/* Check for buffer pointer wrapping */
|
||||
if (bulk_read_state->buffer_in_ptr == bulk_read_state->buffer_end_ptr)
|
||||
{
|
||||
DBG (DBG_usb, "%s: USB-in-USB: buffer wrapped while writing\n",
|
||||
__FUNCTION__);
|
||||
bulk_read_state->buffer_in_ptr = bulk_read_state->buffer;
|
||||
}
|
||||
|
||||
/* Count the amount of data we read */
|
||||
bulk_read_state->bytes_available += next_portion;
|
||||
}
|
||||
|
||||
/* Transfer requested amount of data to the caller */
|
||||
DBG (DBG_usb, "%s: USB-in-USB: data in bulk buffer is available "
|
||||
"(requested %u bytes, available %u bytes)\n",
|
||||
__FUNCTION__, size, bulk_read_state->bytes_available);
|
||||
|
||||
/* Check for buffer pointer wrapping */
|
||||
bytes_until_buffer_end = bulk_read_state->buffer_end_ptr
|
||||
- bulk_read_state->buffer_out_ptr;
|
||||
if (bytes_until_buffer_end <= size)
|
||||
{
|
||||
/* First buffer part */
|
||||
DBG (DBG_usb, "%s: USB-in-USB: reached bulk read buffer end\n", __FUNCTION__);
|
||||
memcpy (bytes, bulk_read_state->buffer_out_ptr, bytes_until_buffer_end);
|
||||
bulk_read_state->buffer_out_ptr = bulk_read_state->buffer;
|
||||
/* And second part (if any) */
|
||||
if (bytes_until_buffer_end < size)
|
||||
{
|
||||
DBG (DBG_usb, "%s: USB-in-USB: giving 2nd buffer part\n", __FUNCTION__);
|
||||
memcpy (bytes + bytes_until_buffer_end,
|
||||
bulk_read_state->buffer_out_ptr,
|
||||
size - bytes_until_buffer_end);
|
||||
bulk_read_state->buffer_out_ptr += size - bytes_until_buffer_end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The data is in one buffer part (w/o wrapping) */
|
||||
memcpy (bytes, bulk_read_state->buffer_out_ptr, size);
|
||||
bulk_read_state->buffer_out_ptr += size;
|
||||
if (bulk_read_state->buffer_out_ptr == bulk_read_state->buffer_end_ptr)
|
||||
{
|
||||
DBG (DBG_usb, "%s: USB-in-USB: buffer wrapped while reading\n",
|
||||
__FUNCTION__);
|
||||
bulk_read_state->buffer_out_ptr = bulk_read_state->buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/* Count the amount of data transferred to the caller */
|
||||
bulk_read_state->bytes_available -= size;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* USB-in-USB: bulk write
|
||||
*
|
||||
* Parameters
|
||||
* dn - sanei_usb device descriptor
|
||||
* cmd - command for bulk write operation
|
||||
* bytes - pointer to data buffer
|
||||
* size - size of data
|
||||
*
|
||||
* Returns
|
||||
* SANE_STATUS_GOOD - all data transferred successfully
|
||||
* all other SANE_Status value - otherwise
|
||||
*/
|
||||
static SANE_Status
|
||||
hp5590_bulk_write (SANE_Int dn, int cmd, unsigned char *bytes,
|
||||
unsigned int size)
|
||||
{
|
||||
struct usb_bulk_setup ctrl;
|
||||
SANE_Status ret;
|
||||
struct bulk_size bulk_size;
|
||||
|
||||
unsigned int len;
|
||||
unsigned char *ptr;
|
||||
unsigned int next_portion;
|
||||
|
||||
DBG (3, "%s: USB-in-USB: command: %04x, size %u\n", __FUNCTION__, cmd,
|
||||
size);
|
||||
|
||||
hp5590_low_assert (bytes != NULL);
|
||||
|
||||
/* Prepare bulk write request */
|
||||
memset (&bulk_size, 0, sizeof (bulk_size));
|
||||
/* Counted in page size */
|
||||
bulk_size.size = size / BULK_WRITE_PAGE_SIZE;
|
||||
|
||||
/* Send bulk write request */
|
||||
DBG (3, "%s: USB-in-USB: total %u pages (each of %u bytes)\n",
|
||||
__FUNCTION__, bulk_size.size, BULK_WRITE_PAGE_SIZE);
|
||||
ret = hp5590_control_msg (dn, USB_DIR_OUT,
|
||||
0x04, cmd, 0,
|
||||
(unsigned char *) &bulk_size, sizeof (bulk_size),
|
||||
CORE_DATA | CORE_BULK_OUT);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
return ret;
|
||||
|
||||
len = size;
|
||||
ptr = bytes;
|
||||
|
||||
/* Send all data in pages */
|
||||
while (len)
|
||||
{
|
||||
next_portion = BULK_WRITE_PAGE_SIZE;
|
||||
if (len < next_portion)
|
||||
next_portion = len;
|
||||
|
||||
DBG (3, "%s: USB-in-USB: next portion %u bytes\n",
|
||||
__FUNCTION__, next_portion);
|
||||
|
||||
/* Prepare bulk write request */
|
||||
memset (&ctrl, 0, sizeof (ctrl));
|
||||
ctrl.bRequestType = 0x01;
|
||||
ctrl.bEndpoint = 0x82;
|
||||
ctrl.wLength = htons (next_portion);
|
||||
|
||||
/* Send bulk write request */
|
||||
ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x04, 0x82, 0,
|
||||
sizeof (ctrl), (unsigned char *) &ctrl);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
return ret;
|
||||
|
||||
/* Check acknowledge for bulk write request */
|
||||
DBG (DBG_usb, "%s: USB-in-USB: checking if command was accepted\n",
|
||||
__FUNCTION__);
|
||||
ret = hp5590_get_ack (dn);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
return ret;
|
||||
|
||||
/* Write bulk data */
|
||||
DBG (3, "%s: USB-in-USB: bulk writing %u bytes\n",
|
||||
__FUNCTION__, next_portion);
|
||||
ret = sanei_usb_write_bulk (dn, ptr, &next_portion);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
{
|
||||
/* Treast EOF as successful result */
|
||||
if (ret == SANE_STATUS_EOF)
|
||||
break;
|
||||
DBG (DBG_err, "%s: USB-in-USB: error during bulk write: %s\n",
|
||||
__FUNCTION__, sane_strstatus (ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Move to the next page */
|
||||
len -= next_portion;
|
||||
ptr += next_portion;
|
||||
}
|
||||
|
||||
/* Verify bulk command */
|
||||
return hp5590_verify_last_cmd (dn, cmd);
|
||||
}
|
||||
/* vim: sw=2 ts=8
|
||||
*/
|
|
@ -0,0 +1,77 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
Copyright (C) 2007 Ilia Sotnikov <hostcc@gmail.com>
|
||||
This file is part of the SANE package.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
|
||||
As a special exception, the authors of SANE give permission for
|
||||
additional uses of the libraries contained in this release of SANE.
|
||||
|
||||
The exception is that, if you link a SANE library with other files
|
||||
to produce an executable, this does not by itself cause the
|
||||
resulting executable to be covered by the GNU General Public
|
||||
License. Your use of that executable is in no way restricted on
|
||||
account of linking the SANE library code into it.
|
||||
|
||||
This exception does not, however, invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public
|
||||
License.
|
||||
|
||||
If you submit changes to SANE to the maintainers to be included in
|
||||
a subsequent release, you agree by submitting the changes that
|
||||
those changes may be distributed with this exception intact.
|
||||
|
||||
If you write modifications of your own for SANE, it is your choice
|
||||
whether to permit this exception to apply to your modifications.
|
||||
If you do not wish that, delete this exception notice.
|
||||
|
||||
This file is part of a SANE backend for HP 5550/5590/7650 Scanners
|
||||
*/
|
||||
|
||||
#ifndef HP5590_LOW_H
|
||||
#define HP5590_LOW_H
|
||||
|
||||
#include "sane/sane.h"
|
||||
|
||||
/* Flags for hp5590_cmd() */
|
||||
#define CMD_IN 1 << 0 /* Indicates IN direction, otherwise - OUT */
|
||||
#define CMD_VERIFY 1 << 1 /* Requests last command verification */
|
||||
|
||||
/* Core flags for hp5590_cmd() - they indicate so called CORE commands */
|
||||
#define CORE_NONE 0 /* No CORE operation */
|
||||
#define CORE_DATA 1 << 0 /* Operate on CORE data */
|
||||
#define CORE_BULK_IN 1 << 1 /* CORE bulk operation - prepare for bulk IN
|
||||
* transfer (not used yet)
|
||||
*/
|
||||
#define CORE_BULK_OUT 1 << 2 /* CORE bulk operation - prepare for bulk OUT
|
||||
* transfer
|
||||
*/
|
||||
static SANE_Status hp5590_cmd (SANE_Int dn,
|
||||
unsigned int flags,
|
||||
unsigned int cmd, unsigned char *data,
|
||||
unsigned int size, unsigned int core_flags);
|
||||
static SANE_Status hp5590_bulk_read (SANE_Int dn,
|
||||
unsigned char *bytes,
|
||||
unsigned int size, void *state);
|
||||
static SANE_Status hp5590_bulk_write (SANE_Int dn, int cmd,
|
||||
unsigned char *bytes,
|
||||
unsigned int size);
|
||||
static SANE_Status hp5590_get_status (SANE_Int dn);
|
||||
static SANE_Status hp5590_low_init_bulk_read_state (void **state);
|
||||
static SANE_Status hp5590_low_free_bulk_read_state (void **state);
|
||||
#endif /* HP5590_LOW_H */
|
||||
/* vim: sw=2 ts=8
|
||||
*/
|
|
@ -0,0 +1,62 @@
|
|||
.TH sane-hp5590 5 "9 Apr 2007" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
|
||||
.IX sane-hp5590
|
||||
.SH NAME
|
||||
sane-hp5590 \- SANE backend for Hewlett-Packard 5550/5590/7650 Workgroup/Document scanners
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.B sane-hp5590
|
||||
library implements a SANE (Scanner Access Now Easy) backend that provides
|
||||
access to the following Hewlett-Packard Workgroup/Document scanners:
|
||||
.PP
|
||||
.RS
|
||||
ScanJet 5550
|
||||
.br
|
||||
ScanJet 5590
|
||||
.br
|
||||
ScanJet 7650
|
||||
.RE
|
||||
.PP
|
||||
If you own a scanner other than the ones listed above that works with this
|
||||
backend, please let us know this by sending the scanner's exact model name and
|
||||
the USB vendor and device ids (e.g. from
|
||||
.IR /proc/bus/usb/devices ,
|
||||
.I sane-find-scanner
|
||||
or syslog) to us. Even if the scanner's name is only slightly different from
|
||||
the models mentioned above, please let us know.
|
||||
.SH CONFIGURATION
|
||||
None required.
|
||||
.SH FILES
|
||||
.TP
|
||||
.I @LIBDIR@/libsane-hp5590.a
|
||||
The static library implementing this backend.
|
||||
.TP
|
||||
.I @LIBDIR@/libsane-hp5590.so
|
||||
The shared library implementing this backend (present on systems that
|
||||
support dynamic loading).
|
||||
.SH ENVIRONMENT
|
||||
.TP
|
||||
.B SANE_DEBUG_HP5590
|
||||
If the library was compiled with debug support enabled, this
|
||||
environment variable controls the debug level for this backend. Higher
|
||||
debug levels increase the verbosity of the output. See used levels below.
|
||||
.P
|
||||
.RS
|
||||
Level 10 - generic processing
|
||||
.br
|
||||
Level 20 - verbose backend messages
|
||||
.br
|
||||
Level 40 - HP5590 high-level commands
|
||||
.br
|
||||
Level 50 - HP5590 low-level (USB-in-USB) commands
|
||||
|
||||
.P
|
||||
Example:
|
||||
|
||||
export SANE_DEBUG_HP5590=50
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR sane (7),
|
||||
.BR sane-usb (5),
|
||||
|
||||
.SH AUTHOR
|
||||
Ilia Sotnikov <hostcc@gmail.com>
|
Ładowanie…
Reference in New Issue