~ubuntu-branches/debian/jessie/sane-backends/jessie

« back to all changes in this revision

Viewing changes to backend/genesys_gl846.c

  • Committer: Package Import Robot
  • Author(s): Mark Buda
  • Date: 2013-11-24 10:05:18 UTC
  • mfrom: (1.1.14)
  • Revision ID: package-import@ubuntu.com-20131124100518-3k4yw6t30auxr5zu
Tags: 1.0.24-1
* New upstream version.
* New maintainer (Closes: 688531)
* Disable USB testing since it (probably) doesn't work on autobuilders.
* Fixed a bunch of lintian warnings.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* sane - Scanner Access Now Easy.
 
2
 
 
3
   Copyright (C) 2012-2013 St�phane Voltz <stef.dev@free.fr>
 
4
   
 
5
    
 
6
   This file is part of the SANE package.
 
7
   
 
8
   This program is free software; you can redistribute it and/or
 
9
   modify it under the terms of the GNU General Public License as
 
10
   published by the Free Software Foundation; either version 2 of the
 
11
   License, or (at your option) any later version.
 
12
   
 
13
   This program is distributed in the hope that it will be useful, but
 
14
   WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
   General Public License for more details.
 
17
   
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program; if not, write to the Free Software
 
20
   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 
21
   MA 02111-1307, USA.
 
22
   
 
23
   As a special exception, the authors of SANE give permission for
 
24
   additional uses of the libraries contained in this release of SANE.
 
25
   
 
26
   The exception is that, if you link a SANE library with other files
 
27
   to produce an executable, this does not by itself cause the
 
28
   resulting executable to be covered by the GNU General Public
 
29
   License.  Your use of that executable is in no way restricted on
 
30
   account of linking the SANE library code into it.
 
31
   
 
32
   This exception does not, however, invalidate any other reasons why
 
33
   the executable file might be covered by the GNU General Public
 
34
   License.
 
35
   
 
36
   If you submit changes to SANE to the maintainers to be included in
 
37
   a subsequent release, you agree by submitting the changes that
 
38
   those changes may be distributed with this exception intact.
 
39
   
 
40
   If you write modifications of your own for SANE, it is your choice
 
41
   whether to permit this exception to apply to your modifications.
 
42
   If you do not wish that, delete this exception notice. 
 
43
*/
 
44
 
 
45
/** @file
 
46
 *
 
47
 * This file handles GL846 and GL845 ASICs since they are really close to each other.
 
48
 */
 
49
#undef BACKEND_NAME
 
50
#define BACKEND_NAME genesys_gl846
 
51
 
 
52
#include "genesys_gl846.h"
 
53
 
 
54
/****************************************************************************
 
55
 Low level function
 
56
 ****************************************************************************/
 
57
 
 
58
/* ------------------------------------------------------------------------ */
 
59
/*                  Read and write RAM, registers and AFE                   */
 
60
/* ------------------------------------------------------------------------ */
 
61
 
 
62
 
 
63
/** @brief read scanned data
 
64
 * Read in 0xeff0 maximum sized blocks. This read is done in 2
 
65
 * parts if not multple of 512. First read is rounded to a multiple of 512 bytes, last read fetches the 
 
66
 * remainder. Read addr is always 0x10000000 with the memory layout setup.
 
67
 * @param dev device to read data from
 
68
 * @param addr address within ASIC memory space, unused but kept for API
 
69
 * @param data pointer where to store the read data
 
70
 * @param len size to read
 
71
 */
 
72
static SANE_Status
 
73
gl846_bulk_read_data (Genesys_Device * dev, uint8_t addr,
 
74
                      uint8_t * data, size_t len)
 
75
{
 
76
  SANE_Status status;
 
77
  size_t size, target, read, done;
 
78
  uint8_t outdata[8];
 
79
  uint8_t *buffer;
 
80
 
 
81
  DBG (DBG_io, "gl846_bulk_read_data: requesting %lu bytes at addr=0x%02x\n", (u_long) len, addr);
 
82
 
 
83
  if (len == 0)
 
84
    return SANE_STATUS_GOOD;
 
85
 
 
86
  target = len;
 
87
  buffer = data;
 
88
 
 
89
  /* loop until computed data size is read */
 
90
  while (target)
 
91
    {
 
92
      if (target > 0xeff0)
 
93
        {
 
94
          size = 0xeff0;
 
95
        }
 
96
      else
 
97
        {
 
98
          size = target;
 
99
        }
 
100
 
 
101
      /* hard coded 0x10000000 addr */
 
102
      outdata[0] = 0;
 
103
      outdata[1] = 0;
 
104
      outdata[2] = 0;
 
105
      outdata[3] = 0x10;
 
106
 
 
107
      /* data size to transfer */
 
108
      outdata[4] = (size & 0xff);
 
109
      outdata[5] = ((size >> 8) & 0xff);
 
110
      outdata[6] = ((size >> 16) & 0xff);
 
111
      outdata[7] = ((size >> 24) & 0xff);
 
112
 
 
113
      status =
 
114
        sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER,
 
115
                               VALUE_BUFFER, 0x00, sizeof (outdata),
 
116
                               outdata);
 
117
      if (status != SANE_STATUS_GOOD)
 
118
        {
 
119
          DBG (DBG_error, "%s failed while writing command: %s\n",
 
120
               __FUNCTION__, sane_strstatus (status));
 
121
          return status;
 
122
        }
 
123
 
 
124
      /* blocks must be multiple of 512 but not last block */
 
125
      read = size;
 
126
      if (read >= 512)
 
127
        {
 
128
          read /= 512;
 
129
          read *= 512;
 
130
        }
 
131
     
 
132
      DBG (DBG_io2,
 
133
           "gl846_bulk_read_data: trying to read %lu bytes of data\n",
 
134
           (u_long) read);
 
135
      status = sanei_usb_read_bulk (dev->dn, buffer, &read);
 
136
      if (status != SANE_STATUS_GOOD)
 
137
        {
 
138
          DBG (DBG_error,
 
139
               "gl846_bulk_read_data failed while reading bulk data: %s\n",
 
140
               sane_strstatus (status));
 
141
          return status;
 
142
        }
 
143
      done=read;
 
144
      DBG (DBG_io2, "gl846_bulk_read_data: %lu bytes of data read\n", (u_long) done);
 
145
 
 
146
      /* read less than 512 bytes remainder */
 
147
      if (read < size)
 
148
        {
 
149
          read = size - read;
 
150
          DBG (DBG_io2,
 
151
               "gl846_bulk_read_data: trying to read %lu bytes of data\n",
 
152
               (u_long) read);
 
153
          status = sanei_usb_read_bulk (dev->dn, buffer+done, &read);
 
154
          if (status != SANE_STATUS_GOOD)
 
155
            {
 
156
              DBG (DBG_error,
 
157
                   "gl846_bulk_read_data failed while reading bulk data: %s\n",
 
158
                   sane_strstatus (status));
 
159
              return status;
 
160
            }
 
161
          done=read;
 
162
          DBG (DBG_io2, "gl846_bulk_read_data: %lu bytes of data read\n", (u_long) done);
 
163
        }
 
164
 
 
165
      DBG (DBG_io2, "%s: read %lu bytes, %lu remaining\n", __FUNCTION__,
 
166
           (u_long) size, (u_long) (target - size));
 
167
 
 
168
      target -= size;
 
169
      buffer += size;
 
170
    }
 
171
 
 
172
  if (DBG_LEVEL >= DBG_data && dev->binary!=NULL)
 
173
    {
 
174
      fwrite(data, len, 1, dev->binary);
 
175
    }
 
176
 
 
177
  DBGCOMPLETED;
 
178
 
 
179
  return SANE_STATUS_GOOD;
 
180
}
 
181
 
 
182
/****************************************************************************
 
183
 Mid level functions 
 
184
 ****************************************************************************/
 
185
 
 
186
static SANE_Bool
 
187
gl846_get_fast_feed_bit (Genesys_Register_Set * regs)
 
188
{
 
189
  Genesys_Register_Set *r = NULL;
 
190
 
 
191
  r = sanei_genesys_get_address (regs, REG02);
 
192
  if (r && (r->value & REG02_FASTFED))
 
193
    return SANE_TRUE;
 
194
  return SANE_FALSE;
 
195
}
 
196
 
 
197
static SANE_Bool
 
198
gl846_get_filter_bit (Genesys_Register_Set * regs)
 
199
{
 
200
  Genesys_Register_Set *r = NULL;
 
201
 
 
202
  r = sanei_genesys_get_address (regs, REG04);
 
203
  if (r && (r->value & REG04_FILTER))
 
204
    return SANE_TRUE;
 
205
  return SANE_FALSE;
 
206
}
 
207
 
 
208
static SANE_Bool
 
209
gl846_get_lineart_bit (Genesys_Register_Set * regs)
 
210
{
 
211
  Genesys_Register_Set *r = NULL;
 
212
 
 
213
  r = sanei_genesys_get_address (regs, REG04);
 
214
  if (r && (r->value & REG04_LINEART))
 
215
    return SANE_TRUE;
 
216
  return SANE_FALSE;
 
217
}
 
218
 
 
219
static SANE_Bool
 
220
gl846_get_bitset_bit (Genesys_Register_Set * regs)
 
221
{
 
222
  Genesys_Register_Set *r = NULL;
 
223
 
 
224
  r = sanei_genesys_get_address (regs, REG04);
 
225
  if (r && (r->value & REG04_BITSET))
 
226
    return SANE_TRUE;
 
227
  return SANE_FALSE;
 
228
}
 
229
 
 
230
static SANE_Bool
 
231
gl846_get_gain4_bit (Genesys_Register_Set * regs)
 
232
{
 
233
  Genesys_Register_Set *r = NULL;
 
234
 
 
235
  r = sanei_genesys_get_address (regs, 0x06);
 
236
  if (r && (r->value & REG06_GAIN4))
 
237
    return SANE_TRUE;
 
238
  return SANE_FALSE;
 
239
}
 
240
 
 
241
static SANE_Bool
 
242
gl846_test_buffer_empty_bit (SANE_Byte val)
 
243
{
 
244
  if (val & REG41_BUFEMPTY)
 
245
    return SANE_TRUE;
 
246
  return SANE_FALSE;
 
247
}
 
248
 
 
249
static SANE_Bool
 
250
gl846_test_motor_flag_bit (SANE_Byte val)
 
251
{
 
252
  if (val & REG41_MOTORENB)
 
253
    return SANE_TRUE;
 
254
  return SANE_FALSE;
 
255
}
 
256
 
 
257
/**
 
258
 * compute the step multiplier used
 
259
 */
 
260
static int
 
261
gl846_get_step_multiplier (Genesys_Register_Set * regs)
 
262
{
 
263
  Genesys_Register_Set *r = NULL;
 
264
  int value = 1;
 
265
 
 
266
  r = sanei_genesys_get_address (regs, 0x9d);
 
267
  if (r != NULL)
 
268
    {
 
269
      value = (r->value & 0x0f)>>1;
 
270
      value = 1 << value;
 
271
    }
 
272
  DBG (DBG_io, "%s: step multiplier is %d\n", __FUNCTION__, value);
 
273
  return value;
 
274
}
 
275
 
 
276
/** @brief sensor profile
 
277
 * search for the database of motor profiles and get the best one. Each
 
278
 * profile is at a specific dpihw. Use LiDE 110 table by default.
 
279
 * @param sensor_type sensor id
 
280
 * @param dpi hardware dpi for the scan
 
281
 * @return a pointer to a Sensor_Profile struct
 
282
 */
 
283
static Sensor_Profile *get_sensor_profile(int sensor_type, int dpi)
 
284
{
 
285
  unsigned int i;
 
286
  int idx;
 
287
 
 
288
  i=0;
 
289
  idx=-1;
 
290
  while(i<sizeof(sensors)/sizeof(Sensor_Profile))
 
291
    {
 
292
      /* exact match */
 
293
      if(sensors[i].sensor_type==sensor_type && sensors[i].dpi==dpi)
 
294
        {
 
295
          return &(sensors[i]);
 
296
        }
 
297
 
 
298
      /* closest match */
 
299
      if(sensors[i].sensor_type==sensor_type)
 
300
        {
 
301
          if(idx<0)
 
302
            {
 
303
              idx=i;
 
304
            }
 
305
          else
 
306
            {
 
307
              if(sensors[i].dpi>=dpi 
 
308
              && sensors[i].dpi<sensors[idx].dpi)
 
309
                {
 
310
                  idx=i;
 
311
                }
 
312
            }
 
313
        }
 
314
      i++;
 
315
    }
 
316
 
 
317
  /* default fallback */
 
318
  if(idx<0)
 
319
    {
 
320
      DBG (DBG_warn,"%s: using default sensor profile\n",__FUNCTION__);
 
321
      idx=0;
 
322
    }
 
323
 
 
324
  return &(sensors[idx]);
 
325
}
 
326
 
 
327
/**@brief compute exposure to use
 
328
 * compute the sensor exposure based on target resolution
 
329
 */
 
330
static int gl846_compute_exposure(Genesys_Device *dev, int xres)
 
331
{
 
332
  Sensor_Profile *sensor;
 
333
 
 
334
  sensor=get_sensor_profile(dev->model->ccd_type, xres);
 
335
  return sensor->exposure;
 
336
}
 
337
 
 
338
 
 
339
/** @brief sensor specific settings
 
340
*/
 
341
static void
 
342
gl846_setup_sensor (Genesys_Device * dev, Genesys_Register_Set * regs, int dpi)
 
343
{
 
344
  Genesys_Register_Set *r;
 
345
  Sensor_Profile *sensor;
 
346
  int dpihw, i;
 
347
  uint16_t exp;
 
348
 
 
349
  DBGSTART;
 
350
  dpihw=sanei_genesys_compute_dpihw(dev,dpi);
 
351
 
 
352
  for (i = 0x06; i < 0x0e; i++)
 
353
    {
 
354
      r = sanei_genesys_get_address (regs, 0x10 + i);
 
355
      if (r)
 
356
        r->value = dev->sensor.regs_0x10_0x1d[i];
 
357
    }
 
358
 
 
359
  for (i = 0; i < 9; i++)
 
360
    {
 
361
      r = sanei_genesys_get_address (regs, 0x52 + i);
 
362
      if (r)
 
363
        r->value = dev->sensor.regs_0x52_0x5e[i];
 
364
    }
 
365
 
 
366
  /* set EXPDUMMY and CKxMAP */
 
367
  dpihw=sanei_genesys_compute_dpihw(dev,dpi);
 
368
  sensor=get_sensor_profile(dev->model->ccd_type, dpihw);
 
369
 
 
370
  sanei_genesys_set_reg_from_set(regs,REG_EXPDMY,(uint8_t)((sensor->expdummy) & 0xff));
 
371
 
 
372
  /* if no calibration has been done, set default values for exposures */
 
373
  exp=dev->sensor.regs_0x10_0x1d[0]*256+dev->sensor.regs_0x10_0x1d[1];
 
374
  if(exp==0)
 
375
    {
 
376
      exp=sensor->expr;
 
377
    }
 
378
  sanei_genesys_set_double(regs,REG_EXPR,exp);
 
379
 
 
380
  exp=dev->sensor.regs_0x10_0x1d[2]*256+dev->sensor.regs_0x10_0x1d[3];
 
381
  if(exp==0)
 
382
    {
 
383
      exp=sensor->expg;
 
384
    }
 
385
  sanei_genesys_set_double(regs,REG_EXPG,exp);
 
386
 
 
387
  exp=dev->sensor.regs_0x10_0x1d[4]*256+dev->sensor.regs_0x10_0x1d[5];
 
388
  if(exp==0)
 
389
    {
 
390
      exp=sensor->expb;
 
391
    }
 
392
  sanei_genesys_set_double(regs,REG_EXPB,exp);
 
393
 
 
394
  sanei_genesys_set_triple(regs,REG_CK1MAP,sensor->ck1map);
 
395
  sanei_genesys_set_triple(regs,REG_CK3MAP,sensor->ck3map);
 
396
  sanei_genesys_set_triple(regs,REG_CK4MAP,sensor->ck4map);
 
397
 
 
398
  /* order of the sub-segments */
 
399
  dev->order=sensor->order;
 
400
 
 
401
  r = sanei_genesys_get_address (regs, 0x17);
 
402
  r->value = sensor->r17;
 
403
 
 
404
  DBGCOMPLETED;
 
405
}
 
406
 
 
407
 
 
408
/* returns the max register bulk size */
 
409
static int
 
410
gl846_bulk_full_size (void)
 
411
{
 
412
  return GENESYS_GL846_MAX_REGS;
 
413
}
 
414
 
 
415
/** @brief set all registers to default values .
 
416
 * This function is called only once at the beginning and
 
417
 * fills register startup values for registers reused across scans.
 
418
 * Those that are rarely modified or not modified are written
 
419
 * individually.
 
420
 * @param dev device structure holding register set to initialize
 
421
 */
 
422
static void
 
423
gl846_init_registers (Genesys_Device * dev)
 
