~ubuntu-branches/ubuntu/saucy/sane-backends/saucy

« back to all changes in this revision

Viewing changes to backend/genesys_gl847.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Ancell
  • Date: 2011-02-14 14:28:56 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110214142856-6gxjetg88q9zctid
Tags: 1.0.22-0ubuntu1
* New upstream release
* debian/control:
  - Use standards version 3.9.1
* debian/patches/allow_dll.d_symlinks.patch:
* debian/patches/fix_epson2_cancel.patch:
* debian/patches/fix_epson2_commands.patch:
* debian/patches/fix_xerox_mfp_color_mode.patch:
* debian/patches/genesys_disable_raw_data_log.patch:
* debian/patches/no_translations.patch:
* debian/patches/saned_exit_avahi_process.patch:
* debian/patches/scsi_perfection_2450.patch:
* debian/patches/scsi_scanjet_4c.patch:
* debian/patches/xerox_mfp_new_ids.patch:
  - Applied upstream
* debian/watch:
  - Dropped, the URL is not consistent between releases

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* sane - Scanner Access Now Easy.
 
2
 
 
3
   Copyright (C) 2010 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
#include "genesys_gl847.h"
 
46
 
 
47
/****************************************************************************
 
48
 Low level function
 
49
 ****************************************************************************/
 
50
 
 
51
/**
 
52
 * decodes and prints content of status (0x41) register
 
53
 * @param val value read from reg41
 
54
 */
 
55
static void
 
56
print_status (uint8_t val)
 
57
{
 
58
  char msg[80];
 
59
 
 
60
  sprintf (msg, "%s%s%s%s%s%s%s%s",
 
61
           val & REG41_PWRBIT ? "PWRBIT " : "",
 
62
           val & REG41_BUFEMPTY ? "BUFEMPTY " : "",
 
63
           val & REG41_FEEDFSH ? "FEEDFSH " : "",
 
64
           val & REG41_SCANFSH ? "SCANFSH " : "",
 
65
           val & REG41_HOMESNR ? "HOMESNR " : "",
 
66
           val & REG41_LAMPSTS ? "LAMPSTS " : "",
 
67
           val & REG41_FEBUSY ? "FEBUSY " : "",
 
68
           val & REG41_MOTORENB ? "MOTORENB" : "");
 
69
  DBG (DBG_info, "status=%s\n", msg);
 
70
}
 
71
 
 
72
/* ------------------------------------------------------------------------ */
 
73
/*                  Read and write RAM, registers and AFE                   */
 
74
/* ------------------------------------------------------------------------ */
 
75
 
 
76
/**
 
77
 * Write to many GL847 registers at once
 
78
 * Note: sequential call to write register, no effective
 
79
 * bulk write implemented.
 
80
 * @param dev device to write to
 
81
 * @param reg pointer to an array of registers
 
82
 * @param elems size of the array
 
83
 */
 
84
#ifndef UNIT_TESTING
 
85
static
 
86
#endif
 
87
  SANE_Status
 
88
gl847_bulk_write_register (Genesys_Device * dev,
 
89
                           Genesys_Register_Set * reg, size_t elems)
 
90
{
 
91
  SANE_Status status = SANE_STATUS_GOOD;
 
92
  size_t i;
 
93
 
 
94
  for (i = 0; i < elems && status == SANE_STATUS_GOOD; i++)
 
95
    {
 
96
      if (reg[i].address != 0)
 
97
        {
 
98
          status =
 
99
            sanei_genesys_write_register (dev, reg[i].address, reg[i].value);
 
100
        }
 
101
    }
 
102
 
 
103
  DBG (DBG_io, "gl847_bulk_write_register: wrote %lu registers\n",
 
104
       (u_long) elems);
 
105
  return status;
 
106
}
 
107
 
 
108
/** @brief read scanned data
 
109
 * Read in 0xeff0 maximum sized blocks. This read is done in 2
 
110
 * parts if not multple of 512. First read is rounded to a multiple of 512 bytes, last read fetches the 
 
111
 * remainder. Read addr is always 0x10000000 with the memory layout setup.
 
112
 * @param dev device to read data from
 
113
 * @param addr address within ASIC emory space
 
114
 * @param data pointer where to store the read data
 
115
 * @param len size to read
 
116
 */
 
117
static SANE_Status
 
118
gl847_bulk_read_data (Genesys_Device * dev, uint8_t addr,
 
119
                      uint8_t * data, size_t len)
 
120
{
 
121
  SANE_Status status;
 
122
  size_t size, target, read, done;
 
123
  uint8_t outdata[8];
 
124
 
 
125
  DBG (DBG_io, "gl847_bulk_read_data: requesting %lu bytes\n", (u_long) len);
 
126
 
 
127
  if (len == 0)
 
128
    return SANE_STATUS_GOOD;
 
129
 
 
130
  target = len;
 
131
 
 
132
  /* loop until computed data size is read */
 
133
  while (target)
 
134
    {
 
135
      if (target > 0xeff0)
 
136
        {
 
137
          size = 0xeff0;
 
138
        }
 
139
      else
 
140
        {
 
141
          size = target;
 
142
        }
 
143
 
 
144
      /* hard coded 0x10000000 addr */
 
145
      outdata[0] = 0;
 
146
      outdata[1] = 0;
 
147
      outdata[2] = 0;
 
148
      outdata[3] = 0x10;
 
149
 
 
150
      /* data size to transfer */
 
151
      outdata[4] = (size & 0xff);
 
152
      outdata[5] = ((size >> 8) & 0xff);
 
153
      outdata[6] = ((size >> 16) & 0xff);
 
154
      outdata[7] = ((size >> 24) & 0xff);
 
155
 
 
156
      status =
 
157
        sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER,
 
158
                               VALUE_BUFFER, 0x00, sizeof (outdata),
 
159
                               outdata);
 
160
      if (status != SANE_STATUS_GOOD)
 
161
        {
 
162
          DBG (DBG_error, "%s failed while writing command: %s\n",
 
163
               __FUNCTION__, sane_strstatus (status));
 
164
          return status;
 
165
        }
 
166
 
 
167
      /* blocks must be multiple of 512 but not last block */
 
168
      read = size;
 
169
      if (read >= 512)
 
170
        {
 
171
          read /= 512;
 
172
          read *= 512;
 
173
        }
 
174
     
 
175
      DBG (DBG_io2,
 
176
           "gl847_bulk_read_data: trying to read %lu bytes of data\n",
 
177
           (u_long) read);
 
178
      status = sanei_usb_read_bulk (dev->dn, data, &read);
 
179
      if (status != SANE_STATUS_GOOD)
 
180
        {
 
181
          DBG (DBG_error,
 
182
               "gl847_bulk_read_data failed while reading bulk data: %s\n",
 
183
               sane_strstatus (status));
 
184
          return status;
 
185
        }
 
186
 
 
187
      /* read less than 512 bytes remainder */
 
188
      if (read < size)
 
189
        {
 
190
          done=read;
 
191
          read = size - read;
 
192
          DBG (DBG_io2,
 
193
               "gl847_bulk_read_data: trying to read %lu bytes of data\n",
 
194
               (u_long) read);
 
195
          status = sanei_usb_read_bulk (dev->dn, data+done, &read);
 
196
          if (status != SANE_STATUS_GOOD)
 
197
            {
 
198
              DBG (DBG_error,
 
199
                   "gl847_bulk_read_data failed while reading bulk data: %s\n",
 
200
                   sane_strstatus (status));
 
201
              return status;
 
202
            }
 
203
        }
 
204
 
 
205
      DBG (DBG_io2, "%s: read %lu bytes, %lu remaining\n", __FUNCTION__,
 
206
           (u_long) size, (u_long) (target - size));
 
207
 
 
208
      target -= size;
 
209
      data += size;
 
210
    }
 
211
 
 
212
  DBGCOMPLETED;
 
213
 
 
214
  return SANE_STATUS_GOOD;
 
215
}
 
216
 
 
217
/****************************************************************************
 
218
 Mid level functions 
 
219
 ****************************************************************************/
 
220
 
 
221
static SANE_Bool
 
222
gl847_get_fast_feed_bit (Genesys_Register_Set * regs)
 
223
{
 
224
  Genesys_Register_Set *r = NULL;
 
225
 
 
226
  r = sanei_genesys_get_address (regs, REG02);
 
227
  if (r && (r->value & REG02_FASTFED))
 
228
    return SANE_TRUE;
 
229
  return SANE_FALSE;
 
230
}
 
231
 
 
232
static SANE_Bool
 
233
gl847_get_filter_bit (Genesys_Register_Set * regs)
 
234
{
 
235
  Genesys_Register_Set *r = NULL;
 
236
 
 
237
  r = sanei_genesys_get_address (regs, REG04);
 
238
  if (r && (r->value & REG04_FILTER))
 
239
    return SANE_TRUE;
 
240
  return SANE_FALSE;
 
241
}
 
242
 
 
243
static SANE_Bool
 
244
gl847_get_lineart_bit (Genesys_Register_Set * regs)
 
245
{
 
246
  Genesys_Register_Set *r = NULL;
 
247
 
 
248
  r = sanei_genesys_get_address (regs, REG04);
 
249
  if (r && (r->value & REG04_LINEART))
 
250
    return SANE_TRUE;
 
251
  return SANE_FALSE;
 
252
}
 
253
 
 
254
static SANE_Bool
 
255
gl847_get_bitset_bit (Genesys_Register_Set * regs)
 
256
{
 
257
  Genesys_Register_Set *r = NULL;
 
258
 
 
259
  r = sanei_genesys_get_address (regs, REG04);
 
260
  if (r && (r->value & REG04_BITSET))
 
261
    return SANE_TRUE;
 
262
  return SANE_FALSE;
 
263
}
 
264
 
 
265
static SANE_Bool
 
266
gl847_get_gain4_bit (Genesys_Register_Set * regs)
 
267
{
 
268
  Genesys_Register_Set *r = NULL;
 
269
 
 
270
  r = sanei_genesys_get_address (regs, 0x06);
 
271
  if (r && (r->value & REG06_GAIN4))
 
272
    return SANE_TRUE;
 
273
  return SANE_FALSE;
 
274
}
 
275
 
 
276
static SANE_Bool
 
277
gl847_test_buffer_empty_bit (SANE_Byte val)
 
278
{
 
279
  if (val & REG41_BUFEMPTY)
 
280
    return SANE_TRUE;
 
281
  return SANE_FALSE;
 
282
}
 
283
 
 
284
static SANE_Bool
 
285
gl847_test_motor_flag_bit (SANE_Byte val)
 
286
{
 
287
  if (val & REG41_MOTORENB)
 
288
    return SANE_TRUE;
 
289
  return SANE_FALSE;
 
290
}
 
291
 
 
292
 
 
293
/** @brief sensor specific settings
 
294
*/
 
295
static void
 
296
gl847_setup_sensor (Genesys_Device * dev, Genesys_Register_Set * regs)
 
297
{
 
298
  Genesys_Register_Set *r;
 
299
  int i;
 
300
 
 
301
  DBGSTART;
 
302
 
 
303
  for (i = 0x06; i < 0x0e; i++)
 
304
    {
 
305
      r = sanei_genesys_get_address (regs, 0x10 + i);
 
306
      if (r)
 
307
        r->value = dev->sensor.regs_0x10_0x1d[i];
 
308
    }
 
309
 
 
310
  for (i = 0; i < 9; i++)
 
311
    {
 
312
      r = sanei_genesys_get_address (regs, 0x52 + i);
 
313
      if (r)
 
314
        r->value = dev->sensor.regs_0x52_0x5e[i];
 
315
    }
 
316
 
 
317
  DBGCOMPLETED;
 
318
}
 
319
 
 
320
 
 
321
/* returns the max register bulk size */
 
322
static int
 
323
gl847_bulk_full_size (void)
 
324
{
 
325
  return GENESYS_GL847_MAX_REGS;
 
326
}
 
327
 
 
328
/** @brief set all registers to default values .
 
329
 * This function is called only once at the beginning and
 
330
 * fills register startup values for registers reused across scans.
 
331
 * Those that are rarely modified or not modified are written
 
332
 * individually.
 
333
 * @param dev device structure holding register set to initialize
 
334
 */
 
335
static void
 
336
gl847_init_registers (Genesys_Device * dev)
 
337
{
 
338
  DBGSTART;
 
339
 
 
340
  memset (dev->reg, 0,
 
341
          GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set));
 
342
 
 
343
  SETREG (0x01, 0x82);
 
344
  SETREG (0x02, 0x18);
 
345
  SETREG (0x03, 0x50);
 
346
  SETREG (0x04, 0x12);
 
347
  SETREG (0x05, 0x80);
 
348
  SETREG (0x06, 0x50);          /* FASTMODE + POWERBIT */
 
349
  SETREG (0x08, 0x10);
 
350
  SETREG (0x09, 0x01);
 
351
  SETREG (0x0a, 0x00);
 
352
  SETREG (0x0b, 0x01);
 
353
  SETREG (0x0c, 0x02);
 
354
  /* SETREG (0x0d, REG0D_CLRMCNT); */
 
355
  SETREG (0x10, 0x00);
 
356
  SETREG (0x11, 0x00);
 
357
  SETREG (0x12, 0x00);
 
358
  SETREG (0x13, 0x00);
 
359
  SETREG (0x14, 0x00);
 
360
  SETREG (0x15, 0x00);
 
361
  SETREG (0x16, 0x10);
 
362
  SETREG (0x17, 0x08);
 
363
  SETREG (0x18, 0x00);
 
364
  SETREG (0x19, 0x50);
 
365
  SETREG (0x1a, 0x34);
 
366
  SETREG (0x1b, 0x00);
 
367
  SETREG (0x1c, 0x02);
 
368
  SETREG (0x1d, 0x04);
 
369
  SETREG (0x1e, 0x10);
 
370
  SETREG (0x1f, 0x04);
 
371
  SETREG (0x20, 0x02);
 
372
  SETREG (0x21, 0x10);
 
373
  SETREG (0x22, 0x7f);
 
374
  SETREG (0x23, 0x7f);
 
375
  SETREG (0x24, 0x10);
 
376
  SETREG (0x25, 0x00);
 
377
  SETREG (0x26, 0x00);
 
378
  SETREG (0x27, 0x00);
 
379
  SETREG (0x2c, 0x09);
 
380
  SETREG (0x2d, 0x60);
 
381
  SETREG (0x2e, 0x80);
 
382
  SETREG (0x2f, 0x80);
 
383
  SETREG (0x30, 0x00);
 
384
  SETREG (0x31, 0x10);
 
385
  SETREG (0x32, 0x15);
 
386
  SETREG (0x33, 0x0e);
 
387
  SETREG (0x34, 0x40);
 
388
  SETREG (0x35, 0x00);
 
389
  SETREG (0x36, 0x2a);
 
390
  SETREG (0x37, 0x30);
 
391
  SETREG (0x38, 0x2a);
 
392
  SETREG (0x39, 0xf8);
 
393
  SETREG (0x3d, 0x00);
 
394
  SETREG (0x3e, 0x00);
 
395
  SETREG (0x3f, 0x00);
 
396
  SETREG (0x52, 0x03);
 
397
  SETREG (0x53, 0x07);
 
398
  SETREG (0x54, 0x00);
 
399
  SETREG (0x55, 0x00);
 
400
  SETREG (0x56, 0x00);
 
401
  SETREG (0x57, 0x00);
 
402
  SETREG (0x58, 0x2a);
 
403
  SETREG (0x59, 0xe1);
 
404
  SETREG (0x5a, 0x55);
 
405
  SETREG (0x5e, 0x41);
 
406
  SETREG (0x5f, 0x40);
 
407
  SETREG (0x60, 0x00);
 
408
  SETREG (0x61, 0x21);
 
409
  SETREG (0x62, 0x40);
 
410
  SETREG (0x63, 0x00);
 
411
  SETREG (0x64, 0x21);
 
412
  SETREG (0x65, 0x40);
 
413
  SETREG (0x67, 0x80);
 
414
  SETREG (0x68, 0x80);
 
415
  SETREG (0x69, 0x20);
 
416
  SETREG (0x6a, 0x20);
 
417
  SETREG (0x74, 0x00);
 
418
  SETREG (0x75, 0x00);
 
419
  SETREG (0x76, 0x3c);
 
420
  SETREG (0x7a, 0x00);
 
421
  SETREG (0x7b, 0x00);
 
422
  SETREG (0x7c, 0x55);
 
423
  SETREG (0x7d, 0x00);
 
424
  /* NOTE: autoconf is a non working option */
 
425
  SETREG (0x87, 0x02);
 
426
  SETREG (0x9d, 0x06);
 
427
  SETREG (0x9d, 0x00); /* 1x multiplier instead of 8x */
 
428
  SETREG (0xa2, 0x0f);
 
429
  SETREG (0xa6, 0x04);
 
430
  SETREG (0xbd, 0x18);
 
431
  SETREG (0xfe, 0x08);
 
432
 
 
433
  /* gamma[0] and gamma[256] values */
 
434
  SETREG (0xbe, 0x00);
 
435
  SETREG (0xc5, 0x00);
 
436
  SETREG (0xc6, 0x00);
 
437
  SETREG (0xc7, 0x00);
 
438
  SETREG (0xc8, 0x00);
 
439
  SETREG (0xc9, 0x00);
 
440
  SETREG (0xca, 0x00);
 
441
 
 
442
  /* fine tune upon device description */
 
443
  dev->reg[reg_0x05].value &= ~REG05_DPIHW;
 
444
  switch (dev->sensor.optical_res)
 
445
    {
 
446
    case 600:
 
447
      dev->reg[reg_0x05].value |= REG05_DPIHW_600;
 
448
      break;
 
449
    case 1200:
 
450
      dev->reg[reg_0x05].value |= REG05_DPIHW_1200;
 
451
      break;
 
452
    case 2400:
 
453
      dev->reg[reg_0x05].value |= REG05_DPIHW_2400;
 
454
      break;
 
455
    case 4800:
 
456
      dev->reg[reg_0x05].value |= REG05_DPIHW_4800;
 
457
      break;
 
458
    }
 
459
 
 
460
  /* initalize calibration reg */
 
461
  memcpy (dev->calib_reg, dev->reg,
 
462
          GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set));
 
463
 
 
464
  DBGCOMPLETED;
 
465
}
 
466
 
 
467
/**@brief send slope table for motor movement 
 
468
 * Send slope_table in machine byte order
 
469
 * @param dev device to send slope table
 
470
 * @param table_nr index of the slope table in ASIC memory
 
471
 * Must be in the [0-4] range.
 
472
 * @param slope_table pointer to 16 bit values array of the slope table
 
473
 * @param steps number of elemnts in the slope table
 
474
 */
 
475
static SANE_Status
 
476
gl847_send_slope_table (Genesys_Device * dev, int table_nr,
 
477
                        uint16_t * slope_table, int steps)
 
478
{
 
479
  SANE_Status status;
 
480
  uint8_t *table;
 
481
  int i;
 
482
  char msg[2048];
 
483
 
 
484
  DBG (DBG_proc, "%s (table_nr = %d, steps = %d)\n", __FUNCTION__,
 
485
       table_nr, steps);
 
486
 
 
487
  /* sanity check */
 
488
  if(table_nr<0 || table_nr>4)
 
489
    {
 
490
      DBG (DBG_error, "%s: invalid table number %d!\n", __FUNCTION__, table_nr);
 
491
      return SANE_STATUS_INVAL;
 
492
    }
 
493
 
 
494
  table = (uint8_t *) malloc (steps * 2);
 
495
  for (i = 0; i < steps; i++)
 
496
    {
 
497
      table[i * 2] = slope_table[i] & 0xff;
 
498
      table[i * 2 + 1] = slope_table[i] >> 8;
 
499
    }
 
500
 
 
501
  if (DBG_LEVEL >= DBG_io)
 
502
    {
 
503
      sprintf (msg, "write slope %d (%d)=", table_nr, steps);
 
504
      for (i = 0; i < steps; i++)
 
505
        {
 
506
          sprintf (msg, "%s,%d", msg, slope_table[i]);
 
507
        }
 
508
      DBG (DBG_io, "%s: %s\n", __FUNCTION__, msg);
 
509
    }
 
510
 
 
511
  /* slope table addresses are fixed */
 
512
  status =
 
513
    sanei_genesys_write_ahb (dev->dn, 0x10000000 + 0x4000 * table_nr, steps * 2, table);
 
514
  if (status != SANE_STATUS_GOOD)
 
515
    {
 
516
      DBG (DBG_error,
 
517
           "%s: write to AHB failed writing slope table %d (%s)\n",
 
518
           __FUNCTION__, table_nr, sane_strstatus (status));
 
519
    }
 
520
 
 
521
  free (table);
 
522
  DBGCOMPLETED;
 
523
  return status;
 
524
}
 
525
 
 
526
/**
 
527
 * Set register values of Analog Device type frontend
 
528
 * */
 
529
static SANE_Status
 
530
gl847_set_ad_fe (Genesys_Device * dev, uint8_t set)
 
531
{
 
532
  SANE_Status status = SANE_STATUS_GOOD;
 
533
  int i;
 
534
  uint16_t val;
 
535
 
 
536
  DBG (DBG_proc, "gl847_set_ad_fe(): start\n");
 
537
  if (set == AFE_INIT)
 
538
    {
 
539
      DBG (DBG_proc, "gl847_set_ad_fe(): setting DAC %u\n",
 
540
           dev->model->dac_type);
 
541
 
 
542
      /* sets to default values */
 
543
      sanei_genesys_init_fe (dev);
 
544
    }
 
545
 
 
546
  /* reset DAC */
 
547
  status = sanei_genesys_fe_write_data (dev, 0x00, 0x80);
 
548
  if (status != SANE_STATUS_GOOD)
 
549
    {
 
550
      DBG (DBG_error, "gl847_set_ad_fe: failed to write reg0: %s\n",
 
551
           sane_strstatus (status));
 
552
      return status;
 
553
    }
 
554
 
 
555
  /* write them to analog frontend */
 
556
  val = dev->frontend.reg[0];
 
557
  status = sanei_genesys_fe_write_data (dev, 0x00, val);
 
558
  if (status != SANE_STATUS_GOOD)
 
559
    {
 
560
      DBG (DBG_error, "gl847_set_ad_fe: failed to write reg0: %s\n",
 
561
           sane_strstatus (status));
 
562
      return status;
 
563
    }
 
564
  val = dev->frontend.reg[1];
 
565
  status = sanei_genesys_fe_write_data (dev, 0x01, val);
 
566
  if (status != SANE_STATUS_GOOD)
 
567
    {
 
568
      DBG (DBG_error, "gl847_set_ad_fe: failed to write reg1: %s\n",
 
569
           sane_strstatus (status));
 
570
      return status;
 
571
    }
 
572
 
 
573
  for (i = 0; i < 3; i++)
 
574
    {
 
575
      val = dev->frontend.gain[i];
 
576
      status = sanei_genesys_fe_write_data (dev, 0x02 + i, val);
 
577
      if (status != SANE_STATUS_GOOD)
 
578
        {
 
579
          DBG (DBG_error,
 
580
               "gl847_set_ad_fe: failed to write gain %d: %s\n", i,
 
581
               sane_strstatus (status));
 
582
          return status;
 
583
        }
 
584
    }
 
585
  for (i = 0; i < 3; i++)
 
586
    {
 
587
      val = dev->frontend.offset[i];
 
588
      status = sanei_genesys_fe_write_data (dev, 0x05 + i, val);
 
589
      if (status != SANE_STATUS_GOOD)
 
590
        {
 
591
          DBG (DBG_error,
 
592
               "gl847_set_ad_fe: failed to write offset %d: %s\n", i,
 
593
               sane_strstatus (status));
 
594
          return status;
 
595
        }
 
596
    }
 
597
 
 
598
  DBG (DBG_proc, "gl847_set_ad_fe(): end\n");
 
599
 
 
600
  return status;
 
601
}
 
602
 
 
603
/* Set values of analog frontend */
 
604
static SANE_Status
 
605
gl847_set_fe (Genesys_Device * dev, uint8_t set)
 
606
{
 
607
  SANE_Status status;
 
608
  uint8_t val;
 
609
 
 
610
  DBG (DBG_proc, "gl847_set_fe (%s)\n",
 
611
       set == AFE_INIT ? "init" : set == AFE_SET ? "set" : set ==
 
612
       AFE_POWER_SAVE ? "powersave" : "huh?");
 
613
  
 
614
  RIE (sanei_genesys_read_register (dev, REG04, &val));
 
615
 
 
616
  /* route to AD devices */
 
617
  if ((val & REG04_FESET) == 0x02)
 
618
    {
 
619
      return gl847_set_ad_fe (dev, set);
 
620
    }
 
621
 
 
622
  /* for now ther is no support for wolfson fe */
 
623
  DBG (DBG_proc, "gl847_set_fe(): unsupported frontend type %d\n",
 
624
       dev->reg[reg_0x04].value & REG04_FESET);
 
625
 
 
626
  DBGCOMPLETED;
 
627
  return SANE_STATUS_UNSUPPORTED;
 
628
}
 
629
 
 
630
#define MOTOR_FLAG_AUTO_GO_HOME             1
 
631
#define MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE 2
 
632
 
 
633
#define MOTOR_ACTION_FEED       1
 
634
#define MOTOR_ACTION_GO_HOME    2
 
635
#define MOTOR_ACTION_HOME_FREE  3
 
636
 
 
637
/** @brief setup motor for off mode
 
638
 * 
 
639
 */
 
640
static SANE_Status
 
641
gl847_init_motor_regs_off (Genesys_Device * dev,
 
642
                           Genesys_Register_Set * reg,
 
643
                           unsigned int scan_lines)
 
