diff options
Diffstat (limited to 'backend/niash_xfer.c')
-rw-r--r-- | backend/niash_xfer.c | 330 |
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); +} |