summaryrefslogtreecommitdiff
path: root/backend/niash_xfer.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/niash_xfer.c')
-rw-r--r--backend/niash_xfer.c330
1 files changed, 330 insertions, 0 deletions
diff --git a/backend/niash_xfer.c b/backend/niash_xfer.c
new file mode 100644
index 0000000..a3d0ea2
--- /dev/null
+++ b/backend/niash_xfer.c
@@ -0,0 +1,330 @@
+/*
+ Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
+
+ 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.
+
+ $Id$
+*/
+
+/*
+ Provides a simple interface to read and write data from the scanner,
+ without any knowledge whether it's a parallel or USB scanner
+*/
+
+#include <stdio.h> /* printf */
+#include <errno.h> /* better error reports */
+#include <string.h> /* better error reports */
+
+#include "niash_xfer.h"
+
+#include "../include/sane/sanei_usb.h"
+
+/* list of supported models */
+STATIC TScannerModel ScannerModels[] = {
+ {"Hewlett-Packard", "ScanJet 3300C", 0x3F0, 0x205, eHp3300c}
+ ,
+ {"Hewlett-Packard", "ScanJet 3400C", 0x3F0, 0x405, eHp3400c}
+ ,
+ {"Hewlett-Packard", "ScanJet 4300C", 0x3F0, 0x305, eHp4300c}
+ ,
+ {"Silitek Corp.", "HP ScanJet 4300c", 0x47b, 0x1002, eHp3400c}
+ ,
+ {"Agfa", "Snapscan Touch", 0x6BD, 0x100, eAgfaTouch}
+ ,
+ {"Trust", "Office Scanner USB 19200", 0x47b, 0x1000, eAgfaTouch}
+ ,
+/* last entry all zeros */
+ {0, 0, 0, 0, 0}
+};
+
+static TFnReportDevice *_pfnReportDevice;
+static TScannerModel *_pModel;
+
+/*
+ MatchUsbDevice
+ ==============
+ Matches a given USB vendor and product id against a list of
+ supported scanners.
+
+ IN iVendor USB vendor ID
+ iProduct USB product ID
+ OUT *ppModel Pointer to TScannerModel structure
+
+ Returns TRUE if a matching USB scanner was found
+*/
+STATIC SANE_Bool
+MatchUsbDevice (int iVendor, int iProduct, TScannerModel ** ppModel)
+{
+ TScannerModel *pModels = ScannerModels;
+
+ DBG (DBG_MSG, "Matching USB device 0x%04X-0x%04X ... ", iVendor, iProduct);
+ while (pModels->pszName != NULL)
+ {
+ if ((pModels->iVendor == iVendor) && (pModels->iProduct == iProduct))
+ {
+ DBG (DBG_MSG, "found %s %s\n", pModels->pszVendor,
+ pModels->pszName);
+ *ppModel = pModels;
+ return SANE_TRUE;
+ }
+ /* next model to match */
+ pModels++;
+ }
+ DBG (DBG_MSG, "nothing found\n");
+ return SANE_FALSE;
+}
+
+/************************************************************************
+ Public functions for the SANE compilation
+************************************************************************/
+
+
+/* callback for sanei_usb_attach_matching_devices */
+static SANE_Status
+_AttachUsb (SANE_String_Const devname)
+{
+ DBG (DBG_MSG, "_AttachUsb: found %s\n", devname);
+
+ _pfnReportDevice (_pModel, (const char *) devname);
+
+ return SANE_STATUS_GOOD;
+}
+
+
+/*
+ NiashXferInit
+ ===============
+ Initialises all registered data transfer modules, which causes
+ them to report any devices found through the pfnReport callback.
+
+ IN pfnReport Function to call to report a transfer device
+*/
+static void
+NiashXferInit (TFnReportDevice * pfnReport)
+{
+ TScannerModel *pModels = ScannerModels;
+
+ sanei_usb_init ();
+ _pfnReportDevice = pfnReport;
+
+ /* loop over all scanner models */
+ while (pModels->pszName != NULL)
+ {
+ DBG (DBG_MSG, "Looking for %s...\n", pModels->pszName);
+ _pModel = pModels;
+ if (sanei_usb_find_devices ((SANE_Int) pModels->iVendor,
+ (SANE_Int) pModels->iProduct,
+ _AttachUsb) != SANE_STATUS_GOOD)
+ {
+
+ DBG (DBG_ERR, "Error invoking sanei_usb_find_devices");
+ break;
+ }
+ pModels++;
+ }
+}
+
+
+static int
+NiashXferOpen (const char *pszName, EScannerModel * peModel)
+{
+ SANE_Status status;
+ SANE_Word vendor, product;
+ int fd;
+ TScannerModel *pModel = 0;
+
+ DBG (DBG_MSG, "Trying to open %s...\n", pszName);
+
+ status = sanei_usb_open (pszName, &fd);
+ if (status != SANE_STATUS_GOOD)
+ {
+ return -1;
+ }
+
+ status = sanei_usb_get_vendor_product (fd, &vendor, &product);
+ if (status == SANE_STATUS_GOOD)
+ {
+ MatchUsbDevice (vendor, product, &pModel);
+ *peModel = pModel->eModel;
+ }
+
+ DBG (DBG_MSG, "handle = %d\n", (int) fd);
+ return fd;
+}
+
+
+static void
+NiashXferClose (int iHandle)
+{
+ /* close usb device */
+ if (iHandle != -1)
+ {
+ sanei_usb_close (iHandle);
+ }
+}
+
+
+static void
+parusb_write_reg (int fd, unsigned char bReg, unsigned char bValue)
+{
+ sanei_usb_control_msg (fd,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+ 0x0C, bReg, 0, 1, &bValue);
+}
+
+
+static void
+parusb_read_reg (int fd, unsigned char bReg, unsigned char *pbValue)
+{
+ sanei_usb_control_msg (fd,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+ 0x0C, bReg, 0, 1, pbValue);
+}
+
+
+static void
+NiashWriteReg (int iHandle, unsigned char bReg, unsigned char bData)
+{
+ if (iHandle < 0)
+ {
+ DBG (DBG_MSG, "Invalid handle %d\n", iHandle);
+ return;
+ }
+
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+ parusb_write_reg (iHandle, EPP_ADDR, bReg);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+ parusb_write_reg (iHandle, EPP_DATA_WRITE, bData);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+}
+
+
+static void
+NiashReadReg (int iHandle, unsigned char bReg, unsigned char *pbData)
+{
+ if (iHandle < 0)
+ {
+ return;
+ }
+
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+ parusb_write_reg (iHandle, EPP_ADDR, bReg);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x34);
+ parusb_read_reg (iHandle, EPP_DATA_READ, pbData);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+}
+
+
+static void
+NiashWriteBulk (int iHandle, unsigned char *pabBuf, int iSize)
+{
+ /* byte abSetup[8] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ HP3400 probably needs 0x01, 0x01 */
+ SANE_Byte abSetup[8] = { 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ size_t size;
+
+ if (iHandle < 0)
+ {
+ return;
+ }
+
+ /* select scanner register 0x24 */
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+ parusb_write_reg (iHandle, EPP_ADDR, 0x24);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+
+ /* tell scanner that a bulk transfer follows */
+ abSetup[4] = (iSize) & 0xFF;
+ abSetup[5] = (iSize >> 8) & 0xFF;
+ sanei_usb_control_msg (iHandle,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+ 0x04, USB_SETUP, 0, 8, abSetup);
+
+ /* do the bulk write */
+ size = iSize;
+ if (sanei_usb_write_bulk (iHandle, pabBuf, &size) != SANE_STATUS_GOOD)
+ {
+ DBG (DBG_ERR, "ERROR: Bulk write failed\n");
+ }
+}
+
+
+static void
+NiashReadBulk (int iHandle, unsigned char *pabBuf, int iSize)
+{
+ SANE_Byte abSetup[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ size_t size;
+
+ if (iHandle < 0)
+ {
+ return;
+ }
+
+ /* select scanner register 0x24 */
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+ parusb_write_reg (iHandle, EPP_ADDR, 0x24);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+
+ /* tell scanner that a bulk transfer follows */
+ abSetup[4] = (iSize) & 0xFF;
+ abSetup[5] = (iSize >> 8) & 0xFF;
+ sanei_usb_control_msg (iHandle,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+ 0x04, USB_SETUP, 0, 8, abSetup);
+
+ /* do the bulk read */
+ size = iSize;
+ if (sanei_usb_read_bulk (iHandle, pabBuf, &size) != SANE_STATUS_GOOD)
+ {
+ DBG (DBG_ERR, "ERROR: Bulk read failed\n");
+ }
+}
+
+
+static void
+NiashWakeup (int iHandle)
+{
+ unsigned char abMagic[] = { 0xA0, 0xA8, 0x50, 0x58, 0x90, 0x98, 0xC0, 0xC8,
+ 0x90, 0x98, 0xE0, 0xE8
+ };
+ int i;
+
+ if (iHandle < 0)
+ {
+ return;
+ }
+
+ /* write magic startup sequence */
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+ for (i = 0; i < (int) sizeof (abMagic); i++)
+ {
+ parusb_write_reg (iHandle, SPP_DATA, abMagic[i]);
+ }
+
+ /* write 0x04 to scanner register 0x00 the hard way */
+ parusb_write_reg (iHandle, SPP_DATA, 0x00);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x15);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x1D);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x15);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+
+ parusb_write_reg (iHandle, SPP_DATA, 0x04);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x15);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x17);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x15);
+ parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
+}