644
{
 
645
  unsigned int feedl;
 
646
  Genesys_Register_Set *r;
 
647
 
 
648
  DBG (DBG_proc, "gl847_init_motor_regs_off : scan_lines=%d\n", scan_lines);
 
649
 
 
650
  feedl = 2;
 
651
 
 
652
/* all needed slopes available. we did even decide which mode to use. 
 
653
   what next?
 
654
   - transfer slopes
 
655
SCAN:
 
656
flags \ use_fast_fed    ! 0         1
 
657
------------------------\--------------------
 
658
                      0 ! 0,1,2     0,1,2,3
 
659
MOTOR_FLAG_AUTO_GO_HOME ! 0,1,2,4   0,1,2,3,4
 
660
OFF:       none
 
661
FEED:      3
 
662
GO_HOME:   3
 
663
HOME_FREE: 3
 
664
   - setup registers
 
665
     * slope specific registers (already done)
 
666
     * DECSEL for HOME_FREE/GO_HOME/SCAN
 
667
     * FEEDL
 
668
     * MTRREV
 
669
     * MTRPWR
 
670
     * FASTFED
 
671
     * STEPSEL
 
672
     * MTRPWM
 
673
     * FSTPSEL
 
674
     * FASTPWM
 
675
     * HOMENEG
 
676
     * BWDSTEP
 
677
     * FWDSTEP
 
678
     * Z1
 
679
     * Z2
 
680
 */
 
681
  r = sanei_genesys_get_address (reg, 0x3d);
 
682
  r->value = (feedl >> 16) & 0xf;
 
683
  r = sanei_genesys_get_address (reg, 0x3e);
 
684
  r->value = (feedl >> 8) & 0xff;
 
685
  r = sanei_genesys_get_address (reg, 0x3f);
 
686
  r->value = feedl & 0xff;
 
687
  DBG (DBG_io ,"%s: feedl=%d\n",__FUNCTION__,feedl);
 
688
 
 
689
  r = sanei_genesys_get_address (reg, 0x25);
 
690
  r->value = (scan_lines >> 16) & 0xf;
 
691
  r = sanei_genesys_get_address (reg, 0x26);
 
692
  r->value = (scan_lines >> 8) & 0xff;
 
693
  r = sanei_genesys_get_address (reg, 0x27);
 
694
  r->value = scan_lines & 0xff;
 
695
 
 
696
  r = sanei_genesys_get_address (reg, REG02);
 
697
  r->value &= ~0x01;            /*LONGCURV OFF */
 
698
  r->value &= ~0x80;            /*NOT_HOME OFF */
 
699
 
 
700
  r->value &= ~0x10;
 
701
 
 
702
  r->value &= ~0x06;
 
703
 
 
704
  r->value &= ~0x08;
 
705
 
 
706
  r->value &= ~0x20;
 
707
 
 
708
  r->value &= ~0x40;
 
709
 
 
710
  r = sanei_genesys_get_address (reg, REG67);
 
711
  r->value = REG67_MTRPWM;
 
712
 
 
713
  r = sanei_genesys_get_address (reg, REG68);
 
714
  r->value = REG68_FASTPWM;
 
715
 
 
716
  r = sanei_genesys_get_address (reg, 0x21);
 
717
  r->value = 1;
 
718
 
 
719
  r = sanei_genesys_get_address (reg, 0x24);
 
720
  r->value = 1;
 
721
 
 
722
  r = sanei_genesys_get_address (reg, 0x69);
 
723
  r->value = 1;
 
724
 
 
725
  r = sanei_genesys_get_address (reg, 0x6a);
 
726
  r->value = 1;
 
727
 
 
728
  r = sanei_genesys_get_address (reg, 0x5f);
 
729
  r->value = 1;
 
730
 
 
731
 
 
732
  DBGCOMPLETED;
 
733
  return SANE_STATUS_GOOD;
 
734
}
 
735
 
 
736
static SANE_Status
 
737
gl847_init_motor_regs (Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int feed_steps,       /*1/base_ydpi */
 
738
/*maybe float for half/quarter step resolution?*/
 
739
                       unsigned int action, unsigned int flags)
 
740
{
 
741
  SANE_Status status;
 
742
  unsigned int fast_exposure;
 
743
  int use_fast_fed = 0;
 
744
  uint16_t fast_slope_table[256];
 
745
  uint8_t val;
 
746
  unsigned int fast_slope_time;
 
747
  unsigned int fast_slope_steps = 32;
 
748
  unsigned int feedl;
 
749
  Genesys_Register_Set *r;
 
750
/*number of scan lines to add in a scan_lines line*/
 
751
 
 
752
  DBG (DBG_proc,
 
753
       "gl847_init_motor_regs : feed_steps=%d, action=%d, flags=%x\n",
 
754
       feed_steps, action, flags);
 
755
 
 
756
  if (action == MOTOR_ACTION_FEED || action == MOTOR_ACTION_GO_HOME || action == MOTOR_ACTION_HOME_FREE)
 
757
    {
 
758
      /* FEED and GO_HOME can use fastest slopes available */
 
759
      fast_slope_steps = 256;
 
760
      fast_exposure = sanei_genesys_exposure_time2 (dev,
 
761
                                                    dev->motor.base_ydpi / 4,
 
762
                                                    0,  /*step_type */
 
763
                                                    0,  /*last used pixel */
 
764
                                                    0,
 
765
                                                    0);
 
766
 
 
767
      DBG (DBG_info, "gl847_init_motor_regs : fast_exposure=%d pixels\n",
 
768
           fast_exposure);
 
769
    }
 
770
 
 
771
/* HOME_FREE must be able to stop in one step, so do not try to get faster */
 
772
  /* XXX STEF XXX
 
773
  if (action == MOTOR_ACTION_HOME_FREE)
 
774
    {
 
775
      fast_slope_steps = 256;
 
776
      fast_exposure = dev->motor.slopes[0][0].maximum_start_speed;
 
777
    }
 
778
    */
 
779
 
 
780
  fast_slope_time = sanei_genesys_create_slope_table3 (dev,
 
781
                                                       fast_slope_table,
 
782
                                                       256,
 
783
                                                       fast_slope_steps,
 
784
                                                       0,
 
785
                                                       fast_exposure,
 
786
                                                       dev->motor.base_ydpi / 4,
 
787
                                                       &fast_slope_steps,
 
788
                                                       &fast_exposure,
 
789
                                                       0);
 
790
 
 
791
  feedl = feed_steps - fast_slope_steps * 2;
 
792
  use_fast_fed = 1;
 
793
 
 
794
/* all needed slopes available. we did even decide which mode to use. 
 
795
   what next?
 
796
   - transfer slopes
 
797
SCAN:
 
798
flags \ use_fast_fed    ! 0         1
 
799
------------------------\--------------------
 
800
                      0 ! 0,1,2     0,1,2,3
 
801
MOTOR_FLAG_AUTO_GO_HOME ! 0,1,2,4   0,1,2,3,4
 
802
OFF:       none
 
803
FEED:      3
 
804
GO_HOME:   3
 
805
HOME_FREE: 3
 
806
   - setup registers
 
807
     * slope specific registers (already done)
 
808
     * DECSEL for HOME_FREE/GO_HOME/SCAN
 
809
     * FEEDL
 
810
     * MTRREV
 
811
     * MTRPWR
 
812
     * FASTFED
 
813
     * STEPSEL
 
814
     * MTRPWM
 
815
     * FSTPSEL
 
816
     * FASTPWM
 
817
     * HOMENEG
 
818
     * BWDSTEP
 
819
     * FWDSTEP
 
820
     * Z1
 
821
     * Z2
 
822
 */
 
823
 
 
824
  r = sanei_genesys_get_address (reg, 0x3d);
 
825
  r->value = (feedl >> 16) & 0xf;
 
826
  r = sanei_genesys_get_address (reg, 0x3e);
 
827
  r->value = (feedl >> 8) & 0xff;
 
828
  r = sanei_genesys_get_address (reg, 0x3f);
 
829
  r->value = feedl & 0xff;
 
830
  DBG (DBG_io ,"%s: feedl=%d\n",__FUNCTION__,feedl);
 
831
 
 
832
  r = sanei_genesys_get_address (reg, 0x25);
 
833
  r->value = 0;
 
834
  r = sanei_genesys_get_address (reg, 0x26);
 
835
  r->value = 0;
 
836
  r = sanei_genesys_get_address (reg, 0x27);
 
837
  r->value = 0;
 
838
 
 
839
  /* set REG 02 */
 
840
  r = sanei_genesys_get_address (reg, REG02);
 
841
  r->value &= ~REG02_LONGCURV;
 
842
  r->value &= ~REG02_HOMENEG;
 
843
  r->value &= ~REG02_AGOHOME;
 
844
  r->value &= ~REG02_ACDCDIS;
 
845
 
 
846
  if (flags & MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE)
 
847
    r->value |= REG02_ACDCDIS;
 
848
 
 
849
  r->value |= REG02_MTRPWR;
 
850
 
 
851
  if (action == MOTOR_ACTION_GO_HOME)
 
852
    r->value |= (REG02_MTRREV | REG02_NOTHOME);
 
853
  else
 
854
    r->value &= ~(REG02_MTRREV | REG02_HOMENEG);
 
855
 
 
856
  if (use_fast_fed)
 
857
    r->value |= REG02_FASTFED;
 
858
  else
 
859
    r->value &= ~REG02_FASTFED;
 
860
 
 
861
  if (flags & MOTOR_FLAG_AUTO_GO_HOME)
 
862
    r->value |= REG02_AGOHOME;
 
863
 
 
864
  /* reset gpio pin */
 
865
  RIE (sanei_genesys_read_register (dev, REG6C, &val));
 
866
  val |= REG6C_GPIO13;
 
867
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
868
  RIE (sanei_genesys_read_register (dev, REG6C, &val));
 
869
  val |= REG6C_GPIO12;
 
870
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
871
 
 
872
  status = gl847_send_slope_table (dev, 0, fast_slope_table, 256);
 
873
  status = gl847_send_slope_table (dev, 1, fast_slope_table, 256);
 
874
  status = gl847_send_slope_table (dev, 2, fast_slope_table, 256);
 
875
  status = gl847_send_slope_table (dev, 3, fast_slope_table, 256);
 
876
  status = gl847_send_slope_table (dev, 4, fast_slope_table, 256);
 
877
 
 
878
  if (status != SANE_STATUS_GOOD)
 
879
    return status;
 
880
 
 
881
  r = sanei_genesys_get_address (reg, REG67);
 
882
  r->value = REG67_MTRPWM;
 
883
 
 
884
  r = sanei_genesys_get_address (reg, REG68);
 
885
  r->value = REG68_FASTPWM;
 
886
 
 
887
  r = sanei_genesys_get_address (reg, 0x21);
 
888
  r->value = 1;
 
889
 
 
890
  r = sanei_genesys_get_address (reg, 0x24);
 
891
  r->value = 1;
 
892
 
 
893
  r = sanei_genesys_get_address (reg, REG60);
 
894
  r->value = 0 << REG60S_STEPSEL;
 
895
 
 
896
  r = sanei_genesys_get_address (reg, REG63);
 
897
  r->value = 0 << REG63S_FSTPSEL;
 
898
 
 
899
  r = sanei_genesys_get_address (reg, 0x69);
 
900
  r->value = 1;
 
901
 
 
902
  r = sanei_genesys_get_address (reg, 0x6a);
 
903
  r->value = fast_slope_steps;
 
904
 
 
905
  r = sanei_genesys_get_address (reg, 0x5f);
 
906
  r->value = fast_slope_steps;
 
907
 
 
908
  DBGCOMPLETED;
 
909
  return SANE_STATUS_GOOD;
 
910
}
 
911
 
 
912
/** @brief set up motor related register for scan
 
913
 * the following registers are modified:
 
914
 * 0x02 
 
915
 *
 
916
   - transfer slopes
 
917
SCAN:
 
918
flags \ use_fast_fed    ! 0         1
 
919
------------------------\--------------------
 
920
                      0 ! 0,1,2     0,1,2,3
 
921
MOTOR_FLAG_AUTO_GO_HOME ! 0,1,2,4   0,1,2,3,4
 
922
OFF:       none
 
923
FEED:      3
 
924
GO_HOME:   3
 
925
HOME_FREE: 3
 
926
   - setup registers
 
927
     * slope specific registers (already done)
 
928
     * DECSEL for HOME_FREE/GO_HOME/SCAN
 
929
     * FEEDL
 
930
     * MTRREV
 
931
     * MTRPWR
 
932
     * FASTFED
 
933
     * STEPSEL
 
934
     * MTRPWM
 
935
     * FSTPSEL
 
936
     * FASTPWM
 
937
     * HOMENEG
 
938
     * BWDSTEP
 
939
     * FWDSTEP
 
940
     * Z1
 
941
     * Z2
 
942
     */
 
943
static SANE_Status
 
944
gl847_init_motor_regs_scan (Genesys_Device * dev,
 
945
                            Genesys_Register_Set * reg,
 
946
                            unsigned int scan_exposure_time,    /*pixel */
 
947
                            float scan_yres,    /*dpi, motor resolution */
 
948
                            int scan_step_type, /*0: full, 1: half, 2: quarter */
 
949
                            unsigned int scan_lines,    /*lines, scan resolution */
 
950
                            unsigned int scan_dummy,
 
951
/*number of scan lines to add in a scan_lines line*/
 
952
                            unsigned int feed_steps,    /*1/base_ydpi */
 
953
/*maybe float for half/quarter step resolution?*/
 
954
                            int scan_power_mode, unsigned int flags)
 
955
{
 
956
  SANE_Status status;
 
957
  unsigned int fast_exposure;
 
958
  int use_fast_fed = 0;
 
959
  unsigned int fast_time;
 
960
  unsigned int slow_time;
 
961
  uint16_t slow_slope_table[256];
 
962
  uint16_t fast_slope_table[256];
 
963
  uint16_t back_slope_table[256];
 
964
  unsigned int slow_slope_time;
 
965
  unsigned int fast_slope_time;
 
966
  unsigned int back_slope_time;
 
967
  unsigned int slow_slope_steps = 0;
 
968
  unsigned int fast_slope_steps = 32;
 
969
  unsigned int back_slope_steps = 0;
 
970
  unsigned int feedl;
 
971
  Genesys_Register_Set *r;
 
972
  unsigned int min_restep = 0x20;
 
973
  uint32_t z1, z2;
 
974
  uint8_t val, effective;
 
975
 
 
976
  DBGSTART;
 
977
  DBG (DBG_proc, "gl847_init_motor_regs_scan : scan_exposure_time=%d, "
 
978
       "scan_yres=%g, scan_step_type=%d, scan_lines=%d, scan_dummy=%d, "
 
979
       "feed_steps=%d, scan_power_mode=%d, flags=%x\n",
 
980
       scan_exposure_time,
 
981
       scan_yres,
 
982
       scan_step_type,
 
983
       scan_lines, scan_dummy, feed_steps, scan_power_mode, flags);
 
984
 
 
985
  fast_exposure =
 
986
    sanei_genesys_exposure_time2 (dev, dev->motor.base_ydpi / 4,
 
987
                                  0, 0, 0, scan_power_mode);
 
988
 
 
989
  DBG (DBG_info, "gl847_init_motor_regs_scan : fast_exposure=%d pixels\n",
 
990
       fast_exposure);
 
991
 
 
992
/*
 
993
  we calculate both tables for SCAN. the fast slope step count depends on
 
994
  how many steps we need for slow acceleration and how much steps we are
 
995
  allowed to use.
 
996
 */
 
997
  slow_slope_time = sanei_genesys_create_slope_table3 (dev,
 
998
                                                       slow_slope_table,
 
999
                                                       256,
 
1000
                                                       256,
 
1001
                                                       scan_step_type,
 
1002
                                                       scan_exposure_time,
 
1003
                                                       scan_yres,
 
1004
                                                       &slow_slope_steps,
 
1005
                                                       NULL, scan_power_mode);
 
1006
 
 
1007
  back_slope_time = sanei_genesys_create_slope_table3 (dev,
 
1008
                                                       back_slope_table,
 
1009
                                                       256,
 
1010
                                                       256,
 
1011
                                                       scan_step_type,
 
1012
                                                       scan_exposure_time,
 
1013
                                                       scan_yres,
 
1014
                                                       &back_slope_steps,
 
1015
                                                       NULL, scan_power_mode);
 
1016
 
 
1017
  if (feed_steps < (slow_slope_steps >> scan_step_type))
 
1018
    {
 
1019
      /*TODO: what should we do here?? go back to exposure calculation? */
 
1020
      feed_steps = slow_slope_steps >> scan_step_type;
 
1021
    }
 
1022
 
 
1023
  if (feed_steps > fast_slope_steps * 2 -
 
1024
      (slow_slope_steps >> scan_step_type))
 
1025
    fast_slope_steps = 256;
 
1026
  else
 
1027
    {
 
1028
      /* we need to shorten fast_slope_steps here. */
 
1029
      fast_slope_steps = (feed_steps - (slow_slope_steps >> scan_step_type)) / 2;
 
1030
    }
 
1031
  if(fast_slope_steps>256)
 
1032
    fast_slope_steps=256;
 
1033
 
 
1034
  DBG (DBG_info,
 
1035
       "gl847_init_motor_regs_scan: Maximum allowed slope steps for fast slope: %d\n",
 
1036
       fast_slope_steps);
 
1037
 
 
1038
  fast_slope_time = sanei_genesys_create_slope_table3 (dev,
 
1039
                                                       fast_slope_table,
 
1040
                                                       256,
 
1041
                                                       fast_slope_steps,
 
1042
                                                       0,
 
1043
                                                       fast_exposure,
 
1044
                                                       dev->motor.base_ydpi / 4,
 
1045
                                                       &fast_slope_steps,
 
1046
                                                       &fast_exposure,
 
1047
                                                       scan_power_mode);
 
1048
 
 
1049
  if (feed_steps <
 
1050
      fast_slope_steps * 2 + (slow_slope_steps >> scan_step_type))
 
1051
    {
 
1052
      use_fast_fed = 0;
 
1053
      DBG (DBG_info,
 
1054
           "gl847_init_motor_regs_scan: feed too short, slow move forced.\n");
 
1055
    }
 
1056
  else
 
1057
    {
 
1058
/* for deciding whether we should use fast mode we need to check how long we 
 
1059
   need for (fast)accelerating, moving, decelerating, (TODO: stopping?) 
 
1060
   (slow)accelerating again versus (slow)accelerating and moving. we need 
 
1061
   fast and slow tables here.
 
1062
*/
 
1063
/*NOTE: scan_exposure_time is per scan_yres*/
 
1064
/*NOTE: fast_exposure is per base_ydpi/4*/
 
1065
/*we use full steps as base unit here*/
 
1066
      fast_time =
 
1067
        fast_exposure / 4 *
 
1068
        (feed_steps - fast_slope_steps * 2 -
 
1069
         (slow_slope_steps >> scan_step_type))
 
1070
        + fast_slope_time * 2 + slow_slope_time;
 
1071
      slow_time =
 
1072
        (scan_exposure_time * scan_yres) / dev->motor.base_ydpi *
 
1073
        (feed_steps - (slow_slope_steps >> scan_step_type)) + slow_slope_time;
 
1074
 
 
1075
      DBG (DBG_info, "gl847_init_motor_regs_scan: Time for slow move: %d\n",
 
1076
           slow_time);
 
1077
      DBG (DBG_info, "gl847_init_motor_regs_scan: Time for fast move: %d\n",
 
1078
           fast_time);
 
1079
 
 
1080
      use_fast_fed = fast_time < slow_time;
 
1081
    }
 
1082
  
 
1083
  DBG (DBG_info, "gl847_init_motor_regs_scan: decided to use %s mode\n",
 
1084
       use_fast_fed ? "fast feed" : "slow feed");
 
1085
 
 
1086
  if (use_fast_fed)
 
1087
    feedl = feed_steps - fast_slope_steps * 2 -
 
1088
      (slow_slope_steps >> scan_step_type);
 
1089
  else if ((feed_steps << scan_step_type) < slow_slope_steps)
 
1090
    feedl = 0;
 
1091
  else
 
1092
    feedl = (feed_steps << scan_step_type) - slow_slope_steps;
 
1093
 
 
1094
 
 
1095
/* all needed slopes available. we did even decide which mode to use. 
 
1096
   what next?  */
 
1097
  r = sanei_genesys_get_address (reg, 0x3d);
 
1098
  r->value = (feedl >> 16) & 0xf;
 
1099
  r = sanei_genesys_get_address (reg, 0x3e);
 
1100
  r->value = (feedl >> 8) & 0xff;
 
1101
  r = sanei_genesys_get_address (reg, 0x3f);
 
1102
  r->value = feedl & 0xff;
 
1103
  DBG (DBG_io ,"%s: feedl=%d\n",__FUNCTION__,feedl);
 
1104
 
 
1105
  r = sanei_genesys_get_address (reg, 0x25);
 
1106
  r->value = (scan_lines >> 16) & 0xf;
 
1107
  r = sanei_genesys_get_address (reg, 0x26);
 
1108
  r->value = (scan_lines >> 8) & 0xff;
 
1109
  r = sanei_genesys_get_address (reg, 0x27);
 
1110
  r->value = scan_lines & 0xff;
 
1111
 
 
1112
  /* compute register 02 value */
 
1113
  r = sanei_genesys_get_address (reg, REG02);
 
1114
  r->value = 0x00;
 
1115
  r->value |= REG02_NOTHOME | REG02_MTRPWR;
 
1116
 
 
1117
  if (use_fast_fed)
 
1118
    r->value |= REG02_FASTFED;
 
1119
  else
 
1120
    r->value &= ~REG02_FASTFED;
 
1121
 
 
1122
  if (flags & MOTOR_FLAG_AUTO_GO_HOME)
 
1123
    r->value |= REG02_AGOHOME;
 
1124
 
 
1125
  if (flags & MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE)
 
1126
    r->value |= REG02_ACDCDIS;
 
1127
 
 
1128
  /* hi res motor speed */
 
1129
  RIE (sanei_genesys_read_register (dev, REG6C, &effective));
 
1130
 
 
1131
  /* if quarter step, bipolar Vref2 */
 
1132
  if (scan_step_type > 1)
 
1133
    {
 
1134
      val = effective & ~REG6C_GPIO13;
 
1135
    }
 
1136
  else
 
1137
    {
 
1138
      val = effective;
 
1139
    }
 
1140
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
1141
 
 
1142
  /* effective scan */
 
1143
  RIE (sanei_genesys_read_register (dev, REG6C, &effective));
 
1144
  val = effective | REG6C_GPIO10;
 
1145
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
1146
 
 
1147
  status = gl847_send_slope_table (dev, 0, slow_slope_table, 256);
 
1148
 
 
1149
  if (status != SANE_STATUS_GOOD)
 
1150
    return status;
 
1151
 
 
1152
  status = gl847_send_slope_table (dev, 1, back_slope_table, 256);
 
1153
 
 
1154
  if (status != SANE_STATUS_GOOD)
 
1155
    return status;
 
1156
 
 
1157
  status = gl847_send_slope_table (dev, 2, slow_slope_table, 256);
 
1158
 
 
1159
  if (status != SANE_STATUS_GOOD)
 
1160
    return status;
 
1161
 
 
1162
  if (use_fast_fed)
 
1163
    {
 
1164
      status = gl847_send_slope_table (dev, 3, fast_slope_table, 256);
 
1165
 
 
1166
      if (status != SANE_STATUS_GOOD)
 
1167
        return status;
 
1168
    }
 
1169
 
 
1170
  if (flags & MOTOR_FLAG_AUTO_GO_HOME)
 
1171
    {
 
1172
      status = gl847_send_slope_table (dev, 4, fast_slope_table, 256);
 
1173
 
 
1174
      if (status != SANE_STATUS_GOOD)
 
1175
        return status;
 
1176
    }
 
1177
 
 
1178
 
 
1179
/* now reg 0x21 and 0x24 are available, we can calculate reg 0x22 and 0x23,
 
1180
   reg 0x60-0x62 and reg 0x63-0x65
 
1181
   rule:
 
1182
   2*STEPNO+FWDSTEP=2*FASTNO+BWDSTEP
 
1183
*/
 
1184
/* steps of table 0*/
 
1185
  if (min_restep < slow_slope_steps * 2 + 2)
 
1186
    min_restep = slow_slope_steps * 2 + 2;
 
1187
/* steps of table 1*/
 
1188
  if (min_restep < back_slope_steps * 2 + 2)
 
1189
    min_restep = back_slope_steps * 2 + 2;
 
1190
/* steps of table 0*/
 
1191
  r = sanei_genesys_get_address (reg, 0x22);
 
1192
  r->value = min_restep - slow_slope_steps * 2;
 
1193
 
 
1194
/* steps of table 1*/
 
1195
  r = sanei_genesys_get_address (reg, 0x23);
 
1196
  r->value = min_restep - back_slope_steps * 2;
 
1197
 
 
1198
 
 
1199
/*
 
1200
  for z1/z2:
 
1201
  in documentation mentioned variables a-d:
 
1202
  a = time needed for acceleration, table 1
 
1203
  b = time needed for reg 0x1f... wouldn't that be reg0x1f*exposure_time?
 
1204
  c = time needed for acceleration, table 1
 
1205
  d = time needed for reg 0x22... wouldn't that be reg0x22*exposure_time?
 
1206
  z1 = (c+d-1) % exposure_time 
 
1207
  z2 = (a+b-1) % exposure_time
 
1208
*/
 
1209
/* i don't see any effect of this. i can only guess that this will enhance 
 
1210
   sub-pixel accuracy
 
1211
   z1 = (slope_0_time-1) % exposure_time;
 
1212
   z2 = (slope_0_time-1) % exposure_time;
 
1213
*/
 
1214
 
 
1215
  sanei_genesys_calculate_zmode2 (use_fast_fed,
 
1216
                                  scan_exposure_time,
 
1217
                                  slow_slope_table,
 
1218
                                  slow_slope_steps,
 
1219
                                  feedl,
 
1220
                                  back_slope_steps,
 
1221
                                  &z1,
 
1222
                                  &z2);
 
1223
 
 
1224
  DBG (DBG_info, "gl847_init_motor_regs_scan: z1 = %d\n", z1);
 
1225
  r = sanei_genesys_get_address (reg, REG60);
 
1226
  r->value = ((z1 >> 16) & REG60_Z1MOD) | (scan_step_type << REG60S_STEPSEL);
 
1227
  r = sanei_genesys_get_address (reg, REG61);
 
1228
  r->value = ((z1 >> 8) & REG61_Z1MOD);
 
1229
  r = sanei_genesys_get_address (reg, REG62);
 
1230
  r->value = (z1 & REG62_Z1MOD);
 
1231
 
 
1232
  DBG (DBG_info, "gl847_init_motor_regs_scan: z2 = %d\n", z2);
 
1233
  r = sanei_genesys_get_address (reg, REG63);
 
1234
  r->value = ((z2 >> 16) & REG63_Z2MOD) | (scan_step_type << REG63S_FSTPSEL);
 
1235
  r = sanei_genesys_get_address (reg, REG64);
 
1236
  r->value = ((z2 >> 8) & REG64_Z2MOD);
 
1237
  r = sanei_genesys_get_address (reg, REG65);
 
1238
  r->value = (z2 & REG65_Z2MOD);
 
1239
 
 
1240
  r = sanei_genesys_get_address (reg, 0x1e);
 
1241
  r->value &= 0xf0;             /* 0 dummy lines */
 
1242
  r->value |= scan_dummy;       /* dummy lines */
 
1243
 
 
1244
  r = sanei_genesys_get_address (reg, REG67);
 
1245
  r->value = REG67_MTRPWM;
 
1246
 
 
1247
  r = sanei_genesys_get_address (reg, REG68);
 
1248
  r->value = REG68_FASTPWM;
 
1249
 
 
1250
  r = sanei_genesys_get_address (reg, 0x21);
 
1251
  r->value = slow_slope_steps;
 
1252
 
 
1253
  r = sanei_genesys_get_address (reg, 0x24);
 
1254
  r->value = back_slope_steps;
 
1255
 
 
1256
  r = sanei_genesys_get_address (reg, 0x69);
 
1257
  r->value = slow_slope_steps;
 
1258
 
 
1259
  r = sanei_genesys_get_address (reg, 0x6a);
 
1260
  r->value = fast_slope_steps;
 
1261
 
 
1262
  r = sanei_genesys_get_address (reg, 0x5f);
 
1263
  r->value = fast_slope_steps;
 
1264
 
 
1265
 
 
1266
  DBGCOMPLETED;
 
1267
  return SANE_STATUS_GOOD;
 
1268
}
 
