patch from <ron@roncemer.com>

fi4220 support
usb support
merge-requests/1/head
Oliver Schirrmeister 2003-02-20 13:33:07 +00:00
rodzic 748037c18b
commit d74d4231ce
8 zmienionych plików z 428 dodań i 102 usunięć

Wyświetl plik

@ -1,3 +1,9 @@
2003-02-20 Oliver Schirrmeister <oschirr@abm.de>
* patch from <ron@roncemer.com>:
fi4220 support
USB support for scanners which send SCSI commands over usb
2003-02-19 Henning Meier-Geinitz <henning@meier-geinitz.de>
* doc/descriptions-external/ma1509.desc: Added description of the

Wyświetl plik

@ -302,6 +302,7 @@ libsane-epson.la: ../sanei/sanei_pio.lo
libsane-fujitsu.la: ../sanei/sanei_config2.lo
libsane-fujitsu.la: ../sanei/sanei_constrain_value.lo
libsane-fujitsu.la: ../sanei/sanei_scsi.lo
libsane-fujitsu.la: ../sanei/sanei_usb.lo
libsane-gphoto2.la: ../sanei/sanei_constrain_value.lo djpeg.lo
libsane-gt68xx.la: ../sanei/sanei_constrain_value.lo
libsane-gt68xx.la: ../sanei/sanei_usb.lo

Wyświetl plik

