summaryrefslogtreecommitdiff
path: root/backend/hp3900_usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/hp3900_usb.c')
-rw-r--r--backend/hp3900_usb.c509
1 files changed, 509 insertions, 0 deletions
diff --git a/backend/hp3900_usb.c b/backend/hp3900_usb.c
new file mode 100644
index 0000000..440c963
--- /dev/null
+++ b/backend/hp3900_usb.c
@@ -0,0 +1,509 @@
+/* HP Scanjet 3900 series - USB layer
+
+ Copyright (C) 2005-2008 Jonathan Bravo Lopez <jkdsoft@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.
+*/
+
+#ifndef USBLAYER
+
+#define USBLAYER
+
+#define TIMEOUT 1000
+#define BLK_READ_EP 0x81
+#define BLK_WRITE_EP 0x02
+
+SANE_Int dataline_count = 0;
+
+/* USB layer commands */
+static SANE_Int usb_ctl_write (USB_Handle usb_handle, SANE_Int address,
+ SANE_Byte * buffer, SANE_Int size,
+ SANE_Int index);
+static SANE_Int usb_ctl_read (USB_Handle usb_handle, SANE_Int address,
+ SANE_Byte * buffer, SANE_Int size,
+ SANE_Int index);
+
+/* Higher level commands*/
+
+static SANE_Int IRead_Byte (USB_Handle usb_handle, SANE_Int address,
+ SANE_Byte * data, SANE_Int index);
+static SANE_Int IRead_Word (USB_Handle usb_handle, SANE_Int address,
+ SANE_Int * data, SANE_Int index);
+static SANE_Int IRead_Integer (USB_Handle usb_handle, SANE_Int address,
+ SANE_Int * data, SANE_Int index);
+static SANE_Int IRead_Buffer (USB_Handle usb_handle, SANE_Int address,
+ SANE_Byte * buffer, SANE_Int size,
+ SANE_Int index);
+static SANE_Int IWrite_Byte (USB_Handle usb_handle, SANE_Int address,
+ SANE_Byte data, SANE_Int index1,
+ SANE_Int index2);
+static SANE_Int IWrite_Word (USB_Handle usb_handle, SANE_Int address,
+ SANE_Int data, SANE_Int index);
+static SANE_Int IWrite_Integer (USB_Handle usb_handle, SANE_Int address,
+ SANE_Int data, SANE_Int index);
+static SANE_Int IWrite_Buffer (USB_Handle usb_handle, SANE_Int address,
+ SANE_Byte * buffer, SANE_Int size,
+ SANE_Int index);
+
+static SANE_Int Read_Byte (USB_Handle usb_handle, SANE_Int address,
+ SANE_Byte * data);
+static SANE_Int Read_Word (USB_Handle usb_handle, SANE_Int address,
+ SANE_Int * data);
+static SANE_Int Read_Integer (USB_Handle usb_handle, SANE_Int address,
+ SANE_Int * data);
+static SANE_Int Read_Buffer (USB_Handle usb_handle, SANE_Int address,
+ SANE_Byte * buffer, SANE_Int size);
+static SANE_Int Read_Bulk (USB_Handle usb_handle, SANE_Byte * buffer,
+ size_t size);
+static SANE_Int Write_Byte (USB_Handle usb_handle, SANE_Int address,
+ SANE_Byte data);
+static SANE_Int Write_Word (USB_Handle usb_handle, SANE_Int address,
+ SANE_Int data);
+/*static SANE_Int Write_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int data);*/
+static SANE_Int Write_Buffer (USB_Handle usb_handle, SANE_Int address,
+ SANE_Byte * buffer, SANE_Int size);
+static SANE_Int Write_Bulk (USB_Handle usb_handle, SANE_Byte * buffer,
+ SANE_Int size);
+
+static SANE_Int show_buffer (SANE_Int level, SANE_Byte * buffer,
+ SANE_Int size);
+
+/* Implementation */
+
+static SANE_Int
+IWrite_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data,
+ SANE_Int index1, SANE_Int index2)
+{
+ SANE_Int rst = ERROR;
+ SANE_Byte buffer[2] = { 0x00, 0x00 };
+
+ if (usb_ctl_read (usb_handle, address + 1, buffer, 0x02, index1) == 2)
+ {
+ buffer[1] = (buffer[0] & 0xff);
+ buffer[0] = (data & 0xff);
+
+ if (usb_ctl_write (usb_handle, address, buffer, 0x02, index2) == 2)
+ rst = OK;
+ }
+
+ return rst;
+}
+
+static SANE_Int
+IWrite_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int data,
+ SANE_Int index)
+{
+ SANE_Int rst = ERROR;
+ SANE_Byte buffer[2];
+
+ buffer[0] = (data & 0xff);
+ buffer[1] = ((data >> 8) & 0xff);
+
+ if (usb_ctl_write (usb_handle, address, buffer, 0x02, index) == 2)
+ rst = OK;
+
+ return rst;
+}
+
+static SANE_Int
+IWrite_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int data,
+ SANE_Int index)
+{
+ SANE_Int rst = ERROR;
+ SANE_Byte buffer[4];
+
+ buffer[0] = (data & 0xff);
+ buffer[1] = ((data >> 8) & 0xff);
+ buffer[2] = ((data >> 16) & 0xff);
+ buffer[3] = ((data >> 24) & 0xff);
+
+ if (usb_ctl_write (usb_handle, address, buffer, 0x04, index) == 4)
+ rst = OK;
+
+ return rst;
+}
+
+static SANE_Int
+IWrite_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer,
+ SANE_Int size, SANE_Int index)
+{
+ SANE_Int ret = ERROR;
+
+ if (!((buffer == NULL) && (size > 0)))
+ if (usb_ctl_write (usb_handle, address, buffer, size, index) == size)
+ ret = OK;
+
+ return ret;
+}
+
+static SANE_Int
+IRead_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data,
+ SANE_Int index)
+{
+ SANE_Byte buffer[2] = { 0x00, 0x00 };
+ SANE_Int ret = ERROR;
+
+ if (data != NULL)
+ if (usb_ctl_read (usb_handle, address, buffer, 0x02, index) == 2)
+ {
+ *data = (SANE_Byte) (buffer[0] & 0xff);
+ ret = OK;
+ }
+
+ return ret;
+}
+
+static SANE_Int
+IRead_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int * data,
+ SANE_Int index)
+{
+ SANE_Byte buffer[2] = { 0x00, 0x00 };
+ SANE_Int ret = ERROR;
+
+ if (data != NULL)
+ if (usb_ctl_read (usb_handle, address, buffer, 0x02, index) == 2)
+ {
+ *data = ((buffer[1] << 8) & 0xffff) + (buffer[0] & 0xff);
+ ret = OK;
+ }
+
+ return ret;
+}
+
+static SANE_Int
+IRead_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int * data,
+ SANE_Int index)
+{
+ SANE_Byte buffer[4] = { 0x00, 0x00, 0x00, 0x00 };
+ SANE_Int ret = ERROR;
+
+ if (data != NULL)
+ {
+ *data = 0;
+ if (usb_ctl_read (usb_handle, address, buffer, 0x04, index) == 4)
+ {
+ SANE_Int C;
+ for (C = 3; C >= 0; C--)
+ *data = ((*data << 8) + (buffer[C] & 0xff)) & 0xffffffff;
+ ret = OK;
+ }
+ }
+
+ return ret;
+}
+
+static SANE_Int
+IRead_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer,
+ SANE_Int size, SANE_Int index)
+{
+ SANE_Int ret = ERROR;
+
+ if (buffer != NULL)
+ if (usb_ctl_read (usb_handle, address, buffer, size, index) == size)
+ ret = OK;
+
+ return ret;
+}
+
+static SANE_Int
+Write_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data)
+{
+ return IWrite_Byte (usb_handle, address, data, 0x100, 0);
+}
+
+static SANE_Int
+Write_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int data)
+{
+ return IWrite_Word (usb_handle, address, data, 0);
+}
+
+/*static SANE_Int Write_Integer(USB_Handle usb_handle, SANE_Int address, SANE_Int data)
+{
+ return IWrite_Integer(usb_handle, address, data, 0);
+}*/
+
+static SANE_Int
+Write_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer,
+ SANE_Int size)
+{
+ return IWrite_Buffer (usb_handle, address, buffer, size, 0);
+}
+
+static SANE_Int
+Read_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data)
+{
+ return IRead_Byte (usb_handle, address, data, 0x100);
+}
+
+static SANE_Int
+Read_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int * data)
+{
+ return IRead_Word (usb_handle, address, data, 0x100);
+}
+
+static SANE_Int
+Read_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int * data)
+{
+ return IRead_Integer (usb_handle, address, data, 0x100);
+}
+
+static SANE_Int
+Read_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer,
+ SANE_Int size)
+{
+ return IRead_Buffer (usb_handle, address, buffer, size, 0x100);
+}
+
+static SANE_Int
+Write_Bulk (USB_Handle usb_handle, SANE_Byte * buffer, SANE_Int size)
+{
+ SANE_Int rst = ERROR;
+
+ if (buffer != NULL)
+ {
+ dataline_count++;
+ DBG (DBG_CTL, "%06i BLK DO: %i. bytes\n", dataline_count, size);
+ show_buffer (4, buffer, size);
+
+#ifdef STANDALONE
+ if (usb_handle != NULL)
+ if (usb_bulk_write
+ (usb_handle, BLK_WRITE_EP, (char *) buffer, size,
+ TIMEOUT) == size)
+ rst = OK;
+#else
+ if (usb_handle != -1)
+ {
+ size_t mysize = size;
+ if (sanei_usb_write_bulk (usb_handle, buffer, &mysize) ==
+ SANE_STATUS_GOOD)
+ rst = OK;
+ }
+#endif
+ }
+
+ if (rst != OK)
+ DBG (DBG_CTL, " : Write_Bulk error\n");
+
+ return rst;
+}
+
+static SANE_Int
+Read_Bulk (USB_Handle usb_handle, SANE_Byte * buffer, size_t size)
+{
+ SANE_Int rst = ERROR;
+
+ if (buffer != NULL)
+ {
+ dataline_count++;
+ DBG (DBG_CTL, "%06i BLK DI: Buffer length = %lu. bytes\n",
+ dataline_count, (u_long) size);
+
+#ifdef STANDALONE
+ if (usb_handle != NULL)
+ rst =
+ usb_bulk_read (usb_handle, BLK_READ_EP, (char *) buffer, size,
+ TIMEOUT);
+#else
+ if (usb_handle != -1)
+ if (sanei_usb_read_bulk (usb_handle, buffer, &size) ==
+ SANE_STATUS_GOOD)
+ rst = size;
+#endif
+ }
+
+ if (rst < 0)
+ DBG (DBG_CTL, " : Read_Bulk error\n");
+ else
+ show_buffer (4, buffer, rst);
+
+ return rst;
+}
+
+static SANE_Int
+usb_ctl_write (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer,
+ SANE_Int size, SANE_Int index)
+{
+ SANE_Int rst = ERROR;
+
+ dataline_count++;
+ DBG (DBG_CTL, "%06i CTL DO: 40 04 %04x %04x %04x\n",
+ dataline_count, address & 0xffff, index, size);
+ show_buffer (DBG_CTL, buffer, size);
+
+#ifdef STANDALONE
+ if (usb_handle != NULL)
+ rst = usb_control_msg (usb_handle, 0x40, /* Request type */
+ 0x04, /* Request */
+ address, /* Value */
+ index, /* Index */
+ (char *) buffer, /* Buffer */
+ size, /* Size */
+ TIMEOUT);
+#else
+ if (usb_handle != -1)
+ {
+ if (sanei_usb_control_msg (usb_handle, 0x40, /* Request type */
+ 0x04, /* Request */
+ address, /* Value */
+ index, /* Index */
+ size, /* Size */
+ buffer) /* Buffer */
+ == SANE_STATUS_GOOD)
+ rst = size;
+ else
+ rst = -1;
+ }
+#endif
+
+ if (rst < 0)
+ DBG (DBG_CTL, " : Error, returned %i\n", rst);
+
+ return rst;
+}
+
+static SANE_Int
+usb_ctl_read (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer,
+ SANE_Int size, SANE_Int index)
+{
+ SANE_Int rst;
+
+ rst = ERROR;
+
+ dataline_count++;
+ DBG (DBG_CTL, "%06i CTL DI: c0 04 %04x %04x %04x\n",
+ dataline_count, address & 0xffff, index, size);
+
+#ifdef STANDALONE
+ if (usb_handle != NULL)
+ rst = usb_control_msg (usb_handle, 0xc0, /* Request type */
+ 0x04, /* Request */
+ address, /* Value */
+ index, /* Index */
+ (char *) buffer, /* Buffer */
+ size, /* Size */
+ TIMEOUT);
+#else
+ if (usb_handle != -1)
+ {
+ if (sanei_usb_control_msg (usb_handle, 0xc0, /* Request type */
+ 0x04, /* Request */
+ address, /* Value */
+ index, /* Index */
+ size, /* Size */
+ buffer) /* Buffer */
+ == SANE_STATUS_GOOD)
+ rst = size;
+ else
+ rst = -1;
+ }
+#endif
+
+ if (rst < 0)
+ DBG (DBG_CTL, " : Error, returned %i\n", rst);
+ else
+ show_buffer (DBG_CTL, buffer, rst);
+
+ return rst;
+}
+
+static SANE_Int
+show_buffer (SANE_Int level, SANE_Byte * buffer, SANE_Int size)
+{
+ if (DBG_LEVEL >= level)
+ {
+ char *sline = NULL;
+ char *sdata = NULL;
+ SANE_Int cont, data, offset = 0, col = 0;
+
+ if ((size > 0) && (buffer != NULL))
+ {
+ sline = (char *) malloc (256);
+ if (sline != NULL)
+ {
+ sdata = (char *) malloc (256);
+ if (sdata != NULL)
+ {
+ bzero (sline, 256);
+ for (cont = 0; cont < size; cont++)
+ {
+ if (col == 0)
+ {
+ if (cont == 0)
+ snprintf (sline, 255, " BF: ");
+ else
+ snprintf (sline, 255, " ");
+ }
+ data = (buffer[cont] & 0xff);
+ snprintf (sdata, 255, "%02x ", data);
+ sline = strcat (sline, sdata);
+ col++;
+ offset++;
+ if (col == 8)
+ {
+ col = 0;
+ snprintf (sdata, 255, " : %i\n", offset - 8);
+ sline = strcat (sline, sdata);
+ DBG (level, "%s", sline);
+ bzero (sline, 256);
+ }
+ }
+ if (col > 0)
+ {
+ for (cont = col; cont < 8; cont++)
+ {
+ snprintf (sdata, 255, "-- ");
+ sline = strcat (sline, sdata);
+ offset++;
+ }
+ snprintf (sdata, 255, " : %i\n", offset - 8);
+ sline = strcat (sline, sdata);
+ DBG (level, "%s", sline);
+ bzero (sline, 256);
+ }
+ free (sdata);
+ }
+ free (sline);
+ }
+ }
+ else
+ DBG (level, " BF: Empty buffer\n");
+ }
+ return OK;
+}
+#endif /*USBLAYER*/