424
{
 
425
  DBGSTART;
 
426
 
 
427
  memset (dev->reg, 0,
 
428
          GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
 
429
 
 
430
  SETREG (0x01,0x60);
 
431
  SETREG (0x02,0x38);
 
432
  SETREG (0x03,0x03);
 
433
  SETREG (0x04,0x22);
 
434
  SETREG (0x05,0x60);
 
435
  SETREG (0x06,0x10);
 
436
  SETREG (0x08,0x60);
 
437
  SETREG (0x09,0x00);
 
438
  SETREG (0x0a,0x00);
 
439
  SETREG (0x0b,0x8b);
 
440
  SETREG (0x0c,0x00);
 
441
  SETREG (0x0d,0x00);
 
442
  SETREG (0x10,0x00);
 
443
  SETREG (0x11,0x00);
 
444
  SETREG (0x12,0x00);
 
445
  SETREG (0x13,0x00);
 
446
  SETREG (0x14,0x00);
 
447
  SETREG (0x15,0x00);
 
448
  SETREG (0x16,0xbb);
 
449
  SETREG (0x17,0x13);
 
450
  SETREG (0x18,0x10);
 
451
  SETREG (0x19,0x2a);
 
452
  SETREG (0x1a,0x34);
 
453
  SETREG (0x1b,0x00);
 
454
  SETREG (0x1c,0x20);
 
455
  SETREG (0x1d,0x06);
 
456
  SETREG (0x1e,0xf0);
 
457
  SETREG (0x1f,0x01);
 
458
  SETREG (0x20,0x03);
 
459
  SETREG (0x21,0x10);
 
460
  SETREG (0x22,0x60);
 
461
  SETREG (0x23,0x60);
 
462
  SETREG (0x24,0x60);
 
463
  SETREG (0x25,0x00);
 
464
  SETREG (0x26,0x00);
 
465
  SETREG (0x27,0x00);
 
466
  SETREG (0x2c,0x00);
 
467
  SETREG (0x2d,0x00);
 
468
  SETREG (0x2e,0x80);
 
469
  SETREG (0x2f,0x80);
 
470
  SETREG (0x30,0x00);
 
471
  SETREG (0x31,0x00);
 
472
  SETREG (0x32,0x00);
 
473
  SETREG (0x33,0x00);
 
474
  SETREG (0x34,0x1f);
 
475
  SETREG (0x35,0x00);
 
476
  SETREG (0x36,0x40);
 
477
  SETREG (0x37,0x00);
 
478
  SETREG (0x38,0x2a);
 
479
  SETREG (0x39,0xf8);
 
480
  SETREG (0x3d,0x00);
 
481
  SETREG (0x3e,0x00);
 
482
  SETREG (0x3f,0x01);
 
483
  SETREG (0x52,0x02);
 
484
  SETREG (0x53,0x04);
 
485
  SETREG (0x54,0x06);
 
486
  SETREG (0x55,0x08);
 
487
  SETREG (0x56,0x0a);
 
488
  SETREG (0x57,0x00);
 
489
  SETREG (0x58,0x59);
 
490
  SETREG (0x59,0x31);
 
491
  SETREG (0x5a,0x40);
 
492
  SETREG (0x5e,0x1f);
 
493
  SETREG (0x5f,0x01);
 
494
  SETREG (0x60,0x00);
 
495
  SETREG (0x61,0x00);
 
496
  SETREG (0x62,0x00);
 
497
  SETREG (0x63,0x00);
 
498
  SETREG (0x64,0x00);
 
499
  SETREG (0x65,0x00);
 
500
  SETREG (0x67,0x7f);
 
501
  SETREG (0x68,0x7f);
 
502
  SETREG (0x69,0x01);
 
503
  SETREG (0x6a,0x01);
 
504
  SETREG (0x70,0x01);
 
505
  SETREG (0x71,0x00);
 
506
  SETREG (0x72,0x02);
 
507
  SETREG (0x73,0x01);
 
508
  SETREG (0x74,0x00);
 
509
  SETREG (0x75,0x00);
 
510
  SETREG (0x76,0x00);
 
511
  SETREG (0x77,0x00);
 
512
  SETREG (0x78,0x00);
 
513
  SETREG (0x79,0x3f);
 
514
  SETREG (0x7a,0x00);
 
515
  SETREG (0x7b,0x09);
 
516
  SETREG (0x7c,0x99);
 
517
  SETREG (0x7d,0x20);
 
518
  SETREG (0x7f,0x05);
 
519
  SETREG (0x80,0x4f);
 
520
  SETREG (0x87,0x02);
 
521
  SETREG (0x94,0xff);
 
522
  SETREG (0x9d,0x04);
 
523
  SETREG (0x9e,0x00);
 
524
  SETREG (0xa1,0xe0);
 
525
  SETREG (0xa2,0x1f);
 
526
  SETREG (0xab,0xc0);
 
527
  SETREG (0xbb,0x00);
 
528
  SETREG (0xbc,0x0f);
 
529
  SETREG (0xdb,0xff);
 
530
  SETREG (0xfe,0x08);
 
531
  SETREG (0xff,0x02);
 
532
  SETREG (0x98,0x20);
 
533
  SETREG (0x99,0x00);
 
534
  SETREG (0x9a,0x90);
 
535
  SETREG (0x9b,0x00);
 
536
  SETREG (0xf8,0x05);
 
537
 
 
538
  /* fine tune upon device description */
 
539
  dev->reg[reg_0x05].value &= ~REG05_DPIHW;
 
540
  switch (dev->sensor.optical_res)
 
541
    {
 
542
    case 600:
 
543
      dev->reg[reg_0x05].value |= REG05_DPIHW_600;
 
544
      break;
 
545
    case 1200:
 
546
      dev->reg[reg_0x05].value |= REG05_DPIHW_1200;
 
547
      break;
 
548
    case 2400:
 
549
      dev->reg[reg_0x05].value |= REG05_DPIHW_2400;
 
550
      break;
 
551
    case 4800:
 
552
      dev->reg[reg_0x05].value |= REG05_DPIHW_4800;
 
553
      break;
 
554
    }
 
555
 
 
556
  /* initalize calibration reg */
 
557
  memcpy (dev->calib_reg, dev->reg,
 
558
          GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
 
559
 
 
560
  DBGCOMPLETED;
 
561
}
 
562
 
 
563
/**@brief send slope table for motor movement 
 
564
 * Send slope_table in machine byte order
 
565
 * @param dev device to send slope table
 
566
 * @param table_nr index of the slope table in ASIC memory
 
567
 * Must be in the [0-4] range.
 
568
 * @param slope_table pointer to 16 bit values array of the slope table
 
569
 * @param steps number of elements in the slope table
 
570
 */
 
571
static SANE_Status
 
572
gl846_send_slope_table (Genesys_Device * dev, int table_nr,
 
573
                        uint16_t * slope_table, int steps)
 
574
{
 
575
  SANE_Status status;
 
576
  uint8_t *table;
 
577
  int i;
 
578
  char msg[10000];
 
579
 
 
580
  DBG (DBG_proc, "%s (table_nr = %d, steps = %d)\n", __FUNCTION__,
 
581
       table_nr, steps);
 
582
 
 
583
  /* sanity check */
 
584
  if(table_nr<0 || table_nr>4)
 
585
    {
 
586
      DBG (DBG_error, "%s: invalid table number %d!\n", __FUNCTION__, table_nr);
 
587
      return SANE_STATUS_INVAL;
 
588
    }
 
589
 
 
590
  table = (uint8_t *) malloc (steps * 2);
 
591
  for (i = 0; i < steps; i++)
 
592
    {
 
593
      table[i * 2] = slope_table[i] & 0xff;
 
594
      table[i * 2 + 1] = slope_table[i] >> 8;
 
595
    }
 
596
 
 
597
  if (DBG_LEVEL >= DBG_io)
 
598
    {
 
599
      sprintf (msg, "write slope %d (%d)=", table_nr, steps);
 
600
      for (i = 0; i < steps; i++)
 
601
        {
 
602
          sprintf (msg+strlen(msg), "%d", slope_table[i]);
 
603
        }
 
604
      DBG (DBG_io, "%s: %s\n", __FUNCTION__, msg);
 
605
    }
 
606
 
 
607
  /* slope table addresses are fixed */
 
608
  status = sanei_genesys_write_ahb (dev->dn, dev->usb_mode, 0x10000000 + 0x4000 * table_nr, steps * 2, table);
 
609
  if (status != SANE_STATUS_GOOD)
 
610
    {
 
611
      DBG (DBG_error,
 
612
           "%s: write to AHB failed writing slope table %d (%s)\n",
 
613
           __FUNCTION__, table_nr, sane_strstatus (status));
 
614
    }
 
615
 
 
616
  free (table);
 
617
  DBGCOMPLETED;
 
618
  return status;
 
619
}
 
620
 
 
621
/**
 
622
 * Set register values of Analog Device type frontend
 
623
 * */
 
624
static SANE_Status
 
625
gl846_set_adi_fe (Genesys_Device * dev, uint8_t set)
 
626
{
 
627
  SANE_Status status = SANE_STATUS_GOOD;
 
628
  int i;
 
629
  uint16_t val;
 
630
  uint8_t val8;
 
631
 
 
632
  DBGSTART;
 
633
 
 
634
  /* wait for FE to be ready */
 
635
  status = sanei_genesys_get_status (dev, &val8);
 
636
  while (val8 & REG41_FEBUSY);
 
637
    {
 
638
      usleep (10000);
 
639
      status = sanei_genesys_get_status (dev, &val8);
 
640
    };
 
641
 
 
642
  if (set == AFE_INIT)
 
643
    {
 
644
      DBG (DBG_proc, "%s(): setting DAC %u\n", __FUNCTION__, dev->model->dac_type);
 
645
 
 
646
      /* sets to default values */
 
647
      sanei_genesys_init_fe (dev);
 
648
    }
 
649
 
 
650
  /* write them to analog frontend */
 
651
  val = dev->frontend.reg[0];
 
652
  status = sanei_genesys_fe_write_data (dev, 0x00, val);
 
653
  if (status != SANE_STATUS_GOOD)
 
654
    {
 
655
      DBG (DBG_error, "%s: failed to write reg0: %s\n", __FUNCTION__,
 
656
           sane_strstatus (status));
 
657
      return status;
 
658
    }
 
659
  val = dev->frontend.reg[1];
 
660
  status = sanei_genesys_fe_write_data (dev, 0x01, val);
 
661
  if (status != SANE_STATUS_GOOD)
 
662
    {
 
663
      DBG (DBG_error, "%s: failed to write reg1: %s\n", __FUNCTION__,
 
664
           sane_strstatus (status));
 
665
      return status;
 
666
    }
 
667
 
 
668
  for (i = 0; i < 3; i++)
 
669
    {
 
670
      val = dev->frontend.gain[i];
 
671
      status = sanei_genesys_fe_write_data (dev, 0x02 + i, val);
 
672
      if (status != SANE_STATUS_GOOD)
 
673
        {
 
674
          DBG (DBG_error,
 
675
               "%s: failed to write gain %d: %s\n", __FUNCTION__, i,
 
676
               sane_strstatus (status));
 
677
          return status;
 
678
        }
 
679
    }
 
680
  for (i = 0; i < 3; i++)
 
681
    {
 
682
      val = dev->frontend.offset[i];
 
683
      status = sanei_genesys_fe_write_data (dev, 0x05 + i, val);
 
684
      if (status != SANE_STATUS_GOOD)
 
685
        {
 
686
          DBG (DBG_error,
 
687
               "%s: failed to write offset %d: %s\n", __FUNCTION__, i,
 
688
               sane_strstatus (status));
 
689
          return status;
 
690
        }
 
691
    }
 
692
 
 
693
  DBGCOMPLETED;
 
694
  return status;
 
695
}
 
696
 
 
697
static SANE_Status
 
698
gl846_homsnr_gpio(Genesys_Device *dev)
 
699
{
 
700
uint8_t val;
 
701
SANE_Status status=SANE_STATUS_GOOD;
 
702
 
 
703
  RIE (sanei_genesys_read_register (dev, REG6C, &val));
 
704
  val |= 0x41;
 
705
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
706
 
 
707
  return status;
 
708
}
 
709
 
 
710
/* Set values of analog frontend */
 
711
static SANE_Status
 
712
gl846_set_fe (Genesys_Device * dev, uint8_t set)
 
713
{
 
714
  SANE_Status status;
 
715
 
 
716
  DBG(DBG_proc, "gl846_set_fe (%s)\n",
 
717
      set == AFE_INIT ? "init" : set == AFE_SET ? "set" :
 
718
      set == AFE_POWER_SAVE ? "powersave" : "huh?");
 
719
 
 
720
  /* route to specific analog frontend setup */
 
721
  switch (dev->reg[reg_0x04].value & REG04_FESET)
 
722
    {
 
723
      case 0x02: /* ADI FE */
 
724
        status = gl846_set_adi_fe(dev, set);
 
725
        break;
 
726
      default:
 
727
        DBG(DBG_proc, "gl846_set_fe(): unsupported frontend type %d\n",
 
728
            dev->reg[reg_0x04].value & REG04_FESET);
 
729
        status = SANE_STATUS_UNSUPPORTED;
 
730
    }
 
731
 
 
732
  DBGCOMPLETED;
 
733
  return status;
 
734
}
 
735
 
 
736
 
 
737
/** @brief set up motor related register for scan
 
738
 */
 
739
static SANE_Status
 
740
gl846_init_motor_regs_scan (Genesys_Device * dev,
 
741
                            Genesys_Register_Set * reg,
 
742
                            unsigned int scan_exposure_time,
 
743
                            float scan_yres,
 
744
                            int scan_step_type,
 
745
                            unsigned int scan_lines,
 
746
                            unsigned int scan_dummy,
 
747
                            unsigned int feed_steps,
 
748
                            int scan_power_mode,
 
749
                            unsigned int flags)
 
750
{
 
751
  SANE_Status status;
 
752
  int use_fast_fed;
 
753
  unsigned int fast_dpi;
 
754
  uint16_t scan_table[SLOPE_TABLE_SIZE];
 
755
  uint16_t fast_table[SLOPE_TABLE_SIZE];
 
756
  int scan_steps, fast_steps, factor;
 
757
  unsigned int feedl, dist;
 
758
  Genesys_Register_Set *r;
 
759
  uint32_t z1, z2;
 
760
  unsigned int min_restep = 0x20;
 
761
  uint8_t val;
 
762
  int fast_step_type;
 
763
  unsigned int ccdlmt,tgtime;
 
764
 
 
765
  DBGSTART;
 
766
  DBG (DBG_proc, "gl846_init_motor_regs_scan : scan_exposure_time=%d, "
 
767
       "scan_yres=%g, scan_step_type=%d, scan_lines=%d, scan_dummy=%d, "
 
768
       "feed_steps=%d, scan_power_mode=%d, flags=%x\n",
 
769
       scan_exposure_time,
 
770
       scan_yres,
 
771
       scan_step_type,
 
772
       scan_lines, scan_dummy, feed_steps, scan_power_mode, flags);
 
773
 
 
774
  /* get step multiplier */
 
775
  factor = gl846_get_step_multiplier (reg);
 
776
 
 
777
  use_fast_fed=0;
 
778
  /* no fast fed since feed works well */
 
779
  if(dev->settings.yres==4444 && feed_steps>100 
 
780
     && ((flags & MOTOR_FLAG_FEED)==0))
 
781
    {
 
782
      use_fast_fed=1;
 
783
    }
 
784
  DBG (DBG_io, "%s: use_fast_fed=%d\n", __FUNCTION__, use_fast_fed);
 
785
 
 
786
  sanei_genesys_set_triple(reg, REG_LINCNT, scan_lines);
 
787
  DBG (DBG_io, "%s: lincnt=%d\n", __FUNCTION__, scan_lines);
 
788
 
 
789
  /* compute register 02 value */
 
790
  r = sanei_genesys_get_address (reg, REG02);
 
791
  r->value = 0x00;
 
792
  r->value |= REG02_MTRPWR;
 
793
 
 
794
  if (use_fast_fed)
 
795
    r->value |= REG02_FASTFED;
 
796
  else
 
797
    r->value &= ~REG02_FASTFED;
 
798
 
 
799
  if (flags & MOTOR_FLAG_AUTO_GO_HOME)
 
800
    r->value |= REG02_AGOHOME | REG02_NOTHOME;
 
801
 
 
802
  if ((flags & MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE)
 
803
      ||(scan_yres>=dev->sensor.optical_res))
 
804
    {
 
805
      r->value |= REG02_ACDCDIS;
 
806
    }
 
807
 
 
808
  /* scan and backtracking slope table */
 
809
  sanei_genesys_slope_table(scan_table,
 
810
                            &scan_steps,
 
811
                            scan_yres,
 
812
                            scan_exposure_time,
 
813
                            dev->motor.base_ydpi,
 
814
                            scan_step_type,
 
815
                            factor,
 
816
                            dev->model->motor_type,
 
817
                            gl846_motors);
 
818
  RIE(gl846_send_slope_table (dev, SCAN_TABLE, scan_table, scan_steps*factor));
 
819
  RIE(gl846_send_slope_table (dev, BACKTRACK_TABLE, scan_table, scan_steps*factor));
 
820
 
 
821
  /* fast table */
 
822
  fast_dpi=sanei_genesys_get_lowest_ydpi(dev);
 
823
  fast_step_type=scan_step_type;
 
824
  if(scan_step_type>=2)
 
825
    {
 
826
      fast_step_type=2;
 
827
    }
 
828
 
 
829
  sanei_genesys_slope_table(fast_table,
 
830
                            &fast_steps,
 
831
                            fast_dpi,
 
832
                            scan_exposure_time,
 
833
                            dev->motor.base_ydpi,
 
834
                            fast_step_type,
 
835
                            factor,
 
836
                            dev->model->motor_type,
 
837
                            gl846_motors);
 
838
 
 
839
  /* manual override of high start value */
 
840
  fast_table[0]=fast_table[1];
 
841
 
 
842
  RIE(gl846_send_slope_table (dev, STOP_TABLE, fast_table, fast_steps*factor));
 
843
  RIE(gl846_send_slope_table (dev, FAST_TABLE, fast_table, fast_steps*factor));
 
844
  RIE(gl846_send_slope_table (dev, HOME_TABLE, fast_table, fast_steps*factor));
 
845
 
 
846
  /* correct move distance by acceleration and deceleration amounts */
 
847
  feedl=feed_steps;
 
848
  if (use_fast_fed) 
 
849
    {
 
850
        feedl<<=fast_step_type;
 
851
        dist=(scan_steps+2*fast_steps)*factor;
 
852
        /* TODO read and decode REGAB */
 
853
        r = sanei_genesys_get_address (reg, 0x5e);
 
854
        dist += (r->value & 31);
 
855
        /* FEDCNT */
 
856
        r = sanei_genesys_get_address (reg, REG_FEDCNT);
 
857
        dist += r->value;
 
858
    }
 
859
  else
 
860
    {
 
861
      feedl<<=scan_step_type;
 
862
      dist=scan_steps*factor;
 
863
      if (flags & MOTOR_FLAG_FEED)
 
864
        dist *=2;
 
865
    }
 
866
  DBG (DBG_io2, "%s: scan steps=%d\n", __FUNCTION__, scan_steps);
 
867
  DBG (DBG_io2, "%s: acceleration distance=%d\n", __FUNCTION__, dist);
 
868
 
 
869
  /* check for overflow */
 
870
  if(dist<feedl)
 
871
    feedl -= dist;
 
872
  else
 
873
    feedl = 0;
 
874
 
 
875
  sanei_genesys_set_triple(reg,REG_FEEDL,feedl);
 
876
  DBG (DBG_io ,"%s: feedl=%d\n",__FUNCTION__,feedl);
 
877
 
 
878
  r = sanei_genesys_get_address (reg, REG0C);
 
879
  ccdlmt=(r->value & REG0C_CCDLMT)+1;
 
880
 
 
881
  r = sanei_genesys_get_address (reg, REG1C);
 
882
  tgtime=1<<(r->value & REG1C_TGTIME);
 
883
 
 
884
  /* hi res motor speed GPIO */
 
885
  /*
 
886
  RIE (sanei_genesys_read_register (dev, REG6C, &effective));
 
887
  */
 
888
 
 
889
  /* if quarter step, bipolar Vref2 */
 
890
  /* XXX STEF XXX GPIO 
 
891
  if (scan_step_type > 1)
 
892
    {
 
893
      if (scan_step_type < 3)
 
894
        {
 
895
          val = effective & ~REG6C_GPIO13;
 
896
        }
 
897
      else
 
898
        {
 
899
          val = effective | REG6C_GPIO13;
 
900
        }
 
901
    }
 
902
  else
 
903
    {
 
904
      val = effective;
 
905
    }
 
906
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
907
    */
 
908
 
 
909
  /* effective scan */
 
910
  /*
 
911
  RIE (sanei_genesys_read_register (dev, REG6C, &effective));
 
912
  val = effective | REG6C_GPIO10;
 
913
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
914
  */
 
915
 
 
916
  if(dev->model->gpo_type==GPO_IMG101)
 
917
    {
 
918
      if(scan_yres==sanei_genesys_compute_dpihw(dev,scan_yres))
 
919
        {
 
920
          val=1;
 
921
        }
 
922
      else
 
923
        {
 
924
          val=0;
 
925
        }
 
926
      RIE (sanei_genesys_write_register (dev, REG7E, val));
 
927
    }
 
928
 
 
929
  min_restep=scan_steps/2-1;
 
930
  if (min_restep < 1)
 
931
    min_restep = 1;
 
932
  r = sanei_genesys_get_address (reg, REG_FWDSTEP);
 
933
  r->value = min_restep;
 
934
  r = sanei_genesys_get_address (reg, REG_BWDSTEP);
 
935
  r->value = min_restep;
 
936
 
 
937
  sanei_genesys_calculate_zmode2(use_fast_fed,
 
938
                                 scan_exposure_time*ccdlmt*tgtime,
 
939
                                 scan_table,
 
940
                                 scan_steps*factor,
 
941
                                 feedl,
 
942
                                 min_restep*factor,
 
943
                                 &z1,
 
944
                                 &z2);
 
945
 
 
946
  DBG (DBG_info, "gl846_init_motor_regs_scan: z1 = %d\n", z1);
 
947
  sanei_genesys_set_triple(reg, REG60, z1 | (scan_step_type << (16+REG60S_STEPSEL)));
 
948
 
 
949
  DBG (DBG_info, "gl846_init_motor_regs_scan: z2 = %d\n", z2);
 
950
  sanei_genesys_set_triple(reg, REG63, z2 | (scan_step_type << (16+REG63S_FSTPSEL)));
 
951
 
 
952
  r = sanei_genesys_get_address (reg, 0x1e);
 
953
  r->value &= 0xf0;             /* 0 dummy lines */
 
954
  r->value |= scan_dummy;       /* dummy lines */
 
955
 
 
956
  r = sanei_genesys_get_address (reg, REG67);
 
957
  r->value = 0x7f;
 
958
 
 
959
  r = sanei_genesys_get_address (reg, REG68);
 
960
  r->value = 0x7f;
 
961
 
 
962
  r = sanei_genesys_get_address (reg, REG_STEPNO);
 
963
  r->value = scan_steps;
 
964
 
 
965
  r = sanei_genesys_get_address (reg, REG_FASTNO);
 
966
  r->value = scan_steps;
 
967
 
 
968
  r = sanei_genesys_get_address (reg, REG_FSHDEC);
 
969
  r->value = scan_steps;
 
970
 
 
971
  r = sanei_genesys_get_address (reg, REG_FMOVNO);
 
972
  r->value = fast_steps;
 
973
 
 
974
  r = sanei_genesys_get_address (reg, REG_FMOVDEC);
 
975
  r->value = fast_steps;
 
976
 
 
977
  DBGCOMPLETED;
 
978
  return SANE_STATUS_GOOD;
 
979
}
 
980
 
 
981
 
 
982
/** @brief set up registers related to sensor
 
983
 * Set up the following registers
 
984
   0x01
 
985
   0x03
 
986
   0x10-0x015     R/G/B exposures
 
987
   0x19           EXPDMY
 
988
   0x2e           BWHI
 
989
   0x2f           BWLO
 
990
   0x04
 
991
   0x87
 
992
   0x05
 
993
   0x2c,0x2d      DPISET
 
994
   0x30,0x31      STRPIXEL
 
995
   0x32,0x33      ENDPIXEL
 
996
   0x35,0x36,0x37 MAXWD [25:2] (>>2)
 
997
   0x38,0x39      LPERIOD
 
998
   0x34           DUMMY
 
999
 */
 
1000
static SANE_Status
 
1001
gl846_init_optical_regs_scan (Genesys_Device * dev,
 
1002
                              Genesys_Register_Set * reg,
 
1003
                              unsigned int exposure_time,
 
1004
                              int used_res,
 
1005
                              unsigned int start,
 
1006
                              unsigned int pixels,
 
1007
                              int channels,
 
1008
                              int depth,
 
1009
                              SANE_Bool half_ccd, int color_filter, int flags)
 
1010
{
 
1011
  unsigned int words_per_line;
 
1012
  unsigned int startx, endx, used_pixels;
 
1013
  unsigned int dpiset, dpihw,segnb,cksel,factor;
 
1014
  unsigned int bytes;
 
1015
  Genesys_Register_Set *r;
 
1016
  SANE_Status status;
 
1017
  Sensor_Profile *sensor;
 
1018
 
 
1019
  DBG (DBG_proc, "gl846_init_optical_regs_scan :  exposure_time=%d, "
 
1020
       "used_res=%d, start=%d, pixels=%d, channels=%d, depth=%d, "
 
1021
       "half_ccd=%d, flags=%x\n", exposure_time,
 
1022
       used_res, start, pixels, channels, depth, half_ccd, flags);
 
1023
 
 
1024
  /* resolution is divided according to CKSEL */ 
 
1025
  r = sanei_genesys_get_address (reg, REG18);
 
1026
  cksel= (r->value & REG18_CKSEL)+1;
 
1027
  DBG (DBG_io2, "%s: cksel=%d\n", __FUNCTION__, cksel);
 
1028
  
 
1029
  /* to manage high resolution device while keeping good
 
1030
   * low resolution scanning speed, we make hardware dpi vary */
 
1031
  dpihw=sanei_genesys_compute_dpihw(dev, used_res * cksel);
 
1032
  factor=dev->sensor.optical_res/dpihw;
 
1033
  DBG (DBG_io2, "%s: dpihw=%d (factor=%d)\n", __FUNCTION__, dpihw, factor);
 
1034
 
 
1035
  /* sensor parameters */
 
1036
  sensor=get_sensor_profile(dev->model->ccd_type, dpihw);
 
1037
  gl846_setup_sensor (dev, reg, dpihw);
 
1038
  dpiset = used_res * cksel;
 
1039
 
 
1040
  /* start and end coordinate in optical dpi coordinates */
 
1041
  startx = start/cksel+dev->sensor.CCD_start_xoffset;
 
1042
  used_pixels=pixels/cksel;
 
1043
 
 
1044
  /* end of sensor window */
 
1045
  endx = startx + used_pixels;
 
1046
 
 
1047
  /* sensors are built from 600 dpi segments for LiDE 100/200
 
1048
   * and 1200 dpi for the 700F */
 
1049
  if (dev->model->flags & GENESYS_FLAG_SIS_SENSOR)
 
1050
    {
 
1051
      segnb=dpihw/600;
 
1052
    }
 
1053
  else
 
1054
    {
 
1055
      segnb=1;
 
1056
    }
 
1057
 
 
1058
  /* compute pixel coordinate in the given dpihw space,
 
1059
   * taking segments into account */
 
1060
  startx/=factor*segnb;
 
1061
  endx/=factor*segnb;
 
1062
  dev->len=endx-startx;
 
1063
  dev->dist=0;
 
1064
  dev->skip=0;
 
1065
 
 
1066
  /* in cas of multi-segments sensor, we have to add the witdh
 
1067
   * of the sensor crossed by the scan area */
 
1068
  if (dev->model->flags & GENESYS_FLAG_SIS_SENSOR && segnb>1)
 
1069
    {
 
1070
      dev->dist = sensor->segcnt;
 
1071
    }
 
1072
 
 
1073
  /* use a segcnt rounded to next even number */
 
1074
  endx += ((dev->dist+1)&0xfffe)*(segnb-1);
 
1075
  used_pixels=endx-startx;
 
1076
 
 
1077
  status = gl846_set_fe (dev, AFE_SET);
 
1078
  if (status != SANE_STATUS_GOOD)
 
1079
    {
 
1080
      DBG (DBG_error,
 
1081
           "gl846_init_optical_regs_scan: failed to set frontend: %s\n",
 
1082
           sane_strstatus (status));
 
1083
      return status;
 
1084
    }
 
1085
 
 
1086
  /* enable shading */
 
1087
  r = sanei_genesys_get_address (reg, REG01);
 
1088
  r->value &= ~REG01_SCAN;
 
1089
  r->value |= REG01_SHDAREA;
 
1090
  if ((flags & OPTICAL_FLAG_DISABLE_SHADING) ||
 
1091
      (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION))
 
1092
    {
 
1093
      r->value &= ~REG01_DVDSET;
 
1094
    }
 
1095
  else
 
1096
    {
 
1097
      r->value |= REG01_DVDSET;
 
1098
    }
 
1099
 
 
1100
  r = sanei_genesys_get_address (reg, REG03);
 
1101
  r->value &= ~REG03_AVEENB;
 
1102
 
 
1103
  if (flags & OPTICAL_FLAG_DISABLE_LAMP)
 
1104
    r->value &= ~REG03_LAMPPWR;
 
1105
  else
 
1106
    r->value |= REG03_LAMPPWR;
 
1107
 
 
1108
  /* BW threshold */
 
1109
  r = sanei_genesys_get_address (reg, 0x2e);
 
1110
  r->value = dev->settings.threshold;
 
1111
  r = sanei_genesys_get_address (reg, 0x2f);
 
1112
  r->value = dev->settings.threshold;
 
1113
 
 
1114
  /* monochrome / color scan */
 
1115
  r = sanei_genesys_get_address (reg, REG04);
 
1116
  switch (depth)
 
1117
    {
 
1118
    case 1:
 
1119
      r->value &= ~REG04_BITSET;
 
1120
      r->value |= REG04_LINEART;
 
1121
      break;
 
1122
    case 8:
 
1123
      r->value &= ~(REG04_LINEART | REG04_BITSET);
 
1124
      break;
 
1125
    case 16:
 
1126
      r->value &= ~REG04_LINEART;
 
1127
      r->value |= REG04_BITSET;
 
1128
      break;
 
1129
    }
 
1130
 
 
1131
  r->value &= ~(REG04_FILTER | REG04_AFEMOD);
 
1132
  if (channels == 1)
 
1133
    {
 
1134
      switch (color_filter)
 
1135
        {
 
1136
        case 0:
 
1137
          r->value |= 0x24;     /* red filter */
 
1138
          break;
 
1139
        case 2:
 
1140
          r->value |= 0x2c;     /* blue filter */
 
1141
          break;
 
1142
        default:
 
1143
          r->value |= 0x28;     /* green filter */
 
1144
          break;
 
1145
        }
 
1146
    }
 
1147
  else
 
1148
    r->value |= 0x20;           /* mono */
 
1149
 
 
1150
  /* register 05 */
 
1151
  r = sanei_genesys_get_address (reg, REG05);
 
1152
 
 
1153
  /* set up dpihw */
 
1154
  r->value &= ~REG05_DPIHW;
 
1155
  switch(dpihw)
 
1156
    {
 
1157
      case 600:
 
1158
        r->value |= REG05_DPIHW_600;
 
1159
        break;
 
1160
      case 1200:
 
1161
        r->value |= REG05_DPIHW_1200;
 
1162
        break;
 
1163
      case 2400:
 
1164
        r->value |= REG05_DPIHW_2400;
 
1165
        break;
 
1166
      case 4800:
 
1167
        r->value |= REG05_DPIHW_4800;
 
1168
        break;
 
1169
    }
 
1170
 
 
1171
  /* enable gamma tables */
 
1172
  if (flags & OPTICAL_FLAG_DISABLE_GAMMA)
 
1173
    r->value &= ~REG05_GMMENB;
 
1174
  else
 
1175
    r->value |= REG05_GMMENB;
 
1176
 
 
1177
  /* CIS scanners can do true gray by setting LEDADD */
 
1178
  /* we set up LEDADD only when asked */
 
1179
  if (dev->model->is_cis == SANE_TRUE)
 
1180
    {
 
1181
      r = sanei_genesys_get_address (reg, 0x87);
 
1182
      r->value &= ~REG87_LEDADD;
 
1183
      if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD))
 
1184
        {
 
1185
          r->value |= REG87_LEDADD;
 
1186
        }
 
1187
      /* RGB weighting 
 
1188
      r = sanei_genesys_get_address (reg, 0x01);
 
1189
      r->value &= ~REG01_TRUEGRAY;
 
1190
      if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD))
 
1191
        {
 
1192
          r->value |= REG01_TRUEGRAY;
 
1193
        }*/
 
1194
    }
 
1195
 
 
1196
  /* words(16bit) before gamma, conversion to 8 bit or lineart*/
 
1197
  words_per_line = (used_pixels * dpiset) / dpihw;
 
1198
  bytes=depth/8;
 
1199
  if (depth == 1)
 
1200
    {
 
1201
      words_per_line = (words_per_line+7)/8 ;
 
1202
      dev->len = (dev->len >> 3) + ((dev->len & 7) ? 1 : 0);
 
1203
      dev->dist = (dev->dist >> 3) + ((dev->dist & 7) ? 1 : 0);
 
1204
    }
 
1205
  else
 
1206
    {
 
1207
      words_per_line *= bytes;
 
1208
      dev->dist *= bytes;
 
1209
      dev->len *= bytes;
 
1210
    }
 
1211
 
 
1212
  dev->bpl = words_per_line;
 
1213
  dev->cur=0;
 
1214
  dev->segnb=segnb;
 
1215
  dev->line_interp = 0;
 
1216
 
 
1217
  sanei_genesys_set_double(reg,REG_DPISET,dpiset);
 
1218
  DBG (DBG_io2, "%s: dpiset used=%d\n", __FUNCTION__, dpiset);
 
1219
 
 
1220
  sanei_genesys_set_double(reg,REG_STRPIXEL,startx);
 
1221
  sanei_genesys_set_double(reg,REG_ENDPIXEL,endx);
 
1222
  DBG (DBG_io2, "%s: startx=%d\n", __FUNCTION__, startx);
 
1223
  DBG (DBG_io2, "%s: endx  =%d\n", __FUNCTION__, endx);
 
1224
 
 
1225
  DBG (DBG_io2, "%s: used_pixels=%d\n", __FUNCTION__, used_pixels);
 
1226
  DBG (DBG_io2, "%s: pixels     =%d\n", __FUNCTION__, pixels);
 
1227
  DBG (DBG_io2, "%s: depth      =%d\n", __FUNCTION__, depth);
 
1228
  DBG (DBG_io2, "%s: dev->bpl   =%lu\n", __FUNCTION__, (unsigned long)dev->bpl);
 
1229
  DBG (DBG_io2, "%s: dev->len   =%lu\n", __FUNCTION__, (unsigned long)dev->len);
 
1230
  DBG (DBG_io2, "%s: dev->dist  =%lu\n", __FUNCTION__, (unsigned long)dev->dist);
 
1231
  DBG (DBG_io2, "%s: dev->segnb =%lu\n", __FUNCTION__, (unsigned long)dev->segnb);
 
1232
  
 
1233
  words_per_line *= channels;
 
1234
  dev->wpl = words_per_line;
 
1235
 
 
1236
  if(dev->oe_buffer.buffer!=NULL)
 
1237
    {
 
1238
      sanei_genesys_buffer_free (&(dev->oe_buffer));
 
1239
    }
 
1240
  RIE (sanei_genesys_buffer_alloc (&(dev->oe_buffer), dev->wpl));
 
1241
 
 
1242
  /* MAXWD is expressed in 4 words unit */
 
1243
  sanei_genesys_set_triple(reg, REG_MAXWD, (words_per_line >> 2));
 
1244
  DBG (DBG_io2, "%s: words_per_line used=%d\n", __FUNCTION__, words_per_line);
 
1245
 
 
1246
  sanei_genesys_set_double(reg, REG_LPERIOD, exposure_time);
 
1247
  DBG (DBG_io2, "%s: exposure_time used=%d\n", __FUNCTION__, exposure_time);
 
1248
 
 
1249
  r = sanei_genesys_get_address (reg, 0x34);
 
1250
  r->value = dev->sensor.dummy_pixel;
 
1251
  
 
1252
  DBGCOMPLETED;
 
1253
  return SANE_STATUS_GOOD;
 
1254
}
 
