1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci   Copyright (C) 2000-2003 Jochen Eisinger <jochen.eisinger@gmx.net>
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   This file implements the hardware driver scanners using a 300dpi CCD */
40141cc406Sopenharmony_ci
41141cc406Sopenharmony_ci#include "mustek_pp_ccd300.h"
42141cc406Sopenharmony_ci
43141cc406Sopenharmony_ci#define MUSTEK_PP_CCD300	4
44141cc406Sopenharmony_ci
45141cc406Sopenharmony_cistatic void config_ccd_101x (Mustek_pp_Handle * dev);
46141cc406Sopenharmony_cistatic void config_ccd (Mustek_pp_Handle * dev);
47141cc406Sopenharmony_cistatic void lamp (Mustek_pp_Handle * dev, int lamp_on);
48141cc406Sopenharmony_ci
49141cc406Sopenharmony_ci#define CCD300_ASIC1013		0xa8
50141cc406Sopenharmony_ci#define CCD300_ASIC1015		0xa5
51141cc406Sopenharmony_ci
52141cc406Sopenharmony_ci#define CCD300_CHANNEL_RED		0
53141cc406Sopenharmony_ci#define CCD300_CHANNEL_GREEN		1
54141cc406Sopenharmony_ci#define CCD300_CHANNEL_BLUE		2
55141cc406Sopenharmony_ci#define CCD300_CHANNEL_GRAY		1
56141cc406Sopenharmony_ci
57141cc406Sopenharmony_ci#define CCD300_MAXHSIZE		2600
58141cc406Sopenharmony_ci#define CCD300_MAXVSIZE		3500
59141cc406Sopenharmony_ci
60141cc406Sopenharmony_ci/*
61141cc406Sopenharmony_ci *  Here starts the driver code for the different chipsets
62141cc406Sopenharmony_ci *
63141cc406Sopenharmony_ci *  The 1013 & 1015 chipsets share large portions of the code. This
64141cc406Sopenharmony_ci *  shared functions end with _101x.
65141cc406Sopenharmony_ci */
66141cc406Sopenharmony_ci
67141cc406Sopenharmony_cistatic const u_char chan_codes_1013[] = { 0x82, 0x42, 0xC2 };
68141cc406Sopenharmony_cistatic const u_char chan_codes_1015[] = { 0x80, 0x40, 0xC0 };
69141cc406Sopenharmony_cistatic const u_char fullstep[] = { 0x09, 0x0C, 0x06, 0x03 };
70141cc406Sopenharmony_cistatic const u_char halfstep[] = { 0x02, 0x03, 0x01, 0x09,
71141cc406Sopenharmony_ci  0x08, 0x0C, 0x04, 0x06
72141cc406Sopenharmony_ci};
73141cc406Sopenharmony_cistatic const u_char voltages[4][3] = { {0x5C, 0x5A, 0x63},
74141cc406Sopenharmony_ci{0xE6, 0xB4, 0xBE},
75141cc406Sopenharmony_ci{0xB4, 0xB4, 0xB4},
76141cc406Sopenharmony_ci{0x64, 0x50, 0x64}
77141cc406Sopenharmony_ci};
78141cc406Sopenharmony_ci
79141cc406Sopenharmony_ci/* Forward declarations of 1013/1015 functions */
80141cc406Sopenharmony_cistatic void set_ccd_channel_1013 (Mustek_pp_Handle * dev, int channel);
81141cc406Sopenharmony_cistatic void motor_backward_1013 (Mustek_pp_Handle * dev);
82141cc406Sopenharmony_cistatic void return_home_1013 (Mustek_pp_Handle * dev);
83141cc406Sopenharmony_cistatic void motor_forward_1013 (Mustek_pp_Handle * dev);
84141cc406Sopenharmony_cistatic void config_ccd_1013 (Mustek_pp_Handle * dev);
85141cc406Sopenharmony_ci
86141cc406Sopenharmony_cistatic void set_ccd_channel_1015 (Mustek_pp_Handle * dev, int channel);
87141cc406Sopenharmony_ci/* static void motor_backward_1015 (Mustek_pp_Handle * dev); */
88141cc406Sopenharmony_cistatic void return_home_1015 (Mustek_pp_Handle * dev, SANE_Bool nowait);
89141cc406Sopenharmony_cistatic void motor_forward_1015 (Mustek_pp_Handle * dev);
90141cc406Sopenharmony_cistatic void config_ccd_1015 (Mustek_pp_Handle * dev);
91141cc406Sopenharmony_ci
92141cc406Sopenharmony_ci
93141cc406Sopenharmony_ci/* These functions are common to all 1013/1015 chipsets */
94141cc406Sopenharmony_ci
95141cc406Sopenharmony_cistatic void
96141cc406Sopenharmony_ciset_led (Mustek_pp_Handle * dev)
97141cc406Sopenharmony_ci{
98141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
99141cc406Sopenharmony_ci
100141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6,
101141cc406Sopenharmony_ci			 (priv->motor_step % 5 == 0 ? 0x03 : 0x13));
102141cc406Sopenharmony_ci
103141cc406Sopenharmony_ci}
104141cc406Sopenharmony_ci
105141cc406Sopenharmony_cistatic void
106141cc406Sopenharmony_ciset_sti (Mustek_pp_Handle * dev)
107141cc406Sopenharmony_ci{
108141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
109141cc406Sopenharmony_ci
110141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 3, 0);
111141cc406Sopenharmony_ci  priv->bank_count++;
112141cc406Sopenharmony_ci  priv->bank_count &= 7;
113141cc406Sopenharmony_ci
114141cc406Sopenharmony_ci}
115141cc406Sopenharmony_ci
116141cc406Sopenharmony_cistatic void
117141cc406Sopenharmony_ciget_bank_count (Mustek_pp_Handle * dev)
118141cc406Sopenharmony_ci{
119141cc406Sopenharmony_ci  u_char val;
120141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
121141cc406Sopenharmony_ci
122141cc406Sopenharmony_ci  sanei_pa4s2_readbegin (dev->fd, 3);
123141cc406Sopenharmony_ci  sanei_pa4s2_readbyte (dev->fd, &val);
124141cc406Sopenharmony_ci  sanei_pa4s2_readend (dev->fd);
125141cc406Sopenharmony_ci
126141cc406Sopenharmony_ci  priv->bank_count = (val & 0x07);
127141cc406Sopenharmony_ci
128141cc406Sopenharmony_ci}
129141cc406Sopenharmony_ci
130141cc406Sopenharmony_cistatic void
131141cc406Sopenharmony_cireset_bank_count (Mustek_pp_Handle * dev)
132141cc406Sopenharmony_ci{
133141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 7);
134141cc406Sopenharmony_ci}
135141cc406Sopenharmony_ci
136141cc406Sopenharmony_cistatic void
137141cc406Sopenharmony_ciwait_bank_change (Mustek_pp_Handle * dev, int bankcount, int niceload)
138141cc406Sopenharmony_ci{
139141cc406Sopenharmony_ci  struct timeval start, end;
140141cc406Sopenharmony_ci  unsigned long diff;
141141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
142141cc406Sopenharmony_ci  int first_time = 1;
143141cc406Sopenharmony_ci
144141cc406Sopenharmony_ci  gettimeofday (&start, NULL);
145141cc406Sopenharmony_ci
146141cc406Sopenharmony_ci  do
147141cc406Sopenharmony_ci    {
148141cc406Sopenharmony_ci      if ((niceload == 0) && (first_time == 0))
149141cc406Sopenharmony_ci	{
150141cc406Sopenharmony_ci	  usleep (1);		/* could be as well sched_yield */
151141cc406Sopenharmony_ci	  first_time = 0;
152141cc406Sopenharmony_ci	}
153141cc406Sopenharmony_ci      get_bank_count (dev);
154141cc406Sopenharmony_ci
155141cc406Sopenharmony_ci      gettimeofday (&end, NULL);
156141cc406Sopenharmony_ci      diff = (end.tv_sec * 1000 + end.tv_usec / 1000) -
157141cc406Sopenharmony_ci	(start.tv_sec * 1000 + start.tv_usec / 1000);
158141cc406Sopenharmony_ci
159141cc406Sopenharmony_ci    }
160141cc406Sopenharmony_ci  while ((priv->bank_count != bankcount) && (diff < priv->wait_bank));
161141cc406Sopenharmony_ci
162141cc406Sopenharmony_ci}
163141cc406Sopenharmony_ci
164141cc406Sopenharmony_cistatic void
165141cc406Sopenharmony_ciset_dpi_value (Mustek_pp_Handle * dev)
166141cc406Sopenharmony_ci{
167141cc406Sopenharmony_ci  u_char val = 0;
168141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
169141cc406Sopenharmony_ci
170141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x80);
171141cc406Sopenharmony_ci
172141cc406Sopenharmony_ci  switch (priv->hwres)
173141cc406Sopenharmony_ci    {
174141cc406Sopenharmony_ci    case 100:
175141cc406Sopenharmony_ci      val = 0x00;
176141cc406Sopenharmony_ci      break;
177141cc406Sopenharmony_ci    case 200:
178141cc406Sopenharmony_ci      val = 0x10;
179141cc406Sopenharmony_ci      break;
180141cc406Sopenharmony_ci    case 300:
181141cc406Sopenharmony_ci      val = 0x20;
182141cc406Sopenharmony_ci      break;
183141cc406Sopenharmony_ci    }
184141cc406Sopenharmony_ci
185141cc406Sopenharmony_ci
186141cc406Sopenharmony_ci  if (priv->ccd_type == 1)
187141cc406Sopenharmony_ci    val |= 0x01;
188141cc406Sopenharmony_ci
189141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 5, val);
190141cc406Sopenharmony_ci
191141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x00);
192141cc406Sopenharmony_ci
193141cc406Sopenharmony_ci  DBG (5, "set_dpi_value: value 0x%02x\n", val);
194141cc406Sopenharmony_ci
195141cc406Sopenharmony_ci}
196141cc406Sopenharmony_ci
197141cc406Sopenharmony_cistatic void
198141cc406Sopenharmony_ciset_line_adjust (Mustek_pp_Handle * dev)
199141cc406Sopenharmony_ci{
200141cc406Sopenharmony_ci  int adjustline;
201141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
202141cc406Sopenharmony_ci
203141cc406Sopenharmony_ci  adjustline = (dev->bottomX - dev->topX) * priv->hwres / 300;
204141cc406Sopenharmony_ci  priv->adjustskip = priv->adjustskip * priv->hwres / 300;
205141cc406Sopenharmony_ci
206141cc406Sopenharmony_ci  DBG (5, "set_line_adjust: ppl %u (%u), adjust %u, skip %u\n",
207141cc406Sopenharmony_ci       dev->params.pixels_per_line, (dev->bottomX - dev->topX), adjustline,
208141cc406Sopenharmony_ci       priv->adjustskip);
209141cc406Sopenharmony_ci
210141cc406Sopenharmony_ci
211141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x11);
212141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 5, (adjustline + priv->adjustskip) >> 8);
213141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x21);
214141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 5, (adjustline + priv->adjustskip) & 0xFF);
215141cc406Sopenharmony_ci
216141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x01);
217141cc406Sopenharmony_ci
218141cc406Sopenharmony_ci}
219141cc406Sopenharmony_ci
220141cc406Sopenharmony_cistatic void
221141cc406Sopenharmony_ciset_lamp (Mustek_pp_Handle * dev, int lamp_on)
222141cc406Sopenharmony_ci{
223141cc406Sopenharmony_ci
224141cc406Sopenharmony_ci  int ctr;
225141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
226141cc406Sopenharmony_ci
227141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0xC3);
228141cc406Sopenharmony_ci
229141cc406Sopenharmony_ci  for (ctr = 0; ctr < 3; ctr++)
230141cc406Sopenharmony_ci    {
231141cc406Sopenharmony_ci      sanei_pa4s2_writebyte (dev->fd, 6, (lamp_on ? 0x47 : 0x57));
232141cc406Sopenharmony_ci      sanei_pa4s2_writebyte (dev->fd, 6, 0x77);
233141cc406Sopenharmony_ci    }
234141cc406Sopenharmony_ci
235141cc406Sopenharmony_ci  priv->motor_step = lamp_on;
236141cc406Sopenharmony_ci
237141cc406Sopenharmony_ci  set_led (dev);
238141cc406Sopenharmony_ci
239141cc406Sopenharmony_ci}
240141cc406Sopenharmony_ci
241141cc406Sopenharmony_cistatic void
242141cc406Sopenharmony_cisend_voltages (Mustek_pp_Handle * dev)
243141cc406Sopenharmony_ci{
244141cc406Sopenharmony_ci
245141cc406Sopenharmony_ci  int voltage, sel = 8, ctr;
246141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
247141cc406Sopenharmony_ci
248141cc406Sopenharmony_ci  switch (priv->ccd_type)
249141cc406Sopenharmony_ci    {
250141cc406Sopenharmony_ci    case 0:
251141cc406Sopenharmony_ci      voltage = 0;
252141cc406Sopenharmony_ci      break;
253141cc406Sopenharmony_ci    case 1:
254141cc406Sopenharmony_ci      voltage = 1;
255141cc406Sopenharmony_ci      break;
256141cc406Sopenharmony_ci    default:
257141cc406Sopenharmony_ci      voltage = 2;
258141cc406Sopenharmony_ci      break;
259141cc406Sopenharmony_ci    }
260141cc406Sopenharmony_ci
261141cc406Sopenharmony_ci  for (ctr = 0; ctr < 3; ctr++)
262141cc406Sopenharmony_ci    {
263141cc406Sopenharmony_ci
264141cc406Sopenharmony_ci      sel <<= 1;
265141cc406Sopenharmony_ci      sanei_pa4s2_writebyte (dev->fd, 6, sel);
266141cc406Sopenharmony_ci      sanei_pa4s2_writebyte (dev->fd, 5, voltages[voltage][ctr]);
267141cc406Sopenharmony_ci
268141cc406Sopenharmony_ci    }
269141cc406Sopenharmony_ci
270141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x00);
271141cc406Sopenharmony_ci
272141cc406Sopenharmony_ci}
273141cc406Sopenharmony_ci
274141cc406Sopenharmony_cistatic int
275141cc406Sopenharmony_cicompar (const void *a, const void *b)
276141cc406Sopenharmony_ci{
277141cc406Sopenharmony_ci  return (signed int) (*(const SANE_Byte *) a) -
278141cc406Sopenharmony_ci    (signed int) (*(const SANE_Byte *) b);
279141cc406Sopenharmony_ci}
280141cc406Sopenharmony_ci
281141cc406Sopenharmony_cistatic void
282141cc406Sopenharmony_ciset_ccd_channel_101x (Mustek_pp_Handle * dev, int channel)
283141cc406Sopenharmony_ci{
284141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
285141cc406Sopenharmony_ci  switch (priv->asic)
286141cc406Sopenharmony_ci    {
287141cc406Sopenharmony_ci    case CCD300_ASIC1013:
288141cc406Sopenharmony_ci      set_ccd_channel_1013 (dev, channel);
289141cc406Sopenharmony_ci      break;
290141cc406Sopenharmony_ci
291141cc406Sopenharmony_ci    case CCD300_ASIC1015:
292141cc406Sopenharmony_ci      set_ccd_channel_1015 (dev, channel);
293141cc406Sopenharmony_ci      break;
294141cc406Sopenharmony_ci    }
295141cc406Sopenharmony_ci}
296141cc406Sopenharmony_ci
297141cc406Sopenharmony_cistatic void
298141cc406Sopenharmony_cimotor_forward_101x (Mustek_pp_Handle * dev)
299141cc406Sopenharmony_ci{
300141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
301141cc406Sopenharmony_ci  switch (priv->asic)
302141cc406Sopenharmony_ci    {
303141cc406Sopenharmony_ci    case CCD300_ASIC1013:
304141cc406Sopenharmony_ci      motor_forward_1013 (dev);
305141cc406Sopenharmony_ci      break;
306141cc406Sopenharmony_ci
307141cc406Sopenharmony_ci    case CCD300_ASIC1015:
308141cc406Sopenharmony_ci      motor_forward_1015 (dev);
309141cc406Sopenharmony_ci      break;
310141cc406Sopenharmony_ci    }
311141cc406Sopenharmony_ci}
312141cc406Sopenharmony_ci
313141cc406Sopenharmony_cistatic void
314141cc406Sopenharmony_cimotor_backward_101x (Mustek_pp_Handle * dev)
315141cc406Sopenharmony_ci{
316141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
317141cc406Sopenharmony_ci  switch (priv->asic)
318141cc406Sopenharmony_ci    {
319141cc406Sopenharmony_ci    case CCD300_ASIC1013:
320141cc406Sopenharmony_ci      motor_backward_1013 (dev);
321141cc406Sopenharmony_ci      break;
322141cc406Sopenharmony_ci
323141cc406Sopenharmony_ci    case CCD300_ASIC1015:
324141cc406Sopenharmony_ci/*      motor_backward_1015 (dev); */
325141cc406Sopenharmony_ci      break;
326141cc406Sopenharmony_ci    }
327141cc406Sopenharmony_ci}
328141cc406Sopenharmony_ci
329141cc406Sopenharmony_cistatic void
330141cc406Sopenharmony_cimove_motor_101x (Mustek_pp_Handle * dev, int forward)
331141cc406Sopenharmony_ci{
332141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
333141cc406Sopenharmony_ci  if (forward == SANE_TRUE)
334141cc406Sopenharmony_ci    motor_forward_101x (dev);
335141cc406Sopenharmony_ci  else
336141cc406Sopenharmony_ci    motor_backward_101x (dev);
337141cc406Sopenharmony_ci
338141cc406Sopenharmony_ci  wait_bank_change (dev, priv->bank_count, 1);
339141cc406Sopenharmony_ci  reset_bank_count (dev);
340141cc406Sopenharmony_ci}
341141cc406Sopenharmony_ci
342141cc406Sopenharmony_ci
343141cc406Sopenharmony_cistatic void
344141cc406Sopenharmony_ciconfig_ccd_101x (Mustek_pp_Handle * dev)
345141cc406Sopenharmony_ci{
346141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
347141cc406Sopenharmony_ci  switch (priv->asic)
348141cc406Sopenharmony_ci    {
349141cc406Sopenharmony_ci    case CCD300_ASIC1013:
350141cc406Sopenharmony_ci      config_ccd_1013 (dev);
351141cc406Sopenharmony_ci      break;
352141cc406Sopenharmony_ci
353141cc406Sopenharmony_ci    case CCD300_ASIC1015:
354141cc406Sopenharmony_ci      config_ccd_1015 (dev);
355141cc406Sopenharmony_ci      break;
356141cc406Sopenharmony_ci    }
357141cc406Sopenharmony_ci}
358141cc406Sopenharmony_ci
359141cc406Sopenharmony_ci
360141cc406Sopenharmony_ci
361141cc406Sopenharmony_cistatic void
362141cc406Sopenharmony_ciread_line_101x (Mustek_pp_Handle * dev, SANE_Byte * buf, SANE_Int pixel,
363141cc406Sopenharmony_ci		SANE_Int RefBlack, SANE_Byte * calib, SANE_Int * gamma)
364141cc406Sopenharmony_ci{
365141cc406Sopenharmony_ci
366141cc406Sopenharmony_ci  SANE_Byte *cal = calib;
367141cc406Sopenharmony_ci  u_char color;
368141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
369141cc406Sopenharmony_ci  int ctr, skips = priv->adjustskip + 1, cval;
370141cc406Sopenharmony_ci
371141cc406Sopenharmony_ci  if (pixel <= 0)
372141cc406Sopenharmony_ci    return;
373141cc406Sopenharmony_ci
374141cc406Sopenharmony_ci  sanei_pa4s2_readbegin (dev->fd, 1);
375141cc406Sopenharmony_ci
376141cc406Sopenharmony_ci
377141cc406Sopenharmony_ci  if (priv->hwres == dev->res)
378141cc406Sopenharmony_ci    {
379141cc406Sopenharmony_ci
380141cc406Sopenharmony_ci      while (skips--)
381141cc406Sopenharmony_ci	sanei_pa4s2_readbyte (dev->fd, &color);
382141cc406Sopenharmony_ci
383141cc406Sopenharmony_ci      for (ctr = 0; ctr < pixel; ctr++)
384141cc406Sopenharmony_ci	{
385141cc406Sopenharmony_ci
386141cc406Sopenharmony_ci	  sanei_pa4s2_readbyte (dev->fd, &color);
387141cc406Sopenharmony_ci
388141cc406Sopenharmony_ci	  cval = color;
389141cc406Sopenharmony_ci
390141cc406Sopenharmony_ci	  if (cval < RefBlack)
391141cc406Sopenharmony_ci	    cval = 0;
392141cc406Sopenharmony_ci	  else
393141cc406Sopenharmony_ci	    cval -= RefBlack;
394141cc406Sopenharmony_ci
395141cc406Sopenharmony_ci	  if (cal)
396141cc406Sopenharmony_ci	    {
397141cc406Sopenharmony_ci	      if (cval >= cal[ctr])
398141cc406Sopenharmony_ci		cval = 0xFF;
399141cc406Sopenharmony_ci	      else
400141cc406Sopenharmony_ci		{
401141cc406Sopenharmony_ci		  cval <<= 8;
402141cc406Sopenharmony_ci		  cval /= (int) cal[ctr];
403141cc406Sopenharmony_ci		}
404141cc406Sopenharmony_ci	    }
405141cc406Sopenharmony_ci
406141cc406Sopenharmony_ci	  if (gamma)
407141cc406Sopenharmony_ci	    cval = gamma[cval];
408141cc406Sopenharmony_ci
409141cc406Sopenharmony_ci	  buf[ctr] = cval;
410141cc406Sopenharmony_ci
411141cc406Sopenharmony_ci	}
412141cc406Sopenharmony_ci
413141cc406Sopenharmony_ci    }
414141cc406Sopenharmony_ci  else
415141cc406Sopenharmony_ci    {
416141cc406Sopenharmony_ci
417141cc406Sopenharmony_ci      int pos = 0, bpos = 0;
418141cc406Sopenharmony_ci
419141cc406Sopenharmony_ci      while (skips--)
420141cc406Sopenharmony_ci	sanei_pa4s2_readbyte (dev->fd, &color);
421141cc406Sopenharmony_ci
422141cc406Sopenharmony_ci      ctr = 0;
423141cc406Sopenharmony_ci
424141cc406Sopenharmony_ci      do
425141cc406Sopenharmony_ci	{
426141cc406Sopenharmony_ci
427141cc406Sopenharmony_ci	  sanei_pa4s2_readbyte (dev->fd, &color);
428141cc406Sopenharmony_ci
429141cc406Sopenharmony_ci	  cval = color;
430141cc406Sopenharmony_ci
431141cc406Sopenharmony_ci	  if (ctr < (pos >> SANE_FIXED_SCALE_SHIFT))
432141cc406Sopenharmony_ci	    {
433141cc406Sopenharmony_ci	      ctr++;
434141cc406Sopenharmony_ci	      continue;
435141cc406Sopenharmony_ci	    }
436141cc406Sopenharmony_ci
437141cc406Sopenharmony_ci	  ctr++;
438141cc406Sopenharmony_ci	  pos += priv->res_step;
439141cc406Sopenharmony_ci
440141cc406Sopenharmony_ci
441141cc406Sopenharmony_ci	  if (cval < RefBlack)
442141cc406Sopenharmony_ci	    cval = 0;
443141cc406Sopenharmony_ci	  else
444141cc406Sopenharmony_ci	    cval -= RefBlack;
445141cc406Sopenharmony_ci
446141cc406Sopenharmony_ci	  if (cal)
447141cc406Sopenharmony_ci	    {
448141cc406Sopenharmony_ci	      if (cval >= cal[bpos])
449141cc406Sopenharmony_ci		cval = 0xFF;
450141cc406Sopenharmony_ci	      else
451141cc406Sopenharmony_ci		{
452141cc406Sopenharmony_ci		  cval <<= 8;
453141cc406Sopenharmony_ci		  cval /= (int) cal[bpos];
454141cc406Sopenharmony_ci		}
455141cc406Sopenharmony_ci	    }
456141cc406Sopenharmony_ci
457141cc406Sopenharmony_ci	  if (gamma)
458141cc406Sopenharmony_ci	    cval = gamma[cval];
459141cc406Sopenharmony_ci
460141cc406Sopenharmony_ci	  buf[bpos++] = cval;
461141cc406Sopenharmony_ci
462141cc406Sopenharmony_ci	}
463141cc406Sopenharmony_ci      while (bpos < pixel);
464141cc406Sopenharmony_ci
465141cc406Sopenharmony_ci    }
466141cc406Sopenharmony_ci
467141cc406Sopenharmony_ci  sanei_pa4s2_readend (dev->fd);
468141cc406Sopenharmony_ci
469141cc406Sopenharmony_ci}
470141cc406Sopenharmony_ci
471141cc406Sopenharmony_cistatic void
472141cc406Sopenharmony_ciread_average_line_101x (Mustek_pp_Handle * dev, SANE_Byte * buf, int pixel,
473141cc406Sopenharmony_ci			int RefBlack)
474141cc406Sopenharmony_ci{
475141cc406Sopenharmony_ci
476141cc406Sopenharmony_ci  SANE_Byte lbuf[4][CCD300_MAXHSIZE * 2];
477141cc406Sopenharmony_ci  int ctr, sum;
478141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
479141cc406Sopenharmony_ci
480141cc406Sopenharmony_ci  for (ctr = 0; ctr < 4; ctr++)
481141cc406Sopenharmony_ci    {
482141cc406Sopenharmony_ci
483141cc406Sopenharmony_ci      wait_bank_change (dev, priv->bank_count, 1);
484141cc406Sopenharmony_ci      read_line_101x (dev, lbuf[ctr], pixel, RefBlack, NULL, NULL);
485141cc406Sopenharmony_ci      reset_bank_count (dev);
486141cc406Sopenharmony_ci      if (ctr < 3)
487141cc406Sopenharmony_ci	set_sti (dev);
488141cc406Sopenharmony_ci
489141cc406Sopenharmony_ci    }
490141cc406Sopenharmony_ci
491141cc406Sopenharmony_ci  for (ctr = 0; ctr < pixel; ctr++)
492141cc406Sopenharmony_ci    {
493141cc406Sopenharmony_ci
494141cc406Sopenharmony_ci      sum = lbuf[0][ctr] + lbuf[1][ctr] + lbuf[2][ctr] + lbuf[3][ctr];
495141cc406Sopenharmony_ci
496141cc406Sopenharmony_ci      buf[ctr] = (sum / 4);
497141cc406Sopenharmony_ci
498141cc406Sopenharmony_ci    }
499141cc406Sopenharmony_ci
500141cc406Sopenharmony_ci}
501141cc406Sopenharmony_ci
502141cc406Sopenharmony_cistatic void
503141cc406Sopenharmony_cifind_black_side_edge_101x (Mustek_pp_Handle * dev)
504141cc406Sopenharmony_ci{
505141cc406Sopenharmony_ci  SANE_Byte buf[CCD300_MAXHSIZE * 2];
506141cc406Sopenharmony_ci  SANE_Byte blackposition[5];
507141cc406Sopenharmony_ci  int pos = 0, ctr, blackpos;
508141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
509141cc406Sopenharmony_ci
510141cc406Sopenharmony_ci
511141cc406Sopenharmony_ci  for (ctr = 0; ctr < 20; ctr++)
512141cc406Sopenharmony_ci    {
513141cc406Sopenharmony_ci
514141cc406Sopenharmony_ci      motor_forward_101x (dev);
515141cc406Sopenharmony_ci      wait_bank_change (dev, priv->bank_count, 1);
516141cc406Sopenharmony_ci      read_line_101x (dev, buf, CCD300_MAXHSIZE, 0, NULL, NULL);
517141cc406Sopenharmony_ci      reset_bank_count (dev);
518141cc406Sopenharmony_ci
519141cc406Sopenharmony_ci      priv->ref_black = priv->ref_red = priv->ref_green = priv->ref_blue =
520141cc406Sopenharmony_ci	buf[0];
521141cc406Sopenharmony_ci
522141cc406Sopenharmony_ci      blackpos = CCD300_MAXHSIZE / 4;
523141cc406Sopenharmony_ci
524141cc406Sopenharmony_ci      while ((abs (buf[blackpos] - buf[0]) >= 15) && (blackpos > 0))
525141cc406Sopenharmony_ci	blackpos--;
526141cc406Sopenharmony_ci
527141cc406Sopenharmony_ci      if (blackpos > 1)
528141cc406Sopenharmony_ci	blackposition[pos++] = blackpos;
529141cc406Sopenharmony_ci
530141cc406Sopenharmony_ci      if (pos == 5)
531141cc406Sopenharmony_ci	break;
532141cc406Sopenharmony_ci
533141cc406Sopenharmony_ci    }
534141cc406Sopenharmony_ci
535141cc406Sopenharmony_ci  blackpos = 0;
536141cc406Sopenharmony_ci
537141cc406Sopenharmony_ci  for (ctr = 0; ctr < pos; ctr++)
538141cc406Sopenharmony_ci    if (blackposition[ctr] > blackpos)
539141cc406Sopenharmony_ci      blackpos = blackposition[ctr];
540141cc406Sopenharmony_ci
541141cc406Sopenharmony_ci  if (blackpos < 0x66)
542141cc406Sopenharmony_ci    blackpos = 0x6A;
543141cc406Sopenharmony_ci
544141cc406Sopenharmony_ci  priv->blackpos = blackpos;
545141cc406Sopenharmony_ci  priv->saved_skipcount = (blackpos + 12) & 0xFF;
546141cc406Sopenharmony_ci
547141cc406Sopenharmony_ci}
548141cc406Sopenharmony_ci
549141cc406Sopenharmony_cistatic void
550141cc406Sopenharmony_cimin_color_levels_101x (Mustek_pp_Handle * dev)
551141cc406Sopenharmony_ci{
552141cc406Sopenharmony_ci
553141cc406Sopenharmony_ci  SANE_Byte buf[CCD300_MAXHSIZE * 2];
554141cc406Sopenharmony_ci  int ctr, sum = 0;
555141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
556141cc406Sopenharmony_ci
557141cc406Sopenharmony_ci  for (ctr = 0; ctr < 8; ctr++)
558141cc406Sopenharmony_ci    {
559141cc406Sopenharmony_ci
560141cc406Sopenharmony_ci      set_ccd_channel_101x (dev, CCD300_CHANNEL_RED);
561141cc406Sopenharmony_ci      set_sti (dev);
562141cc406Sopenharmony_ci      wait_bank_change (dev, priv->bank_count, 1);
563141cc406Sopenharmony_ci
564141cc406Sopenharmony_ci      read_line_101x (dev, buf, CCD300_MAXHSIZE, 0, NULL, NULL);
565141cc406Sopenharmony_ci
566141cc406Sopenharmony_ci      reset_bank_count (dev);
567141cc406Sopenharmony_ci
568141cc406Sopenharmony_ci      sum += buf[3];
569141cc406Sopenharmony_ci
570141cc406Sopenharmony_ci    }
571141cc406Sopenharmony_ci
572141cc406Sopenharmony_ci  priv->ref_red = sum / 8;
573141cc406Sopenharmony_ci
574141cc406Sopenharmony_ci  sum = 0;
575141cc406Sopenharmony_ci
576141cc406Sopenharmony_ci  for (ctr = 0; ctr < 8; ctr++)
577141cc406Sopenharmony_ci    {
578141cc406Sopenharmony_ci
579141cc406Sopenharmony_ci      set_ccd_channel_101x (dev, CCD300_CHANNEL_GREEN);
580141cc406Sopenharmony_ci      set_sti (dev);
581141cc406Sopenharmony_ci      wait_bank_change (dev, priv->bank_count, 1);
582141cc406Sopenharmony_ci
583141cc406Sopenharmony_ci      read_line_101x (dev, buf, CCD300_MAXHSIZE, 0, NULL, NULL);
584141cc406Sopenharmony_ci
585141cc406Sopenharmony_ci      reset_bank_count (dev);
586141cc406Sopenharmony_ci
587141cc406Sopenharmony_ci      sum += buf[3];
588141cc406Sopenharmony_ci
589141cc406Sopenharmony_ci    }
590141cc406Sopenharmony_ci
591141cc406Sopenharmony_ci  priv->ref_green = sum / 8;
592141cc406Sopenharmony_ci
593141cc406Sopenharmony_ci  sum = 0;
594141cc406Sopenharmony_ci
595141cc406Sopenharmony_ci  for (ctr = 0; ctr < 8; ctr++)
596141cc406Sopenharmony_ci    {
597141cc406Sopenharmony_ci
598141cc406Sopenharmony_ci      set_ccd_channel_101x (dev, CCD300_CHANNEL_BLUE);
599141cc406Sopenharmony_ci      set_sti (dev);
600141cc406Sopenharmony_ci      wait_bank_change (dev, priv->bank_count, 1);
601141cc406Sopenharmony_ci
602141cc406Sopenharmony_ci      read_line_101x (dev, buf, CCD300_MAXHSIZE, 0, NULL, NULL);
603141cc406Sopenharmony_ci
604141cc406Sopenharmony_ci      reset_bank_count (dev);
605141cc406Sopenharmony_ci
606141cc406Sopenharmony_ci      sum += buf[3];
607141cc406Sopenharmony_ci
608141cc406Sopenharmony_ci    }
609141cc406Sopenharmony_ci
610141cc406Sopenharmony_ci  priv->ref_blue = sum / 8;
611141cc406Sopenharmony_ci
612141cc406Sopenharmony_ci}
613141cc406Sopenharmony_ci
614141cc406Sopenharmony_ci
615141cc406Sopenharmony_cistatic void
616141cc406Sopenharmony_cimax_color_levels_101x (Mustek_pp_Handle * dev)
617141cc406Sopenharmony_ci{
618141cc406Sopenharmony_ci
619141cc406Sopenharmony_ci  int ctr, line, sum;
620141cc406Sopenharmony_ci  SANE_Byte rbuf[32][CCD300_MAXHSIZE * 2];
621141cc406Sopenharmony_ci  SANE_Byte gbuf[32][CCD300_MAXHSIZE * 2];
622141cc406Sopenharmony_ci  SANE_Byte bbuf[32][CCD300_MAXHSIZE * 2];
623141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
624141cc406Sopenharmony_ci
625141cc406Sopenharmony_ci  SANE_Byte maxbuf[32];
626141cc406Sopenharmony_ci
627141cc406Sopenharmony_ci  for (ctr = 0; ctr < 32; ctr++)
628141cc406Sopenharmony_ci    {
629141cc406Sopenharmony_ci
630141cc406Sopenharmony_ci      if (dev->mode == MODE_COLOR)
631141cc406Sopenharmony_ci	{
632141cc406Sopenharmony_ci
633141cc406Sopenharmony_ci	  set_ccd_channel_101x (dev, CCD300_CHANNEL_RED);
634141cc406Sopenharmony_ci	  motor_forward_101x (dev);
635141cc406Sopenharmony_ci
636141cc406Sopenharmony_ci	  read_average_line_101x (dev, rbuf[ctr], dev->params.pixels_per_line,
637141cc406Sopenharmony_ci				  priv->ref_red);
638141cc406Sopenharmony_ci
639141cc406Sopenharmony_ci	  set_ccd_channel_101x (dev, CCD300_CHANNEL_GREEN);
640141cc406Sopenharmony_ci	  set_sti (dev);
641141cc406Sopenharmony_ci
642141cc406Sopenharmony_ci	  read_average_line_101x (dev, gbuf[ctr], dev->params.pixels_per_line,
643141cc406Sopenharmony_ci				  priv->ref_green);
644141cc406Sopenharmony_ci
645141cc406Sopenharmony_ci	  set_ccd_channel_101x (dev, CCD300_CHANNEL_BLUE);
646141cc406Sopenharmony_ci	  set_sti (dev);
647141cc406Sopenharmony_ci
648141cc406Sopenharmony_ci	  read_average_line_101x (dev, bbuf[ctr], dev->params.pixels_per_line,
649141cc406Sopenharmony_ci				  priv->ref_blue);
650141cc406Sopenharmony_ci
651141cc406Sopenharmony_ci	}
652141cc406Sopenharmony_ci      else
653141cc406Sopenharmony_ci	{
654141cc406Sopenharmony_ci
655141cc406Sopenharmony_ci	  priv->channel = CCD300_CHANNEL_GRAY;
656141cc406Sopenharmony_ci
657141cc406Sopenharmony_ci	  motor_forward_101x (dev);
658141cc406Sopenharmony_ci
659141cc406Sopenharmony_ci	  read_average_line_101x (dev, gbuf[ctr], dev->params.pixels_per_line,
660141cc406Sopenharmony_ci				  priv->ref_black);
661141cc406Sopenharmony_ci
662141cc406Sopenharmony_ci	}
663141cc406Sopenharmony_ci
664141cc406Sopenharmony_ci    }
665141cc406Sopenharmony_ci
666141cc406Sopenharmony_ci
667141cc406Sopenharmony_ci  for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++)
668141cc406Sopenharmony_ci    {
669141cc406Sopenharmony_ci      for (line = 0; line < 32; line++)
670141cc406Sopenharmony_ci	maxbuf[line] = gbuf[line][ctr];
671141cc406Sopenharmony_ci
672141cc406Sopenharmony_ci      qsort (maxbuf, 32, sizeof (maxbuf[0]), compar);
673141cc406Sopenharmony_ci
674141cc406Sopenharmony_ci      sum = maxbuf[4] + maxbuf[5] + maxbuf[6] + maxbuf[7];
675141cc406Sopenharmony_ci
676141cc406Sopenharmony_ci      priv->calib_g[ctr] = sum / 4;
677141cc406Sopenharmony_ci
678141cc406Sopenharmony_ci    }
679141cc406Sopenharmony_ci
680141cc406Sopenharmony_ci  if (dev->mode == MODE_COLOR)
681141cc406Sopenharmony_ci    {
682141cc406Sopenharmony_ci
683141cc406Sopenharmony_ci      for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++)
684141cc406Sopenharmony_ci	{
685141cc406Sopenharmony_ci	  for (line = 0; line < 32; line++)
686141cc406Sopenharmony_ci	    maxbuf[line] = rbuf[line][ctr];
687141cc406Sopenharmony_ci
688141cc406Sopenharmony_ci	  qsort (maxbuf, 32, sizeof (maxbuf[0]), compar);
689141cc406Sopenharmony_ci
690141cc406Sopenharmony_ci	  sum = maxbuf[4] + maxbuf[5] + maxbuf[6] + maxbuf[7];
691141cc406Sopenharmony_ci
692141cc406Sopenharmony_ci	  priv->calib_r[ctr] = sum / 4;
693141cc406Sopenharmony_ci
694141cc406Sopenharmony_ci	}
695141cc406Sopenharmony_ci
696141cc406Sopenharmony_ci      for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++)
697141cc406Sopenharmony_ci	{
698141cc406Sopenharmony_ci	  for (line = 0; line < 32; line++)
699141cc406Sopenharmony_ci	    maxbuf[line] = bbuf[line][ctr];
700141cc406Sopenharmony_ci
701141cc406Sopenharmony_ci	  qsort (maxbuf, 32, sizeof (maxbuf[0]), compar);
702141cc406Sopenharmony_ci
703141cc406Sopenharmony_ci	  sum = maxbuf[4] + maxbuf[5] + maxbuf[6] + maxbuf[7];
704141cc406Sopenharmony_ci
705141cc406Sopenharmony_ci	  priv->calib_b[ctr] = sum / 4;
706141cc406Sopenharmony_ci
707141cc406Sopenharmony_ci	}
708141cc406Sopenharmony_ci
709141cc406Sopenharmony_ci    }
710141cc406Sopenharmony_ci
711141cc406Sopenharmony_ci}
712141cc406Sopenharmony_ci
713141cc406Sopenharmony_cistatic void
714141cc406Sopenharmony_cifind_black_top_edge_101x (Mustek_pp_Handle * dev)
715141cc406Sopenharmony_ci{
716141cc406Sopenharmony_ci
717141cc406Sopenharmony_ci  int lines = 0, ctr, pos;
718141cc406Sopenharmony_ci  SANE_Byte buf[CCD300_MAXHSIZE * 2];
719141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
720141cc406Sopenharmony_ci
721141cc406Sopenharmony_ci  priv->channel = CCD300_CHANNEL_GRAY;
722141cc406Sopenharmony_ci
723141cc406Sopenharmony_ci  do
724141cc406Sopenharmony_ci    {
725141cc406Sopenharmony_ci
726141cc406Sopenharmony_ci      motor_forward_101x (dev);
727141cc406Sopenharmony_ci      wait_bank_change (dev, priv->bank_count, 1);
728141cc406Sopenharmony_ci
729141cc406Sopenharmony_ci      read_line_101x (dev, buf, CCD300_MAXHSIZE, priv->ref_black, NULL, NULL);
730141cc406Sopenharmony_ci
731141cc406Sopenharmony_ci      reset_bank_count (dev);
732141cc406Sopenharmony_ci
733141cc406Sopenharmony_ci      pos = 0;
734141cc406Sopenharmony_ci
735141cc406Sopenharmony_ci      for (ctr = priv->blackpos; ctr > priv->blackpos - 10; ctr--)
736141cc406Sopenharmony_ci	if (buf[ctr] <= 15)
737141cc406Sopenharmony_ci	  pos++;
738141cc406Sopenharmony_ci
739141cc406Sopenharmony_ci    }
740141cc406Sopenharmony_ci  while ((pos >= 8) && (lines++ < 67));
741141cc406Sopenharmony_ci
742141cc406Sopenharmony_ci}
743141cc406Sopenharmony_ci
744141cc406Sopenharmony_cistatic void
745141cc406Sopenharmony_cicalibrate_device_101x (Mustek_pp_Handle * dev)
746141cc406Sopenharmony_ci{
747141cc406Sopenharmony_ci
748141cc406Sopenharmony_ci  int saved_ppl = dev->params.pixels_per_line, ctr;
749141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
750141cc406Sopenharmony_ci
751141cc406Sopenharmony_ci  priv->saved_mode = dev->mode;
752141cc406Sopenharmony_ci  priv->saved_invert = dev->invert;
753141cc406Sopenharmony_ci  priv->saved_skipcount = priv->skipcount;
754141cc406Sopenharmony_ci  priv->saved_skipimagebyte = priv->skipimagebytes;
755141cc406Sopenharmony_ci  priv->saved_adjustskip = priv->adjustskip;
756141cc406Sopenharmony_ci  priv->saved_res = dev->res;
757141cc406Sopenharmony_ci  priv->saved_hwres = priv->hwres;
758141cc406Sopenharmony_ci  priv->saved_res_step = priv->res_step;
759141cc406Sopenharmony_ci  priv->saved_line_step = priv->line_step;
760141cc406Sopenharmony_ci  priv->saved_channel = priv->channel;
761141cc406Sopenharmony_ci
762141cc406Sopenharmony_ci  dev->params.pixels_per_line = CCD300_MAXHSIZE;
763141cc406Sopenharmony_ci  priv->hwres = dev->res = 300;
764141cc406Sopenharmony_ci  dev->mode = MODE_GRAYSCALE;
765141cc406Sopenharmony_ci  priv->skipcount = priv->skipimagebytes = 0;
766141cc406Sopenharmony_ci  dev->invert = SANE_FALSE;
767141cc406Sopenharmony_ci  priv->channel = CCD300_CHANNEL_GRAY;
768141cc406Sopenharmony_ci
769141cc406Sopenharmony_ci  config_ccd_101x (dev);
770141cc406Sopenharmony_ci  get_bank_count (dev);
771141cc406Sopenharmony_ci
772141cc406Sopenharmony_ci  find_black_side_edge_101x (dev);
773141cc406Sopenharmony_ci
774141cc406Sopenharmony_ci  for (ctr = 0; ctr < 4; ctr++)
775141cc406Sopenharmony_ci    move_motor_101x (dev, SANE_TRUE);
776141cc406Sopenharmony_ci
777141cc406Sopenharmony_ci  dev->mode = priv->saved_mode;
778141cc406Sopenharmony_ci  dev->invert = priv->saved_invert;
779141cc406Sopenharmony_ci  priv->skipcount = priv->saved_skipcount;
780141cc406Sopenharmony_ci  priv->skipimagebytes = priv->saved_skipimagebyte;
781141cc406Sopenharmony_ci  priv->adjustskip = priv->saved_adjustskip;
782141cc406Sopenharmony_ci  dev->res = priv->saved_res;
783141cc406Sopenharmony_ci  priv->hwres = priv->saved_hwres;
784141cc406Sopenharmony_ci  priv->res_step = priv->saved_res_step;
785141cc406Sopenharmony_ci  priv->line_step = priv->saved_line_step;
786141cc406Sopenharmony_ci  priv->channel = priv->saved_channel;
787141cc406Sopenharmony_ci
788141cc406Sopenharmony_ci  priv->hwres = dev->res = 300;
789141cc406Sopenharmony_ci  priv->skipcount = priv->skipimagebytes = 0;
790141cc406Sopenharmony_ci  dev->invert = SANE_FALSE;
791141cc406Sopenharmony_ci
792141cc406Sopenharmony_ci  config_ccd_101x (dev);
793141cc406Sopenharmony_ci  get_bank_count (dev);
794141cc406Sopenharmony_ci
795141cc406Sopenharmony_ci  if ((dev->mode == MODE_COLOR) && (priv->ccd_type != 0))
796141cc406Sopenharmony_ci    min_color_levels_101x (dev);
797141cc406Sopenharmony_ci
798141cc406Sopenharmony_ci  dev->mode = priv->saved_mode;
799141cc406Sopenharmony_ci  dev->invert = priv->saved_invert;
800141cc406Sopenharmony_ci  priv->skipcount = priv->saved_skipcount;
801141cc406Sopenharmony_ci  priv->skipimagebytes = priv->saved_skipimagebyte;
802141cc406Sopenharmony_ci  priv->adjustskip = priv->saved_adjustskip;
803141cc406Sopenharmony_ci  dev->res = priv->saved_res;
804141cc406Sopenharmony_ci  priv->hwres = priv->saved_hwres;
805141cc406Sopenharmony_ci  priv->res_step = priv->saved_res_step;
806141cc406Sopenharmony_ci  priv->line_step = priv->saved_line_step;
807141cc406Sopenharmony_ci  priv->channel = priv->saved_channel;
808141cc406Sopenharmony_ci
809141cc406Sopenharmony_ci  dev->params.pixels_per_line = saved_ppl;
810141cc406Sopenharmony_ci  dev->invert = SANE_FALSE;
811141cc406Sopenharmony_ci
812141cc406Sopenharmony_ci  config_ccd_101x (dev);
813141cc406Sopenharmony_ci  get_bank_count (dev);
814141cc406Sopenharmony_ci
815141cc406Sopenharmony_ci  max_color_levels_101x (dev);
816141cc406Sopenharmony_ci
817141cc406Sopenharmony_ci  dev->params.pixels_per_line = CCD300_MAXHSIZE;
818141cc406Sopenharmony_ci  dev->mode = MODE_GRAYSCALE;
819141cc406Sopenharmony_ci  priv->hwres = dev->res = 300;
820141cc406Sopenharmony_ci  priv->skipcount = priv->skipimagebytes = 0;
821141cc406Sopenharmony_ci  dev->invert = SANE_FALSE;
822141cc406Sopenharmony_ci
823141cc406Sopenharmony_ci  config_ccd_101x (dev);
824141cc406Sopenharmony_ci  get_bank_count (dev);
825141cc406Sopenharmony_ci
826141cc406Sopenharmony_ci  find_black_top_edge_101x (dev);
827141cc406Sopenharmony_ci
828141cc406Sopenharmony_ci  dev->mode = priv->saved_mode;
829141cc406Sopenharmony_ci  dev->invert = priv->saved_invert;
830141cc406Sopenharmony_ci  priv->skipcount = priv->saved_skipcount;
831141cc406Sopenharmony_ci  priv->skipimagebytes = priv->saved_skipimagebyte;
832141cc406Sopenharmony_ci  priv->adjustskip = priv->saved_adjustskip;
833141cc406Sopenharmony_ci  dev->res = priv->saved_res;
834141cc406Sopenharmony_ci  priv->hwres = priv->saved_hwres;
835141cc406Sopenharmony_ci  priv->res_step = priv->saved_res_step;
836141cc406Sopenharmony_ci  priv->line_step = priv->saved_line_step;
837141cc406Sopenharmony_ci  priv->channel = priv->saved_channel;
838141cc406Sopenharmony_ci
839141cc406Sopenharmony_ci  dev->params.pixels_per_line = saved_ppl;
840141cc406Sopenharmony_ci
841141cc406Sopenharmony_ci  config_ccd_101x (dev);
842141cc406Sopenharmony_ci  get_bank_count (dev);
843141cc406Sopenharmony_ci
844141cc406Sopenharmony_ci}
845141cc406Sopenharmony_ci
846141cc406Sopenharmony_cistatic void
847141cc406Sopenharmony_ciget_grayscale_line_101x (Mustek_pp_Handle * dev, SANE_Byte * buf)
848141cc406Sopenharmony_ci{
849141cc406Sopenharmony_ci
850141cc406Sopenharmony_ci  int skips;
851141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
852141cc406Sopenharmony_ci
853141cc406Sopenharmony_ci  priv->line_diff += SANE_FIX (300.0 / (float) dev->res);
854141cc406Sopenharmony_ci
855141cc406Sopenharmony_ci  skips = (priv->line_diff >> SANE_FIXED_SCALE_SHIFT);
856141cc406Sopenharmony_ci
857141cc406Sopenharmony_ci  while (--skips)
858141cc406Sopenharmony_ci    {
859141cc406Sopenharmony_ci      motor_forward_101x (dev);
860141cc406Sopenharmony_ci      wait_bank_change (dev, priv->bank_count, 1);
861141cc406Sopenharmony_ci      reset_bank_count (dev);
862141cc406Sopenharmony_ci    }
863141cc406Sopenharmony_ci
864141cc406Sopenharmony_ci  priv->line_diff &= 0xFFFF;
865141cc406Sopenharmony_ci
866141cc406Sopenharmony_ci  motor_forward_101x (dev);
867141cc406Sopenharmony_ci  wait_bank_change (dev, priv->bank_count, 1);
868141cc406Sopenharmony_ci
869141cc406Sopenharmony_ci  read_line_101x (dev, buf, dev->params.pixels_per_line, priv->ref_black,
870141cc406Sopenharmony_ci		  priv->calib_g, NULL);
871141cc406Sopenharmony_ci
872141cc406Sopenharmony_ci  reset_bank_count (dev);
873141cc406Sopenharmony_ci
874141cc406Sopenharmony_ci}
875141cc406Sopenharmony_ci
876141cc406Sopenharmony_cistatic void
877141cc406Sopenharmony_ciget_lineart_line_101x (Mustek_pp_Handle * dev, SANE_Byte * buf)
878141cc406Sopenharmony_ci{
879141cc406Sopenharmony_ci
880141cc406Sopenharmony_ci  int ctr;
881141cc406Sopenharmony_ci  SANE_Byte gbuf[CCD300_MAXHSIZE * 2];
882141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
883141cc406Sopenharmony_ci
884141cc406Sopenharmony_ci  get_grayscale_line_101x (dev, gbuf);
885141cc406Sopenharmony_ci
886141cc406Sopenharmony_ci  memset (buf, 0xFF, dev->params.bytes_per_line);
887141cc406Sopenharmony_ci
888141cc406Sopenharmony_ci  for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++)
889141cc406Sopenharmony_ci    buf[ctr >> 3] ^= ((gbuf[ctr] > priv->bw) ? (1 << (7 - ctr % 8)) : 0);
890141cc406Sopenharmony_ci
891141cc406Sopenharmony_ci}
892141cc406Sopenharmony_ci
893141cc406Sopenharmony_cistatic void
894141cc406Sopenharmony_ciget_color_line_101x (Mustek_pp_Handle * dev, SANE_Byte * buf)
895141cc406Sopenharmony_ci{
896141cc406Sopenharmony_ci
897141cc406Sopenharmony_ci  SANE_Byte *red, *blue, *src, *dest;
898141cc406Sopenharmony_ci  int gotline = 0, ctr;
899141cc406Sopenharmony_ci  int gored, goblue, gogreen;
900141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
901141cc406Sopenharmony_ci  int step = priv->line_step;
902141cc406Sopenharmony_ci
903141cc406Sopenharmony_ci  do
904141cc406Sopenharmony_ci    {
905141cc406Sopenharmony_ci
906141cc406Sopenharmony_ci      red = priv->red[priv->redline];
907141cc406Sopenharmony_ci      blue = priv->blue[priv->blueline];
908141cc406Sopenharmony_ci
909141cc406Sopenharmony_ci      priv->ccd_line++;
910141cc406Sopenharmony_ci
911141cc406Sopenharmony_ci      if ((priv->rdiff >> SANE_FIXED_SCALE_SHIFT) == priv->ccd_line)
912141cc406Sopenharmony_ci	{
913141cc406Sopenharmony_ci	  gored = 1;
914141cc406Sopenharmony_ci	  priv->rdiff += step;
915141cc406Sopenharmony_ci	}
916141cc406Sopenharmony_ci      else
917141cc406Sopenharmony_ci	gored = 0;
918141cc406Sopenharmony_ci
919141cc406Sopenharmony_ci      if ((priv->bdiff >> SANE_FIXED_SCALE_SHIFT) == priv->ccd_line)
920141cc406Sopenharmony_ci	{
921141cc406Sopenharmony_ci	  goblue = 1;
922141cc406Sopenharmony_ci	  priv->bdiff += step;
923141cc406Sopenharmony_ci	}
924141cc406Sopenharmony_ci      else
925141cc406Sopenharmony_ci	goblue = 0;
926141cc406Sopenharmony_ci
927141cc406Sopenharmony_ci      if ((priv->gdiff >> SANE_FIXED_SCALE_SHIFT) == priv->ccd_line)
928141cc406Sopenharmony_ci	{
929141cc406Sopenharmony_ci	  gogreen = 1;
930141cc406Sopenharmony_ci	  priv->gdiff += step;
931141cc406Sopenharmony_ci	}
932141cc406Sopenharmony_ci      else
933141cc406Sopenharmony_ci	gogreen = 0;
934141cc406Sopenharmony_ci
935141cc406Sopenharmony_ci      if (!gored && !goblue && !gogreen)
936141cc406Sopenharmony_ci	{
937141cc406Sopenharmony_ci	  motor_forward_101x (dev);
938141cc406Sopenharmony_ci	  wait_bank_change (dev, priv->bank_count, 1);
939141cc406Sopenharmony_ci	  reset_bank_count (dev);
940141cc406Sopenharmony_ci	  if (priv->ccd_line >= (priv->line_step >> SANE_FIXED_SCALE_SHIFT))
941141cc406Sopenharmony_ci	    priv->redline = (priv->redline + 1) % priv->green_offs;
942141cc406Sopenharmony_ci	  if (priv->ccd_line >=
943141cc406Sopenharmony_ci	      priv->blue_offs + (priv->line_step >> SANE_FIXED_SCALE_SHIFT))
944141cc406Sopenharmony_ci	    priv->blueline = (priv->blueline + 1) % priv->blue_offs;
945141cc406Sopenharmony_ci	  continue;
946141cc406Sopenharmony_ci	}
947141cc406Sopenharmony_ci
948141cc406Sopenharmony_ci      if (gored)
949141cc406Sopenharmony_ci	priv->channel = CCD300_CHANNEL_RED;
950141cc406Sopenharmony_ci      else if (goblue)
951141cc406Sopenharmony_ci	priv->channel = CCD300_CHANNEL_BLUE;
952141cc406Sopenharmony_ci      else
953141cc406Sopenharmony_ci	priv->channel = CCD300_CHANNEL_GREEN;
954141cc406Sopenharmony_ci
955141cc406Sopenharmony_ci      motor_forward_101x (dev);
956141cc406Sopenharmony_ci      wait_bank_change (dev, priv->bank_count, 1);
957141cc406Sopenharmony_ci
958141cc406Sopenharmony_ci      if (priv->ccd_line >= priv->green_offs && gogreen)
959141cc406Sopenharmony_ci	{
960141cc406Sopenharmony_ci	  src = red;
961141cc406Sopenharmony_ci	  dest = buf;
962141cc406Sopenharmony_ci
963141cc406Sopenharmony_ci	  for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++)
964141cc406Sopenharmony_ci	    {
965141cc406Sopenharmony_ci	      *dest = *src++;
966141cc406Sopenharmony_ci	      dest += 3;
967141cc406Sopenharmony_ci	    }
968141cc406Sopenharmony_ci	}
969141cc406Sopenharmony_ci
970141cc406Sopenharmony_ci      if (gored)
971141cc406Sopenharmony_ci	{
972141cc406Sopenharmony_ci
973141cc406Sopenharmony_ci	  read_line_101x (dev, red, dev->params.pixels_per_line,
974141cc406Sopenharmony_ci			  priv->ref_red, priv->calib_r, NULL);
975141cc406Sopenharmony_ci
976141cc406Sopenharmony_ci	  reset_bank_count (dev);
977141cc406Sopenharmony_ci
978141cc406Sopenharmony_ci	}
979141cc406Sopenharmony_ci
980141cc406Sopenharmony_ci      priv->redline = (priv->redline + 1) % priv->green_offs;
981141cc406Sopenharmony_ci
982141cc406Sopenharmony_ci      if (priv->ccd_line >= priv->green_offs && gogreen)
983141cc406Sopenharmony_ci	{
984141cc406Sopenharmony_ci	  src = blue;
985141cc406Sopenharmony_ci	  dest = buf + 2;
986141cc406Sopenharmony_ci
987141cc406Sopenharmony_ci
988141cc406Sopenharmony_ci	  for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++)
989141cc406Sopenharmony_ci	    {
990141cc406Sopenharmony_ci	      *dest = *src++;
991141cc406Sopenharmony_ci	      dest += 3;
992141cc406Sopenharmony_ci	    }
993141cc406Sopenharmony_ci
994141cc406Sopenharmony_ci	}
995141cc406Sopenharmony_ci
996141cc406Sopenharmony_ci      if (goblue)
997141cc406Sopenharmony_ci	{
998141cc406Sopenharmony_ci	  if (gored)
999141cc406Sopenharmony_ci	    {
1000141cc406Sopenharmony_ci	      set_ccd_channel_101x (dev, CCD300_CHANNEL_BLUE);
1001141cc406Sopenharmony_ci	      set_sti (dev);
1002141cc406Sopenharmony_ci	      wait_bank_change (dev, priv->bank_count, 1);
1003141cc406Sopenharmony_ci	    }
1004141cc406Sopenharmony_ci
1005141cc406Sopenharmony_ci	  read_line_101x (dev, blue, dev->params.pixels_per_line,
1006141cc406Sopenharmony_ci			  priv->ref_blue, priv->calib_b, NULL);
1007141cc406Sopenharmony_ci
1008141cc406Sopenharmony_ci	  reset_bank_count (dev);
1009141cc406Sopenharmony_ci
1010141cc406Sopenharmony_ci	}
1011141cc406Sopenharmony_ci
1012141cc406Sopenharmony_ci      if (priv->ccd_line >=
1013141cc406Sopenharmony_ci	  priv->blue_offs + (priv->line_step >> SANE_FIXED_SCALE_SHIFT))
1014141cc406Sopenharmony_ci	priv->blueline = (priv->blueline + 1) % priv->blue_offs;
1015141cc406Sopenharmony_ci
1016141cc406Sopenharmony_ci      if (gogreen)
1017141cc406Sopenharmony_ci	{
1018141cc406Sopenharmony_ci
1019141cc406Sopenharmony_ci	  if (gored || goblue)
1020141cc406Sopenharmony_ci	    {
1021141cc406Sopenharmony_ci	      set_ccd_channel_101x (dev, CCD300_CHANNEL_GREEN);
1022141cc406Sopenharmony_ci	      set_sti (dev);
1023141cc406Sopenharmony_ci	      wait_bank_change (dev, priv->bank_count, 1);
1024141cc406Sopenharmony_ci	    }
1025141cc406Sopenharmony_ci
1026141cc406Sopenharmony_ci	  read_line_101x (dev, priv->green, dev->params.pixels_per_line,
1027141cc406Sopenharmony_ci			  priv->ref_green, priv->calib_g, NULL);
1028141cc406Sopenharmony_ci
1029141cc406Sopenharmony_ci	  reset_bank_count (dev);
1030141cc406Sopenharmony_ci
1031141cc406Sopenharmony_ci	  src = priv->green;
1032141cc406Sopenharmony_ci	  dest = buf + 1;
1033141cc406Sopenharmony_ci
1034141cc406Sopenharmony_ci	  for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++)
1035141cc406Sopenharmony_ci	    {
1036141cc406Sopenharmony_ci	      *dest = *src++;
1037141cc406Sopenharmony_ci	      dest += 3;
1038141cc406Sopenharmony_ci	    }
1039141cc406Sopenharmony_ci
1040141cc406Sopenharmony_ci	  gotline = 1;
1041141cc406Sopenharmony_ci	}
1042141cc406Sopenharmony_ci
1043141cc406Sopenharmony_ci    }
1044141cc406Sopenharmony_ci  while (!gotline);
1045141cc406Sopenharmony_ci
1046141cc406Sopenharmony_ci}
1047141cc406Sopenharmony_ci
1048141cc406Sopenharmony_ci
1049141cc406Sopenharmony_ci
1050141cc406Sopenharmony_ci/* these functions are for the 1013 chipset */
1051141cc406Sopenharmony_ci
1052141cc406Sopenharmony_cistatic void
1053141cc406Sopenharmony_ciset_ccd_channel_1013 (Mustek_pp_Handle * dev, int channel)
1054141cc406Sopenharmony_ci{
1055141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1056141cc406Sopenharmony_ci  priv->channel = channel;
1057141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, chan_codes_1013[channel]);
1058141cc406Sopenharmony_ci}
1059141cc406Sopenharmony_ci
1060141cc406Sopenharmony_cistatic void
1061141cc406Sopenharmony_cimotor_backward_1013 (Mustek_pp_Handle * dev)
1062141cc406Sopenharmony_ci{
1063141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1064141cc406Sopenharmony_ci
1065141cc406Sopenharmony_ci  priv->motor_step++;
1066141cc406Sopenharmony_ci  set_led (dev);
1067141cc406Sopenharmony_ci
1068141cc406Sopenharmony_ci  if (priv->motor_phase > 3)
1069141cc406Sopenharmony_ci    priv->motor_phase = 3;
1070141cc406Sopenharmony_ci
1071141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x62);
1072141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 5, fullstep[priv->motor_phase]);
1073141cc406Sopenharmony_ci
1074141cc406Sopenharmony_ci  priv->motor_phase = (priv->motor_phase == 0 ? 3 : priv->motor_phase - 1);
1075141cc406Sopenharmony_ci
1076141cc406Sopenharmony_ci  set_ccd_channel_1013 (dev, priv->channel);
1077141cc406Sopenharmony_ci  set_sti (dev);
1078141cc406Sopenharmony_ci
1079141cc406Sopenharmony_ci}
1080141cc406Sopenharmony_ci
1081141cc406Sopenharmony_cistatic void
1082141cc406Sopenharmony_cireturn_home_1013 (Mustek_pp_Handle * dev)
1083141cc406Sopenharmony_ci{
1084141cc406Sopenharmony_ci  u_char ishome;
1085141cc406Sopenharmony_ci  int ctr;
1086141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1087141cc406Sopenharmony_ci
1088141cc406Sopenharmony_ci  /* 1013 can't return home all alone, nowait ignored */
1089141cc406Sopenharmony_ci
1090141cc406Sopenharmony_ci  for (ctr = 0; ctr < 4500; ctr++)
1091141cc406Sopenharmony_ci    {
1092141cc406Sopenharmony_ci
1093141cc406Sopenharmony_ci      /* check_is_home_1013 */
1094141cc406Sopenharmony_ci      sanei_pa4s2_readbegin (dev->fd, 2);
1095141cc406Sopenharmony_ci      sanei_pa4s2_readbyte (dev->fd, &ishome);
1096141cc406Sopenharmony_ci      sanei_pa4s2_readend (dev->fd);
1097141cc406Sopenharmony_ci
1098141cc406Sopenharmony_ci      /* yes, it should be is_not_home */
1099141cc406Sopenharmony_ci      if ((ishome & 1) == 0)
1100141cc406Sopenharmony_ci	break;
1101141cc406Sopenharmony_ci
1102141cc406Sopenharmony_ci      motor_backward_1013 (dev);
1103141cc406Sopenharmony_ci      wait_bank_change (dev, priv->bank_count, 0);
1104141cc406Sopenharmony_ci      reset_bank_count (dev);
1105141cc406Sopenharmony_ci
1106141cc406Sopenharmony_ci    }
1107141cc406Sopenharmony_ci
1108141cc406Sopenharmony_ci}
1109141cc406Sopenharmony_ci
1110141cc406Sopenharmony_cistatic void
1111141cc406Sopenharmony_cimotor_forward_1013 (Mustek_pp_Handle * dev)
1112141cc406Sopenharmony_ci{
1113141cc406Sopenharmony_ci
1114141cc406Sopenharmony_ci  int ctr;
1115141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1116141cc406Sopenharmony_ci
1117141cc406Sopenharmony_ci  priv->motor_step++;
1118141cc406Sopenharmony_ci  set_led (dev);
1119141cc406Sopenharmony_ci
1120141cc406Sopenharmony_ci  for (ctr = 0; ctr < 2; ctr++)
1121141cc406Sopenharmony_ci    {
1122141cc406Sopenharmony_ci
1123141cc406Sopenharmony_ci      sanei_pa4s2_writebyte (dev->fd, 6, 0x62);
1124141cc406Sopenharmony_ci      sanei_pa4s2_writebyte (dev->fd, 5, halfstep[priv->motor_phase]);
1125141cc406Sopenharmony_ci
1126141cc406Sopenharmony_ci      priv->motor_phase =
1127141cc406Sopenharmony_ci	(priv->motor_phase == 7 ? 0 : priv->motor_phase + 1);
1128141cc406Sopenharmony_ci
1129141cc406Sopenharmony_ci    }
1130141cc406Sopenharmony_ci
1131141cc406Sopenharmony_ci  set_ccd_channel_1013 (dev, priv->channel);
1132141cc406Sopenharmony_ci  set_sti (dev);
1133141cc406Sopenharmony_ci}
1134141cc406Sopenharmony_ci
1135141cc406Sopenharmony_ci
1136141cc406Sopenharmony_ci
1137141cc406Sopenharmony_cistatic void
1138141cc406Sopenharmony_ciconfig_ccd_1013 (Mustek_pp_Handle * dev)
1139141cc406Sopenharmony_ci{
1140141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1141141cc406Sopenharmony_ci
1142141cc406Sopenharmony_ci  if (dev->res != 0)
1143141cc406Sopenharmony_ci    priv->res_step = SANE_FIX ((float) priv->hwres / (float) dev->res);
1144141cc406Sopenharmony_ci
1145141cc406Sopenharmony_ci  set_dpi_value (dev);
1146141cc406Sopenharmony_ci
1147141cc406Sopenharmony_ci  /* set_start_channel_1013 (dev); */
1148141cc406Sopenharmony_ci
1149141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x05);
1150141cc406Sopenharmony_ci
1151141cc406Sopenharmony_ci  switch (dev->mode)
1152141cc406Sopenharmony_ci    {
1153141cc406Sopenharmony_ci    case MODE_BW:
1154141cc406Sopenharmony_ci    case MODE_GRAYSCALE:
1155141cc406Sopenharmony_ci      priv->channel = CCD300_CHANNEL_GRAY;
1156141cc406Sopenharmony_ci      break;
1157141cc406Sopenharmony_ci
1158141cc406Sopenharmony_ci    case MODE_COLOR:
1159141cc406Sopenharmony_ci      priv->channel = CCD300_CHANNEL_RED;
1160141cc406Sopenharmony_ci      break;
1161141cc406Sopenharmony_ci
1162141cc406Sopenharmony_ci    }
1163141cc406Sopenharmony_ci
1164141cc406Sopenharmony_ci  set_ccd_channel_1013 (dev, priv->channel);
1165141cc406Sopenharmony_ci
1166141cc406Sopenharmony_ci  /* set_invert_1013 (dev); */
1167141cc406Sopenharmony_ci
1168141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6,
1169141cc406Sopenharmony_ci			 (dev->invert == SANE_TRUE ? 0x04 : 0x14));
1170141cc406Sopenharmony_ci
1171141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x37);
1172141cc406Sopenharmony_ci  reset_bank_count (dev);
1173141cc406Sopenharmony_ci
1174141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x27);
1175141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x67);
1176141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x17);
1177141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x77);
1178141cc406Sopenharmony_ci
1179141cc406Sopenharmony_ci  /* set_initial_skip_1013 (dev); */
1180141cc406Sopenharmony_ci
1181141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x41);
1182141cc406Sopenharmony_ci
1183141cc406Sopenharmony_ci  priv->adjustskip = priv->skipcount + priv->skipimagebytes;
1184141cc406Sopenharmony_ci
1185141cc406Sopenharmony_ci  DBG (5, "config_ccd_1013: adjustskip %u\n", priv->adjustskip);
1186141cc406Sopenharmony_ci
1187141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 5, priv->adjustskip / 16 + 2);
1188141cc406Sopenharmony_ci
1189141cc406Sopenharmony_ci  priv->adjustskip %= 16;
1190141cc406Sopenharmony_ci
1191141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x81);
1192141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 5, 0x70);
1193141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x01);
1194141cc406Sopenharmony_ci
1195141cc406Sopenharmony_ci
1196141cc406Sopenharmony_ci  set_line_adjust (dev);
1197141cc406Sopenharmony_ci
1198141cc406Sopenharmony_ci  get_bank_count (dev);
1199141cc406Sopenharmony_ci
1200141cc406Sopenharmony_ci}
1201141cc406Sopenharmony_ci
1202141cc406Sopenharmony_ci/* these functions are for the 1015 chipset */
1203141cc406Sopenharmony_ci
1204141cc406Sopenharmony_ci
1205141cc406Sopenharmony_cistatic void
1206141cc406Sopenharmony_cimotor_control_1015 (Mustek_pp_Handle * dev, u_char control)
1207141cc406Sopenharmony_ci{
1208141cc406Sopenharmony_ci  u_char val;
1209141cc406Sopenharmony_ci
1210141cc406Sopenharmony_ci  DBG (5, "motor_controll_1015: control code 0x%02x\n",
1211141cc406Sopenharmony_ci       (unsigned int) control);
1212141cc406Sopenharmony_ci
1213141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0xF6);
1214141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x22);
1215141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 5, control);
1216141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x02);
1217141cc406Sopenharmony_ci
1218141cc406Sopenharmony_ci  do
1219141cc406Sopenharmony_ci    {
1220141cc406Sopenharmony_ci
1221141cc406Sopenharmony_ci      sanei_pa4s2_readbegin (dev->fd, 2);
1222141cc406Sopenharmony_ci      sanei_pa4s2_readbyte (dev->fd, &val);
1223141cc406Sopenharmony_ci      sanei_pa4s2_readend (dev->fd);
1224141cc406Sopenharmony_ci
1225141cc406Sopenharmony_ci    }
1226141cc406Sopenharmony_ci  while ((val & 0x08) != 0);
1227141cc406Sopenharmony_ci
1228141cc406Sopenharmony_ci}
1229141cc406Sopenharmony_ci
1230141cc406Sopenharmony_cistatic void
1231141cc406Sopenharmony_cireturn_home_1015 (Mustek_pp_Handle * dev, SANE_Bool nowait)
1232141cc406Sopenharmony_ci{
1233141cc406Sopenharmony_ci
1234141cc406Sopenharmony_ci  u_char ishome, control = 0xC3;
1235141cc406Sopenharmony_ci
1236141cc406Sopenharmony_ci  motor_control_1015 (dev, control);
1237141cc406Sopenharmony_ci
1238141cc406Sopenharmony_ci  do
1239141cc406Sopenharmony_ci    {
1240141cc406Sopenharmony_ci
1241141cc406Sopenharmony_ci      /* check_is_home_1015 */
1242141cc406Sopenharmony_ci      sanei_pa4s2_readbegin (dev->fd, 2);
1243141cc406Sopenharmony_ci      sanei_pa4s2_readbyte (dev->fd, &ishome);
1244141cc406Sopenharmony_ci      sanei_pa4s2_readend (dev->fd);
1245141cc406Sopenharmony_ci
1246141cc406Sopenharmony_ci      if (nowait)
1247141cc406Sopenharmony_ci	break;
1248141cc406Sopenharmony_ci
1249141cc406Sopenharmony_ci      usleep (1000);		/* much nicer load */
1250141cc406Sopenharmony_ci
1251141cc406Sopenharmony_ci    }
1252141cc406Sopenharmony_ci  while ((ishome & 2) == 0);
1253141cc406Sopenharmony_ci
1254141cc406Sopenharmony_ci}
1255141cc406Sopenharmony_ci
1256141cc406Sopenharmony_cistatic void
1257141cc406Sopenharmony_cimotor_forward_1015 (Mustek_pp_Handle * dev)
1258141cc406Sopenharmony_ci{
1259141cc406Sopenharmony_ci  u_char control = 0x1B;
1260141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1261141cc406Sopenharmony_ci
1262141cc406Sopenharmony_ci  priv->motor_step++;
1263141cc406Sopenharmony_ci  set_led (dev);
1264141cc406Sopenharmony_ci
1265141cc406Sopenharmony_ci
1266141cc406Sopenharmony_ci  motor_control_1015 (dev, control);
1267141cc406Sopenharmony_ci
1268141cc406Sopenharmony_ci  set_ccd_channel_1015 (dev, priv->channel);
1269141cc406Sopenharmony_ci  set_sti (dev);
1270141cc406Sopenharmony_ci
1271141cc406Sopenharmony_ci}
1272141cc406Sopenharmony_ci
1273141cc406Sopenharmony_ci/*
1274141cc406Sopenharmony_cistatic void
1275141cc406Sopenharmony_cimotor_backward_1015 (Mustek_pp_Handle * dev)
1276141cc406Sopenharmony_ci{
1277141cc406Sopenharmony_ci  u_char control = 0x43;
1278141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1279141cc406Sopenharmony_ci
1280141cc406Sopenharmony_ci  priv->motor_step++;
1281141cc406Sopenharmony_ci
1282141cc406Sopenharmony_ci  set_led (dev);
1283141cc406Sopenharmony_ci
1284141cc406Sopenharmony_ci  switch (priv->ccd_type)
1285141cc406Sopenharmony_ci    {
1286141cc406Sopenharmony_ci    case 1:
1287141cc406Sopenharmony_ci      control = 0x1B;
1288141cc406Sopenharmony_ci      break;
1289141cc406Sopenharmony_ci
1290141cc406Sopenharmony_ci    default:
1291141cc406Sopenharmony_ci      control = 0x43;
1292141cc406Sopenharmony_ci      break;
1293141cc406Sopenharmony_ci    }
1294141cc406Sopenharmony_ci
1295141cc406Sopenharmony_ci  motor_control_1015 (dev, control);
1296141cc406Sopenharmony_ci
1297141cc406Sopenharmony_ci  set_ccd_channel_1015 (dev, priv->channel);
1298141cc406Sopenharmony_ci  set_sti (dev);
1299141cc406Sopenharmony_ci
1300141cc406Sopenharmony_ci}
1301141cc406Sopenharmony_ci*/
1302141cc406Sopenharmony_ci
1303141cc406Sopenharmony_ci
1304141cc406Sopenharmony_cistatic void
1305141cc406Sopenharmony_ciset_ccd_channel_1015 (Mustek_pp_Handle * dev, int channel)
1306141cc406Sopenharmony_ci{
1307141cc406Sopenharmony_ci
1308141cc406Sopenharmony_ci  u_char chancode = chan_codes_1015[channel];
1309141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1310141cc406Sopenharmony_ci
1311141cc406Sopenharmony_ci  priv->channel = channel;
1312141cc406Sopenharmony_ci
1313141cc406Sopenharmony_ci  priv->image_control &= 0x34;
1314141cc406Sopenharmony_ci  chancode |= priv->image_control;
1315141cc406Sopenharmony_ci
1316141cc406Sopenharmony_ci
1317141cc406Sopenharmony_ci  priv->image_control = chancode;
1318141cc406Sopenharmony_ci
1319141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, chancode);
1320141cc406Sopenharmony_ci
1321141cc406Sopenharmony_ci}
1322141cc406Sopenharmony_ci
1323141cc406Sopenharmony_ci
1324141cc406Sopenharmony_cistatic void
1325141cc406Sopenharmony_ciconfig_ccd_1015 (Mustek_pp_Handle * dev)
1326141cc406Sopenharmony_ci{
1327141cc406Sopenharmony_ci
1328141cc406Sopenharmony_ci  u_char val;
1329141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1330141cc406Sopenharmony_ci
1331141cc406Sopenharmony_ci  if (dev->res != 0)
1332141cc406Sopenharmony_ci    priv->res_step = SANE_FIX ((float) priv->hwres / (float) dev->res);
1333141cc406Sopenharmony_ci
1334141cc406Sopenharmony_ci
1335141cc406Sopenharmony_ci  set_dpi_value (dev);
1336141cc406Sopenharmony_ci
1337141cc406Sopenharmony_ci  priv->image_control = 4;
1338141cc406Sopenharmony_ci
1339141cc406Sopenharmony_ci  /* set_start_channel_1015 (dev); */
1340141cc406Sopenharmony_ci
1341141cc406Sopenharmony_ci  switch (dev->mode)
1342141cc406Sopenharmony_ci    {
1343141cc406Sopenharmony_ci    case MODE_BW:
1344141cc406Sopenharmony_ci    case MODE_GRAYSCALE:
1345141cc406Sopenharmony_ci      priv->channel = CCD300_CHANNEL_GRAY;
1346141cc406Sopenharmony_ci      break;
1347141cc406Sopenharmony_ci
1348141cc406Sopenharmony_ci    case MODE_COLOR:
1349141cc406Sopenharmony_ci      priv->channel = CCD300_CHANNEL_RED;
1350141cc406Sopenharmony_ci      break;
1351141cc406Sopenharmony_ci
1352141cc406Sopenharmony_ci    }
1353141cc406Sopenharmony_ci
1354141cc406Sopenharmony_ci  set_ccd_channel_1015 (dev, priv->channel);
1355141cc406Sopenharmony_ci
1356141cc406Sopenharmony_ci
1357141cc406Sopenharmony_ci  /* set_invert_1015 (dev); */
1358141cc406Sopenharmony_ci
1359141cc406Sopenharmony_ci  priv->image_control &= 0xE4;
1360141cc406Sopenharmony_ci
1361141cc406Sopenharmony_ci  if (dev->invert == SANE_FALSE)
1362141cc406Sopenharmony_ci    priv->image_control |= 0x10;
1363141cc406Sopenharmony_ci
1364141cc406Sopenharmony_ci
1365141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, priv->image_control);
1366141cc406Sopenharmony_ci
1367141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x23);
1368141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 5, 0x00);
1369141cc406Sopenharmony_ci
1370141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x43);
1371141cc406Sopenharmony_ci
1372141cc406Sopenharmony_ci  switch (priv->ccd_type)
1373141cc406Sopenharmony_ci    {
1374141cc406Sopenharmony_ci    case 1:
1375141cc406Sopenharmony_ci      val = 0x6B;
1376141cc406Sopenharmony_ci      break;
1377141cc406Sopenharmony_ci    case 4:
1378141cc406Sopenharmony_ci      val = 0x9F;
1379141cc406Sopenharmony_ci      break;
1380141cc406Sopenharmony_ci    default:
1381141cc406Sopenharmony_ci      val = 0x92;
1382141cc406Sopenharmony_ci      break;
1383141cc406Sopenharmony_ci    }
1384141cc406Sopenharmony_ci
1385141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 5, val);
1386141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x03);
1387141cc406Sopenharmony_ci
1388141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x37);
1389141cc406Sopenharmony_ci  reset_bank_count (dev);
1390141cc406Sopenharmony_ci
1391141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x27);
1392141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x67);
1393141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x17);
1394141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x77);
1395141cc406Sopenharmony_ci
1396141cc406Sopenharmony_ci  /* set_initial_skip_1015 (dev); */
1397141cc406Sopenharmony_ci
1398141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x41);
1399141cc406Sopenharmony_ci
1400141cc406Sopenharmony_ci  priv->adjustskip = priv->skipcount + priv->skipimagebytes;
1401141cc406Sopenharmony_ci
1402141cc406Sopenharmony_ci  /* if (dev->CCD.mode == MODE_COLOR)
1403141cc406Sopenharmony_ci     dev->CCD.adjustskip <<= 3; */
1404141cc406Sopenharmony_ci
1405141cc406Sopenharmony_ci
1406141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 5, priv->adjustskip / 32 + 1);
1407141cc406Sopenharmony_ci
1408141cc406Sopenharmony_ci  priv->adjustskip %= 32;
1409141cc406Sopenharmony_ci
1410141cc406Sopenharmony_ci
1411141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x81);
1412141cc406Sopenharmony_ci
1413141cc406Sopenharmony_ci  /* expose time */
1414141cc406Sopenharmony_ci  switch (priv->ccd_type)
1415141cc406Sopenharmony_ci    {
1416141cc406Sopenharmony_ci    case 1:
1417141cc406Sopenharmony_ci
1418141cc406Sopenharmony_ci      val = 0xA8;
1419141cc406Sopenharmony_ci      break;
1420141cc406Sopenharmony_ci    case 0:
1421141cc406Sopenharmony_ci      val = 0x8A;
1422141cc406Sopenharmony_ci      break;
1423141cc406Sopenharmony_ci    default:
1424141cc406Sopenharmony_ci      val = 0xA8;
1425141cc406Sopenharmony_ci      break;
1426141cc406Sopenharmony_ci    }
1427141cc406Sopenharmony_ci
1428141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 5, val);
1429141cc406Sopenharmony_ci
1430141cc406Sopenharmony_ci  sanei_pa4s2_writebyte (dev->fd, 6, 0x01);
1431141cc406Sopenharmony_ci
1432141cc406Sopenharmony_ci
1433141cc406Sopenharmony_ci  set_line_adjust (dev);
1434141cc406Sopenharmony_ci
1435141cc406Sopenharmony_ci  get_bank_count (dev);
1436141cc406Sopenharmony_ci
1437141cc406Sopenharmony_ci}
1438141cc406Sopenharmony_ci
1439141cc406Sopenharmony_ci
1440141cc406Sopenharmony_ci/* these functions are interfaces only */
1441141cc406Sopenharmony_cistatic void
1442141cc406Sopenharmony_ciconfig_ccd (Mustek_pp_Handle * dev)
1443141cc406Sopenharmony_ci{
1444141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1445141cc406Sopenharmony_ci
1446141cc406Sopenharmony_ci  DBG (5, "config_ccd: %d dpi, mode %d, invert %d, size %d\n",
1447141cc406Sopenharmony_ci       priv->hwres, dev->mode, dev->invert, dev->params.pixels_per_line);
1448141cc406Sopenharmony_ci
1449141cc406Sopenharmony_ci  switch (priv->asic)
1450141cc406Sopenharmony_ci    {
1451141cc406Sopenharmony_ci    case CCD300_ASIC1013:
1452141cc406Sopenharmony_ci      config_ccd_1013 (dev);
1453141cc406Sopenharmony_ci      break;
1454141cc406Sopenharmony_ci
1455141cc406Sopenharmony_ci    case CCD300_ASIC1015:
1456141cc406Sopenharmony_ci      config_ccd_1015 (dev);
1457141cc406Sopenharmony_ci      break;
1458141cc406Sopenharmony_ci    }
1459141cc406Sopenharmony_ci
1460141cc406Sopenharmony_ci}
1461141cc406Sopenharmony_ci
1462141cc406Sopenharmony_cistatic void
1463141cc406Sopenharmony_cireturn_home (Mustek_pp_Handle * dev, SANE_Bool nowait)
1464141cc406Sopenharmony_ci{
1465141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1466141cc406Sopenharmony_ci
1467141cc406Sopenharmony_ci  priv->saved_mode = dev->mode;
1468141cc406Sopenharmony_ci  priv->saved_invert = dev->invert;
1469141cc406Sopenharmony_ci  priv->saved_skipcount = priv->skipcount;
1470141cc406Sopenharmony_ci  priv->saved_skipimagebyte = priv->skipimagebytes;
1471141cc406Sopenharmony_ci  priv->saved_adjustskip = priv->adjustskip;
1472141cc406Sopenharmony_ci  priv->saved_res = dev->res;
1473141cc406Sopenharmony_ci  priv->saved_hwres = priv->hwres;
1474141cc406Sopenharmony_ci  priv->saved_res_step = priv->res_step;
1475141cc406Sopenharmony_ci  priv->saved_line_step = priv->line_step;
1476141cc406Sopenharmony_ci  priv->saved_channel = priv->channel;
1477141cc406Sopenharmony_ci
1478141cc406Sopenharmony_ci
1479141cc406Sopenharmony_ci  priv->hwres = dev->res = 100;
1480141cc406Sopenharmony_ci  dev->mode = MODE_GRAYSCALE;
1481141cc406Sopenharmony_ci
1482141cc406Sopenharmony_ci  priv->skipcount = priv->skipimagebytes = 0;
1483141cc406Sopenharmony_ci
1484141cc406Sopenharmony_ci  config_ccd (dev);
1485141cc406Sopenharmony_ci
1486141cc406Sopenharmony_ci  switch (priv->asic)
1487141cc406Sopenharmony_ci    {
1488141cc406Sopenharmony_ci    case CCD300_ASIC1013:
1489141cc406Sopenharmony_ci      return_home_1013 (dev);
1490141cc406Sopenharmony_ci      break;
1491141cc406Sopenharmony_ci
1492141cc406Sopenharmony_ci    case CCD300_ASIC1015:
1493141cc406Sopenharmony_ci      return_home_1015 (dev, nowait);
1494141cc406Sopenharmony_ci      break;
1495141cc406Sopenharmony_ci    }
1496141cc406Sopenharmony_ci
1497141cc406Sopenharmony_ci
1498141cc406Sopenharmony_ci  dev->mode = priv->saved_mode;
1499141cc406Sopenharmony_ci  dev->invert = priv->saved_invert;
1500141cc406Sopenharmony_ci  priv->skipcount = priv->saved_skipcount;
1501141cc406Sopenharmony_ci  priv->skipimagebytes = priv->saved_skipimagebyte;
1502141cc406Sopenharmony_ci  priv->adjustskip = priv->saved_adjustskip;
1503141cc406Sopenharmony_ci  dev->res = priv->saved_res;
1504141cc406Sopenharmony_ci  priv->hwres = priv->saved_hwres;
1505141cc406Sopenharmony_ci  priv->res_step = priv->saved_res_step;
1506141cc406Sopenharmony_ci  priv->line_step = priv->saved_line_step;
1507141cc406Sopenharmony_ci  priv->channel = priv->saved_channel;
1508141cc406Sopenharmony_ci  priv->motor_step = 0;
1509141cc406Sopenharmony_ci
1510141cc406Sopenharmony_ci  config_ccd (dev);
1511141cc406Sopenharmony_ci}
1512141cc406Sopenharmony_ci
1513141cc406Sopenharmony_cistatic void
1514141cc406Sopenharmony_cilamp (Mustek_pp_Handle * dev, int lamp_on)
1515141cc406Sopenharmony_ci{
1516141cc406Sopenharmony_ci
1517141cc406Sopenharmony_ci  set_lamp (dev, lamp_on);
1518141cc406Sopenharmony_ci
1519141cc406Sopenharmony_ci}
1520141cc406Sopenharmony_ci
1521141cc406Sopenharmony_cistatic void
1522141cc406Sopenharmony_ciset_voltages (Mustek_pp_Handle * dev)
1523141cc406Sopenharmony_ci{
1524141cc406Sopenharmony_ci  send_voltages (dev);
1525141cc406Sopenharmony_ci}
1526141cc406Sopenharmony_ci
1527141cc406Sopenharmony_cistatic void
1528141cc406Sopenharmony_cimove_motor (Mustek_pp_Handle * dev, int count, int forward)
1529141cc406Sopenharmony_ci{
1530141cc406Sopenharmony_ci
1531141cc406Sopenharmony_ci  int ctr;
1532141cc406Sopenharmony_ci
1533141cc406Sopenharmony_ci  DBG (5, "move_motor: %u steps (%s)\n", count,
1534141cc406Sopenharmony_ci       (forward == SANE_TRUE ? "forward" : "backward"));
1535141cc406Sopenharmony_ci
1536141cc406Sopenharmony_ci
1537141cc406Sopenharmony_ci  for (ctr = 0; ctr < count; ctr++)
1538141cc406Sopenharmony_ci    {
1539141cc406Sopenharmony_ci
1540141cc406Sopenharmony_ci      move_motor_101x (dev, forward);
1541141cc406Sopenharmony_ci
1542141cc406Sopenharmony_ci    }
1543141cc406Sopenharmony_ci
1544141cc406Sopenharmony_ci
1545141cc406Sopenharmony_ci}
1546141cc406Sopenharmony_ci
1547141cc406Sopenharmony_cistatic void
1548141cc406Sopenharmony_cicalibrate (Mustek_pp_Handle * dev)
1549141cc406Sopenharmony_ci{
1550141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1551141cc406Sopenharmony_ci
1552141cc406Sopenharmony_ci  DBG (5, "calibrate entered (asic = 0x%02x)\n", priv->asic);
1553141cc406Sopenharmony_ci
1554141cc406Sopenharmony_ci  calibrate_device_101x (dev);
1555141cc406Sopenharmony_ci
1556141cc406Sopenharmony_ci  DBG (5, "calibrate: ref_black %d, blackpos %d\n",
1557141cc406Sopenharmony_ci       priv->ref_black, priv->blackpos);
1558141cc406Sopenharmony_ci
1559141cc406Sopenharmony_ci}
1560141cc406Sopenharmony_ci
1561141cc406Sopenharmony_ci
1562141cc406Sopenharmony_cistatic void
1563141cc406Sopenharmony_ciget_lineart_line (Mustek_pp_Handle * dev, SANE_Byte * buf)
1564141cc406Sopenharmony_ci{
1565141cc406Sopenharmony_ci  get_lineart_line_101x (dev, buf);
1566141cc406Sopenharmony_ci}
1567141cc406Sopenharmony_ci
1568141cc406Sopenharmony_cistatic void
1569141cc406Sopenharmony_ciget_grayscale_line (Mustek_pp_Handle * dev, SANE_Byte * buf)
1570141cc406Sopenharmony_ci{
1571141cc406Sopenharmony_ci
1572141cc406Sopenharmony_ci  get_grayscale_line_101x (dev, buf);
1573141cc406Sopenharmony_ci}
1574141cc406Sopenharmony_ci
1575141cc406Sopenharmony_cistatic void
1576141cc406Sopenharmony_ciget_color_line (Mustek_pp_Handle * dev, SANE_Byte * buf)
1577141cc406Sopenharmony_ci{
1578141cc406Sopenharmony_ci
1579141cc406Sopenharmony_ci  get_color_line_101x (dev, buf);
1580141cc406Sopenharmony_ci
1581141cc406Sopenharmony_ci}
1582141cc406Sopenharmony_ci
1583141cc406Sopenharmony_ci
1584141cc406Sopenharmony_cistatic SANE_Status
1585141cc406Sopenharmony_ciccd300_init (SANE_Int options, SANE_String_Const port,
1586141cc406Sopenharmony_ci	     SANE_String_Const name, SANE_Attach_Callback attach)
1587141cc406Sopenharmony_ci{
1588141cc406Sopenharmony_ci  SANE_Status status;
1589141cc406Sopenharmony_ci  unsigned char asic, ccd;
1590141cc406Sopenharmony_ci  int fd;
1591141cc406Sopenharmony_ci
1592141cc406Sopenharmony_ci  if (options != CAP_NOTHING)
1593141cc406Sopenharmony_ci    {
1594141cc406Sopenharmony_ci      DBG (1, "ccd300_init: called with unknown options (%#02x)\n", options);
1595141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1596141cc406Sopenharmony_ci    }
1597141cc406Sopenharmony_ci
1598141cc406Sopenharmony_ci  /* try to attach to he supplied port */
1599141cc406Sopenharmony_ci  status = sanei_pa4s2_open (port, &fd);
1600141cc406Sopenharmony_ci
1601141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1602141cc406Sopenharmony_ci    {
1603141cc406Sopenharmony_ci      DBG (2, "ccd300_init: couldn't attach to port ``%s'' (%s)\n",
1604141cc406Sopenharmony_ci	   port, sane_strstatus (status));
1605141cc406Sopenharmony_ci      return status;
1606141cc406Sopenharmony_ci    }
1607141cc406Sopenharmony_ci
1608141cc406Sopenharmony_ci  sanei_pa4s2_enable (fd, SANE_TRUE);
1609141cc406Sopenharmony_ci  sanei_pa4s2_readbegin (fd, 0);
1610141cc406Sopenharmony_ci  sanei_pa4s2_readbyte (fd, &asic);
1611141cc406Sopenharmony_ci  sanei_pa4s2_readend (fd);
1612141cc406Sopenharmony_ci  sanei_pa4s2_readbegin (fd, 2);
1613141cc406Sopenharmony_ci  sanei_pa4s2_readbyte (fd, &ccd);
1614141cc406Sopenharmony_ci  sanei_pa4s2_readend (fd);
1615141cc406Sopenharmony_ci  sanei_pa4s2_enable (fd, SANE_FALSE);
1616141cc406Sopenharmony_ci  sanei_pa4s2_close (fd);
1617141cc406Sopenharmony_ci
1618141cc406Sopenharmony_ci  if (asic != CCD300_ASIC1013 && asic != CCD300_ASIC1015)
1619141cc406Sopenharmony_ci    {
1620141cc406Sopenharmony_ci      DBG (2, "ccd300_init: scanner not recognized (unknown ASIC id %#02x)\n",
1621141cc406Sopenharmony_ci	   asic);
1622141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1623141cc406Sopenharmony_ci    }
1624141cc406Sopenharmony_ci
1625141cc406Sopenharmony_ci  ccd &= (asic == CCD300_ASIC1013 ? 0x04 : 0x05);
1626141cc406Sopenharmony_ci
1627141cc406Sopenharmony_ci  DBG (3, "ccd_init: found scanner on port ``%s'' (ASIC id %#02x, CCD %d)\n",
1628141cc406Sopenharmony_ci       port, asic, ccd);
1629141cc406Sopenharmony_ci
1630141cc406Sopenharmony_ci  return attach (port, name, MUSTEK_PP_CCD300, options);
1631141cc406Sopenharmony_ci
1632141cc406Sopenharmony_ci}
1633141cc406Sopenharmony_ci
1634141cc406Sopenharmony_cistatic void
1635141cc406Sopenharmony_ciccd300_capabilities (SANE_Int info, SANE_String * model,
1636141cc406Sopenharmony_ci		     SANE_String * vendor, SANE_String * type,
1637141cc406Sopenharmony_ci		     SANE_Int * maxres, SANE_Int * minres,
1638141cc406Sopenharmony_ci		     SANE_Int * maxhsize, SANE_Int * maxvsize,
1639141cc406Sopenharmony_ci		     SANE_Int * caps)
1640141cc406Sopenharmony_ci{
1641141cc406Sopenharmony_ci  *model = strdup ("600 III EP Plus");
1642141cc406Sopenharmony_ci  *vendor = strdup ("Mustek");
1643141cc406Sopenharmony_ci  *type = strdup ("flatbed (CCD 300 dpi)");
1644141cc406Sopenharmony_ci  DBG (3,
1645141cc406Sopenharmony_ci       "ccd300_capabilities: 600 III EP Plus flatbed CCD (300 dpi) scanner\n");
1646141cc406Sopenharmony_ci
1647141cc406Sopenharmony_ci  *maxres = 300;
1648141cc406Sopenharmony_ci  *minres = 50;
1649141cc406Sopenharmony_ci  *maxhsize = CCD300_MAXHSIZE;
1650141cc406Sopenharmony_ci  *maxvsize = CCD300_MAXVSIZE;
1651141cc406Sopenharmony_ci  *caps = info | CAP_INVERT | CAP_LAMP_OFF;
1652141cc406Sopenharmony_ci}
1653141cc406Sopenharmony_ci
1654141cc406Sopenharmony_cistatic SANE_Status
1655141cc406Sopenharmony_ciccd300_open (SANE_String port, SANE_Int caps, SANE_Int * fd)
1656141cc406Sopenharmony_ci{
1657141cc406Sopenharmony_ci  SANE_Status status;
1658141cc406Sopenharmony_ci
1659141cc406Sopenharmony_ci  if (caps & ~(CAP_NOTHING | CAP_INVERT | CAP_LAMP_OFF))
1660141cc406Sopenharmony_ci    {
1661141cc406Sopenharmony_ci      DBG (1, "ccd300_open: called with unknown capabilities (%#02x)\n",
1662141cc406Sopenharmony_ci	   caps);
1663141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1664141cc406Sopenharmony_ci    }
1665141cc406Sopenharmony_ci
1666141cc406Sopenharmony_ci  DBG (3, "ccd300_open: called for port ``%s''\n", port);
1667141cc406Sopenharmony_ci
1668141cc406Sopenharmony_ci  status = sanei_pa4s2_open (port, fd);
1669141cc406Sopenharmony_ci
1670141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1671141cc406Sopenharmony_ci    DBG (2, "ccd300_open: open failed (%s)\n", sane_strstatus (status));
1672141cc406Sopenharmony_ci
1673141cc406Sopenharmony_ci  return status;
1674141cc406Sopenharmony_ci}
1675141cc406Sopenharmony_ci
1676141cc406Sopenharmony_cistatic void
1677141cc406Sopenharmony_ciccd300_setup (SANE_Handle handle)
1678141cc406Sopenharmony_ci{
1679141cc406Sopenharmony_ci  Mustek_pp_Handle *dev = handle;
1680141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv;
1681141cc406Sopenharmony_ci  unsigned char asic, ccd;
1682141cc406Sopenharmony_ci
1683141cc406Sopenharmony_ci  DBG (3, "ccd300_setup: called for port ``%s''\n", dev->dev->port);
1684141cc406Sopenharmony_ci
1685141cc406Sopenharmony_ci  if ((priv = malloc (sizeof (mustek_pp_ccd300_priv))) == NULL)
1686141cc406Sopenharmony_ci    {
1687141cc406Sopenharmony_ci      DBG (1, "ccd300_setup: not enough memory\n");
1688141cc406Sopenharmony_ci      return;			/* can you here the shit hitting the fan? */
1689141cc406Sopenharmony_ci    }
1690141cc406Sopenharmony_ci
1691141cc406Sopenharmony_ci  dev->priv = priv;
1692141cc406Sopenharmony_ci  memset (priv, 0, sizeof (mustek_pp_ccd300_priv));
1693141cc406Sopenharmony_ci
1694141cc406Sopenharmony_ci  priv->bw = 128;
1695141cc406Sopenharmony_ci  priv->wait_bank = 700;
1696141cc406Sopenharmony_ci  priv->top = 47;
1697141cc406Sopenharmony_ci
1698141cc406Sopenharmony_ci  sanei_pa4s2_enable (dev->fd, SANE_TRUE);
1699141cc406Sopenharmony_ci
1700141cc406Sopenharmony_ci  sanei_pa4s2_readbegin (dev->fd, 0);
1701141cc406Sopenharmony_ci  sanei_pa4s2_readbyte (dev->fd, &asic);
1702141cc406Sopenharmony_ci  sanei_pa4s2_readend (dev->fd);
1703141cc406Sopenharmony_ci  sanei_pa4s2_readbegin (dev->fd, 2);
1704141cc406Sopenharmony_ci  sanei_pa4s2_readbyte (dev->fd, &ccd);
1705141cc406Sopenharmony_ci  sanei_pa4s2_readend (dev->fd);
1706141cc406Sopenharmony_ci  ccd &= (asic == CCD300_ASIC1013 ? 0x04 : 0x05);
1707141cc406Sopenharmony_ci  priv->asic = asic;
1708141cc406Sopenharmony_ci  priv->ccd_type = ccd;
1709141cc406Sopenharmony_ci
1710141cc406Sopenharmony_ci  return_home (dev, SANE_TRUE);
1711141cc406Sopenharmony_ci  lamp (dev, SANE_TRUE);
1712141cc406Sopenharmony_ci  sanei_pa4s2_enable (dev->fd, SANE_FALSE);
1713141cc406Sopenharmony_ci  dev->lamp_on = time (NULL);
1714141cc406Sopenharmony_ci  dev->res = priv->hwres = 300;
1715141cc406Sopenharmony_ci  dev->mode = MODE_COLOR;
1716141cc406Sopenharmony_ci}
1717141cc406Sopenharmony_ci
1718141cc406Sopenharmony_cistatic void
1719141cc406Sopenharmony_ciccd300_close (SANE_Handle handle)
1720141cc406Sopenharmony_ci{
1721141cc406Sopenharmony_ci
1722141cc406Sopenharmony_ci  Mustek_pp_Handle *dev = handle;
1723141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1724141cc406Sopenharmony_ci
1725141cc406Sopenharmony_ci  DBG (3, "ccd300_close: called for port ``%s''\n", dev->dev->port);
1726141cc406Sopenharmony_ci
1727141cc406Sopenharmony_ci  sanei_pa4s2_enable (dev->fd, SANE_TRUE);
1728141cc406Sopenharmony_ci  lamp (dev, SANE_FALSE);
1729141cc406Sopenharmony_ci  return_home (dev, SANE_FALSE);
1730141cc406Sopenharmony_ci  sanei_pa4s2_enable (dev->fd, SANE_FALSE);
1731141cc406Sopenharmony_ci
1732141cc406Sopenharmony_ci  sanei_pa4s2_close (dev->fd);
1733141cc406Sopenharmony_ci  free (priv);
1734141cc406Sopenharmony_ci
1735141cc406Sopenharmony_ci  DBG (3, "ccd300_close: device shut down and all buffers freed\n");
1736141cc406Sopenharmony_ci}
1737141cc406Sopenharmony_ci
1738141cc406Sopenharmony_cistatic SANE_Status
1739141cc406Sopenharmony_ciccd300_config (SANE_Handle handle, SANE_String_Const optname,
1740141cc406Sopenharmony_ci	       SANE_String_Const optval)
1741141cc406Sopenharmony_ci{
1742141cc406Sopenharmony_ci  Mustek_pp_Handle *dev = handle;
1743141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1744141cc406Sopenharmony_ci  int value = -1;
1745141cc406Sopenharmony_ci
1746141cc406Sopenharmony_ci  DBG (3, "ccd300_config: called for port ``%s'' (%s%s%s)\n",
1747141cc406Sopenharmony_ci       dev->dev->port,
1748141cc406Sopenharmony_ci       optname, (optval ? " = " : ""), (optval ? optval : ""));
1749141cc406Sopenharmony_ci
1750141cc406Sopenharmony_ci  if (!strcmp (optname, "bw"))
1751141cc406Sopenharmony_ci    {
1752141cc406Sopenharmony_ci
1753141cc406Sopenharmony_ci      if (!optval)
1754141cc406Sopenharmony_ci	{
1755141cc406Sopenharmony_ci	  DBG (1, "ccd300_config: missing value for option ``bw''\n");
1756141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1757141cc406Sopenharmony_ci	}
1758141cc406Sopenharmony_ci
1759141cc406Sopenharmony_ci      /* ok, ok, should be strtol... know what? send me a patch. */
1760141cc406Sopenharmony_ci      value = atoi (optval);
1761141cc406Sopenharmony_ci
1762141cc406Sopenharmony_ci      if ((value < 0) || (value > 255))
1763141cc406Sopenharmony_ci	{
1764141cc406Sopenharmony_ci	  DBG (1,
1765141cc406Sopenharmony_ci	       "ccd300_config: value ``%s'' for option ``bw'' is out of range (0 <= bw <= 255)\n",
1766141cc406Sopenharmony_ci	       optval);
1767141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1768141cc406Sopenharmony_ci	}
1769141cc406Sopenharmony_ci
1770141cc406Sopenharmony_ci      priv->bw = value;
1771141cc406Sopenharmony_ci
1772141cc406Sopenharmony_ci    }
1773141cc406Sopenharmony_ci  else if (!strcmp (optname, "waitbank"))
1774141cc406Sopenharmony_ci    {
1775141cc406Sopenharmony_ci
1776141cc406Sopenharmony_ci      if (!optval)
1777141cc406Sopenharmony_ci	{
1778141cc406Sopenharmony_ci	  DBG (1, "ccd300_config: missing value for option ``waitbank''\n");
1779141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1780141cc406Sopenharmony_ci	}
1781141cc406Sopenharmony_ci
1782141cc406Sopenharmony_ci      value = atoi (optval);
1783141cc406Sopenharmony_ci
1784141cc406Sopenharmony_ci      if (value < 0)
1785141cc406Sopenharmony_ci	{
1786141cc406Sopenharmony_ci	  DBG (1,
1787141cc406Sopenharmony_ci	       "ccd300_config: value ``%s'' for option ``waitbank'' is out of range (>= 0)\n",
1788141cc406Sopenharmony_ci	       optval);
1789141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1790141cc406Sopenharmony_ci	}
1791141cc406Sopenharmony_ci
1792141cc406Sopenharmony_ci      priv->wait_bank = value;
1793141cc406Sopenharmony_ci    }
1794141cc406Sopenharmony_ci  else if (!strcmp (optname, "top"))
1795141cc406Sopenharmony_ci    {
1796141cc406Sopenharmony_ci
1797141cc406Sopenharmony_ci      if (!optval)
1798141cc406Sopenharmony_ci	{
1799141cc406Sopenharmony_ci	  DBG (1, "ccd300_config: missing value for option ``top''\n");
1800141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1801141cc406Sopenharmony_ci	}
1802141cc406Sopenharmony_ci
1803141cc406Sopenharmony_ci      value = atoi (optval);
1804141cc406Sopenharmony_ci
1805141cc406Sopenharmony_ci      if (value < 0)
1806141cc406Sopenharmony_ci	{
1807141cc406Sopenharmony_ci	  DBG (1,
1808141cc406Sopenharmony_ci	       "ccd300_config: value ``%s'' for option ``top'' is out of range (>= 0)\n",
1809141cc406Sopenharmony_ci	       optval);
1810141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1811141cc406Sopenharmony_ci	}
1812141cc406Sopenharmony_ci
1813141cc406Sopenharmony_ci      priv->top = value;
1814141cc406Sopenharmony_ci    }
1815141cc406Sopenharmony_ci  else
1816141cc406Sopenharmony_ci    {
1817141cc406Sopenharmony_ci      DBG (1, "ccd300_config: unknown option ``%s''", optname);
1818141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1819141cc406Sopenharmony_ci    }
1820141cc406Sopenharmony_ci
1821141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1822141cc406Sopenharmony_ci
1823141cc406Sopenharmony_ci}
1824141cc406Sopenharmony_ci
1825141cc406Sopenharmony_cistatic void
1826141cc406Sopenharmony_ciccd300_stop (SANE_Handle handle)
1827141cc406Sopenharmony_ci{
1828141cc406Sopenharmony_ci  Mustek_pp_Handle *dev = handle;
1829141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1830141cc406Sopenharmony_ci  int cnt;
1831141cc406Sopenharmony_ci
1832141cc406Sopenharmony_ci  DBG (3, "ccd300_stop: stopping scan operating on port ``%s''\n",
1833141cc406Sopenharmony_ci       dev->dev->port);
1834141cc406Sopenharmony_ci
1835141cc406Sopenharmony_ci  sanei_pa4s2_enable (dev->fd, SANE_TRUE);
1836141cc406Sopenharmony_ci  return_home (dev, SANE_TRUE);
1837141cc406Sopenharmony_ci  sanei_pa4s2_enable (dev->fd, SANE_FALSE);
1838141cc406Sopenharmony_ci
1839141cc406Sopenharmony_ci  free (priv->calib_r);
1840141cc406Sopenharmony_ci  free (priv->calib_g);
1841141cc406Sopenharmony_ci  free (priv->calib_b);
1842141cc406Sopenharmony_ci
1843141cc406Sopenharmony_ci  if (priv->red)
1844141cc406Sopenharmony_ci    {
1845141cc406Sopenharmony_ci      for (cnt = 0; cnt < priv->green_offs; cnt++)
1846141cc406Sopenharmony_ci	free (priv->red[cnt]);
1847141cc406Sopenharmony_ci      free (priv->red);
1848141cc406Sopenharmony_ci    }
1849141cc406Sopenharmony_ci  if (priv->blue)
1850141cc406Sopenharmony_ci    {
1851141cc406Sopenharmony_ci      for (cnt = 0; cnt < priv->blue_offs; cnt++)
1852141cc406Sopenharmony_ci	free (priv->blue[cnt]);
1853141cc406Sopenharmony_ci      free (priv->blue);
1854141cc406Sopenharmony_ci    }
1855141cc406Sopenharmony_ci  free (priv->green);
1856141cc406Sopenharmony_ci
1857141cc406Sopenharmony_ci  priv->calib_r = priv->calib_g = priv->calib_b = NULL;
1858141cc406Sopenharmony_ci  priv->red = priv->blue = NULL;
1859141cc406Sopenharmony_ci  priv->green = NULL;
1860141cc406Sopenharmony_ci
1861141cc406Sopenharmony_ci}
1862141cc406Sopenharmony_ci
1863141cc406Sopenharmony_cistatic SANE_Status
1864141cc406Sopenharmony_ciccd300_start (SANE_Handle handle)
1865141cc406Sopenharmony_ci{
1866141cc406Sopenharmony_ci  Mustek_pp_Handle *dev = handle;
1867141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
1868141cc406Sopenharmony_ci
1869141cc406Sopenharmony_ci  DBG (3, "ccd300_start: called for port ``%s''\n", dev->dev->port);
1870141cc406Sopenharmony_ci
1871141cc406Sopenharmony_ci  if (dev->res <= 100)
1872141cc406Sopenharmony_ci    priv->hwres = 100;
1873141cc406Sopenharmony_ci  else if (dev->res <= 200)
1874141cc406Sopenharmony_ci    priv->hwres = 200;
1875141cc406Sopenharmony_ci  else if (dev->res <= 300)
1876141cc406Sopenharmony_ci    priv->hwres = 300;
1877141cc406Sopenharmony_ci
1878141cc406Sopenharmony_ci  DBG (4, "ccd300_start: setting hardware resolution to %d dpi\n",
1879141cc406Sopenharmony_ci       priv->hwres);
1880141cc406Sopenharmony_ci
1881141cc406Sopenharmony_ci  priv->skipimagebytes = dev->topX;
1882141cc406Sopenharmony_ci
1883141cc406Sopenharmony_ci  sanei_pa4s2_enable (dev->fd, SANE_TRUE);
1884141cc406Sopenharmony_ci  config_ccd (dev);
1885141cc406Sopenharmony_ci  set_voltages (dev);
1886141cc406Sopenharmony_ci  get_bank_count (dev);
1887141cc406Sopenharmony_ci
1888141cc406Sopenharmony_ci  if (priv->bank_count != 0)
1889141cc406Sopenharmony_ci    {
1890141cc406Sopenharmony_ci      DBG (2, "ccd300_start: bank count is not zero...\n");
1891141cc406Sopenharmony_ci    }
1892141cc406Sopenharmony_ci
1893141cc406Sopenharmony_ci  return_home (dev, SANE_FALSE);
1894141cc406Sopenharmony_ci
1895141cc406Sopenharmony_ci  priv->motor_step = 0;
1896141cc406Sopenharmony_ci
1897141cc406Sopenharmony_ci  /* allocate memory for calibration */
1898141cc406Sopenharmony_ci  if ((priv->calib_g = malloc (dev->params.pixels_per_line)) == NULL)
1899141cc406Sopenharmony_ci    {
1900141cc406Sopenharmony_ci      sanei_pa4s2_enable (dev->fd, SANE_FALSE);
1901141cc406Sopenharmony_ci      DBG (1, "ccd300_start: not enough memory\n");
1902141cc406Sopenharmony_ci      return SANE_STATUS_NO_MEM;
1903141cc406Sopenharmony_ci    }
1904141cc406Sopenharmony_ci
1905141cc406Sopenharmony_ci  if (dev->mode == MODE_COLOR)
1906141cc406Sopenharmony_ci    {
1907141cc406Sopenharmony_ci      priv->calib_r = malloc (dev->params.pixels_per_line);
1908141cc406Sopenharmony_ci      priv->calib_b = malloc (dev->params.pixels_per_line);
1909141cc406Sopenharmony_ci
1910141cc406Sopenharmony_ci      if ((priv->calib_r == NULL) || (priv->calib_b == NULL))
1911141cc406Sopenharmony_ci	{
1912141cc406Sopenharmony_ci	  free (priv->calib_g);
1913141cc406Sopenharmony_ci	  free (priv->calib_r);
1914141cc406Sopenharmony_ci	  free (priv->calib_b);
1915141cc406Sopenharmony_ci	  priv->calib_r = priv->calib_g = priv->calib_b = NULL;
1916141cc406Sopenharmony_ci
1917141cc406Sopenharmony_ci	  sanei_pa4s2_enable (dev->fd, SANE_FALSE);
1918141cc406Sopenharmony_ci	  DBG (1, "ccd300_start: not enough memory\n");
1919141cc406Sopenharmony_ci	  return SANE_STATUS_NO_MEM;
1920141cc406Sopenharmony_ci	}
1921141cc406Sopenharmony_ci    }
1922141cc406Sopenharmony_ci
1923141cc406Sopenharmony_ci  calibrate (dev);
1924141cc406Sopenharmony_ci
1925141cc406Sopenharmony_ci  if (priv->ccd_type == 1)
1926141cc406Sopenharmony_ci    {
1927141cc406Sopenharmony_ci      priv->blue_offs = 4;
1928141cc406Sopenharmony_ci      priv->green_offs = 8;
1929141cc406Sopenharmony_ci    }
1930141cc406Sopenharmony_ci  else
1931141cc406Sopenharmony_ci    {
1932141cc406Sopenharmony_ci      priv->blue_offs = 8;
1933141cc406Sopenharmony_ci      priv->green_offs = 16;
1934141cc406Sopenharmony_ci    }
1935141cc406Sopenharmony_ci
1936141cc406Sopenharmony_ci  move_motor (dev, priv->top + dev->topY -
1937141cc406Sopenharmony_ci	      (dev->mode == MODE_COLOR ? priv->green_offs : 0), SANE_TRUE);
1938141cc406Sopenharmony_ci
1939141cc406Sopenharmony_ci  if (priv->ccd_type == 1)
1940141cc406Sopenharmony_ci    sanei_pa4s2_writebyte (dev->fd, 6, 0x15);
1941141cc406Sopenharmony_ci
1942141cc406Sopenharmony_ci  sanei_pa4s2_enable (dev->fd, SANE_FALSE);
1943141cc406Sopenharmony_ci
1944141cc406Sopenharmony_ci  if (dev->mode == MODE_COLOR)
1945141cc406Sopenharmony_ci    {
1946141cc406Sopenharmony_ci      int failed = SANE_FALSE, cnt;
1947141cc406Sopenharmony_ci
1948141cc406Sopenharmony_ci      priv->line_step = SANE_FIX (300.0 / (float) dev->res);
1949141cc406Sopenharmony_ci      priv->rdiff = priv->line_step;
1950141cc406Sopenharmony_ci      priv->bdiff = priv->rdiff + (priv->blue_offs << SANE_FIXED_SCALE_SHIFT);
1951141cc406Sopenharmony_ci      priv->gdiff =
1952141cc406Sopenharmony_ci	priv->rdiff + (priv->green_offs << SANE_FIXED_SCALE_SHIFT);
1953141cc406Sopenharmony_ci
1954141cc406Sopenharmony_ci      priv->red = malloc (sizeof (SANE_Byte *) * priv->green_offs);
1955141cc406Sopenharmony_ci      priv->blue = malloc (sizeof (SANE_Byte *) * priv->blue_offs);
1956141cc406Sopenharmony_ci      priv->green = malloc (dev->params.pixels_per_line);
1957141cc406Sopenharmony_ci
1958141cc406Sopenharmony_ci      if ((priv->red == NULL) || (priv->blue == NULL)
1959141cc406Sopenharmony_ci	  || (priv->green == NULL))
1960141cc406Sopenharmony_ci	{
1961141cc406Sopenharmony_ci	  free (priv->calib_r);
1962141cc406Sopenharmony_ci	  free (priv->calib_g);
1963141cc406Sopenharmony_ci	  free (priv->calib_b);
1964141cc406Sopenharmony_ci	  priv->calib_r = priv->calib_g = priv->calib_b = NULL;
1965141cc406Sopenharmony_ci
1966141cc406Sopenharmony_ci	  free (priv->red);
1967141cc406Sopenharmony_ci	  free (priv->green);
1968141cc406Sopenharmony_ci	  free (priv->blue);
1969141cc406Sopenharmony_ci	  priv->red = priv->blue = NULL;
1970141cc406Sopenharmony_ci	  priv->green = NULL;
1971141cc406Sopenharmony_ci
1972141cc406Sopenharmony_ci	  DBG (1, "ccd300_start: not enough memory for ld buffers\n");
1973141cc406Sopenharmony_ci	  return SANE_STATUS_NO_MEM;
1974141cc406Sopenharmony_ci	}
1975141cc406Sopenharmony_ci
1976141cc406Sopenharmony_ci      /* note to myself: better allocate one huge chunk of memory and set
1977141cc406Sopenharmony_ci         pointers */
1978141cc406Sopenharmony_ci      for (cnt = 0; cnt < priv->green_offs; cnt++)
1979141cc406Sopenharmony_ci	if ((priv->red[cnt] = malloc (dev->params.pixels_per_line)) == NULL)
1980141cc406Sopenharmony_ci	  failed = SANE_TRUE;
1981141cc406Sopenharmony_ci
1982141cc406Sopenharmony_ci      for (cnt = 0; cnt < priv->blue_offs; cnt++)
1983141cc406Sopenharmony_ci	if ((priv->blue[cnt] = malloc (dev->params.pixels_per_line)) == NULL)
1984141cc406Sopenharmony_ci	  failed = SANE_TRUE;
1985141cc406Sopenharmony_ci
1986141cc406Sopenharmony_ci      if (failed == SANE_TRUE)
1987141cc406Sopenharmony_ci	{
1988141cc406Sopenharmony_ci	  free (priv->calib_r);
1989141cc406Sopenharmony_ci	  free (priv->calib_g);
1990141cc406Sopenharmony_ci	  free (priv->calib_b);
1991141cc406Sopenharmony_ci	  priv->calib_r = priv->calib_g = priv->calib_b = NULL;
1992141cc406Sopenharmony_ci
1993141cc406Sopenharmony_ci	  for (cnt = 0; cnt < priv->green_offs; cnt++)
1994141cc406Sopenharmony_ci	    free (priv->red[cnt]);
1995141cc406Sopenharmony_ci	  for (cnt = 0; cnt < priv->blue_offs; cnt++)
1996141cc406Sopenharmony_ci	    free (priv->blue[cnt]);
1997141cc406Sopenharmony_ci
1998141cc406Sopenharmony_ci	  free (priv->red);
1999141cc406Sopenharmony_ci	  free (priv->green);
2000141cc406Sopenharmony_ci	  free (priv->blue);
2001141cc406Sopenharmony_ci	  priv->red = priv->blue = NULL;
2002141cc406Sopenharmony_ci	  priv->green = NULL;
2003141cc406Sopenharmony_ci
2004141cc406Sopenharmony_ci	  DBG (1, "ccd300_start: not enough memory for ld buffers\n");
2005141cc406Sopenharmony_ci	  return SANE_STATUS_NO_MEM;
2006141cc406Sopenharmony_ci	}
2007141cc406Sopenharmony_ci
2008141cc406Sopenharmony_ci      priv->redline = priv->blueline = priv->ccd_line = 0;
2009141cc406Sopenharmony_ci    }
2010141cc406Sopenharmony_ci
2011141cc406Sopenharmony_ci  priv->lines = 0;
2012141cc406Sopenharmony_ci  priv->lines_left = dev->params.lines;
2013141cc406Sopenharmony_ci
2014141cc406Sopenharmony_ci  DBG (3, "ccd300_start: device ready for scanning\n");
2015141cc406Sopenharmony_ci
2016141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2017141cc406Sopenharmony_ci}
2018141cc406Sopenharmony_ci
2019141cc406Sopenharmony_cistatic void
2020141cc406Sopenharmony_ciccd300_read (SANE_Handle handle, SANE_Byte * buffer)
2021141cc406Sopenharmony_ci{
2022141cc406Sopenharmony_ci  Mustek_pp_Handle *dev = handle;
2023141cc406Sopenharmony_ci  mustek_pp_ccd300_priv *priv = dev->priv;
2024141cc406Sopenharmony_ci
2025141cc406Sopenharmony_ci  DBG (3, "ccd300_read: receiving one line from port ``%s''\n",
2026141cc406Sopenharmony_ci       dev->dev->port);
2027141cc406Sopenharmony_ci
2028141cc406Sopenharmony_ci  sanei_pa4s2_enable (dev->fd, SANE_TRUE);
2029141cc406Sopenharmony_ci
2030141cc406Sopenharmony_ci  switch (dev->mode)
2031141cc406Sopenharmony_ci    {
2032141cc406Sopenharmony_ci    case MODE_BW:
2033141cc406Sopenharmony_ci      get_lineart_line (dev, buffer);
2034141cc406Sopenharmony_ci      break;
2035141cc406Sopenharmony_ci
2036141cc406Sopenharmony_ci    case MODE_GRAYSCALE:
2037141cc406Sopenharmony_ci      get_grayscale_line (dev, buffer);
2038141cc406Sopenharmony_ci      break;
2039141cc406Sopenharmony_ci
2040141cc406Sopenharmony_ci    case MODE_COLOR:
2041141cc406Sopenharmony_ci      get_color_line (dev, buffer);
2042141cc406Sopenharmony_ci      break;
2043141cc406Sopenharmony_ci    }
2044141cc406Sopenharmony_ci
2045141cc406Sopenharmony_ci  priv->lines_left--;
2046141cc406Sopenharmony_ci  priv->lines++;
2047141cc406Sopenharmony_ci
2048141cc406Sopenharmony_ci  DBG (4, "ccd300_read: %d lines read (%d to go)\n", priv->lines,
2049141cc406Sopenharmony_ci       priv->lines_left);
2050141cc406Sopenharmony_ci
2051141cc406Sopenharmony_ci  if (priv->lines_left == 0)
2052141cc406Sopenharmony_ci    {
2053141cc406Sopenharmony_ci      DBG (3, "ccd300_read: scan finished\n");
2054141cc406Sopenharmony_ci      return_home (dev, SANE_TRUE);
2055141cc406Sopenharmony_ci    }
2056141cc406Sopenharmony_ci
2057141cc406Sopenharmony_ci  sanei_pa4s2_enable (dev->fd, SANE_FALSE);
2058141cc406Sopenharmony_ci
2059141cc406Sopenharmony_ci}
2060