@ -228,6 +228,16 @@ static unsigned char set_windowC[] =
{ SET_WINDOW, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
/* opcode, lun, _____4 X reserved____, transfer length, control byte */
static scsiblk set_windowB = { set_windowC, sizeof (set_windowC) };
#define set_SW_xferlen(sb, len) putnbyte(sb + 0x06, len, 3)
/* With the fi-series scanners, we have to use a 12-byte command
* instead of a 10-byte command when communicating via USB. This
* may be a firmware bug. */
static unsigned char set_usb_windowC[] =
{ SET_WINDOW, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00 };
/* opcode, lun, _____4 X reserved____, transfer length, control byte */
static scsiblk set_usb_windowB = { set_usb_windowC, sizeof (set_usb_windowC) };
#define set_SW_xferlen(sb, len) putnbyte(sb + 0x06, len, 3)
/* ==================================================================== */
@ -378,6 +388,17 @@ static scsiblk mode_select_headerB = {
};
/* With the fi-series scanners, we have to use a 10-byte header
* instead of a 4-byte header when communicating via USB. This
* may be a firmware bug. */
static unsigned char mode_select_usb_headerC[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static scsiblk mode_select_usb_headerB = {
mode_select_usb_headerC, sizeof (mode_select_usb_headerC)
};
static unsigned char mode_select_parameter_blockC[] = {
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,

Wyświetl plik

@ -77,6 +77,10 @@
- 3092 support (mgoppold@tbz-pariv.de)
- tested 4097 support
- changed some functions to receive compressed data
V 1.4, 13-Feb-2003
- fi-4220C support (ron@roncemer.com)
- USB support for scanners which send SCSI commands over usb
(ron@roncemer.com)
SANE FLOW DIAGRAM
@ -124,6 +128,7 @@
#include "sane/sanei_backend.h"
#include "sane/sanei_scsi.h"
#include "sane/sanei_usb.h"
#include "sane/saneopts.h"
#include "sane/sanei_config.h"
@ -337,6 +342,11 @@ static struct fujitsu *current_scanner;
*/
static const SANE_Device **devlist = 0;
/*
* used by attachScanner and attachOne
*/
static Fujitsu_Connection_Type mostRecentConfigConnectionType = SANE_FUJITSU_SCSI;
/*
* @@ Section 2 - SANE Interface
*/
@ -364,11 +374,14 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
size_t len;
FILE *fp;
mostRecentConfigConnectionType = SANE_FUJITSU_SCSI;
authorize = authorize; /* get rid of compiler warning */
DBG_INIT ();
DBG (10, "sane_init\n");
sanei_usb_init();
if (version_code)
*version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, 0);
fp = sanei_config_open (FUJITSU_CONFIG_FILE);
@ -393,6 +406,7 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
while (sanei_config_read (line, PATH_MAX, fp))
{
int vendor, product;
/* ignore comments */
if (line[0] == '#')
@ -457,11 +471,23 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
lp);
}
}
else /* must be a device name if it's not an option */
else if (sscanf(lp, "usb %i %i", &vendor, &product) == 2)
{
mostRecentConfigConnectionType = SANE_FUJITSU_USB;
sanei_usb_attach_matching_devices(lp, attachOne);
mostRecentConfigConnectionType = SANE_FUJITSU_SCSI;
}
else /* must be a device name if it's not an option */
{
if ((strncmp ("usb", lp, 3) == 0) && isspace (lp[3])) {
lp += 3;
lp = sanei_config_skip_whitespace (lp);
mostRecentConfigConnectionType = SANE_FUJITSU_USB;
}
strncpy (devName, lp, sizeof (devName));
devName[sizeof (devName) - 1] = '\0';
sanei_config_attach_matching_devices (devName, attachOne);
mostRecentConfigConnectionType = SANE_FUJITSU_SCSI;
}
}
fclose (fp);
@ -568,7 +594,10 @@ sane_open (SANE_String_Const name, SANE_Handle * handle)
case MODEL_3093:
case MODEL_4097:
case MODEL_FI:
setDefaults3096 (scanner);
if ( strstr (scanner->productName, "4220") )
setDefaults3091 (scanner);
else
setDefaults3096 (scanner);
break;
case MODEL_SP15:
@ -1351,7 +1380,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
case MODEL_3097:
case MODEL_4097:
case MODEL_FI:
return (setMode3096 (scanner, newMode));
if ( strstr (scanner->productName, "4220") )
return (setMode3091 (scanner, newMode));
else
return (setMode3096 (scanner, newMode));
case MODEL_SP15:
return (setModeSP15 (scanner, newMode));
}
@ -1871,23 +1903,35 @@ sane_start (SANE_Handle handle)
if (scanner->sfd < 0)
{
/* first call */
if (sanei_scsi_open (scanner->sane.name, &(scanner->sfd),
senseHandler, 0) != SANE_STATUS_GOOD)
{
DBG (MSG_ERR,
"sane_start: open of %s failed:\n", scanner->sane.name);
return SANE_STATUS_INVAL;
}
if (scanner->connection == SANE_FUJITSU_USB) {
DBG (10, "sane_start opening USB device\n");
if (sanei_usb_open (scanner->sane.name, &(scanner->sfd)) !=
SANE_STATUS_GOOD) {
DBG (MSG_ERR,
"sane_start: open of %s failed:\n", scanner->sane.name);
return SANE_STATUS_INVAL;
}
} else if (scanner->connection == SANE_FUJITSU_SCSI) {
DBG (10, "sane_start opening SCSI device\n");
if (sanei_scsi_open (scanner->sane.name, &(scanner->sfd),
scsiSenseHandler, 0) != SANE_STATUS_GOOD) {
DBG (MSG_ERR,
"sane_start: open of %s failed:\n", scanner->sane.name);
return SANE_STATUS_INVAL;
}
}
}
scanner->object_count = 1;
scanner->eof = SANE_FALSE;
if ((ret = grabScanner (scanner)))
{
DBG (5, "sane_start: unable to reserve scanner\n");
sanei_scsi_close (scanner->sfd);
if (scanner->connection == SANE_FUJITSU_USB) {
sanei_usb_close (scanner->sfd);
} else if (scanner->connection == SANE_FUJITSU_SCSI) {
sanei_scsi_close (scanner->sfd);
}
scanner->object_count = 0;
scanner->sfd = -1;
return ret;
@ -1907,7 +1951,11 @@ sane_start (SANE_Handle handle)
{
DBG (5, "sane_start: ERROR: failed to start send command\n");
freeScanner (scanner);
sanei_scsi_close (scanner->sfd);
if (scanner->connection == SANE_FUJITSU_USB) {
sanei_usb_close (scanner->sfd);
} else if (scanner->connection == SANE_FUJITSU_SCSI) {
sanei_scsi_close (scanner->sfd);
}
scanner->object_count = 0;
scanner->sfd = -1;
return ret;
@ -1917,7 +1965,11 @@ sane_start (SANE_Handle handle)
{
DBG (5, "sane_start: ERROR: failed to start imprinter command\n");
freeScanner (scanner);
sanei_scsi_close (scanner->sfd);
if (scanner->connection == SANE_FUJITSU_USB) {
sanei_usb_close (scanner->sfd);
} else if (scanner->connection == SANE_FUJITSU_SCSI) {
sanei_scsi_close (scanner->sfd);
}
scanner->object_count = 0;
scanner->sfd = -1;
return ret;
@ -1929,7 +1981,11 @@ sane_start (SANE_Handle handle)
{
DBG (5, "sane_start: WARNING: ADF empty\n");
freeScanner (scanner);
sanei_scsi_close (scanner->sfd);
if (scanner->connection == SANE_FUJITSU_USB) {
sanei_usb_close (scanner->sfd);
} else if (scanner->connection == SANE_FUJITSU_SCSI) {
sanei_scsi_close (scanner->sfd);
}
scanner->object_count = 0;
scanner->sfd = -1;
return ret;
@ -1942,7 +1998,11 @@ sane_start (SANE_Handle handle)
{
DBG (5, "sane_start: ERROR: failed to set window\n");
freeScanner (scanner);
sanei_scsi_close (scanner->sfd);
if (scanner->connection == SANE_FUJITSU_USB) {
sanei_usb_close (scanner->sfd);
} else if (scanner->connection == SANE_FUJITSU_SCSI) {
sanei_scsi_close (scanner->sfd);
}
scanner->object_count = 0;
scanner->sfd = -1;
return ret;
@ -1965,7 +2025,11 @@ sane_start (SANE_Handle handle)
DBG (MSG_ERR, "ERROR: could not create pipe\n");
scanner->object_count = 0;
freeScanner (scanner);
sanei_scsi_close (scanner->sfd);
if (scanner->connection == SANE_FUJITSU_USB) {
sanei_usb_close (scanner->sfd);
} else if (scanner->connection == SANE_FUJITSU_SCSI) {
sanei_scsi_close (scanner->sfd);
}
scanner->sfd = -1;
return SANE_STATUS_IO_ERROR;
}
@ -1980,7 +2044,11 @@ sane_start (SANE_Handle handle)
DBG (MSG_ERR, "ERROR: could not create temporary file.\n");
scanner->object_count = 0;
freeScanner (scanner);
sanei_scsi_close (scanner->sfd);
if (scanner->connection == SANE_FUJITSU_USB) {
sanei_usb_close (scanner->sfd);
} else if (scanner->connection == SANE_FUJITSU_SCSI) {
sanei_scsi_close (scanner->sfd);
}
scanner->sfd = -1;
return SANE_STATUS_IO_ERROR;
}
@ -1992,7 +2060,11 @@ sane_start (SANE_Handle handle)
DBG (MSG_ERR, "ERROR: could not create duplex pipe.\n");
scanner->object_count = 0;
freeScanner (scanner);
sanei_scsi_close (scanner->sfd);
if (scanner->connection == SANE_FUJITSU_USB) {
sanei_usb_close (scanner->sfd);
} else if (scanner->connection == SANE_FUJITSU_SCSI) {
sanei_scsi_close (scanner->sfd);
}
scanner->sfd = -1;
return SANE_STATUS_IO_ERROR;
}
@ -2294,7 +2366,7 @@ static SANE_Status
attachScanner (const char *devicename, struct fujitsu **devp)
{
struct fujitsu *dev;
int sfd;
SANE_Int sfd;
DBG (15, "attach_scanner: %s\n", devicename);
@ -2312,11 +2384,19 @@ attachScanner (const char *devicename, struct fujitsu **devp)
}
DBG (15, "attach_scanner: opening %s\n", devicename);
if (sanei_scsi_open (devicename, &sfd, senseHandler, 0) != 0)
{
DBG (5, "attach_scanner: open failed\n");
return SANE_STATUS_INVAL;
if (mostRecentConfigConnectionType == SANE_FUJITSU_USB) {
DBG (15, "attachScanner opening USB device\n");
if (sanei_usb_open (devicename, &sfd) != SANE_STATUS_GOOD) {
DBG (5, "attach_scanner: open failed\n");
return SANE_STATUS_INVAL;
}
} else if (mostRecentConfigConnectionType == SANE_FUJITSU_SCSI) {
DBG (15, "attachScanner opening SCSI device\n");
if (sanei_scsi_open (devicename, &sfd, scsiSenseHandler, 0) != 0) {
DBG (5, "attach_scanner: open failed\n");
return SANE_STATUS_INVAL;
}
}
if (NULL == (dev = malloc (sizeof (*dev))))
return SANE_STATUS_NO_MEM;
@ -2327,6 +2407,7 @@ attachScanner (const char *devicename, struct fujitsu **devp)
return SANE_STATUS_NO_MEM;
dev->devicename = strdup (devicename);
dev->connection = mostRecentConfigConnectionType;
dev->sfd = sfd;
/*
@ -2335,14 +2416,22 @@ attachScanner (const char *devicename, struct fujitsu **devp)
if (identifyScanner (dev) != 0)
{
DBG (5, "attach_scanner: scanner identification failed\n");
sanei_scsi_close (dev->sfd);
if (dev->connection == SANE_FUJITSU_USB) {
sanei_usb_close (dev->sfd);
} else if (dev->connection == SANE_FUJITSU_SCSI) {
sanei_scsi_close (dev->sfd);
}
free (dev->buffer);
free (dev);
return SANE_STATUS_INVAL;
}
/* Why? */
sanei_scsi_close (dev->sfd);
if (dev->connection == SANE_FUJITSU_USB) {
sanei_usb_close (dev->sfd);
} else if (dev->connection == SANE_FUJITSU_SCSI) {
sanei_scsi_close (dev->sfd);
}
dev->sfd = -1;
dev->sane.name = dev->devicename;
@ -2380,7 +2469,7 @@ attachOne (const char *name)
* Responsible for producing a meaningful debug message.
*/
static SANE_Status
senseHandler (int scsi_fd, u_char * sensed_data, void *arg)
scsiSenseHandler (int scsi_fd, u_char * sensed_data, void *arg)
{
unsigned int ret = SANE_STATUS_IO_ERROR;
unsigned int sense = get_RS_sense_key (sensed_data);
@ -2615,7 +2704,8 @@ doInquiry (struct fujitsu *s)
hexdump (MSG_IO, "inquiry", inquiryB.cmd, inquiryB.size);
do_scsi_cmd (s->sfd, inquiryB.cmd, inquiryB.size, s->buffer, 96, NULL);
do_cmd (s->connection, s->sfd, inquiryB.cmd, inquiryB.size,
s->buffer, 96, NULL);
}
static SANE_Status
@ -2631,26 +2721,37 @@ get_hardware_status (struct fujitsu *s)
{
int sfd;
if (sanei_scsi_open (s->devicename, &sfd, senseHandler, 0) != 0)
{
DBG (5, "get_hardware_status: open failed\n");
return SANE_STATUS_INVAL;
}
if (s->connection == SANE_FUJITSU_USB) {
DBG (10, "get_hardware_status opening USB device\n");
if (sanei_usb_open (s->devicename, &sfd) != SANE_STATUS_GOOD) {
DBG (5, "get_hardware_status: open failed\n");
return SANE_STATUS_INVAL;
}
} else if (s->connection == SANE_FUJITSU_SCSI) {
DBG (10, "get_hardware_status opening SCSI device\n");
if (sanei_scsi_open (s->devicename, &sfd, scsiSenseHandler, 0)!=0) {
DBG (5, "get_hardware_status: open failed\n");
return SANE_STATUS_INVAL;
}
}
hexdump (MSG_IO, "get_hardware_status",
hw_statusB.cmd, hw_statusB.size);
ret = do_scsi_cmd (sfd, hw_statusB.cmd, hw_statusB.size,
s->buffer, 10, NULL);
sanei_scsi_close (sfd);
ret = do_cmd (s->connection, sfd, hw_statusB.cmd, hw_statusB.size,
s->buffer, 10, NULL);
if (s->connection == SANE_FUJITSU_USB) {
sanei_usb_close (sfd);
} else if (s->connection == SANE_FUJITSU_SCSI) {
sanei_scsi_close (sfd);
}
}
else
{
hexdump (MSG_IO, "get_hardware_status",
hw_statusB.cmd, hw_statusB.size);
ret = do_scsi_cmd (s->sfd, hw_statusB.cmd, hw_statusB.size,
s->buffer, 10, NULL);
ret = do_cmd (s->connection, s->sfd, hw_statusB.cmd, hw_statusB.size,
s->buffer, 10, NULL);
}
if (ret == SANE_STATUS_GOOD)
@ -2686,8 +2787,8 @@ getVitalProductData (struct fujitsu *s)
set_IN_page_code (inquiryB.cmd, 0xf0);
hexdump (MSG_IO, "get_vital_product_data", inquiryB.cmd, inquiryB.size);
ret = do_scsi_cmd (s->sfd, inquiryB.cmd, inquiryB.size,
s->buffer, 0x64, NULL);
ret = do_cmd (s->connection, s->sfd, inquiryB.cmd, inquiryB.size,
s->buffer, 0x64, NULL);
if (ret == SANE_STATUS_GOOD)
{
DBG (MSG_INFO, "standard options\n");
@ -2780,15 +2881,31 @@ getVitalProductData (struct fujitsu *s)
return ret;
}
/**
* Sends a command to the device. This calls do_scsi_cmd or do_usb_cmd.
*/
static int
do_cmd (Fujitsu_Connection_Type connection, int fd, unsigned char *cmd,
int cmd_len, unsigned char *out, size_t req_out_len,
size_t *res_out_len)
{
if (connection == SANE_FUJITSU_SCSI) {
return do_scsi_cmd(fd, cmd, cmd_len, out, req_out_len, res_out_len);
}
if (connection == SANE_FUJITSU_USB) {
return do_usb_cmd(fd, cmd, cmd_len, out, req_out_len, res_out_len);
}
return SANE_STATUS_INVAL;
}
/**
* Sends a SCSI command to the device. This is just a wrapper around
* sanei_scsi_cmd with some debug printing.
*/
static int
do_scsi_cmd (int fd, unsigned char *cmd, int cmd_len,
unsigned char *out, size_t req_out_len, size_t *res_out_len)
do_scsi_cmd (int fd, unsigned char *cmd,
int cmd_len, unsigned char *out, size_t req_out_len,
size_t *res_out_len)
{
int ret;
size_t ol = req_out_len;
@ -2823,6 +2940,118 @@ do_scsi_cmd (int fd, unsigned char *cmd, int cmd_len,
return ret;
}
#define USB_CMD_HEADER_BYTES 19
#define USB_CMD_MIN_BYTES 31
/**
* Sends a USB command to the device.
*/
static int
do_usb_cmd (int fd, unsigned char *cmd,
int cmd_len, unsigned char *out, size_t req_out_len,
size_t *res_out_len)
{
int ret = SANE_STATUS_GOOD;
size_t cnt, ol;
int op_code = 0;
int i, j;
int tries = 0;
unsigned char buf[1024];
/* unsigned char sense_bytes[64]; */
retry:
hexdump (IO_CMD, "<cmd<", cmd, cmd_len);
if (cmd_len > 0) op_code = ((int)cmd[0]) & 0xff;
if ((cmd_len+USB_CMD_HEADER_BYTES) > (int)sizeof(buf)) {
/* Command too long. */
return SANE_STATUS_INVAL;
}
buf[0] = (unsigned char)'C';
for (i = 1; i < USB_CMD_HEADER_BYTES; i++) buf[i] = (unsigned char)0;
memcpy(&buf[USB_CMD_HEADER_BYTES], cmd, cmd_len);
for (i = USB_CMD_HEADER_BYTES+cmd_len; i < USB_CMD_MIN_BYTES; i++) {
buf[i] = (unsigned char)0;
}
/* The SCAN command must be at least 32 bytes long. */
if ( (op_code == SCAN) && (i < 32) ) {
for (; i < 32; i++) buf[i] = (unsigned char)0;
}
for (j = 0; j < i;) {
cnt = i-j;
/* First URB has to be 31 bytes. */
/* All other URBs must be 64 bytes (max) per URB. */
if ( (j == 0) && (cnt > 31) ) cnt = 31; else if (cnt > 64) cnt = 64;
hexdump (IO_CMD, "*** URB going out:", &buf[j], cnt);
DBG (IO_CMD, "try to write %u bytes\n", cnt);
ret = sanei_usb_write_bulk(fd, &buf[j], &cnt);
DBG (IO_CMD, "wrote %u bytes\n", cnt);
if (ret != SANE_STATUS_GOOD) break;
j += cnt;
}
if (ret != SANE_STATUS_GOOD) {
DBG (MSG_ERR, "*** Got error %d trying to write\n", ret);
}
ol = 0;
if (ret == SANE_STATUS_GOOD) {
if ( (out != NULL) && (req_out_len > 0) ) {
while (ol < req_out_len) {
cnt = (size_t)(req_out_len-ol);
DBG (IO_CMD, "try to read %u bytes\n", cnt);
ret = sanei_usb_read_bulk(fd, &out[ol], &cnt);
DBG (IO_CMD, "read %u bytes\n", cnt);
if (cnt > 0) {
hexdump (IO_CMD, "*** Data read:", &out[ol], cnt);
}
if (ret != SANE_STATUS_GOOD) {
DBG(MSG_ERR, "*** Got error %d trying to read\n", ret);
}
if (ret != SANE_STATUS_GOOD) break;
ol += cnt;
}
}
DBG(MSG_ERR, "*** Try to read CSW\n");
cnt = sizeof(buf);
sanei_usb_read_bulk(fd, buf, &cnt);
hexdump (IO_CMD, "*** Read CSW", buf, cnt);
}
/* Auto-retry failed data reads, in case the scanner is busy. */
if ( (op_code == READ) && (tries < 100) && (ol == 0) ) {
usleep(100000L);
tries++;
goto retry;
}
if (res_out_len != NULL)
{
*res_out_len = ol;
}
if ((req_out_len != 0) && (req_out_len != ol))
{
DBG (MSG_ERR, "do_usb_cmd: asked %lu bytes, got %lu\n",
(u_long) req_out_len, (u_long) ol);
}
if (ret)
{
DBG (MSG_ERR, "do_usb_cmd: returning 0x%08x\n", ret);
}
DBG (IO_CMD_RES, "do_usb_cmd: returning %lu bytes:\n", (u_long) ol);
if (out != NULL && ol != 0)
{
hexdump (IO_CMD_RES, ">rslt>", out, (ol > 0x60) ? 0x60 : ol);
}
return ret;
}
/**
* Prints a hex dump of the given buffer onto the debug output stream.
@ -2927,8 +3156,8 @@ freeScanner (struct fujitsu *s)
#endif
hexdump (MSG_IO, "release_unit", release_unitB.cmd, release_unitB.size);
ret = do_scsi_cmd (s->sfd, release_unitB.cmd, release_unitB.size,
NULL, 0, NULL);
ret = do_cmd (s->connection, s->sfd, release_unitB.cmd,
release_unitB.size, NULL, 0, NULL);
if (ret)
return ret;
@ -2959,8 +3188,8 @@ grabScanner (struct fujitsu *s)
wait_scanner (s);
hexdump (MSG_IO, "reserve_unit", reserve_unitB.cmd, reserve_unitB.size);
ret = do_scsi_cmd (s->sfd, reserve_unitB.cmd, reserve_unitB.size,
NULL, 0, NULL);
ret = do_cmd (s->connection, s->sfd, reserve_unitB.cmd,
reserve_unitB.size, NULL, 0, NULL);
if (ret)
return ret;
@ -2968,7 +3197,7 @@ grabScanner (struct fujitsu *s)
return 0;
}
static int fujitsu_wait_scanner(int fd)
static int fujitsu_wait_scanner(Fujitsu_Connection_Type connection, int fd)
{
int ret = -1;
int cnt = 0;
@ -2979,8 +3208,8 @@ static int fujitsu_wait_scanner(int fd)
{
hexdump (MSG_IO, "test_unit_ready", test_unit_readyB.cmd,
test_unit_readyB.size);
ret = do_scsi_cmd (fd, test_unit_readyB.cmd,
test_unit_readyB.size, 0, 0, NULL);
ret = do_cmd (connection, fd, test_unit_readyB.cmd,
test_unit_readyB.size, 0, 0, NULL);
if (ret == SANE_STATUS_DEVICE_BUSY)
{
usleep (500000); /* wait 0.5 seconds */
@ -3009,7 +3238,7 @@ static int fujitsu_wait_scanner(int fd)
static int
wait_scanner (struct fujitsu *s)
{
return fujitsu_wait_scanner(s->sfd);
return fujitsu_wait_scanner(s->connection, s->sfd);
}
/**
@ -3041,7 +3270,8 @@ object_position (struct fujitsu *s, int i_load)
}
hexdump (MSG_IO, "object_position", s->buffer, object_positionB.size);
ret = do_scsi_cmd (s->sfd, s->buffer, object_positionB.size, NULL, 0, NULL);
ret = do_cmd (s->connection, s->sfd, s->buffer, object_positionB.size,
NULL, 0, NULL);
if (ret != SANE_STATUS_GOOD)
return ret;
wait_scanner (s);
@ -3073,7 +3303,8 @@ objectDischarge (struct fujitsu *s)
set_OP_autofeed (s->buffer, OP_Discharge);
}
hexdump (MSG_IO, "object_position", s->buffer, object_positionB.size);
ret = do_scsi_cmd (s->sfd, s->buffer, object_positionB.size, NULL, 0, NULL);
ret = do_cmd (s->connection, s->sfd, s->buffer, object_positionB.size,
NULL, 0, NULL);
wait_scanner (s);
DBG (10, "objectDischarge: ok\n");
return ret;
@ -3090,8 +3321,8 @@ do_reset (struct fujitsu *scanner)
DBG (10, "doReset\n");
if (scanner->model == MODEL_3092) {
ret = do_scsi_cmd (scanner->sfd, reset_unitB.cmd, reset_unitB.size,
NULL, 0, NULL);
ret = do_cmd (scanner->connection, scanner->sfd, reset_unitB.cmd,
reset_unitB.size, NULL, 0, NULL);
if (ret)
return ret;
}
@ -3140,7 +3371,11 @@ doCancel (struct fujitsu *scanner)
{
freeScanner (scanner);
DBG (10, "doCancel: close filedescriptor\n");
sanei_scsi_close (scanner->sfd);
if (scanner->connection == SANE_FUJITSU_USB) {
sanei_usb_close (scanner->sfd);
} else if (scanner->connection == SANE_FUJITSU_SCSI) {
sanei_scsi_close (scanner->sfd);
}
scanner->sfd = -1;
}
@ -3210,7 +3445,7 @@ startScan (struct fujitsu *s)
}
hexdump (MSG_IO, "start_scan", command, cmdsize);
ret = do_scsi_cmd (s->sfd, command, cmdsize, NULL, 0, NULL);
ret = do_cmd (s->connection, s->sfd, command, cmdsize, NULL, 0, NULL);
free (command);
@ -3259,8 +3494,8 @@ set_mode_params (struct fujitsu *s)
hexdump (MSG_IO, "mode_select", s->buffer,
i_param_size + mode_selectB.size);
ret = do_scsi_cmd (s->sfd, s->buffer,
i_param_size + mode_selectB.size, NULL, 0, NULL);
ret = do_cmd (s->connection, s->sfd, s->buffer,
i_param_size + mode_selectB.size, NULL, 0, NULL);
}
@ -3286,30 +3521,40 @@ fujitsu_set_sleep_mode(struct fujitsu *s)
if (s->model == MODEL_FI) /*...and others */
{
/* With the fi-series scanners, we have to use a 10-byte header
* instead of a 4-byte header when communicating via USB. This
* may be a firmware bug. */
scsiblk *headerB;
int xfer_length_pos_adj;
if (s->connection == SANE_FUJITSU_USB) {
headerB = &mode_select_usb_headerB;
xfer_length_pos_adj = mode_select_headerB.size-mode_select_usb_headerB.size;
} else {
headerB = &mode_select_headerB;
xfer_length_pos_adj = 0;
}
memcpy (s->buffer, mode_selectB.cmd, mode_selectB.size);
memcpy (s->buffer + mode_selectB.size, mode_select_headerB.cmd,
mode_select_headerB.size);
memcpy (s->buffer + mode_selectB.size + mode_select_headerB.size,
memcpy (s->buffer + mode_selectB.size, headerB->cmd,
headerB->size);
memcpy (s->buffer + mode_selectB.size + headerB->size,
mode_select_parameter_blockB.cmd,
mode_select_parameter_blockB.size);
command = s->buffer + mode_selectB.size + mode_select_headerB.size;
command = s->buffer + mode_selectB.size + headerB->size;
i_cmd_size = 6;
set_MSEL_len (command, i_cmd_size);
set_MSEL_pagecode (command, MSEL_sleep);
set_MSEL_sleep_mode(command, s->sleep_time);
i_param_size = mode_select_headerB.size + i_cmd_size + 2;
set_MSEL_xfer_length (s->buffer, i_param_size);
i_param_size = headerB->size + i_cmd_size + 2;
set_MSEL_xfer_length (s->buffer, i_param_size + xfer_length_pos_adj);
hexdump (MSG_IO, "mode_select", s->buffer,
i_param_size + mode_selectB.size);
ret = do_scsi_cmd (s->sfd, s->buffer,
i_param_size + mode_selectB.size, NULL, 0, NULL);
ret = do_cmd (s->connection, s->sfd, s->buffer,
i_param_size + mode_selectB.size, NULL, 0, NULL);
if (!ret)
{
@ -3429,8 +3674,8 @@ read_large_data_block (struct fujitsu *s, unsigned char *buffer,
set_R_window_id (readB.cmd, i_window_id);
set_R_xfer_length (readB.cmd, dataToRead);
status = do_scsi_cmd (s->sfd, readB.cmd, readB.size, myBuffer,
dataToRead, &data_read);
status = do_cmd (s->connection, s->sfd, readB.cmd, readB.size,
myBuffer, dataToRead, &data_read);
if (status == SANE_STATUS_EOF)
{
@ -4105,22 +4350,34 @@ imprinter(struct fujitsu *s)
{
int sfd;
if (sanei_scsi_open (s->devicename, &sfd, senseHandler, 0) != 0)
{
DBG (5, "imprinter: open failed\n");
return SANE_STATUS_INVAL;
}
if (s->connection == SANE_FUJITSU_USB) {
DBG (10, "imprinter opening USB device\n");
if (sanei_usb_open (s->devicename, &sfd) != SANE_STATUS_GOOD) {
DBG (5, "imprinter: open failed\n");
return SANE_STATUS_INVAL;
}
} else if (s->connection == SANE_FUJITSU_SCSI) {
DBG (10, "imprinter opening SCSI device\n");
if (sanei_scsi_open
(s->devicename, &sfd, scsiSenseHandler, 0) != 0) {
DBG (5, "imprinter: open failed\n");
return SANE_STATUS_INVAL;
}
}
fujitsu_wait_scanner(sfd);
ret = do_scsi_cmd (sfd, s->buffer,
imprinterB.size + i_size,
NULL, 0, NULL);
sanei_scsi_close (sfd);
fujitsu_wait_scanner(s->connection, sfd);
ret = do_cmd (s->connection, sfd, s->buffer, imprinterB.size + i_size,
NULL, 0, NULL);
if (s->connection == SANE_FUJITSU_USB) {
sanei_usb_close (sfd);
} else if (s->connection == SANE_FUJITSU_SCSI) {
sanei_scsi_close (sfd);
}
}
else
{
ret = do_scsi_cmd (s->sfd, s->buffer,
imprinterB.size + i_size,
ret = do_cmd (s->connection, s->sfd, s->buffer,
imprinterB.size + i_size,
NULL, 0, NULL);
}
@ -4191,9 +4448,9 @@ fujitsu_send(struct fujitsu *s)
hexdump (MSG_IO, "send", s->buffer,
i_strlen + send_imprinterB.size + sendB.size);
ret = do_scsi_cmd (s->sfd, s->buffer,
i_strlen + send_imprinterB.size + sendB.size,
NULL, 0, NULL);
ret = do_cmd (s->connection, s->sfd, s->buffer,
i_strlen + send_imprinterB.size + sendB.size,
NULL, 0, NULL);
}
@ -4219,6 +4476,7 @@ setWindowParam (struct fujitsu *s)
unsigned char buffer[max_WDB_size];
int ret;
int scsiCommandLength = 0;
scsiblk *setwinB;
/* the amout of window data we're going to send. may have to be reduced
* depending on scanner model. */
@ -4352,18 +4610,24 @@ setWindowParam (struct fujitsu *s)
* follows without a header of its own.
*/
if ( (s->model == MODEL_FI) && (s->connection == SANE_FUJITSU_USB) ) {
setwinB = &set_usb_windowB;
} else {
setwinB = &set_windowB;
}
/* SET WINDOW command and command descriptor block.
* The transfer length will be filled in later using set_SW_xferlen.
*/
memcpy (s->buffer, set_windowB.cmd, set_windowB.size);
memcpy (s->buffer, setwinB->cmd, setwinB->size);
/* header for first set of window data */
memcpy ((s->buffer + set_windowB.size),
memcpy ((s->buffer + setwinB->size),
window_parameter_data_blockB.cmd,
window_parameter_data_blockB.size);
/* set window data size */
set_WPDB_wdblen ((s->buffer + set_windowB.size), windowDataSize);
set_WPDB_wdblen ((s->buffer + setwinB->size), windowDataSize);
if (s->duplex_mode == DUPLEX_BACK)
{
@ -4375,7 +4639,7 @@ setWindowParam (struct fujitsu *s)
}
/* now copy window data itself */
memcpy (s->buffer + set_windowB.size + window_parameter_data_blockB.size,
memcpy (s->buffer + setwinB->size + window_parameter_data_blockB.size,
buffer, windowDataSize);
/* when in duplex mode, add a second window */
@ -4394,7 +4658,7 @@ setWindowParam (struct fujitsu *s)
set_WD_paper_length_Y (buffer, 0);
}
hexdump (MSG_IO, "Window set - back", buffer, windowDataSize);
memcpy (s->buffer + set_windowB.size +
memcpy (s->buffer + setwinB->size +
window_parameter_data_blockB.size + windowDataSize, buffer,
windowDataSize);
set_SW_xferlen (s->buffer,
@ -4402,7 +4666,7 @@ setWindowParam (struct fujitsu *s)
2 * windowDataSize));
scsiCommandLength =
window_parameter_data_blockB.size + 2 * windowDataSize +
set_windowB.size;
setwinB->size;
}
else
{
@ -4410,10 +4674,11 @@ setWindowParam (struct fujitsu *s)
set_SW_xferlen (s->buffer, (window_parameter_data_blockB.size +
windowDataSize));
scsiCommandLength =
window_parameter_data_blockB.size + windowDataSize + set_windowB.size;
window_parameter_data_blockB.size + windowDataSize + setwinB->size;
}
ret = do_scsi_cmd (s->sfd, s->buffer, scsiCommandLength, NULL, 0, NULL);
ret = do_cmd (s->connection, s->sfd, s->buffer, scsiCommandLength,
NULL, 0, NULL);
if (ret)
return ret;
DBG (10, "set_window_param: ok\n");
@ -6427,7 +6692,7 @@ setDefaults3091 (struct fujitsu *scanner)
scanner->val[OPT_TL_X].w = 0;
scanner->val[OPT_TL_Y].w = 0;
/* this size is just big enough to match letter and A4 formats */
scanner->bottom_right_x = SANE_FIX (215.9);
scanner->bottom_right_x = SANE_FIX (215.0);
scanner->bottom_right_y = SANE_FIX (297.0);
scanner->page_width = FIXED_MM_TO_SCANNER_UNIT (scanner->bottom_right_x);
scanner->page_height = FIXED_MM_TO_SCANNER_UNIT (scanner->bottom_right_y);
@ -6453,6 +6718,8 @@ setDefaults3091 (struct fujitsu *scanner)
scanner->opt[OPT_DROPOUT_COLOR].cap = SANE_CAP_INACTIVE;
scanner->dropout_color = MSEL_dropout_DEFAULT;
if ( strstr (scanner->productName, "4220" ))
scanner->gamma = 0x80;
scanner->sleep_time = 15;
scanner->use_imprinter = SANE_FALSE;

Wyświetl plik

@ -1,3 +1,8 @@
#option force-model fi-4340Cdi
#/dev/sg1
scsi FUJITSU
# For Fujitsu scanners connected via USB on a known device:
# usb /dev/usb/scanner0
# For Fujitsu scanners connected via USB where vendor/product Id are known
# (use lsusb to find these):
# usb 0x04c5 0x1042

Wyświetl plik

@ -102,6 +102,13 @@ enum fujitsu_Option
};
typedef enum { /* hardware connection to the scanner */
SANE_FUJITSU_NODEV, /* default, no HW specified yet */
SANE_FUJITSU_SCSI, /* SCSI interface */
SANE_FUJITSU_PIO, /* parallel interface */
SANE_FUJITSU_USB /* USB interface */
} Fujitsu_Connection_Type;
struct fujitsu
{
struct fujitsu *next;
@ -121,6 +128,9 @@ struct fujitsu
int model; /* The scanner model. */
char *devicename; /* The name of the scanner device. */
Fujitsu_Connection_Type connection; /* hardware interface type */
int sfd; /* The scanner device file descriptor. */
int color_raster_offset; /* offset between r and b scan line and */
@ -466,16 +476,26 @@ static void doInquiry (struct fujitsu *s);
static SANE_Status attachScanner (const char *devicename,
struct fujitsu **devp);
static SANE_Status senseHandler (int scsi_fd, u_char * result, void *arg);
static SANE_Status scsiSenseHandler (int scsi_fd, u_char * result, void *arg);
static int identifyScanner (struct fujitsu *s);
static void doInquiry (struct fujitsu *s);
static int
do_cmd (Fujitsu_Connection_Type connection, int fd, unsigned char *cmd,
int cmd_len, unsigned char *out, size_t req_out_len,
size_t *res_out_len);
static int do_scsi_cmd (int fd, unsigned char *cmd, int cmd_len,
unsigned char *out, size_t req_out_len,
size_t *res_out_len);
static int
do_usb_cmd (int fd, unsigned char *cmd,
int cmd_len, unsigned char *out, size_t req_out_len,
size_t *res_out_len);
static void hexdump (int level, char *comment, unsigned char *p, int l);
static SANE_Status init_options (struct fujitsu *scanner);

Wyświetl plik

@ -37,6 +37,8 @@
:interface "SCSI"
:model "M4097"
:interface "SCSI"
:model "fi-4220C"
:interface "SCSI USB"
:model "fi-4340C"
:interface "SCSI"
:interface "SCSI USB"

Wyświetl plik

@ -4,13 +4,13 @@
.IX sane-m3096g
.SH NAME
sane-fujitsu \- SANE backend for Fujitsu flatbed scanners
sane-fujitsu \- SANE backend for Fujitsu flatbed and ADF scanners
.SH DESCRIPTION
The
.B sane-fujitsu
library implements a SANE (Scanner Access Now Easy) backend which
provides access to Fujitsu flatbed scanners.
provides access to Fujitsu flatbed and ADF scanners.
At present, the following
scanners are known to work with this backend:
.PP
@ -27,6 +27,8 @@ FUJITSU M3093GD
.br
FUJITSU M4097
.br
FUJITSU fi-4220C
.br
FUJITSU fi-4340C
.br
FUJITSU M3091DCd BF21
@ -157,6 +159,7 @@ often be alleviated by using "scsi-buf-size=32768".
sane(7),
sane\-scsi(5),
sane\-sp15c(5)
sane\-usb(5),
.br
Fujitsu ScanPartner 15C OEM Manual, Doc. No. 250-0081-0
.br
@ -172,6 +175,7 @@ with credit to the unnamed author of the coolscan driver
3091 driver: Frederik Ramm <frederik@remote.org>
3093GD,fi-4340C, ipc and cmp options: Oliver Schirrmeister <oschirr@abm.de>
3092 patch: Mario Goppold <mgoppold@tbzpariv.tcc-chemnitz.de>
fi-4220C patch and USB support: Ronald B. Cemer <ron@roncemer.com>
.SH LIMITATIONS
Only tested with Linux 2.4
@ -180,4 +184,4 @@ I'm sure there are plenty, and not too well hidden,
but I haven't seen them yet.
I don't know if the ScanPartner 15C still works, because I'm not able
to test it.
3091/3092 don't support halftone
3091/3092 don't support halftone