1255
 
 
1256
/* set up registers for an actual scan
 
1257
 *
 
1258
 * this function sets up the scanner to scan in normal or single line mode
 
1259
 */
 
1260
#ifndef UNIT_TESTING
 
1261
static
 
1262
#endif
 
1263
  SANE_Status
 
1264
gl846_init_scan_regs (Genesys_Device * dev,
 
1265
                      Genesys_Register_Set * reg,
 
1266
                      float xres,       /*dpi */
 
1267
                      float yres,       /*dpi */
 
1268
                      float startx,     /*optical_res, from dummy_pixel+1 */
 
1269
                      float starty,     /*base_ydpi, from home! */
 
1270
                      float pixels,
 
1271
                      float lines,
 
1272
                      unsigned int depth,
 
1273
                      unsigned int channels,
 
1274
                      int color_filter,
 
1275
                      unsigned int flags)
 
1276
{
 
1277
  int used_res;
 
1278
  int start, used_pixels;
 
1279
  int bytes_per_line;
 
1280
  int move;
 
1281
  unsigned int lincnt;
 
1282
  unsigned int oflags; /**> optical flags */
 
1283
  unsigned int mflags; /**> motor flags */
 
1284
  int exposure_time;
 
1285
  int stagger;
 
1286
 
 
1287
  int slope_dpi = 0;
 
1288
  int dummy = 0;
 
1289
  int scan_step_type = 1;
 
1290
  int scan_power_mode = 0;
 
1291
  int max_shift;
 
1292
  size_t requested_buffer_size, read_buffer_size;
 
1293
 
 
1294
  SANE_Bool half_ccd;           /* false: full CCD res is used, true, half max CCD res is used */
 
1295
  int optical_res;
 
1296
  SANE_Status status;
 
1297
 
 
1298
  DBG (DBG_info,
 
1299
       "gl846_init_scan_regs settings:\n"
 
1300
       "Resolution    : %gDPI/%gDPI\n"
 
1301
       "Lines         : %g\n"
 
1302
       "PPL           : %g\n"
 
1303
       "Startpos      : %g/%g\n"
 
1304
       "Depth/Channels: %u/%u\n"
 
1305
       "Flags         : %x\n\n",
 
1306
       xres, yres, lines, pixels, startx, starty, depth, channels, flags);
 
1307
 
 
1308
  /* we may have 2 domains for ccd: xres below or above half ccd max dpi */
 
1309
  if (dev->sensor.optical_res < 2 * xres ||
 
1310
      !(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE))
 
1311
    {
 
1312
      half_ccd = SANE_FALSE;
 
1313
    }
 
1314
  else
 
1315
    {
 
1316
      half_ccd = SANE_TRUE;
 
1317
    }
 
1318
 
 
1319
  /* optical_res */
 
1320
  optical_res = dev->sensor.optical_res;
 
1321
  if (half_ccd)
 
1322
    optical_res /= 2;
 
1323
 
 
1324
  /* stagger */
 
1325
  if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE))
 
1326
    stagger = (4 * yres) / dev->motor.base_ydpi;
 
1327
  else
 
1328
    stagger = 0;
 
1329
  DBG (DBG_info, "gl846_init_scan_regs : stagger=%d lines\n", stagger);
 
1330
 
 
1331
  /* used_res */
 
1332
  if (flags & SCAN_FLAG_USE_OPTICAL_RES)
 
1333
    {
 
1334
      used_res = optical_res;
 
1335
    }
 
1336
  else
 
1337
    {
 
1338
      /* resolution is choosen from a list */
 
1339
      used_res = xres;
 
1340
    }
 
1341
 
 
1342
  /* compute scan parameters values */
 
1343
  /* pixels are allways given at full optical resolution */
 
1344
  /* use detected left margin and fixed value */
 
1345
  /* start */
 
1346
  /* add x coordinates */
 
1347
  start = startx;
 
1348
 
 
1349
  if (stagger > 0)
 
1350
    start |= 1;
 
1351
 
 
1352
  /* compute correct pixels number */
 
1353
  /* pixels */
 
1354
  used_pixels = (pixels * optical_res) / xres;
 
1355
 
 
1356
  /* round up pixels number if needed */
 
1357
  if (used_pixels * xres < pixels * optical_res)
 
1358
    used_pixels++;
 
1359
 
 
1360
  dummy = 3-channels;
 
1361
 
 
1362
/* slope_dpi */
 
1363
/* cis color scan is effectively a gray scan with 3 gray lines per color
 
1364
   line and a FILTER of 0 */
 
1365
  if (dev->model->is_cis)
 
1366
    slope_dpi = yres * channels;
 
1367
  else
 
1368
    slope_dpi = yres;
 
1369
 
 
1370
  slope_dpi = slope_dpi * (1 + dummy);
 
1371
 
 
1372
  exposure_time = gl846_compute_exposure (dev, used_res);
 
1373
  scan_step_type = sanei_genesys_compute_step_type(gl846_motors, dev->model->motor_type, exposure_time);
 
1374
 
 
1375
  DBG (DBG_info, "gl846_init_scan_regs : exposure_time=%d pixels\n", exposure_time);
 
1376
  DBG (DBG_info, "gl846_init_scan_regs : scan_step_type=%d\n", scan_step_type);
 
1377
 
 
1378
/*** optical parameters ***/
 
1379
  /* in case of dynamic lineart, we use an internal 8 bit gray scan
 
1380
   * to generate 1 lineart data */
 
1381
  if ((flags & SCAN_FLAG_DYNAMIC_LINEART) && (dev->settings.scan_mode == SCAN_MODE_LINEART))
 
1382
    {
 
1383
      depth = 8;
 
1384
    }
 
1385
 
 
1386
  /* we enable true gray for cis scanners only, and just when doing 
 
1387
   * scan since color calibration is OK for this mode
 
1388
   */
 
1389
  oflags = 0;
 
1390
  if(flags & SCAN_FLAG_DISABLE_SHADING)
 
1391
    oflags |= OPTICAL_FLAG_DISABLE_SHADING;
 
1392
  if(flags & SCAN_FLAG_DISABLE_GAMMA)
 
1393
    oflags |= OPTICAL_FLAG_DISABLE_GAMMA;
 
1394
  if(flags & SCAN_FLAG_DISABLE_LAMP)
 
1395
    oflags |= OPTICAL_FLAG_DISABLE_LAMP;
 