1269
 
 
1270
static int
 
1271
gl847_get_dpihw (Genesys_Device * dev)
 
1272
{
 
1273
  Genesys_Register_Set *r;
 
1274
  r = sanei_genesys_get_address (dev->reg, REG05);
 
1275
  if ((r->value & REG05_DPIHW) == REG05_DPIHW_600)
 
1276
    return 600;
 
1277
  if ((r->value & REG05_DPIHW) == REG05_DPIHW_1200)
 
1278
    return 1200;
 
1279
  if ((r->value & REG05_DPIHW) == REG05_DPIHW_2400)
 
1280
    return 2400;
 
1281
  if ((r->value & REG05_DPIHW) == REG05_DPIHW_4800)
 
1282
    return 4800;
 
1283
  return 0;
 
1284
}
 
1285
 
 
1286
#define OPTICAL_FLAG_DISABLE_GAMMA   1
 
1287
#define OPTICAL_FLAG_DISABLE_SHADING 2
 
1288
#define OPTICAL_FLAG_DISABLE_LAMP    4
 
1289
#define OPTICAL_FLAG_ENABLE_LEDADD   8
 
1290
 
 
1291
static SANE_Status
 
1292
gl847_init_optical_regs_off (Genesys_Device * dev, Genesys_Register_Set * reg)
 
1293
{
 
1294
  Genesys_Register_Set *r;
 
1295
 
 
1296
  DBG (DBG_proc, "gl847_init_optical_regs_off : start\n");
 
1297
 
 
1298
  r = sanei_genesys_get_address (reg, REG01);
 
1299
  r->value &= ~REG01_SCAN;
 
1300
 
 
1301
  DBGCOMPLETED;
 
1302
  return SANE_STATUS_GOOD;
 
1303
}
 
1304
 
 
1305
/** @brief set up registers related to sensor
 
1306
 * Set up the following registers
 
1307
   0x01
 
1308
   0x03
 
1309
   0x10-0x015     R/G/B exposures
 
1310
   0x19           EXPDMY
 
1311
   0x2e           BWHI
 
1312
   0x2f           BWLO
 
1313
   0x04
 
1314
   0x87
 
1315
   0x05
 
1316
   0x2c,0x2d      DPISET
 
1317
   0x30,0x31      STRPIXEL
 
1318
   0x32,0x33      ENDPIXEL
 
1319
   0x35,0x36,0x37 MAXWD [25:2] (>>2)
 
1320
   0x38,0x39      LPERIOD
 
1321
   0x34           DUMMY
 
1322
 */
 
1323
static SANE_Status
 
1324
gl847_init_optical_regs_scan (Genesys_Device * dev,
 
1325
                              Genesys_Register_Set * reg,
 
1326
                              unsigned int exposure_time,
 
1327
                              int used_res,
 
1328
                              unsigned int start,
 
1329
                              unsigned int pixels,
 
1330
                              int channels,
 
1331
                              int depth,
 
1332
                              SANE_Bool half_ccd, int color_filter, int flags)
 
1333
{
 
1334
  unsigned int words_per_line;
 
1335
  unsigned int startx,endx, used_pixels,max_pixels;
 
1336
  unsigned int dpiset;
 
1337
  unsigned int i,bytes;
 
1338
  Genesys_Register_Set *r;
 
1339
  SANE_Status status;
 
1340
  int double_xres;
 
1341
 
 
1342
  DBG (DBG_proc, "gl847_init_optical_regs_scan :  exposure_time=%d, "
 
1343
       "used_res=%d, start=%d, pixels=%d, channels=%d, depth=%d, "
 
1344
       "half_ccd=%d, flags=%x\n",
 
1345
       exposure_time,
 
1346
       used_res, start, pixels, channels, depth, half_ccd, flags);
 
1347
 
 
1348
  /* during calibration , we don't want double xres */
 
1349
  if(dev->settings.double_xres==SANE_TRUE && used_res<dev->sensor.optical_res)
 
1350
    {
 
1351
      double_xres=SANE_TRUE;
 
1352
    }
 
1353
  else
 
1354
    {
 
1355
      double_xres=SANE_FALSE;
 
1356
    }
 
1357
 
 
1358
  startx = dev->sensor.dummy_pixel + 1 + dev->sensor.CCD_start_xoffset;
 
1359
  if(double_xres==SANE_TRUE)
 
1360
    {
 
1361
      max_pixels = dev->sensor.sensor_pixels/2;
 
1362
    }
 
1363
  else
 
1364
    {
 
1365
      max_pixels = dev->sensor.sensor_pixels;
 
1366
    }
 
1367
  if(pixels<max_pixels)
 
1368
    {
 
1369
      used_pixels = max_pixels;
 
1370
    }
 
1371
  else
 
1372
    {
 
1373
      used_pixels = pixels;
 
1374
    }
 
1375
  endx = startx + used_pixels;
 
1376
 
 
1377
  status = gl847_set_fe (dev, AFE_SET);
 
1378
  if (status != SANE_STATUS_GOOD)
 
1379
    {
 
1380
      DBG (DBG_error,
 
1381
           "gl847_init_optical_regs_scan: failed to set frontend: %s\n",
 
1382
           sane_strstatus (status));
 
1383
      return status;
 
1384
    }
 
1385
 
 
1386
  /* adjust used_res for chosen dpihw */
 
1387
  used_res = used_res * gl847_get_dpihw (dev) / dev->sensor.optical_res;
 
1388
  if(double_xres==SANE_TRUE)
 
1389
    {
 
1390
      used_res *=2;
 
1391
    }
 
1392
  dpiset = used_res;
 
1393
 
 
1394
  /* enable shading */
 
1395
  r = sanei_genesys_get_address (reg, REG01);
 
1396
  r->value &= ~REG01_SCAN;
 
1397
  r->value |= REG01_SHDAREA;
 
1398
  if ((flags & OPTICAL_FLAG_DISABLE_SHADING) ||
 
1399
      (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION))
 
1400
    {
 
1401
      r->value &= ~REG01_DVDSET;
 
1402
    }
 
1403
  else
 
1404
    {
 
1405
      r->value |= REG01_DVDSET;
 
1406
    }
 
1407
 
 
1408
  r = sanei_genesys_get_address (reg, REG03);
 
1409
  r->value &= ~REG03_AVEENB;
 
1410
  if (flags & OPTICAL_FLAG_DISABLE_LAMP)
 
1411
    r->value &= ~REG03_LAMPPWR;
 
1412
  else
 
1413
    r->value |= REG03_LAMPPWR;
 
1414
 
 
1415
  /* exposure times */
 
1416
  for (i = 0; i < 6; i++)
 
1417
    {
 
1418
      r = sanei_genesys_get_address (reg, 0x10 + i);
 
1419
      if (flags & OPTICAL_FLAG_DISABLE_LAMP)
 
1420
        r->value = 0x01;        /* 0x0101 is as off as possible */
 
1421
      else
 
1422
        r->value = dev->sensor.regs_0x10_0x1d[i];
 
1423
    }
 
1424
 
 
1425
  r = sanei_genesys_get_address (reg, 0x19);
 
1426
  r->value = 0x50;
 
1427
 
 
1428
  /* BW threshold */
 
1429
  r = sanei_genesys_get_address (reg, 0x2e);
 
1430
  r->value = dev->settings.threshold;
 
1431
  r = sanei_genesys_get_address (reg, 0x2f);
 
1432
  r->value = dev->settings.threshold;
 
1433
 
 
1434
  /* monochrome / color scan */
 
1435
  r = sanei_genesys_get_address (reg, REG04);
 
1436
  switch (depth)
 
1437
    {
 
1438
    case 1:
 
1439
      r->value &= ~REG04_BITSET;
 
1440
      r->value |= REG04_LINEART;
 
1441
      break;
 
1442
    case 8:
 
1443
      r->value &= ~(REG04_LINEART | REG04_BITSET);
 
1444
      break;
 
1445
    case 16:
 
1446
      r->value &= ~REG04_LINEART;
 
1447
      r->value |= REG04_BITSET;
 
1448
      break;
 
1449
    }
 
1450
 
 
1451
  r->value &= ~(REG04_FILTER | REG04_AFEMOD);
 
1452
  if (channels == 1)
 
1453
    {
 
1454
      switch (color_filter)
 
1455
        {
 
1456
        case 0:
 
1457
          r->value |= 0x14;     /* red filter */
 
1458
          break;
 
1459
        case 2:
 
1460
          r->value |= 0x1c;     /* blue filter */
 
1461
          break;
 
1462
        default:
 
1463
          r->value |= 0x18;     /* green filter */
 
1464
          break;
 
1465
        }
 
1466
    }
 
1467
  else
 
1468
    r->value |= 0x10;           /* mono */
 
1469
 
 
1470
  /* CIS scanners can do true gray by setting LEDADD */
 
1471
  /* we set up LEDADD only when asked */
 
1472
  if (dev->model->is_cis == SANE_TRUE)
 
1473
    {
 
1474
      r = sanei_genesys_get_address (reg, 0x87);
 
1475
      r->value &= ~REG87_LEDADD;
 
1476
      if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD))
 
1477
        {
 
1478
          r->value |= REG87_LEDADD;
 
1479
        }
 
1480
      /* RGB wrighting 
 
1481
      r = sanei_genesys_get_address (reg, 0x01);
 
1482
      r->value &= ~REG01_TRUEGRAY;
 
1483
      if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD))
 
1484
        {
 
1485
          r->value |= REG01_TRUEGRAY;
 
1486
        }*/
 
1487
    }
 
1488
 
 
1489
  /* enable gamma tables */
 
1490
  r = sanei_genesys_get_address (reg, REG05);
 
1491
  if (flags & OPTICAL_FLAG_DISABLE_GAMMA)
 
1492
    r->value &= ~REG05_GMMENB;
 
1493
  else
 
1494
    r->value |= REG05_GMMENB;
 
1495
 
 
1496
  /* sensor parameters */
 
1497
  gl847_setup_sensor (dev, dev->reg);
 
1498
 
 
1499
  r = sanei_genesys_get_address (reg, 0x2c);
 
1500
  r->value = HIBYTE (dpiset);
 
1501
  r = sanei_genesys_get_address (reg, 0x2d);
 
1502
  r->value = LOBYTE (dpiset);
 
1503
  DBG (DBG_io2, "%s: dpiset used=%d\n", __FUNCTION__, dpiset);
 
1504
 
 
1505
  r = sanei_genesys_get_address (reg, 0x30);
 
1506
  r->value = HIBYTE (startx);
 
1507
  r = sanei_genesys_get_address (reg, 0x31);
 
1508
  r->value = LOBYTE (startx);
 
1509
  r = sanei_genesys_get_address (reg, 0x32);
 
1510
  r->value = HIBYTE (endx);
 
1511
  r = sanei_genesys_get_address (reg, 0x33);
 
1512
  r->value = LOBYTE (endx);
 
1513
 
 
1514
  /* words(16bit) before gamma, conversion to 8 bit or lineart*/
 
1515
  words_per_line = (used_pixels * dpiset) / gl847_get_dpihw (dev);
 
1516
  bytes=depth/8;
 
1517
  if (depth == 1)
 
1518
    {
 
1519
      words_per_line = (words_per_line >> 3) + ((words_per_line & 7) ? 1 : 0);
 
1520
    }
 
1521
  else
 
1522
    {
 
1523
      words_per_line *= bytes;
 
1524
    }
 
1525
 
 
1526
  dev->bpl = words_per_line;
 
1527
  dev->cur=0;
 
1528
  dev->len=((pixels*dpiset)/gl847_get_dpihw (dev))/2*bytes;
 
1529
  dev->dist=dev->bpl/2;
 
1530
  dev->skip=((start*dpiset)/gl847_get_dpihw (dev))/2*bytes;
 
1531
  if(dev->skip>=dev->dist && double_xres==SANE_FALSE)
 
1532
    {
 
1533
      dev->skip-=dev->dist;
 
1534
    }
 
1535
 
 
1536
  DBG (DBG_io2, "%s: used_pixels=%d\n", __FUNCTION__, used_pixels);
 
1537
  DBG (DBG_io2, "%s: pixels     =%d\n", __FUNCTION__, pixels);
 
1538
  DBG (DBG_io2, "%s: depth      =%d\n", __FUNCTION__, depth);
 
1539
  DBG (DBG_io2, "%s: dev->bpl   =%lu\n", __FUNCTION__, (unsigned long)dev->bpl);
 
1540
  DBG (DBG_io2, "%s: dev->len   =%lu\n", __FUNCTION__, (unsigned long)dev->len);
 
1541
  DBG (DBG_io2, "%s: dev->dist  =%lu\n", __FUNCTION__, (unsigned long)dev->dist);
 
1542
  DBG (DBG_io2, "%s: dev->skip  =%lu\n", __FUNCTION__, (unsigned long)dev->skip);
 
1543
  
 
1544
  words_per_line *= channels;
 
1545
  dev->wpl = words_per_line;
 
1546
 
 
1547
  if(dev->oe_buffer.buffer!=NULL)
 
1548
    {
 
1549
      sanei_genesys_buffer_free (&(dev->oe_buffer));
 
1550
    }
 
1551
  RIE (sanei_genesys_buffer_alloc (&(dev->oe_buffer), dev->wpl));
 
1552
 
 
1553
 
 
1554
  /* MAXWD is expressed in 4 words unit */
 
1555
  r = sanei_genesys_get_address (reg, 0x35);
 
1556
  r->value = LOBYTE (HIWORD (words_per_line >> 2));
 
1557
  r = sanei_genesys_get_address (reg, 0x36);
 
1558
  r->value = HIBYTE (LOWORD (words_per_line >> 2));
 
1559
  r = sanei_genesys_get_address (reg, 0x37);
 
1560
  r->value = LOBYTE (LOWORD (words_per_line >> 2));
 
1561
  DBG (DBG_io2, "%s: words_per_line used=%d\n", __FUNCTION__, words_per_line);
 
1562
 
 
1563
  r = sanei_genesys_get_address (reg, 0x38);
 
1564
  r->value = HIBYTE (exposure_time);
 
1565
  r = sanei_genesys_get_address (reg, 0x39);
 
1566
  r->value = LOBYTE (exposure_time);
 
1567
  DBG (DBG_io2, "%s: exposure_time used=%d\n", __FUNCTION__, exposure_time);
 
1568
 
 
1569
  r = sanei_genesys_get_address (reg, 0x34);
 
1570
  r->value = dev->sensor.dummy_pixel;
 
1571
  
 
1572
  DBGCOMPLETED;
 
1573
  return SANE_STATUS_GOOD;
 
1574
}
 
1575
 
 
1576
 
 
1577
static int
 
1578
gl847_get_led_exposure (Genesys_Device * dev)
 
1579
{
 
1580
  int d, r, g, b, m;
 
1581
  if (!dev->model->is_cis)
 
1582
    return 0;
 
1583
  d = dev->reg[reg_0x19].value;
 
1584
  r = dev->sensor.regs_0x10_0x1d[1] | (dev->sensor.regs_0x10_0x1d[0] << 8);
 
1585
  g = dev->sensor.regs_0x10_0x1d[3] | (dev->sensor.regs_0x10_0x1d[2] << 8);
 
1586
  b = dev->sensor.regs_0x10_0x1d[5] | (dev->sensor.regs_0x10_0x1d[4] << 8);
 
1587
 
 
1588
  m = r;
 
1589
  if (m < g)
 
1590
    m = g;
 
1591
  if (m < b)
 
1592
    m = b;
 
1593
 
 
1594
  return m + d;
 
1595
}
 
1596
 
 
1597
/* set up registers for an actual scan
 
1598
 *
 
1599
 * this function sets up the scanner to scan in normal or single line mode
 
1600
 */
 
1601
#ifndef UNIT_TESTING
 
1602
static
 
1603
#endif
 
1604
  SANE_Status
 
1605
gl847_init_scan_regs (Genesys_Device * dev,
 
1606
                      Genesys_Register_Set * reg,
 
1607
                      float xres,       /*dpi */
 
1608
                      float yres,       /*dpi */
 
1609
                      float startx,     /*optical_res, from dummy_pixel+1 */
 
1610
                      float starty,     /*base_ydpi, from home! */
 
1611
                      float pixels,
 
1612
                      float lines,
 
1613
                      unsigned int depth,
 
1614
                      unsigned int channels,
 
1615
                      int color_filter, unsigned int flags)
 
1616
{
 
1617
  int used_res;
 
1618
  int start, used_pixels;
 
1619
  int bytes_per_line;
 
1620
  int move;
 
1621
  unsigned int lincnt;
 
1622
  unsigned int oflags; /**> optical flags */
 
1623
  int exposure_time, exposure_time2, led_exposure;
 
1624
  int i;
 
1625
  int stagger;
 
1626
 
 
1627
  int slope_dpi = 0;
 
1628
  int pixels_exposure;
 
1629
  int dummy = 0;
 
1630
  int scan_step_type = 1;
 
1631
  int scan_power_mode = 0;
 
1632
  int max_shift;
 
1633
  size_t requested_buffer_size, read_buffer_size;
 
1634
 
 
1635
  SANE_Bool half_ccd;           /* false: full CCD res is used, true, half max CCD res is used */
 
1636
  int optical_res;
 
1637
  SANE_Status status;
 
1638
 
 
1639
  DBG (DBG_info,
 
1640
       "gl847_init_scan_regs settings:\n"
 
1641
       "Resolution    : %gDPI/%gDPI\n"
 
1642
       "Lines         : %g\n"
 
1643
       "PPL           : %g\n"
 
1644
       "Startpos      : %g/%g\n"
 
1645
       "Depth/Channels: %u/%u\n"
 
1646
       "Flags         : %x\n\n",
 
1647
       xres, yres, lines, pixels, startx, starty, depth, channels, flags);
 
1648
 
 
1649
/*
 
1650
results:
 
1651
 
 
1652
for scanner:
 
1653
half_ccd
 
1654
start
 
1655
end
 
1656
dpiset
 
1657
exposure_time
 
1658
dummy
 
1659
z1
 
1660
z2
 
1661
 
 
1662
for ordered_read:
 
1663
  dev->words_per_line
 
1664
  dev->read_factor
 
1665
  dev->requested_buffer_size
 
1666
  dev->read_buffer_size
 
1667
  dev->read_pos
 
1668
  dev->read_bytes_in_buffer
 
1669
  dev->read_bytes_left
 
1670
  dev->max_shift
 
1671
  dev->stagger
 
1672
 
 
1673
independent of our calculated values:
 
1674
  dev->total_bytes_read
 
1675
  dev->bytes_to_read
 
1676
 */
 
1677
 
 
1678
/* half_ccd */
 
1679
  /* we have 2 domains for ccd: xres below or above half ccd max dpi */
 
1680
  if (dev->sensor.optical_res < 2 * xres ||
 
1681
      !(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE))
 
1682
    {
 
1683
      half_ccd = SANE_FALSE;
 
1684
    }
 
1685
  else
 
1686
    {
 
1687
      half_ccd = SANE_TRUE;
 
1688
    }
 
1689
 
 
1690
/* optical_res */
 
1691
 
 
1692
  optical_res = dev->sensor.optical_res;
 
1693
  if (half_ccd)
 
1694
    optical_res /= 2;
 
1695
 
 
1696
/* stagger */
 
1697
 
 
1698
  if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE))
 
1699
    stagger = (4 * yres) / dev->motor.base_ydpi;
 
1700
  else
 
1701
    stagger = 0;
 
1702
  DBG (DBG_info, "gl847_init_scan_regs : stagger=%d lines\n", stagger);
 
1703
 
 
1704
  /* used_res */
 
1705
  i = optical_res / xres;
 
1706
  if (flags & SCAN_FLAG_USE_OPTICAL_RES)
 
1707
    {
 
1708
      used_res = optical_res;
 
1709
    }
 
1710
  else
 
1711
    {
 
1712
      /* resolution is choosen from a list */
 
1713
      used_res = xres;
 
1714
    }
 
1715
 
 
1716
  /* compute scan parameters values */
 
1717
  /* pixels are allways given at full optical resolution */
 
1718
  /* use detected left margin and fixed value */
 
1719
  /* start */
 
1720
  /* add x coordinates */
 
1721
  start = startx;
 
1722
 
 
1723
  if (stagger > 0)
 
1724
    start |= 1;
 
1725
 
 
1726
  /* compute correct pixels number */
 
1727
  /* pixels */
 
1728
  used_pixels = (pixels * optical_res) / xres;
 
1729
 
 
1730
  /* round up pixels number if needed */
 
1731
  if (used_pixels * xres < pixels * optical_res)
 
1732
    used_pixels++;
 
1733
 
 
1734
  dummy = 3-channels;
 
1735
 
 
1736
/* slope_dpi */
 
1737
/* cis color scan is effectively a gray scan with 3 gray lines per color
 
1738
   line and a FILTER of 0 */
 
1739
  if (dev->model->is_cis)
 
1740
    slope_dpi = yres * channels;
 
1741
  else
 
1742
    slope_dpi = yres;
 
1743
 
 
1744
  slope_dpi = slope_dpi * (1 + dummy);
 
1745
 
 
1746
  /* scan_step_type */
 
1747
  switch((int)yres)
 
1748
    {
 
1749
    case 75:
 
1750
    case 100:
 
1751
    case 150:
 
1752
      scan_step_type = 0;
 
1753
      break;
 
1754
    case 200:
 
1755
    case 300:
 
1756
      scan_step_type = 1;
 
1757
      break;
 
1758
    default:
 
1759
      scan_step_type = 2;
 
1760
    }
 
1761
 
 
1762
  /* exposure_time , CCD case not handled */
 
1763
  led_exposure = gl847_get_led_exposure (dev);
 
1764
 
 
1765
  pixels_exposure=dev->sensor.sensor_pixels+572;
 
1766
  if(xres<dev->sensor.optical_res)
 
1767
    pixels_exposure=(pixels_exposure*xres)/dev->sensor.optical_res-32;
 
1768
  else
 
1769
    pixels_exposure=0;
 
1770
 
 
1771
  exposure_time = sanei_genesys_exposure_time2 (dev,
 
1772
                                                slope_dpi,
 
1773
                                                scan_step_type,
 
1774
                                                pixels_exposure,
 
1775
                                                led_exposure,
 
1776
                                                scan_power_mode);
 
1777
 
 
1778
  while (scan_power_mode + 1 < dev->motor.power_mode_count)
 
1779
    {
 
1780
      exposure_time2 = sanei_genesys_exposure_time2 (dev,
 
1781
                                                     slope_dpi,
 
1782
                                                     scan_step_type,
 
1783
                                                     pixels_exposure,
 
1784
                                                     led_exposure,
 
1785
                                                     scan_power_mode + 1);
 
1786
      if (exposure_time < exposure_time2)
 
1787
        break;
 
1788
      exposure_time = exposure_time2;
 
1789
      scan_power_mode++;
 
1790
    }
 
1791
 
 
1792
  DBG (DBG_info, "gl847_init_scan_regs : exposure_time=%d pixels\n",
 
1793
       exposure_time);
 
1794
  DBG (DBG_info, "gl847_init_scan_regs : scan_step_type=%d\n",
 
1795
       scan_step_type);
 
1796
 
 
1797
/*** optical parameters ***/
 
1798
  /* in case of dynamic lineart, we use an internal 8 bit gray scan
 
1799
   * to generate 1 lineart data */
 
1800
  if ((flags & SCAN_FLAG_DYNAMIC_LINEART) && (dev->settings.scan_mode == SCAN_MODE_LINEART))
 
1801
    {
 
1802
      depth = 8;
 
1803
    }
 
