• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2   Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
3 
4   This program is free software; you can redistribute it and/or
5   modify it under the terms of the GNU General Public License
6   as published by the Free Software Foundation; either version 2
7   of the License, or (at your option) any later version.
8 
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13 
14   You should have received a copy of the GNU General Public License
15   along with this program.  If not, see <https://www.gnu.org/licenses/>.
16 */
17 
18 /*
19         Provides a simple interface to read and write data from the scanner,
20         without any knowledge whether it's a parallel or USB scanner
21 */
22 
23 #include <stdio.h>              /* printf */
24 #include <errno.h>              /* better error reports */
25 #include <string.h>             /* better error reports */
26 
27 #include "niash_xfer.h"
28 
29 #include "../include/sane/sanei_usb.h"
30 
31 /* list of supported models */
32 STATIC TScannerModel ScannerModels[] = {
33   {"Hewlett-Packard", "ScanJet 3300C", 0x3F0, 0x205, eHp3300c}
34   ,
35   {"Hewlett-Packard", "ScanJet 3400C", 0x3F0, 0x405, eHp3400c}
36   ,
37   {"Hewlett-Packard", "ScanJet 4300C", 0x3F0, 0x305, eHp4300c}
38   ,
39   {"Silitek Corp.", "HP ScanJet 4300c", 0x47b, 0x1002, eHp3400c}
40   ,
41   {"Agfa", "Snapscan Touch", 0x6BD, 0x100, eAgfaTouch}
42   ,
43   {"Trust", "Office Scanner USB 19200", 0x47b, 0x1000, eAgfaTouch}
44   ,
45 /* last entry all zeros */
46   {0, 0, 0, 0, 0}
47 };
48 
49 static TFnReportDevice *_pfnReportDevice;
50 static TScannerModel *_pModel;
51 
52 /*
53   MatchUsbDevice
54   ==============
55         Matches a given USB vendor and product id against a list of
56         supported scanners.
57 
58   IN  iVendor   USB vendor ID
59           iProduct  USB product ID
60   OUT *ppModel  Pointer to TScannerModel structure
61 
62   Returns TRUE if a matching USB scanner was found
63 */
64 STATIC SANE_Bool
MatchUsbDevice(int iVendor,int iProduct,TScannerModel ** ppModel)65 MatchUsbDevice (int iVendor, int iProduct, TScannerModel ** ppModel)
66 {
67   TScannerModel *pModels = ScannerModels;
68 
69   DBG (DBG_MSG, "Matching USB device 0x%04X-0x%04X ... ", iVendor, iProduct);
70   while (pModels->pszName != NULL)
71     {
72       if ((pModels->iVendor == iVendor) && (pModels->iProduct == iProduct))
73         {
74           DBG (DBG_MSG, "found %s %s\n", pModels->pszVendor,
75                pModels->pszName);
76           *ppModel = pModels;
77           return SANE_TRUE;
78         }
79       /* next model to match */
80       pModels++;
81     }
82   DBG (DBG_MSG, "nothing found\n");
83   return SANE_FALSE;
84 }
85 
86 /************************************************************************
87   Public functions for the SANE compilation
88 ************************************************************************/
89 
90 
91 /* callback for sanei_usb_attach_matching_devices */
92 static SANE_Status
_AttachUsb(SANE_String_Const devname)93 _AttachUsb (SANE_String_Const devname)
94 {
95   DBG (DBG_MSG, "_AttachUsb: found %s\n", devname);
96 
97   _pfnReportDevice (_pModel, (const char *) devname);
98 
99   return SANE_STATUS_GOOD;
100 }
101 
102 
103 /*
104   NiashXferInit
105   ===============
106         Initialises all registered data transfer modules, which causes
107         them to report any devices found through the pfnReport callback.
108 
109   IN  pfnReport Function to call to report a transfer device
110 */
111 static void
NiashXferInit(TFnReportDevice * pfnReport)112 NiashXferInit (TFnReportDevice * pfnReport)
113 {
114   TScannerModel *pModels = ScannerModels;
115 
116   sanei_usb_init ();
117   _pfnReportDevice = pfnReport;
118 
119   /* loop over all scanner models */
120   while (pModels->pszName != NULL)
121     {
122       DBG (DBG_MSG, "Looking for %s...\n", pModels->pszName);
123       _pModel = pModels;
124       if (sanei_usb_find_devices ((SANE_Int) pModels->iVendor,
125                                   (SANE_Int) pModels->iProduct,
126                                   _AttachUsb) != SANE_STATUS_GOOD)
127         {
128 
129           DBG (DBG_ERR, "Error invoking sanei_usb_find_devices");
130           break;
131         }
132       pModels++;
133     }
134 }
135 
136 
137 static int
NiashXferOpen(const char * pszName,EScannerModel * peModel)138 NiashXferOpen (const char *pszName, EScannerModel * peModel)
139 {
140   SANE_Status status;
141   SANE_Word vendor, product;
142   int fd;
143   TScannerModel *pModel = 0;
144 
145   DBG (DBG_MSG, "Trying to open %s...\n", pszName);
146 
147   status = sanei_usb_open (pszName, &fd);
148   if (status != SANE_STATUS_GOOD)
149     {
150       return -1;
151     }
152 
153   status = sanei_usb_get_vendor_product (fd, &vendor, &product);
154   if (status == SANE_STATUS_GOOD)
155     {
156       MatchUsbDevice (vendor, product, &pModel);
157       *peModel = pModel->eModel;
158     }
159 
160   DBG (DBG_MSG, "handle = %d\n", (int) fd);
161   return fd;
162 }
163 
164 
165 static void
NiashXferClose(int iHandle)166 NiashXferClose (int iHandle)
167 {
168   /* close usb device */
169   if (iHandle != -1)
170     {
171       sanei_usb_close (iHandle);
172     }
173 }
174 
175 
176 static void
parusb_write_reg(int fd,unsigned char bReg,unsigned char bValue)177 parusb_write_reg (int fd, unsigned char bReg, unsigned char bValue)
178 {
179   sanei_usb_control_msg (fd,
180                          USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
181                          0x0C, bReg, 0, 1, &bValue);
182 }
183 
184 
185 static void
parusb_read_reg(int fd,unsigned char bReg,unsigned char * pbValue)186 parusb_read_reg (int fd, unsigned char bReg, unsigned char *pbValue)
187 {
188   sanei_usb_control_msg (fd,
189                          USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
190                          0x0C, bReg, 0, 1, pbValue);
191 }
192 
193 
194 static void
NiashWriteReg(int iHandle,unsigned char bReg,unsigned char bData)195 NiashWriteReg (int iHandle, unsigned char bReg, unsigned char bData)
196 {
197   if (iHandle < 0)
198     {
199       DBG (DBG_MSG, "Invalid handle %d\n", iHandle);
200       return;
201     }
202 
203   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
204   parusb_write_reg (iHandle, EPP_ADDR, bReg);
205   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
206   parusb_write_reg (iHandle, EPP_DATA_WRITE, bData);
207   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
208 }
209 
210 
211 static void
NiashReadReg(int iHandle,unsigned char bReg,unsigned char * pbData)212 NiashReadReg (int iHandle, unsigned char bReg, unsigned char *pbData)
213 {
214   if (iHandle < 0)
215     {
216       return;
217     }
218 
219   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
220   parusb_write_reg (iHandle, EPP_ADDR, bReg);
221   parusb_write_reg (iHandle, SPP_CONTROL, 0x34);
222   parusb_read_reg (iHandle, EPP_DATA_READ, pbData);
223   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
224 }
225 
226 
227 static void
NiashWriteBulk(int iHandle,unsigned char * pabBuf,int iSize)228 NiashWriteBulk (int iHandle, unsigned char *pabBuf, int iSize)
229 {
230   /*  byte  abSetup[8] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
231      HP3400 probably needs 0x01, 0x01 */
232   SANE_Byte abSetup[8] = { 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
233   size_t size;
234 
235   if (iHandle < 0)
236     {
237       return;
238     }
239 
240   /* select scanner register 0x24 */
241   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
242   parusb_write_reg (iHandle, EPP_ADDR, 0x24);
243   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
244 
245   /* tell scanner that a bulk transfer follows */
246   abSetup[4] = (iSize) & 0xFF;
247   abSetup[5] = (iSize >> 8) & 0xFF;
248   sanei_usb_control_msg (iHandle,
249                          USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
250                          0x04, USB_SETUP, 0, 8, abSetup);
251 
252   /* do the bulk write */
253   size = iSize;
254   if (sanei_usb_write_bulk (iHandle, pabBuf, &size) != SANE_STATUS_GOOD)
255     {
256       DBG (DBG_ERR, "ERROR: Bulk write failed\n");
257     }
258 }
259 
260 
261 static void
NiashReadBulk(int iHandle,unsigned char * pabBuf,int iSize)262 NiashReadBulk (int iHandle, unsigned char *pabBuf, int iSize)
263 {
264   SANE_Byte abSetup[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
265   size_t size;
266 
267   if (iHandle < 0)
268     {
269       return;
270     }
271 
272   /* select scanner register 0x24 */
273   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
274   parusb_write_reg (iHandle, EPP_ADDR, 0x24);
275   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
276 
277   /* tell scanner that a bulk transfer follows */
278   abSetup[4] = (iSize) & 0xFF;
279   abSetup[5] = (iSize >> 8) & 0xFF;
280   sanei_usb_control_msg (iHandle,
281                          USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
282                          0x04, USB_SETUP, 0, 8, abSetup);
283 
284   /* do the bulk read */
285   size = iSize;
286   if (sanei_usb_read_bulk (iHandle, pabBuf, &size) != SANE_STATUS_GOOD)
287     {
288       DBG (DBG_ERR, "ERROR: Bulk read failed\n");
289     }
290 }
291 
292 
293 static void
NiashWakeup(int iHandle)294 NiashWakeup (int iHandle)
295 {
296   unsigned char abMagic[] = { 0xA0, 0xA8, 0x50, 0x58, 0x90, 0x98, 0xC0, 0xC8,
297     0x90, 0x98, 0xE0, 0xE8
298   };
299   int i;
300 
301   if (iHandle < 0)
302     {
303       return;
304     }
305 
306   /* write magic startup sequence */
307   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
308   for (i = 0; i < (int) sizeof (abMagic); i++)
309     {
310       parusb_write_reg (iHandle, SPP_DATA, abMagic[i]);
311     }
312 
313   /* write 0x04 to scanner register 0x00 the hard way */
314   parusb_write_reg (iHandle, SPP_DATA, 0x00);
315   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
316   parusb_write_reg (iHandle, SPP_CONTROL, 0x15);
317   parusb_write_reg (iHandle, SPP_CONTROL, 0x1D);
318   parusb_write_reg (iHandle, SPP_CONTROL, 0x15);
319   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
320 
321   parusb_write_reg (iHandle, SPP_DATA, 0x04);
322   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
323   parusb_write_reg (iHandle, SPP_CONTROL, 0x15);
324   parusb_write_reg (iHandle, SPP_CONTROL, 0x17);
325   parusb_write_reg (iHandle, SPP_CONTROL, 0x15);
326   parusb_write_reg (iHandle, SPP_CONTROL, 0x14);
327 }
328