1396
  
 
1397
  if (dev->model->is_cis && dev->settings.true_gray)
 
1398
    {
 
1399
      oflags |= OPTICAL_FLAG_ENABLE_LEDADD;
 
1400
    }
 
1401
 
 
1402
  status = gl846_init_optical_regs_scan (dev,
 
1403
                                         reg,
 
1404
                                         exposure_time,
 
1405
                                         used_res,
 
1406
                                         start,
 
1407
                                         used_pixels,
 
1408
                                         channels,
 
1409
                                         depth,
 
1410
                                         half_ccd,
 
1411
                                         color_filter,
 
1412
                                         oflags);
 
1413
 
 
1414
  if (status != SANE_STATUS_GOOD)
 
1415
    return status;
 
1416
 
 
1417
/*** motor parameters ***/
 
1418
 
 
1419
  /* max_shift */
 
1420
  max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,flags);
 
1421
 
 
1422
  /* lincnt */
 
1423
  lincnt = lines + max_shift + stagger;
 
1424
 
 
1425
  /* add tl_y to base movement */
 
1426
  move = starty;
 
1427
  DBG (DBG_info, "gl846_init_scan_regs: move=%d steps\n", move);
 
1428
 
 
1429
  mflags=0;
 
1430
  if(flags & SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE)
 
1431
    mflags |= MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE;
 
1432
  if(flags & SCAN_FLAG_FEEDING)
 
1433
    mflags |= MOTOR_FLAG_FEED;
 
1434
 
 
1435
    status = gl846_init_motor_regs_scan (dev,
 
1436
                                         reg,
 
1437
                                         exposure_time,
 
1438
                                         slope_dpi,
 
1439
                                         scan_step_type,
 
1440
                                         dev->model->is_cis ? lincnt *
 
1441
                                         channels : lincnt, dummy, move,
 
1442
                                         scan_power_mode,
 
1443
                                         mflags);
 
1444
 
 
1445
  if (status != SANE_STATUS_GOOD)
 
1446
    return status;
 
1447
 
 
1448
 
 
1449
  /*** prepares data reordering ***/
 
1450
 
 
1451
/* words_per_line */
 
1452
  bytes_per_line = (used_pixels * used_res) / optical_res;
 
1453
  bytes_per_line = (bytes_per_line * channels * depth) / 8;
 
1454
 
 
1455
  requested_buffer_size = 8 * bytes_per_line;
 
1456
  /* we must use a round number of bytes_per_line */
 
1457
  /* XXX STEF XXX
 
1458
  if (requested_buffer_size > BULKIN_MAXSIZE)
 
1459
    requested_buffer_size =
 
1460
      (BULKIN_MAXSIZE / bytes_per_line) * bytes_per_line;
 
1461
  */
 
1462
 
 
1463
  read_buffer_size =
 
1464
    2 * requested_buffer_size +
 
1465
    ((max_shift + stagger) * used_pixels * channels * depth) / 8;
 
1466
 
 
1467
  RIE (sanei_genesys_buffer_free (&(dev->read_buffer)));
 
1468
  RIE (sanei_genesys_buffer_alloc (&(dev->read_buffer), read_buffer_size));
 
1469
 
 
1470
  RIE (sanei_genesys_buffer_free (&(dev->lines_buffer)));
 
1471
  RIE (sanei_genesys_buffer_alloc (&(dev->lines_buffer), read_buffer_size));
 
1472
 
 
1473
  RIE (sanei_genesys_buffer_free (&(dev->shrink_buffer)));
 
1474
  RIE (sanei_genesys_buffer_alloc (&(dev->shrink_buffer),
 
1475
                                   requested_buffer_size));
 
1476
 
 
1477
  RIE (sanei_genesys_buffer_free (&(dev->out_buffer)));
 
1478
  RIE (sanei_genesys_buffer_alloc (&(dev->out_buffer),
 
1479
                                   (8 * dev->settings.pixels * channels *
 
1480
                                    depth) / 8));
 
1481
 
 
1482
 
 
1483
  dev->read_bytes_left = bytes_per_line * lincnt;
 
1484
 
 
1485
  DBG (DBG_info,
 
1486
       "gl846_init_scan_regs: physical bytes to read = %lu\n",
 
1487
       (u_long) dev->read_bytes_left);
 
1488
  dev->read_active = SANE_TRUE;
 
1489
 
 
1490
 
 
1491
  dev->current_setup.pixels = (used_pixels * used_res) / optical_res;
 
1492
  dev->current_setup.lines = lincnt;
 
1493
  dev->current_setup.depth = depth;
 
1494
  dev->current_setup.channels = channels;
 
1495
  dev->current_setup.exposure_time = exposure_time;
 
1496
  dev->current_setup.xres = used_res;
 
1497
  dev->current_setup.yres = yres;
 
1498
  dev->current_setup.half_ccd = half_ccd;
 
1499
  dev->current_setup.stagger = stagger;
 
1500
  dev->current_setup.max_shift = max_shift + stagger;
 
1501
 
 
1502
/* TODO: should this be done elsewhere? */
 
1503
  /* scan bytes to send to the frontend */
 
1504
  /* theory :
 
1505
     target_size =
 
1506
     (dev->settings.pixels * dev->settings.lines * channels * depth) / 8;
 
1507
     but it suffers from integer overflow so we do the following: 
 
1508
 
 
1509
     1 bit color images store color data byte-wise, eg byte 0 contains 
 
1510
     8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains 
 
1511
     8 bits of blue.
 
1512
     This does not fix the overflow, though. 
 
1513
     644mp*16 = 10gp, leading to an overflow
 
1514
     -- pierre
 
1515
   */
 
1516
 
 
1517
  dev->total_bytes_read = 0;
 
1518
  if (depth == 1)
 
1519
    dev->total_bytes_to_read =
 
1520
      ((dev->settings.pixels * dev->settings.lines) / 8 +
 
1521
       (((dev->settings.pixels * dev->settings.lines) % 8) ? 1 : 0)) *
 
1522
      channels;
 
1523
  else
 
1524
    dev->total_bytes_to_read =
 
1525
      dev->settings.pixels * dev->settings.lines * channels * (depth / 8);
 
1526
 
 
1527
  DBG (DBG_info, "gl846_init_scan_regs: total bytes to send = %lu\n",
 
1528
       (u_long) dev->total_bytes_to_read);
 
1529
/* END TODO */
 
1530
 
 
1531
  DBGCOMPLETED;
 
1532
  return SANE_STATUS_GOOD;
 
1533
}
 
1534
 
 
1535
static SANE_Status
 
1536
gl846_calculate_current_setup (Genesys_Device * dev)
 
1537
{
 
1538
  int channels;
 
1539
  int depth;
 
1540
  int start;
 
1541
 
 
1542
  float xres;                   /*dpi */
 
1543
  float yres;                   /*dpi */
 
1544
  float startx;                 /*optical_res, from dummy_pixel+1 */
 
1545
  float pixels;
 
1546
  float lines;
 
1547
 
 
1548
  int used_res;
 
1549
  int used_pixels;
 
1550
  unsigned int lincnt;
 
1551
  int exposure_time;
 
1552
  int stagger;
 
1553
 
 
1554
  int slope_dpi;
 
1555
  int dummy = 0;
 
1556
  int max_shift;
 
1557
 
 
1558
  SANE_Bool half_ccd;           /* false: full CCD res is used, true, half max CCD res is used */
 
1559
  int optical_res;
 
1560
 
 
1561
  DBG (DBG_info,
 
1562
       "gl846_calculate_current_setup settings:\n"
 
1563
       "Resolution: %uDPI\n"
 
1564
       "Lines     : %u\n"
 
1565
       "PPL       : %u\n"
 
1566
       "Startpos  : %.3f/%.3f\n"
 
1567
       "Scan mode : %d\n\n",
 
1568
       dev->settings.yres, dev->settings.lines, dev->settings.pixels,
 
1569
       dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode);
 
1570
 
 
1571
  /* channels */
 
1572
  if (dev->settings.scan_mode == 4)     /* single pass color */
 
1573
    channels = 3;
 
1574
  else
 
1575
    channels = 1;
 
1576
 
 
1577
  /* depth */
 
1578
  depth = dev->settings.depth;
 
1579
  if (dev->settings.scan_mode == 0)
 
1580
    depth = 1;
 
1581
 
 
1582
  /* start */
 
1583
  start = SANE_UNFIX (dev->model->x_offset);
 
1584
  start += dev->settings.tl_x;
 
1585
  start = (start * dev->sensor.optical_res) / MM_PER_INCH;
 
1586
 
 
1587
 
 
1588
  xres = dev->settings.xres;    /*dpi */
 
1589
  yres = dev->settings.yres;    /*dpi */
 
1590
  startx = start;               /*optical_res, from dummy_pixel+1 */
 
1591
  pixels = dev->settings.pixels;
 
1592
  lines = dev->settings.lines;
 
1593
 
 
1594
  DBG (DBG_info,
 
1595
       "gl846_calculate_current_setup settings:\n"
 
1596
       "Resolution    : %gDPI/%gDPI\n"
 
1597
       "Lines         : %g\n"
 
1598
       "PPL           : %g\n"
 
1599
       "Startpos      : %g\n"
 
1600
       "Depth/Channels: %u/%u\n\n",
 
1601
       xres, yres, lines, pixels, startx, depth, channels);
 
1602
 
 
1603
/* half_ccd */
 
1604
  /* we have 2 domains for ccd: xres below or above half ccd max dpi */
 
1605
  if ((dev->sensor.optical_res < 2 * xres) ||
 
1606
      !(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE))
 
1607
    {
 
1608
      half_ccd = SANE_FALSE;
 
1609
    }
 
1610
  else
 
1611
    {
 
1612
      half_ccd = SANE_TRUE;
 
1613
    }
 
1614
 
 
1615
  /* optical_res */
 
1616
  optical_res = dev->sensor.optical_res;
 
1617
 
 
1618
  /* stagger */
 
1619
  if (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)
 
1620
    stagger = (4 * yres) / dev->motor.base_ydpi;
 
1621
  else
 
1622
    stagger = 0;
 
1623
  DBG (DBG_info, "gl846_calculate_current_setup: stagger=%d lines\n",
 
1624
       stagger);
 
1625
 
 
1626
  /* resolution is choosen from a fixed list */
 
1627
  used_res = xres;
 
1628
 
 
1629
  /* compute scan parameters values */
 
1630
  /* pixels are allways given at half or full CCD optical resolution */
 
1631
  /* use detected left margin  and fixed value */
 
1632
 
 
1633
  /* compute correct pixels number */
 
1634
  used_pixels = (pixels * optical_res) / used_res;
 
1635
  dummy = 3-channels;
 
1636
 
 
1637
  /* slope_dpi */
 
1638
  /* cis color scan is effectively a gray scan with 3 gray lines per color
 
1639
   line and a FILTER of 0 */
 
1640
  if (dev->model->is_cis)
 
1641
    slope_dpi = yres * channels;
 
1642
  else
 
1643
    slope_dpi = yres;
 
1644
 
 
1645
  slope_dpi = slope_dpi * (1 + dummy);
 
1646
 
 
1647
  exposure_time = gl846_compute_exposure (dev, used_res);
 
1648
  DBG (DBG_info, "%s : exposure_time=%d pixels\n", __FUNCTION__, exposure_time);
 
1649
 
 
1650
  /* max_shift */
 
1651
  max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,0);
 
1652
 
 
1653
  /* lincnt */
 
1654
  lincnt = lines + max_shift + stagger;
 
1655
 
 
1656
  dev->current_setup.pixels = (used_pixels * used_res) / optical_res;
 
1657
  dev->current_setup.lines = lincnt;
 
1658
  dev->current_setup.depth = depth;
 
1659
  dev->current_setup.channels = channels;
 
1660
  dev->current_setup.exposure_time = exposure_time;
 
1661
  dev->current_setup.xres = used_res;
 
1662
  dev->current_setup.yres = yres;
 
1663
  dev->current_setup.half_ccd = half_ccd;
 
1664
  dev->current_setup.stagger = stagger;
 
1665
  dev->current_setup.max_shift = max_shift + stagger;
 
1666
 
 
1667
  DBGCOMPLETED;
 
1668
  return SANE_STATUS_GOOD;
 
1669
}
 
1670
 
 
1671
static void
 
1672
gl846_set_motor_power (Genesys_Register_Set * regs, SANE_Bool set)
 
1673
{
 
1674
 
 
1675
  DBG (DBG_proc, "gl846_set_motor_power\n");
 
1676
 
 
1677
  if (set)
 
1678
    {
 
1679
      sanei_genesys_set_reg_from_set (regs, REG02,
 
1680
                                      sanei_genesys_read_reg_from_set (regs,
 
1681
                                                                       REG02)
 
1682
                                      | REG02_MTRPWR);
 
1683
    }
 
1684
  else
 
1685
    {
 
1686
      sanei_genesys_set_reg_from_set (regs, REG02,
 
1687
                                      sanei_genesys_read_reg_from_set (regs,
 
1688
                                                                       REG02)
 
1689
                                      & ~REG02_MTRPWR);
 
1690
    }
 
1691
}
 
1692
 
 
1693
static void
 
1694
gl846_set_lamp_power (Genesys_Device __sane_unused__ * dev,
 
1695
                      Genesys_Register_Set * regs, SANE_Bool set)
 
1696
{
 
1697
  if (set)
 
1698
    {
 
1699
      sanei_genesys_set_reg_from_set (regs, REG03,
 
1700
                                      sanei_genesys_read_reg_from_set (regs, REG03)
 
1701
                                      | REG03_LAMPPWR);
 
1702
    }
 
1703
  else
 
1704
    {
 
1705
      sanei_genesys_set_reg_from_set (regs, REG03,
 
1706
                                      sanei_genesys_read_reg_from_set (regs, REG03)
 
1707
                                      & ~REG03_LAMPPWR);
 
1708
    }
 
1709
}
 
1710
 
 
1711
/*for fast power saving methods only, like disabling certain amplifiers*/
 
1712
static SANE_Status
 
1713
gl846_save_power (Genesys_Device * dev, SANE_Bool enable)
 
1714
{
 
1715
  DBG (DBG_proc, "gl846_save_power: enable = %d\n", enable);
 
1716
  if (dev == NULL)
 
1717
    return SANE_STATUS_INVAL;
 
1718
 
 
1719
  DBGCOMPLETED;
 
1720
  return SANE_STATUS_GOOD;
 
1721
}
 
1722
 
 
1723
static SANE_Status
 
1724
gl846_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ )
 
1725
{
 
1726
  DBG (DBG_proc, "gl846_set_powersaving (delay = %d)\n", delay);
 
1727
  if (dev == NULL)
 
1728
    return SANE_STATUS_INVAL;
 
1729
 
 
1730
  DBGCOMPLETED;
 
1731
  return SANE_STATUS_GOOD;
 
1732
}
 
1733
 
 
1734
static SANE_Status
 
1735
gl846_start_action (Genesys_Device * dev)
 
1736
{
 
1737
  return sanei_genesys_write_register (dev, 0x0f, 0x01);
 
1738
}
 
1739
 
 
1740
#ifndef UNIT_TESTING
 
1741
static
 
1742
#endif
 
1743
SANE_Status
 
1744
gl846_stop_action (Genesys_Device * dev)
 
1745
{
 
1746
  SANE_Status status;
 
1747
  uint8_t val40, val;
 
1748
  unsigned int loop;
 
1749
 
 
1750
  DBGSTART;
 
1751
 
 
1752
  /* post scan gpio : without that HOMSNR is unreliable */
 
1753
  gl846_homsnr_gpio(dev);
 
1754
  status = sanei_genesys_get_status (dev, &val);
 
1755
  if (DBG_LEVEL >= DBG_io)
 
1756
    {
 
1757
      sanei_genesys_print_status (val);
 
1758
    }
 
1759
 
 
1760
  status = sanei_genesys_read_register (dev, REG40, &val40);
 
1761
  if (status != SANE_STATUS_GOOD)
 
1762
    {
 
1763
      DBG (DBG_error,
 
1764
           "%s: failed to read home sensor: %s\n", __FUNCTION__,
 
1765
           sane_strstatus (status));
 
1766
      DBGCOMPLETED;
 
1767
      return status;
 
1768
    }
 
1769
 
 
1770
  /* only stop action if needed */
 
1771
  if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG))
 
1772
    {
 
1773
      DBG (DBG_info, "%s: already stopped\n", __FUNCTION__);
 
1774
      DBGCOMPLETED;
 
1775
      return SANE_STATUS_GOOD;
 
1776
    }
 
1777
 
 
1778
  /* ends scan */
 
1779
  val = sanei_genesys_read_reg_from_set (dev->reg, REG01);
 
1780
  val &= ~REG01_SCAN;
 
1781
  sanei_genesys_set_reg_from_set (dev->reg, REG01, val);
 
1782
  status = sanei_genesys_write_register (dev, REG01, val);
 
1783
  if (status != SANE_STATUS_GOOD)
 
1784
    {
 
1785
      DBG (DBG_error,
 
1786
           "%s: failed to write register 01: %s\n", __FUNCTION__,
 
1787
           sane_strstatus (status));
 
1788
      return status;
 
1789
    }
 
1790
  usleep (100 * 1000);
 
1791
 
 
1792
  loop = 10;
 
1793
  while (loop > 0)
 
1794
    {
 
1795
      status = sanei_genesys_get_status (dev, &val);
 
1796
      if (DBG_LEVEL >= DBG_io)
 
1797
        {
 
1798
          sanei_genesys_print_status (val);
 
1799
        }
 
1800
      status = sanei_genesys_read_register (dev, REG40, &val40);
 
1801
      if (status != SANE_STATUS_GOOD)
 
1802
        {
 
1803
          DBG (DBG_error,
 
1804
               "%s: failed to read home sensor: %s\n", __FUNCTION__,
 
1805
               sane_strstatus (status));
 
1806
          DBGCOMPLETED;
 
1807
          return status;
 
1808
        }
 
1809
 
 
1810
      /* if scanner is in command mode, we are done */
 
1811
      if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG)
 
1812
          && !(val & REG41_MOTORENB))
 
1813
        {
 
1814
          DBGCOMPLETED;
 
1815
          return SANE_STATUS_GOOD;
 
1816
        }
 
1817
 
 
1818
      usleep (100 * 1000);
 
1819
      loop--;
 
1820
    }
 
1821
 
 
1822
  DBGCOMPLETED;
 
1823
  return SANE_STATUS_IO_ERROR;
 
1824
}
 
1825
 
 
1826
/* Send the low-level scan command */
 
1827
#ifndef UNIT_TESTING
 
1828
static
 
1829
#endif
 
1830
  SANE_Status
 
1831
gl846_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg,
 
1832
                  SANE_Bool start_motor)
 
1833
{
 
1834
  SANE_Status status;
 
1835
  uint8_t val;
 
1836
  Genesys_Register_Set *r;
 
1837
 
 
1838
  DBGSTART;
 
1839
 
 
1840
  /* XXX STEF XXX SCAN GPIO */
 
1841
  /*
 
1842
  RIE (sanei_genesys_read_register (dev, REG6C, &val));
 
1843
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
1844
  */
 
1845
 
 
1846
  val = REG0D_CLRLNCNT;
 
1847
  RIE (sanei_genesys_write_register (dev, REG0D, val));
 
1848
  val = REG0D_CLRMCNT;
 
1849
  RIE (sanei_genesys_write_register (dev, REG0D, val));
 
1850
 
 
1851
  RIE (sanei_genesys_read_register (dev, REG01, &val));
 
1852
  val |= REG01_SCAN;
 
1853
  RIE (sanei_genesys_write_register (dev, REG01, val));
 
1854
  r = sanei_genesys_get_address (reg, REG01);
 
1855
  r->value = val;
 
1856
 
 
1857
  if (start_motor)
 
1858
    {
 
1859
      RIE (sanei_genesys_write_register (dev, REG0F, 1));
 
1860
    }
 
1861
  else
 
1862
    {
 
1863
      RIE (sanei_genesys_write_register (dev, REG0F, 0));
 
1864
    }
 
1865
 
 
1866
  DBGCOMPLETED;
 
1867
 
 
1868
  return status;
 
1869
}
 
