kopia lustrzana https://gitlab.com/sane-project/backends
* backend/canon_dr.[ch], backend/canon_dr-cmd.h: backend v20
- improved macros for inquiry and set window - shorten inquiry vpd length to match windows driver - remove status-length config option - add padded-read config option - rewrite do_usb_cmd to pad reads and calloc/copy buffers * backend/canon_dr.conf.in: s/status-length/padded-read/gmerge-requests/1/head
rodzic
dc278c2e9f
commit
a50ac53580
|
@ -1,3 +1,12 @@
|
||||||
|
2009-03-23 m. allan noah <kitno455 a t gmail d o t com>
|
||||||
|
* backend/canon_dr.[ch], backend/canon_dr-cmd.h: backend v20
|
||||||
|
- improved macros for inquiry and set window
|
||||||
|
- shorten inquiry vpd length to match windows driver
|
||||||
|
- remove status-length config option
|
||||||
|
- add padded-read config option
|
||||||
|
- rewrite do_usb_cmd to pad reads and calloc/copy buffers
|
||||||
|
* backend/canon_dr.conf.in: s/status-length/padded-read/g
|
||||||
|
|
||||||
2009-03-22 m. allan noah <kitno455 a t gmail d o t com>
|
2009-03-22 m. allan noah <kitno455 a t gmail d o t com>
|
||||||
* backend/canon_dr.[ch]: backend v19
|
* backend/canon_dr.[ch]: backend v19
|
||||||
- pad gray deinterlacing area for DR-2510C
|
- pad gray deinterlacing area for DR-2510C
|
||||||
|
|
|
@ -11,8 +11,7 @@
|
||||||
|
|
||||||
#define USB_HEADER_LEN 12
|
#define USB_HEADER_LEN 12
|
||||||
#define USB_COMMAND_LEN 12
|
#define USB_COMMAND_LEN 12
|
||||||
#define USB_STATUS_LEN_MAX 32
|
#define USB_STATUS_LEN 4
|
||||||
#define USB_STATUS_OFFSET 0
|
|
||||||
#define USB_COMMAND_TIME 30000
|
#define USB_COMMAND_TIME 30000
|
||||||
#define USB_DATA_TIME 30000
|
#define USB_DATA_TIME 30000
|
||||||
#define USB_STATUS_TIME 30000
|
#define USB_STATUS_TIME 30000
|
||||||
|
@ -110,12 +109,11 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
|
||||||
#define INQUIRY_len 6
|
#define INQUIRY_len 6
|
||||||
|
|
||||||
#define INQUIRY_std_len 0x30
|
#define INQUIRY_std_len 0x30
|
||||||
#define INQUIRY_vpd_len 0x28
|
#define INQUIRY_vpd_len 0x1e
|
||||||
|
|
||||||
#define set_IN_evpd(icb, val) setbitfield(icb + 1, 1, 0, val)
|
#define set_IN_evpd(icb, val) setbitfield(icb + 1, 1, 0, val)
|
||||||
#define set_IN_page_code(icb, val) icb[0x02]=val
|
#define set_IN_page_code(icb, val) icb[0x02]=val
|
||||||
#define set_IN_return_size(icb,val) icb[0x04]=val
|
#define set_IN_return_size(icb,val) icb[0x04]=val
|
||||||
#define set_IN_length(out,n) out[0x04]=n-5
|
|
||||||
|
|
||||||
#define get_IN_periph_qual(in) getbitfield(in, 0x07, 5)
|
#define get_IN_periph_qual(in) getbitfield(in, 0x07, 5)
|
||||||
#define IN_periph_qual_lun 0x00
|
#define IN_periph_qual_lun 0x00
|
||||||
|
@ -157,10 +155,10 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
|
||||||
#define get_IN_std_res_1200(in) getbitfield(in+ 0x13, 1, 0)
|
#define get_IN_std_res_1200(in) getbitfield(in+ 0x13, 1, 0)
|
||||||
#define get_IN_window_width(in) getnbyte(in + 0x14, 4)
|
#define get_IN_window_width(in) getnbyte(in + 0x14, 4)
|
||||||
#define get_IN_window_length(in) getnbyte(in + 0x18, 4)
|
#define get_IN_window_length(in) getnbyte(in + 0x18, 4)
|
||||||
#define get_IN_unknown7(in) getbitfield(in+0x1c, 1, 7)
|
#define get_IN_awd(in) getbitfield(in+0x1c, 1, 7)
|
||||||
#define get_IN_unknown6(in) getbitfield(in+0x1c, 1, 6)
|
#define get_IN_ce_emphasis(in) getbitfield(in+0x1c, 1, 6)
|
||||||
#define get_IN_unknown5(in) getbitfield(in+0x1c, 1, 5)
|
#define get_IN_c_emphasis(in) getbitfield(in+0x1c, 1, 5)
|
||||||
#define get_IN_unknown4(in) getbitfield(in+0x1c, 1, 4)
|
#define get_IN_high_quality(in) getbitfield(in+0x1c, 1, 4)
|
||||||
#define get_IN_multilevel(in) getbitfield(in+0x1c, 1, 3)
|
#define get_IN_multilevel(in) getbitfield(in+0x1c, 1, 3)
|
||||||
#define get_IN_half_tone(in) getbitfield(in+0x1c, 1, 2)
|
#define get_IN_half_tone(in) getbitfield(in+0x1c, 1, 2)
|
||||||
#define get_IN_monochrome(in) getbitfield(in+0x1c, 1, 1)
|
#define get_IN_monochrome(in) getbitfield(in+0x1c, 1, 1)
|
||||||
|
@ -427,8 +425,10 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
|
||||||
/* 0x1d - Reverse image, reserved area, padding type */
|
/* 0x1d - Reverse image, reserved area, padding type */
|
||||||
#define set_WD_rif(sb, val) setbitfield(sb + 0x1d, 1, 7, val)
|
#define set_WD_rif(sb, val) setbitfield(sb + 0x1d, 1, 7, val)
|
||||||
#define get_WD_rif(sb) getbitfield(sb + 0x1d, 1, 7)
|
#define get_WD_rif(sb) getbitfield(sb + 0x1d, 1, 7)
|
||||||
#define set_WD_reserved(sb, val) sb[0x1d] = val
|
#define set_WD_rgb(sb, val) setbitfield(sb + 0x1d, 7, 6, val)
|
||||||
#define get_WD_reserved(sb) sb[0x1d]
|
#define get_WD_rgb(sb) getbitfield(sb + 0x1d, 7, 6)
|
||||||
|
#define set_WD_padding(sb, val) setbitfield(sb + 0x1d, 7, 0, val)
|
||||||
|
#define get_WD_padding(sb) getbitfield(sb + 0x1d, 7, 0)
|
||||||
|
|
||||||
/* 0x1e,0x1f - Bit ordering */
|
/* 0x1e,0x1f - Bit ordering */
|
||||||
#define set_WD_bitorder(sb, val) putnbyte(sb + 0x1e, val, 2)
|
#define set_WD_bitorder(sb, val) putnbyte(sb + 0x1e, val, 2)
|
||||||
|
|
|
@ -150,6 +150,12 @@
|
||||||
v19 2009-03-22, MAN
|
v19 2009-03-22, MAN
|
||||||
- pad gray deinterlacing area for DR-2510C
|
- pad gray deinterlacing area for DR-2510C
|
||||||
- override tl_x and br_x for fixed width scanners
|
- override tl_x and br_x for fixed width scanners
|
||||||
|
v20 2009-03-23, MAN
|
||||||
|
- improved macros for inquiry and set window
|
||||||
|
- shorten inquiry vpd length to match windows driver
|
||||||
|
- remove status-length config option
|
||||||
|
- add padded-read config option
|
||||||
|
- rewrite do_usb_cmd to pad reads and calloc/copy buffers
|
||||||
|
|
||||||
SANE FLOW DIAGRAM
|
SANE FLOW DIAGRAM
|
||||||
|
|
||||||
|
@ -210,7 +216,7 @@
|
||||||
#include "canon_dr.h"
|
#include "canon_dr.h"
|
||||||
|
|
||||||
#define DEBUG 1
|
#define DEBUG 1
|
||||||
#define BUILD 19
|
#define BUILD 20
|
||||||
|
|
||||||
/* values for SANE_DEBUG_CANON_DR env var:
|
/* values for SANE_DEBUG_CANON_DR env var:
|
||||||
- errors 5
|
- errors 5
|
||||||
|
@ -259,8 +265,8 @@ static const char string_Back[] = "Back";
|
||||||
/* Also set via config file. */
|
/* Also set via config file. */
|
||||||
static int global_buffer_size;
|
static int global_buffer_size;
|
||||||
static int global_buffer_size_default = 64 * 1024;
|
static int global_buffer_size_default = 64 * 1024;
|
||||||
static int global_status_length;
|
static int global_padded_read;
|
||||||
static int global_status_length_default = 4;
|
static int global_padded_read_default = 0;
|
||||||
static char global_vendor_name[9];
|
static char global_vendor_name[9];
|
||||||
static char global_model_name[17];
|
static char global_model_name[17];
|
||||||
static char global_version_name[5];
|
static char global_version_name[5];
|
||||||
|
@ -409,29 +415,29 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
|
||||||
global_buffer_size = buf;
|
global_buffer_size = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* STATUS: we clamp from 1 to 32 */
|
/* PADDED READ: we clamp to 0 or 1 */
|
||||||
else if (!strncmp (lp, "status-length", 13) && isspace (lp[13])) {
|
else if (!strncmp (lp, "padded-read", 11) && isspace (lp[11])) {
|
||||||
|
|
||||||
int buf;
|
int buf;
|
||||||
lp += 13;
|
lp += 11;
|
||||||
lp = sanei_config_skip_whitespace (lp);
|
lp = sanei_config_skip_whitespace (lp);
|
||||||
buf = atoi (lp);
|
buf = atoi (lp);
|
||||||
|
|
||||||
if (buf < 1) {
|
if (buf < 0) {
|
||||||
DBG (5, "sane_get_devices: config option \"status-length\" "
|
DBG (5, "sane_get_devices: config option \"padded-read\" "
|
||||||
"(%d) is < 1, ignoring!\n", buf);
|
"(%d) is < 0, ignoring!\n", buf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf > 32) {
|
if (buf > 1) {
|
||||||
DBG (5, "sane_get_devices: config option \"status-length\" "
|
DBG (5, "sane_get_devices: config option \"padded-read\" "
|
||||||
"(%d) is > 32, ignoring!\n", buf);
|
"(%d) is > 1, ignoring!\n", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG (15, "sane_get_devices: setting \"status-length\" "
|
DBG (15, "sane_get_devices: setting \"padded-read\" to %d\n",
|
||||||
"to %d\n", buf);
|
buf);
|
||||||
|
|
||||||
global_status_length = buf;
|
global_padded_read = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* VENDOR: we ingest up to 8 bytes */
|
/* VENDOR: we ingest up to 8 bytes */
|
||||||
|
@ -597,7 +603,7 @@ attach_one (const char *device_name, int connType)
|
||||||
|
|
||||||
/* config file settings */
|
/* config file settings */
|
||||||
s->buffer_size = global_buffer_size;
|
s->buffer_size = global_buffer_size;
|
||||||
s->status_length = global_status_length;
|
s->padded_read = global_padded_read;
|
||||||
|
|
||||||
/* copy the device name */
|
/* copy the device name */
|
||||||
strcpy (s->device_name, device_name);
|
strcpy (s->device_name, device_name);
|
||||||
|
@ -958,10 +964,10 @@ init_vpd (struct scanner *s)
|
||||||
s->max_y_basic = get_IN_window_length(in);
|
s->max_y_basic = get_IN_window_length(in);
|
||||||
DBG(15, " max length: %2.2f inches\n",(float)s->max_y_basic/s->basic_y_res);
|
DBG(15, " max length: %2.2f inches\n",(float)s->max_y_basic/s->basic_y_res);
|
||||||
|
|
||||||
DBG (15, " unknown7: %d\n", get_IN_unknown7(in));
|
DBG (15, " AWD: %d\n", get_IN_awd(in));
|
||||||
DBG (15, " unknown6: %d\n", get_IN_unknown6(in));
|
DBG (15, " CE Emphasis: %d\n", get_IN_ce_emphasis(in));
|
||||||
DBG (15, " unknown5: %d\n", get_IN_unknown5(in));
|
DBG (15, " C Emphasis: %d\n", get_IN_c_emphasis(in));
|
||||||
DBG (15, " unknown4: %d\n", get_IN_unknown4(in));
|
DBG (15, " High quality: %d\n", get_IN_high_quality(in));
|
||||||
|
|
||||||
/* known modes */
|
/* known modes */
|
||||||
s->can_grayscale = get_IN_multilevel (in);
|
s->can_grayscale = get_IN_multilevel (in);
|
||||||
|
@ -1035,24 +1041,20 @@ init_model (struct scanner *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* specific settings missing from vpd */
|
/* specific settings missing from vpd */
|
||||||
if (strstr (s->model_name,"DR-9080")){
|
if (strstr (s->model_name,"DR-9080")
|
||||||
|
|| strstr (s->model_name,"DR-7580")){
|
||||||
s->has_comp_JPEG = 1;
|
s->has_comp_JPEG = 1;
|
||||||
s->unknown_byte = 0x20;
|
s->rgb_format = 2;
|
||||||
}
|
|
||||||
|
|
||||||
else if (strstr (s->model_name,"DR-7580")){
|
|
||||||
s->has_comp_JPEG = 1;
|
|
||||||
s->unknown_byte = 0x20;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strstr (s->model_name,"DR-2580")){
|
else if (strstr (s->model_name,"DR-2580")){
|
||||||
s->invert_tly = 1;
|
s->invert_tly = 1;
|
||||||
s->unknown_byte = 0x10;
|
s->rgb_format = 1;
|
||||||
s->has_counter = 1;
|
s->has_counter = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strstr (s->model_name,"DR-2510")){
|
else if (strstr (s->model_name,"DR-2510")){
|
||||||
s->unknown_byte = 0x10;
|
s->rgb_format = 1;
|
||||||
s->unknown_byte2 = 0x80;
|
s->unknown_byte2 = 0x80;
|
||||||
s->has_counter = 1;
|
s->has_counter = 1;
|
||||||
s->head_interlace = HEAD_INTERLACE_2510;
|
s->head_interlace = HEAD_INTERLACE_2510;
|
||||||
|
@ -3145,9 +3147,10 @@ set_window (struct scanner *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
set_WD_rif (desc1, s->rif);
|
set_WD_rif (desc1, s->rif);
|
||||||
|
set_WD_rgb(desc1, s->rgb_format);
|
||||||
|
set_WD_padding(desc1, s->padding);
|
||||||
|
|
||||||
/*FIXME: what is this? */
|
/*FIXME: what is this? */
|
||||||
set_WD_reserved(desc1, s->unknown_byte);
|
|
||||||
set_WD_reserved2(desc1, s->unknown_byte2);
|
set_WD_reserved2(desc1, s->unknown_byte2);
|
||||||
|
|
||||||
set_WD_compress_type(desc1, COMP_NONE);
|
set_WD_compress_type(desc1, COMP_NONE);
|
||||||
|
@ -3996,7 +3999,7 @@ static void
|
||||||
default_globals(void)
|
default_globals(void)
|
||||||
{
|
{
|
||||||
global_buffer_size = global_buffer_size_default;
|
global_buffer_size = global_buffer_size_default;
|
||||||
global_status_length = global_status_length_default;
|
global_padded_read = global_padded_read_default;
|
||||||
global_vendor_name[0] = 0;
|
global_vendor_name[0] = 0;
|
||||||
global_model_name[0] = 0;
|
global_model_name[0] = 0;
|
||||||
global_version_name[0] = 0;
|
global_version_name[0] = 0;
|
||||||
|
@ -4330,164 +4333,216 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime,
|
||||||
unsigned char * inBuff, size_t * inLen
|
unsigned char * inBuff, size_t * inLen
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/*sanei_usb overwrites the transfer size,
|
size_t offset;
|
||||||
* so make some local copies */
|
size_t length;
|
||||||
size_t usb_cmdLen = USB_HEADER_LEN + USB_COMMAND_LEN;
|
size_t actual;
|
||||||
size_t usb_outLen = USB_HEADER_LEN + outLen;
|
unsigned char * buffer;
|
||||||
size_t usb_statLen = s->status_length;
|
int timeout;
|
||||||
size_t askLen = 0;
|
|
||||||
|
|
||||||
/*copy the callers buffs into larger, padded ones*/
|
|
||||||
unsigned char usb_cmdBuff[USB_HEADER_LEN + USB_COMMAND_LEN];
|
|
||||||
unsigned char * usb_outBuff;
|
|
||||||
unsigned char usb_statBuff[USB_STATUS_LEN_MAX];
|
|
||||||
|
|
||||||
int cmdTime = USB_COMMAND_TIME;
|
|
||||||
int outTime = USB_DATA_TIME;
|
|
||||||
int inTime = USB_DATA_TIME;
|
|
||||||
int statTime = USB_STATUS_TIME;
|
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int ret2 = 0;
|
int ret2 = 0;
|
||||||
|
|
||||||
DBG (10, "do_usb_cmd: start\n");
|
DBG (10, "do_usb_cmd: start\n");
|
||||||
|
|
||||||
if(shortTime){
|
/****************************************************************/
|
||||||
cmdTime = USB_COMMAND_TIME/60;
|
/* the command stage */
|
||||||
outTime = USB_DATA_TIME/60;
|
{
|
||||||
inTime = USB_DATA_TIME/60;
|
offset = USB_HEADER_LEN;
|
||||||
statTime = USB_STATUS_TIME/60;
|
length = offset+USB_COMMAND_LEN;
|
||||||
}
|
actual = length;
|
||||||
|
timeout = USB_COMMAND_TIME;
|
||||||
|
|
||||||
/* build a USB packet around the SCSI command */
|
/* change timeout */
|
||||||
memset(&usb_cmdBuff,0,usb_cmdLen);
|
if(shortTime)
|
||||||
usb_cmdBuff[3] = usb_cmdLen-4;
|
timeout/=60;
|
||||||
usb_cmdBuff[5] = 1;
|
sanei_usb_set_timeout(timeout);
|
||||||
usb_cmdBuff[6] = 0x90;
|
|
||||||
memcpy(usb_cmdBuff+USB_HEADER_LEN,cmdBuff,cmdLen);
|
|
||||||
|
|
||||||
/* change timeout */
|
/* build buffer */
|
||||||
sanei_usb_set_timeout(cmdTime);
|
buffer = calloc(length,1);
|
||||||
|
if(!buffer){
|
||||||
/* write the command out */
|
DBG(5,"cmd: no mem\n");
|
||||||
DBG(25, "cmd: writing %d bytes, timeout %d\n", (int)usb_cmdLen,
|
|
||||||
cmdTime);
|
|
||||||
hexdump(30, "cmd: >>", usb_cmdBuff, usb_cmdLen);
|
|
||||||
ret = sanei_usb_write_bulk(s->fd, usb_cmdBuff, &usb_cmdLen);
|
|
||||||
DBG(25, "cmd: wrote %d bytes, retVal %d\n", (int)usb_cmdLen, ret);
|
|
||||||
|
|
||||||
if(ret == SANE_STATUS_EOF){
|
|
||||||
DBG(5,"cmd: got EOF, returning IO_ERROR\n");
|
|
||||||
return SANE_STATUS_IO_ERROR;
|
return SANE_STATUS_IO_ERROR;
|
||||||
}
|
}
|
||||||
if(ret != SANE_STATUS_GOOD){
|
|
||||||
DBG(5,"cmd: return error '%s'\n",sane_strstatus(ret));
|
/* build a USB packet around the SCSI command */
|
||||||
|
buffer[3] = length-4;
|
||||||
|
buffer[5] = 1;
|
||||||
|
buffer[6] = 0x90;
|
||||||
|
memcpy(buffer+offset,cmdBuff,cmdLen);
|
||||||
|
|
||||||
|
/* write the command out */
|
||||||
|
DBG(25, "cmd: writing %d bytes, timeout %d\n", (int)length, timeout);
|
||||||
|
hexdump(30, "cmd: >>", buffer, length);
|
||||||
|
ret = sanei_usb_write_bulk(s->fd, buffer, &actual);
|
||||||
|
DBG(25, "cmd: wrote %d bytes, retVal %d\n", (int)actual, ret);
|
||||||
|
|
||||||
|
if(length != actual){
|
||||||
|
DBG(5,"cmd: wrong size %d/%d\n", (int)length, (int)actual);
|
||||||
|
free(buffer);
|
||||||
|
return SANE_STATUS_IO_ERROR;
|
||||||
|
}
|
||||||
|
if(ret != SANE_STATUS_GOOD){
|
||||||
|
DBG(5,"cmd: write error '%s'\n",sane_strstatus(ret));
|
||||||
|
free(buffer);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
}
|
}
|
||||||
if(usb_cmdLen != USB_HEADER_LEN + USB_COMMAND_LEN){
|
|
||||||
DBG(5,"cmd: wrong size %d/%d\n", USB_COMMAND_LEN, (int)usb_cmdLen);
|
/****************************************************************/
|
||||||
|
/* the output stage */
|
||||||
|
if(outBuff && outLen){
|
||||||
|
|
||||||
|
offset = USB_HEADER_LEN;
|
||||||
|
length = offset+outLen;
|
||||||
|
actual = length;
|
||||||
|
timeout = USB_DATA_TIME;
|
||||||
|
|
||||||
|
/* change timeout */
|
||||||
|
if(shortTime)
|
||||||
|
timeout/=60;
|
||||||
|
sanei_usb_set_timeout(timeout);
|
||||||
|
|
||||||
|
/* build buffer */
|
||||||
|
buffer = calloc(length,1);
|
||||||
|
if(!buffer){
|
||||||
|
DBG(5,"out: no mem\n");
|
||||||
return SANE_STATUS_IO_ERROR;
|
return SANE_STATUS_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* build a USB packet around the SCSI command */
|
||||||
|
buffer[3] = length-4;
|
||||||
|
buffer[5] = 2;
|
||||||
|
buffer[6] = 0xb0;
|
||||||
|
memcpy(buffer+offset,outBuff,outLen);
|
||||||
|
|
||||||
|
/* write the command out */
|
||||||
|
DBG(25, "out: writing %d bytes, timeout %d\n", (int)length, timeout);
|
||||||
|
hexdump(30, "out: >>", buffer, length);
|
||||||
|
ret = sanei_usb_write_bulk(s->fd, buffer, &actual);
|
||||||
|
DBG(25, "out: wrote %d bytes, retVal %d\n", (int)actual, ret);
|
||||||
|
|
||||||
|
if(length != actual){
|
||||||
|
DBG(5,"out: wrong size %d/%d\n", (int)length, (int)actual);
|
||||||
|
free(buffer);
|
||||||
|
return SANE_STATUS_IO_ERROR;
|
||||||
|
}
|
||||||
|
if(ret != SANE_STATUS_GOOD){
|
||||||
|
DBG(5,"out: write error '%s'\n",sane_strstatus(ret));
|
||||||
|
free(buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this command has a write component, and a place to get it */
|
/****************************************************************/
|
||||||
if(outBuff && outLen && outTime){
|
/* the input stage */
|
||||||
|
if(inBuff && inLen){
|
||||||
|
|
||||||
usb_outBuff = calloc(usb_outLen,1);
|
offset = 0;
|
||||||
if(!usb_outBuff){
|
if(s->padded_read)
|
||||||
DBG(5,"out: no mem\n");
|
offset = USB_HEADER_LEN;
|
||||||
return SANE_STATUS_IO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
usb_outBuff[3] = usb_outLen-4;
|
length = offset+*inLen;
|
||||||
usb_outBuff[5] = 2;
|
actual = length;
|
||||||
usb_outBuff[6] = 0xb0;
|
timeout = USB_DATA_TIME;
|
||||||
memcpy(usb_outBuff+USB_HEADER_LEN,outBuff,outLen);
|
|
||||||
|
|
||||||
/* change timeout */
|
/* change timeout */
|
||||||
sanei_usb_set_timeout(outTime);
|
if(shortTime)
|
||||||
|
timeout/=60;
|
||||||
|
sanei_usb_set_timeout(timeout);
|
||||||
|
|
||||||
DBG(25, "out: writing %d bytes, timeout %d\n", (int)usb_outLen, outTime);
|
/* build buffer */
|
||||||
hexdump(30, "out: >>", usb_outBuff, usb_outLen);
|
buffer = calloc(length,1);
|
||||||
ret = sanei_usb_write_bulk(s->fd, usb_outBuff, &usb_outLen);
|
if(!buffer){
|
||||||
DBG(25, "out: wrote %d bytes, retVal %d\n", (int)usb_outLen, ret);
|
DBG(5,"in: no mem\n");
|
||||||
|
return SANE_STATUS_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG(25, "in: reading %d bytes, timeout %d\n", (int)length, timeout);
|
||||||
|
ret = sanei_usb_read_bulk(s->fd, buffer, &actual);
|
||||||
|
DBG(25, "in: read %d bytes, retval %d\n", (int)actual, ret);
|
||||||
|
hexdump(30, "in: <<", buffer, actual);
|
||||||
|
|
||||||
if(ret == SANE_STATUS_EOF){
|
if(!actual){
|
||||||
DBG(5,"out: got EOF, returning IO_ERROR\n");
|
*inLen = 0;
|
||||||
free(usb_outBuff);
|
DBG(5,"in: got no data, clearing\n");
|
||||||
return SANE_STATUS_IO_ERROR;
|
free(buffer);
|
||||||
}
|
|
||||||
if(ret != SANE_STATUS_GOOD){
|
|
||||||
DBG(5,"out: return error '%s'\n",sane_strstatus(ret));
|
|
||||||
free(usb_outBuff);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if(usb_outLen != outLen + USB_HEADER_LEN){
|
|
||||||
DBG(5,"out: wrong size %d/%d\n", (int)outLen, (int)usb_outLen);
|
|
||||||
free(usb_outBuff);
|
|
||||||
return SANE_STATUS_IO_ERROR;
|
|
||||||
}
|
|
||||||
free(usb_outBuff);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this command has a read component, and a place to put it */
|
|
||||||
if(inBuff && inLen && inTime){
|
|
||||||
|
|
||||||
askLen = *inLen;
|
|
||||||
memset(inBuff,0,askLen);
|
|
||||||
|
|
||||||
/* change timeout */
|
|
||||||
sanei_usb_set_timeout(inTime);
|
|
||||||
|
|
||||||
DBG(25, "in: reading %d bytes, timeout %d\n", (int)askLen, inTime);
|
|
||||||
|
|
||||||
ret = sanei_usb_read_bulk(s->fd, inBuff, inLen);
|
|
||||||
DBG(25, "in: read %d bytes, retval %d\n", (int)*inLen, ret);
|
|
||||||
hexdump(30, "in: <<", inBuff, *inLen);
|
|
||||||
|
|
||||||
if(!*inLen){
|
|
||||||
DBG(5,"in: got no data, clearing\n");
|
|
||||||
return do_usb_clear(s,runRS);
|
|
||||||
}
|
|
||||||
if(ret != SANE_STATUS_GOOD){
|
|
||||||
DBG(5,"in: return error '%s'\n",sane_strstatus(ret));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if(*inLen != askLen){
|
|
||||||
ret = SANE_STATUS_EOF;
|
|
||||||
DBG(5,"in: wrong size, %d/%d\n", (int)*inLen,(int)askLen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*gather the scsi status byte. use ret2 instead of ret for status*/
|
|
||||||
memset(&usb_statBuff,0,USB_STATUS_LEN_MAX);
|
|
||||||
|
|
||||||
/* change timeout */
|
|
||||||
sanei_usb_set_timeout(statTime);
|
|
||||||
|
|
||||||
DBG(25, "stat: reading %d bytes, timeout %d\n", (int)usb_statLen, statTime);
|
|
||||||
ret2 = sanei_usb_read_bulk(s->fd, usb_statBuff, &usb_statLen);
|
|
||||||
DBG(25, "stat: read %d bytes, retVal %d\n", (int)usb_statLen, ret2);
|
|
||||||
hexdump(30, "stat: <<", usb_statBuff, usb_statLen);
|
|
||||||
|
|
||||||
if(!usb_statLen){
|
|
||||||
DBG(5,"stat: got no data, clearing\n");
|
|
||||||
return do_usb_clear(s,runRS);
|
return do_usb_clear(s,runRS);
|
||||||
}
|
}
|
||||||
if(ret2 != SANE_STATUS_GOOD){
|
if(actual < offset){
|
||||||
DBG(5,"stat: return error '%s'\n",sane_strstatus(ret2));
|
*inLen = 0;
|
||||||
return ret2;
|
DBG(5,"in: read shorter than offset\n");
|
||||||
}
|
free(buffer);
|
||||||
if(usb_statLen != (size_t)s->status_length){
|
|
||||||
DBG(5,"stat: wrong size %d/%d\n", s->status_length, (int)usb_statLen);
|
|
||||||
return SANE_STATUS_IO_ERROR;
|
return SANE_STATUS_IO_ERROR;
|
||||||
|
}
|
||||||
|
if(ret != SANE_STATUS_GOOD){
|
||||||
|
*inLen = 0;
|
||||||
|
DBG(5,"in: return error '%s'\n",sane_strstatus(ret));
|
||||||
|
free(buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(length != actual){
|
||||||
|
ret = SANE_STATUS_EOF;
|
||||||
|
DBG(5,"in: short read, %d/%d\n", (int)length,(int)actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ignore the USB packet around the SCSI command */
|
||||||
|
*inLen = actual - offset;
|
||||||
|
memcpy(inBuff,buffer+offset,*inLen);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: interpret the status fields
|
/****************************************************************/
|
||||||
if(usb_statBuff[0] || usb_statBuff[1] || usb_statBuff[2] || usb_statBuff[3]){
|
/* the status stage */
|
||||||
DBG(25,"stat: bad stat?\n");
|
{
|
||||||
return SANE_STATUS_IO_ERROR;
|
offset = 0;
|
||||||
|
if(s->padded_read)
|
||||||
|
offset = USB_HEADER_LEN;
|
||||||
|
|
||||||
|
length = offset+USB_STATUS_LEN;
|
||||||
|
actual = length;
|
||||||
|
timeout = USB_STATUS_TIME;
|
||||||
|
|
||||||
|
/* change timeout */
|
||||||
|
if(shortTime)
|
||||||
|
timeout/=60;
|
||||||
|
sanei_usb_set_timeout(timeout);
|
||||||
|
|
||||||
|
/* build buffer */
|
||||||
|
buffer = calloc(length,1);
|
||||||
|
if(!buffer){
|
||||||
|
DBG(5,"stat: no mem\n");
|
||||||
|
return SANE_STATUS_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG(25, "stat: reading %d bytes, timeout %d\n", (int)length, timeout);
|
||||||
|
ret2 = sanei_usb_read_bulk(s->fd, buffer, &actual);
|
||||||
|
DBG(25, "stat: read %d bytes, retval %d\n", (int)actual, ret2);
|
||||||
|
hexdump(30, "stat: <<", buffer, actual);
|
||||||
|
|
||||||
|
if(!actual){
|
||||||
|
DBG(5,"stat: got no data, clearing\n");
|
||||||
|
free(buffer);
|
||||||
|
return do_usb_clear(s,runRS);
|
||||||
|
}
|
||||||
|
if(ret2 != SANE_STATUS_GOOD){
|
||||||
|
DBG(5,"stat: return error '%s'\n",sane_strstatus(ret2));
|
||||||
|
free(buffer);
|
||||||
|
return ret2;
|
||||||
|
}
|
||||||
|
if(length != actual){
|
||||||
|
DBG(5,"stat: short read, %d/%d\n",(int)length,(int)actual);
|
||||||
|
free(buffer);
|
||||||
|
return SANE_STATUS_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*FIXME: inspect the status response?*/
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
DBG (10, "do_usb_cmd: finish\n");
|
DBG (10, "do_usb_cmd: finish\n");
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
#option buffer-size 65536
|
#option buffer-size 65536
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# Most scanners use a 4 byte status, but some use 16
|
# Most scanners dont pad their reads
|
||||||
#option status-length 4
|
#option padded-read 0
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# SCSI scanners:
|
# SCSI scanners:
|
||||||
|
@ -46,10 +46,10 @@ scsi CANON DR
|
||||||
# gmail dot com - with canon_dr in the subject line
|
# gmail dot com - with canon_dr in the subject line
|
||||||
|
|
||||||
# DR-2080C (uses weird protocol)
|
# DR-2080C (uses weird protocol)
|
||||||
option vendor-name CANON
|
option vendor-name CANON
|
||||||
option model-name DR-2080C
|
option model-name DR-2080C
|
||||||
option version-name XXXX
|
option version-name XXXX
|
||||||
option status-length 16
|
option padded-read 1
|
||||||
usb 0x04a9 0x1601
|
usb 0x04a9 0x1601
|
||||||
|
|
||||||
# CR-180
|
# CR-180
|
||||||
|
@ -74,10 +74,10 @@ usb 0x04a9 0x1608
|
||||||
usb 0x04a9 0x1609
|
usb 0x04a9 0x1609
|
||||||
|
|
||||||
# DR-2050C/SP (uses weird protocol)
|
# DR-2050C/SP (uses weird protocol)
|
||||||
option vendor-name CANON
|
option vendor-name CANON
|
||||||
option model-name DR-2050C
|
option model-name DR-2050C
|
||||||
option version-name XXXX
|
option version-name XXXX
|
||||||
option status-length 16
|
option padded-read 1
|
||||||
usb 0x04a9 0x160a
|
usb 0x04a9 0x160a
|
||||||
|
|
||||||
# DR-7580
|
# DR-7580
|
||||||
|
|
|
@ -143,12 +143,13 @@ struct scanner
|
||||||
int has_back; /* not all duplex scanners can do adf back side only */
|
int has_back; /* not all duplex scanners can do adf back side only */
|
||||||
int has_comp_JPEG;
|
int has_comp_JPEG;
|
||||||
int has_buffer;
|
int has_buffer;
|
||||||
|
int rgb_format; /* meaning unknown */
|
||||||
|
int padding; /* meaning unknown */
|
||||||
|
|
||||||
int invert_tly; /* weird bug in some smaller scanners */
|
int invert_tly; /* weird bug in some smaller scanners */
|
||||||
int unknown_byte; /* weird byte, required, meaning unknown */
|
|
||||||
int unknown_byte2; /* weird byte, required, meaning unknown */
|
int unknown_byte2; /* weird byte, required, meaning unknown */
|
||||||
size_t status_length; /* usually 4, sometimes 16 */
|
int padded_read; /* some machines need extra 12 bytes on reads */
|
||||||
int fixed_width; /* sometime machines always scan full width */
|
int fixed_width; /* some machines always scan full width */
|
||||||
|
|
||||||
int color_interlace; /* different models interlace colors differently */
|
int color_interlace; /* different models interlace colors differently */
|
||||||
int duplex_interlace; /* different models interlace sides differently */
|
int duplex_interlace; /* different models interlace sides differently */
|
||||||
|
|
Ładowanie…
Reference in New Issue