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