1870
 
 
1871
 
 
1872
/* Send the stop scan command */
 
1873
#ifndef UNIT_TESTING
 
1874
static
 
1875
#endif
 
1876
  SANE_Status
 
1877
gl846_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg,
 
1878
                SANE_Bool check_stop)
 
1879
{
 
1880
  SANE_Status status;
 
1881
 
 
1882
  DBG (DBG_proc, "gl846_end_scan (check_stop = %d)\n", check_stop);
 
1883
  if (reg == NULL)
 
1884
    return SANE_STATUS_INVAL;
 
1885
 
 
1886
  if (dev->model->is_sheetfed == SANE_TRUE)
 
1887
    {
 
1888
      status = SANE_STATUS_GOOD;
 
1889
    }
 
1890
  else                          /* flat bed scanners */
 
1891
    {
 
1892
      status = gl846_stop_action (dev);
 
1893
      if (status != SANE_STATUS_GOOD)
 
1894
        {
 
1895
          DBG (DBG_error,
 
1896
               "gl846_end_scan: failed to stop: %s\n",
 
1897
               sane_strstatus (status));
 
1898
          return status;
 
1899
        }
 
1900
    }
 
1901
 
 
1902
  DBGCOMPLETED;
 
1903
  return status;
 
1904
}
 
1905
 
 
1906
/* Moves the slider to the home (top) postion slowly */
 
1907
#ifndef UNIT_TESTING
 
1908
static
 
1909
#endif
 
1910
SANE_Status
 
1911
gl846_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home)
 
1912
{
 
1913
  Genesys_Register_Set local_reg[GENESYS_GL846_MAX_REGS];
 
1914
  SANE_Status status;
 
1915
  Genesys_Register_Set *r;
 
1916
  float resolution;
 
1917
  uint8_t val;
 
1918
  int loop = 0;
 
1919
  int scan_mode;
 
1920
 
 
1921
  DBG (DBG_proc, "gl846_slow_back_home (wait_until_home = %d)\n",
 
1922
       wait_until_home);
 
1923
 
 
1924
  if(dev->usb_mode<0)
 
1925
    {
 
1926
      DBGCOMPLETED;
 
1927
      return SANE_STATUS_GOOD;
 
1928
    }
 
1929
 
 
1930
  /* post scan gpio : without that HOMSNR is unreliable */
 
1931
  gl846_homsnr_gpio(dev);
 
1932
 
 
1933
  /* first read gives HOME_SENSOR true */
 
1934
  status = sanei_genesys_get_status (dev, &val);
 
1935
  if (status != SANE_STATUS_GOOD)
 
1936
    {
 
1937
      DBG (DBG_error,
 
1938
           "gl846_slow_back_home: failed to read home sensor: %s\n",
 
1939
           sane_strstatus (status));
 
1940
      return status;
 
1941
    }
 
1942
  if (DBG_LEVEL >= DBG_io)
 
1943
    {
 
1944
      sanei_genesys_print_status (val);
 
1945
    }
 
1946
  usleep (100000);              /* sleep 100 ms */
 
1947
 
 
1948
  /* second is reliable */
 
1949
  status = sanei_genesys_get_status (dev, &val);
 
1950
  if (status != SANE_STATUS_GOOD)
 
1951
    {
 
1952
      DBG (DBG_error,
 
1953
           "gl846_slow_back_home: failed to read home sensor: %s\n",
 
1954
           sane_strstatus (status));
 
1955
      return status;
 
1956
    }
 
1957
  if (DBG_LEVEL >= DBG_io)
 
1958
    {
 
1959
      sanei_genesys_print_status (val);
 
1960
    }
 
1961
 
 
1962
  /* is sensor at home? */
 
1963
  if (val & HOMESNR)
 
1964
    {
 
1965
      DBG (DBG_info, "%s: already at home, completed\n", __FUNCTION__);
 
1966
      dev->scanhead_position_in_steps = 0;
 
1967
      DBGCOMPLETED;
 
1968
      return SANE_STATUS_GOOD;
 
1969
    }
 
1970
 
 
1971
  memcpy (local_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
 
1972
  
 
1973
  resolution=sanei_genesys_get_lowest_ydpi(dev);
 
1974
  
 
1975
  /* TODO add scan_mode to the API */
 
1976
  scan_mode= dev->settings.scan_mode;
 
1977
  dev->settings.scan_mode=SCAN_MODE_LINEART;
 
1978
  gl846_init_scan_regs (dev,
 
1979
                        local_reg,
 
1980
                        resolution,
 
1981
                        resolution,
 
1982
                        100,
 
1983
                        30000,
 
1984
                        100,
 
1985
                        100,
 
1986
                        8,
 
1987
                        1,
 
1988
                        0,
 
1989
                        SCAN_FLAG_DISABLE_SHADING |
 
1990
                        SCAN_FLAG_DISABLE_GAMMA |
 
1991
                        SCAN_FLAG_IGNORE_LINE_DISTANCE);
 
1992
  dev->settings.scan_mode=scan_mode;
 
1993
 
 
1994
  /* clear scan and feed count */
 
1995
  RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT));
 
1996
  
 
1997
  /* set up for reverse */
 
1998
  r = sanei_genesys_get_address (local_reg, REG02);
 
1999
  r->value |= REG02_MTRREV;
 
2000
 
 
2001
  RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS));
 
2002
 
 
2003
  status = gl846_start_action (dev);
 
2004
  if (status != SANE_STATUS_GOOD)
 
2005
    {
 
2006
      DBG (DBG_error,
 
2007
           "gl846_slow_back_home: failed to start motor: %s\n",
 
2008
           sane_strstatus (status));
 
2009
      gl846_stop_action (dev);
 
2010
      /* send original registers */
 
2011
      dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL846_MAX_REGS);
 
2012
      return status;
 
2013
    }
 
2014
 
 
2015
  /* post scan gpio : without that HOMSNR is unreliable */
 
2016
  gl846_homsnr_gpio(dev);
 
2017
 
 
2018
  if (wait_until_home)
 
2019
    {
 
2020
      while (loop < 300)        /* do not wait longer then 30 seconds */
 
2021
        {
 
2022
          status = sanei_genesys_get_status (dev, &val);
 
2023
          if (status != SANE_STATUS_GOOD)
 
2024
            {
 
2025
              DBG (DBG_error,
 
2026
                   "gl846_slow_back_home: failed to read home sensor: %s\n",
 
2027
                   sane_strstatus (status));
 
2028
              return status;
 
2029
            }
 
2030
 
 
2031
          if (val & HOMESNR)    /* home sensor */
 
2032
            {
 
2033
              DBG (DBG_info, "gl846_slow_back_home: reached home position\n");
 
2034
              gl846_stop_action (dev);
 
2035
              dev->scanhead_position_in_steps = 0;
 
2036
              DBGCOMPLETED;
 
2037
              return SANE_STATUS_GOOD;
 
2038
            }
 
2039
          usleep (100000);      /* sleep 100 ms */
 
2040
          ++loop;
 
2041
        }
 
2042
 
 
2043
      /* when we come here then the scanner needed too much time for this, so we better stop the motor */
 
2044
      gl846_stop_action (dev);
 
2045
      DBG (DBG_error,
 
2046
           "gl846_slow_back_home: timeout while waiting for scanhead to go home\n");
 
2047
      return SANE_STATUS_IO_ERROR;
 
2048
    }
 
2049
 
 
2050
  DBG (DBG_info, "gl846_slow_back_home: scanhead is still moving\n");
 
2051
  DBGCOMPLETED;
 
2052
  return SANE_STATUS_GOOD;
 
2053
}
 
2054
 
 
2055
/* Automatically set top-left edge of the scan area by scanning a 200x200 pixels
 
2056
   area at 600 dpi from very top of scanner */
 
2057
static SANE_Status
 
2058
gl846_search_start_position (Genesys_Device * dev)
 
2059
{
 
2060
  int size;
 
2061
  SANE_Status status;
 
2062
  uint8_t *data;
 
2063
  Genesys_Register_Set local_reg[GENESYS_GL846_MAX_REGS];
 
2064
  int steps;
 
2065
 
 
2066
  int pixels = 600;
 
2067
  int dpi = 300;
 
2068
 
 
2069
  DBG (DBG_proc, "gl846_search_start_position\n");
 
2070
 
 
2071
  memcpy (local_reg, dev->reg,
 
2072
          GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
 
2073
 
 
2074
  /* sets for a 200 lines * 600 pixels */
 
2075
  /* normal scan with no shading */
 
2076
 
 
2077
  status = gl846_init_scan_regs (dev, local_reg, dpi, dpi, 0, 0,        /*we should give a small offset here~60 steps */
 
2078
                                 600, dev->model->search_lines, 8, 1, 1,        /*green */
 
2079
                                 SCAN_FLAG_DISABLE_SHADING |
 
2080
                                 SCAN_FLAG_DISABLE_GAMMA |
 
2081
                                 SCAN_FLAG_IGNORE_LINE_DISTANCE);
 
2082
  if (status != SANE_STATUS_GOOD)
 
2083
    {
 
2084
      DBG (DBG_error,
 
2085
           "gl846_search_start_position: failed to set up registers: %s\n",
 
2086
           sane_strstatus (status));
 
2087
      DBGCOMPLETED;
 
2088
      return status;
 
2089
    }
 
2090
 
 
2091
  /* send to scanner */
 
2092
  status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS);
 
2093
  if (status != SANE_STATUS_GOOD)
 
2094
    {
 
2095
      DBG (DBG_error,
 
2096
           "gl846_search_start_position: failed to bulk write registers: %s\n",
 
2097
           sane_strstatus (status));
 
2098
      DBGCOMPLETED;
 
2099
      return status;
 
2100
    }
 
2101
 
 
2102
  size = pixels * dev->model->search_lines;
 
2103
 
 
2104
  data = malloc (size);
 
2105
  if (!data)
 
2106
    {
 
2107
      DBG (DBG_error,
 
2108
           "gl846_search_start_position: failed to allocate memory\n");
 
2109
      return SANE_STATUS_NO_MEM;
 
2110
    }
 
2111
 
 
2112
  status = gl846_begin_scan (dev, local_reg, SANE_TRUE);
 
2113
  if (status != SANE_STATUS_GOOD)
 
2114
    {
 
2115
      free (data);
 
2116
      DBG (DBG_error,
 
2117
           "gl846_search_start_position: failed to begin scan: %s\n",
 
2118
           sane_strstatus (status));
 
2119
      return status;
 
2120
    }
 
2121
 
 
2122
  /* waits for valid data */
 
2123
  do
 
2124
    sanei_genesys_test_buffer_empty (dev, &steps);
 
2125
  while (steps);
 
2126
 
 
2127
  /* now we're on target, we can read data */
 
2128
  status = sanei_genesys_read_data_from_scanner (dev, data, size);
 
2129
  if (status != SANE_STATUS_GOOD)
 
2130
    {
 
2131
      free (data);
 
2132
      DBG (DBG_error,
 
2133
           "gl846_search_start_position: failed to read data: %s\n",
 
2134
           sane_strstatus (status));
 
2135
      return status;
 
2136
    }
 
2137
 
 
2138
  if (DBG_LEVEL >= DBG_data)
 
2139
    sanei_genesys_write_pnm_file ("search_position.pnm", data, 8, 1, pixels,
 
2140
                                  dev->model->search_lines);
 
2141
 
 
2142
  status = gl846_end_scan (dev, local_reg, SANE_TRUE);
 
2143
  if (status != SANE_STATUS_GOOD)
 
2144
    {
 
2145
      free (data);
 
2146
      DBG (DBG_error,
 
2147
           "gl846_search_start_position: failed to end scan: %s\n",
 
2148
           sane_strstatus (status));
 
2149
      return status;
 
2150
    }
 
2151
 
 
2152
  /* update regs to copy ASIC internal state */
 
2153
  memcpy (dev->reg, local_reg,
 
2154
          GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
 
2155
 
 
2156
/*TODO: find out where sanei_genesys_search_reference_point 
 
2157
  stores information, and use that correctly*/
 
2158
  status =
 
2159
    sanei_genesys_search_reference_point (dev, data, 0, dpi, pixels,
 
2160
                                          dev->model->search_lines);
 
2161
  if (status != SANE_STATUS_GOOD)
 
2162
    {
 
2163
      free (data);
 
2164
      DBG (DBG_error,
 
2165
           "gl846_search_start_position: failed to set search reference point: %s\n",
 
2166
           sane_strstatus (status));
 
2167
      return status;
 
2168
    }
 
2169
 
 
2170
  free (data);
 
2171
  return SANE_STATUS_GOOD;
 
2172
}
 
2173
 
 
2174
/* 
 
2175
 * sets up register for coarse gain calibration
 
2176
 * todo: check it for scanners using it */
 
2177
static SANE_Status
 
2178
gl846_init_regs_for_coarse_calibration (Genesys_Device * dev)
 
2179
{
 
2180
  SANE_Status status;
 
2181
  uint8_t channels;
 
2182
  uint8_t cksel;
 
2183
 
 
2184
  DBG (DBG_proc, "gl846_init_regs_for_coarse_calibration\n");
 
2185
 
 
2186
 
 
2187
  cksel = (dev->calib_reg[reg_0x18].value & REG18_CKSEL) + 1;   /* clock speed = 1..4 clocks */
 
2188
 
 
2189
  /* set line size */
 
2190
  if (dev->settings.scan_mode == SCAN_MODE_COLOR)       /* single pass color */
 
2191
    channels = 3;
 
2192
  else
 
2193
    channels = 1;
 
2194
 
 
2195
  status = gl846_init_scan_regs (dev,
 
2196
                                 dev->calib_reg,
 
2197
                                 dev->settings.xres,
 
2198
                                 dev->settings.yres,
 
2199
                                 0,
 
2200
                                 0,
 
2201
                                 dev->sensor.optical_res / cksel,
 
2202
                                 20,
 
2203
                                 16,
 
2204
                                 channels,
 
2205
                                 dev->settings.color_filter,
 
2206
                                 SCAN_FLAG_DISABLE_SHADING |
 
2207
                                 SCAN_FLAG_DISABLE_GAMMA |
 
2208
                                 SCAN_FLAG_SINGLE_LINE |
 
2209
                                 SCAN_FLAG_IGNORE_LINE_DISTANCE);
 
2210
  if (status != SANE_STATUS_GOOD)
 
2211
    {
 
2212
      DBG (DBG_error,
 
2213
           "gl846_init_register_for_coarse_calibration: Failed to setup scan: %s\n",
 
2214
           sane_strstatus (status));
 
2215
      return status;
 
2216
    }
 
2217
 
 
2218
  DBG (DBG_info,
 
2219
       "gl846_init_register_for_coarse_calibration: optical sensor res: %d dpi, actual res: %d\n",
 
2220
       dev->sensor.optical_res / cksel, dev->settings.xres);
 
2221
 
 
2222
  status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS);
 
2223
  if (status != SANE_STATUS_GOOD)
 
2224
    {
 
2225
      DBG (DBG_error,
 
2226
           "gl846_init_register_for_coarse_calibration: Failed to bulk write registers: %s\n",
 
2227
           sane_strstatus (status));
 
2228
      return status;
 
2229
    }
 
2230
 
 
2231
  DBGCOMPLETED;
 
2232
  return SANE_STATUS_GOOD;
 
2233
}
 
2234
 
 
2235
/** @brief moves the slider to steps at motor base dpi
 
2236
 * @param dev device to work on
 
2237
 * @param steps number of steps to move in base_dpi line count
 
2238
 * */
 
2239
#ifndef UNIT_TESTING
 
2240
static
 
2241
#endif
 
2242
SANE_Status
 
2243
gl846_feed (Genesys_Device * dev, unsigned int steps)
 
2244
{
 
2245
  Genesys_Register_Set local_reg[GENESYS_GL846_MAX_REGS];
 
2246
  SANE_Status status;
 
2247
  Genesys_Register_Set *r;
 
2248
  float resolution;
 
2249
  uint8_t val;
 
2250
 
 
2251
  DBGSTART;
 
2252
  DBG (DBG_io, "%s: steps=%d\n", __FUNCTION__, steps);
 
2253
 
 
2254
  /* prepare local registers */
 
2255
  memcpy (local_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
 
2256
 
 
2257
  resolution=sanei_genesys_get_lowest_ydpi(dev);
 
2258
  gl846_init_scan_regs (dev,
 
2259
                        local_reg,
 
2260
                        resolution,
 
2261
                        resolution,
 
2262
                        0,
 
2263
                        steps,
 
2264
                        100,
 
2265
                        3,
 
2266
                        8,
 
2267
                        3,
 
2268
                        dev->settings.color_filter,
 
2269
                        SCAN_FLAG_DISABLE_SHADING |
 
2270
                        SCAN_FLAG_DISABLE_GAMMA |
 
2271
                        SCAN_FLAG_FEEDING |
 
2272
                        SCAN_FLAG_IGNORE_LINE_DISTANCE);
 
2273
 
 
2274
  /* set exposure to zero */
 
2275
  sanei_genesys_set_triple(local_reg,REG_EXPR,0);
 
2276
  sanei_genesys_set_triple(local_reg,REG_EXPG,0);
 
2277
  sanei_genesys_set_triple(local_reg,REG_EXPB,0);
 
2278
 
 
2279
  /* clear scan and feed count */
 
2280
  RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT));
 
2281
  RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRMCNT));
 
2282
  
 
2283
  /* set up for no scan */
 
2284
  r = sanei_genesys_get_address (local_reg, REG01);
 
2285
  r->value &= ~REG01_SCAN;
 
2286
  
 
2287
  /* send registers */
 
2288
  RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS));
 
2289
 
 
2290
  status = gl846_start_action (dev);
 
2291
  if (status != SANE_STATUS_GOOD)
 
2292
    {
 
2293
      DBG (DBG_error, "%s: failed to start motor: %s\n", __FUNCTION__, sane_strstatus (status));
 
2294
      gl846_stop_action (dev);
 
2295
 
 
2296
      /* restore original registers */
 
2297
      dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL846_MAX_REGS);
 
2298
      return status;
 
2299
    }
 
2300
 
 
2301
  /* wait until feed count reaches the required value, but do not
 
2302
   * exceed 30s */
 
2303
  do
 
2304
    {
 
2305
          status = sanei_genesys_get_status (dev, &val);
 
2306
    }
 
2307
  while (status == SANE_STATUS_GOOD && !(val & FEEDFSH));
 
2308
 
 
2309
  /* then stop scanning */
 
2310
  RIE(gl846_stop_action (dev));
 
2311
  
 
2312
  DBGCOMPLETED;
 
2313
  return SANE_STATUS_GOOD;
 
2314
}
 
2315
 
 
2316
 
 
2317
/* init registers for shading calibration */
 
2318
static SANE_Status
 
2319
gl846_init_regs_for_shading (Genesys_Device * dev)
 