1804
 
 
1805
  /* we enable true gray for cis scanners only, and just when doing 
 
1806
   * scan since color calibration is OK for this mode
 
1807
   */
 
1808
  oflags = 0;
 
1809
  if(flags & SCAN_FLAG_DISABLE_SHADING)
 
1810
    oflags |= OPTICAL_FLAG_DISABLE_SHADING;
 
1811
  if(flags & SCAN_FLAG_DISABLE_GAMMA)
 
1812
    oflags |= OPTICAL_FLAG_DISABLE_GAMMA;
 
1813
  if(flags & SCAN_FLAG_DISABLE_LAMP)
 
1814
    oflags |= OPTICAL_FLAG_DISABLE_LAMP;
 
1815
  
 
1816
  if (dev->model->is_cis && dev->settings.true_gray)
 
1817
    {
 
1818
      oflags |= OPTICAL_FLAG_ENABLE_LEDADD;
 
1819
    }
 
1820
 
 
1821
  status = gl847_init_optical_regs_scan (dev,
 
1822
                                         reg,
 
1823
                                         exposure_time,
 
1824
                                         used_res,
 
1825
                                         start,
 
1826
                                         used_pixels,
 
1827
                                         channels,
 
1828
                                         depth,
 
1829
                                         half_ccd,
 
1830
                                         color_filter,
 
1831
                                         oflags);
 
1832
 
 
1833
  if (status != SANE_STATUS_GOOD)
 
1834
    return status;
 
1835
 
 
1836
/*** motor parameters ***/
 
1837
 
 
1838
/* max_shift */
 
1839
  /* scanned area must be enlarged by max color shift needed */
 
1840
  /* all values are assumed >= 0 */
 
1841
  if (channels > 1 && !(flags & SCAN_FLAG_IGNORE_LINE_DISTANCE))
 
1842
    {
 
1843
      max_shift = dev->model->ld_shift_r;
 
1844
      if (dev->model->ld_shift_b > max_shift)
 
1845
        max_shift = dev->model->ld_shift_b;
 
1846
      if (dev->model->ld_shift_g > max_shift)
 
1847
        max_shift = dev->model->ld_shift_g;
 
1848
      max_shift = (max_shift * yres) / dev->motor.base_ydpi;
 
1849
    }
 
1850
  else
 
1851
    {
 
1852
      max_shift = 0;
 
1853
    }
 
1854
 
 
1855
/* lincnt */
 
1856
  lincnt = lines + max_shift + stagger;
 
1857
 
 
1858
  /* add tl_y to base movement */
 
1859
  move = starty;
 
1860
  DBG (DBG_info, "gl847_init_scan_regs: move=%d steps\n", move);
 
1861
 
 
1862
  /* subtract current head position */
 
1863
  /* XXX STEF XXX
 
1864
  move -= dev->scanhead_position_in_steps;
 
1865
  DBG (DBG_info, "gl847_init_scan_regs: move=%d steps\n", move);
 
1866
 
 
1867
  if (move < 0)
 
1868
    move = 0; */
 
1869
 
 
1870
  /* round it */
 
1871
/* the move is not affected by dummy -- pierre */
 
1872
/*  move = ((move + dummy) / (dummy + 1)) * (dummy + 1);
 
1873
    DBG (DBG_info, "gl847_init_scan_regs: move=%d steps\n", move);*/
 
1874
 
 
1875
  if (flags & SCAN_FLAG_SINGLE_LINE)
 
1876
    status = gl847_init_motor_regs_off (dev,
 
1877
                                        reg,
 
1878
                                        dev->model->is_cis ? lincnt *
 
1879
                                        channels : lincnt);
 
1880
  else
 
1881
    status = gl847_init_motor_regs_scan (dev,
 
1882
                                         reg,
 
1883
                                         exposure_time,
 
1884
                                         slope_dpi,
 
1885
                                         scan_step_type,
 
1886
                                         dev->model->is_cis ? lincnt *
 
1887
                                         channels : lincnt, dummy, move,
 
1888
                                         scan_power_mode,
 
1889
                                         (flags &
 
1890
                                          SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE)
 
1891
                                         ?
 
1892
                                         MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE
 
1893
                                         : 0);
 
1894
 
 
1895
  if (status != SANE_STATUS_GOOD)
 
1896
    return status;
 
1897
 
 
1898
 
 
1899
  /*** prepares data reordering ***/
 
1900
 
 
1901
/* words_per_line */
 
1902
  bytes_per_line = (used_pixels * used_res) / optical_res;
 
1903
  bytes_per_line = (bytes_per_line * channels * depth) / 8;
 
1904
 
 
1905
  requested_buffer_size = 8 * bytes_per_line;
 
1906
  /* we must use a round number of bytes_per_line */
 
1907
  if (requested_buffer_size > BULKIN_MAXSIZE)
 
1908
    requested_buffer_size =
 
1909
      (BULKIN_MAXSIZE / bytes_per_line) * bytes_per_line;
 
1910
 
 
1911
  read_buffer_size =
 
1912
    2 * requested_buffer_size +
 
1913
    ((max_shift + stagger) * used_pixels * channels * depth) / 8;
 
1914
 
 
1915
  RIE (sanei_genesys_buffer_free (&(dev->read_buffer)));
 
1916
  RIE (sanei_genesys_buffer_alloc (&(dev->read_buffer), read_buffer_size));
 
1917
 
 
1918
  RIE (sanei_genesys_buffer_free (&(dev->lines_buffer)));
 
1919
  RIE (sanei_genesys_buffer_alloc (&(dev->lines_buffer), read_buffer_size));
 
1920
 
 
1921
  RIE (sanei_genesys_buffer_free (&(dev->shrink_buffer)));
 
1922
  RIE (sanei_genesys_buffer_alloc (&(dev->shrink_buffer),
 
1923
                                   requested_buffer_size));
 
1924
 
 
1925
  RIE (sanei_genesys_buffer_free (&(dev->out_buffer)));
 
1926
  RIE (sanei_genesys_buffer_alloc (&(dev->out_buffer),
 
1927
                                   (8 * dev->settings.pixels * channels *
 
1928
                                    depth) / 8));
 
1929
 
 
1930
 
 
1931
  dev->read_bytes_left = bytes_per_line * lincnt;
 
1932
 
 
1933
  DBG (DBG_info,
 
1934
       "gl847_init_scan_regs: physical bytes to read = %lu\n",
 
1935
       (u_long) dev->read_bytes_left);
 
1936
  dev->read_active = SANE_TRUE;
 
1937
 
 
1938
 
 
1939
  dev->current_setup.pixels = (used_pixels * used_res) / optical_res;
 
1940
  dev->current_setup.lines = lincnt;
 
1941
  dev->current_setup.depth = depth;
 
1942
  dev->current_setup.channels = channels;
 
1943
  dev->current_setup.exposure_time = exposure_time;
 
1944
  dev->current_setup.xres = used_res;
 
1945
  dev->current_setup.yres = yres;
 
1946
  dev->current_setup.half_ccd = half_ccd;
 
1947
  dev->current_setup.stagger = stagger;
 
1948
  dev->current_setup.max_shift = max_shift + stagger;
 
1949
 
 
1950
/* TODO: should this be done elsewhere? */
 
1951
  /* scan bytes to send to the frontend */
 
1952
  /* theory :
 
1953
     target_size =
 
1954
     (dev->settings.pixels * dev->settings.lines * channels * depth) / 8;
 
1955
     but it suffers from integer overflow so we do the following: 
 
1956
 
 
1957
     1 bit color images store color data byte-wise, eg byte 0 contains 
 
1958
     8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains 
 
1959
     8 bits of blue.
 
1960
     This does not fix the overflow, though. 
 
1961
     644mp*16 = 10gp, leading to an overflow
 
1962
     -- pierre
 
1963
   */
 
1964
 
 
1965
  dev->total_bytes_read = 0;
 
1966
  if (depth == 1 || dev->settings.scan_mode == SCAN_MODE_LINEART)
 
1967
    dev->total_bytes_to_read =
 
1968
      ((dev->settings.pixels * dev->settings.lines) / 8 +
 
1969
       (((dev->settings.pixels * dev->settings.lines) % 8) ? 1 : 0)) *
 
1970
      channels;
 
1971
  else
 
1972
    dev->total_bytes_to_read =
 
1973
      dev->settings.pixels * dev->settings.lines * channels * (depth / 8);
 
1974
 
 
1975
  DBG (DBG_info, "gl847_init_scan_regs: total bytes to send = %lu\n",
 
1976
       (u_long) dev->total_bytes_to_read);
 
1977
/* END TODO */
 
1978
 
 
1979
  DBGCOMPLETED;
 
1980
  return SANE_STATUS_GOOD;
 
1981
}
 
1982
 
 
1983
static SANE_Status
 
1984
gl847_calculate_current_setup (Genesys_Device * dev)
 
1985
{
 
1986
  int channels;
 
1987
  int depth;
 
1988
  int start;
 
1989
 
 
1990
  float xres;                   /*dpi */
 
1991
  float yres;                   /*dpi */
 
1992
  float startx;                 /*optical_res, from dummy_pixel+1 */
 
1993
  float pixels;
 
1994
  float lines;
 
1995
  int color_filter;
 
1996
 
 
1997
  int used_res;
 
1998
  int used_pixels;
 
1999
  unsigned int lincnt;
 
2000
  int exposure_time, exposure_time2, led_exposure;
 
2001
  int i;
 
2002
  int stagger;
 
2003
 
 
2004
  int slope_dpi = 0;
 
2005
  int dummy = 0;
 
2006
  int scan_step_type = 1;
 
2007
  int scan_power_mode = 0;
 
2008
  int max_shift;
 
2009
  int pixels_exposure;
 
2010
 
 
2011
  SANE_Bool half_ccd;           /* false: full CCD res is used, true, half max CCD res is used */
 
2012
  int optical_res;
 
2013
 
 
2014
  DBG (DBG_info,
 
2015
       "gl847_calculate_current_setup settings:\n"
 
2016
       "Resolution: %uDPI\n"
 
2017
       "Lines     : %u\n"
 
2018
       "PPL       : %u\n"
 
2019
       "Startpos  : %.3f/%.3f\n"
 
2020
       "Scan mode : %d\n\n",
 
2021
       dev->settings.yres, dev->settings.lines, dev->settings.pixels,
 
2022
       dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode);
 
2023
 
 
2024
  /* channels */
 
2025
  if (dev->settings.scan_mode == 4)     /* single pass color */
 
2026
    channels = 3;
 
2027
  else
 
2028
    channels = 1;
 
2029
 
 
2030
  /* depth */
 
2031
  depth = dev->settings.depth;
 
2032
  if (dev->settings.scan_mode == 0)
 
2033
    depth = 1;
 
2034
 
 
2035
  /* start */
 
2036
  start = SANE_UNFIX (dev->model->x_offset);
 
2037
  start += dev->settings.tl_x;
 
2038
  start = (start * dev->sensor.optical_res) / MM_PER_INCH;
 
2039
 
 
2040
 
 
2041
  xres = dev->settings.xres;    /*dpi */
 
2042
  yres = dev->settings.yres;    /*dpi */
 
2043
  startx = start;               /*optical_res, from dummy_pixel+1 */
 
2044
  pixels = dev->settings.pixels;
 
2045
  lines = dev->settings.lines;
 
2046
  color_filter = dev->settings.color_filter;
 
2047
 
 
2048
 
 
2049
  DBG (DBG_info,
 
2050
       "gl847_calculate_current_setup settings:\n"
 
2051
       "Resolution    : %gDPI/%gDPI\n"
 
2052
       "Lines         : %g\n"
 
2053
       "PPL           : %g\n"
 
2054
       "Startpos      : %g\n"
 
2055
       "Depth/Channels: %u/%u\n\n",
 
2056
       xres, yres, lines, pixels, startx, depth, channels);
 
2057
 
 
2058
/* half_ccd */
 
2059
  /* we have 2 domains for ccd: xres below or above half ccd max dpi */
 
2060
  if ((dev->sensor.optical_res < 2 * xres) ||
 
2061
      !(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE))
 
2062
    {
 
2063
      half_ccd = SANE_FALSE;
 
2064
    }
 
2065
  else
 
2066
    {
 
2067
      half_ccd = SANE_TRUE;
 
2068
    }
 
2069
 
 
2070
/* optical_res */
 
2071
 
 
2072
  optical_res = dev->sensor.optical_res;
 
2073
  if (half_ccd)
 
2074
    optical_res /= 2;
 
2075
 
 
2076
/* stagger */
 
2077
 
 
2078
  if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE))
 
2079
    stagger = (4 * yres) / dev->motor.base_ydpi;
 
2080
  else
 
2081
    stagger = 0;
 
2082
  DBG (DBG_info, "gl847_calculate_current_setup: stagger=%d lines\n",
 
2083
       stagger);
 
2084
 
 
2085
/* used_res */
 
2086
  i = optical_res / xres;
 
2087
 
 
2088
#if 0
 
2089
/* gl847 supports 1/1 1/2 1/3 1/4 1/5 1/6 1/8 1/10 1/12 1/15 averaging */
 
2090
  if (i < 2)                    /* optical_res >= xres > optical_res/2 */
 
2091
    used_res = optical_res;
 
2092
  else if (i < 3)               /* optical_res/2 >= xres > optical_res/3 */
 
2093
    used_res = optical_res / 2;
 
2094
  else if (i < 4)               /* optical_res/3 >= xres > optical_res/4 */
 
2095
    used_res = optical_res / 3;
 
2096
  else if (i < 5)               /* optical_res/4 >= xres > optical_res/5 */
 
2097
    used_res = optical_res / 4;
 
2098
  else if (i < 6)               /* optical_res/5 >= xres > optical_res/6 */
 
2099
    used_res = optical_res / 5;
 
2100
  else if (i < 8)               /* optical_res/6 >= xres > optical_res/8 */
 
2101
    used_res = optical_res / 6;
 
2102
  else if (i < 10)              /* optical_res/8 >= xres > optical_res/10 */
 
2103
    used_res = optical_res / 8;
 
2104
  else if (i < 12)              /* optical_res/10 >= xres > optical_res/12 */
 
2105
    used_res = optical_res / 10;
 
2106
  else if (i < 15)              /* optical_res/12 >= xres > optical_res/15 */
 
2107
    used_res = optical_res / 12;
 
2108
  else
 
2109
    used_res = optical_res / 15;
 
2110
#endif
 
2111
  /* resolution is choosen from a fixed list */
 
2112
  used_res = xres;
 
2113
 
 
2114
  /* compute scan parameters values */
 
2115
  /* pixels are allways given at half or full CCD optical resolution */
 
2116
  /* use detected left margin  and fixed value */
 
2117
 
 
2118
  /* compute correct pixels number */
 
2119
  used_pixels = (pixels * optical_res) / used_res;
 
2120
 
 
2121
/* dummy */
 
2122
  /* dummy lines: may not be usefull, for instance 250 dpi works with 0 or 1
 
2123
     dummy line. Maybe the dummy line adds correctness since the motor runs 
 
2124
     slower (higher dpi) 
 
2125
   */
 
2126
/* for cis this creates better aligned color lines:
 
2127
dummy \ scanned lines
 
2128
   0: R           G           B           R ...
 
2129
   1: R        G        B        -        R ...
 
2130
   2: R      G      B       -      -      R ...
 
2131
   3: R     G     B     -     -     -     R ...
 
2132
   4: R    G    B     -   -     -    -    R ...
 
2133
   5: R    G   B    -   -   -    -   -    R ...
 
2134
   6: R   G   B   -   -   -   -   -   -   R ...
 
2135
   7: R   G  B   -  -   -   -  -   -  -   R ...
 
2136
   8: R  G  B   -  -  -   -  -  -   -  -  R ...
 
2137
   9: R  G  B  -  -  -  -  -  -  -  -  -  R ...
 
2138
  10: R  G B  -  -  -  - -  -  -  -  - -  R ...
 
2139
  11: R  G B  - -  - -  -  - -  - -  - -  R ...
 
2140
  12: R G  B - -  - -  - -  - -  - - -  - R ...
 
2141
  13: R G B  - - - -  - - -  - - - -  - - R ...
 
2142
  14: R G B - - -  - - - - - -  - - - - - R ...
 
2143
  15: R G B - - - - - - - - - - - - - - - R ...
 
2144
 -- pierre
 
2145
 */
 
2146
  dummy = 3-channels;
 
2147
 
 
2148
/* slope_dpi */
 
2149
/* cis color scan is effectively a gray scan with 3 gray lines per color
 
2150
   line and a FILTER of 0 */
 
2151
  if (dev->model->is_cis)
 
2152
    slope_dpi = yres * channels;
 
2153
  else
 
2154
    slope_dpi = yres;
 
2155
 
 
2156
  slope_dpi = slope_dpi * (1 + dummy);
 
2157
 
 
2158
  /* scan_step_type */
 
2159
  switch((int)yres)
 
2160
    {
 
2161
    case 75:
 
2162
    case 100:
 
2163
    case 150:
 
2164
      scan_step_type = 0;
 
2165
      break;
 
2166
    case 200:
 
2167
    case 300:
 
2168
      scan_step_type = 1;
 
2169
      break;
 
2170
    default:
 
2171
      scan_step_type = 2;
 
2172
    }
 
2173
 
 
2174
  led_exposure = gl847_get_led_exposure (dev);
 
2175
 
 
2176
  pixels_exposure=dev->sensor.sensor_pixels+572;
 
2177
  if(xres<dev->sensor.optical_res)
 
2178
    pixels_exposure=(pixels_exposure*xres)/dev->sensor.optical_res-32;
 
2179
  else
 
2180
    pixels_exposure=0;
 
2181
 
 
2182
/* exposure_time */
 
2183
  exposure_time = sanei_genesys_exposure_time2 (dev,
 
2184
                                                slope_dpi,
 
2185
                                                scan_step_type,
 
2186
                                                pixels_exposure,
 
2187
                                                led_exposure,
 
2188
                                                scan_power_mode);
 
2189
 
 
2190
  while (scan_power_mode + 1 < dev->motor.power_mode_count)
 
2191
    {
 
2192
      exposure_time2 = sanei_genesys_exposure_time2 (dev,
 
2193
                                                     slope_dpi,
 
2194
                                                     scan_step_type,
 
2195
                                                     pixels_exposure,
 
2196
                                                     led_exposure,
 
2197
                                                     scan_power_mode + 1);
 
2198
      if (exposure_time < exposure_time2)
 
2199
        break;
 
2200
      exposure_time = exposure_time2;
 
2201
      scan_power_mode++;
 
2202
    }
 
2203
 
 
2204
  DBG (DBG_info,
 
2205
       "gl847_calculate_current_setup : exposure_time=%d pixels\n",
 
2206
       exposure_time);
 
2207
 
 
2208
/* max_shift */
 
2209
  /* scanned area must be enlarged by max color shift needed */
 
2210
  /* all values are assumed >= 0 */
 
2211
  if (channels > 1)
 
2212
    {
 
2213
      max_shift = dev->model->ld_shift_r;
 
2214
      if (dev->model->ld_shift_b > max_shift)
 
2215
        max_shift = dev->model->ld_shift_b;
 
2216
      if (dev->model->ld_shift_g > max_shift)
 
2217
        max_shift = dev->model->ld_shift_g;
 
2218
      max_shift = (max_shift * yres) / dev->motor.base_ydpi;
 
2219
    }
 
2220
  else
 
2221
    {
 
2222
      max_shift = 0;
 
2223
    }
 
2224
 
 
2225
/* lincnt */
 
2226
  lincnt = lines + max_shift + stagger;
 
2227
 
 
2228
  dev->current_setup.pixels = (used_pixels * used_res) / optical_res;
 
2229
  dev->current_setup.lines = lincnt;
 
2230
  dev->current_setup.depth = depth;
 
2231
  dev->current_setup.channels = channels;
 
2232
  dev->current_setup.exposure_time = exposure_time;
 
2233
  dev->current_setup.xres = used_res;
 
2234
  dev->current_setup.yres = yres;
 
2235
  dev->current_setup.half_ccd = half_ccd;
 
2236
  dev->current_setup.stagger = stagger;
 
2237
  dev->current_setup.max_shift = max_shift + stagger;
 
2238
 
 
2239
  DBGCOMPLETED;
 
2240
  return SANE_STATUS_GOOD;
 
2241
}
 
2242
 
 
2243
static void
 
2244
gl847_set_motor_power (Genesys_Register_Set * regs, SANE_Bool set)
 
2245
{
 
2246
 
 
2247
  DBG (DBG_proc, "gl847_set_motor_power\n");
 
2248
 
 
2249
  if (set)
 
2250
    {
 
2251
      sanei_genesys_set_reg_from_set (regs, REG02,
 
2252
                                      sanei_genesys_read_reg_from_set (regs,
 
2253
                                                                       REG02)
 
2254
                                      | REG02_MTRPWR);
 
2255
    }
 
2256
  else
 
2257
    {
 
2258
      sanei_genesys_set_reg_from_set (regs, REG02,
 
2259
                                      sanei_genesys_read_reg_from_set (regs,
 
2260
                                                                       REG02)
 
2261
                                      & ~REG02_MTRPWR);
 
2262
    }
 
2263
}
 
2264
 
 
2265
static void
 
2266
gl847_set_lamp_power (Genesys_Device * dev,
 
2267
                      Genesys_Register_Set * regs, SANE_Bool set)
 
2268
{
 
2269
  Genesys_Register_Set *r;
 
2270
  int i;
 
2271
 
 
2272
  if (set)
 
2273
    {
 
2274
      sanei_genesys_set_reg_from_set (regs, 0x03,
 
2275
                                      sanei_genesys_read_reg_from_set (regs,
 
2276
                                                                       0x03)
 
2277
                                      | REG03_LAMPPWR);
 
2278
 
 
2279
      for (i = 0; i < 6; i++)
 
2280
        {
 
2281
          r = sanei_genesys_get_address (dev->calib_reg, 0x10+i);
 
2282
          r->value = dev->sensor.regs_0x10_0x1d[i];
 
2283
        }
 
2284
      r = sanei_genesys_get_address (regs, 0x19);
 
2285
      r->value = 0x50;
 
2286
    }
 
2287
  else
 
2288
    {
 
2289
      sanei_genesys_set_reg_from_set (regs, 0x03,
 
2290
                                      sanei_genesys_read_reg_from_set (regs,
 
2291
                                                                       0x03)
 
2292
                                      & ~REG03_LAMPPWR);
 
2293
 
 
2294
      for (i = 0; i < 6; i++)
 
2295
        {
 
2296
          r = sanei_genesys_get_address (dev->calib_reg, 0x10+i);
 
2297
          r->value = 0x00;
 
2298
        }
 
2299
      r = sanei_genesys_get_address (regs, 0x19);
 
2300
      r->value = 0xff;
 
2301
    }
 
2302
}
 
2303
 
 
2304
/*for fast power saving methods only, like disabling certain amplifiers*/
 
2305
static SANE_Status
 
2306
gl847_save_power (Genesys_Device * dev, SANE_Bool enable)
 
2307
{
 
2308
  DBG (DBG_proc, "gl847_save_power: enable = %d\n", enable);
 
2309
  if (dev == NULL)
 
2310
    return SANE_STATUS_INVAL;
 
2311
 
 
2312
  DBGCOMPLETED;
 
2313
  return SANE_STATUS_GOOD;
 
2314
}
 
2315
 
 
2316
static SANE_Status
 
2317
gl847_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ )
 
2318
{
 
2319
  DBG (DBG_proc, "gl847_set_powersaving (delay = %d)\n", delay);
 
2320
  if (dev == NULL)
 
2321
    return SANE_STATUS_INVAL;
 
2322
 
 
2323
  DBGCOMPLETED;
 
2324
  return SANE_STATUS_GOOD;
 
2325
}
 
2326
 
 
2327
static SANE_Status
 
2328
gl847_start_action (Genesys_Device * dev)
 
2329
{
 
2330
  return sanei_genesys_write_register (dev, 0x0f, 0x01);
 
2331
}
 
2332
 
 
2333
static SANE_Status
 
2334
gl847_stop_action (Genesys_Device * dev)
 
2335
{
 
2336
  Genesys_Register_Set local_reg[GENESYS_GL847_MAX_REGS];
 
2337
  SANE_Status status;
 
2338
  uint8_t val40, val;
 
2339
  unsigned int loop;
 
2340
 
 
2341
  DBG (DBG_proc, "%s\n", __FUNCTION__);
 
2342
 
 
2343
  status = sanei_genesys_get_status (dev, &val);
 
2344
  if (DBG_LEVEL >= DBG_io)
 
2345
    {
 
2346
      print_status (val);
 
2347
    }
 
2348
 
 
2349
  val40 = 0;
 
2350
  status = sanei_genesys_read_register (dev, REG40, &val40);
 
2351
  if (status != SANE_STATUS_GOOD)
 
2352
    {
 
2353
      DBG (DBG_error,
 
2354
           "%s: failed to read home sensor: %s\n", __FUNCTION__,
 
2355
           sane_strstatus (status));
 
2356
      DBGCOMPLETED;
 
2357
      return status;
 
2358
    }
 
2359
 
 
2360
  /* only stop action if needed */
 
2361
  if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG))
 
2362
    {
 
2363
      DBG (DBG_info, "%s: already stopped\n", __FUNCTION__);
 
2364
      DBGCOMPLETED;
 
2365
      return SANE_STATUS_GOOD;
 
2366
    }
 
2367
 
 
2368
  memset (local_reg, 0, sizeof (local_reg));
 
2369
 
 
2370
  memcpy (local_reg, dev->reg,
 
2371
          GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set));
 
2372
 
 
2373
  gl847_init_optical_regs_off (dev, local_reg);
 
2374
 
 
2375
  gl847_init_motor_regs_off (dev, local_reg, 0);
 
2376
  status = gl847_bulk_write_register (dev, local_reg, GENESYS_GL847_MAX_REGS);
 
2377
  if (status != SANE_STATUS_GOOD)
 
