1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci   Copyright (C) Marian Eichholz 2001
3141cc406Sopenharmony_ci   This file is part of the SANE package.
4141cc406Sopenharmony_ci
5141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
6141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
7141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
8141cc406Sopenharmony_ci   License, or (at your option) any later version.
9141cc406Sopenharmony_ci
10141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
11141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
12141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13141cc406Sopenharmony_ci   General Public License for more details.
14141cc406Sopenharmony_ci
15141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
16141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17141cc406Sopenharmony_ci
18141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
19141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
20141cc406Sopenharmony_ci
21141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
22141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
23141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
24141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
25141cc406Sopenharmony_ci   account of linking the SANE library code into it.
26141cc406Sopenharmony_ci
27141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
28141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
29141cc406Sopenharmony_ci   License.
30141cc406Sopenharmony_ci
31141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
32141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
33141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
34141cc406Sopenharmony_ci
35141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
36141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
37141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
38141cc406Sopenharmony_ci*/
39141cc406Sopenharmony_ci
40141cc406Sopenharmony_ci/* ======================================================================
41141cc406Sopenharmony_ci
42141cc406Sopenharmony_ciUserspace scan tool for the Microtek 3600 scanner
43141cc406Sopenharmony_ci
44141cc406Sopenharmony_ci(C) Marian Eichholz 2001
45141cc406Sopenharmony_ci
46141cc406Sopenharmony_ci26.4.2001: Added an abstraction layer for TransferControlMsg.
47141cc406Sopenharmony_ci
48141cc406Sopenharmony_ci====================================================================== */
49141cc406Sopenharmony_ci
50141cc406Sopenharmony_ci#include "sm3600-scantool.h"
51141cc406Sopenharmony_ci
52141cc406Sopenharmony_ci/* **********************************************************************
53141cc406Sopenharmony_ci
54141cc406Sopenharmony_ciTransferControlMsg()
55141cc406Sopenharmony_ci
56141cc406Sopenharmony_ci********************************************************************** */
57141cc406Sopenharmony_ci
58141cc406Sopenharmony_cistatic int TransferControlMsg(TInstance *this,
59141cc406Sopenharmony_ci		       int nReqType,
60141cc406Sopenharmony_ci		       int nRequest,
61141cc406Sopenharmony_ci		       int nValue,
62141cc406Sopenharmony_ci		       int nIndex,
63141cc406Sopenharmony_ci		       void *pBuffer,
64141cc406Sopenharmony_ci		       int  cchBuffer,
65141cc406Sopenharmony_ci		       int  cJiffiesTimeout)
66141cc406Sopenharmony_ci{
67141cc406Sopenharmony_ci  SANE_Status err;
68141cc406Sopenharmony_ci
69141cc406Sopenharmony_ci  (void) cJiffiesTimeout;
70141cc406Sopenharmony_ci
71141cc406Sopenharmony_ci  err = sanei_usb_control_msg (this->hScanner,
72141cc406Sopenharmony_ci			 nReqType,
73141cc406Sopenharmony_ci			 nRequest,
74141cc406Sopenharmony_ci			 nValue,
75141cc406Sopenharmony_ci			 nIndex,
76141cc406Sopenharmony_ci			 cchBuffer,
77141cc406Sopenharmony_ci			 pBuffer);
78141cc406Sopenharmony_ci  if (err)
79141cc406Sopenharmony_ci    return err;
80141cc406Sopenharmony_ci  return cchBuffer;
81141cc406Sopenharmony_ci}
82141cc406Sopenharmony_ci
83141cc406Sopenharmony_ci/* **********************************************************************
84141cc406Sopenharmony_ci
85141cc406Sopenharmony_cicch=BulkRead()
86141cc406Sopenharmony_ci
87141cc406Sopenharmony_ci********************************************************************** */
88141cc406Sopenharmony_ci
89141cc406Sopenharmony_cistatic int TransferBulkRead(TInstance *this,
90141cc406Sopenharmony_ci	     int nEndPoint,
91141cc406Sopenharmony_ci	     void *pBuffer,
92141cc406Sopenharmony_ci	     int cchMax,
93141cc406Sopenharmony_ci	     int cJiffiesTimeout)
94141cc406Sopenharmony_ci{
95141cc406Sopenharmony_ci  int err;
96141cc406Sopenharmony_ci  size_t sz = cchMax;
97141cc406Sopenharmony_ci
98141cc406Sopenharmony_ci  (void) nEndPoint;
99141cc406Sopenharmony_ci  (void) cJiffiesTimeout;
100141cc406Sopenharmony_ci
101141cc406Sopenharmony_ci  err = sanei_usb_read_bulk(this->hScanner,
102141cc406Sopenharmony_ci			    pBuffer,
103141cc406Sopenharmony_ci			    &sz);
104141cc406Sopenharmony_ci  if (err)
105141cc406Sopenharmony_ci    return err;
106141cc406Sopenharmony_ci  return sz;
107141cc406Sopenharmony_ci}
108141cc406Sopenharmony_ci
109141cc406Sopenharmony_ci/* **********************************************************************
110141cc406Sopenharmony_ci
111141cc406Sopenharmony_ciRegWrite(iRegister, cb, ulValue)
112141cc406Sopenharmony_ciRegWriteArray(iRegister, cb, unsigned char uchValues)
113141cc406Sopenharmony_ci
114141cc406Sopenharmony_ci********************************************************************** */
115141cc406Sopenharmony_ci
116141cc406Sopenharmony_ci__SM3600EXPORT__
117141cc406Sopenharmony_ciTState RegWrite(TInstance *this, int iRegister, int cb, unsigned long ulValue)
118141cc406Sopenharmony_ci{
119141cc406Sopenharmony_ci  char *pchBuffer;
120141cc406Sopenharmony_ci  int   i;
121141cc406Sopenharmony_ci  TBool bOk=true;
122141cc406Sopenharmony_ci  INST_ASSERT();
123141cc406Sopenharmony_ci  /* some rough assertions */
124141cc406Sopenharmony_ci  if (cb<1 || cb>4)
125141cc406Sopenharmony_ci  return SetError(this,SANE_STATUS_INVAL,"unsupported control transfer size %d",cb);
126141cc406Sopenharmony_ci  pchBuffer=malloc(cb);
127141cc406Sopenharmony_ci  CHECK_POINTER(pchBuffer);
128141cc406Sopenharmony_ci  for (i=0; i<cb; i++)
129141cc406Sopenharmony_ci  {
130141cc406Sopenharmony_ci    pchBuffer[i]=(char)(ulValue&0xFF);
131141cc406Sopenharmony_ci    ulValue=ulValue>>8;
132141cc406Sopenharmony_ci  }
133141cc406Sopenharmony_ci  if (!bOk)
134141cc406Sopenharmony_ci  {
135141cc406Sopenharmony_ci    free(pchBuffer);
136141cc406Sopenharmony_ci    return SetError(this,SANE_STATUS_IO_ERROR,
137141cc406Sopenharmony_ci		    "error in reg out: %d,%d,%08X",iRegister,cb,ulValue);
138141cc406Sopenharmony_ci  }
139141cc406Sopenharmony_ci  i=TransferControlMsg(this,  /* handle */
140141cc406Sopenharmony_ci		    0x40,                  /* request type */
141141cc406Sopenharmony_ci		    0x08,                  /* request */
142141cc406Sopenharmony_ci		    iRegister,             /* value */
143141cc406Sopenharmony_ci		    0,                     /* index */
144141cc406Sopenharmony_ci		    pchBuffer, cb,         /* bytes, size */
145141cc406Sopenharmony_ci		    USB_TIMEOUT_JIFFIES);                /* TO, jiffies... */
146141cc406Sopenharmony_ci  free(pchBuffer);
147141cc406Sopenharmony_ci  if (i<0)
148141cc406Sopenharmony_ci    return SetError(this,SANE_STATUS_IO_ERROR,"error during register write");
149141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
150141cc406Sopenharmony_ci}
151141cc406Sopenharmony_ci
152141cc406Sopenharmony_ci__SM3600EXPORT__
153141cc406Sopenharmony_ciTState RegWriteArray(TInstance *this, int iRegister, int cb, unsigned char *pchBuffer)
154141cc406Sopenharmony_ci{
155141cc406Sopenharmony_ci  int   i;
156141cc406Sopenharmony_ci  INST_ASSERT();
157141cc406Sopenharmony_ci  /* some rough assertions */
158141cc406Sopenharmony_ci  i=TransferControlMsg(this,        /* handle */
159141cc406Sopenharmony_ci		    0x40,                  /* request type */
160141cc406Sopenharmony_ci		    0x08,                  /* request */
161141cc406Sopenharmony_ci		    iRegister,             /* value */
162141cc406Sopenharmony_ci		    0,                     /* index */
163141cc406Sopenharmony_ci		    pchBuffer, cb,         /* bytes, size */
164141cc406Sopenharmony_ci		    USB_TIMEOUT_JIFFIES);                /* TO, jiffies... */
165141cc406Sopenharmony_ci  if (i<0)
166141cc406Sopenharmony_ci    return SetError(this,SANE_STATUS_IO_ERROR,"error during register write");
167141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
168141cc406Sopenharmony_ci}
169141cc406Sopenharmony_ci
170141cc406Sopenharmony_ci/* **********************************************************************
171141cc406Sopenharmony_ci
172141cc406Sopenharmony_ciMemWriteArray(iAddress, cb, ulValue)
173141cc406Sopenharmony_ci
174141cc406Sopenharmony_ci********************************************************************** */
175141cc406Sopenharmony_ci
176141cc406Sopenharmony_ci__SM3600EXPORT__
177141cc406Sopenharmony_ciTState MemWriteArray(TInstance *this, int iAddress,
178141cc406Sopenharmony_ci		     int cb, unsigned char *pchBuffer)
179141cc406Sopenharmony_ci{
180141cc406Sopenharmony_ci  int   i;
181141cc406Sopenharmony_ci  INST_ASSERT();
182141cc406Sopenharmony_ci  /* some rough assertions */
183141cc406Sopenharmony_ci  i=TransferControlMsg(this,
184141cc406Sopenharmony_ci		    0x40,                  /* request type */
185141cc406Sopenharmony_ci		    0x09,                  /* request */
186141cc406Sopenharmony_ci		    iAddress,              /* value */
187141cc406Sopenharmony_ci		    0,                     /* index */
188141cc406Sopenharmony_ci		    pchBuffer, cb,         /* bytes, size */
189141cc406Sopenharmony_ci		    10000);                /* TO, jiffies... */
190141cc406Sopenharmony_ci  if (i<0)
191141cc406Sopenharmony_ci    return SetError(this,SANE_STATUS_IO_ERROR,"error during memory write");
192141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
193141cc406Sopenharmony_ci}
194141cc406Sopenharmony_ci
195141cc406Sopenharmony_ci/* **********************************************************************
196141cc406Sopenharmony_ci
197141cc406Sopenharmony_ciMemReadArray(iRegister, cb, ulValue)
198141cc406Sopenharmony_ci
199141cc406Sopenharmony_ci********************************************************************** */
200141cc406Sopenharmony_ci
201141cc406Sopenharmony_ci#ifdef INSANE_VERSION
202141cc406Sopenharmony_ci
203141cc406Sopenharmony_ci__SM3600EXPORT__
204141cc406Sopenharmony_ciTState MemReadArray(TInstance *this, int iAddress, int cb, unsigned char *pchBuffer)
205141cc406Sopenharmony_ci{
206141cc406Sopenharmony_ci  int   i;
207141cc406Sopenharmony_ci  INST_ASSERT();
208141cc406Sopenharmony_ci  /* some rough assertions */
209141cc406Sopenharmony_ci  i=TransferControlMsg(this,
210141cc406Sopenharmony_ci		    0xC0,                  /* request type */
211141cc406Sopenharmony_ci		    0x01,                  /* request */
212141cc406Sopenharmony_ci		    iAddress,              /* value */
213141cc406Sopenharmony_ci		    0,                     /* index */
214141cc406Sopenharmony_ci		    pchBuffer, cb,         /* bytes, size */
215141cc406Sopenharmony_ci		    USB_TIMEOUT_JIFFIES);                /* TO, jiffies... */
216141cc406Sopenharmony_ci  if (i<0)
217141cc406Sopenharmony_ci    return SetError(this,SANE_STATUS_IO_ERROR,"error during memory read");
218141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
219141cc406Sopenharmony_ci}
220141cc406Sopenharmony_ci
221141cc406Sopenharmony_ci/* **********************************************************************
222141cc406Sopenharmony_ci
223141cc406Sopenharmony_ciRegCheck(iRegister, cb, ulValue)
224141cc406Sopenharmony_ci
225141cc406Sopenharmony_ci********************************************************************** */
226141cc406Sopenharmony_ci
227141cc406Sopenharmony_ci__SM3600EXPORT__
228141cc406Sopenharmony_ciTState RegCheck(TInstance *this, int iRegister, int cch, unsigned long ulValue)
229141cc406Sopenharmony_ci{
230141cc406Sopenharmony_ci  char *pchBuffer,*pchTransfer;
231141cc406Sopenharmony_ci  int   i,rcCode;
232141cc406Sopenharmony_ci  TBool bOk;
233141cc406Sopenharmony_ci  INST_ASSERT();
234141cc406Sopenharmony_ci  if (cch<1 || cch>3)
235141cc406Sopenharmony_ci    return SetError(this,SANE_STATUS_INVAL,"unsupported control transfer size %d",cch);
236141cc406Sopenharmony_ci  pchBuffer=malloc(cch);
237141cc406Sopenharmony_ci  pchTransfer=calloc(1,cch);
238141cc406Sopenharmony_ci  rcCode=SANE_STATUS_GOOD;
239141cc406Sopenharmony_ci  if (!pchBuffer || !pchTransfer)
240141cc406Sopenharmony_ci    {
241141cc406Sopenharmony_ci      if (pchBuffer) free(pchBuffer);
242141cc406Sopenharmony_ci      if (pchTransfer) free(pchTransfer);
243141cc406Sopenharmony_ci      rcCode=SetError(this, SANE_STATUS_NO_MEM, "no memory in RegCheck()");
244141cc406Sopenharmony_ci    }
245141cc406Sopenharmony_ci  bOk=true;
246141cc406Sopenharmony_ci  for (i=0; !rcCode && i<cch; i++)
247141cc406Sopenharmony_ci    {
248141cc406Sopenharmony_ci      pchBuffer[i]=(char)(ulValue&0x00FF);
249141cc406Sopenharmony_ci      ulValue=(ulValue>>8);
250141cc406Sopenharmony_ci    }
251141cc406Sopenharmony_ci  if (!rcCode)
252141cc406Sopenharmony_ci    {
253141cc406Sopenharmony_ci      if (!bOk)
254141cc406Sopenharmony_ci	rcCode=SetError(this,SANE_STATUS_IO_ERROR,
255141cc406Sopenharmony_ci			"error in reg out: %d,%d,%08X",iRegister,cch,ulValue);
256141cc406Sopenharmony_ci      else
257141cc406Sopenharmony_ci	{
258141cc406Sopenharmony_ci	  i=TransferControlMsg(this,  /* handle */
259141cc406Sopenharmony_ci		    0xC0,                  /* request type */
260141cc406Sopenharmony_ci		    0x00,                  /* request */
261141cc406Sopenharmony_ci		    iRegister,             /* value */
262141cc406Sopenharmony_ci		    0,                     /* index */
263141cc406Sopenharmony_ci		    pchTransfer, cch,      /* bytes, size */
264141cc406Sopenharmony_ci		    USB_TIMEOUT_JIFFIES);                /* TO, jiffies... */
265141cc406Sopenharmony_ci	  if (i<0)
266141cc406Sopenharmony_ci	    rcCode=SetError(this,SANE_STATUS_IO_ERROR,
267141cc406Sopenharmony_ci			    "error during register check");
268141cc406Sopenharmony_ci	}
269141cc406Sopenharmony_ci    }
270141cc406Sopenharmony_ci  if (!rcCode && memcmp(pchTransfer,pchBuffer,cch))
271141cc406Sopenharmony_ci    {
272141cc406Sopenharmony_ci      DumpBuffer(stdout,pchTransfer,cch);
273141cc406Sopenharmony_ci      rcCode=SetError(this,SANE_STATUS_IO_ERROR,
274141cc406Sopenharmony_ci		      "check register failed for %d,%d,%08X",
275141cc406Sopenharmony_ci		      iRegister,cch,ulValue);
276141cc406Sopenharmony_ci    }
277141cc406Sopenharmony_ci  free(pchTransfer); free(pchBuffer);
278141cc406Sopenharmony_ci  return rcCode;
279141cc406Sopenharmony_ci}
280141cc406Sopenharmony_ci
281141cc406Sopenharmony_ci/* **********************************************************************
282141cc406Sopenharmony_ci
283141cc406Sopenharmony_cicchRead=BulkRead(fh,cchBulk)
284141cc406Sopenharmony_ci
285141cc406Sopenharmony_ci********************************************************************** */
286141cc406Sopenharmony_ci
287141cc406Sopenharmony_ci__SM3600EXPORT__
288141cc406Sopenharmony_ciint BulkRead(TInstance *this, FILE *fhOut, unsigned int cchBulk)
289141cc406Sopenharmony_ci{
290141cc406Sopenharmony_ci  int   cchRead,rc;
291141cc406Sopenharmony_ci  char *pchBuffer;
292141cc406Sopenharmony_ci  INST_ASSERT();
293141cc406Sopenharmony_ci  pchBuffer=(char*)malloc(cchBulk);
294141cc406Sopenharmony_ci  CHECK_POINTER(pchBuffer);
295141cc406Sopenharmony_ci  cchRead=0;
296141cc406Sopenharmony_ci  rc=0;
297141cc406Sopenharmony_ci  while (!rc && cchBulk)
298141cc406Sopenharmony_ci    {
299141cc406Sopenharmony_ci      int cchChunk;
300141cc406Sopenharmony_ci      int cchReal;
301141cc406Sopenharmony_ci
302141cc406Sopenharmony_ci      cchChunk=cchBulk;
303141cc406Sopenharmony_ci      if (cchChunk>0x1000)
304141cc406Sopenharmony_ci	cchChunk=0x1000;
305141cc406Sopenharmony_ci      cchReal=TransferBulkRead(this,
306141cc406Sopenharmony_ci		       0x82,
307141cc406Sopenharmony_ci		       pchBuffer+cchRead,
308141cc406Sopenharmony_ci		       cchChunk,
309141cc406Sopenharmony_ci		       USB_TIMEOUT_JIFFIES);
310141cc406Sopenharmony_ci      dprintf(DEBUG_COMM,"bulk read: %d -> %d\n",cchChunk,cchReal);
311141cc406Sopenharmony_ci      if (cchReal>=0)
312141cc406Sopenharmony_ci	{
313141cc406Sopenharmony_ci	  cchBulk-=cchReal;
314141cc406Sopenharmony_ci	  cchRead+=cchReal;
315141cc406Sopenharmony_ci	  if (cchReal<cchChunk) /* last Chunk of a series */
316141cc406Sopenharmony_ci	    break;
317141cc406Sopenharmony_ci	}
318141cc406Sopenharmony_ci      else
319141cc406Sopenharmony_ci	{
320141cc406Sopenharmony_ci	  rc=SetError(this,SANE_STATUS_IO_ERROR,
321141cc406Sopenharmony_ci		      "bulk read of %d bytes failed: %s",
322141cc406Sopenharmony_ci		      cchChunk,
323141cc406Sopenharmony_ci		      "I/O error"
324141cc406Sopenharmony_ci		      );
325141cc406Sopenharmony_ci	  continue;
326141cc406Sopenharmony_ci	}
327141cc406Sopenharmony_ci    }
328141cc406Sopenharmony_ci  dprintf(DEBUG_COMM,"writing %d bytes\n",cchRead);
329141cc406Sopenharmony_ci  if (fhOut && !rc)
330141cc406Sopenharmony_ci    {
331141cc406Sopenharmony_ci      fwrite(pchBuffer,1,cchRead,fhOut);
332141cc406Sopenharmony_ci      if (ferror(fhOut))
333141cc406Sopenharmony_ci	rc=SetError(this,SANE_STATUS_IO_ERROR,
334141cc406Sopenharmony_ci		    "scan file write failed: %s",
335141cc406Sopenharmony_ci		    strerror(errno));
336141cc406Sopenharmony_ci    }
337141cc406Sopenharmony_ci  free(pchBuffer);
338141cc406Sopenharmony_ci  return rc ? -1 : cchRead;
339141cc406Sopenharmony_ci}
340141cc406Sopenharmony_ci
341141cc406Sopenharmony_ci#endif
342141cc406Sopenharmony_ci
343141cc406Sopenharmony_ci/* **********************************************************************
344141cc406Sopenharmony_ci
345141cc406Sopenharmony_cicchRead=BulkReadBuffer(puchBuffer, cchBulk)
346141cc406Sopenharmony_ci
347141cc406Sopenharmony_ci********************************************************************** */
348141cc406Sopenharmony_ci
349141cc406Sopenharmony_ci__SM3600EXPORT__
350141cc406Sopenharmony_ciint BulkReadBuffer(TInstance *this,
351141cc406Sopenharmony_ci		   unsigned char *puchBufferOut,
352141cc406Sopenharmony_ci		   unsigned int cchBulk)
353141cc406Sopenharmony_ci{
354141cc406Sopenharmony_ci  int   cchRead,rc;
355141cc406Sopenharmony_ci  char *pchBuffer;
356141cc406Sopenharmony_ci  INST_ASSERT();
357141cc406Sopenharmony_ci  pchBuffer=(char*)malloc(cchBulk);
358141cc406Sopenharmony_ci  CHECK_POINTER(pchBuffer);
359141cc406Sopenharmony_ci  cchRead=0;
360141cc406Sopenharmony_ci  rc=0;
361141cc406Sopenharmony_ci  while (!rc && cchBulk)
362141cc406Sopenharmony_ci    {
363141cc406Sopenharmony_ci      int cchChunk;
364141cc406Sopenharmony_ci      int cchReal;
365141cc406Sopenharmony_ci
366141cc406Sopenharmony_ci      cchChunk=cchBulk;
367141cc406Sopenharmony_ci      if (cchChunk>0x1000)
368141cc406Sopenharmony_ci	cchChunk=0x1000;
369141cc406Sopenharmony_ci      cchReal=TransferBulkRead(this,
370141cc406Sopenharmony_ci		       0x82,
371141cc406Sopenharmony_ci		       pchBuffer+cchRead,
372141cc406Sopenharmony_ci		       cchChunk,
373141cc406Sopenharmony_ci		       USB_TIMEOUT_JIFFIES);
374141cc406Sopenharmony_ci      dprintf(DEBUG_COMM,"bulk read: %d -> %d\n",cchChunk,cchReal);
375141cc406Sopenharmony_ci      if (cchReal>=0)
376141cc406Sopenharmony_ci	{
377141cc406Sopenharmony_ci	  cchBulk-=cchReal;
378141cc406Sopenharmony_ci	  cchRead+=cchReal;
379141cc406Sopenharmony_ci	  if (cchReal<cchChunk) /* last Chunk of a series */
380141cc406Sopenharmony_ci	    break;
381141cc406Sopenharmony_ci	}
382141cc406Sopenharmony_ci      else
383141cc406Sopenharmony_ci	rc=SetError(this,SANE_STATUS_IO_ERROR,
384141cc406Sopenharmony_ci		    "bulk read of %d bytes failed: %s",
385141cc406Sopenharmony_ci		    cchChunk,
386141cc406Sopenharmony_ci		    "I/O error"
387141cc406Sopenharmony_ci		    );
388141cc406Sopenharmony_ci    }
389141cc406Sopenharmony_ci  dprintf(DEBUG_COMM,"writing %d bytes\n",cchRead);
390141cc406Sopenharmony_ci
391141cc406Sopenharmony_ci  if (!rc && puchBufferOut)
392141cc406Sopenharmony_ci    memcpy(puchBufferOut,pchBuffer,cchRead);
393141cc406Sopenharmony_ci  free(pchBuffer);
394141cc406Sopenharmony_ci  return rc ? -1 : cchRead;
395141cc406Sopenharmony_ci}
396141cc406Sopenharmony_ci
397141cc406Sopenharmony_ci/* **********************************************************************
398141cc406Sopenharmony_ci
399141cc406Sopenharmony_ciRegRead(iRegister, int cch)
400141cc406Sopenharmony_ci
401141cc406Sopenharmony_ciRead register in big endian (INTEL-) format.
402141cc406Sopenharmony_ci
403141cc406Sopenharmony_ci********************************************************************** */
404141cc406Sopenharmony_ci
405141cc406Sopenharmony_ci__SM3600EXPORT__
406141cc406Sopenharmony_ciunsigned int RegRead(TInstance *this, int iRegister, int cch)
407141cc406Sopenharmony_ci{
408141cc406Sopenharmony_ci  char        *pchTransfer;
409141cc406Sopenharmony_ci  int          i;
410141cc406Sopenharmony_ci  unsigned int n;
411141cc406Sopenharmony_ci  INST_ASSERT();
412141cc406Sopenharmony_ci  if (cch<1 || cch>4)
413141cc406Sopenharmony_ci    {
414141cc406Sopenharmony_ci      SetError(this,SANE_STATUS_INVAL,
415141cc406Sopenharmony_ci		    "unsupported control read size %d",cch);
416141cc406Sopenharmony_ci      return 0;
417141cc406Sopenharmony_ci    }
418141cc406Sopenharmony_ci  pchTransfer=calloc(1,cch);
419141cc406Sopenharmony_ci  CHECK_POINTER(pchTransfer);
420141cc406Sopenharmony_ci  i=TransferControlMsg(this,  /* handle */
421141cc406Sopenharmony_ci        0xC0,                  /* request type */
422141cc406Sopenharmony_ci	0x00,                  /* request */
423141cc406Sopenharmony_ci	iRegister,             /* value */
424141cc406Sopenharmony_ci	0,                     /* index */
425141cc406Sopenharmony_ci	pchTransfer, cch,      /* bytes, size */
426141cc406Sopenharmony_ci	USB_TIMEOUT_JIFFIES);                /* TO, jiffies... */
427141cc406Sopenharmony_ci  if (i>=0)
428141cc406Sopenharmony_ci    {
429141cc406Sopenharmony_ci      n=0;
430141cc406Sopenharmony_ci      for (i=cch-1; i>=0; i--)
431141cc406Sopenharmony_ci	n=(n<<8)|(unsigned char)pchTransfer[i];
432141cc406Sopenharmony_ci      free(pchTransfer);
433141cc406Sopenharmony_ci      return n;
434141cc406Sopenharmony_ci    }
435141cc406Sopenharmony_ci  free(pchTransfer);
436141cc406Sopenharmony_ci  SetError(this,SANE_STATUS_IO_ERROR,"error during register read");
437141cc406Sopenharmony_ci  return 0;
438141cc406Sopenharmony_ci}
439