2320
{
 
2321
  SANE_Status status;
 
2322
  float move;
 
2323
 
 
2324
  DBGSTART;
 
2325
  dev->calib_channels = 3;
 
2326
 
 
2327
  /* initial calibration reg values */
 
2328
  memcpy (dev->calib_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
 
2329
 
 
2330
  dev->calib_resolution = sanei_genesys_compute_dpihw(dev,dev->settings.xres);
 
2331
  dev->calib_lines = dev->model->shading_lines;
 
2332
  if(dev->calib_resolution==4800)
 
2333
    dev->calib_lines *= 2;
 
2334
  dev->calib_pixels = (dev->sensor.sensor_pixels*dev->calib_resolution)/dev->sensor.optical_res;
 
2335
  DBG (DBG_io, "%s: calib_lines  = %d\n", __FUNCTION__, (unsigned int)dev->calib_lines);
 
2336
  DBG (DBG_io, "%s: calib_pixels = %d\n", __FUNCTION__, (unsigned int)dev->calib_pixels);
 
2337
 
 
2338
  /* this is aworkaround insufficent distance for slope 
 
2339
   * motor acceleration TODO special motor slope for shading  */
 
2340
  move=1;
 
2341
  if(dev->calib_resolution<1200)
 
2342
    {
 
2343
      move=40;
 
2344
    }
 
2345
 
 
2346
  status = gl846_init_scan_regs (dev,
 
2347
                                 dev->calib_reg,
 
2348
                                 dev->calib_resolution,
 
2349
                                 dev->calib_resolution,
 
2350
                                 0,
 
2351
                                 move,
 
2352
                                 dev->calib_pixels,
 
2353
                                 dev->calib_lines,
 
2354
                                 16,
 
2355
                                 dev->calib_channels,
 
2356
                                 dev->settings.color_filter,
 
2357
                                 SCAN_FLAG_DISABLE_SHADING |
 
2358
                                 SCAN_FLAG_DISABLE_GAMMA |
 
2359
                                 SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE |
 
2360
                                 SCAN_FLAG_IGNORE_LINE_DISTANCE);
 
2361
 
 
2362
  if (status != SANE_STATUS_GOOD)
 
2363
    {
 
2364
      DBG (DBG_error, "%s: failed to setup scan: %s\n", __FUNCTION__, sane_strstatus (status));
 
2365
      return status;
 
2366
    }
 
2367
 
 
2368
  status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS);
 
2369
  if (status != SANE_STATUS_GOOD)
 
2370
    {
 
2371
      DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __FUNCTION__, sane_strstatus (status));
 
2372
      return status;
 
2373
    }
 
2374
 
 
2375
  /* we use GENESYS_FLAG_SHADING_REPARK */
 
2376
  dev->scanhead_position_in_steps = 0;
 
2377
 
 
2378
  DBGCOMPLETED;
 
2379
  return SANE_STATUS_GOOD;
 
2380
}
 
2381
 
 
2382
/** @brief set up registers for the actual scan
 
2383
 */
 
2384
static SANE_Status
 
2385
gl846_init_regs_for_scan (Genesys_Device * dev)
 
2386
{
 
2387
  int channels;
 
2388
  int flags;
 
2389
  int depth;
 
2390
  float move;
 
2391
  int move_dpi;
 
2392
  float start;
 
2393
 
 
2394
  SANE_Status status;
 
2395
 
 
2396
  DBG (DBG_info,
 
2397
       "gl846_init_regs_for_scan settings:\nResolution: %uDPI\n"
 
2398
       "Lines     : %u\nPPL       : %u\nStartpos  : %.3f/%.3f\nScan mode : %d\n\n",
 
2399
       dev->settings.yres, dev->settings.lines, dev->settings.pixels,
 
2400
       dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode);
 
2401
 
 
2402
 /* channels */
 
2403
  if (dev->settings.scan_mode == SCAN_MODE_COLOR)       /* single pass color */
 
2404
    channels = 3;
 
2405
  else
 
2406
    channels = 1;
 
2407
 
 
2408
  /* depth */
 
2409
  depth = dev->settings.depth;
 
2410
  if (dev->settings.scan_mode == SCAN_MODE_LINEART)
 
2411
    depth = 1;
 
2412
 
 
2413
 
 
2414
  /* steps to move to reach scanning area:
 
2415
     - first we move to physical start of scanning
 
2416
     either by a fixed steps amount from the black strip
 
2417
     or by a fixed amount from parking position,
 
2418
     minus the steps done during shading calibration
 
2419
     - then we move by the needed offset whitin physical
 
2420
     scanning area
 
2421
 
 
2422
     assumption: steps are expressed at maximum motor resolution
 
2423
 
 
2424
     we need:   
 
2425
     SANE_Fixed y_offset;                       
 
2426
     SANE_Fixed y_size;                 
 
2427
     SANE_Fixed y_offset_calib;
 
2428
     mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */
 
2429
 
 
2430
  /* if scanner uses GENESYS_FLAG_SEARCH_START y_offset is
 
2431
     relative from origin, else, it is from parking position */
 
2432
 
 
2433
  move_dpi = dev->motor.base_ydpi;
 
2434
 
 
2435
  move = SANE_UNFIX (dev->model->y_offset);
 
2436
  move += dev->settings.tl_y;
 
2437
  move = (move * move_dpi) / MM_PER_INCH;
 
2438
  move -= dev->scanhead_position_in_steps;
 
2439
  DBG (DBG_info, "%s: move=%f steps\n",__FUNCTION__, move);
 
2440
 
 
2441
  /* fast move to scan area */
 
2442
  /* we don't move fast the whole distance since it would involve
 
2443
   * computing acceleration/deceleration distance for scan
 
2444
   * resolution. So leave a remainder for it so scan makes the final
 
2445
   * move tuning */
 
2446
  if(channels*dev->settings.yres>=600 && move>700)
 
2447
    {
 
2448
      status = gl846_feed (dev, move-500);
 
2449
      if (status != SANE_STATUS_GOOD)
 
2450
        {
 
2451
          DBG (DBG_error, "%s: failed to move to scan area\n",__FUNCTION__);
 
2452
          return status;
 
2453
        }
 
2454
      move=500;
 
2455
    }
 
2456
 
 
2457
  DBG (DBG_info, "gl846_init_regs_for_scan: move=%f steps\n", move);
 
2458
  DBG (DBG_info, "%s: move=%f steps\n", __FUNCTION__, move);
 
2459
 
 
2460
  /* start */
 
2461
  start = SANE_UNFIX (dev->model->x_offset);
 
2462
  start += dev->settings.tl_x;
 
2463
  start = (start * dev->sensor.optical_res) / MM_PER_INCH;
 
2464
 
 
2465
  flags = 0;
 
2466
 
 
2467
  /* emulated lineart from gray data is required for now */
 
2468
  if(dev->settings.scan_mode == SCAN_MODE_LINEART 
 
2469
     && dev->settings.dynamic_lineart)
 
2470
    {
 
2471
      flags |= SCAN_FLAG_DYNAMIC_LINEART;
 
2472
    }
 
2473
 
 
2474
  /* backtracking isn't handled well, so don't enable it */
 
2475
  flags |= SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE;
 
2476
 
 
2477
  status = gl846_init_scan_regs (dev,
 
2478
                                 dev->reg,
 
2479
                                 dev->settings.xres,
 
2480
                                 dev->settings.yres,
 
2481
                                 start,
 
2482
                                 move,
 
2483
                                 dev->settings.pixels,
 
2484
                                 dev->settings.lines,
 
2485
                                 depth,
 
2486
                                 channels,
 
2487
                                 dev->settings.color_filter,
 
2488
                                 flags);
 
2489
 
 
2490
  if (status != SANE_STATUS_GOOD)
 
2491
    return status;
 
2492
  
 
2493
  DBGCOMPLETED;
 
2494
  return SANE_STATUS_GOOD;
 
2495
}
 
2496
 
 
2497
 
 
2498
/**
 
2499
 * Send shading calibration data. The buffer is considered to always hold values
 
2500
 * for all the channels.
 
2501
 */
 
2502
static SANE_Status
 
2503
gl846_send_shading_data (Genesys_Device * dev, uint8_t * data, int size)
 
2504
{
 
2505
  SANE_Status status = SANE_STATUS_GOOD;
 
2506
  uint32_t addr, length, i, x, factor, pixels;
 
2507
  uint32_t dpiset, dpihw, strpixel, endpixel;
 
2508
  uint16_t tempo;
 
2509
  uint32_t lines, channels;
 
2510
  uint8_t val,*buffer,*ptr,*src;
 
2511
 
 
2512
  DBGSTART;
 
2513
  DBG( DBG_io2, "%s: writing %d bytes of shading data\n",__FUNCTION__,size);
 
2514
 
 
2515
  /* shading data is plit in 3 (up to 5 with IR) areas 
 
2516
     write(0x10014000,0x00000dd8)
 
2517
     URB 23429  bulk_out len  3544  wrote 0x33 0x10 0x....
 
2518
     write(0x1003e000,0x00000dd8)
 
2519
     write(0x10068000,0x00000dd8)
 
2520
   */
 
2521
  length = (uint32_t) (size / 3);
 
2522
  sanei_genesys_get_double(dev->reg,REG_STRPIXEL,&tempo);
 
2523
  strpixel=tempo;
 
2524
  sanei_genesys_get_double(dev->reg,REG_ENDPIXEL,&tempo);
 
2525
  endpixel=tempo;
 
2526
 
 
2527
  /* compute deletion factor */
 
2528
  sanei_genesys_get_double(dev->reg,REG_DPISET,&tempo);
 
2529
  dpiset=tempo;
 
2530
  DBG( DBG_io2, "%s: STRPIXEL=%d, ENDPIXEL=%d, PIXELS=%d, DPISET=%d\n",__FUNCTION__,strpixel,endpixel,endpixel-strpixel,dpiset);
 
2531
  dpihw=sanei_genesys_compute_dpihw(dev,dpiset);
 
2532
  factor=dpihw/dpiset;
 
2533
  DBG( DBG_io2, "%s: factor=%d\n",__FUNCTION__,factor);
 
2534
 
 
2535
  if(DBG_LEVEL>=DBG_data)
 
2536
    {
 
2537
      dev->binary=fopen("binary.pnm","wb");
 
2538
      sanei_genesys_get_triple(dev->reg, REG_LINCNT, &lines);
 
2539
      channels=dev->current_setup.channels;
 
2540
      if(dev->binary!=NULL)
 
2541
        {
 
2542
          fprintf(dev->binary,"P5\n%d %d\n%d\n",(endpixel-strpixel)/factor*channels,lines/channels,255);
 
2543
        }
 
2544
    }
 
2545
  
 
2546
  pixels=endpixel-strpixel;
 
2547
 
 
2548
  /* since we're using SHDAREA, substract startx coordinate from shading */
 
2549
  strpixel-=((dev->sensor.CCD_start_xoffset*600)/dev->sensor.optical_res);
 
2550
  
 
2551
  /* turn pixel value into bytes 2x16 bits words */
 
2552
  strpixel*=2*2; 
 
2553
  pixels*=2*2;
 
2554
 
 
2555
  /* allocate temporary buffer */
 
2556
  buffer=(uint8_t *)malloc(pixels);
 
2557
  memset(buffer,0,pixels);
 
2558
  DBG( DBG_io2, "%s: using chunks of %d (0x%04x) bytes\n",__FUNCTION__,pixels,pixels);
 
2559
 
 
2560
  /* base addr of data has been written in reg D0-D4 in 4K word, so AHB address
 
2561
   * is 8192*reg value */
 
2562
 
 
2563
  /* write actual color channel data */
 
2564
  for(i=0;i<3;i++)
 
2565
    {
 
2566
      /* build up actual shading data by copying the part from the full width one
 
2567
       * to the one corresponding to SHDAREA */
 
2568
      ptr=buffer;
 
2569
 
 
2570
      /* iterate on both sensor segment */
 
2571
      for(x=0;x<pixels;x+=4*factor)
 
2572
        {
 
2573
          /* coefficient source */
 
2574
          src=(data+strpixel+i*length)+x;
 
2575
 
 
2576
          /* coefficient copy */
 
2577
          ptr[0]=src[0];
 
2578
          ptr[1]=src[1];
 
2579
          ptr[2]=src[2];
 
2580
          ptr[3]=src[3];
 
2581
          
 
2582
          /* next shading coefficient */
 
2583
          ptr+=4;
 
2584
        }
 
2585
 
 
2586
      RIE (sanei_genesys_read_register (dev, 0xd0+i, &val));
 
2587
      addr = val * 8192 + 0x10000000;
 
2588
      status = sanei_genesys_write_ahb (dev->dn, dev->usb_mode, addr, pixels, buffer);
 
2589
      if (status != SANE_STATUS_GOOD)
 
2590
        {
 
2591
          DBG (DBG_error, "gl846_send_shading_data; write to AHB failed (%s)\n",
 
2592
              sane_strstatus (status));
 
2593
          return status;
 
2594
        }
 
2595
    }
 
2596
 
 
2597
  free(buffer);
 
2598
  DBGCOMPLETED;
 
2599
 
 
2600
  return status;
 
2601
}
 
2602
 
 
2603
/** @brief calibrates led exposure
 
2604
 * Calibrate exposure by scanning a white area until the used exposure gives
 
2605
 * data white enough.
 
2606
 * @param dev device to calibrate
 
2607
 */
 
2608
static SANE_Status
 
2609
gl846_led_calibration (Genesys_Device * dev)
 
2610
{
 
2611
  int num_pixels;
 
2612
  int total_size;
 
2613
  int used_res;
 
2614
  uint8_t *line;
 
2615
  int i, j;
 
2616
  SANE_Status status = SANE_STATUS_GOOD;
 
2617
  int val;
 
2618
  int channels, depth;
 
2619
  int avg[3], top[3], bottom[3];
 
2620
  int turn;
 
2621
  char fn[20];
 
2622
  uint16_t exp[3];
 
2623
  Sensor_Profile *sensor;
 
2624
  float move;
 
2625
  SANE_Bool acceptable;
 
2626
 
 
2627
  DBGSTART;
 
2628
 
 
2629
  move = SANE_UNFIX (dev->model->y_offset_calib);
 
2630
  move = (move * (dev->motor.base_ydpi/4)) / MM_PER_INCH;
 
2631
  if(move>20)
 
2632
    {
 
2633
      RIE(gl846_feed (dev, move));
 
2634
    }
 
2635
  DBG (DBG_io, "%s: move=%f steps\n", __FUNCTION__, move);
 
2636
 
 
2637
  /* offset calibration is always done in color mode */
 
2638
  channels = 3;
 
2639
  depth=16;
 
2640
  used_res=sanei_genesys_compute_dpihw(dev,dev->settings.xres);
 
2641
  sensor=get_sensor_profile(dev->model->ccd_type, used_res);
 
2642
  num_pixels = (dev->sensor.sensor_pixels*used_res)/dev->sensor.optical_res;
 
2643
  
 
2644
  /* initial calibration reg values */
 
2645
  memcpy (dev->calib_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
 
2646
 
 
2647
  /* set up for the calibration scan */
 
2648
  status = gl846_init_scan_regs (dev,
 
2649
                                 dev->calib_reg,
 
2650
                                 used_res,
 
2651
                                 used_res,
 
2652
                                 0,
 
2653
                                 0,
 
2654
                                 num_pixels,
 
2655
                                 1,
 
2656
                                 depth,
 
2657
                                 channels,
 
2658
                                 dev->settings.color_filter,
 
2659
                                 SCAN_FLAG_DISABLE_SHADING |
 
2660
                                 SCAN_FLAG_DISABLE_GAMMA |
 
2661
                                 SCAN_FLAG_SINGLE_LINE |
 
2662
                                 SCAN_FLAG_IGNORE_LINE_DISTANCE);
 
2663
  if (status != SANE_STATUS_GOOD)
 
2664
    {
 
2665
      DBG (DBG_error, "%s: failed to setup scan: %s\n", __FUNCTION__, sane_strstatus (status));
 
2666
      return status;
 
2667
    }
 
2668
 
 
2669
  total_size = num_pixels * channels * (depth/8) * 1;   /* colors * bytes_per_color * scan lines */
 
2670
  line = malloc (total_size);
 
2671
  if (!line)
 
2672
    return SANE_STATUS_NO_MEM;
 
2673
 
 
2674
  /* initial loop values and boundaries */
 
2675
  exp[0]=sensor->expr;
 
2676
  exp[1]=sensor->expg;
 
2677
  exp[2]=sensor->expb;
 
2678
 
 
2679
  bottom[0]=29000;
 
2680
  bottom[1]=29000;
 
2681
  bottom[2]=29000;
 
2682
 
 
2683
  top[0]=41000;
 
2684
  top[1]=51000;
 
2685
  top[2]=51000;
 
2686
 
 
2687
  turn = 0;
 
2688
 
 
2689
  /* no move during led calibration */
 
2690
  gl846_set_motor_power (dev->calib_reg, SANE_FALSE);
 
2691
  do
 
2692
    {
 
2693
      /* set up exposure */
 
2694
      sanei_genesys_set_double(dev->calib_reg,REG_EXPR,exp[0]);
 
2695
      sanei_genesys_set_double(dev->calib_reg,REG_EXPG,exp[1]);
 
2696
      sanei_genesys_set_double(dev->calib_reg,REG_EXPB,exp[2]);
 
2697
 
 
2698
      /* write registers and scan data */
 
2699
      RIEF (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS), line);
 
2700
 
 
2701
      DBG (DBG_info, "gl846_led_calibration: starting line reading\n");
 
2702
      RIEF (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), line);
 
2703
      RIEF (sanei_genesys_read_data_from_scanner (dev, line, total_size), line);
 
2704
 
 
2705
      /* stop scanning */
 
2706
      RIEF (gl846_stop_action (dev), line);
 
2707
 
 
2708
      if (DBG_LEVEL >= DBG_data)
 
2709
        {
 
2710
          snprintf (fn, 20, "led_%02d.pnm", turn);
 
2711
          sanei_genesys_write_pnm_file (fn, line, depth, channels, num_pixels, 1);
 
2712
        }
 
2713
 
 
2714
      /* compute average */
 
2715
      for (j = 0; j < channels; j++)
 
2716
        {
 
2717
          avg[j] = 0;
 
2718
          for (i = 0; i < num_pixels; i++)
 
2719
            {
 
2720
              if (dev->model->is_cis)
 
2721
                val =
 
2722
                  line[i * 2 + j * 2 * num_pixels + 1] * 256 +
 
2723
                  line[i * 2 + j * 2 * num_pixels];
 
2724
              else
 
2725
                val =
 
2726
                  line[i * 2 * channels + 2 * j + 1] * 256 +
 
2727
                  line[i * 2 * channels + 2 * j];
 
2728
              avg[j] += val;
 
2729
            }
 
2730
 
 
2731
          avg[j] /= num_pixels;
 
2732
        }
 
2733
 
 
2734
      DBG (DBG_info, "gl846_led_calibration: average: %d,%d,%d\n", avg[0], avg[1], avg[2]);
 
2735
 
 
2736
      /* check if exposure gives average within the boundaries */
 
2737
      acceptable = SANE_TRUE;
 
2738
      for(i=0;i<3;i++)
 
2739
        {
 
2740
          if(avg[i]<bottom[i])
 
2741
            {
 
2742
              exp[i]=(exp[i]*bottom[i])/avg[i];
 
2743
              acceptable = SANE_FALSE;
 
2744
            }
 
2745
          if(avg[i]>top[i])
 
2746
            {
 
2747
              exp[i]=(exp[i]*top[i])/avg[i];
 
2748
              acceptable = SANE_FALSE;
 
2749
            }
 
2750
        }
 
2751
 
 
2752
      turn++;
 
2753
    }
 
2754
  while (!acceptable && turn < 100);
 
2755
 
 
2756
  DBG (DBG_info, "gl846_led_calibration: acceptable exposure: %d,%d,%d\n", exp[0], exp[1], exp[2]);
 
2757
 
 
2758
  /* set these values as final ones for scan */
 
2759
  sanei_genesys_set_double(dev->reg,REG_EXPR,exp[0]);
 
2760
  sanei_genesys_set_double(dev->reg,REG_EXPG,exp[1]);
 
2761
  sanei_genesys_set_double(dev->reg,REG_EXPB,exp[2]);
 
2762
 
 
2763
  /* store in this struct since it is the one used by cache calibration */
 
2764
  dev->sensor.regs_0x10_0x1d[0] = (exp[0] >> 8) & 0xff;
 
2765
  dev->sensor.regs_0x10_0x1d[1] = exp[0] & 0xff;
 
2766
  dev->sensor.regs_0x10_0x1d[2] = (exp[1] >> 8) & 0xff;
 
2767
  dev->sensor.regs_0x10_0x1d[3] = exp[1] & 0xff;
 
2768
  dev->sensor.regs_0x10_0x1d[4] = (exp[2] >> 8) & 0xff;
 
2769
  dev->sensor.regs_0x10_0x1d[5] = exp[2] & 0xff;
 
2770
 
 
2771
  /* cleanup before return */
 
2772
  free (line);
 
2773
  
 
2774
  /* go back home */
 
