sane-project-backends/backend/hp5400_sanei.c

356 wiersze
8.3 KiB
C

/* sane - Scanner Access Now Easy.
(c) 2003 Henning Meier-Geinitz, <henning@meier-geinitz.de>
(c) 2003 Martijn van Oosterhout, kleptog@svana.org
(c) 2002 Bertrik Sikken, bertrik@zonnet.nl
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.
Transport layer for communication with HP5400/5470 scanner.
Implementation using sanei_usb
Additions to support bulk data transport. Added debugging info - 19/02/2003 Martijn
Changed to use sanei_usb instead of direct /dev/usb/scanner access - 15/04/2003 Henning
*/
#include "hp5400_xfer.h"
#include <stdio.h>
#include "../include/sane/sanei_usb.h"
#define CMD_INITBULK1 0x0087 /* send 0x14 */
#define CMD_INITBULK2 0x0083 /* send 0x24 */
#define CMD_INITBULK3 0x0082 /* transfer length 0xf000 */
static void
_UsbWriteControl (int fd, int iValue, int iIndex, void *pabData, int iSize)
{
int requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT;
int request = (iSize > 1) ? 0x04 : 0x0C;
DBG (DBG_MSG,
"Write: reqtype = 0x%02X, req = 0x%02X, value = %04X, len = %d\n",
requesttype, request, iValue, iSize);
if (iSize > 0)
{
int i;
DBG (DBG_MSG, " Data: ");
for (i = 0; i < iSize && i < 8; i++)
DBG (DBG_MSG, "%02X ", ((unsigned char *) pabData)[i]);
if (iSize > 8)
DBG (DBG_MSG, "...");
DBG (DBG_MSG, "\n");
}
if (fd != -1)
{
sanei_usb_control_msg (fd, requesttype, request, iValue, iIndex, iSize,
pabData);
}
/* No error checking? */
}
void
hp5400_command_write_noverify (int fd, int iValue, void *pabData, int iSize)
{
_UsbWriteControl (fd, iValue, 0, pabData, iSize);
}
static void
_UsbReadControl (int fd, int iValue, int iIndex, void *pabData, int iSize)
{
int requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN;
int request = (iSize > 1) ? 0x04 : 0x0C;
DBG (DBG_MSG, "Read: reqtype = 0x%02X, req = 0x%02X, value = %04X\n",
requesttype, request, iValue);
if (fd != -1)
{
sanei_usb_control_msg (fd, requesttype, request, iValue, iIndex, iSize,
pabData);
}
}
int
hp5400_open (const char *filename)
{
int fd, iVendor, iProduct;
SANE_Status status;
if (!filename)
filename = "/dev/usb/scanner0";
status = sanei_usb_open (filename, &fd);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_MSG, "hp5400_open: open returned %s\n",
sane_strstatus (status));
return -1;
}
status = sanei_usb_get_vendor_product (fd, &iVendor, &iProduct);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_MSG, "hp5400_open: can't get vendor/product ids: %s\n",
sane_strstatus (status));
sanei_usb_close (fd);
return -1;
}
if ((iVendor != 0x03F0) || ((iProduct != 0x1005) && (iProduct != 0x1105)))
{
DBG (DBG_MSG, "hp5400_open: vendor/product 0x%04X-0x%04X is not "
"supported\n", iVendor, iProduct);
sanei_usb_close (fd);
return -1;
}
DBG (DBG_MSG, "vendor/product 0x%04X-0x%04X opened\n", iVendor, iProduct);
return fd;
}
void
hp5400_close (int iHandle)
{
sanei_usb_close (iHandle);
}
/* returns value > 0 if verify ok */
int
hp5400_command_verify (int iHandle, int iCmd)
{
unsigned char abData[4];
int fd;
if (iHandle < 0)
{
DBG (DBG_ERR, "hp5400_command_verify: invalid handle\n");
return -1;
}
fd = iHandle;
/* command 0xc500: read back previous command */
_UsbReadControl (fd, 0xc500, 0, (char *) abData, 2);
if (abData[0] != (iCmd >> 8))
{
DBG (DBG_ERR,
"hp5400_command_verify failed, expected 0x%02X%02X, got 0x%02X%02X\n",
(int) (iCmd >> 8), (int) (iCmd & 0xff), (int) abData[0],
(int) abData[1]);
return -1;
}
if (abData[1] != 0) /* Error code non-zero */
{
_UsbReadControl (fd, 0x0300, 0, (char *) abData, 3);
DBG (DBG_ERR, " error response is: %02X %02X %02X\n", abData[0],
abData[1], abData[2]);
return -1;
}
DBG (DBG_MSG, "Command %02X verified\n", abData[0]);
return 1;
}
/* returns > 0 if command OK */
int
hp5400_command_read_noverify (int iHandle, int iCmd, int iLen, void *pbData)
{
int fd;
if (iHandle < 0)
{
DBG (DBG_ERR, "hp5400_command_read: invalid handle\n");
return -1;
}
fd = iHandle;
_UsbReadControl (fd, iCmd, 0, pbData, iLen);
return 1;
}
/* returns > 0 if command OK */
int
hp5400_command_read (int iHandle, int iCmd, int iLen, void *pbData)
{
hp5400_command_read_noverify (iHandle, iCmd, iLen, pbData);
return hp5400_command_verify (iHandle, iCmd);
}
/* returns >0 if command OK */
int
hp5400_command_write (int iHandle, int iCmd, int iLen, void *pbData)
{
int fd;
if (iHandle < 0)
{
DBG (DBG_ERR, "hp5400_command_write: invalid handle\n");
return -1;
}
fd = iHandle;
_UsbWriteControl (fd, iCmd, 0, (char *) pbData, iLen);
return hp5400_command_verify (iHandle, iCmd);
}
/* returns >0 if command OK */
int
hp5400_bulk_read (int iHandle, int len, int block, FILE * file)
{
int fd;
char x1 = 0x14, x2 = 0x24;
short buf[4] = { 0, 0, 0, 0 };
unsigned char *buffer;
int res = 0;
buf[2] = block;
if (iHandle < 0)
{
DBG (DBG_ERR, "hp5400_command_read: invalid handle\n");
return -1;
}
fd = iHandle;
buffer = malloc (block);
_UsbWriteControl (fd, CMD_INITBULK1, 0, &x1, 1);
_UsbWriteControl (fd, CMD_INITBULK2, 0, &x2, 1);
while (len > 0)
{
_UsbWriteControl (fd, CMD_INITBULK3, 0, (unsigned char *) &buf,
sizeof (buf));
res = block;
sanei_usb_read_bulk (fd, buffer, &res);
DBG (DBG_MSG, "Read bulk returned %d, %d remain\n", res, len);
if (res > 0)
{
fwrite (buffer, (len < res) ? len : res, 1, file);
}
len -= block;
}
/* error handling? */
return 0;
}
/* returns >0 if command OK */
int
hp5400_bulk_read_block (int iHandle, int iCmd, void *cmd, int cmdlen,
void *buffer, int len)
{
int fd;
int res = 0;
if (iHandle < 0)
{
DBG (DBG_ERR, "hp5400_command_write: invalid handle\n");
return -1;
}
fd = iHandle;
_UsbWriteControl (fd, iCmd, 0, cmd, cmdlen);
res = len;
sanei_usb_read_bulk (fd, buffer, &res);
DBG (DBG_MSG, "Read block returned %d when reading %d\n", res, len);
return res;
}
/* returns >0 if command OK */
int
hp5400_bulk_command_write (int iHandle, int iCmd, void *cmd, int cmdlen,
int datalen, int block, char *data)
{
int fd;
int res = 0, offset = 0;
if (iHandle < 0)
{
DBG (DBG_ERR, "hp5400_command_write: invalid handle\n");
return -1;
}
fd = iHandle;
DBG (DBG_MSG, "bulk_command_write(%04X,<%d bytes>,<%d bytes>)\n", iCmd,
cmdlen, datalen);
_UsbWriteControl (fd, iCmd, 0, cmd, cmdlen);
while (datalen > 0)
{
{
int i;
DBG (DBG_MSG, " Data: ");
for (i = 0; i < datalen && i < block && i < 8; i++)
DBG (DBG_MSG, "%02X ", ((unsigned char *) data + offset)[i]);
if (i >= 8)
DBG (DBG_MSG, "...");
DBG (DBG_MSG, "\n");
}
res = (datalen < block) ? datalen : block;
sanei_usb_write_bulk (fd, data + offset, &res);
DBG (DBG_MSG, "Write returned %d, %d remain\n", res, datalen);
datalen -= block;
offset += block;
}
return hp5400_command_verify (iHandle, iCmd);
}
/**
ScannerIsOn
retrieve on/off status from scanner
@return 1 if is on 0 if is off -1 if is not reachable
*/
int
hp5400_isOn (int iHandle)
{
unsigned char text2400[3];
hp5400_command_read (iHandle, 0x2400, 0x03, text2400);
/* byte 0 indicates if is on or off if 0x02 */
/* byte 1 indicates time since is on */
/* byte 2 indicates time since is power plugged */
if (text2400[0] & 0x02)
{
return 1; /* is on */
}
return 0; /* is off */
}