summaryrefslogtreecommitdiff
path: root/backend/hp5400_sanei.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/hp5400_sanei.c')
-rw-r--r--backend/hp5400_sanei.c387
1 files changed, 387 insertions, 0 deletions
diff --git a/backend/hp5400_sanei.c b/backend/hp5400_sanei.c
new file mode 100644
index 0000000..1396cb1
--- /dev/null
+++ b/backend/hp5400_sanei.c
@@ -0,0 +1,387 @@
+/* sane - Scanner Access Now Easy.
+ Copyright (C) 2003 Martijn van Oosterhout <kleptog@svana.org>
+ Copyright (C) 2003 Thomas Soumarmon <thomas.soumarmon@cogitae.net>
+ Copyright (c) 2003 Henning Meier-Geinitz, <henning@meier-geinitz.de>
+
+ Originally copied from HP3300 testtools. Original notice follows:
+
+ Copyright (C) 2001 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.
+
+ 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.
+
+ 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 "hp5400_debug.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;
+
+ HP5400_DBG (DBG_MSG,
+ "Write: reqtype = 0x%02X, req = 0x%02X, value = %04X, len = %d\n",
+ requesttype, request, iValue, iSize);
+
+ if (iSize > 0)
+ {
+ int i;
+ HP5400_DBG (DBG_MSG, " Data: ");
+ for (i = 0; i < iSize && i < 8; i++)
+ HP5400_DBG (DBG_MSG, "%02X ", ((unsigned char *) pabData)[i]);
+ if (iSize > 8)
+ HP5400_DBG (DBG_MSG, "...");
+ HP5400_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;
+
+ HP5400_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);
+ }
+}
+
+
+HP5400_SANE_STATIC 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)
+ {
+ HP5400_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)
+ {
+ HP5400_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)))
+ {
+ HP5400_DBG (DBG_MSG, "hp5400_open: vendor/product 0x%04X-0x%04X is not "
+ "supported\n", iVendor, iProduct);
+ sanei_usb_close (fd);
+ return -1;
+ }
+
+ HP5400_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)
+ {
+ HP5400_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))
+ {
+ HP5400_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);
+ HP5400_DBG (DBG_ERR, " error response is: %02X %02X %02X\n", abData[0],
+ abData[1], abData[2]);
+
+ return -1;
+ }
+
+ HP5400_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)
+ {
+ HP5400_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)
+ {
+ HP5400_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);
+}
+
+#ifdef STANDALONE
+/* returns >0 if command OK */
+int
+hp5400_bulk_read (int iHandle, size_t len, int block, FILE * file)
+{
+ SANE_Int fd;
+ char x1 = 0x14, x2 = 0x24;
+ short buf[4] = { 0, 0, 0, 0 };
+ SANE_Byte *buffer;
+ size_t res = 0;
+
+ buf[2] = block;
+
+ if (iHandle < 0)
+ {
+ HP5400_DBG (DBG_ERR, "hp5400_command_read: invalid handle\n");
+ return -1;
+ }
+ fd = iHandle;
+
+ buffer = (unsigned char*) 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);
+ HP5400_DBG (DBG_MSG, "Read bulk returned %lu, %lu remain\n",
+ (u_long) res, (u_long) len);
+ if (res > 0)
+ {
+ fwrite (buffer, (len < res) ? len : res, 1, file);
+ }
+ len -= block;
+ }
+ /* error handling? */
+ return 0;
+}
+#endif
+
+/* returns >0 if command OK */
+int
+hp5400_bulk_read_block (int iHandle, int iCmd, void *cmd, int cmdlen,
+ void *buffer, int len)
+{
+ SANE_Int fd;
+ size_t res = 0;
+
+ if (iHandle < 0)
+ {
+ HP5400_DBG (DBG_ERR, "hp5400_command_read_block: invalid handle\n");
+ return -1;
+ }
+ fd = iHandle;
+
+ _UsbWriteControl (fd, iCmd, 0, cmd, cmdlen);
+ res = len;
+ sanei_usb_read_bulk (fd, (SANE_Byte *) buffer, &res);
+ HP5400_DBG (DBG_MSG, "Read block returned %lu when reading %d\n",
+ (u_long) 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)
+{
+ SANE_Int fd;
+ size_t res = 0, offset = 0;
+
+ if (iHandle < 0)
+ {
+ HP5400_DBG (DBG_ERR, "hp5400_bulk_command_write: invalid handle\n");
+ return -1;
+ }
+ fd = iHandle;
+
+ HP5400_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;
+ HP5400_DBG (DBG_MSG, " Data: ");
+ for (i = 0; i < datalen && i < block && i < 8; i++)
+ HP5400_DBG (DBG_MSG, "%02X ", ((unsigned char *) data + offset)[i]);
+ if (i >= 8)
+ HP5400_DBG (DBG_MSG, "...");
+ HP5400_DBG (DBG_MSG, "\n");
+ }
+ res = (datalen < block) ? datalen : block;
+ sanei_usb_write_bulk (fd, (SANE_Byte *) (data + offset), &res);
+ HP5400_DBG (DBG_MSG, "Write returned %lu, %d remain\n", (u_long) res, datalen);
+ datalen -= block;
+ offset += block;
+ }
+
+ return hp5400_command_verify (iHandle, iCmd);
+}
+
+#ifdef STANDALONE
+/**
+ 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 */
+}
+#endif
+