2775
  if(move>20)
 
2776
    {
 
2777
      status=gl846_slow_back_home (dev, SANE_TRUE);
 
2778
    }
 
2779
 
 
2780
  DBGCOMPLETED;
 
2781
  return status;
 
2782
}
 
2783
 
 
2784
/** 
 
2785
 * set up GPIO/GPOE for idle state
 
2786
 */
 
2787
static SANE_Status
 
2788
gl846_init_gpio (Genesys_Device * dev)
 
2789
{
 
2790
  SANE_Status status = SANE_STATUS_GOOD;
 
2791
  int idx=0;
 
2792
 
 
2793
  DBGSTART;
 
2794
 
 
2795
  /* search GPIO profile */
 
2796
  while(gpios[idx].sensor_id!=0 && dev->model->gpo_type!=gpios[idx].sensor_id)
 
2797
    {
 
2798
      idx++;
 
2799
    }
 
2800
  if(gpios[idx].sensor_id==0)
 
2801
    {
 
2802
      DBG (DBG_error, "%s: failed to find GPIO profile for sensor_id=%d\n", __FUNCTION__, dev->model->ccd_type);
 
2803
      return SANE_STATUS_INVAL;
 
2804
    }
 
2805
 
 
2806
  RIE (sanei_genesys_write_register (dev, REGA7, gpios[idx].ra7));
 
2807
  RIE (sanei_genesys_write_register (dev, REGA6, gpios[idx].ra6));
 
2808
  
 
2809
  RIE (sanei_genesys_write_register (dev, REG6B, gpios[idx].r6b));
 
2810
  RIE (sanei_genesys_write_register (dev, REG6C, gpios[idx].r6c));
 
2811
  RIE (sanei_genesys_write_register (dev, REG6D, gpios[idx].r6d));
 
2812
  RIE (sanei_genesys_write_register (dev, REG6E, gpios[idx].r6e));
 
2813
  RIE (sanei_genesys_write_register (dev, REG6F, gpios[idx].r6f));
 
2814
 
 
2815
  RIE (sanei_genesys_write_register (dev, REGA8, gpios[idx].ra8));
 
2816
  RIE (sanei_genesys_write_register (dev, REGA9, gpios[idx].ra9));
 
2817
 
 
2818
  DBGCOMPLETED;
 
2819
  return status;
 
2820
}
 
2821
 
 
2822
/** 
 
2823
 * set memory layout by filling values in dedicated registers
 
2824
 */
 
2825
static SANE_Status
 
2826
gl846_init_memory_layout (Genesys_Device * dev)
 
2827
{
 
2828
  SANE_Status status = SANE_STATUS_GOOD;
 
2829
  int idx = 0, i;
 
2830
  uint8_t val;
 
2831
 
 
2832
  DBGSTART
 
2833
 
 
2834
  /* point to per model memory layout */
 
2835
  idx = 0;
 
2836
  while(layouts[idx].model!=NULL && strcmp(dev->model->name,layouts[idx].model)!=0)
 
2837
    {
 
2838
      if(strcmp(dev->model->name,layouts[idx].model)!=0)
 
2839
        idx++;
 
2840
    }
 
2841
  if(layouts[idx].model==NULL)
 
2842
    {
 
2843
      DBG(DBG_error, "%s: failed to find memory layout for model %s!\n", __FUNCTION__, dev->model->name);
 
2844
      return SANE_STATUS_INVAL;
 
2845
    }
 
2846
 
 
2847
  /* CLKSET and DRAMSEL */
 
2848
  val = layouts[idx].dramsel;
 
2849
  RIE (sanei_genesys_write_register (dev, REG0B, val));
 
2850
  dev->reg[reg_0x0b].value = val;
 
2851
 
 
2852
  /* prevent further writings by bulk write register */
 
2853
  dev->reg[reg_0x0b].address = 0x00;
 
2854
 
 
2855
  /* setup base address for shading and scanned data. */
 
2856
  for(i=0;i<10;i++)
 
2857
    {
 
2858
      sanei_genesys_write_register (dev, 0xe0+i, layouts[idx].rx[i]);
 
2859
    }
 
2860
 
 
2861
  DBGCOMPLETED;
 
2862
  return status;
 
2863
}
 
2864
 
 
2865
/* *
 
2866
 * initialize ASIC from power on condition
 
2867
 */
 
2868
#ifndef UNIT_TESTING
 
2869
static
 
2870
#endif 
 
2871
SANE_Status
 
2872
gl846_boot (Genesys_Device * dev, SANE_Bool cold)
 
2873
{
 
2874
  SANE_Status status;
 
2875
  uint8_t val;
 
2876
 
 
2877
  DBGSTART;
 
2878
 
 
2879
  /* reset ASIC if cold boot */
 
2880
  if(cold)
 
2881
    {
 
2882
      RIE (sanei_genesys_write_register (dev, 0x0e, 0x01));
 
2883
      RIE (sanei_genesys_write_register (dev, 0x0e, 0x00));
 
2884
    }
 
2885
  
 
2886
  if(dev->usb_mode == 1)
 
2887
    {
 
2888
      val = 0x14;
 
2889
    }
 
2890
  else
 
2891
    {
 
2892
      val = 0x11;
 
2893
    }
 
2894
  RIE (sanei_genesys_write_0x8c (dev, 0x0f, val));
 
2895
 
 
2896
  /* test CHKVER */
 
2897
  RIE (sanei_genesys_read_register (dev, REG40, &val));
 
2898
  if (val & REG40_CHKVER)
 
2899
    {
 
2900
      RIE (sanei_genesys_read_register (dev, 0x00, &val));
 
2901
      DBG (DBG_info, "%s: reported version for genesys chip is 0x%02x\n", __FUNCTION__, val);
 
2902
    }
 
2903
 
 
2904
  /* Set default values for registers */
 
2905
  gl846_init_registers (dev);
 
2906
 
 
2907
  /* Write initial registers */
 
2908
  RIE (dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL846_MAX_REGS));
 
2909
 
 
2910
  /* Enable DRAM by setting a rising edge on bit 3 of reg 0x0b */
 
2911
  val = dev->reg[reg_0x0b].value & REG0B_DRAMSEL;
 
2912
  val = (val | REG0B_ENBDRAM);
 
2913
  RIE (sanei_genesys_write_register (dev, REG0B, val));
 
2914
  dev->reg[reg_0x0b].value = val;
 
2915
 
 
2916
  /* CIS_LINE */
 
2917
  if (dev->model->is_cis)
 
2918
    {
 
2919
      SETREG (0x08, REG08_CIS_LINE);
 
2920
      RIE (sanei_genesys_write_register (dev, 0x08, dev->reg[reg_0x08].value));
 
2921
    }
 
2922
 
 
2923
  /* set up clocks */
 
2924
  RIE (sanei_genesys_write_0x8c (dev, 0x10, 0x0e));
 
2925
  RIE (sanei_genesys_write_0x8c (dev, 0x13, 0x0e));
 
2926
 
 
2927
  /* setup gpio */
 
2928
  RIE (gl846_init_gpio (dev));
 
2929
 
 
2930
  /* setup internal memory layout */
 
2931
  RIE (gl846_init_memory_layout (dev));
 
2932
 
 
2933
  SETREG (0xf8, 0x05);
 
2934
  RIE (sanei_genesys_write_register (dev, 0xf8, dev->reg[reg_0xf8].value));
 
2935
 
 
2936
  DBGCOMPLETED;
 
2937
  return SANE_STATUS_GOOD;
 
2938
}
 
2939
 
 
2940
/**
 
2941
 * initialize backend and ASIC : registers, motor tables, and gamma tables
 
2942
 * then ensure scanner's head is at home
 
2943
 */
 
2944
#ifndef UNIT_TESTING
 
2945
static
 
2946
#endif
 
2947
SANE_Status gl846_init (Genesys_Device * dev)
 
2948
{
 
2949
  SANE_Status status;
 
2950
 
 
2951
  DBG_INIT ();
 
2952
  DBGSTART;
 
2953
  
 
2954
  status=sanei_genesys_asic_init(dev, GENESYS_GL846_MAX_REGS);
 
2955
 
 
2956
  DBGCOMPLETED;
 
2957
  return status;
 
2958
}
 
2959
 
 
2960
static SANE_Status
 
2961
gl846_update_hardware_sensors (Genesys_Scanner * s)
 
2962
{
 
2963
  /* do what is needed to get a new set of events, but try to not lose
 
2964
     any of them.
 
2965
   */
 
2966
  SANE_Status status = SANE_STATUS_GOOD;
 
2967
  uint8_t val;
 
2968
  uint8_t scan, file, email, copy;
 
2969
  switch(s->dev->model->gpo_type)
 
2970
    {
 
2971
      default:
 
2972
        scan=0x01;
 
2973
        file=0x02;
 
2974
        email=0x04;
 
2975
        copy=0x08;
 
2976
    }
 
2977
  RIE (sanei_genesys_read_register (s->dev, REG6D, &val));
 
2978
 
 
2979
  if (s->val[OPT_SCAN_SW].b == s->last_val[OPT_SCAN_SW].b)
 
2980
    s->val[OPT_SCAN_SW].b = (val & scan) == 0;
 
2981
  if (s->val[OPT_FILE_SW].b == s->last_val[OPT_FILE_SW].b)
 
2982
    s->val[OPT_FILE_SW].b = (val & file) == 0;
 
2983
  if (s->val[OPT_EMAIL_SW].b == s->last_val[OPT_EMAIL_SW].b)
 
2984
    s->val[OPT_EMAIL_SW].b = (val & email) == 0;
 
2985
  if (s->val[OPT_COPY_SW].b == s->last_val[OPT_COPY_SW].b)
 
2986
    s->val[OPT_COPY_SW].b = (val & copy) == 0;
 
2987
 
 
2988
  return status;
 
2989
}
 
2990
 
 
2991
/** @brief search for a full width black or white strip.
 
2992
 * This function searches for a black or white stripe across the scanning area.
 
2993
 * When searching backward, the searched area must completely be of the desired 
 
2994
 * color since this area will be used for calibration which scans forward.
 
2995
 * @param dev scanner device
 
2996
 * @param forward SANE_TRUE if searching forward, SANE_FALSE if searching backward
 
2997
 * @param black SANE_TRUE if searching for a black strip, SANE_FALSE for a white strip
 
2998
 * @return SANE_STATUS_GOOD if a matching strip is found, SANE_STATUS_UNSUPPORTED if not
 
2999
 */
 
3000
static SANE_Status
 
3001
gl846_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black)
 
3002
{
 
3003
  unsigned int pixels, lines, channels;
 
3004
  SANE_Status status;
 
3005
  Genesys_Register_Set local_reg[GENESYS_GL846_MAX_REGS];
 
3006
  size_t size;
 
3007
  uint8_t *data;
 
3008
  int steps, depth, dpi;
 
3009
  unsigned int pass, count, found, x, y;
 
3010
  char title[80];
 
3011
  Genesys_Register_Set *r;
 
3012
 
 
3013
  DBG (DBG_proc, "gl846_search_strip %s %s\n", black ? "black" : "white",
 
3014
       forward ? "forward" : "reverse");
 
3015
 
 
3016
  gl846_set_fe (dev, AFE_SET);
 
3017
  status = gl846_stop_action (dev);
 
3018
  if (status != SANE_STATUS_GOOD)
 
3019
    {
 
3020
      DBG (DBG_error,
 
3021
           "gl846_search_strip: failed to stop: %s\n",
 
3022
           sane_strstatus (status));
 
3023
      return status;
 
3024
    }
 
3025
 
 
3026
  /* set up for a gray scan at lowest dpi */
 
3027
  dpi = 9600;
 
3028
  for (x = 0; x < MAX_RESOLUTIONS; x++)
 
3029
    {
 
3030
      if (dev->model->xdpi_values[x] > 0 && dev->model->xdpi_values[x] < dpi)
 
3031
        dpi = dev->model->xdpi_values[x];
 
3032
    }
 
3033
  channels = 1;
 
3034
  /* 10 MM */
 
3035
  /* lines = (10 * dpi) / MM_PER_INCH; */
 
3036
  /* shading calibation is done with dev->motor.base_ydpi */
 
3037
  lines = (dev->model->shading_lines * dpi) / dev->motor.base_ydpi;
 
3038
  depth = 8;
 
3039
  pixels = (dev->sensor.sensor_pixels * dpi) / dev->sensor.optical_res;
 
3040
  size = pixels * channels * lines * (depth / 8);
 
3041
  data = malloc (size);
 
3042
  if (!data)
 
3043
    {
 
3044
      DBG (DBG_error, "gl846_search_strip: failed to allocate memory\n");
 
3045
      return SANE_STATUS_NO_MEM;
 
3046
    }
 
3047
  dev->scanhead_position_in_steps = 0;
 
3048
 
 
3049
  memcpy (local_reg, dev->reg,
 
3050
          GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
 
3051
 
 
3052
  status = gl846_init_scan_regs (dev,
 
3053
                                 local_reg,
 
3054
                                 dpi,
 
3055
                                 dpi,
 
3056
                                 0,
 
3057
                                 0,
 
3058
                                 pixels,
 
3059
                                 lines,
 
3060
                                 depth,
 
3061
                                 channels,
 
3062
                                 0,
 
3063
                                 SCAN_FLAG_DISABLE_SHADING |
 
3064
                                 SCAN_FLAG_DISABLE_GAMMA);
 
3065
  if (status != SANE_STATUS_GOOD)
 
3066
    {
 
3067
      free(data);
 
3068
      DBG (DBG_error,
 
3069
           "gl846_search_strip: failed to setup for scan: %s\n",
 
3070
           sane_strstatus (status));
 
3071
      return status;
 
3072
    }
 
3073
 
 
3074
  /* set up for reverse or forward */
 
3075
  r = sanei_genesys_get_address (local_reg, REG02);
 
3076
  if (forward)
 
3077
    r->value &= ~REG02_MTRREV;
 
3078
  else
 
3079
    r->value |= REG02_MTRREV;
 
3080
 
 
3081
 
 
3082
  status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS);
 
3083
  if (status != SANE_STATUS_GOOD)
 
3084
    {
 
3085
      free(data);
 
3086
      DBG (DBG_error,
 
3087
           "gl846_search_strip: Failed to bulk write registers: %s\n",
 
3088
           sane_strstatus (status));
 
3089
      return status;
 
3090
    }
 
3091
 
 
3092
  status = gl846_begin_scan (dev, local_reg, SANE_TRUE);
 
3093
  if (status != SANE_STATUS_GOOD)
 
3094
    {
 
3095
      free (data);
 
3096
      DBG (DBG_error,
 
3097
           "gl846_search_strip: failed to begin scan: %s\n",
 
3098
           sane_strstatus (status));
 
3099
      return status;
 
3100
    }
 
3101
 
 
3102
  /* waits for valid data */
 
3103
  do
 
3104
    sanei_genesys_test_buffer_empty (dev, &steps);
 
3105
  while (steps);
 
3106
 
 
3107
  /* now we're on target, we can read data */
 
3108
  status = sanei_genesys_read_data_from_scanner (dev, data, size);
 
3109
  if (status != SANE_STATUS_GOOD)
 
3110
    {
 
3111
      free (data);
 
3112
      DBG (DBG_error,
 
3113
           "gl846_search_start_position: failed to read data: %s\n",
 
3114
           sane_strstatus (status));
 
3115
      return status;
 
3116
    }
 
3117
 
 
3118
  status = gl846_stop_action (dev);
 
3119
  if (status != SANE_STATUS_GOOD)
 
3120
    {
 
3121
      free (data);
 
3122
      DBG (DBG_error, "gl846_search_strip: gl846_stop_action failed\n");
 
3123
      return status;
 
3124
    }
 
3125
 
 
3126
  pass = 0;
 
3127
  if (DBG_LEVEL >= DBG_data)
 
3128
    {
 
3129
      sprintf (title, "search_strip_%s_%s%02d.pnm",
 
3130
               black ? "black" : "white", forward ? "fwd" : "bwd", (int)pass);
 
3131
      sanei_genesys_write_pnm_file (title, data, depth, channels, pixels,
 
3132
                                    lines);
 
3133
    }
 
3134
 
 
3135
  /* loop until strip is found or maximum pass number done */
 
3136
  found = 0;
 
3137
  while (pass < 20 && !found)
 
3138
    {
 
3139
      status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS);
 
3140
      if (status != SANE_STATUS_GOOD)
 
3141
        {
 
3142
          DBG (DBG_error,
 
3143
               "gl846_search_strip: Failed to bulk write registers: %s\n",
 
3144
               sane_strstatus (status));
 
3145
          return status;
 
3146
        }
 
3147
 
 
3148
      /* now start scan */
 
3149
      status = gl846_begin_scan (dev, local_reg, SANE_TRUE);
 
3150
      if (status != SANE_STATUS_GOOD)
 
3151
        {
 
3152
          free (data);
 
3153
          DBG (DBG_error,
 
3154
               "gl846_search_strip: failed to begin scan: %s\n",
 
3155
               sane_strstatus (status));
 
3156
          return status;
 
3157
        }
 
3158
 
 
3159
      /* waits for valid data */
 
3160
      do
 
3161
        sanei_genesys_test_buffer_empty (dev, &steps);
 
3162
      while (steps);
 
3163
 
 
3164
      /* now we're on target, we can read data */
 
3165
      status = sanei_genesys_read_data_from_scanner (dev, data, size);
 
3166
      if (status != SANE_STATUS_GOOD)
 
3167
        {
 
3168
          free (data);
 
3169
          DBG (DBG_error,
 
3170
               "gl846_search_start_position: failed to read data: %s\n",
 
3171
               sane_strstatus (status));
 
3172
          return status;
 
3173
        }
 
3174
 
 
3175
      status = gl846_stop_action (dev);
 
3176
      if (status != SANE_STATUS_GOOD)
 
3177
        {
 
3178
          free (data);
 
3179
          DBG (DBG_error, "gl846_search_strip: gl846_stop_action failed\n");
 
3180
          return status;
 
3181
        }
 
3182
 
 
3183
      if (DBG_LEVEL >= DBG_data)
 
3184
        {
 
3185
          sprintf (title, "search_strip_%s_%s%02d.pnm",
 
3186
                   black ? "black" : "white", forward ? "fwd" : "bwd", (int)pass);
 
3187
          sanei_genesys_write_pnm_file (title, data, depth, channels,
 
3188
                                        pixels, lines);
 
3189
        }
 
3190
 
 
3191
      /* search data to find black strip */
 
3192
      /* when searching forward, we only need one line of the searched color since we
 
3193
       * will scan forward. But when doing backward search, we need all the area of the
 
3194
       * same color */
 
3195
      if (forward)
 
3196
        {
 
3197
          for (y = 0; y < lines && !found; y++)
 
3198
            {
 
3199
              count = 0;
 
3200
              /* count of white/black pixels depending on the color searched */
 
3201
              for (x = 0; x < pixels; x++)
 
3202
                {
 
3203
                  /* when searching for black, detect white pixels */
 
3204
                  if (black && data[y * pixels + x] > 90)
 
3205
                    {
 
3206
                      count++;
 
3207
                    }
 
3208
                  /* when searching for white, detect black pixels */
 
3209
                  if (!black && data[y * pixels + x] < 60)
 
3210
                    {
 
3211
                      count++;
 
3212
                    }
 
3213
                }
 
3214
 
 
3215
              /* at end of line, if count >= 3%, line is not fully of the desired color
 
3216
               * so we must go to next line of the buffer */
 
3217
              /* count*100/pixels < 3 */
 
3218
              if ((count * 100) / pixels < 3)
 
3219
                {
 
3220
                  found = 1;
 
3221
                  DBG (DBG_data,
 
3222
                       "gl846_search_strip: strip found forward during pass %d at line %d\n",
 
3223
                       pass, y);
 
3224
                }
 
3225
              else
 
3226
                {
 
3227
                  DBG (DBG_data,
 
3228
                       "gl846_search_strip: pixels=%d, count=%d (%d%%)\n",
 
3229
                       pixels, count, (100 * count) / pixels);
 
3230
                }
 
3231
            }
 
3232
        }
 
3233
      else                      /* since calibration scans are done forward, we need the whole area
 
3234
                                   to be of the required color when searching backward */
 
3235
        {
 
3236
          count = 0;
 
3237
          for (y = 0; y < lines; y++)
 
3238
            {
 
3239
              /* count of white/black pixels depending on the color searched */
 
3240
              for (x = 0; x < pixels; x++)
 
3241
                {
 
3242
                  /* when searching for black, detect white pixels */
 
3243
                  if (black && data[y * pixels + x] > 90)
 
3244
                    {
 
3245
                      count++;
 
3246
                    }
 
3247
                  /* when searching for white, detect black pixels */
 
3248
                  if (!black && data[y * pixels + x] < 60)
 
3249
                    {
 
3250
                      count++;
 
3251
                    }
 
3252
                }
 
3253
            }
 
3254
 
 
3255
          /* at end of area, if count >= 3%, area is not fully of the desired color
 
3256
           * so we must go to next buffer */
 
3257
          if ((count * 100) / (pixels * lines) < 3)
 
3258
            {
 
3259
              found = 1;
 
3260
              DBG (DBG_data,
 
3261
                   "gl846_search_strip: strip found backward during pass %d \n",
 
3262
                   pass);
 
3263
            }
 
3264
          else
 
3265
            {
 
3266
              DBG (DBG_data,
 
3267
                   "gl846_search_strip: pixels=%d, count=%d (%d%%)\n",
 
3268
                   pixels, count, (100 * count) / pixels);
 
3269
            }
 
3270
        }
 
3271
      pass++;
 
3272
    }
 
