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_cicolor scan routine
45141cc406Sopenharmony_ci
46141cc406Sopenharmony_ci(C) Marian Eichholz 2001
47141cc406Sopenharmony_ci
48141cc406Sopenharmony_ci====================================================================== */
49141cc406Sopenharmony_ci
50141cc406Sopenharmony_ci#include "sm3600-scantool.h"
51141cc406Sopenharmony_ci
52141cc406Sopenharmony_ci#define ORDER_RGB             "012"
53141cc406Sopenharmony_ci#define ORDER_BRG             "120"
54141cc406Sopenharmony_ci
55141cc406Sopenharmony_ci/* **********************************************************************
56141cc406Sopenharmony_ci
57141cc406Sopenharmony_ciReadNextColorLine()
58141cc406Sopenharmony_ci
59141cc406Sopenharmony_ci********************************************************************** */
60141cc406Sopenharmony_ci
61141cc406Sopenharmony_cistatic TState ReadNextColorLine(PTInstance this)
62141cc406Sopenharmony_ci{
63141cc406Sopenharmony_ci  int           iWrite,i;
64141cc406Sopenharmony_ci  int           iRead; /* read position in raw line */
65141cc406Sopenharmony_ci  int           nInterpolator;
66141cc406Sopenharmony_ci  int           iOffsetR,iOffsetG,iOffsetB;
67141cc406Sopenharmony_ci  short        *pchLineSwap;
68141cc406Sopenharmony_ci  TBool         bVisible;
69141cc406Sopenharmony_ci
70141cc406Sopenharmony_ci  bVisible=false;
71141cc406Sopenharmony_ci  do {
72141cc406Sopenharmony_ci      iWrite=0;
73141cc406Sopenharmony_ci      while (iWrite<3*this->state.cxMax) /* max 1 time in reality */
74141cc406Sopenharmony_ci	{
75141cc406Sopenharmony_ci	  while (iWrite<3*this->state.cxMax &&
76141cc406Sopenharmony_ci		 this->state.iBulkReadPos<this->state.cchBulk)
77141cc406Sopenharmony_ci	    this->state.ppchLines[0][iWrite++] =
78141cc406Sopenharmony_ci	      this->state.pchBuf[this->state.iBulkReadPos++];
79141cc406Sopenharmony_ci	  if (iWrite<3*this->state.cxMax) /* we need an additional chunk */
80141cc406Sopenharmony_ci	    {
81141cc406Sopenharmony_ci	      if (this->state.bLastBulk)
82141cc406Sopenharmony_ci		return SANE_STATUS_EOF;
83141cc406Sopenharmony_ci	      this->state.cchBulk=BulkReadBuffer(this,this->state.pchBuf,
84141cc406Sopenharmony_ci						 USB_CHUNK_SIZE);
85141cc406Sopenharmony_ci	      dprintf(DEBUG_SCAN,"bulk read: %d byte(s), line #%d\n",
86141cc406Sopenharmony_ci		      this->state.cchBulk, this->state.iLine);
87141cc406Sopenharmony_ci	      if (this->bWriteRaw)
88141cc406Sopenharmony_ci		fwrite(this->state.pchBuf,1,this->state.cchBulk,this->fhScan);
89141cc406Sopenharmony_ci	      INST_ASSERT();
90141cc406Sopenharmony_ci	      if (this->state.cchBulk!=USB_CHUNK_SIZE)
91141cc406Sopenharmony_ci		this->state.bLastBulk=true;
92141cc406Sopenharmony_ci	      this->state.iBulkReadPos=0;
93141cc406Sopenharmony_ci	    }
94141cc406Sopenharmony_ci	} /* while raw line buffer acquiring */
95141cc406Sopenharmony_ci      this->state.iLine++;
96141cc406Sopenharmony_ci      if (this->state.iLine>2*this->state.ySensorSkew)
97141cc406Sopenharmony_ci	{
98141cc406Sopenharmony_ci	  bVisible=true;
99141cc406Sopenharmony_ci	  iOffsetR=(this->state.szOrder[0]-'0')*this->state.cxMax;
100141cc406Sopenharmony_ci	  iOffsetG=(this->state.szOrder[1]-'0')*this->state.cxMax;
101141cc406Sopenharmony_ci	  iOffsetB=(this->state.szOrder[2]-'0')*this->state.cxMax;
102141cc406Sopenharmony_ci	  for (nInterpolator=100, iWrite=0, iRead=0;
103141cc406Sopenharmony_ci	       iRead<3*this->state.cxMax && iWrite<this->state.cchLineOut;
104141cc406Sopenharmony_ci	       iRead++)
105141cc406Sopenharmony_ci	    {
106141cc406Sopenharmony_ci	      nInterpolator+=this->state.nFixAspect;
107141cc406Sopenharmony_ci	      if (nInterpolator<100) continue; /* res. reduction */
108141cc406Sopenharmony_ci	      nInterpolator-=100;
109141cc406Sopenharmony_ci	      /* dprintf(DEBUG_SCAN," i=%d",iTo); */
110141cc406Sopenharmony_ci	      /* the first scan lines only fill the line backlog buffer */
111141cc406Sopenharmony_ci	      {
112141cc406Sopenharmony_ci		/* dprintf(DEBUG_SCAN,"assembling line %d\n",++this->state.iLine); */
113141cc406Sopenharmony_ci		this->state.pchLineOut[iWrite++]=
114141cc406Sopenharmony_ci		  this->state.ppchLines[2*this->state.ySensorSkew][iRead+iOffsetR];
115141cc406Sopenharmony_ci		this->state.pchLineOut[iWrite++]=
116141cc406Sopenharmony_ci		  this->state.ppchLines[1*this->state.ySensorSkew][iRead+iOffsetG];
117141cc406Sopenharmony_ci		this->state.pchLineOut[iWrite++]=
118141cc406Sopenharmony_ci		  this->state.ppchLines[0*this->state.ySensorSkew][iRead+iOffsetB];
119141cc406Sopenharmony_ci	      }
120141cc406Sopenharmony_ci	    }
121141cc406Sopenharmony_ci	} /* if visible line */
122141cc406Sopenharmony_ci      /* cycle backlog buffers */
123141cc406Sopenharmony_ci      pchLineSwap=this->state.ppchLines[this->state.cBacklog-1];
124141cc406Sopenharmony_ci      for (i=this->state.cBacklog-2; i>=0; i--)
125141cc406Sopenharmony_ci	this->state.ppchLines[i+1]=this->state.ppchLines[i];
126141cc406Sopenharmony_ci      this->state.ppchLines[0]=pchLineSwap;
127141cc406Sopenharmony_ci  } while (!bVisible);
128141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
129141cc406Sopenharmony_ci}
130141cc406Sopenharmony_ci
131141cc406Sopenharmony_ci/* ======================================================================
132141cc406Sopenharmony_ci
133141cc406Sopenharmony_ciStartScanColor()
134141cc406Sopenharmony_ci
135141cc406Sopenharmony_ci====================================================================== */
136141cc406Sopenharmony_ci
137141cc406Sopenharmony_ci/* Parameter are in resolution units! */
138141cc406Sopenharmony_ci__SM3600EXPORT__
139141cc406Sopenharmony_ciTState StartScanColor(TInstance *this)
140141cc406Sopenharmony_ci{
141141cc406Sopenharmony_ci
142141cc406Sopenharmony_ci  /* live could be easy: Simple calculate a window, start the scan,
143141cc406Sopenharmony_ci     get the data and get off. It dimply does not work.  We have to
144141cc406Sopenharmony_ci     deal with the fact, that the pixels are reported with color scan
145141cc406Sopenharmony_ci     line by color scan line, and have to be rearranged to RGB
146141cc406Sopenharmony_ci     triples. They even ar enot always in RGB order, but mostly in BRG
147141cc406Sopenharmony_ci     order. And they have a skew of 2/300 inch , given by the slider
148141cc406Sopenharmony_ci     construction.  Thus, we have to deal with several buffers, some
149141cc406Sopenharmony_ci     interpolation, and related management stuff. */
150141cc406Sopenharmony_ci  int             i;
151141cc406Sopenharmony_ci  if (this->state.bScanning)
152141cc406Sopenharmony_ci    return SetError(this,SANE_STATUS_DEVICE_BUSY,"scan active");
153141cc406Sopenharmony_ci  memset(&(this->state),0,sizeof(this->state));
154141cc406Sopenharmony_ci  this->state.ReadProc  =ReadNextColorLine;
155141cc406Sopenharmony_ci  this->state.ySensorSkew=0;
156141cc406Sopenharmony_ci
157141cc406Sopenharmony_ci  GetAreaSize(this);
158141cc406Sopenharmony_ci
159141cc406Sopenharmony_ci  switch (this->param.res)
160141cc406Sopenharmony_ci    {
161141cc406Sopenharmony_ci    case 200: this->state.ySensorSkew=1; break;
162141cc406Sopenharmony_ci    case 300: this->state.ySensorSkew=2; break;
163141cc406Sopenharmony_ci    case 600: this->state.ySensorSkew=4; break;
164141cc406Sopenharmony_ci    default: break;
165141cc406Sopenharmony_ci    }
166141cc406Sopenharmony_ci  /* since we need 2*this->state.ySensorSkew additional scan lines for de-skewing of
167141cc406Sopenharmony_ci     the sensor lines, we enlarge the window and shorten the initial movement
168141cc406Sopenharmony_ci     accordingly */
169141cc406Sopenharmony_ci  this->state.cyTotalPath =
170141cc406Sopenharmony_ci    this->param.y/2-(2*this->state.ySensorSkew)*600/this->param.res;
171141cc406Sopenharmony_ci  DoJog(this,this->state.cyTotalPath); INST_ASSERT();
172141cc406Sopenharmony_ci  this->state.cyTotalPath +=
173141cc406Sopenharmony_ci    (this->state.cyPixel+2*this->state.ySensorSkew)
174141cc406Sopenharmony_ci    *600/this->param.res; /* for jogging back */
175141cc406Sopenharmony_ci
176141cc406Sopenharmony_ci  /*
177141cc406Sopenharmony_ci    regular scan is asynchronously, that is,
178141cc406Sopenharmony_ci    the scanning is issued, and the driver does bulk reads,
179141cc406Sopenharmony_ci    until there are no data left.
180141cc406Sopenharmony_ci    Each line has a full R, G and B subline, 8bit each sample.
181141cc406Sopenharmony_ci  */
182141cc406Sopenharmony_ci  {
183141cc406Sopenharmony_ci    unsigned char uchRegs[]={
184141cc406Sopenharmony_ci      0xFC /*!!R_SPOS!!*/, 0x00 /*R_SPOSH*/, 0x24 /*!!0x03!!*/,
185141cc406Sopenharmony_ci      0xB0 /*!!R_SWID!!*/, 0xC4 /*!!R_SWIDH!!*/,
186141cc406Sopenharmony_ci      1,0,
187141cc406Sopenharmony_ci      0xFF /*!!0x08!!*/, 0xFF /*!!0x09!!*/,
188141cc406Sopenharmony_ci      0x22 /*!!R_LEN!!*/, 0x07 /*!!R_LENH!!*/, 0x6D /*0x0C*/,
189141cc406Sopenharmony_ci      0x70 /*0x0D*/, 0x69 /*0x0E*/, 0xD0 /*0x0F*/,
190141cc406Sopenharmony_ci      0x00 /*0x10*/, 0x00 /*0x11*/, 0x42 /*!!0x12!!*/,
191141cc406Sopenharmony_ci      0x15 /*0x13*/, 0x84 /*!!0x14!!*/, 0x2A /*0x15*/,
192141cc406Sopenharmony_ci      0xC5 /*!!0x16!!*/, 0x40 /*0x17*/, 0xC5 /*!!0x18!!*/,
193141cc406Sopenharmony_ci      0x40 /*0x19*/, 0xFF /*0x1A*/, 0x01 /*0x1B*/,
194141cc406Sopenharmony_ci      0x88 /*0x1C*/, 0x40 /*0x1D*/, 0x4C /*0x1E*/,
195141cc406Sopenharmony_ci      0x50 /*0x1F*/, 0x00 /*0x20*/, 0x0C /*0x21*/,
196141cc406Sopenharmony_ci      0x21 /*0x22*/, 0xF0 /*0x23*/, 0x40 /*0x24*/,
197141cc406Sopenharmony_ci      0x00 /*0x25*/, 0x0A /*0x26*/, 0xF0 /*0x27*/,
198141cc406Sopenharmony_ci      0x00 /*0x28*/, 0x00 /*0x29*/, 0x4E /*0x2A*/,
199141cc406Sopenharmony_ci      0xF0 /*0x2B*/, 0x00 /*0x2C*/, 0x00 /*0x2D*/,
200141cc406Sopenharmony_ci      0x4E /*0x2E*/, 0x80 /*R_CCAL*/, 0x80 /*R_CCAL2*/,
201141cc406Sopenharmony_ci      0x80 /*R_CCAL3*/, 0x0B /*0x32*/, 0x2D /*0x33*/,
202141cc406Sopenharmony_ci      0x43 /*!!0x34!!*/, 0x29 /*0x35*/, 0x00 /*0x36*/,
203141cc406Sopenharmony_ci      0x00 /*0x37*/, 0x00 /*0x38*/, 0x00 /*0x39*/,
204141cc406Sopenharmony_ci      0x00 /*0x3A*/, 0x00 /*0x3B*/, 0xFF /*0x3C*/,
205141cc406Sopenharmony_ci      0x0F /*0x3D*/, 0x00 /*0x3E*/, 0x00 /*0x3F*/,
206141cc406Sopenharmony_ci      0x01 /*0x40*/, 0x00 /*0x41*/, 0x80 /*R_CSTAT*/,
207141cc406Sopenharmony_ci      0x03 /*0x43*/, 0x01 /*R_LMP*/, 0x00 /*0x45*/,
208141cc406Sopenharmony_ci      0x39 /*R_CTL*/, 0xC5 /*!!0x47!!*/, 0x40 /*0x48*/,
209141cc406Sopenharmony_ci      0x9E /*0x49*/, 0x8C /*0x4A*/ };
210141cc406Sopenharmony_ci    RegWriteArray(this,R_ALL, NUM_SCANREGS, uchRegs);
211141cc406Sopenharmony_ci    RegWrite(this,R_SPOS, 2, this->param.x/2 + this->calibration.xMargin);
212141cc406Sopenharmony_ci    RegWrite(this,R_SLEN, 2,
213141cc406Sopenharmony_ci	     this->state.cyWindow+
214141cc406Sopenharmony_ci	     (2*this->state.ySensorSkew)*600/this->param.res);
215141cc406Sopenharmony_ci    this->state.szOrder=ORDER_BRG;
216141cc406Sopenharmony_ci    RegWrite(this,R_CCAL, 3, this->calibration.rgbBias); INST_ASSERT(); /* 0xBBGGRR */
217141cc406Sopenharmony_ci    switch (this->param.res)
218141cc406Sopenharmony_ci      {
219141cc406Sopenharmony_ci      case 75:
220141cc406Sopenharmony_ci	RegWrite(this,R_XRES,1, 0x20); /* ups, can  do only 100 dpi horizontal */
221141cc406Sopenharmony_ci	RegWrite(this,R_SWID, 2, 0xC000 | this->state.cxWindow);
222141cc406Sopenharmony_ci	RegWrite(this,0x34, 1, 0x83); /* halves the vertical resolution */
223141cc406Sopenharmony_ci	RegWrite(this,0x47,1,0xC0); /* reduces the speed a bit */
224141cc406Sopenharmony_ci	break;
225141cc406Sopenharmony_ci      case 100:
226141cc406Sopenharmony_ci	RegWrite(this,R_XRES,1, 0x20);
227141cc406Sopenharmony_ci	RegWrite(this,R_SWID, 2, 0xC000 | this->state.cxWindow);
228141cc406Sopenharmony_ci	RegWrite(this,0x34, 1, 0x63); /* halves the vertical resolution */
229141cc406Sopenharmony_ci	RegWrite(this,0x47,1,0xC0); /* reduces the speed a bit */
230141cc406Sopenharmony_ci	/* I have no idea, what these differences are good for. The seem to produce
231141cc406Sopenharmony_ci	   a slight blue presence.
232141cc406Sopenharmony_ci	   RegWrite(this,0x16, 1, 0xC0);  RegWrite(this,0x18, 1, 0xC0);
233141cc406Sopenharmony_ci	   RegWrite(this,0x12, 1, 0x40);  RegWrite(this,0x10, 2, 0x0728);
234141cc406Sopenharmony_ci	   RegWrite(this,0x14, 1, 0x80); */
235141cc406Sopenharmony_ci	break;
236141cc406Sopenharmony_ci      case 200:
237141cc406Sopenharmony_ci	RegWrite(this,R_XRES,1, 0x24);
238141cc406Sopenharmony_ci	RegWrite(this,R_SWID, 2, 0xC000 | this->state.cxWindow);
239141cc406Sopenharmony_ci	break;
240141cc406Sopenharmony_ci      case 300:
241141cc406Sopenharmony_ci	RegWrite(this,0x08,2, 0x6A6A);
242141cc406Sopenharmony_ci	RegWrite(this,R_XRES,1, 0x2A);
243141cc406Sopenharmony_ci	RegWrite(this,R_SWID, 2, 0x4000 | this->state.cxWindow);
244141cc406Sopenharmony_ci	RegWrite(this,0x34, 1, 0x03); /* halves the vertical resolution */
245141cc406Sopenharmony_ci	RegWrite(this,0x47,1,0xC0); /* reduces the speed a bit */
246141cc406Sopenharmony_ci	this->state.szOrder=ORDER_RGB;
247141cc406Sopenharmony_ci	break;
248141cc406Sopenharmony_ci      case 600:
249141cc406Sopenharmony_ci	RegWrite(this,R_XRES,1, 0x3F);
250141cc406Sopenharmony_ci	RegWrite(this,R_SWID, 2, 0xC000 | this->state.cxWindow);
251141cc406Sopenharmony_ci	RegWrite(this,0x34, 1, 0x03); /* halves the vertical resolution */
252141cc406Sopenharmony_ci	RegWrite(this,0x47,1,0xC2); /* reduces the speed a bit */
253141cc406Sopenharmony_ci	break;
254141cc406Sopenharmony_ci      case 1200:
255141cc406Sopenharmony_ci	/* not supported, since the driver supports only 600 dpi in color */
256141cc406Sopenharmony_ci	break;
257141cc406Sopenharmony_ci      }
258141cc406Sopenharmony_ci  }
259141cc406Sopenharmony_ci
260141cc406Sopenharmony_ci  /* setup gamma tables */
261141cc406Sopenharmony_ci  RegWrite(this,0x41,1,0x03); /* gamma, RGB */
262141cc406Sopenharmony_ci  RegWrite(this,0x40,1,0x28); /* offset FIFO 8*3 (GAMMA)+16 KB(gain) spared */
263141cc406Sopenharmony_ci  /*
264141cc406Sopenharmony_ci    hey, surprise: Although the color lines are sent in a strange order,
265141cc406Sopenharmony_ci    the gamma tables are mapped constantly to the sensors (i.e. RGB)
266141cc406Sopenharmony_ci  */
267141cc406Sopenharmony_ci  UploadGammaTable(this,0x0000,this->agammaR);
268141cc406Sopenharmony_ci  UploadGammaTable(this,0x2000,this->agammaG);
269141cc406Sopenharmony_ci  UploadGammaTable(this,0x4000,this->agammaB);
270141cc406Sopenharmony_ci  INST_ASSERT();
271141cc406Sopenharmony_ci
272141cc406Sopenharmony_ci  UploadGainCorrection(this,0x6000);
273141cc406Sopenharmony_ci  INST_ASSERT();
274141cc406Sopenharmony_ci
275141cc406Sopenharmony_ci  /* enough for 1/100 inch sensor distance */
276141cc406Sopenharmony_ci  this->state.cBacklog=1+2*this->state.ySensorSkew;
277141cc406Sopenharmony_ci
278141cc406Sopenharmony_ci  /* allocate raw line buffers */
279141cc406Sopenharmony_ci  this->state.ppchLines=calloc(this->state.cBacklog,sizeof(short*));
280141cc406Sopenharmony_ci  this->state.pchBuf=malloc(0x8000);
281141cc406Sopenharmony_ci  if (!this->state.ppchLines || !this->state.pchBuf)
282141cc406Sopenharmony_ci    return FreeState(this,SetError(this,
283141cc406Sopenharmony_ci				   SANE_STATUS_NO_MEM,"no buffers available"));
284141cc406Sopenharmony_ci
285141cc406Sopenharmony_ci  for (i=0; i<this->state.cBacklog; i++)
286141cc406Sopenharmony_ci  {
287141cc406Sopenharmony_ci    this->state.ppchLines[i]=calloc(1,3*this->state.cxMax*sizeof(short)); /* must be less than 0x8000 */
288141cc406Sopenharmony_ci    if (!this->state.ppchLines[i])
289141cc406Sopenharmony_ci      return FreeState(this,
290141cc406Sopenharmony_ci		       SetError(this,SANE_STATUS_NO_MEM,
291141cc406Sopenharmony_ci				"no line buffer available"));
292141cc406Sopenharmony_ci  }
293141cc406Sopenharmony_ci
294141cc406Sopenharmony_ci  /* calculate and prepare intermediate line transfer buffer */
295141cc406Sopenharmony_ci
296141cc406Sopenharmony_ci  this->state.cchLineOut=3*this->state.cxPixel;
297141cc406Sopenharmony_ci  this->state.pchLineOut = malloc(this->state.cchLineOut);
298141cc406Sopenharmony_ci  if (!this->state.pchLineOut)
299141cc406Sopenharmony_ci    return FreeState(this,SetError(this,
300141cc406Sopenharmony_ci				   SANE_STATUS_NO_MEM,
301141cc406Sopenharmony_ci				   "no buffers available"));
302141cc406Sopenharmony_ci
303141cc406Sopenharmony_ci  RegWrite(this,R_CTL, 1, 0x39);    /* #1532[005.0] */
304141cc406Sopenharmony_ci  RegWrite(this,R_CTL, 1, 0x79);    /* #1533[005.0] */
305141cc406Sopenharmony_ci  RegWrite(this,R_CTL, 1, 0xF9);    /* #1534[005.0] */
306141cc406Sopenharmony_ci  INST_ASSERT();
307141cc406Sopenharmony_ci
308141cc406Sopenharmony_ci  this->state.bScanning = true;
309141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
310141cc406Sopenharmony_ci}
311