2378
    {
 
2379
      DBG (DBG_error, "%s: failed to bulk write registers: %s\n",
 
2380
           __FUNCTION__, sane_strstatus (status));
 
2381
      return status;
 
2382
    }
 
2383
 
 
2384
  /* looks like writing the right registers to zero is enough to get the chip 
 
2385
     out of scan mode into command mode, actually triggering(writing to 
 
2386
     register 0x0f) seems to be unnecessary */
 
2387
 
 
2388
  loop = 10;
 
2389
  while (loop > 0)
 
2390
    {
 
2391
      status = sanei_genesys_get_status (dev, &val);
 
2392
      if (DBG_LEVEL >= DBG_io)
 
2393
        {
 
2394
          print_status (val);
 
2395
        }
 
2396
      val40 = 0;
 
2397
      status = sanei_genesys_read_register (dev, 0x40, &val40);
 
2398
      if (status != SANE_STATUS_GOOD)
 
2399
        {
 
2400
          DBG (DBG_error,
 
2401
               "%s: failed to read home sensor: %s\n", __FUNCTION__,
 
2402
               sane_strstatus (status));
 
2403
          DBGCOMPLETED;
 
2404
          return status;
 
2405
        }
 
2406
 
 
2407
      /* if scanner is in command mode, we are done */
 
2408
      if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG)
 
2409
          && !(val & REG41_MOTORENB))
 
2410
        {
 
2411
          DBGCOMPLETED;
 
2412
          return SANE_STATUS_GOOD;
 
2413
        }
 
2414
 
 
2415
      usleep (100 * 1000);
 
2416
      loop--;
 
2417
    }
 
2418
 
 
2419
  DBGCOMPLETED;
 
2420
  return SANE_STATUS_IO_ERROR;
 
2421
}
 
2422
 
 
2423
static SANE_Status
 
2424
gl847_get_paper_sensor (Genesys_Device * dev, SANE_Bool * paper_loaded)
 
2425
{
 
2426
  SANE_Status status;
 
2427
  uint8_t val;
 
2428
 
 
2429
  status = sanei_genesys_read_register (dev, REG6D, &val);
 
2430
  if (status != SANE_STATUS_GOOD)
 
2431
    {
 
2432
      DBG (DBG_error,
 
2433
           "gl847_get_paper_sensor: failed to read gpio: %s\n",
 
2434
           sane_strstatus (status));
 
2435
      return status;
 
2436
    }
 
2437
  *paper_loaded = (val & 0x1) == 0;
 
2438
  return SANE_STATUS_GOOD;
 
2439
 
 
2440
  return SANE_STATUS_INVAL;
 
2441
}
 
2442
 
 
2443
static SANE_Status
 
2444
gl847_eject_document (Genesys_Device * dev)
 
2445
{
 
2446
  Genesys_Register_Set local_reg[GENESYS_GL847_MAX_REGS];
 
2447
  SANE_Status status;
 
2448
  uint8_t val;
 
2449
  SANE_Bool paper_loaded;
 
2450
  unsigned int init_steps;
 
2451
  float feed_mm;
 
2452
  int loop;
 
2453
 
 
2454
  DBG (DBG_proc, "gl847_eject_document\n");
 
2455
 
 
2456
  if (!dev->model->is_sheetfed == SANE_TRUE)
 
2457
    {
 
2458
      DBG (DBG_proc,
 
2459
           "gl847_eject_document: there is no \"eject sheet\"-concept for non sheet fed\n");
 
2460
      DBG (DBG_proc, "gl847_eject_document: finished\n");
 
2461
      return SANE_STATUS_GOOD;
 
2462
    }
 
2463
 
 
2464
 
 
2465
  memset (local_reg, 0, sizeof (local_reg));
 
2466
  val = 0;
 
2467
 
 
2468
  status = sanei_genesys_get_status (dev, &val);
 
2469
  if (status != SANE_STATUS_GOOD)
 
2470
    {
 
2471
      DBG (DBG_error,
 
2472
           "gl847_eject_document: Failed to read status register: %s\n",
 
2473
           sane_strstatus (status));
 
2474
      return status;
 
2475
    }
 
2476
 
 
2477
  status = gl847_stop_action (dev);
 
2478
  if (status != SANE_STATUS_GOOD)
 
2479
    {
 
2480
      DBG (DBG_error,
 
2481
           "gl847_eject_document: failed to stop motor: %s\n",
 
2482
           sane_strstatus (status));
 
2483
      return SANE_STATUS_IO_ERROR;
 
2484
    }
 
2485
 
 
2486
  memcpy (local_reg, dev->reg,
 
2487
          GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set));
 
2488
 
 
2489
  gl847_init_optical_regs_off (dev, local_reg);
 
2490
 
 
2491
  gl847_init_motor_regs (dev, local_reg, 65536, MOTOR_ACTION_FEED, 0);
 
2492
 
 
2493
  status = gl847_bulk_write_register (dev, local_reg, GENESYS_GL847_MAX_REGS);
 
2494
  if (status != SANE_STATUS_GOOD)
 
2495
    {
 
2496
      DBG (DBG_error,
 
2497
           "gl847_eject_document: failed to bulk write registers: %s\n",
 
2498
           sane_strstatus (status));
 
2499
      return status;
 
2500
    }
 
2501
 
 
2502
  status = gl847_start_action (dev);
 
2503
  if (status != SANE_STATUS_GOOD)
 
2504
    {
 
2505
      DBG (DBG_error,
 
2506
           "gl847_eject_document: failed to start motor: %s\n",
 
2507
           sane_strstatus (status));
 
2508
      gl847_stop_action (dev);
 
2509
      /* send original registers */
 
2510
      gl847_bulk_write_register (dev, dev->reg, GENESYS_GL847_MAX_REGS);
 
2511
      return status;
 
2512
    }
 
2513
 
 
2514
  RIE (gl847_get_paper_sensor (dev, &paper_loaded));
 
2515
  if (paper_loaded)
 
2516
    {
 
2517
      DBG (DBG_info, "gl847_eject_document: paper still loaded\n");
 
2518
      /* force document TRUE, because it is definitely present */
 
2519
      dev->document = SANE_TRUE;
 
2520
      dev->scanhead_position_in_steps = 0;
 
2521
 
 
2522
      loop = 300;
 
2523
      while (loop > 0)          /* do not wait longer then 30 seconds */
 
2524
        {
 
2525
 
 
2526
          RIE (gl847_get_paper_sensor (dev, &paper_loaded));
 
2527
 
 
2528
          if (!paper_loaded)
 
2529
            {
 
2530
              DBG (DBG_info, "gl847_eject_document: reached home position\n");
 
2531
              DBG (DBG_proc, "gl847_eject_document: finished\n");
 
2532
              break;
 
2533
            }
 
2534
          usleep (100000);      /* sleep 100 ms */
 
2535
          --loop;
 
2536
        }
 
2537
 
 
2538
      if (loop == 0)
 
2539
        {
 
2540
          /* when we come here then the scanner needed too much time for this, so we better stop the motor */
 
2541
          gl847_stop_action (dev);
 
2542
          DBG (DBG_error,
 
2543
               "gl847_eject_document: timeout while waiting for scanhead to go home\n");
 
2544
          return SANE_STATUS_IO_ERROR;
 
2545
        }
 
2546
    }
 
2547
 
 
2548
  feed_mm = SANE_UNFIX (dev->model->eject_feed);
 
2549
  if (dev->document)
 
2550
    {
 
2551
      feed_mm += SANE_UNFIX (dev->model->post_scan);
 
2552
    }
 
2553
 
 
2554
  status = sanei_genesys_read_feed_steps (dev, &init_steps);
 
2555
  if (status != SANE_STATUS_GOOD)
 
2556
    {
 
2557
      DBG (DBG_error,
 
2558
           "gl847_eject_document: Failed to read feed steps: %s\n",
 
2559
           sane_strstatus (status));
 
2560
      return status;
 
2561
    }
 
2562
 
 
2563
  /* now feed for extra <number> steps */
 
2564
  loop = 0;
 
2565
  while (loop < 300)            /* do not wait longer then 30 seconds */
 
2566
    {
 
2567
      unsigned int steps;
 
2568
 
 
2569
      status = sanei_genesys_read_feed_steps (dev, &steps);
 
2570
      if (status != SANE_STATUS_GOOD)
 
2571
        {
 
2572
          DBG (DBG_error,
 
2573
               "gl847_eject_document: Failed to read feed steps: %s\n",
 
2574
               sane_strstatus (status));
 
2575
          return status;
 
2576
        }
 
2577
 
 
2578
      DBG (DBG_info, "gl847_eject_document: init_steps: %d, steps: %d\n",
 
2579
           init_steps, steps);
 
2580
 
 
2581
      if (steps > init_steps + (feed_mm * dev->motor.base_ydpi) / MM_PER_INCH)
 
2582
        {
 
2583
          break;
 
2584
        }
 
2585
 
 
2586
      usleep (100000);          /* sleep 100 ms */
 
2587
      ++loop;
 
2588
    }
 
2589
 
 
2590
  status = gl847_stop_action (dev);
 
2591
  if (status != SANE_STATUS_GOOD)
 
2592
    {
 
2593
      DBG (DBG_error,
 
2594
           "gl847_eject_document: Failed to stop motor: %s\n",
 
2595
           sane_strstatus (status));
 
2596
      return status;
 
2597
    }
 
2598
 
 
2599
  dev->document = SANE_FALSE;
 
2600
 
 
2601
  DBG (DBG_proc, "gl847_eject_document: finished\n");
 
2602
  return SANE_STATUS_GOOD;
 
2603
}
 
2604
 
 
2605
 
 
2606
static SANE_Status
 
2607
gl847_load_document (Genesys_Device * dev)
 
2608
{
 
2609
  SANE_Status status;
 
2610
  SANE_Bool paper_loaded;
 
2611
  int loop = 300;
 
2612
  DBG (DBG_proc, "gl847_load_document\n");
 
2613
  while (loop > 0)              /* do not wait longer then 30 seconds */
 
2614
    {
 
2615
 
 
2616
      RIE (gl847_get_paper_sensor (dev, &paper_loaded));
 
2617
 
 
2618
      if (paper_loaded)
 
2619
        {
 
2620
          DBG (DBG_info, "gl847_load_document: document inserted\n");
 
2621
 
 
2622
          /* when loading OK, document is here */
 
2623
          dev->document = SANE_TRUE;
 
2624
 
 
2625
          usleep (1000000);     /* give user 1000ms to place document correctly */
 
2626
          break;
 
2627
        }
 
2628
      usleep (100000);          /* sleep 100 ms */
 
2629
      --loop;
 
2630
    }
 
2631
 
 
2632
  if (loop == 0)
 
2633
    {
 
2634
      /* when we come here then the user needed to much time for this */
 
2635
      DBG (DBG_error,
 
2636
           "gl847_load_document: timeout while waiting for document\n");
 
2637
      return SANE_STATUS_IO_ERROR;
 
2638
    }
 
2639
 
 
2640
  DBG (DBG_proc, "gl847_load_document: finished\n");
 
2641
  return SANE_STATUS_GOOD;
 
2642
}
 
2643
 
 
2644
/**
 
2645
 * detects end of document and adjust current scan
 
2646
 * to take it into account
 
2647
 * used by sheetfed scanners
 
2648
 */
 
2649
static SANE_Status
 
2650
gl847_detect_document_end (Genesys_Device * dev)
 
2651
{
 
2652
  SANE_Status status = SANE_STATUS_GOOD;
 
2653
  SANE_Bool paper_loaded;
 
2654
  unsigned int scancnt = 0;
 
2655
  int flines, channels, depth, bytes_remain, sublines,
 
2656
    bytes_to_flush, lines, sub_bytes, tmp, read_bytes_left;
 
2657
  DBG (DBG_proc, "%s: begin\n", __FUNCTION__);
 
2658
 
 
2659
  RIE (gl847_get_paper_sensor (dev, &paper_loaded));
 
2660
 
 
2661
  /* sheetfed scanner uses home sensor as paper present */
 
2662
  if ((dev->document == SANE_TRUE) && !paper_loaded)
 
2663
    {
 
2664
      DBG (DBG_info, "%s: no more document\n", __FUNCTION__);
 
2665
      dev->document = SANE_FALSE;
 
2666
 
 
2667
      channels = dev->current_setup.channels;
 
2668
      depth = dev->current_setup.depth;
 
2669
      read_bytes_left = (int) dev->read_bytes_left;
 
2670
      DBG (DBG_io, "gl847_detect_document_end: read_bytes_left=%d\n",
 
2671
           read_bytes_left);
 
2672
 
 
2673
      /* get lines read */
 
2674
      status = sanei_genesys_read_scancnt (dev, &scancnt);
 
2675
      if (status != SANE_STATUS_GOOD)
 
2676
        {
 
2677
          flines = 0;
 
2678
        }
 
2679
      else
 
2680
        {
 
2681
          /* compute number of line read */
 
2682
          tmp = (int) dev->total_bytes_read;
 
2683
          if (depth == 1 || dev->settings.scan_mode == SCAN_MODE_LINEART)
 
2684
            flines = tmp * 8 / dev->settings.pixels / channels;
 
2685
          else
 
2686
            flines = tmp / (depth / 8) / dev->settings.pixels / channels;
 
2687
 
 
2688
          /* number of scanned lines, but no read yet */
 
2689
          flines = scancnt - flines;
 
2690
 
 
2691
          DBG (DBG_io,
 
2692
               "gl847_detect_document_end: %d scanned but not read lines\n",
 
2693
               flines);
 
2694
        }
 
2695
 
 
2696
      /* adjust number of bytes to read 
 
2697
       * we need to read the final bytes which are word per line * number of last lines
 
2698
       * to have doc leaving feeder */
 
2699
      lines =
 
2700
        (SANE_UNFIX (dev->model->post_scan) * dev->current_setup.yres) /
 
2701
        MM_PER_INCH + flines;
 
2702
      DBG (DBG_io, "gl847_detect_document_end: adding %d line to flush\n",
 
2703
           lines);
 
2704
 
 
2705
      /* number of bytes to read from scanner to get document out of it after
 
2706
       * end of document dectected by hardware sensor */
 
2707
      bytes_to_flush = lines * dev->wpl;
 
2708
 
 
2709
      /* if we are already close to end of scan, flushing isn't needed */
 
2710
      if (bytes_to_flush < read_bytes_left)
 
2711
        {
 
2712
          /* we take all these step to work around an overflow on some plateforms */
 
2713
          tmp = (int) dev->total_bytes_read;
 
2714
          DBG (DBG_io, "gl847_detect_document_end: tmp=%d\n", tmp);
 
2715
          bytes_remain = (int) dev->total_bytes_to_read;
 
2716
          DBG (DBG_io, "gl847_detect_document_end: bytes_remain=%d\n",
 
2717
               bytes_remain);
 
2718
          bytes_remain = bytes_remain - tmp;
 
2719
          DBG (DBG_io, "gl847_detect_document_end: bytes_remain=%d\n",
 
2720
               bytes_remain);
 
2721
 
 
2722
          /* remaining lines to read by frontend for the current scan */
 
2723
          if (depth == 1 || dev->settings.scan_mode == SCAN_MODE_LINEART)
 
2724
            {
 
2725
              flines = bytes_remain * 8 / dev->settings.pixels / channels;
 
2726
            }
 
2727
          else
 
2728
            flines = bytes_remain / (depth / 8)
 
2729
              / dev->settings.pixels / channels;
 
2730
          DBG (DBG_io, "gl847_detect_document_end: flines=%d\n", flines);
 
2731
 
 
2732
          if (flines > lines)
 
2733
            {
 
2734
              /* change the value controlling communication with the frontend :
 
2735
               * total bytes to read is current value plus the number of remaining lines 
 
2736
               * multiplied by bytes per line */
 
2737
              sublines = flines - lines;
 
2738
 
 
2739
              if (depth == 1 || dev->settings.scan_mode == SCAN_MODE_LINEART)
 
2740
                sub_bytes =
 
2741
                  ((dev->settings.pixels * sublines) / 8 +
 
2742
                   (((dev->settings.pixels * sublines) % 8) ? 1 : 0)) *
 
2743
                  channels;
 
2744
              else
 
2745
                sub_bytes =
 
2746
                  dev->settings.pixels * sublines * channels * (depth / 8);
 
2747
 
 
2748
              dev->total_bytes_to_read -= sub_bytes;
 
2749
 
 
2750
              /* then adjust the physical bytes to read */
 
2751
              if (read_bytes_left > sub_bytes)
 
2752
                {
 
2753
                  dev->read_bytes_left -= sub_bytes;
 
2754
                }
 
2755
              else
 
2756
                {
 
2757
                  dev->total_bytes_to_read = dev->total_bytes_read;
 
2758
                  dev->read_bytes_left = 0;
 
2759
                }
 
2760
 
 
2761
              DBG (DBG_io, "gl847_detect_document_end: sublines=%d\n",
 
2762
                   sublines);
 
2763
              DBG (DBG_io, "gl847_detect_document_end: subbytes=%d\n",
 
2764
                   sub_bytes);
 
2765
              DBG (DBG_io,
 
2766
                   "gl847_detect_document_end: total_bytes_to_read=%lu\n",
 
2767
                   (unsigned long)dev->total_bytes_to_read);
 
2768
              DBG (DBG_io,
 
2769
                   "gl847_detect_document_end: read_bytes_left=%d\n",
 
2770
                   read_bytes_left);
 
2771
            }
 
2772
        }
 
2773
      else
 
2774
        {
 
2775
          DBG (DBG_io, "gl847_detect_document_end: no flushing needed\n");
 
2776
        }
 
2777
    }
 
2778
 
 
2779
  DBG (DBG_proc, "%s: finished\n", __FUNCTION__);
 
2780
  return SANE_STATUS_GOOD;
 
2781
}
 
2782
 
 
2783
/* Send the low-level scan command */
 
2784
/* todo : is this that useful ? */
 
2785
#ifndef UNIT_TESTING
 
2786
static
 
2787
#endif
 
2788
  SANE_Status
 
2789
gl847_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg,
 
2790
                  SANE_Bool start_motor)
 
2791
{
 
2792
  SANE_Status status;
 
2793
  uint8_t val;
 
2794
 
 
2795
  DBGSTART;
 
2796
 
 
2797
  /* clear GPIO 10 */
 
2798
  RIE (sanei_genesys_read_register (dev, REG6C, &val));
 
2799
  val &= ~REG6C_GPIO10;
 
2800
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
2801
 
 
2802
  val = REG0D_CLRLNCNT;
 
2803
  RIE (sanei_genesys_write_register (dev, REG0D, val));
 
2804
  val = REG0D_CLRMCNT;
 
2805
  RIE (sanei_genesys_write_register (dev, REG0D, val));
 
2806
 
 
2807
  RIE (sanei_genesys_read_register (dev, REG01, &val));
 
2808
  val |= REG01_SCAN;
 
2809
  RIE (sanei_genesys_write_register (dev, REG01, val));
 
2810
 
 
2811
  if (start_motor)
 
2812
    {
 
2813
      RIE (sanei_genesys_write_register (dev, REG0F, 1));
 
2814
    }
 
2815
  else
 
2816
    {
 
2817
      RIE (sanei_genesys_write_register (dev, REG0F, 0));
 
2818
    }
 
2819
 
 
2820
  DBGCOMPLETED;
 
2821
 
 
2822
  return status;
 
2823
}
 
2824
 
 
2825
 
 
2826
/* Send the stop scan command */
 
2827
#ifndef UNIT_TESTING
 
2828
static
 
2829
#endif
 
2830
  SANE_Status
 
2831
gl847_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg,
 
2832
                SANE_Bool check_stop)
 
2833
{
 
2834
  SANE_Status status;
 
2835
 
 
2836
  DBG (DBG_proc, "gl847_end_scan (check_stop = %d)\n", check_stop);
 
2837
  if (reg == NULL)
 
2838
    return SANE_STATUS_INVAL;
 
2839
 
 
2840
  if (dev->model->is_sheetfed == SANE_TRUE)
 
2841
    {
 
2842
      status = SANE_STATUS_GOOD;
 
2843
    }
 
2844
  else                          /* flat bed scanners */
 
2845
    {
 
2846
      status = gl847_stop_action (dev);
 
2847
      if (status != SANE_STATUS_GOOD)
 
2848
        {
 
2849
          DBG (DBG_error,
 
2850
               "gl847_end_scan: Failed to stop: %s\n",
 
2851
               sane_strstatus (status));
 
2852
          return status;
 
2853
        }
 
2854
    }
 
2855
 
 
2856
  DBGCOMPLETED;
 
2857
  return status;
 
2858
}
 
2859
 
 
2860
/* Moves the slider to steps */
 
2861
static SANE_Status
 
2862
gl847_feed (Genesys_Device * dev, int steps)
 
2863
{
 
2864
  Genesys_Register_Set local_reg[GENESYS_GL847_MAX_REGS];
 
2865
  SANE_Status status;
 
2866
  uint8_t val;
 
2867
  int loop;
 
2868
 
 
2869
  DBG (DBG_proc, "gl847_feed (steps = %d)\n", steps);
 
2870
 
 
2871
  status = gl847_stop_action (dev);
 
2872
  if (status != SANE_STATUS_GOOD)
 
2873
    {
 
2874
      DBG (DBG_error,
 
2875
           "gl847_feed: failed to stop action: %s\n",
 
2876
           sane_strstatus (status));
 
2877
      return status;
 
2878
    }
 
2879
 
 
2880
  memset (local_reg, 0, sizeof (local_reg));
 
2881
 
 
2882
  memcpy (local_reg, dev->reg,
 
2883
          GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set));
 
2884
 
 
2885
  gl847_init_optical_regs_off (dev, local_reg);
 
2886
 
 
2887
  gl847_init_motor_regs (dev, local_reg, steps, MOTOR_ACTION_FEED, 0);
 
2888
 
 
2889
  status = gl847_bulk_write_register (dev, local_reg, GENESYS_GL847_MAX_REGS);
 
2890
  if (status != SANE_STATUS_GOOD)
 
2891
    {
 
2892
      DBG (DBG_error,
 
2893
           "gl847_feed: failed to bulk write registers: %s\n",
 
2894
           sane_strstatus (status));
 
2895
      return status;
 
2896
    }
 
2897
 
 
2898
  status = gl847_start_action (dev);
 
2899
  if (status != SANE_STATUS_GOOD)
 
2900
    {
 
2901
      DBG (DBG_error,
 
2902
           "gl847_feed: failed to start motor: %s\n",
 
2903
           sane_strstatus (status));
 
2904
      gl847_stop_action (dev);
 
2905
      /* send original registers */
 
2906
      gl847_bulk_write_register (dev, dev->reg, GENESYS_GL847_MAX_REGS);
 
2907
      return status;
 
2908
    }
 
2909
 
 
2910
  loop = 0;
 
2911
  while (loop < 300)            /* do not wait longer then 30 seconds */
 
2912
    {
 
2913
      status = sanei_genesys_get_status (dev, &val);
 
2914
      if (status != SANE_STATUS_GOOD)
 
2915
        {
 
2916
          DBG (DBG_error,
 
2917
               "gl847_feed: failed to read home sensor: %s\n",
 
2918
               sane_strstatus (status));
 
2919
          return status;
 
2920
        }
 
2921
 
 
2922
      if (!(val & REG41_MOTORENB))      /* motor enabled */
 
2923
        {
 
2924
          DBG (DBG_proc, "gl847_feed: finished\n");
 
2925
          dev->scanhead_position_in_steps += steps;
 
2926
          return SANE_STATUS_GOOD;
 
2927
        }
 
2928
      usleep (100000);          /* sleep 100 ms */
 
2929
      ++loop;
 
2930
    }
 
2931
 
 
2932
  /* when we come here then the scanner needed too much time for this, so we better stop the motor */
 
2933
  gl847_stop_action (dev);
 
2934
 
 
2935
  DBG (DBG_error,
 
2936
       "gl847_feed: timeout while feeding\n");
 
2937
  return SANE_STATUS_IO_ERROR;
 
2938
}
 
2939
 
 
2940
/* Moves the slider to the home (top) postion slowly */
 
2941
static SANE_Status
 
2942
gl847_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home)
 
2943
{
 
2944
  Genesys_Register_Set local_reg[GENESYS_GL847_MAX_REGS];
 
2945
  SANE_Status status;
 
2946
  uint8_t val;
 
2947
 
 
2948
  DBG (DBG_proc, "gl847_slow_back_home (wait_until_home = %d)\n",
 
2949
       wait_until_home);
 
2950
 
 
2951
  if (dev->model->is_sheetfed == SANE_TRUE)
 
2952
    {
 
2953
      DBG (DBG_proc,
 
2954
           "gl847_slow_back_home: there is no \"home\"-concept for sheet fed\n");
 
2955
      DBG (DBG_proc, "gl847_slow_back_home: finished\n");
 
2956
      return SANE_STATUS_GOOD;
 
2957
    }
 
2958
 
 
2959
  memset (local_reg, 0, sizeof (local_reg));
 
2960
 
 
2961
  /* reset gpio pin */
 
2962
  RIE (sanei_genesys_read_register (dev, REG6C, &val));
 
2963
  val = dev->gpo.value[0];
 
2964
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
2965
 
 
2966
  /* first read gives HOME_SENSOR true */
 
2967
  status = sanei_genesys_get_status (dev, &val);
 
2968
  if (status != SANE_STATUS_GOOD)
 
2969
    {
 
2970
      DBG (DBG_error,
 
2971
           "gl847_slow_back_home: failed to read home sensor: %s\n",
 
2972
           sane_strstatus (status));
 
2973
      return status;
 
2974
    }
 
2975
  if (DBG_LEVEL >= DBG_io)
 
2976
    {
 
2977
      print_status (val);
 
2978
    }
 
2979
  usleep (100000);              /* sleep 100 ms */
 
2980
 
 
2981
  /* second is reliable */
 
2982
  status = sanei_genesys_get_status (dev, &val);
 
2983
  if (status != SANE_STATUS_GOOD)
 
2984
    {
 
2985
      DBG (DBG_error,
 
2986
           "gl847_slow_back_home: failed to read home sensor: %s\n",
 
2987
           sane_strstatus (status));
 
2988
      return status;
 
2989
    }
 
2990
  if (DBG_LEVEL >= DBG_io)
 
2991
    {
 
2992
      print_status (val);
 
2993
    }
 
2994
 
 
2995
  dev->scanhead_position_in_steps = 0;
 
2996
 
 
2997
  if (val & REG41_HOMESNR)      /* is sensor at home? */
 
2998
    {
 
2999
      DBG (DBG_info, "gl847_slow_back_home: already at home, completed\n");
 
3000
      dev->scanhead_position_in_steps = 0;
 
3001
      DBGCOMPLETED;
 
3002
      return SANE_STATUS_GOOD;
 
3003
    }
 
3004
 
 
3005
  /* if motor is on, stop current action */
 
3006
  if (val & REG41_MOTORENB)
 
3007
    {
 
3008
      status = gl847_stop_action (dev);
 
3009
      if (status != SANE_STATUS_GOOD)
 
3010
        {
 
3011
          DBG (DBG_error,
 
3012
               "gl847_slow_back_home: failed to stop motor: %s\n",
 
3013
               sane_strstatus (status));
 
3014
          return SANE_STATUS_IO_ERROR;
 
3015
        }
 
3016
    }
 
3017
 
 
3018
  memcpy (local_reg, dev->reg,
 
3019
          GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set));
 