3273
  free (data);
 
3274
  if (found)
 
3275
    {
 
3276
      status = SANE_STATUS_GOOD;
 
3277
      DBG (DBG_info, "gl846_search_strip: %s strip found\n",
 
3278
           black ? "black" : "white");
 
3279
    }
 
3280
  else
 
3281
    {
 
3282
      status = SANE_STATUS_UNSUPPORTED;
 
3283
      DBG (DBG_info, "gl846_search_strip: %s strip not found\n",
 
3284
           black ? "black" : "white");
 
3285
    }
 
3286
 
 
3287
  DBGCOMPLETED;
 
3288
  return status;
 
3289
}
 
3290
 
 
3291
/**
 
3292
 * average dark pixels of a 8 bits scan
 
3293
 */
 
3294
static int
 
3295
dark_average (uint8_t * data, unsigned int pixels, unsigned int lines,
 
3296
              unsigned int channels, unsigned int black)
 
3297
{
 
3298
  unsigned int i, j, k, average, count;
 
3299
  unsigned int avg[3];
 
3300
  uint8_t val;
 
3301
 
 
3302
  /* computes average value on black margin */
 
3303
  for (k = 0; k < channels; k++)
 
3304
    {
 
3305
      avg[k] = 0;
 
3306
      count = 0;
 
3307
      for (i = 0; i < lines; i++)
 
3308
        {
 
3309
          for (j = 0; j < black; j++)
 
3310
            {
 
3311
              val = data[i * channels * pixels + j + k];
 
3312
              avg[k] += val;
 
3313
              count++;
 
3314
            }
 
3315
        }
 
3316
      if (count)
 
3317
        avg[k] /= count;
 
3318
      DBG (DBG_info, "dark_average: avg[%d] = %d\n", k, avg[k]);
 
3319
    }
 
3320
  average = 0;
 
3321
  for (i = 0; i < channels; i++)
 
3322
    average += avg[i];
 
3323
  average /= channels;
 
3324
  DBG (DBG_info, "dark_average: average = %d\n", average);
 
3325
  return average;
 
3326
}
 
3327
 
 
3328
static SANE_Status
 
3329
gl846_offset_calibration (Genesys_Device * dev)
 
3330
{
 
3331
  SANE_Status status = SANE_STATUS_GOOD;
 
3332
  uint8_t *first_line, *second_line, reg04;
 
3333
  unsigned int channels, bpp;
 
3334
  char title[32];
 
3335
  int pass = 0, avg, total_size;
 
3336
  int topavg, bottomavg, resolution, lines;
 
3337
  int top, bottom, black_pixels, pixels;
 
3338
 
 
3339
  DBGSTART;
 
3340
 
 
3341
  /* no gain nor offset for AKM AFE */
 
3342
  RIE (sanei_genesys_read_register (dev, REG04, &reg04));
 
3343
  if ((reg04 & REG04_FESET) == 0x02)
 
3344
    {
 
3345
      DBGCOMPLETED;
 
3346
      return status;
 
3347
    }
 
3348
 
 
3349
  /* offset calibration is always done in color mode */
 
3350
  channels = 3;
 
3351
  resolution=dev->sensor.optical_res;
 
3352
  dev->calib_pixels = dev->sensor.sensor_pixels;
 
3353
  lines=1;
 
3354
  bpp=8;
 
3355
  pixels= (dev->sensor.sensor_pixels*resolution) / dev->sensor.optical_res;
 
3356
  black_pixels = (dev->sensor.black_pixels * resolution) / dev->sensor.optical_res;
 
3357
  DBG (DBG_io2, "gl846_offset_calibration: black_pixels=%d\n", black_pixels);
 
3358
 
 
3359
  status = gl846_init_scan_regs (dev,
 
3360
                                 dev->calib_reg,
 
3361
                                 resolution,
 
3362
                                 resolution,
 
3363
                                 0,
 
3364
                                 0,
 
3365
                                 pixels,
 
3366
                                 lines,
 
3367
                                 bpp,
 
3368
                                 channels,
 
3369
                                 dev->settings.color_filter,
 
3370
                                 SCAN_FLAG_DISABLE_SHADING |
 
3371
                                 SCAN_FLAG_DISABLE_GAMMA |
 
3372
                                 SCAN_FLAG_SINGLE_LINE |
 
3373
                                 SCAN_FLAG_IGNORE_LINE_DISTANCE);
 
3374
  if (status != SANE_STATUS_GOOD)
 
3375
    {
 
3376
      DBG (DBG_error,
 
3377
           "gl846_offset_calibration: failed to setup scan: %s\n",
 
3378
           sane_strstatus (status));
 
3379
      return status;
 
3380
    }
 
3381
  gl846_set_motor_power (dev->calib_reg, SANE_FALSE);
 
3382
 
 
3383
  /* allocate memory for scans */
 
3384
  total_size = pixels * channels * lines * (bpp/8);     /* colors * bytes_per_color * scan lines */
 
3385
 
 
3386
  first_line = malloc (total_size);
 
3387
  if (!first_line)
 
3388
    return SANE_STATUS_NO_MEM;
 
3389
 
 
3390
  second_line = malloc (total_size);
 
3391
  if (!second_line)
 
3392
    {
 
3393
      free (first_line);
 
3394
      return SANE_STATUS_NO_MEM;
 
3395
    }
 
3396
 
 
3397
  /* init gain */
 
3398
  dev->frontend.gain[0] = 0;
 
3399
  dev->frontend.gain[1] = 0;
 
3400
  dev->frontend.gain[2] = 0;
 
3401
 
 
3402
  /* scan with no move */
 
3403
  bottom = 10;
 
3404
  dev->frontend.offset[0] = bottom;
 
3405
  dev->frontend.offset[1] = bottom;
 
3406
  dev->frontend.offset[2] = bottom;
 
3407
 
 
3408
  RIEF2 (gl846_set_fe(dev, AFE_SET), first_line, second_line);
 
3409
  RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS), first_line, second_line);
 
3410
  DBG (DBG_info, "gl846_offset_calibration: starting first line reading\n");
 
3411
  RIEF2 (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line);
 
3412
  RIEF2 (sanei_genesys_read_data_from_scanner (dev, first_line, total_size), first_line, second_line);
 
3413
  if (DBG_LEVEL >= DBG_data)
 
3414
   {
 
3415
      snprintf(title,20,"offset%03d.pnm",bottom);
 
3416
      sanei_genesys_write_pnm_file (title, first_line, bpp, channels, pixels, lines);
 
3417
   }
 
3418
     
 
3419
  bottomavg = dark_average (first_line, pixels, lines, channels, black_pixels);
 
3420
  DBG (DBG_io2, "gl846_offset_calibration: bottom avg=%d\n", bottomavg);
 
3421
 
 
3422
  /* now top value */
 
3423
  top = 255;
 
3424
  dev->frontend.offset[0] = top;
 
3425
  dev->frontend.offset[1] = top;
 
3426
  dev->frontend.offset[2] = top;
 
3427
  RIEF2 (gl846_set_fe(dev, AFE_SET), first_line, second_line);
 
3428
  RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS), first_line, second_line);
 
3429
  DBG (DBG_info, "gl846_offset_calibration: starting second line reading\n");
 
3430
  RIEF2 (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line);
 
3431
  RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line);
 
3432
      
 
3433
  topavg = dark_average (second_line, pixels, lines, channels, black_pixels);
 
3434
  DBG (DBG_io2, "gl846_offset_calibration: top avg=%d\n", topavg);
 
3435
 
 
3436
  /* loop until acceptable level */
 
3437
  while ((pass < 32) && (top - bottom > 1))
 
3438
    {
 
3439
      pass++;
 
3440
 
 
3441
      /* settings for new scan */
 
3442
      dev->frontend.offset[0] = (top + bottom) / 2;
 
3443
      dev->frontend.offset[1] = (top + bottom) / 2;
 
3444
      dev->frontend.offset[2] = (top + bottom) / 2;
 
3445
 
 
3446
      /* scan with no move */
 
3447
      RIEF2 (gl846_set_fe(dev, AFE_SET), first_line, second_line);
 
3448
      RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS), first_line, second_line);
 
3449
      DBG (DBG_info, "gl846_offset_calibration: starting second line reading\n");
 
3450
      RIEF2 (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line);
 
3451
      RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line);
 
3452
 
 
3453
      if (DBG_LEVEL >= DBG_data)
 
3454
        {
 
3455
          sprintf (title, "offset%03d.pnm", dev->frontend.offset[1]);
 
3456
          sanei_genesys_write_pnm_file (title, second_line, bpp, channels, pixels, lines);
 
3457
        }
 
3458
 
 
3459
      avg = dark_average (second_line, pixels, lines, channels, black_pixels);
 
3460
      DBG (DBG_info, "gl846_offset_calibration: avg=%d offset=%d\n", avg,
 
3461
           dev->frontend.offset[1]);
 
3462
 
 
3463
      /* compute new boundaries */
 
3464
      if (topavg == avg)
 
3465
        {
 
3466
          topavg = avg;
 
3467
          top = dev->frontend.offset[1];
 
3468
        }
 
3469
      else
 
3470
        {
 
3471
          bottomavg = avg;
 
3472
          bottom = dev->frontend.offset[1];
 
3473
        }
 
3474
    }
 
3475
  DBG (DBG_info, "gl846_offset_calibration: offset=(%d,%d,%d)\n", dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]);
 
3476
 
 
3477
  /* cleanup before return */
 
3478
  free (first_line);
 
3479
  free (second_line);
 
3480
 
 
3481
  DBGCOMPLETED;
 
3482
  return SANE_STATUS_GOOD;
 
3483
}
 
3484
 
 
3485
static SANE_Status
 
3486
gl846_coarse_gain_calibration (Genesys_Device * dev, int dpi)
 
3487
{
 
3488
  int pixels;
 
3489
  int total_size;
 
3490
  uint8_t *line, reg04;
 
3491
  int i, j, channels;
 
3492
  SANE_Status status = SANE_STATUS_GOOD;
 
3493
  int max[3];
 
3494
  float gain[3],coeff;
 
3495
  int val, code, lines;
 
3496
  int resolution;
 
3497
  int bpp;
 
3498
 
 
3499
  DBG (DBG_proc, "gl846_coarse_gain_calibration: dpi = %d\n", dpi);
 
3500
 
 
3501
  /* no gain nor offset for AKM AFE */
 
3502
  RIE (sanei_genesys_read_register (dev, REG04, &reg04));
 
3503
  if ((reg04 & REG04_FESET) == 0x02)
 
3504
    {
 
3505
      DBGCOMPLETED;
 
3506
      return status;
 
3507
    }
 
3508
 
 
3509
  /* coarse gain calibration is always done in color mode */
 
3510
  channels = 3;
 
3511
 
 
3512
  /* follow CKSEL */
 
3513
  if(dev->settings.xres<dev->sensor.optical_res)
 
3514
    {
 
3515
      coeff=0.9;
 
3516
      /*resolution=dev->sensor.optical_res/2;*/
 
3517
      resolution=dev->sensor.optical_res;
 
3518
    }
 
3519
  else
 
3520
    {
 
3521
      resolution=dev->sensor.optical_res;
 
3522
      coeff=1.0;
 
3523
    }
 
3524
  lines=10;
 
3525
  bpp=8;
 
3526
  pixels = (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res;
 
3527
 
 
3528
  status = gl846_init_scan_regs (dev,
 
3529
                                 dev->calib_reg,
 
3530
                                 resolution,
 
3531
                                 resolution,
 
3532
                                 0,
 
3533
                                 0,
 
3534
                                 pixels,
 
3535
                                 lines,
 
3536
                                 bpp,
 
3537
                                 channels,
 
3538
                                 dev->settings.color_filter,
 
3539
                                 SCAN_FLAG_DISABLE_SHADING |
 
3540
                                 SCAN_FLAG_DISABLE_GAMMA |
 
3541
                                 SCAN_FLAG_SINGLE_LINE |
 
3542
                                 SCAN_FLAG_IGNORE_LINE_DISTANCE);
 
3543
  gl846_set_motor_power (dev->calib_reg, SANE_FALSE);
 
3544
 
 
3545
  if (status != SANE_STATUS_GOOD)
 
3546
    {
 
3547
      DBG (DBG_error,
 
3548
           "gl846_coarse_calibration: failed to setup scan: %s\n",
 
3549
           sane_strstatus (status));
 
3550
      return status;
 
3551
    }
 
3552
 
 
3553
  RIE (dev->model->cmd_set->bulk_write_register
 
3554
       (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS));
 
3555
 
 
3556
  total_size = pixels * channels * (16/bpp) * lines;
 
3557
 
 
3558
  line = malloc (total_size);
 
3559
  if (!line)
 
3560
    return SANE_STATUS_NO_MEM;
 
3561
 
 
3562
  RIEF (gl846_set_fe(dev, AFE_SET), line);
 
3563
  RIEF (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), line);
 
3564
  RIEF (sanei_genesys_read_data_from_scanner (dev, line, total_size), line);
 
3565
 
 
3566
  if (DBG_LEVEL >= DBG_data)
 
3567
    sanei_genesys_write_pnm_file ("coarse.pnm", line, bpp, channels, pixels, lines);
 
3568
 
 
3569
  /* average value on each channel */
 
3570
  for (j = 0; j < channels; j++)
 
3571
    {
 
3572
      max[j] = 0;
 
3573
      for (i = pixels/4; i < (pixels*3/4); i++)
 
3574
        {
 
3575
          if(bpp==16)
 
3576
            {
 
3577
          if (dev->model->is_cis)
 
3578
            val =
 
3579
              line[i * 2 + j * 2 * pixels + 1] * 256 +
 
3580
              line[i * 2 + j * 2 * pixels];
 
3581
          else
 
3582
            val =
 
3583
              line[i * 2 * channels + 2 * j + 1] * 256 +
 
3584
              line[i * 2 * channels + 2 * j];
 
3585
            }
 
3586
          else
 
3587
            {
 
3588
          if (dev->model->is_cis)
 
3589
            val = line[i + j * pixels];
 
3590
          else
 
3591
            val = line[i * channels + j];
 
3592
            }
 
3593
 
 
3594
            max[j] += val;
 
3595
        }
 
3596
      max[j] = max[j] / (pixels/2);
 
3597
 
 
3598
      gain[j] = ((float) dev->sensor.gain_white_ref*coeff) / max[j];
 
3599
 
 
3600
      /* turn logical gain value into gain code, checking for overflow */
 
3601
      code = 283 - 208 / gain[j];
 
3602
      if (code > 255)
 
3603
        code = 255;
 
3604
      else if (code < 0)
 
3605
        code = 0;
 
3606
      dev->frontend.gain[j] = code;
 
3607
 
 
3608
      DBG (DBG_proc,
 
3609
           "gl846_coarse_gain_calibration: channel %d, max=%d, gain = %f, setting:%d\n",
 
3610
           j, max[j], gain[j], dev->frontend.gain[j]);
 
3611
    }
 
3612
 
 
3613
  if (dev->model->is_cis)
 
3614
    {
 
3615
      if (dev->frontend.gain[0] > dev->frontend.gain[1])
 
3616
        dev->frontend.gain[0] = dev->frontend.gain[1];
 
3617
      if (dev->frontend.gain[0] > dev->frontend.gain[2])
 
3618
        dev->frontend.gain[0] = dev->frontend.gain[2];
 
3619
      dev->frontend.gain[2] = dev->frontend.gain[1] = dev->frontend.gain[0];
 
3620
    }
 
3621
 
 
3622
  if (channels == 1)
 
3623
    {
 
3624
      dev->frontend.gain[0] = dev->frontend.gain[1];
 
3625
      dev->frontend.gain[2] = dev->frontend.gain[1];
 
3626
    }
 
3627
 
 
3628
  free (line);
 
3629
 
 
3630
  RIE (gl846_stop_action (dev));
 
3631
 
 
3632
  status=gl846_slow_back_home (dev, SANE_TRUE);
 
3633
 
 
3634
  DBGCOMPLETED;
 
3635
  return status;
 
3636
}
 
3637
 
 
3638
 
 
3639
/** the gl846 command set */
 
3640
static Genesys_Command_Set gl846_cmd_set = {
 
3641
  "gl846-generic",              /* the name of this set */
 
3642
 
 
3643
  gl846_init,
 
3644
  NULL,
 
3645
  gl846_init_regs_for_coarse_calibration,
 
3646
  gl846_init_regs_for_shading,
 
3647
  gl846_init_regs_for_scan,
 
3648
 
 
3649
  gl846_get_filter_bit,
 
3650
  gl846_get_lineart_bit,
 
3651
  gl846_get_bitset_bit,
 
3652
  gl846_get_gain4_bit,
 
3653
  gl846_get_fast_feed_bit,
 
3654
  gl846_test_buffer_empty_bit,
 
3655
  gl846_test_motor_flag_bit,
 
3656
 
 
3657
  gl846_bulk_full_size,
 
3658
 
 
3659
  gl846_set_fe,
 
3660
  gl846_set_powersaving,
 
3661
  gl846_save_power,
 
3662
 
 
3663
  gl846_set_motor_power,
 
3664
  gl846_set_lamp_power,
 
3665
 
 
3666
  gl846_begin_scan,
 
3667
  gl846_end_scan,
 
3668
 
 
3669
  sanei_genesys_send_gamma_table,
 
3670
 
 
3671
  gl846_search_start_position,
 
3672
 
 
3673
  gl846_offset_calibration,
 
3674
  gl846_coarse_gain_calibration,
 
3675
  gl846_led_calibration,
 
3676
 
 
3677
  gl846_slow_back_home,
 
3678
 
 
3679
  sanei_genesys_bulk_write_register,
 
3680
  NULL,
 
3681
  gl846_bulk_read_data,
 
3682
 
 
3683
  gl846_update_hardware_sensors,
 
3684
 
 
3685
  NULL,
 
3686
  NULL,
 
3687
  NULL,
 
3688
  gl846_search_strip,
 
3689
 
 
3690
  sanei_genesys_is_compatible_calibration,
 
3691
  NULL,
 
3692
  gl846_send_shading_data,
 
3693
  gl846_calculate_current_setup,
 
3694
  gl846_boot
 
3695
};
 
3696
 
 
3697
SANE_Status
 
3698
sanei_gl846_init_cmd_set (Genesys_Device * dev)
 
3699
{
 
3700
  dev->model->cmd_set = &gl846_cmd_set;
 
3701
  return SANE_STATUS_GOOD;
 
3702
}
 
3703
 
 
3704
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */