• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* sane - Scanner Access Now Easy.
2    Copyright (C) Marian Eichholz 2001
3    This file is part of the SANE package.
4 
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 
18    As a special exception, the authors of SANE give permission for
19    additional uses of the libraries contained in this release of SANE.
20 
21    The exception is that, if you link a SANE library with other files
22    to produce an executable, this does not by itself cause the
23    resulting executable to be covered by the GNU General Public
24    License.  Your use of that executable is in no way restricted on
25    account of linking the SANE library code into it.
26 
27    This exception does not, however, invalidate any other reasons why
28    the executable file might be covered by the GNU General Public
29    License.
30 
31    If you submit changes to SANE to the maintainers to be included in
32    a subsequent release, you agree by submitting the changes that
33    those changes may be distributed with this exception intact.
34 
35    If you write modifications of your own for SANE, it is your choice
36    whether to permit this exception to apply to your modifications.
37    If you do not wish that, delete this exception notice.
38 */
39 
40 /* ======================================================================
41 
42 Userspace scan tool for the Microtek 3600 scanner
43 
44 (C) Marian Eichholz 2001
45 
46 26.4.2001: Added an abstraction layer for TransferControlMsg.
47 
48 ====================================================================== */
49 
50 #include "sm3600-scantool.h"
51 
52 /* **********************************************************************
53 
54 TransferControlMsg()
55 
56 ********************************************************************** */
57 
TransferControlMsg(TInstance * this,int nReqType,int nRequest,int nValue,int nIndex,void * pBuffer,int cchBuffer,int cJiffiesTimeout)58 static int TransferControlMsg(TInstance *this,
59 		       int nReqType,
60 		       int nRequest,
61 		       int nValue,
62 		       int nIndex,
63 		       void *pBuffer,
64 		       int  cchBuffer,
65 		       int  cJiffiesTimeout)
66 {
67   SANE_Status err;
68 
69   (void) cJiffiesTimeout;
70 
71   err = sanei_usb_control_msg (this->hScanner,
72 			 nReqType,
73 			 nRequest,
74 			 nValue,
75 			 nIndex,
76 			 cchBuffer,
77 			 pBuffer);
78   if (err)
79     return err;
80   return cchBuffer;
81 }
82 
83 /* **********************************************************************
84 
85 cch=BulkRead()
86 
87 ********************************************************************** */
88 
TransferBulkRead(TInstance * this,int nEndPoint,void * pBuffer,int cchMax,int cJiffiesTimeout)89 static int TransferBulkRead(TInstance *this,
90 	     int nEndPoint,
91 	     void *pBuffer,
92 	     int cchMax,
93 	     int cJiffiesTimeout)
94 {
95   int err;
96   size_t sz = cchMax;
97 
98   (void) nEndPoint;
99   (void) cJiffiesTimeout;
100 
101   err = sanei_usb_read_bulk(this->hScanner,
102 			    pBuffer,
103 			    &sz);
104   if (err)
105     return err;
106   return sz;
107 }
108 
109 /* **********************************************************************
110 
111 RegWrite(iRegister, cb, ulValue)
112 RegWriteArray(iRegister, cb, unsigned char uchValues)
113 
114 ********************************************************************** */
115 
116 __SM3600EXPORT__
RegWrite(TInstance * this,int iRegister,int cb,unsigned long ulValue)117 TState RegWrite(TInstance *this, int iRegister, int cb, unsigned long ulValue)
118 {
119   char *pchBuffer;
120   int   i;
121   TBool bOk=true;
122   INST_ASSERT();
123   /* some rough assertions */
124   if (cb<1 || cb>4)
125   return SetError(this,SANE_STATUS_INVAL,"unsupported control transfer size %d",cb);
126   pchBuffer=malloc(cb);
127   CHECK_POINTER(pchBuffer);
128   for (i=0; i<cb; i++)
129   {
130     pchBuffer[i]=(char)(ulValue&0xFF);
131     ulValue=ulValue>>8;
132   }
133   if (!bOk)
134   {
135     free(pchBuffer);
136     return SetError(this,SANE_STATUS_IO_ERROR,
137 		    "error in reg out: %d,%d,%08X",iRegister,cb,ulValue);
138   }
139   i=TransferControlMsg(this,  /* handle */
140 		    0x40,                  /* request type */
141 		    0x08,                  /* request */
142 		    iRegister,             /* value */
143 		    0,                     /* index */
144 		    pchBuffer, cb,         /* bytes, size */
145 		    USB_TIMEOUT_JIFFIES);                /* TO, jiffies... */
146   free(pchBuffer);
147   if (i<0)
148     return SetError(this,SANE_STATUS_IO_ERROR,"error during register write");
149   return SANE_STATUS_GOOD;
150 }
151 
152 __SM3600EXPORT__
RegWriteArray(TInstance * this,int iRegister,int cb,unsigned char * pchBuffer)153 TState RegWriteArray(TInstance *this, int iRegister, int cb, unsigned char *pchBuffer)
154 {
155   int   i;
156   INST_ASSERT();
157   /* some rough assertions */
158   i=TransferControlMsg(this,        /* handle */
159 		    0x40,                  /* request type */
160 		    0x08,                  /* request */
161 		    iRegister,             /* value */
162 		    0,                     /* index */
163 		    pchBuffer, cb,         /* bytes, size */
164 		    USB_TIMEOUT_JIFFIES);                /* TO, jiffies... */
165   if (i<0)
166     return SetError(this,SANE_STATUS_IO_ERROR,"error during register write");
167   return SANE_STATUS_GOOD;
168 }
169 
170 /* **********************************************************************
171 
172 MemWriteArray(iAddress, cb, ulValue)
173 
174 ********************************************************************** */
175 
176 __SM3600EXPORT__
MemWriteArray(TInstance * this,int iAddress,int cb,unsigned char * pchBuffer)177 TState MemWriteArray(TInstance *this, int iAddress,
178 		     int cb, unsigned char *pchBuffer)
179 {
180   int   i;
181   INST_ASSERT();
182   /* some rough assertions */
183   i=TransferControlMsg(this,
184 		    0x40,                  /* request type */
185 		    0x09,                  /* request */
186 		    iAddress,              /* value */
187 		    0,                     /* index */
188 		    pchBuffer, cb,         /* bytes, size */
189 		    10000);                /* TO, jiffies... */
190   if (i<0)
191     return SetError(this,SANE_STATUS_IO_ERROR,"error during memory write");
192   return SANE_STATUS_GOOD;
193 }
194 
195 /* **********************************************************************
196 
197 MemReadArray(iRegister, cb, ulValue)
198 
199 ********************************************************************** */
200 
201 #ifdef INSANE_VERSION
202 
203 __SM3600EXPORT__
MemReadArray(TInstance * this,int iAddress,int cb,unsigned char * pchBuffer)204 TState MemReadArray(TInstance *this, int iAddress, int cb, unsigned char *pchBuffer)
205 {
206   int   i;
207   INST_ASSERT();
208   /* some rough assertions */
209   i=TransferControlMsg(this,
210 		    0xC0,                  /* request type */
211 		    0x01,                  /* request */
212 		    iAddress,              /* value */
213 		    0,                     /* index */
214 		    pchBuffer, cb,         /* bytes, size */
215 		    USB_TIMEOUT_JIFFIES);                /* TO, jiffies... */
216   if (i<0)
217     return SetError(this,SANE_STATUS_IO_ERROR,"error during memory read");
218   return SANE_STATUS_GOOD;
219 }
220 
221 /* **********************************************************************
222 
223 RegCheck(iRegister, cb, ulValue)
224 
225 ********************************************************************** */
226 
227 __SM3600EXPORT__
RegCheck(TInstance * this,int iRegister,int cch,unsigned long ulValue)228 TState RegCheck(TInstance *this, int iRegister, int cch, unsigned long ulValue)
229 {
230   char *pchBuffer,*pchTransfer;
231   int   i,rcCode;
232   TBool bOk;
233   INST_ASSERT();
234   if (cch<1 || cch>3)
235     return SetError(this,SANE_STATUS_INVAL,"unsupported control transfer size %d",cch);
236   pchBuffer=malloc(cch);
237   pchTransfer=calloc(1,cch);
238   rcCode=SANE_STATUS_GOOD;
239   if (!pchBuffer || !pchTransfer)
240     {
241       if (pchBuffer) free(pchBuffer);
242       if (pchTransfer) free(pchTransfer);
243       rcCode=SetError(this, SANE_STATUS_NO_MEM, "no memory in RegCheck()");
244     }
245   bOk=true;
246   for (i=0; !rcCode && i<cch; i++)
247     {
248       pchBuffer[i]=(char)(ulValue&0x00FF);
249       ulValue=(ulValue>>8);
250     }
251   if (!rcCode)
252     {
253       if (!bOk)
254 	rcCode=SetError(this,SANE_STATUS_IO_ERROR,
255 			"error in reg out: %d,%d,%08X",iRegister,cch,ulValue);
256       else
257 	{
258 	  i=TransferControlMsg(this,  /* handle */
259 		    0xC0,                  /* request type */
260 		    0x00,                  /* request */
261 		    iRegister,             /* value */
262 		    0,                     /* index */
263 		    pchTransfer, cch,      /* bytes, size */
264 		    USB_TIMEOUT_JIFFIES);                /* TO, jiffies... */
265 	  if (i<0)
266 	    rcCode=SetError(this,SANE_STATUS_IO_ERROR,
267 			    "error during register check");
268 	}
269     }
270   if (!rcCode && memcmp(pchTransfer,pchBuffer,cch))
271     {
272       DumpBuffer(stdout,pchTransfer,cch);
273       rcCode=SetError(this,SANE_STATUS_IO_ERROR,
274 		      "check register failed for %d,%d,%08X",
275 		      iRegister,cch,ulValue);
276     }
277   free(pchTransfer); free(pchBuffer);
278   return rcCode;
279 }
280 
281 /* **********************************************************************
282 
283 cchRead=BulkRead(fh,cchBulk)
284 
285 ********************************************************************** */
286 
287 __SM3600EXPORT__
BulkRead(TInstance * this,FILE * fhOut,unsigned int cchBulk)288 int BulkRead(TInstance *this, FILE *fhOut, unsigned int cchBulk)
289 {
290   int   cchRead,rc;
291   char *pchBuffer;
292   INST_ASSERT();
293   pchBuffer=(char*)malloc(cchBulk);
294   CHECK_POINTER(pchBuffer);
295   cchRead=0;
296   rc=0;
297   while (!rc && cchBulk)
298     {
299       int cchChunk;
300       int cchReal;
301 
302       cchChunk=cchBulk;
303       if (cchChunk>0x1000)
304 	cchChunk=0x1000;
305       cchReal=TransferBulkRead(this,
306 		       0x82,
307 		       pchBuffer+cchRead,
308 		       cchChunk,
309 		       USB_TIMEOUT_JIFFIES);
310       dprintf(DEBUG_COMM,"bulk read: %d -> %d\n",cchChunk,cchReal);
311       if (cchReal>=0)
312 	{
313 	  cchBulk-=cchReal;
314 	  cchRead+=cchReal;
315 	  if (cchReal<cchChunk) /* last Chunk of a series */
316 	    break;
317 	}
318       else
319 	{
320 	  rc=SetError(this,SANE_STATUS_IO_ERROR,
321 		      "bulk read of %d bytes failed: %s",
322 		      cchChunk,
323 		      "I/O error"
324 		      );
325 	  continue;
326 	}
327     }
328   dprintf(DEBUG_COMM,"writing %d bytes\n",cchRead);
329   if (fhOut && !rc)
330     {
331       fwrite(pchBuffer,1,cchRead,fhOut);
332       if (ferror(fhOut))
333 	rc=SetError(this,SANE_STATUS_IO_ERROR,
334 		    "scan file write failed: %s",
335 		    strerror(errno));
336     }
337   free(pchBuffer);
338   return rc ? -1 : cchRead;
339 }
340 
341 #endif
342 
343 /* **********************************************************************
344 
345 cchRead=BulkReadBuffer(puchBuffer, cchBulk)
346 
347 ********************************************************************** */
348 
349 __SM3600EXPORT__
BulkReadBuffer(TInstance * this,unsigned char * puchBufferOut,unsigned int cchBulk)350 int BulkReadBuffer(TInstance *this,
351 		   unsigned char *puchBufferOut,
352 		   unsigned int cchBulk)
353 {
354   int   cchRead,rc;
355   char *pchBuffer;
356   INST_ASSERT();
357   pchBuffer=(char*)malloc(cchBulk);
358   CHECK_POINTER(pchBuffer);
359   cchRead=0;
360   rc=0;
361   while (!rc && cchBulk)
362     {
363       int cchChunk;
364       int cchReal;
365 
366       cchChunk=cchBulk;
367       if (cchChunk>0x1000)
368 	cchChunk=0x1000;
369       cchReal=TransferBulkRead(this,
370 		       0x82,
371 		       pchBuffer+cchRead,
372 		       cchChunk,
373 		       USB_TIMEOUT_JIFFIES);
374       dprintf(DEBUG_COMM,"bulk read: %d -> %d\n",cchChunk,cchReal);
375       if (cchReal>=0)
376 	{
377 	  cchBulk-=cchReal;
378 	  cchRead+=cchReal;
379 	  if (cchReal<cchChunk) /* last Chunk of a series */
380 	    break;
381 	}
382       else
383 	rc=SetError(this,SANE_STATUS_IO_ERROR,
384 		    "bulk read of %d bytes failed: %s",
385 		    cchChunk,
386 		    "I/O error"
387 		    );
388     }
389   dprintf(DEBUG_COMM,"writing %d bytes\n",cchRead);
390 
391   if (!rc && puchBufferOut)
392     memcpy(puchBufferOut,pchBuffer,cchRead);
393   free(pchBuffer);
394   return rc ? -1 : cchRead;
395 }
396 
397 /* **********************************************************************
398 
399 RegRead(iRegister, int cch)
400 
401 Read register in big endian (INTEL-) format.
402 
403 ********************************************************************** */
404 
405 __SM3600EXPORT__
RegRead(TInstance * this,int iRegister,int cch)406 unsigned int RegRead(TInstance *this, int iRegister, int cch)
407 {
408   char        *pchTransfer;
409   int          i;
410   unsigned int n;
411   INST_ASSERT();
412   if (cch<1 || cch>4)
413     {
414       SetError(this,SANE_STATUS_INVAL,
415 		    "unsupported control read size %d",cch);
416       return 0;
417     }
418   pchTransfer=calloc(1,cch);
419   CHECK_POINTER(pchTransfer);
420   i=TransferControlMsg(this,  /* handle */
421         0xC0,                  /* request type */
422 	0x00,                  /* request */
423 	iRegister,             /* value */
424 	0,                     /* index */
425 	pchTransfer, cch,      /* bytes, size */
426 	USB_TIMEOUT_JIFFIES);                /* TO, jiffies... */
427   if (i>=0)
428     {
429       n=0;
430       for (i=cch-1; i>=0; i--)
431 	n=(n<<8)|(unsigned char)pchTransfer[i];
432       free(pchTransfer);
433       return n;
434     }
435   free(pchTransfer);
436   SetError(this,SANE_STATUS_IO_ERROR,"error during register read");
437   return 0;
438 }
439