3020
 
 
3021
  gl847_init_optical_regs_off (dev, local_reg);
 
3022
 
 
3023
  gl847_init_motor_regs (dev, local_reg, 65536, MOTOR_ACTION_GO_HOME, 0);
 
3024
 
 
3025
  status = gl847_bulk_write_register (dev, local_reg, GENESYS_GL847_MAX_REGS);
 
3026
  if (status != SANE_STATUS_GOOD)
 
3027
    {
 
3028
      DBG (DBG_error,
 
3029
           "gl847_slow_back_home: failed to bulk write registers: %s\n",
 
3030
           sane_strstatus (status));
 
3031
      return status;
 
3032
    }
 
3033
 
 
3034
  status = gl847_start_action (dev);
 
3035
  if (status != SANE_STATUS_GOOD)
 
3036
    {
 
3037
      DBG (DBG_error,
 
3038
           "gl847_slow_back_home: failed to start motor: %s\n",
 
3039
           sane_strstatus (status));
 
3040
      gl847_stop_action (dev);
 
3041
      /* send original registers */
 
3042
      gl847_bulk_write_register (dev, dev->reg, GENESYS_GL847_MAX_REGS);
 
3043
      return status;
 
3044
    }
 
3045
 
 
3046
  if (wait_until_home)
 
3047
    {
 
3048
      int loop = 0;
 
3049
 
 
3050
      while (loop < 300)        /* do not wait longer then 30 seconds */
 
3051
        {
 
3052
          status = sanei_genesys_get_status (dev, &val);
 
3053
          if (status != SANE_STATUS_GOOD)
 
3054
            {
 
3055
              DBG (DBG_error,
 
3056
                   "gl847_slow_back_home: failed to read home sensor: %s\n",
 
3057
                   sane_strstatus (status));
 
3058
              return status;
 
3059
            }
 
3060
 
 
3061
          if (val & REG41_HOMESNR)      /* home sensor */
 
3062
            {
 
3063
              DBG (DBG_info, "gl847_slow_back_home: reached home position\n");
 
3064
              DBG (DBG_proc, "gl847_slow_back_home: finished\n");
 
3065
              return SANE_STATUS_GOOD;
 
3066
            }
 
3067
          usleep (100000);      /* sleep 100 ms */
 
3068
          ++loop;
 
3069
        }
 
3070
 
 
3071
      /* when we come here then the scanner needed too much time for this, so we better stop the motor */
 
3072
      gl847_stop_action (dev);
 
3073
      DBG (DBG_error,
 
3074
           "gl847_slow_back_home: timeout while waiting for scanhead to go home\n");
 
3075
      return SANE_STATUS_IO_ERROR;
 
3076
    }
 
3077
 
 
3078
  DBG (DBG_info, "gl847_slow_back_home: scanhead is still moving\n");
 
3079
  DBG (DBG_proc, "gl847_slow_back_home: finished\n");
 
3080
  return SANE_STATUS_GOOD;
 
3081
}
 
3082
 
 
3083
/* Automatically set top-left edge of the scan area by scanning a 200x200 pixels
 
3084
   area at 600 dpi from very top of scanner */
 
3085
static SANE_Status
 
3086
gl847_search_start_position (Genesys_Device * dev)
 
3087
{
 
3088
  int size;
 
3089
  SANE_Status status;
 
3090
  uint8_t *data;
 
3091
  Genesys_Register_Set local_reg[GENESYS_GL847_MAX_REGS];
 
3092
  int steps;
 
3093
 
 
3094
  int pixels = 600;
 
3095
  int dpi = 300;
 
3096
 
 
3097
  DBG (DBG_proc, "gl847_search_start_position\n");
 
3098
 
 
3099
  memset (local_reg, 0, sizeof (local_reg));
 
3100
  memcpy (local_reg, dev->reg,
 
3101
          GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set));
 
3102
 
 
3103
  /* sets for a 200 lines * 600 pixels */
 
3104
  /* normal scan with no shading */
 
3105
 
 
3106
  status = gl847_init_scan_regs (dev, local_reg, dpi, dpi, 0, 0,        /*we should give a small offset here~60 steps */
 
3107
                                 600, dev->model->search_lines, 8, 1, 1,        /*green */
 
3108
                                 SCAN_FLAG_DISABLE_SHADING |
 
3109
                                 SCAN_FLAG_DISABLE_GAMMA |
 
3110
                                 SCAN_FLAG_IGNORE_LINE_DISTANCE |
 
3111
                                 SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE);
 
3112
 
 
3113
  /* send to scanner */
 
3114
  status = gl847_bulk_write_register (dev, local_reg, GENESYS_GL847_MAX_REGS);
 
3115
  if (status != SANE_STATUS_GOOD)
 
3116
    {
 
3117
      DBG (DBG_error,
 
3118
           "gl847_search_start_position: failed to bulk write registers: %s\n",
 
3119
           sane_strstatus (status));
 
3120
      return status;
 
3121
    }
 
3122
 
 
3123
  size = pixels * dev->model->search_lines;
 
3124
 
 
3125
  data = malloc (size);
 
3126
  if (!data)
 
3127
    {
 
3128
      DBG (DBG_error,
 
3129
           "gl847_search_start_position: failed to allocate memory\n");
 
3130
      return SANE_STATUS_NO_MEM;
 
3131
    }
 
3132
 
 
3133
  status = gl847_begin_scan (dev, local_reg, SANE_TRUE);
 
3134
  if (status != SANE_STATUS_GOOD)
 
3135
    {
 
3136
      free (data);
 
3137
      DBG (DBG_error,
 
3138
           "gl847_search_start_position: failed to begin scan: %s\n",
 
3139
           sane_strstatus (status));
 
3140
      return status;
 
3141
    }
 
3142
 
 
3143
  /* waits for valid data */
 
3144
  do
 
3145
    sanei_genesys_test_buffer_empty (dev, &steps);
 
3146
  while (steps);
 
3147
 
 
3148
  /* now we're on target, we can read data */
 
3149
  status = sanei_genesys_read_data_from_scanner (dev, data, size);
 
3150
  if (status != SANE_STATUS_GOOD)
 
3151
    {
 
3152
      free (data);
 
3153
      DBG (DBG_error,
 
3154
           "gl847_search_start_position: failed to read data: %s\n",
 
3155
           sane_strstatus (status));
 
3156
      return status;
 
3157
    }
 
3158
 
 
3159
  if (DBG_LEVEL >= DBG_data)
 
3160
    sanei_genesys_write_pnm_file ("search_position.pnm", data, 8, 1, pixels,
 
3161
                                  dev->model->search_lines);
 
3162
 
 
3163
  status = gl847_end_scan (dev, local_reg, SANE_TRUE);
 
3164
  if (status != SANE_STATUS_GOOD)
 
3165
    {
 
3166
      free (data);
 
3167
      DBG (DBG_error,
 
3168
           "gl847_search_start_position: failed to end scan: %s\n",
 
3169
           sane_strstatus (status));
 
3170
      return status;
 
3171
    }
 
3172
 
 
3173
  /* update regs to copy ASIC internal state */
 
3174
  memcpy (dev->reg, local_reg,
 
3175
          GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set));
 
3176
 
 
3177
/*TODO: find out where sanei_genesys_search_reference_point 
 
3178
  stores information, and use that correctly*/
 
3179
  status =
 
3180
    sanei_genesys_search_reference_point (dev, data, 0, dpi, pixels,
 
3181
                                          dev->model->search_lines);
 
3182
  if (status != SANE_STATUS_GOOD)
 
3183
    {
 
3184
      free (data);
 
3185
      DBG (DBG_error,
 
3186
           "gl847_search_start_position: failed to set search reference point: %s\n",
 
3187
           sane_strstatus (status));
 
3188
      return status;
 
3189
    }
 
3190
 
 
3191
  free (data);
 
3192
  return SANE_STATUS_GOOD;
 
3193
}
 
3194
 
 
3195
/* 
 
3196
 * sets up register for coarse gain calibration
 
3197
 * todo: check it for scanners using it */
 
3198
static SANE_Status
 
3199
gl847_init_regs_for_coarse_calibration (Genesys_Device * dev)
 
3200
{
 
3201
  SANE_Status status;
 
3202
  uint8_t channels;
 
3203
  uint8_t cksel;
 
3204
 
 
3205
  DBG (DBG_proc, "gl847_init_regs_for_coarse_calibration\n");
 
3206
 
 
3207
 
 
3208
  cksel = (dev->calib_reg[reg_0x18].value & REG18_CKSEL) + 1;   /* clock speed = 1..4 clocks */
 
3209
 
 
3210
  /* set line size */
 
3211
  if (dev->settings.scan_mode == SCAN_MODE_COLOR)       /* single pass color */
 
3212
    channels = 3;
 
3213
  else
 
3214
    channels = 1;
 
3215
 
 
3216
  status = gl847_init_scan_regs (dev,
 
3217
                                 dev->calib_reg,
 
3218
                                 dev->settings.xres,
 
3219
                                 dev->settings.yres,
 
3220
                                 0,
 
3221
                                 0,
 
3222
                                 dev->sensor.optical_res / cksel,
 
3223
                                 20,
 
3224
                                 16,
 
3225
                                 channels,
 
3226
                                 dev->settings.color_filter,
 
3227
                                 SCAN_FLAG_DISABLE_SHADING |
 
3228
                                 SCAN_FLAG_DISABLE_GAMMA |
 
3229
                                 SCAN_FLAG_SINGLE_LINE |
 
3230
                                 SCAN_FLAG_IGNORE_LINE_DISTANCE);
 
3231
  if (status != SANE_STATUS_GOOD)
 
3232
    {
 
3233
      DBG (DBG_error,
 
3234
           "gl847_init_register_for_coarse_calibration: Failed to setup scan: %s\n",
 
3235
           sane_strstatus (status));
 
3236
      return status;
 
3237
    }
 
3238
 
 
3239
  DBG (DBG_info,
 
3240
       "gl847_init_register_for_coarse_calibration: optical sensor res: %d dpi, actual res: %d\n",
 
3241
       dev->sensor.optical_res / cksel, dev->settings.xres);
 
3242
 
 
3243
  status =
 
3244
    gl847_bulk_write_register (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS);
 
3245
  if (status != SANE_STATUS_GOOD)
 
3246
    {
 
3247
      DBG (DBG_error,
 
3248
           "gl847_init_register_for_coarse_calibration: Failed to bulk write registers: %s\n",
 
3249
           sane_strstatus (status));
 
3250
      return status;
 
3251
    }
 
3252
 
 
3253
  DBGCOMPLETED;
 
3254
  return SANE_STATUS_GOOD;
 
3255
}
 
3256
 
 
3257
 
 
3258
/* init registers for shading calibration */
 
3259
static SANE_Status
 
3260
gl847_init_regs_for_shading (Genesys_Device * dev)
 
3261
{
 
3262
  SANE_Status status;
 
3263
 
 
3264
  DBG (DBG_proc, "gl847_init_regs_for_shading: lines = %d\n",
 
3265
       dev->model->shading_lines);
 
3266
 
 
3267
  dev->calib_channels = 3;
 
3268
 
 
3269
  /* initial calibration reg values */
 
3270
  memcpy (dev->calib_reg, dev->reg,
 
3271
          GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set));
 
3272
 
 
3273
  dev->calib_pixels = dev->sensor.sensor_pixels;
 
3274
 
 
3275
  status = gl847_init_scan_regs (dev,
 
3276
                                 dev->calib_reg,
 
3277
                                 dev->sensor.optical_res,
 
3278
                                 dev->motor.base_ydpi,
 
3279
                                 0,
 
3280
                                 0,
 
3281
                                 dev->calib_pixels,
 
3282
                                 dev->model->shading_lines,
 
3283
                                 16,
 
3284
                                 dev->calib_channels,
 
3285
                                 dev->settings.color_filter,
 
3286
                                 SCAN_FLAG_DISABLE_SHADING |
 
3287
                                 SCAN_FLAG_DISABLE_GAMMA |
 
3288
                                 SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE |
 
3289
                                 SCAN_FLAG_IGNORE_LINE_DISTANCE |
 
3290
                                 SCAN_FLAG_USE_OPTICAL_RES);
 
3291
 
 
3292
 
 
3293
  if (status != SANE_STATUS_GOOD)
 
3294
    {
 
3295
      DBG (DBG_error,
 
3296
           "gl847_init_registers_for_shading: Failed to setup scan: %s\n",
 
3297
           sane_strstatus (status));
 
3298
      return status;
 
3299
    }
 
3300
  
 
3301
  dev->scanhead_position_in_steps += dev->model->shading_lines;
 
3302
 
 
3303
  status =
 
3304
    gl847_bulk_write_register (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS);
 
3305
  if (status != SANE_STATUS_GOOD)
 
3306
    {
 
3307
      DBG (DBG_error,
 
3308
           "gl847_init_registers_for_shading: Failed to bulk write registers: %s\n",
 
3309
           sane_strstatus (status));
 
3310
      return status;
 
3311
    }
 
3312
 
 
3313
  DBGCOMPLETED;
 
3314
  return SANE_STATUS_GOOD;
 
3315
}
 
3316
 
 
3317
/** @brief set up registers for the actual scan
 
3318
 */
 
3319
static SANE_Status
 
3320
gl847_init_regs_for_scan (Genesys_Device * dev)
 
3321
{
 
3322
  int channels;
 
3323
  int flags;
 
3324
  int depth;
 
3325
  float move;
 
3326
  int move_dpi;
 
3327
  float start;
 
3328
  uint8_t val;
 
3329
 
 
3330
  SANE_Status status;
 
3331
 
 
3332
  DBG (DBG_info,
 
3333
       "gl847_init_regs_for_scan settings:\nResolution: %uDPI\n"
 
3334
       "Lines     : %u\nPPL       : %u\nStartpos  : %.3f/%.3f\nScan mode : %d\n\n",
 
3335
       dev->settings.yres, dev->settings.lines, dev->settings.pixels,
 
3336
       dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode);
 
3337
 
 
3338
  gl847_slow_back_home (dev, 1);
 
3339
 
 
3340
 /* channels */
 
3341
  if (dev->settings.scan_mode == SCAN_MODE_COLOR)       /* single pass color */
 
3342
    channels = 3;
 
3343
  else
 
3344
    channels = 1;
 
3345
 
 
3346
  /* depth */
 
3347
  depth = dev->settings.depth;
 
3348
  if (dev->settings.scan_mode == SCAN_MODE_LINEART)
 
3349
    depth = 1;
 
3350
 
 
3351
 
 
3352
  /* steps to move to reach scanning area:
 
3353
     - first we move to physical start of scanning
 
3354
     either by a fixed steps amount from the black strip
 
3355
     or by a fixed amount from parking position,
 
3356
     minus the steps done during shading calibration
 
3357
     - then we move by the needed offset whitin physical
 
3358
     scanning area
 
3359
 
 
3360
     assumption: steps are expressed at maximum motor resolution
 
3361
 
 
3362
     we need:   
 
3363
     SANE_Fixed y_offset;                       
 
3364
     SANE_Fixed y_size;                 
 
3365
     SANE_Fixed y_offset_calib;
 
3366
     mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */
 
3367
 
 
3368
  /* if scanner uses GENESYS_FLAG_SEARCH_START y_offset is
 
3369
     relative from origin, else, it is from parking position */
 
3370
 
 
3371
  move_dpi = dev->motor.base_ydpi;
 
3372
 
 
3373
  move = SANE_UNFIX (dev->model->y_offset);
 
3374
  move += dev->settings.tl_y;
 
3375
  move = (move * move_dpi) / MM_PER_INCH;
 
3376
  DBG (DBG_info, "gl847_init_regs_for_scan: move=%f steps\n", move);
 
3377
 
 
3378
  /* at high res we do fast move to scan area */
 
3379
  if(dev->settings.xres>150)
 
3380
    {
 
3381
      status = gl847_feed (dev, move);
 
3382
      if (status != SANE_STATUS_GOOD)
 
3383
        {
 
3384
          DBG (DBG_error, "%s: failed to move to scan area\n",__FUNCTION__);
 
3385
          return status;
 
3386
        }
 
3387
      move=0;
 
3388
    }
 
3389
 
 
3390
  /* clear scancnt and fedcnt */
 
3391
  val = REG0D_CLRLNCNT;
 
3392
  RIE (sanei_genesys_write_register (dev, REG0D, val));
 
3393
  val = REG0D_CLRMCNT;
 
3394
  RIE (sanei_genesys_write_register (dev, REG0D, val));
 
3395
 
 
3396
  /* start */
 
3397
  start = SANE_UNFIX (dev->model->x_offset);
 
3398
  start += dev->settings.tl_x;
 
3399
  start = (start * dev->sensor.optical_res) / MM_PER_INCH;
 
3400
 
 
3401
  flags = 0;
 
3402
 
 
3403
  /* emulated lineart from gray data is required for now */
 
3404
  flags |= SCAN_FLAG_DYNAMIC_LINEART;
 
3405
 
 
3406
  status = gl847_init_scan_regs (dev,
 
3407
                                 dev->reg,
 
3408
                                 dev->settings.xres,
 
3409
                                 dev->settings.yres,
 
3410
                                 start,
 
3411
                                 move,
 
3412
                                 dev->settings.pixels,
 
3413
                                 dev->settings.lines,
 
3414
                                 depth,
 
3415
                                 channels,
 
3416
                                 dev->settings.color_filter,
 
3417
                                 flags);
 
3418
 
 
3419
  if (status != SANE_STATUS_GOOD)
 
3420
    return status;
 
3421
 
 
3422
  DBGCOMPLETED;
 
3423
  return SANE_STATUS_GOOD;
 
3424
}
 
3425
 
 
3426
 
 
3427
/** @brief send gmma table to scanner
 
3428
 * This function sends generic gamma table (ie ones built with
 
3429
 * provided gamma) or the user defined one if provided by 
 
3430
 * fontend.
 
3431
 * @param dev device to write to
 
3432
 * @param generic flag for using generic gamma tables
 
3433
 */
 
3434
static SANE_Status
 
3435
gl847_send_gamma_table (Genesys_Device * dev, SANE_Bool generic)
 
3436
{
 
3437
  int size;
 
3438
  int status;
 
3439
  uint8_t *gamma, val;
 
3440
  int i, gmmval;
 
3441
 
 
3442
  DBG (DBG_proc, "gl847_send_gamma_table\n");
 
3443
 
 
3444
  /* don't send anything if no specific gamma table defined */
 
3445
  if (!generic
 
3446
      && (dev->sensor.red_gamma_table == NULL
 
3447
          || dev->sensor.green_gamma_table == NULL
 
3448
          || dev->sensor.blue_gamma_table == NULL))
 
3449
    {
 
3450
      DBG (DBG_proc, "gl847_send_gamma_table: nothing to send, skipping\n");
 
3451
      return SANE_STATUS_GOOD;
 
3452
    }
 
3453
 
 
3454
  size = 256;
 
3455
 
 
3456
  /* allocate temporary gamma tables: 16 bits words, 3 channels */
 
3457
  gamma = (uint8_t *) malloc (size * 2 * 3);
 
3458
  if (!gamma)
 
3459
    return SANE_STATUS_NO_MEM;
 
3460
 
 
3461
  /* take care off generic/specific data */
 
3462
  if (generic)
 
3463
    {
 
3464
      /* fill with default values */
 
3465
      for (i = 0; i < size; i++)
 
3466
        {
 
3467
          gmmval = i * 256;
 
3468
          gamma[i * 2 + size * 0 + 0] = gmmval & 0xff;
 
3469
          gamma[i * 2 + size * 0 + 1] = (gmmval >> 8) & 0xff;
 
3470
          gamma[i * 2 + size * 2 + 0] = gmmval & 0xff;
 
3471
          gamma[i * 2 + size * 2 + 1] = (gmmval >> 8) & 0xff;
 
3472
          gamma[i * 2 + size * 4 + 0] = gmmval & 0xff;
 
3473
          gamma[i * 2 + size * 4 + 1] = (gmmval >> 8) & 0xff;
 
3474
        }
 
3475
    }
 
3476
  else
 
3477
    {
 
3478
      /* copy sensor specific's gamma tables */
 
3479
      for (i = 0; i < size; i++)
 
3480
        {
 
3481
          gamma[i * 2 + size * 0 + 0] = dev->sensor.red_gamma_table[i] & 0xff;
 
3482
          gamma[i * 2 + size * 0 + 1] =
 
3483
            (dev->sensor.red_gamma_table[i] >> 8) & 0xff;
 
3484
          gamma[i * 2 + size * 2 + 0] =
 
3485
            dev->sensor.green_gamma_table[i] & 0xff;
 
3486
          gamma[i * 2 + size * 2 + 1] =
 
3487
            (dev->sensor.green_gamma_table[i] >> 8) & 0xff;
 
3488
          gamma[i * 2 + size * 4 + 0] =
 
3489
            dev->sensor.blue_gamma_table[i] & 0xff;
 
3490
          gamma[i * 2 + size * 4 + 1] =
 
3491
            (dev->sensor.blue_gamma_table[i] >> 8) & 0xff;
 
3492
        }
 
3493
    }
 
3494
 
 
3495
  /* loop sending gamma tables NOTE: 0x01000000 not 0x10000000 */
 
3496
  for (i = 0; i < 3; i++)
 
3497
    {
 
3498
      /* clear corresponding GMM_N bit */
 
3499
      RIE (sanei_genesys_read_register (dev, 0xbd, &val));
 
3500
      val &= ~(0x01 << i);
 
3501
      RIE (sanei_genesys_write_register (dev, 0xbd, val));
 
3502
 
 
3503
      /* clear corresponding GMM_F bit */
 
3504
      RIE (sanei_genesys_read_register (dev, 0xbe, &val));
 
3505
      val &= ~(0x01 << i);
 
3506
      RIE (sanei_genesys_write_register (dev, 0xbe, val));
 
3507
 
 
3508
      /* set GMM_Z */
 
3509
      RIE (sanei_genesys_write_register (dev, 0xc5+2*i, 0x00));
 
3510
      RIE (sanei_genesys_write_register (dev, 0xc6+2*i, 0x00));
 
3511
 
 
3512
      status =
 
3513
        sanei_genesys_write_ahb (dev->dn, 0x01000000 + 0x200 * i, size * 2,
 
3514
                   gamma + i * size * 2);
 
3515
      if (status != SANE_STATUS_GOOD)
 
3516
        {
 
3517
          DBG (DBG_error,
 
3518
               "gl847_send_gamma_table: write to AHB failed writing table %d (%s)\n",
 
3519
               i, sane_strstatus (status));
 
3520
        }
 
3521
    }
 
3522
 
 
3523
  free (gamma);
 
3524
  DBGCOMPLETED;
 
3525
  return status;
 
3526
}
 
3527
 
 
3528
/**
 
3529
 * Send shading calibration data. The buffer is considered to always hold values
 
3530
 * for all the channels.
 
3531
 */
 
3532
static SANE_Status
 
3533
gl847_send_shading_data (Genesys_Device * dev, uint8_t * data, int size)
 
3534
{
 
3535
  SANE_Status status = SANE_STATUS_GOOD;
 
3536
  uint32_t addr, length;
 
3537
  uint8_t val;
 
3538
 
 
3539
  DBGSTART;
 
3540
  DBG( DBG_io2, "%s: writing %d bytes of shading data\n",__FUNCTION__,size);
 
3541
 
 
3542
  /* shading data is plit in 3 (up to 5 with IR) areas 
 
3543
     write(0x10014000,0x00000dd8)
 
3544
     URB 23429  bulk_out len  3544  wrote 0x33 0x10 0x....
 
3545
     write(0x1003e000,0x00000dd8)
 
3546
     write(0x10068000,0x00000dd8)
 
3547
   */
 
3548
  length = (uint32_t) (size / 3);
 
3549
  DBG( DBG_io2, "%s: using chunks of %d (0x%04x) bytes\n",__FUNCTION__,length,length);
 
3550
 
 
3551
  /* base addr of data has been written in reg D0-D4 in 4K word, so AHB address
 
3552
   * is 8192*reg value */
 
3553
 
 
3554
  /* write actual red data */
 
3555
  RIE (sanei_genesys_read_register (dev, 0xd0, &val));
 
3556
  addr = val * 8192 + 0x10000000;
 
3557
  status = sanei_genesys_write_ahb (dev->dn, addr, length, data);
 
3558
  if (status != SANE_STATUS_GOOD)
 
3559
    {
 
3560
      DBG (DBG_error, "gl847_send_shading_data; write to AHB failed (%s)\n",
 
3561
           sane_strstatus (status));
 
3562
      return status;
 
3563
    }
 
3564
 
 
3565
  /* write actual green data */
 
3566
  RIE (sanei_genesys_read_register (dev, 0xd1, &val));
 
3567
  addr = val * 8192 + 0x10000000;
 
3568
  status = sanei_genesys_write_ahb (dev->dn, addr, length, data + length);
 
3569
  if (status != SANE_STATUS_GOOD)
 
3570
    {
 
3571
      DBG (DBG_error, "gl847_send_shading_data; write to AHB failed (%s)\n",
 
3572
           sane_strstatus (status));
 
3573
      return status;
 
3574
    }
 
3575
 
 
3576
  /* write actual blue data */
 
3577
  RIE (sanei_genesys_read_register (dev, 0xd2, &val));
 
3578
  addr = val * 8192 + 0x10000000;
 
3579
  status = sanei_genesys_write_ahb (dev->dn, addr, length, data + 2 * length);
 
3580
  if (status != SANE_STATUS_GOOD)
 
3581
    {
 
3582
      DBG (DBG_error, "gl847_send_shading_data; write to AHB failed (%s)\n",
 
3583
           sane_strstatus (status));
 
3584
      return status;
 
3585
    }
 
3586
 
 
3587
  DBGCOMPLETED;
 
3588
 
 
3589
  return status;
 
3590
}
 
3591
 
 
3592
/* this function does the led calibration by scanning one line of the calibration
 
3593
   area below scanner's top on white strip.
 
3594
 
 
3595
-needs working coarse/gain
 
3596
*/
 
3597
static SANE_Status
 
3598
gl847_led_calibration (Genesys_Device * dev)
 
3599
{
 
3600
  int num_pixels;
 
3601
  int total_size;
 
3602
  int used_res;
 
3603
  uint8_t *line;
 
3604
  int i, j;
 
3605
  SANE_Status status = SANE_STATUS_GOOD;
 
3606
  int val;
 
3607
  int channels, depth;
 
3608
  int avg[3], avga, avge;
 
3609
  int turn;
 
3610
  char fn[20];
 
3611
  uint16_t expr, expg, expb;
 
3612
  Genesys_Register_Set *r;
 
3613
 
 
3614
  SANE_Bool acceptable = SANE_FALSE;
 
3615
 
 
3616
  DBG (DBG_proc, "gl847_led_calibration\n");
 
3617
 
 
3618
  /* offset calibration is always done in color mode */
 
3619
  channels = 3;
 
3620
  depth=16;
 
3621
  used_res = dev->sensor.optical_res;
 
3622
  num_pixels = (dev->sensor.sensor_pixels*used_res)/dev->sensor.optical_res;
 
3623
  
 
3624
  /* initial calibration reg values */
 
3625
  memcpy (dev->calib_reg, dev->reg,
 
3626
          GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set));
 
3627
 
 
3628
  status = gl847_init_scan_regs (dev,
 
3629
                                 dev->calib_reg,
 
3630
                                 used_res,
 
3631
                                 dev->motor.base_ydpi,
 
3632
                                 0,
 
3633
                                 0,
 
3634
                                 num_pixels,
 
3635
                                 1,
 
3636
                                 depth,
 
3637
                                 channels,
 
3638
                                 dev->settings.color_filter,
 
3639
                                 SCAN_FLAG_DISABLE_SHADING |
 
3640
                                 SCAN_FLAG_DISABLE_GAMMA |
 
3641
                                 SCAN_FLAG_SINGLE_LINE |
 
3642
                                 SCAN_FLAG_IGNORE_LINE_DISTANCE |
 
3643
                                 SCAN_FLAG_USE_OPTICAL_RES);
 
3644
 
 
3645
  if (status != SANE_STATUS_GOOD)
 
3646
    {
 
3647
      DBG (DBG_error,
 
3648
           "gl847_led_calibration: failed to setup scan: %s\n",
 
3649
           sane_strstatus (status));
 
3650
      return status;
 
3651
    }
 
3652
 
 
3653
  RIE (gl847_bulk_write_register
 
3654
       (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS));
 
3655
 
 
3656
 
 
3657
  total_size = num_pixels * channels * (depth/8) * 1;   /* colors * bytes_per_color * scan lines */
 
3658
 
 
3659
  line = malloc (total_size);
 
3660
  if (!line)
 
3661
    return SANE_STATUS_NO_MEM;
 
3662
 
 
3663
/* 
 
3664
   we try to get equal bright leds here:
 
3665
 
 
3666
   loop:
 
3667
     average per color
 
3668
     adjust exposure times
 
3669
 */
 
3670
 
 
3671
  expr = (dev->sensor.regs_0x10_0x1d[0] << 8) | dev->sensor.regs_0x10_0x1d[1];
 
3672
  expg = (dev->sensor.regs_0x10_0x1d[2] << 8) | dev->sensor.regs_0x10_0x1d[3];
 
3673
  expb = (dev->sensor.regs_0x10_0x1d[4] << 8) | dev->sensor.regs_0x10_0x1d[5];
 
3674
 
 
3675
  turn = 0;
 
3676
 
 
3677
  do
 
3678
    {
 
3679
 
 
3680
      dev->sensor.regs_0x10_0x1d[0] = (expr >> 8) & 0xff;
 
3681
      dev->sensor.regs_0x10_0x1d[1] = expr & 0xff;
 
3682
      dev->sensor.regs_0x10_0x1d[2] = (expg >> 8) & 0xff;
 
3683
      dev->sensor.regs_0x10_0x1d[3] = expg & 0xff;
 
3684
      dev->sensor.regs_0x10_0x1d[4] = (expb >> 8) & 0xff;
 
3685
      dev->sensor.regs_0x10_0x1d[5] = expb & 0xff;
 
3686
 
 
3687
      for (i = 0; i < 6; i++)
 
3688
        {
 
3689
          r = sanei_genesys_get_address (dev->calib_reg, 0x10+i);
 
3690
          r->value = dev->sensor.regs_0x10_0x1d[i];
 
3691
        }
 
3692
 
 
3693
      RIE (gl847_bulk_write_register
 
3694
           (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS));
 
3695
 
 
3696
      DBG (DBG_info, "gl847_led_calibration: starting first line reading\n");
 
3697
      RIE (gl847_begin_scan (dev, dev->calib_reg, SANE_TRUE));
 
3698
      RIE (sanei_genesys_read_data_from_scanner (dev, line, total_size));
 
3699
 
 
3700
      if (DBG_LEVEL >= DBG_data)
 
3701
        {
 
3702
          snprintf (fn, 20, "led_%02d.pnm", turn);
 
3703
          sanei_genesys_write_pnm_file (fn,
 
3704
                                        line, depth, channels, num_pixels, 1);
 
3705
        }
 
3706
 
 
3707
      acceptable = SANE_TRUE;
 
3708
 
 
3709
      for (j = 0; j < channels; j++)
 
3710
        {
 
3711
          avg[j] = 0;
 
3712
          for (i = 0; i < num_pixels; i++)
 
3713
            {
 
3714
              if (dev->model->is_cis)
 
3715
                val =
 
3716
                  line[i * 2 + j * 2 * num_pixels + 1] * 256 +
 
3717
                  line[i * 2 + j * 2 * num_pixels];
 
3718
              else
 
3719
                val =
 
3720
                  line[i * 2 * channels + 2 * j + 1] * 256 +
 
3721
                  line[i * 2 * channels + 2 * j];
 
3722
              avg[j] += val;
 
3723
            }
 
3724
 
 
3725
          avg[j] /= num_pixels;
 
3726
        }
 
3727
 
 
3728
      DBG (DBG_info, "gl847_led_calibration: average: "
 
3729
           "%d,%d,%d\n", avg[0], avg[1], avg[2]);
 
3730
 
 
3731
      acceptable = SANE_TRUE;
 
3732
 
 
3733
      if (avg[0] < avg[1] * 0.95 || avg[1] < avg[0] * 0.95 ||
 
3734
          avg[0] < avg[2] * 0.95 || avg[2] < avg[0] * 0.95 ||
 
3735
          avg[1] < avg[2] * 0.95 || avg[2] < avg[1] * 0.95)
 
3736
        acceptable = SANE_FALSE;
 
3737
 
 
3738
      if (!acceptable)
 
3739
        {
 
3740
          avga = (avg[0] + avg[1] + avg[2]) / 3;
 
3741
          expr = (expr * avga) / avg[0];
 
3742
          expg = (expg * avga) / avg[1];
 
3743
          expb = (expb * avga) / avg[2];
 
3744
/*
 
3745
  keep the resulting exposures below this value.
 
3746
  too long exposure drives the ccd into saturation.
 
3747
  we may fix this by relying on the fact that 
 
3748
  we get a striped scan without shading, by means of
 
3749
  statistical calculation 
 
3750
*/
 
3751
          avge = (expr + expg + expb) / 3;
 
3752
 
 
3753
          /* don't overflow max exposure */
 
3754
          if (avge > 3000)
 
3755
            {
 
3756
              expr = (expr * 2000) / avge;
 
3757
              expg = (expg * 2000) / avge;
 
3758
              expb = (expb * 2000) / avge;
 
3759
            }
 
3760
          if (avge < 50)
 
3761
            {
 
3762
              expr = (expr * 50) / avge;
 
3763
              expg = (expg * 50) / avge;
 
3764
              expb = (expb * 50) / avge;
 
3765
            }
 
3766
 
 
3767
        }
 
3768
 
 
3769
      RIE (gl847_stop_action (dev));
 
3770
 
 
3771
      turn++;
 
3772
 
 
3773
    }
 
3774
  while (!acceptable && turn < 100);
 
3775
 
 
3776
  DBG (DBG_info, "gl847_led_calibration: acceptable exposure: %d,%d,%d\n",
 
3777
       expr, expg, expb);
 
3778
 
 
3779
  /* cleanup before return */
 
3780
  free (line);
 
3781
 
 
3782
  gl847_slow_back_home (dev, SANE_TRUE);
 
3783
 
 
3784
  DBGCOMPLETED;
 
3785
  return status;
 
3786
}
 
3787
 
 
3788
/* this function does the offset calibration by scanning one line of the calibration
 
3789
   area below scanner's top. There is a black margin and the remaining is white.
 
3790
   sanei_genesys_search_start() must have been called so that the offsets and margins
 
3791
   are allready known.
 
3792
 
 
3793
this function expects the slider to be where?
 
3794
*/
 
3795
static SANE_Status
 
3796
gl847_offset_calibration (Genesys_Device * dev)
 
3797
{
 
3798
  DBG (DBG_proc, "%s: not implemented \n", __FUNCTION__);
 
3799
  return SANE_STATUS_GOOD;
 
3800
}
 
3801
 
 
3802
 
 
3803
/* alternative coarse gain calibration 
 
3804
   this on uses the settings from offset_calibration and
 
3805
   uses only one scanline
 
3806
 */
 
3807
/*
 
3808
  with offset and coarse calibration we only want to get our input range into
 
3809
  a reasonable shape. the fine calibration of the upper and lower bounds will 
 
3810
  be done with shading.
 
3811
 */
 
3812
static SANE_Status
 
3813
gl847_coarse_gain_calibration (Genesys_Device * dev, int dpi)
 
3814
{
 
3815
  DBG (DBG_proc, "%s: not implemented \n", __FUNCTION__);
 
3816
  return SANE_STATUS_GOOD;
 
3817
}
 
3818
 
 
3819
/*
 
3820
 * wait for lamp warmup by scanning the same line until difference
 
3821
 * between 2 scans is below a threshold
 
3822
 */
 
3823
static SANE_Status
 
3824
gl847_init_regs_for_warmup (Genesys_Device * dev,
 
3825
                            Genesys_Register_Set * local_reg,
 
3826
                            int *channels, int *total_size)
 
3827
{
 
3828
  DBG (DBG_proc, "%s: not implemented \n", __FUNCTION__);
 
3829
  return SANE_STATUS_GOOD;
 
3830
}
 
3831
 
 
3832
static SANE_Status
 
3833
gl847_is_compatible_calibration (Genesys_Device * dev,
 
3834
                                 Genesys_Calibration_Cache * cache,
 
3835
                                 int for_overwrite)
 
3836
{
 
3837
#ifdef HAVE_SYS_TIME_H
 
3838
  struct timeval time;
 
3839
#endif
 
3840
  SANE_Status status;
 
3841
 
 
3842
  DBG (DBG_proc, "gl847_is_compatible_calibration\n");
 
3843
 
 
3844
  status = gl847_calculate_current_setup (dev);
 
3845
 
 
3846
  if (status != SANE_STATUS_GOOD)
 
3847
    {
 
3848
      DBG (DBG_error,
 
3849
           "gl847_is_compatible_calibration: failed to calculate current setup: %s\n",
 
3850
           sane_strstatus (status));
 
3851
      return status;
 
3852
    }
 
3853
 
 
3854
  DBG (DBG_proc, "gl847_is_compatible_calibration: checking\n");
 
3855
 
 
3856
  if (dev->current_setup.half_ccd != cache->used_setup.half_ccd)
 
3857
    return SANE_STATUS_UNSUPPORTED;
 
3858
 
 
3859
  /* a cache entry expires after 60 minutes for non sheetfed scanners */
 
3860
#ifdef HAVE_SYS_TIME_H
 
3861
  gettimeofday (&time, NULL);
 
3862
  if ((time.tv_sec - cache->last_calibration > 60 * 60)
 
3863
      && (dev->model->is_sheetfed == SANE_FALSE)
 
3864
      && (dev->settings.scan_method == SCAN_METHOD_FLATBED))
 
3865
    {
 
3866
      DBG (DBG_proc,
 
3867
           "gl847_is_compatible_calibration: expired entry, non compatible cache\n");
 
3868
      return SANE_STATUS_UNSUPPORTED;
 
3869
    }
 
3870
#endif
 
3871
 
 
3872
  DBGCOMPLETED;
 
3873
  return SANE_STATUS_GOOD;
 
3874
}
 
3875
 
 
3876
/** 
 
3877
 * set up GPIO/GPOE for idle state
 
3878
 */
 
3879
static SANE_Status
 
3880
gl847_init_gpio (Genesys_Device * dev)
 
3881
{
 
3882
  SANE_Status status = SANE_STATUS_GOOD;
 
3883
  uint8_t val, effective;
 
3884
 
 
3885
  DBG (DBG_proc, "gl847_init_gpio: start\n");
 
3886
 
 
3887
  RIE (sanei_genesys_write_register (dev, 0x6e, dev->gpo.enable[0]));
 
3888
  RIE (sanei_genesys_write_register (dev, 0x6f, dev->gpo.enable[1]));
 
3889
  RIE (sanei_genesys_write_register (dev, 0xa7, 0x04));
 
3890
  RIE (sanei_genesys_write_register (dev, 0xa8, 0x00));
 
3891
  RIE (sanei_genesys_write_register (dev, 0xa9, 0x00));
 
3892
 
 
3893
  /* toggle needed bits one after all */
 
3894
  /* TODO define a function for bit toggling */
 
3895
  RIE (sanei_genesys_read_register (dev, REG6C, &effective));
 
3896
  val = effective | 0x80;
 
3897
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
3898
  RIE (sanei_genesys_read_register (dev, REG6C, &effective));
 
3899
  if (effective != val)
 
3900
    {
 
3901
      DBG (DBG_warn,
 
3902
           "gl847_init_gpio: effective!=needed (0x%02x!=0x%02x) \n",
 
3903
           effective, val);
 
3904
    }
 
3905
 
 
3906
  val = effective | 0x40;
 
3907
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
3908
  RIE (sanei_genesys_read_register (dev, REG6C, &effective));
 
3909
  if (effective != val)
 
3910
    {
 
3911
      DBG (DBG_warn,
 
3912
           "gl847_init_gpio: effective!=needed (0x%02x!=0x%02x) \n",
 
3913
           effective, val);
 
3914
    }
 
3915
 
 
3916
  val = effective | 0x20;
 
3917
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
3918
 
 
3919
  /* seems useless : memory or clock related ? */
 
3920
  RIE (sanei_genesys_read_register (dev, REG0B, &effective));
 
3921
  RIE (sanei_genesys_write_register (dev, REG0B, effective));
 
3922
 
 
3923
  RIE (sanei_genesys_read_register (dev, REG6C, &effective));
 
3924
  if (effective != val)
 
3925
    {
 
3926
      DBG (DBG_warn,
 
3927
           "gl847_init_gpio: effective!=needed (0x%02x!=0x%02x) \n",
 
3928
           effective, val);
 
3929
    }
 
3930
 
 
3931
  /* not done yet for LiDE 100
 
3932
     val = effective | 0x08;
 
3933
     RIE (sanei_genesys_write_register (dev, REG6C, val));
 
3934
     RIE (sanei_genesys_read_register (dev, REG6C, &effective));
 
3935
     if (effective != val)
 
3936
     {
 
3937
     DBG (DBG_warn, "gl847_init_gpio: effective!=needed (0x%02x!=0x%02x) \n",
 
3938
     effective, val);
 
3939
     } */
 
3940
 
 
3941
  val = effective | 0x02;
 
3942
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
3943
  RIE (sanei_genesys_read_register (dev, REG6C, &effective));
 
3944
  if (effective != val)
 
3945
    {
 
3946
      DBG (DBG_warn,
 
3947
           "gl847_init_gpio: effective!=needed (0x%02x!=0x%02x) \n",
 
3948
           effective, val);
 
3949
    }
 
3950
 
 
3951
  val = effective | 0x01;
 
3952
  RIE (sanei_genesys_write_register (dev, REG6C, val));
 
3953
  RIE (sanei_genesys_read_register (dev, REG6C, &effective));
 
3954
  if (effective != val)
 
3955
    {
 
3956
      DBG (DBG_warn,
 
3957
           "gl847_init_gpio: effective!=needed (0x%02x!=0x%02x) \n",
 
3958
           effective, val);
 
3959
    }
 
3960
 
 
3961
  DBGCOMPLETED;
 
3962
  return status;
 
3963
}
 
3964
 
 
3965
/** 
 
3966
 * set memory layout by filling values in dedicated registers
 
3967
 */
 
3968
static SANE_Status
 
3969
gl847_init_memory_layout (Genesys_Device * dev)
 
3970
{
 
3971
  SANE_Status status = SANE_STATUS_GOOD;
 
3972
  int idx = 0;
 
3973
 
 
3974
  DBG (DBG_proc, "gl847_init_memory_layout\n");
 
3975
 
 
3976
  /* point to per model memory layout */
 
3977
  idx = 0;
 
3978
  if (strcmp (dev->model->name, "canon-lide-100") == 0)
 
3979
    {
 
3980
      idx = 0;
 
3981
    }
 
3982
  if (strcmp (dev->model->name, "canon-lide-200") == 0)
 
3983
    {
 
3984
      idx = 1;
 
3985
    }
 
3986
  if (strcmp (dev->model->name, "canon-5600f") == 0)
 
3987
    {
 
3988
      idx = 2;
 
3989
    }
 
3990
  if (strcmp (dev->model->name, "canon-lide-700f") == 0)
 
3991
    {
 
3992
      idx = 3;
 
3993
    }
 
3994
 
 
3995
  /* setup base address for shading data. */
 
3996
  /* values must be multiplied by 8192=0x4000 to give address on AHB */
 
3997
  /* R-Channel shading bank0 address setting for CIS */
 
3998
  sanei_genesys_write_register (dev, 0xd0, layouts[idx].rd0);
 
3999
  /* G-Channel shading bank0 address setting for CIS */
 
4000
  sanei_genesys_write_register (dev, 0xd1, layouts[idx].rd1);
 
4001
  /* B-Channel shading bank0 address setting for CIS */
 
4002
  sanei_genesys_write_register (dev, 0xd2, layouts[idx].rd2);
 
4003
 
 
4004
  /* setup base address for scanned data. */
 
4005
  /* values must be multiplied by 1024*2=0x0800 to give address on AHB */
 
4006
  /* R-Channel ODD image buffer 0x0124->0x92000 */
 
4007
  /* size for each buffer is 0x16d*1k word */
 
4008
  sanei_genesys_write_register (dev, 0xe0, layouts[idx].re0);
 
4009
  sanei_genesys_write_register (dev, 0xe1, layouts[idx].re1);
 
4010
/* R-Channel ODD image buffer end-address 0x0291->0x148800 => size=0xB6800*/
 
4011
  sanei_genesys_write_register (dev, 0xe2, layouts[idx].re2);
 
4012
  sanei_genesys_write_register (dev, 0xe3, layouts[idx].re3);
 
4013
 
 
4014
  /* R-Channel EVEN image buffer 0x0292 */
 
4015
  sanei_genesys_write_register (dev, 0xe4, layouts[idx].re4);
 
4016
  sanei_genesys_write_register (dev, 0xe5, layouts[idx].re5);
 
4017
/* R-Channel EVEN image buffer end-address 0x03ff*/
 
4018
  sanei_genesys_write_register (dev, 0xe6, layouts[idx].re6);
 
4019
  sanei_genesys_write_register (dev, 0xe7, layouts[idx].re7);
 
4020
 
 
4021
/* same for green, since CIS, same addresses */
 
4022
  sanei_genesys_write_register (dev, 0xe8, layouts[idx].re0);
 
4023
  sanei_genesys_write_register (dev, 0xe9, layouts[idx].re1);
 
4024
  sanei_genesys_write_register (dev, 0xea, layouts[idx].re2);
 
4025
  sanei_genesys_write_register (dev, 0xeb, layouts[idx].re3);
 
4026
  sanei_genesys_write_register (dev, 0xec, layouts[idx].re4);
 
4027
  sanei_genesys_write_register (dev, 0xed, layouts[idx].re5);
 
4028
  sanei_genesys_write_register (dev, 0xee, layouts[idx].re6);
 
4029
  sanei_genesys_write_register (dev, 0xef, layouts[idx].re7);
 
4030
 
 
4031
/* same for blue, since CIS, same addresses */
 
4032
  sanei_genesys_write_register (dev, 0xf0, layouts[idx].re0);
 
4033
  sanei_genesys_write_register (dev, 0xf1, layouts[idx].re1);
 
4034
  sanei_genesys_write_register (dev, 0xf2, layouts[idx].re2);
 
4035
  sanei_genesys_write_register (dev, 0xf3, layouts[idx].re3);
 
4036
  sanei_genesys_write_register (dev, 0xf4, layouts[idx].re4);
 
4037
  sanei_genesys_write_register (dev, 0xf5, layouts[idx].re5);
 
4038
  sanei_genesys_write_register (dev, 0xf6, layouts[idx].re6);
 
4039
  sanei_genesys_write_register (dev, 0xf7, layouts[idx].re7);
 
4040
 
 
4041
  DBGCOMPLETED;
 
4042
  return status;
 
4043
}
 
4044
 
 
4045
/* *
 
4046
 * initialize ASIC from power on condition
 
4047
 */
 
4048
static SANE_Status
 
4049
gl847_cold_boot (Genesys_Device * dev)
 
4050
{
 
4051
  SANE_Status status;
 
4052
  uint8_t val;
 
4053
 
 
4054
  DBGSTART;
 
4055
 
 
4056
  RIE (sanei_genesys_write_register (dev, 0x0e, 0x01));
 
4057
  RIE (sanei_genesys_write_register (dev, 0x0e, 0x00));
 
4058
 
 
4059
  /* test CHKVER */
 
4060
  RIE (sanei_genesys_read_register (dev, REG40, &val));
 
4061
  if (val & REG40_CHKVER)
 
4062
    {
 
4063
      RIE (sanei_genesys_read_register (dev, 0x00, &val));
 
4064
      DBG (DBG_info, "gl847_cold_boot: reported version for genesys chip is 0x%02x\n", val);
 
4065
    }
 
4066
 
 
4067
  /* setup GPIO */
 
4068
  sanei_genesys_read_register (dev, REGA6, &val);
 
4069
  sanei_genesys_write_register (dev, REGA6, val | 0x04);
 
4070
  sanei_genesys_write_register (dev, REGA7, 0x0f);
 
4071
  sanei_genesys_write_register (dev, REGA9, 0x00);
 
4072
 
 
4073
  /* Set default values for registers */
 
4074
  gl847_init_registers (dev);
 
4075
 
 
4076
  RIE (sanei_genesys_write_register (dev, REG6B, 0x02));
 
4077
  RIE (sanei_genesys_write_register (dev, REG6C, 0x00));
 
4078
  RIE (sanei_genesys_write_register (dev, REG6D, 0x20));
 
4079
  RIE (sanei_genesys_write_register (dev, REG6E, 0x7e));
 
4080
  RIE (sanei_genesys_write_register (dev, REG6F, 0x21));
 
4081
 
 
4082
  /* Write initial registers */
 
4083
  RIE (gl847_bulk_write_register (dev, dev->reg, GENESYS_GL847_MAX_REGS));
 
4084
 
 
4085
  /* Enable DRAM by setting a rising edge on bit 3 of reg 0x0b */
 
4086
  val = dev->reg[reg_0x0b].value & REG0B_DRAMSEL;
 
4087
  val = (val | REG0B_ENBDRAM);
 
4088
  RIE (sanei_genesys_write_register (dev, REG0B, val));
 
4089
  dev->reg[reg_0x0b].value = val;
 
4090
 
 
4091
  /* read back GPIO TODO usefull ? */
 
4092
  sanei_genesys_read_register (dev, REGA6, &val);
 
4093
  if (val != 0x04)
 
4094
    {
 
4095
      DBG (DBG_warn, "gl847_cold_boot: GPIO is 0x%02d instead of 0x04\n", val);
 
4096
    }
 
4097
 
 
4098
  /* set up clock once for all */
 
4099
  RIE (sanei_genesys_write_register (dev, 0x77, 0x00));
 
4100
  RIE (sanei_genesys_write_register (dev, 0x78, 0x00));
 
4101
  RIE (sanei_genesys_write_register (dev, 0x79, 0x9f));
 
4102
 
 
4103
  /* CLKSET */
 
4104
  val = (dev->reg[reg_0x0b].value & ~REG0B_CLKSET) | REG0B_30MHZ;
 
4105
  RIE (sanei_genesys_write_register (dev, REG0B, val));
 
4106
  dev->reg[reg_0x0b].value = val;
 
4107
 
 
4108
  /* prevent further writings by bulk write register */
 
4109
  dev->reg[reg_0x0b].address = 0x00;
 
4110
 
 
4111
  /* CIS_LINE */
 
4112
  SETREG (0x08, REG08_CIS_LINE);
 
4113
  RIE (sanei_genesys_write_register (dev, 0x08, dev->reg[reg_0x08].value));
 
4114
 
 
4115
  /* set up end access */
 
4116
  RIE (sanei_genesys_write_0x8c (dev, 0x10, 0x0b));
 
4117
  RIE (sanei_genesys_write_0x8c (dev, 0x13, 0x0e));
 
4118
 
 
4119
  sanei_genesys_write_register (dev, REGA7, 0x04);
 
4120
  sanei_genesys_write_register (dev, REGA9, 0x00);
 
4121
 
 
4122
  /* setup gpio */
 
4123
  RIE (gl847_init_gpio (dev));
 
4124
 
 
4125
  /* setup internal memory layout */
 
4126
  RIE (gl847_init_memory_layout (dev));
 
4127
 
 
4128
  SETREG (0xf8, 0x01);
 
4129
  RIE (sanei_genesys_write_register (dev, 0xf8, dev->reg[reg_0xf8].value));
 
4130
 
 
4131
  DBGCOMPLETED;
 
4132
  return SANE_STATUS_GOOD;
 
4133
}
 
4134
 
 
4135
/** @brief dummy scan at 150 to warm scanner
 
4136
 *
 
4137
 * */
 
4138
static SANE_Status
 
4139
gl847_warm_scan (Genesys_Device * dev)
 
4140
{
 
4141
  SANE_Status status;
 
4142
  size_t size;
 
4143
  uint8_t *line;
 
4144
  float pixels;
 
4145
  int dpi = 300;
 
4146
 
 
4147
  DBGSTART;
 
4148
 
 
4149
  pixels = (dev->sensor.sensor_pixels * dpi) / dev->sensor.optical_res;
 
4150
  status = gl847_init_scan_regs (dev,
 
4151
                                 dev->reg,
 
4152
                                 dpi,
 
4153
                                 dpi,
 
4154
                                 0,
 
4155
                                 90,
 
4156
                                 pixels,
 
4157
                                 1,
 
4158
                                 16,
 
4159
                                 3,
 
4160
                                 0,
 
4161
                                 SCAN_FLAG_DISABLE_SHADING |
 
4162
                                 SCAN_FLAG_DISABLE_GAMMA |
 
4163
                                 SCAN_FLAG_IGNORE_LINE_DISTANCE |
 
4164
                                 SCAN_FLAG_USE_OPTICAL_RES);
 
4165
 
 
4166
  RIE (gl847_bulk_write_register
 
4167
       (dev, dev->reg, GENESYS_GL847_MAX_REGS));
 
4168
 
 
4169
  /* colors * bytes_per_color * scan lines */
 
4170
  size = ((int) pixels) * 3 * 2 * 1;
 
4171
 
 
4172
  line = malloc (size);
 
4173
  if (!line)
 
4174
    return SANE_STATUS_NO_MEM;
 
4175
 
 
4176
  DBG (DBG_info, "%s: starting dummy data reading\n", __FUNCTION__);
 
4177
 
 
4178
  RIE (gl847_begin_scan (dev, dev->reg, SANE_TRUE));
 
4179
  sanei_genesys_read_data_from_scanner (dev, line, size);
 
4180
  RIE (gl847_end_scan (dev, dev->reg, SANE_TRUE));
 
4181
 
 
4182
  free (line);
 
4183
  RIE (gl847_slow_back_home (dev, SANE_TRUE));
 
4184
 
 
4185
  DBGCOMPLETED;
 
4186
  return SANE_STATUS_GOOD;
 
4187
}
 
4188
 
 
4189
/* *
 
4190
 * initialize backend and ASIC : registers, motor tables, and gamma tables
 
4191
 * then ensure scanner's head is at home
 
4192
 */
 
4193
static SANE_Status
 
4194
gl847_init (Genesys_Device * dev)
 
4195
{
 
4196
  SANE_Status status;
 
4197
  uint8_t val;
 
4198
  SANE_Bool cold = SANE_TRUE;
 
4199
  int size;
 
4200
 
 
4201
  DBG_INIT ();
 
4202
  DBGSTART;
 
4203
  
 
4204
  status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_IN, REQUEST_REGISTER, VALUE_GET_REGISTER, 0, 1, &val);
 
4205
  if (status != SANE_STATUS_GOOD)
 
4206
    {
 
4207
      DBG (DBG_error,
 
4208
           "gl847_init: request register failed %s\n", sane_strstatus (status));
 
4209
      return status;
 
4210
    }
 
4211
  DBG( DBG_io2, "gl847_init: value=0x%02x\n",val);
 
4212
 
 
4213
  /* check if the device has already been initialized and powered up 
 
4214
   * we read register 6 and check PWRBIT, if reset scanner has been
 
4215
   * freshly powered up. This bit will be set to later so that following
 
4216
   * reads can detect power down/up cycle*/
 
4217
  RIE (sanei_genesys_read_register (dev, 0x06, &val));
 
4218
  if (val & REG06_PWRBIT)
 
4219
    {
 
4220
      cold = SANE_FALSE;
 
4221
    }
 
4222
  DBG (DBG_info, "%s: device is %s\n", __FUNCTION__, cold ? "cold" : "warm");
 
4223
 
 
4224
  /* don't do anything is backend is initialized and hardware hasn't been
 
4225
   * replug */
 
4226
  if (dev->already_initialized && !cold)
 
4227
    {
 
4228
      DBG (DBG_info, "gl847_init: already initialized, nothing to do\n");
 
4229
      return SANE_STATUS_GOOD;
 
4230
    }
 
4231
 
 
4232
  /* set up hardware and registers */
 
4233
  RIE (gl847_cold_boot (dev));
 
4234
 
 
4235
  /* now hardware part is OK, set up device struct */
 
4236
  FREE_IFNOT_NULL (dev->white_average_data);
 
4237
  FREE_IFNOT_NULL (dev->dark_average_data);
 
4238
  FREE_IFNOT_NULL (dev->sensor.red_gamma_table);
 
4239
  FREE_IFNOT_NULL (dev->sensor.green_gamma_table);
 
4240
  FREE_IFNOT_NULL (dev->sensor.blue_gamma_table);
 
4241
 
 
4242
  dev->settings.color_filter = 0;
 
4243
 
 
4244
  memcpy (dev->calib_reg, dev->reg,
 
4245
          GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set));
 
4246
 
 
4247
  /* Set analog frontend */
 
4248
  RIE (gl847_set_fe (dev, AFE_INIT));
 
4249
 
 
4250
  /* init gamma tables */
 
4251
  size = 256;
 
4252
  if (dev->sensor.red_gamma_table == NULL)
 
4253
    {
 
4254
      dev->sensor.red_gamma_table = (uint16_t *) malloc (2 * size);
 
4255
      if (dev->sensor.red_gamma_table == NULL)
 
4256
        {
 
4257
          DBG (DBG_error,
 
4258
               "gl847_init: could not allocate memory for gamma table\n");
 
4259
          return SANE_STATUS_NO_MEM;
 
4260
        }
 
4261
      sanei_genesys_create_gamma_table (dev->sensor.red_gamma_table, size,
 
4262
                                        65535, 65535, dev->sensor.red_gamma);
 
4263
    }
 
4264
  if (dev->sensor.green_gamma_table == NULL)
 
4265
    {
 
4266
      dev->sensor.green_gamma_table = (uint16_t *) malloc (2 * size);
 
4267
      if (dev->sensor.red_gamma_table == NULL)
 
4268
        {
 
4269
          DBG (DBG_error,
 
4270
               "gl847_init: could not allocate memory for gamma table\n");
 
4271
          return SANE_STATUS_NO_MEM;
 
4272
        }
 
4273
      sanei_genesys_create_gamma_table (dev->sensor.green_gamma_table, size,
 
4274
                                        65535, 65535,
 
4275
                                        dev->sensor.green_gamma);
 
4276
    }
 
4277
  if (dev->sensor.blue_gamma_table == NULL)
 
4278
    {
 
4279
      dev->sensor.blue_gamma_table = (uint16_t *) malloc (2 * size);
 
4280
      if (dev->sensor.red_gamma_table == NULL)
 
4281
        {
 
4282
          DBG (DBG_error,
 
4283
               "gl847_init: could not allocate memory for gamma table\n");
 
4284
          return SANE_STATUS_NO_MEM;
 
4285
        }
 
4286
      sanei_genesys_create_gamma_table (dev->sensor.blue_gamma_table, size,
 
4287
                                        65535, 65535, dev->sensor.blue_gamma);
 
4288
    }
 
4289
  
 
4290
  dev->oe_buffer.buffer=NULL;
 
4291
  dev->already_initialized = SANE_TRUE;
 
4292
 
 
4293
  /* Move home if needed */
 
4294
  RIE (gl847_slow_back_home (dev, SANE_TRUE));
 
4295
  RIE (gl847_warm_scan (dev));
 
4296
  dev->scanhead_position_in_steps = 0;
 
4297
 
 
4298
  /* Set powersaving (default = 15 minutes) */
 
4299
  RIE (gl847_set_powersaving (dev, 15));
 
4300
 
 
4301
  DBGCOMPLETED;
 
4302
  return status;
 
4303
}
 
4304
 
 
4305
static SANE_Status
 
4306
gl847_update_hardware_sensors (Genesys_Scanner * s)
 
4307
{
 
4308
  /* do what is needed to get a new set of events, but try to not lose
 
4309
     any of them.
 
4310
   */
 
4311
  SANE_Status status = SANE_STATUS_GOOD;
 
4312
  uint8_t val;
 
4313
 
 
4314
  RIE (sanei_genesys_read_register (s->dev, REG6D, &val));
 
4315
 
 
4316
  if (s->val[OPT_SCAN_SW].b == s->last_val[OPT_SCAN_SW].b)
 
4317
    s->val[OPT_SCAN_SW].b = (val & 0x01) == 0;
 
4318
  if (s->val[OPT_FILE_SW].b == s->last_val[OPT_FILE_SW].b)
 
4319
    s->val[OPT_FILE_SW].b = (val & 0x02) == 0;
 
4320
  if (s->val[OPT_EMAIL_SW].b == s->last_val[OPT_EMAIL_SW].b)
 
4321
    s->val[OPT_EMAIL_SW].b = (val & 0x04) == 0;
 
4322
  if (s->val[OPT_COPY_SW].b == s->last_val[OPT_COPY_SW].b)
 
4323
    s->val[OPT_COPY_SW].b = (val & 0x08) == 0;
 
4324
 
 
4325
  return status;
 
4326
}
 
4327
 
 
4328
/** @brief search for a full width black or white strip.
 
4329
 * This function searches for a black or white stripe across the scanning area.
 
4330
 * When searching backward, the searched area must completely be of the desired 
 
4331
 * color since this area will be used for calibration which scans forward.
 
4332
 * @param dev scanner device
 
4333
 * @param forward SANE_TRUE if searching forward, SANE_FALSE if searching backward
 
4334
 * @param black SANE_TRUE if searching for a black strip, SANE_FALSE for a white strip
 
4335
 * @return SANE_STATUS_GOOD if a matching strip is found, SANE_STATUS_UNSUPPORTED if not
 
4336
 */
 
4337
static SANE_Status
 
4338
gl847_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black)
 
4339
{
 
4340
  unsigned int pixels, lines, channels;
 
4341
  SANE_Status status;
 
4342
  Genesys_Register_Set local_reg[GENESYS_GL847_MAX_REGS];
 
4343
  size_t size;
 
4344
  uint8_t *data;
 
4345
  int steps, depth, dpi;
 
4346
  unsigned int pass, count, found, x, y;
 
4347
  char title[80];
 
4348
  Genesys_Register_Set *r;
 
4349
 
 
4350
  DBG (DBG_proc, "gl847_search_strip %s %s\n", black ? "black" : "white",
 
4351
       forward ? "forward" : "reverse");
 
4352
 
 
4353
  gl847_set_fe (dev, AFE_SET);
 
4354
  status = gl847_stop_action (dev);
 
4355
  if (status != SANE_STATUS_GOOD)
 
4356
    {
 
4357
      DBG (DBG_error,
 
4358
           "gl847_search_strip: failed to stop: %s\n",
 
4359
           sane_strstatus (status));
 
4360
      return status;
 
4361
    }
 
4362
 
 
4363
  /* set up for a gray scan at lowest dpi */
 
4364
  dpi = 9600;
 
4365
  for (x = 0; x < MAX_RESOLUTIONS; x++)
 
4366
    {
 
4367
      if (dev->model->xdpi_values[x] > 0 && dev->model->xdpi_values[x] < dpi)
 
4368
        dpi = dev->model->xdpi_values[x];
 
4369
    }
 
4370
  channels = 1;
 
4371
  /* 10 MM */
 
4372
  lines = (10 * dpi) / MM_PER_INCH;
 
4373
  /* shading calibation is done with dev->motor.base_ydpi */
 
4374
  lines = (dev->model->shading_lines * dpi) / dev->motor.base_ydpi;
 
4375
  depth = 8;
 
4376
  pixels = (dev->sensor.sensor_pixels * dpi) / dev->sensor.optical_res;
 
4377
  size = pixels * channels * lines * (depth / 8);
 
4378
  data = malloc (size);
 
4379
  if (!data)
 
4380
    {
 
4381
      DBG (DBG_error, "gl847_search_strip: failed to allocate memory\n");
 
4382
      return SANE_STATUS_NO_MEM;
 
4383
    }
 
4384
  dev->scanhead_position_in_steps = 0;
 
4385
 
 
4386
  memcpy (local_reg, dev->reg,
 
4387
          GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set));
 
4388
 
 
4389
  status = gl847_init_scan_regs (dev,
 
4390
                                 local_reg,
 
4391
                                 dpi,
 
4392
                                 dpi,
 
4393
                                 0,
 
4394
                                 0,
 
4395
                                 pixels,
 
4396
                                 lines,
 
4397
                                 depth,
 
4398
                                 channels,
 
4399
                                 0,
 
4400
                                 SCAN_FLAG_DISABLE_SHADING |
 
4401
                                 SCAN_FLAG_DISABLE_GAMMA);
 
4402
  if (status != SANE_STATUS_GOOD)
 
4403
    {
 
4404
      DBG (DBG_error,
 
4405
           "gl847_search_strip: failed to setup for scan: %s\n",
 
4406
           sane_strstatus (status));
 
4407
      return status;
 
4408
    }
 
4409
 
 
4410
  /* set up for reverse or forward */
 
4411
  r = sanei_genesys_get_address (local_reg, REG02);
 
4412
  if (forward)
 
4413
    r->value &= ~REG02_MTRREV;
 
4414
  else
 
4415
    r->value |= REG02_MTRREV;
 
4416
 
 
4417
 
 
4418
  status = gl847_bulk_write_register (dev, local_reg, GENESYS_GL847_MAX_REGS);
 
4419
  if (status != SANE_STATUS_GOOD)
 
4420
    {
 
4421
      DBG (DBG_error,
 
4422
           "gl847_search_strip: Failed to bulk write registers: %s\n",
 
4423
           sane_strstatus (status));
 
4424
      return status;
 
4425
    }
 
4426
 
 
4427
  status = gl847_begin_scan (dev, local_reg, SANE_TRUE);
 
4428
  if (status != SANE_STATUS_GOOD)
 
4429
    {
 
4430
      free (data);
 
4431
      DBG (DBG_error,
 
4432
           "gl847_search_strip: failed to begin scan: %s\n",
 
4433
           sane_strstatus (status));
 
4434
      return status;
 
4435
    }
 
4436
 
 
4437
  /* waits for valid data */
 
4438
  do
 
4439
    sanei_genesys_test_buffer_empty (dev, &steps);
 
4440
  while (steps);
 
4441
 
 
4442
  /* now we're on target, we can read data */
 
4443
  status = sanei_genesys_read_data_from_scanner (dev, data, size);
 
4444
  if (status != SANE_STATUS_GOOD)
 
4445
    {
 
4446
      free (data);
 
4447
      DBG (DBG_error,
 
4448
           "gl847_search_start_position: failed to read data: %s\n",
 
4449
           sane_strstatus (status));
 
4450
      return status;
 
4451
    }
 
4452
 
 
4453
  status = gl847_stop_action (dev);
 
4454
  if (status != SANE_STATUS_GOOD)
 
4455
    {
 
4456
      free (data);
 
4457
      DBG (DBG_error, "gl847_search_strip: gl847_stop_action failed\n");
 
4458
      return status;
 
4459
    }
 
4460
 
 
4461
  pass = 0;
 
4462
  if (DBG_LEVEL >= DBG_data)
 
4463
    {
 
4464
      sprintf (title, "search_strip_%s_%s%02d.pnm",
 
4465
               black ? "black" : "white", forward ? "fwd" : "bwd", pass);
 
4466
      sanei_genesys_write_pnm_file (title, data, depth, channels, pixels,
 
4467
                                    lines);
 
4468
    }
 
4469
 
 
4470
  /* loop until strip is found or maximum pass number done */
 
4471
  found = 0;
 
4472
  while (pass < 20 && !found)
 
4473
    {
 
4474
      status =
 
4475
        gl847_bulk_write_register (dev, local_reg, GENESYS_GL847_MAX_REGS);
 
4476
      if (status != SANE_STATUS_GOOD)
 
4477
        {
 
4478
          DBG (DBG_error,
 
4479
               "gl847_search_strip: Failed to bulk write registers: %s\n",
 
4480
               sane_strstatus (status));
 
4481
          return status;
 
4482
        }
 
4483
 
 
4484
      /* now start scan */
 
4485
      status = gl847_begin_scan (dev, local_reg, SANE_TRUE);
 
4486
      if (status != SANE_STATUS_GOOD)
 
4487
        {
 
4488
          free (data);
 
4489
          DBG (DBG_error,
 
4490
               "gl847_search_strip: failed to begin scan: %s\n",
 
4491
               sane_strstatus (status));
 
4492
          return status;
 
4493
        }
 
4494
 
 
4495
      /* waits for valid data */
 
4496
      do
 
4497
        sanei_genesys_test_buffer_empty (dev, &steps);
 
4498
      while (steps);
 
4499
 
 
4500
      /* now we're on target, we can read data */
 
4501
      status = sanei_genesys_read_data_from_scanner (dev, data, size);
 
4502
      if (status != SANE_STATUS_GOOD)
 
4503
        {
 
4504
          free (data);
 
4505
          DBG (DBG_error,
 
4506
               "gl847_search_start_position: failed to read data: %s\n",
 
4507
               sane_strstatus (status));
 
4508
          return status;
 
4509
        }
 
4510
 
 
4511
      status = gl847_stop_action (dev);
 
4512
      if (status != SANE_STATUS_GOOD)
 
4513
        {
 
4514
          free (data);
 
4515
          DBG (DBG_error, "gl847_search_strip: gl847_stop_action failed\n");
 
4516
          return status;
 
4517
        }
 
4518
 
 
4519
      if (DBG_LEVEL >= DBG_data)
 
4520
        {
 
4521
          sprintf (title, "search_strip_%s_%s%02d.pnm",
 
4522
                   black ? "black" : "white", forward ? "fwd" : "bwd", pass);
 
4523
          sanei_genesys_write_pnm_file (title, data, depth, channels,
 
4524
                                        pixels, lines);
 
4525
        }
 
4526
 
 
4527
      /* search data to find black strip */
 
4528
      /* when searching forward, we only need one line of the searched color since we
 
4529
       * will scan forward. But when doing backward search, we need all the area of the
 
4530
       * same color */
 
4531
      if (forward)
 
4532
        {
 
4533
          for (y = 0; y < lines && !found; y++)
 
4534
            {
 
4535
              count = 0;
 
4536
              /* count of white/black pixels depending on the color searched */
 
4537
              for (x = 0; x < pixels; x++)
 
4538
                {
 
4539
                  /* when searching for black, detect white pixels */
 
4540
                  if (black && data[y * pixels + x] > 90)
 
4541
                    {
 
4542
                      count++;
 
4543
                    }
 
4544
                  /* when searching for white, detect black pixels */
 
4545
                  if (!black && data[y * pixels + x] < 60)
 
4546
                    {
 
4547
                      count++;
 
4548
                    }
 
4549
                }
 
4550
 
 
4551
              /* at end of line, if count >= 3%, line is not fully of the desired color
 
4552
               * so we must go to next line of the buffer */
 
4553
              /* count*100/pixels < 3 */
 
4554
              if ((count * 100) / pixels < 3)
 
4555
                {
 
4556
                  found = 1;
 
4557
                  DBG (DBG_data,
 
4558
                       "gl847_search_strip: strip found forward during pass %d at line %d\n",
 
4559
                       pass, y);
 
4560
                }
 
4561
              else
 
4562
                {
 
4563
                  DBG (DBG_data,
 
4564
                       "gl847_search_strip: pixels=%d, count=%d (%d%%)\n",
 
4565
                       pixels, count, (100 * count) / pixels);
 
4566
                }
 
4567
            }
 
4568
        }
 
4569
      else                      /* since calibration scans are done forward, we need the whole area
 
4570
                                   to be of the required color when searching backward */
 
4571
        {
 
4572
          count = 0;
 
4573
          for (y = 0; y < lines; y++)
 
4574
            {
 
4575
              /* count of white/black pixels depending on the color searched */
 
4576
              for (x = 0; x < pixels; x++)
 
4577
                {
 
4578
                  /* when searching for black, detect white pixels */
 
4579
                  if (black && data[y * pixels + x] > 90)
 
4580
                    {
 
4581
                      count++;
 
4582
                    }
 
4583
                  /* when searching for white, detect black pixels */
 
4584
                  if (!black && data[y * pixels + x] < 60)
 
4585
                    {
 
4586
                      count++;
 
4587
                    }
 
4588
                }
 
4589
            }
 
4590
 
 
4591
          /* at end of area, if count >= 3%, area is not fully of the desired color
 
4592
           * so we must go to next buffer */
 
4593
          if ((count * 100) / (pixels * lines) < 3)
 
4594
            {
 
4595
              found = 1;
 
4596
              DBG (DBG_data,
 
4597
                   "gl847_search_strip: strip found backward during pass %d \n",
 
4598
                   pass);
 
4599
            }
 
4600
          else
 
4601
            {
 
4602
              DBG (DBG_data,
 
4603
                   "gl847_search_strip: pixels=%d, count=%d (%d%%)\n",
 
4604
                   pixels, count, (100 * count) / pixels);
 
4605
            }
 
4606
        }
 
4607
      pass++;
 
4608
    }
 
4609
  free (data);
 
4610
  if (found)
 
4611
    {
 
4612
      status = SANE_STATUS_GOOD;
 
4613
      DBG (DBG_info, "gl847_search_strip: %s strip found\n",
 
4614
           black ? "black" : "white");
 
4615
    }
 
4616
  else
 
4617
    {
 
4618
      status = SANE_STATUS_UNSUPPORTED;
 
4619
      DBG (DBG_info, "gl847_search_strip: %s strip not found\n",
 
4620
           black ? "black" : "white");
 
4621
    }
 
4622
 
 
4623
  DBGCOMPLETED;
 
4624
  return status;
 
4625
}
 
4626
 
 
4627
/** the gl847 command set */
 
4628
static Genesys_Command_Set gl847_cmd_set = {
 
4629
  "gl847-generic",              /* the name of this set */
 
4630
 
 
4631
  gl847_init,
 
4632
  gl847_init_regs_for_warmup,
 
4633
  gl847_init_regs_for_coarse_calibration,
 
4634
  gl847_init_regs_for_shading,
 
4635
  gl847_init_regs_for_scan,
 
4636
 
 
4637
  gl847_get_filter_bit,
 
4638
  gl847_get_lineart_bit,
 
4639
  gl847_get_bitset_bit,
 
4640
  gl847_get_gain4_bit,
 
4641
  gl847_get_fast_feed_bit,
 
4642
  gl847_test_buffer_empty_bit,
 
4643
  gl847_test_motor_flag_bit,
 
4644
 
 
4645
  gl847_bulk_full_size,
 
4646
 
 
4647
  gl847_set_fe,
 
4648
  gl847_set_powersaving,
 
4649
  gl847_save_power,
 
4650
 
 
4651
  gl847_set_motor_power,
 
4652
  gl847_set_lamp_power,
 
4653
 
 
4654
  gl847_begin_scan,
 
4655
  gl847_end_scan,
 
4656
 
 
4657
  gl847_send_gamma_table,
 
4658
 
 
4659
  gl847_search_start_position,
 
4660
 
 
4661
  gl847_offset_calibration,
 
4662
  gl847_coarse_gain_calibration,
 
4663
  gl847_led_calibration,
 
4664
 
 
4665
  gl847_slow_back_home,
 
4666
 
 
4667
  gl847_bulk_write_register,
 
4668
  NULL,
 
4669
  gl847_bulk_read_data,
 
4670
 
 
4671
  gl847_update_hardware_sensors,
 
4672
 
 
4673
  gl847_load_document,
 
4674
  gl847_detect_document_end,
 
4675
  gl847_eject_document,
 
4676
  gl847_search_strip,
 
4677
 
 
4678
  gl847_is_compatible_calibration,
 
4679
  NULL,
 
4680
  gl847_send_shading_data
 
4681
};
 
4682
 
 
4683
SANE_Status
 
4684
sanei_gl847_init_cmd_set (Genesys_Device * dev)
 
4685
{
 
4686
  dev->model->cmd_set = &gl847_cmd_set;
 
4687
  return SANE_STATUS_GOOD;
 
4688
}
 
4689
 
 
4690
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */