Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 18479
Collapse All | Expand All

(-)sane-backends-1.0.12/backend/Makefile.in (-3 / +6 lines)
Lines 62-68 Link Here
62
62
63
@SET_MAKE@
63
@SET_MAKE@
64
64
65
PRELOADABLE_BACKENDS = abaton agfafocus apple artec as6e avision bh canon \
65
PRELOADABLE_BACKENDS = niash  abaton agfafocus apple artec as6e avision bh canon \
66
        canon630u @CANON_PP@ coolscan coolscan2 dc25 @DC210@ @DC240@ dmc \
66
        canon630u @CANON_PP@ coolscan coolscan2 dc25 @DC210@ @DC240@ dmc \
67
        epson fujitsu @GPHOTO2@ gt68xx hp @HPSJ5S@ leo matsushita microtek \
67
        epson fujitsu @GPHOTO2@ gt68xx hp @HPSJ5S@ leo matsushita microtek \
68
        microtek2 mustek mustek_pp mustek_usb nec @NET@ pie @PINT@ plustek \
68
        microtek2 mustek mustek_pp mustek_usb nec @NET@ pie @PINT@ plustek \
Lines 70-76 Link Here
70
        sp15c st400 tamarack test teco1 teco2 teco3 umax umax_pp umax1220u \
70
        sp15c st400 tamarack test teco1 teco2 teco3 umax umax_pp umax1220u \
71
        @V4L@ artec_eplus48u ma1509 ibm hp5400
71
        @V4L@ artec_eplus48u ma1509 ibm hp5400
72
ifneq (@SELECTED_BACKENDS@,)
72
ifneq (@SELECTED_BACKENDS@,)
73
PRELOADABLE_BACKENDS = @SELECTED_BACKENDS@
73
PRELOADABLE_BACKENDS = niash  @SELECTED_BACKENDS@
74
endif
74
endif
75
75
76
ALL_BACKENDS = $(PRELOADABLE_BACKENDS) dll
76
ALL_BACKENDS = $(PRELOADABLE_BACKENDS) dll
Lines 266-272 Link Here
266
266
267
libsane-abaton.la: ../sanei/sanei_config2.lo
267
libsane-abaton.la: ../sanei/sanei_config2.lo
268
libsane-abaton.la: ../sanei/sanei_constrain_value.lo
268
libsane-abaton.la: ../sanei/sanei_constrain_value.lo
269
libsane-abaton.la: ../sanei/sanei_scsi.lo
269
libsane-abaton.la: ../sanei/sanei_scsi.lo 
270
libsane-niash.la: ../sanei/sanei_config2.lo 
271
libsane-niash.la: ../sanei/sanei_constrain_value.lo 
272
libsane-niash.la: ../sanei/sanei_usb.lo
270
libsane-agfafocus.la: ../sanei/sanei_config2.lo
273
libsane-agfafocus.la: ../sanei/sanei_config2.lo
271
libsane-agfafocus.la: ../sanei/sanei_constrain_value.lo
274
libsane-agfafocus.la: ../sanei/sanei_constrain_value.lo
272
libsane-agfafocus.la: ../sanei/sanei_scsi.lo
275
libsane-agfafocus.la: ../sanei/sanei_scsi.lo
(-)sane-backends-1.0.12/backend/dll.conf (+1 lines)
Lines 64-66 Link Here
64
# HP OfficeJet backend homepage: http://hpoj.sf.net/
64
# HP OfficeJet backend homepage: http://hpoj.sf.net/
65
# Uncomment the following line if hpoj is installed:
65
# Uncomment the following line if hpoj is installed:
66
#hpoj
66
#hpoj
67
niash
(-)sane-backends-1.0.12/backend/hp3300c.c (+1077 lines)
Line 0 Link Here
1
/*
2
  Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
3
4
  This program is free software; you can redistribute it and/or
5
  modify it under the terms of the GNU General Public License
6
  as published by the Free Software Foundation; either version 2
7
  of the License, or (at your option) any later version.
8
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18
  $Id: hp3300c.c,v 1.52 2003/03/24 19:14:46 bertrik Exp $
19
*/
20
21
/*
22
    Core HP3300c functions.
23
*/
24
25
#include <stdio.h>  /* fopen, fread, fwrite, fclose etc */
26
#include <stdarg.h> /* va_list for vfprintf */
27
#include <string.h> /* memcpy, memset */
28
#include <unistd.h> /* unlink */
29
#include <stdlib.h> /* malloc, free */
30
#include <math.h>   /* exp, pow */
31
32
#include "mytypes.h"
33
#include "hp3300c_xfer.h"
34
35
#include "hp3300c.h"
36
37
38
#ifndef MIN
39
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
40
#endif
41
42
#ifndef MAX
43
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
44
#endif
45
46
47
#define XFER_BUF_SIZE  0xF000
48
49
50
/* HP3400 firmware data */
51
static byte abData0000[] = {
52
  0xfe, 0x9f, 0x58, 0x1b, 0x00, 0x03, 0xa4, 0x02, 0x63, 0x02, 0x33, 0x02, 0x0d, 0x02, 0xf0, 0x01,
53
  0xd8, 0x01, 0xc5, 0x01, 0xb5, 0x01, 0xa8, 0x01, 0x9d, 0x01, 0x93, 0x01, 0x8b, 0x01, 0x84, 0x01,
54
  0x7e, 0x01, 0x79, 0x01, 0x74, 0x01, 0x70, 0x01, 0x6d, 0x01, 0x69, 0x01, 0x67, 0x01, 0x64, 0x01,
55
  0x62, 0x01, 0x60, 0x01, 0x5f, 0x01, 0x5d, 0x01, 0x5c, 0x01, 0x5b, 0x01, 0x5a, 0x01, 0x59, 0x01,
56
  0x58, 0x01, 0x57, 0x01, 0x57, 0x01, 0x56, 0x01, 0x56, 0x01, 0x55, 0x01, 0x55, 0x01, 0x54, 0x01,
57
  0x54, 0x01, 0x54, 0x01, 0x54, 0x01, 0x53, 0x01, 0x53, 0x01, 0x53, 0x01, 0x53, 0x01, 0x52, 0x81 };
58
/*  1st word : 0x9ffe = 40958, strip 15th bit: 0x1ffe = 8190
59
    2nd word : 0x1b58 = 7000 -> coincidence ?
60
    other words: formula: y = 676 / (2 - exp(0.113 * (1-x)) ), where x = 0 for first entry
61
*/
62
63
/* more HP3400 firmware data */
64
static byte abData0400[] = {
65
  0xa4, 0x82, 0x00, 0x80, 0xa4, 0x82, 0xaa, 0x02, 0xc0, 0x02, 0xe8, 0x02, 0x3e, 0x03, 0xc8, 0x03,
66
  0x58, 0x1b, 0xfe, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67
  0x00, 0x00, 0x00, 0x00 };
68
69
70
71
/* utility function to show a hexdump of a buffer */
72
void DumpHex(byte *pabData, int iLen, int iWidth)
73
{
74
  int i;
75
  for (i = 0; i < iLen; i++) {
76
    if ((i % iWidth) == 0) {
77
      printf("\n%04X", i);
78
    }
79
    printf(" %02X", pabData[i]);
80
  }
81
  printf("\n");
82
}
83
84
85
static void _ConvertMotorTable(byte *pabOld, byte *pabNew, int iSize, int iLpi)
86
{
87
  int iData, i, iBit15;
88
89
  for (i = 0; i < (iSize / 2); i++) {
90
    iData = pabOld[2*i + 0] + (pabOld[2*i + 1] << 8);
91
    iBit15 = (iData & 0x8000);
92
    iData = (iData & 0x7FFF);
93
    if (iData <= 0x400) {
94
      iData = iData * iLpi / 300;
95
    }
96
    if (iBit15 != 0) {
97
      iData |= 0x8000;
98
    }
99
    pabNew[2*i + 0] = iData & 255;
100
    pabNew[2*i + 1] = (iData >> 8) & 255;
101
  }
102
}
103
104
105
/*************************************************************************
106
  _ProbeRegisters
107
  ===============
108
    Tries to determine certain hardware properties.
109
110
  This is done by checking the writeability of some scanner registers.
111
  We cannot rely simply on the scanner model to contain a specific
112
  chip. The HP3300c for example uses one of at least three slightly
113
  different scanner ASICs (NIASH00012, NIASH00013 and NIASH00014).
114
115
  OUT pHWParams     Hardware parameters, updated fields:
116
        fGamma16    TRUE if 16 bit gamma tables can be used
117
        fReg07      TRUE if reg07 is writeable
118
        iBufferSize Size of scanner's internal buffer
119
120
  Returns TRUE if a NIASH chipset was found.
121
*************************************************************************/
122
static bool _ProbeRegisters(THWParams *pHWParams)
123
{
124
  byte bData1, bData2;
125
  int iHandle;
126
127
  iHandle = pHWParams->iXferHandle;
128
129
  DBG(DBG_MSG, "Probing scanner...\n");
130
131
  /* check register 0x04 */
132
  Hp3300cRegWrite (iHandle, 0x04, 0x55);
133
  Hp3300cRegRead  (iHandle, 0x04, &bData1);
134
  Hp3300cRegWrite (iHandle, 0x04, 0xAA);
135
  Hp3300cRegRead  (iHandle, 0x04, &bData2);
136
  Hp3300cRegWrite (iHandle, 0x04, 0x07);
137
  if ((bData1 != 0x55) || (bData2 != 0xAA)) {
138
    DBG(DBG_ERR, "  No NIASH chipset found!\n");
139
    return FALSE;
140
  }
141
142
  /* check writeability of register 3 bit 1 */
143
  Hp3300cRegRead  (iHandle, 0x03, &bData1);
144
  Hp3300cRegWrite (iHandle, 0x03, bData1 | 0x02);
145
  Hp3300cRegRead  (iHandle, 0x03, &bData2);
146
  Hp3300cRegWrite (iHandle, 0x03, bData1);
147
  pHWParams->fGamma16 = ((bData2 & 0x02) != 0);
148
  DBG(DBG_MSG, "  Gamma table entries are %d bit\n", pHWParams->fGamma16 ? 16 : 8);
149
150
  /* check register 0x07 */
151
  Hp3300cRegRead  (iHandle, 0x07, &bData1);
152
  Hp3300cRegWrite (iHandle, 0x07, 0x1C);
153
  Hp3300cRegRead  (iHandle, 0x07, &bData2);
154
  Hp3300cRegWrite (iHandle, 0x07, bData1);
155
  pHWParams->fReg07 = (bData2 == 0x1C);
156
157
  if (!pHWParams->fGamma16) {
158
    /* internal scan buffer size is an educated guess, but seems to correlate
159
       well with the size calculated from several windows driver log files
160
       size = 128kB - 44088 bytes (space required for gamma/calibration table)
161
    */
162
    pHWParams->iBufferSize = 86984L;
163
    DBG(DBG_MSG, "  NIASH version < 00014\n");
164
  }
165
  else {
166
    pHWParams->iBufferSize = 0x60000L;
167
    if (!pHWParams->fReg07) {
168
      DBG(DBG_MSG, "  NIASH version = 00014\n");
169
    }
170
    else {
171
      DBG(DBG_MSG, "  NIASH version > 00014\n");
172
    }
173
  }
174
175
  return TRUE;
176
}
177
178
179
/* returns 0 on success, < 0 otherwise */
180
int Hp3300cOpen(THWParams *pHWParams, char *pszName)
181
{
182
  int iXferHandle;
183
184
  iXferHandle = Hp3300cXferOpen(pszName, &pHWParams->eModel);
185
  if (iXferHandle < 0) {
186
    DBG(DBG_ERR, "Hp3300cXferOpen failed for '%s'\n", pszName);
187
    return -1;
188
  }
189
  
190
  pHWParams->iXferHandle = iXferHandle;
191
192
  Hp3300cWakeup(pHWParams->iXferHandle);
193
194
  /* default HW params */
195
  pHWParams->iSensorSkew =  8;
196
  pHWParams->iTopLeftX =    0;
197
  pHWParams->iTopLeftY =    3;
198
  pHWParams->fReg07 =       FALSE;
199
  pHWParams->iSkipLines =   0;
200
  pHWParams->iExpTime =     5408;
201
  pHWParams->iReversedHead = TRUE;
202
203
  switch (pHWParams->eModel) {
204
205
  case eHp3300c:
206
    DBG(DBG_MSG, "Setting params for Hp3300\n");
207
    pHWParams->iTopLeftX =  4;
208
    pHWParams->iTopLeftY =  11;
209
    pHWParams->iSkipLines = 14;
210
    break;
211
212
  case eHp3400c: case eHp4300c:
213
    DBG(DBG_MSG, "Setting params for Hp3400c/Hp4300c\n");
214
    pHWParams->iTopLeftX =  2;
215
    pHWParams->iTopLeftY =  13;
216
    pHWParams->fReg07 =     TRUE;
217
    break;
218
219
  case eAgfaTouch:
220
    DBG(DBG_MSG, "Setting params for AgfaTouch\n");
221
    pHWParams->iReversedHead = FALSE; /* head not reversed on Agfa Touch */
222
    pHWParams->iTopLeftX =     3;
223
    pHWParams->iTopLeftY =     10;
224
    pHWParams->iSkipLines =    7;
225
    break;
226
227
  case eUnknownModel:
228
    DBG(DBG_MSG, "Setting params for UnknownModel\n");
229
    break;
230
231
  default:
232
    DBG(DBG_ERR, "ERROR: internal error! (%d)\n", (int)pHWParams->eModel);
233
    return -1;
234
  }
235
236
  /* autodetect some hardware properties */
237
  if (!_ProbeRegisters(pHWParams)) {
238
    DBG(DBG_ERR, "_ProbeRegisters failed!\n");
239
    return -1;
240
  }
241
  
242
  return 0;
243
}
244
245
246
void Hp3300cClose(THWParams *pHWPar)
247
{
248
  Hp3300cXferClose(pHWPar->iXferHandle);
249
  pHWPar->iXferHandle = 0;
250
}
251
252
253
static void WriteRegWord(int iHandle, byte bReg, word wData)
254
{
255
  Hp3300cRegWrite(iHandle, bReg, wData & 0xFF);
256
  Hp3300cRegWrite(iHandle, bReg + 1, (wData >> 8) & 0xFF);
257
}
258
259
260
/* calculate a 4096 byte gamma table */
261
void CalcGamma(byte *pabTable, double Gamma)
262
{
263
  int i, iData;
264
265
  /* fill gamma table */
266
  for (i = 0; i < 4096; i++) {
267
    iData = floor(256.0 * pow(((double)i / 4096.0), 1.0 / Gamma));
268
    pabTable[i] = iData;
269
  }
270
}
271
272
273
/*
274
  Hp3400WriteFw
275
  =============
276
    Writes data to scanners with a NIASH00019 chipset, e.g.
277
    gamma, calibration and motor control data.
278
279
  IN  pabData   pointer to firmware data
280
      iLen      Size of firmware date (bytes)
281
      iAddr     Scanner address to write to
282
*/
283
static void Hp3400cWriteFW(int iXferHandle, byte *pabData, int iLen, int iAddr)
284
{
285
  iAddr--;
286
  Hp3300cRegWrite(iXferHandle, 0x21, iAddr & 0xFF);
287
  Hp3300cRegWrite(iXferHandle, 0x22, (iAddr >> 8) & 0xFF);
288
  Hp3300cRegWrite(iXferHandle, 0x23, (iAddr >> 16) & 0xFF);
289
  Hp3300cBulkWrite(iXferHandle, pabData, iLen);
290
}
291
292
293
/* Writes the gamma and offset/gain tables to the scanner.
294
   In case a calibration file exist, it will be used for offset/gain */
295
void WriteGammaCalibTable(byte *pabGammaR, byte *pabGammaG, byte *pabGammaB,
296
    byte *pabCalibTable, int iGain, int iOffset, THWParams *pHWPar)
297
{
298
  int           i, j, k;
299
  static byte   abGamma[60000];
300
  int           iData;
301
  int           iHandle;
302
303
  iHandle = pHWPar->iXferHandle;
304
305
  j = 0;
306
  /* fill gamma table for red component */
307
  /* pad entries with 0 for 16-bit gamma table */
308
  for (i = 0; i < 4096; i++) {
309
    if (pHWPar->fGamma16) {
310
      abGamma[j++] = 0;
311
    }
312
    abGamma[j++] = pabGammaR[i];
313
  }
314
  /* fill gamma table for green component */
315
  for (i = 0; i < 4096; i++) {
316
    if (pHWPar->fGamma16) {
317
      abGamma[j++] = 0;
318
    }
319
    abGamma[j++] = pabGammaG[i];
320
  }
321
  /* fill gamma table for blue component */
322
  for (i = 0; i < 4096; i++) {
323
    if (pHWPar->fGamma16) {
324
      abGamma[j++] = 0;
325
    }
326
    abGamma[j++] = pabGammaB[i];
327
  }
328
329
  if (pabCalibTable == NULL) {
330
    iData = (iGain << 6) + iOffset;
331
    for (i = 0; i < HW_PIXELS; i++) {
332
      for (k = 0; k < 3; k++) {
333
        abGamma[j++] = (iData) & 255;
334
        abGamma[j++] = (iData >> 8) & 255;
335
      }
336
    }
337
  }
338
  else {
339
    memcpy(&abGamma[j], pabCalibTable, HW_PIXELS * 6);
340
    j += HW_PIXELS * 6;
341
  }
342
343
  Hp3300cRegWrite(iHandle, 0x02, 0x80);
344
  Hp3300cRegWrite(iHandle, 0x03, 0x01);
345
  Hp3300cRegWrite(iHandle, 0x03, 0x11);
346
  Hp3300cRegWrite(iHandle, 0x02, 0x84);
347
348
  if (pHWPar->fReg07) {
349
    Hp3400cWriteFW(iHandle, abGamma, j, 0x2000);
350
  }
351
  else {
352
    Hp3300cBulkWrite(iHandle, abGamma, j);
353
  }
354
355
  Hp3300cRegWrite(iHandle, 0x02, 0x80);
356
}
357
358
359
static void WriteAFEReg(int iHandle, int iReg, int iData)
360
{
361
  Hp3300cRegWrite(iHandle, 0x25, iReg);
362
  Hp3300cRegWrite(iHandle, 0x26, iData);
363
}
364
365
366
/* setup the analog front-end -> coarse calibration */
367
static void WriteAFE(int iHandle)
368
{
369
  /* see WM8143 datasheet */
370
371
  WriteAFEReg(iHandle, 0x04, 0x00);
372
  WriteAFEReg(iHandle, 0x03, 0x12);
373
  WriteAFEReg(iHandle, 0x02, 0x04);
374
  WriteAFEReg(iHandle, 0x05, 0x10);
375
  WriteAFEReg(iHandle, 0x01, 0x03);
376
377
  WriteAFEReg(iHandle, 0x20, 0xc0);/*c8*/    /* red offset */
378
  WriteAFEReg(iHandle, 0x21, 0xc0);/*c8*/    /* green offset */
379
  WriteAFEReg(iHandle, 0x22, 0xc0);/*d0*/    /* blue offset */
380
381
  WriteAFEReg(iHandle, 0x28, 0x05);/*5*/     /* red gain */
382
  WriteAFEReg(iHandle, 0x29, 0x03);/*3*/     /* green gain */
383
  WriteAFEReg(iHandle, 0x2A, 0x04);/*4*/     /* blue gain */
384
}
385
386
387
/* wait for the carriage to return */
388
static void WaitReadyBit(int iHandle)
389
{
390
  byte bData;
391
392
  do {
393
    Hp3300cRegRead(iHandle, 0x03, &bData);
394
  } while ((bData & 8) == 0);
395
}
396
397
398
/*
399
  Initialisation specific for NIASH00014 and lower chips
400
*/
401
static void InitNiash00014(TScanParams *pParams, THWParams *pHWParams)
402
{
403
  int iHandle, iLpiCode;
404
405
  iHandle = pHWParams->iXferHandle;
406
407
  /* exposure time (in units 24/Fcrystal)? */
408
  WriteRegWord(iHandle, 0x08, pHWParams->iExpTime - 1);
409
410
  /* width in pixels */
411
  WriteRegWord(iHandle, 0x12, pParams->iWidth - 1);
412
413
  /* top */
414
  WriteRegWord  (iHandle, 0x17, pParams->iTop);
415
  WriteRegWord  (iHandle, 0x19, pParams->iTop);
416
417
  /* time between stepper motor steps (in units of 24/Fcrystal)? */
418
  iLpiCode = pParams->iLpi * pHWParams->iExpTime / 1200L;
419
420
  if (!pHWParams->fGamma16) {
421
    /* NIASH 00012 / 00013 init */
422
423
    /* LPI specific settings */
424
    if (pParams->iLpi < 600) {
425
      /* set halfres bit */
426
      Hp3300cRegWrite(iHandle, 0x06, 0x01);
427
      /* double lpi code because of halfres bit */
428
      iLpiCode *= 2;
429
    }
430
    else {
431
      /* clear halfres bit */
432
      Hp3300cRegWrite(iHandle, 0x06, 0x00);
433
      /* add exptime to make it scan slower */
434
      iLpiCode += pHWParams->iExpTime;
435
    }
436
437
    /* unknown setting */
438
    WriteRegWord  (iHandle, 0x27, 0x7FD2);
439
    WriteRegWord  (iHandle, 0x29, 0x6421);
440
441
  }
442
  else {
443
    /* NIASH 00014 init */
444
445
    /* halfres bit always cleared */
446
    Hp3300cRegWrite(iHandle, 0x06, 0x00);
447
448
    /* LPI specific settings */
449
    if (pParams->iLpi >= 600) {
450
      /* add exptime to make it scan slower */
451
      iLpiCode += pHWParams->iExpTime;
452
    }
453
454
    /* unknown setting */
455
    WriteRegWord  (iHandle, 0x27, 0xc862);/*c862 */
456
    WriteRegWord  (iHandle, 0x29, 0xb853);/*b853 */
457
  }
458
459
  /* LPI code */
460
  WriteRegWord(iHandle, 0x0A, iLpiCode - 1);
461
462
  /* backtrack reversing speed */
463
  Hp3300cRegWrite(iHandle, 0x1E, (iLpiCode - 1) / 32);
464
}
465
466
467
/*
468
  Initialisation specific for NIASH00019 chips
469
*/
470
static void InitNiash00019(TScanParams *pParams, THWParams *pHWParams)
471
{
472
  int iHandle, iLpiCode;
473
  static byte abMotor[512];
474
475
476
  iHandle = pHWParams->iXferHandle;
477
478
  /* exposure time (in units 24/Fcrystal)? */
479
  WriteRegWord  (iHandle, 0x08, pHWParams->iExpTime);
480
481
  /* width in pixels */
482
  WriteRegWord  (iHandle, 0x12, pParams->iWidth);
483
484
  /* ? */
485
  WriteRegWord  (iHandle, 0x27, 0xc862);/*c862 */
486
  WriteRegWord  (iHandle, 0x29, 0xb853);/*b853 */
487
488
  /* specific handling of 150 dpi resolution */
489
  if (pParams->iLpi == 150) {
490
    /* use 300 LPI but skip every other line */
491
    pParams->iLpi = 300;
492
    Hp3300cRegWrite(iHandle, 0x06, 0x01);
493
  }
494
  else {
495
    Hp3300cRegWrite(iHandle, 0x06, 0x00);
496
  }
497
498
  /* DPI and position table */
499
  Hp3300cRegWrite (iHandle, 0x07, 0x02);
500
  _ConvertMotorTable(abData0000, abMotor, sizeof(abData0000), pParams->iLpi);
501
  Hp3400cWriteFW(iHandle, abMotor, sizeof(abData0000), 0x000);
502
  _ConvertMotorTable(abData0400, abMotor, sizeof(abData0400), pParams->iLpi);
503
  Hp3400cWriteFW(iHandle, abMotor, sizeof(abData0400), 0x400);
504
505
  /* backtrack reversing speed */
506
  iLpiCode = pParams->iLpi * pHWParams->iExpTime / 1200L;
507
  Hp3300cRegWrite(iHandle, 0x1E, (iLpiCode - 1) / 32);
508
}
509
510
511
/*
512
  Scanner initialisation common to all NIASH chips
513
*/
514
static void InitNiashCommon(TScanParams *pParams, THWParams *pHWParams)
515
{
516
  int iWidthHW, iHandle, iMaxLevel;
517
518
519
  iHandle = pHWParams->iXferHandle;
520
521
  Hp3300cRegWrite (iHandle, 0x02, 0x80);
522
  Hp3300cRegWrite (iHandle, 0x03, 0x11);
523
  Hp3300cRegWrite (iHandle, 0x01, 0x8B);
524
  Hp3300cRegWrite (iHandle, 0x05, 0x01);
525
526
  /* dpi */
527
  WriteRegWord  (iHandle, 0x0C, pParams->iDpi);
528
529
  /* calculate width in units of HW resolution */
530
  iWidthHW = pParams->iWidth * (HW_DPI / pParams->iDpi);
531
532
  /* set left and right limits */
533
  if ( pHWParams->iReversedHead ) {
534
    /* head is reversed */
535
    /* right */
536
    WriteRegWord  (iHandle, 0x0E, 3 * (HW_PIXELS - (pParams->iLeft + iWidthHW)) );
537
538
    /* left */
539
    WriteRegWord  (iHandle, 0x10, 3 * (HW_PIXELS - pParams->iLeft) - 1);
540
  } else {
541
    /* head is not reversed */
542
    /*left  */
543
    WriteRegWord  (iHandle, 0x0E, 3 * pParams->iLeft);
544
545
    /* right */
546
    WriteRegWord  (iHandle, 0x10, 3 * (pParams->iLeft + iWidthHW) - 1);
547
  }
548
549
  /* bottom */
550
  WriteRegWord  (iHandle, 0x1B, pParams->iBottom); /* 0x393C); */
551
552
  /* forward jogging speed */
553
  Hp3300cRegWrite  (iHandle, 0x1D, 0x60);
554
555
  /* backtrack reversing speed? */
556
  Hp3300cRegWrite (iHandle, 0x2B, 0x15);
557
558
  /* backtrack distance */
559
  if (pParams->iLpi < 600) {
560
    Hp3300cRegWrite(iHandle, 0x1F, 0x30);
561
  }
562
  else {
563
    Hp3300cRegWrite(iHandle, 0x1F, 0x18);
564
  }
565
566
  /* max buffer level before backtrace */
567
  iMaxLevel = MIN(pHWParams->iBufferSize / pParams->iWidth, 250);
568
  Hp3300cRegWrite (iHandle, 0x14, iMaxLevel - 1);
569
570
  /* lamp PWM, max = 0x1ff? */
571
  WriteRegWord  (iHandle, 0x2C, 0x01FF);
572
573
  /* not needed? */
574
  Hp3300cRegWrite (iHandle, 0x15, 0x90);/* 90 */
575
  Hp3300cRegWrite (iHandle, 0x16, 0x70);/* 70 */
576
577
  WriteAFE(iHandle);
578
579
  WaitReadyBit(iHandle);
580
581
  Hp3300cRegWrite  (iHandle, 0x03, 0x05);
582
583
  Hp3300cRegWrite(iHandle, 0x02, pParams->fCalib ? 0x88 : 0xA8);
584
}
585
586
587
/* write registers */
588
bool InitScan(TScanParams *pParams, THWParams *pHWParams)
589
{
590
  int         iHeight;
591
  int         iExpTime;
592
  TScanParams Params;
593
  int         iHandle;
594
595
  iHandle = pHWParams->iXferHandle;
596
597
  /* check validity of scanparameters */
598
  switch (pParams->iDpi) {
599
  case 150: case 300: case 600:
600
    break;
601
  default:
602
    DBG(DBG_ERR, "Invalid dpi (%d)\n", pParams->iDpi);
603
    return FALSE;
604
  }
605
606
  iHeight = (pParams->iBottom - pParams->iTop + 1);
607
  if (iHeight <= 0) {
608
    DBG(DBG_ERR, "Invalid height (%d)\n", iHeight);
609
    return FALSE;
610
  }
611
612
  if (pParams->iWidth <= 0) {
613
    DBG(DBG_ERR, "Invalid width (%d)\n", pParams->iWidth);
614
    return FALSE;
615
  }
616
617
  switch (pParams->iLpi) {
618
  case 150: case 300: case 600:
619
    break;
620
  default:
621
    DBG(DBG_ERR, "Invalid lpi (%d)\n", pParams->iLpi);
622
    return FALSE;
623
  }
624
625
  /* exposure time (in units of 24/Fcrystal?), must be divisible by 8 !!! */
626
  iExpTime = 5408;
627
  if ((iExpTime % 8) != 0) {
628
    DBG(DBG_ERR, "Invalid exposure time (%d)\n", iExpTime);
629
    return FALSE;
630
  }
631
632
  /*
633
    *** Done checking scan parameters validity ***
634
  */
635
636
  /*
637
      copy the parameters locally and make pParams point to the local copy
638
   */
639
  memcpy(&Params, pParams, sizeof(Params));
640
  pParams = &Params;
641
642
  if (!pHWParams->fReg07) {
643
    /* init NIASH00014 and lower */
644
    InitNiash00014(pParams, pHWParams);
645
  }
646
  else {
647
    /* init NIASH00019 */
648
    InitNiash00019(pParams, pHWParams);
649
  }
650
651
  /* common NIASH init */
652
  InitNiashCommon(pParams, pHWParams);
653
654
  return TRUE;
655
}
656
657
658
/************************************************************************/
659
660
static void XferBufferGetLine(int iHandle, TDataPipe *p, byte *pabLine)
661
{
662
  byte bData;
663
664
  /* time for a fresh read? */
665
  if (p->iCurLine == 0) {
666
    /*    DBG(DBG_MSG, "Reading buffer %d bytes\n", _iLinesPerXferBuf
667
     * _iBytesPerLine); */
668
    Hp3300cRegRead(iHandle, 0x20, &bData);
669
    DBG(DBG_MSG, "buffer level = %3d, <reading %5d bytes>, ",
670
     (int)bData, p->iLinesPerXferBuf * p->iBytesPerLine);
671
    Hp3300cBulkRead(iHandle, p->pabXferBuf, p->iLinesPerXferBuf * p->iBytesPerLine);
672
    Hp3300cRegRead(iHandle, 0x20, &bData);
673
    DBG(DBG_MSG, "buffer level = %3d\r", bData);
674
    fflush(stdout);
675
  }
676
  /* copy one line */
677
  if (pabLine != NULL) {
678
    memcpy(pabLine, &p->pabXferBuf[p->iCurLine * p->iBytesPerLine], p->iBytesPerLine);
679
  }
680
  /* advance pointer */
681
  p->iCurLine = (p->iCurLine + 1) % p->iLinesPerXferBuf;
682
}
683
684
685
static void XferBufferInit(int iHandle, TDataPipe *p)
686
{
687
  int i;
688
689
  p->pabXferBuf = (byte *)malloc(XFER_BUF_SIZE);
690
  p->iCurLine = 0;
691
692
  /* skip garbage lines */
693
  for (i = 0; i < p->iSkipLines; i++) {
694
    XferBufferGetLine(iHandle, p, NULL);
695
  }
696
}
697
698
699
static void XferBufferExit(TDataPipe *p)
700
{
701
  if (p->pabXferBuf != NULL) {
702
    free(p->pabXferBuf);
703
    p->pabXferBuf = NULL;
704
  }
705
  else {
706
    DBG(DBG_ERR, "XferBufExit: Xfer buffer not initialised!\n");
707
  }
708
}
709
710
711
/* unscrambles a line:
712
   - combining the proper R, G and B lines and converting them to interpixel RGB
713
   - mirroring left to right
714
*/
715
static void _UnscrambleLine(byte *pabLine,
716
  byte *pabRed, byte *pabGrn, byte *pabBlu, int iWidth, bool iReversedHead)
717
{
718
  int i, j;
719
  if (iReversedHead) {
720
    /* reversed */
721
    for (i = 0; i < iWidth; i++) {
722
      j = (iWidth - i) * 3;
723
      pabLine[j - 3] = pabRed[i];
724
      pabLine[j - 2] = pabGrn[i + iWidth];
725
      pabLine[j - 1] = pabBlu[i + iWidth * 2];
726
    }
727
  } else {
728
    /* not reversed */
729
    for (i = 0; i < iWidth; i++) {
730
      pabLine[3 * i] = pabRed[i];
731
      pabLine[3 * i + 1] = pabGrn[i + iWidth];
732
      pabLine[3 * i + 2] = pabBlu[i + iWidth * 2];
733
    }
734
  }
735
}
736
737
738
/* gets an unscrambled line from the circular buffer. the first couple of lines contain garbage */
739
void CircBufferGetLine(int iHandle, TDataPipe *p, byte *pabLine, bool iReversedHead)
740
{
741
  if (iReversedHead) {
742
    XferBufferGetLine(iHandle, p, &p->pabCircBuf[p->iRedLine * p->iBytesPerLine]);
743
  } else {
744
    XferBufferGetLine(iHandle, p, &p->pabCircBuf[p->iBluLine * p->iBytesPerLine]);
745
  }
746
747
  if (pabLine != NULL) {
748
    _UnscrambleLine(pabLine,
749
      &p->pabCircBuf[p->iRedLine * p->iBytesPerLine],
750
      &p->pabCircBuf[p->iGrnLine * p->iBytesPerLine],
751
      &p->pabCircBuf[p->iBluLine * p->iBytesPerLine],
752
      p->iBytesPerLine / 3,
753
      iReversedHead);
754
  }
755
756
  /* advance pointers */
757
  p->iRedLine = (p->iRedLine + 1) % p->iLinesPerCircBuf;
758
  p->iGrnLine = (p->iGrnLine + 1) % p->iLinesPerCircBuf;
759
  p->iBluLine = (p->iBluLine + 1) % p->iLinesPerCircBuf;
760
}
761
762
763
void CircBufferInit(int iHandle, TDataPipe *p, int iBytesPerLine, int iMisAlignment, bool iReversedHead)
764
{
765
  int i;
766
767
  p->iBytesPerLine = iBytesPerLine;
768
  if (iMisAlignment == 0) {
769
    p->iLinesPerCircBuf = 1;
770
  }
771
  else {
772
    p->iLinesPerCircBuf = 3 * iMisAlignment;
773
  }
774
775
  DBG(DBG_MSG, "_iBytesPerLine = %d\n", p->iBytesPerLine);
776
  DBG(DBG_MSG, "_iLinesPerCircBuf = %d\n", p->iLinesPerCircBuf);
777
  p->pabCircBuf = (byte *)malloc(iBytesPerLine * p->iLinesPerCircBuf);
778
  if (p->pabCircBuf == NULL) {
779
    DBG(DBG_ERR, "Unable to allocate %d bytes for circular buffer\n", (int)(iBytesPerLine * p->iLinesPerCircBuf));
780
    return;
781
  }
782
  DBG(DBG_MSG, "Allocated %d bytes for circular buffer\n", iBytesPerLine * p->iLinesPerCircBuf);
783
784
  if (iReversedHead) {
785
    p->iBluLine = 0;
786
    p->iGrnLine = iMisAlignment;
787
    p->iRedLine = iMisAlignment * 2;
788
  } else {
789
    p->iRedLine = 0;
790
    p->iGrnLine = iMisAlignment;
791
    p->iBluLine = iMisAlignment * 2;
792
  }
793
794
  p->iLinesPerXferBuf = XFER_BUF_SIZE / iBytesPerLine;
795
  DBG(DBG_MSG, "_iLinesPerXferBuf = %d\n", p->iLinesPerXferBuf);
796
  DBG(DBG_MSG, "Xfer block size = %d\n", p->iLinesPerXferBuf * p->iBytesPerLine);
797
798
  /* init transfer buffer */
799
  XferBufferInit(iHandle, p);
800
801
  /* fill circular buffer */
802
  for (i = 0; i < p->iLinesPerCircBuf; i++) {
803
    CircBufferGetLine(iHandle, p, NULL, iReversedHead);
804
  }
805
}
806
807
808
void CircBufferExit(TDataPipe *p)
809
{
810
  XferBufferExit(p);
811
  if (p->pabCircBuf != NULL) {
812
    DBG(DBG_MSG, "\n");
813
    free(p->pabCircBuf);
814
    p->pabCircBuf = NULL;
815
  }
816
  else {
817
    DBG(DBG_ERR, "CircBufferExit: Circular buffer not initialised!\n");
818
  }
819
}
820
821
822
/************************************************************************/
823
824
/*************************************************************************
825
  ScanLines
826
  =========
827
    Helper function to scan in an image and output the result to a file.
828
829
  IN  pFile     File to write image data to
830
      pParams   User-defineable settings describing the image to be scanned
831
      pHWParams Scanner hardware settings
832
833
*************************************************************************/
834
void ScanLines(FILE *pFile, TScanParams *pParams, THWParams *pHWParams)
835
{
836
  static byte  abBuf[HW_PIXELS * 3];
837
  int   iBytesPerLine;
838
  int   iHeight;
839
  int   iHandle;
840
  bool  iReversedHead;
841
  TDataPipe DataPipe;
842
843
  iHandle = pHWParams->iXferHandle;
844
845
  iHeight = pParams->iHeight;
846
  iBytesPerLine = pParams->iWidth * 3;
847
  DataPipe.iSkipLines = 0;
848
  iReversedHead = pHWParams->iReversedHead;
849
850
  if (InitScan(pParams, pHWParams)) {
851
    CircBufferInit(iHandle, &DataPipe, iBytesPerLine, pHWParams->iSensorSkew * pParams->iLpi / HW_LPI, iReversedHead);
852
    while (iHeight-- > 0) {
853
      CircBufferGetLine(iHandle, &DataPipe, abBuf, iReversedHead);
854
      fwrite(abBuf, 1, iBytesPerLine, pFile);
855
    }
856
    CircBufferExit(&DataPipe);
857
  }
858
  FinishScan(pHWParams);
859
}
860
861
862
static int _CalcAvg(byte *pabBuf, int n, int iStep)
863
{
864
  int  i, j, x;
865
866
  for (i = j = x = 0; i < n; i++) {
867
    x += pabBuf[j];
868
    j += iStep;
869
  }
870
  return (x / n);
871
}
872
873
874
/* converts white line data and black point data into a calibration table */
875
static void CreateCalibTable(byte *abWhite, byte bBlackR, byte bBlackG,
876
  byte bBlackB, int iReversedHead, byte *pabCalibTable)
877
{
878
  int i, j, iGain, iOffset, iData;
879
  byte *pabPixel;
880
881
  j = 0;
882
  for (i = 0; i < HW_PIXELS; i++) {
883
    if (iReversedHead) {
884
      pabPixel = &abWhite[(HW_PIXELS - i - 1) * 3];
885
    }
886
    else {
887
      pabPixel = &abWhite[i * 3];
888
    }
889
    /* red */
890
    if (bBlackR > 16) bBlackR = 16 ;
891
    iGain = 65536 / MAX(1, pabPixel[0] - bBlackR);
892
    iOffset = bBlackR * 4;
893
    if (iOffset > 63) iOffset = 63 ;
894
    iData = (iGain << 6) + iOffset;
895
    pabCalibTable[j++] = (iData) & 255;
896
    pabCalibTable[j++] = (iData >> 8) & 255;
897
    /* green */
898
    if (bBlackG > 16) bBlackG = 16 ;
899
    iGain = 65536 / MAX(1, pabPixel[1] - bBlackG);
900
    iOffset = bBlackG * 4;
901
    if (iOffset > 63) iOffset = 63 ;
902
    iData = (iGain << 6) + iOffset;
903
    pabCalibTable[j++] = (iData) & 255;
904
    pabCalibTable[j++] = (iData >> 8) & 255;
905
    /* blue */
906
    if (bBlackB > 16) bBlackB = 16 ;
907
    iGain = 65536 / MAX(1, pabPixel[2] - bBlackB);
908
    iOffset = bBlackB * 4;
909
    if (iOffset > 63) iOffset = 63 ;
910
    iData = (iGain << 6) + iOffset;
911
    pabCalibTable[j++] = (iData) & 255;
912
    pabCalibTable[j++] = (iData >> 8) & 255;
913
  }
914
}
915
916
917
/*************************************************************************
918
  Lamp control functions
919
*************************************************************************/
920
bool GetLamp(THWParams *pHWParams, bool *pfLampIsOn)
921
{
922
  byte bData;
923
924
  Hp3300cRegRead(pHWParams->iXferHandle, 0x03, &bData);
925
  *pfLampIsOn = ((bData & 0x01) != 0);
926
  return TRUE;
927
}
928
929
930
bool SetLamp(THWParams *pHWParams, bool fLampOn)
931
{
932
  byte bData;
933
  int iHandle;
934
935
  iHandle = pHWParams->iXferHandle;
936
937
  Hp3300cRegRead(iHandle, 0x03, &bData);
938
  if (fLampOn) {
939
    Hp3300cRegWrite(iHandle, 0x03, bData | 0x01);
940
  }
941
  else {
942
    Hp3300cRegWrite(iHandle, 0x03, bData & ~0x01);
943
  }
944
  return TRUE;
945
}
946
947
948
/*************************************************************************
949
  Experimental simple calibration
950
951
  Basic idea:
952
  * a strip starting at position 0 is scanned in
953
  * per-pixel white level is determined by average of first 4 lines
954
  * global black level is determined by minimum value of all lines
955
*************************************************************************/
956
bool SimpleCalib(THWParams *pHWPar, byte *pabCalibTable)
957
{
958
  byte bMinR, bMinG, bMinB;
959
  TDataPipe DataPipe;
960
  TScanParams Params;
961
  byte abGamma[4096];
962
  int i, j;
963
  static byte abBuf[HW_PIXELS * 3 * 71]; /* Carefull : see startWhite and endWhite below */
964
  static byte abLine[HW_PIXELS * 3];
965
  static byte abWhite[HW_PIXELS * 3];
966
  byte *pabWhite;
967
  int iWhiteR, iWhiteG, iWhiteB;
968
  int iHandle;
969
  bool iReversedHead;
970
  int startWhiteY, endWhiteY ;
971
  int startBlackY, endBlackY ;
972
  int startBlackX, endBlackX ;
973
974
  iHandle = pHWPar->iXferHandle;
975
  iReversedHead = pHWPar->iReversedHead;
976
977
  DataPipe.iSkipLines = pHWPar->iSkipLines;
978
979
  Params.iDpi = HW_DPI;
980
  Params.iLpi = HW_DPI;
981
  if (iReversedHead) /* hp scanners */
982
    Params.iTop = 60;
983
  else /* agfa scanners */
984
    Params.iTop = 30 ;
985
  Params.iBottom = HP3300C_BOTTOM;
986
  Params.iLeft = 0;
987
  Params.iWidth = HW_PIXELS;
988
  Params.iHeight = 54;
989
  Params.fCalib = TRUE;
990
991
  /* write gamma table with neutral gain / offset */
992
  CalcGamma(abGamma, 1.0);
993
  WriteGammaCalibTable(abGamma, abGamma, abGamma, NULL, 256, 0, pHWPar);
994
995
  if (!InitScan(&Params, pHWPar)) {
996
    return FALSE;
997
  }
998
999
  /* Definition of white and black areas */
1000
  if (iReversedHead) { /* hp scanners */
1001
    startWhiteY = 0 ;
1002
    endWhiteY = 15 ;
1003
    startBlackY = 16 ;
1004
    endBlackY = 135 ;
1005
    startBlackX = 0 ;
1006
    endBlackX = HW_PIXELS ;
1007
  } else { /* agfa scanners */
1008
    startWhiteY = 0 ;
1009
    endWhiteY = 70 ;
1010
    startBlackY = 86 ;
1011
    endBlackY = 135 ;
1012
    startBlackX = 1666 ;
1013
    endBlackX = 3374 ;
1014
  }
1015
1016
  CircBufferInit(iHandle, &DataPipe, HW_PIXELS * 3, Params.iLpi / 150, iReversedHead);
1017
  /* white level */
1018
  /* skip some lines */
1019
  for (i = 0; i < startWhiteY; i++) {
1020
    CircBufferGetLine(iHandle, &DataPipe, abLine, iReversedHead);
1021
  }
1022
  /* Get white lines */
1023
  for (i = 0; i < endWhiteY - startWhiteY + 1; i++) {
1024
    CircBufferGetLine(iHandle, &DataPipe, &abBuf[i * HW_PIXELS * 3], iReversedHead);
1025
  }
1026
  /* black level */
1027
  bMinR = 255; bMinG = 255; bMinB = 255;
1028
  /* Skip some lines */
1029
  for (i = 0; i < startBlackY; i++) {
1030
    CircBufferGetLine(iHandle, &DataPipe, abLine, iReversedHead);
1031
  }
1032
  for (i = 0; i < endBlackY - startBlackY + 1; i++) {
1033
    CircBufferGetLine(iHandle, &DataPipe, abLine, iReversedHead);
1034
    for (j = 0; j < endBlackX; j++) {
1035
      bMinR = MIN(abLine[j * 3 + 0], bMinR);
1036
      bMinG = MIN(abLine[j * 3 + 1], bMinG);
1037
      bMinB = MIN(abLine[j * 3 + 2], bMinB);
1038
    }
1039
  }
1040
  CircBufferExit(&DataPipe);
1041
  FinishScan(pHWPar);
1042
1043
  /* calc average white level */
1044
  pabWhite = abBuf;
1045
  for (i = 0; i < HW_PIXELS; i++) {
1046
    abWhite[i * 3 + 0] = _CalcAvg(&pabWhite[i * 3 + 0], endWhiteY - startWhiteY + 1, HW_PIXELS * 3);
1047
    abWhite[i * 3 + 1] = _CalcAvg(&pabWhite[i * 3 + 1], endWhiteY - startWhiteY + 1, HW_PIXELS * 3);
1048
    abWhite[i * 3 + 2] = _CalcAvg(&pabWhite[i * 3 + 2], endWhiteY - startWhiteY + 1, HW_PIXELS * 3);
1049
  }
1050
  iWhiteR = _CalcAvg(&abWhite[0], HW_PIXELS, 3);
1051
  iWhiteG = _CalcAvg(&abWhite[1], HW_PIXELS, 3);
1052
  iWhiteB = _CalcAvg(&abWhite[2], HW_PIXELS, 3);
1053
1054
  DBG(DBG_MSG, "Black level (%d,%d,%d), White level (%d,%d,%d)\n",
1055
          (int)bMinR, (int)bMinG, (int)bMinB, iWhiteR, iWhiteG, iWhiteB);
1056
1057
  /* convert the white line and black point into a calibration table */
1058
  CreateCalibTable(abWhite, bMinR, bMinG, bMinB, iReversedHead,
1059
                   pabCalibTable);
1060
1061
  return TRUE;
1062
}
1063
1064
1065
/*************************************************************************
1066
  FinishScan
1067
  ==========
1068
    Finishes the scan. Makes the scanner head move back to the home position.
1069
1070
*************************************************************************/
1071
void FinishScan(THWParams *pHWParams)
1072
{
1073
  Hp3300cRegWrite(pHWParams->iXferHandle, 0x02, 0x80);
1074
}
1075
1076
1077
(-)sane-backends-1.0.12/backend/hp3300c.h (+113 lines)
Line 0 Link Here
1
/*
2
  Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
3
4
  This program is free software; you can redistribute it and/or
5
  modify it under the terms of the GNU General Public License
6
  as published by the Free Software Foundation; either version 2
7
  of the License, or (at your option) any later version.
8
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18
  $Id: hp3300c.h,v 1.24 2002/11/04 23:48:32 bertrik Exp $
19
*/
20
21
/*
22
    Core HP3300c functions.
23
*/
24
25
26
#ifndef _HP3300C_H_
27
#define _HP3300C_H_
28
29
#include <unistd.h>
30
31
#include "mytypes.h"
32
#include "hp3300c_xfer.h"   /* for EScannerModel */
33
34
#define HP3300C_RIGHT  330
35
#define HP3300C_TOP    452
36
#define HP3300C_BOTTOM (HP3300C_TOP + 14200UL)
37
38
#define HW_PIXELS   5300    /* number of pixels supported by hardware */
39
#define HW_DPI      600     /* horizontal resolution of hardware */
40
#define HW_LPI      1200    /* vertical resolution of hardware */
41
42
43
typedef struct {
44
  int           iXferHandle;    /* handle used for data transfer to HW */
45
  int           iTopLeftX;      /* in mm */
46
  int           iTopLeftY;      /* in mm */
47
  int           iSensorSkew;    /* in units of 1/1200 inch */
48
  int           iSkipLines;     /* lines of garbage to skip */
49
  bool          fReg07;         /* NIASH00019 */
50
  bool          fGamma16;       /* if TRUE, gamma entries are 16 bit */
51
  int           iExpTime;
52
  bool          iReversedHead;  /* Head is reversed */
53
  int           iBufferSize;    /* Size of internal scan buffer */
54
  EScannerModel eModel;
55
} THWParams;
56
57
58
typedef struct {
59
  int   iDpi;         /* horizontal resolution */
60
  int   iLpi;         /* vertical resolution */
61
  int   iTop;         /* in HW coordinates */
62
  int   iLeft;        /* in HW coordinates */
63
  int   iWidth;       /* pixels */
64
  int   iHeight;      /* lines */
65
  int   iBottom;
66
67
  int   fCalib;       /* if TRUE, disable backtracking? */
68
} TScanParams;
69
70
71
typedef struct {
72
  /* transfer buffer */
73
  byte  *pabXferBuf;
74
  int   iCurLine, iBytesPerLine, iLinesPerXferBuf;
75
  int   iSkipLines;
76
  /* circular buffer */
77
  byte  *pabCircBuf;
78
  int   iLinesPerCircBuf;
79
  int   iRedLine, iGrnLine, iBluLine;
80
  /* current line buffer */
81
  byte  *pabLineBuf;
82
  int   iBytesLeft;
83
} TDataPipe;
84
85
86
int   Hp3300cOpen(THWParams *pHWParams, char *pszName);
87
void  Hp3300cClose(THWParams *pHWParams);
88
89
void  DumpHex(byte *pabData, int iLen, int iWidth);
90
91
void  ScanLines(FILE *pFile, TScanParams *pParams, THWParams *pHWParams);
92
bool  SimpleCalib(THWParams *pHWPar, byte *pabCalibTable);
93
94
bool  GetLamp(THWParams *pHWParams, bool *pfLampIsOn);
95
bool  SetLamp(THWParams *pHWParams, bool fLampOn);
96
97
bool  InitScan(TScanParams *pParams, THWParams *pHWParams);
98
void  FinishScan(THWParams *pHWParams);
99
100
void  CalcGamma(byte *pabTable, double Gamma);
101
void  WriteGammaCalibTable( byte *pabGammaR, byte *pabGammaG, byte *pabGammaB,
102
                            byte *pabCalibTable, int iGain, int iOffset,
103
                            THWParams *pHWPar);
104
105
void  CircBufferInit(int iHandle, TDataPipe *p, int iBytesPerLine,
106
                     int iMisAlignment, bool iReversedHead);
107
void  CircBufferGetLine(int iHandle, TDataPipe *p, byte *pabLine,
108
                        bool iReversedHead);
109
void  CircBufferExit(TDataPipe *p);
110
111
112
#endif /* NO _HP3300C_H_ */
113
(-)sane-backends-1.0.12/backend/hp3300c_ieee1284.c (+229 lines)
Line 0 Link Here
1
/*
2
  Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
3
4
  This program is free software; you can redistribute it and/or
5
  modify it under the terms of the GNU General Public License
6
  as published by the Free Software Foundation; either version 2
7
  of the License, or (at your option) any later version.
8
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18
  $Id: hp3300c_ieee1284.c,v 1.8 2002/11/19 22:58:31 bertrik Exp $
19
*/
20
21
/*
22
    Provides a simple interface to read and write data from the scanner,
23
    without any knowledge whether it's a parallel or USB scanner
24
*/
25
26
#ifdef LIBIEEE1284_SUPPORT
27
28
#include "mytypes.h"
29
#include "hp3300c_xfer.h"
30
31
#include "ieee1284.h"
32
33
34
void
35
ParInit(TFnReportDevice *pfnReportDevice)
36
{
37
  int i;
38
  static char  abDeviceId[256];
39
  struct parport *pMyPort;
40
  struct parport_list mylist;
41
  TScannerModel *pModel;
42
43
  pMyPort = (struct parport *)-1;
44
45
  ieee1284_find_ports(&mylist, 0);
46
  DBG(DBG_MSG, "Found %d parallel ports:\n", mylist.portc);
47
48
  for (i = 0; i < mylist.portc; i++) {
49
    pMyPort = mylist.portv[i];
50
    DBG(DBG_MSG, "Port %3d : %s\n", i, pMyPort->name);
51
52
    /* try to get a device id, no daisy chain assumed */
53
    memset(abDeviceId, 0, sizeof(abDeviceId));
54
    if (ieee1284_get_deviceid(pMyPort, -1, 0, abDeviceId, sizeof(abDeviceId) - 1) >= 0) {
55
      DBG(DBG_MSG, "Device ID: %s\n", abDeviceId + 2);
56
    }
57
58
    /* hack: for now just let pModel to the first entry of ScannerModels */
59
    pModel = ScannerModels;
60
61
    pfnReportDevice(pModel, (char *)pMyPort->name);
62
  }
63
  ieee1284_free_ports(&mylist);
64
}
65
66
67
static int
68
ParOpen(char *pszName, EScannerModel *peModel)
69
{
70
  struct parport *pMyPort;
71
  struct parport_list mylist;
72
  int i, iCaps, iResult;
73
74
  iResult = -1;
75
  ieee1284_find_ports(&mylist, 0);
76
  for (i = 0; i < mylist.portc; i++) {
77
    pMyPort = mylist.portv[i];
78
    if (strcmp(pMyPort->name, pszName) == 0) {
79
      /* open port non-exclusively (exclusive won't work?) */
80
      if (ieee1284_open(pMyPort, 0, &iCaps) != E1284_OK) {
81
        DBG(DBG_MSG, "Failed to open %s\n", pMyPort->name);
82
        break;
83
      }
84
85
      /* claim the port. We're abusing a bit here because a claim should be
86
        reasonably short, while we keep the port claimed continuously.
87
      */
88
      if (ieee1284_claim(pMyPort) != E1284_OK) {
89
        DBG(DBG_MSG, "Failed to claim %s\n", pMyPort->name);
90
        ieee1284_close(pMyPort);
91
        break;
92
      }
93
94
      DBG(DBG_MSG, "Successfully claimed %s, capabilities %04X\n", pMyPort->name,
95
        iCaps);
96
      iResult = (int)pMyPort;
97
      break;
98
    }
99
  }
100
  ieee1284_free_ports(&mylist);
101
  return iResult;
102
}
103
104
105
static void
106
ParClose(int iHandle)
107
{
108
  struct parport *pMyPort;
109
110
  if (iHandle < 0) {
111
    DBG(DBG_ERR, "ParExit: nothing to close\n");
112
    return;
113
  }
114
115
  pMyPort = (struct parport *)iHandle;
116
117
  ieee1284_release(pMyPort);
118
  ieee1284_close(pMyPort);
119
}
120
121
122
static void ParWriteReg(int iHandle, byte bReg, byte bData)
123
{
124
  int iRet;
125
  struct parport *pMyPort;
126
127
  pMyPort = (struct parport *)iHandle;
128
129
  switch (bReg) {
130
  case EPP_ADDR:
131
    iRet = ieee1284_epp_write_addr(pMyPort, 0, &bData, 1);
132
    if (iRet < 0) {
133
      DBG(DBG_ERR, "ieee1284_epp_write_addr failed (%d)\n", iRet);
134
    }
135
    break;
136
  case EPP_DATA_WRITE:
137
    iRet = ieee1284_epp_write_data(pMyPort, 0, &bData, 1);
138
    if (iRet < 0) {
139
      DBG(DBG_ERR, "ieee1284_epp_write_data failed (%d)\n", iRet);
140
    }
141
    break;
142
  case SPP_CONTROL:
143
    /* TODO: check direction bit and explicitly set direction */
144
    ieee1284_write_control(pMyPort, bData);
145
    break;
146
  case SPP_DATA:
147
    ieee1284_write_data(pMyPort, bData);
148
    break;
149
  default:
150
    DBG(DBG_ERR, "Invalid write function requested (%d)\n", bReg);
151
    break;
152
  }
153
}
154
155
156
static void
157
ParReadReg(int iHandle, byte bReg, byte *pbData)
158
{
159
  int iRet;
160
  struct parport *pMyPort;
161
162
  pMyPort = (struct parport *)iHandle;
163
164
  switch (bReg) {
165
  case EPP_ADDR:
166
    iRet = ieee1284_epp_read_addr(pMyPort, 0, pbData, 1);
167
    if (iRet < 0) {
168
      DBG(DBG_ERR, "ieee1284_epp_read_addr failed (%d)\n", iRet);
169
    }
170
    break;
171
  case EPP_DATA_READ:
172
    iRet = ieee1284_epp_read_data(pMyPort, 0, pbData, 1);
173
    if (iRet < 0) {
174
      DBG(DBG_ERR, "ieee1284_epp_read_data failed (%d)\n", iRet);
175
    }
176
    break;
177
  case SPP_CONTROL:
178
    *pbData = ieee1284_read_control(pMyPort);
179
    break;
180
  case SPP_DATA:
181
    *pbData = ieee1284_read_data(pMyPort);
182
    break;
183
  default:
184
    DBG(DBG_ERR, "Invalid read function requested (%d)\n", bReg);
185
    break;
186
  }
187
}
188
189
190
static void
191
ParWriteBulk(int iHandle, byte *pabData, int iSize)
192
{
193
  int iRet;
194
  struct parport *pMyPort;
195
196
  pMyPort = (struct parport *)iHandle;
197
  iRet = ieee1284_epp_write_data(pMyPort, 0, pabData, iSize);
198
  if (iRet < 0) {
199
    DBG(DBG_ERR, "ieee1284_epp_write_data failed (%d)\n", iRet);
200
  }
201
}
202
203
204
static void
205
ParReadBulk(int iHandle, byte *pabData, int iSize)
206
{
207
  int iRet;
208
  struct parport *pMyPort;
209
210
  pMyPort = (struct parport *)iHandle;
211
  iRet = ieee1284_epp_read_data(pMyPort, 0, pabData, iSize);
212
  if (iRet < 0) {
213
    DBG(DBG_ERR, "ieee1284_epp_write_data failed (%d)\n", iRet);
214
  }
215
}
216
217
218
XferModule IEEE1284Dev = {
219
    "LibIEEE1284 parallel port",
220
    ParInit,
221
    ParOpen,
222
    ParClose,
223
    ParWriteReg,
224
    ParReadReg,
225
    ParWriteBulk,
226
    ParReadBulk
227
};
228
229
#endif /* LIBIEEE1284_SUPPORT */
(-)sane-backends-1.0.12/backend/hp3300c_saneiusb.c (+191 lines)
Line 0 Link Here
1
/*
2
  Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
3
4
  This program is free software; you can redistribute it and/or
5
  modify it under the terms of the GNU General Public License
6
  as published by the Free Software Foundation; either version 2
7
  of the License, or (at your option) any later version.
8
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18
  $Id: hp3300c_saneiusb.c,v 1.9 2002/11/12 21:24:43 bertrik Exp $
19
*/
20
21
/*
22
  This is the sanei_usb transfer method
23
*/
24
25
#include "mytypes.h"
26
27
#include <stdio.h>     /* printf */
28
#include <sane/sanei_usb.h>
29
30
#include "hp3300c_xfer.h"
31
32
33
static TFnReportDevice *_pfnReportDevice;
34
static TScannerModel *_pModel;
35
36
37
static void _SaneiUsbWriteControl(int fd, byte bValue, byte *pabData, int iSize)
38
{
39
  sanei_usb_control_msg(fd,
40
                        USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
41
                        (iSize > 1) ? 0x04 : 0x0C,
42
                        bValue,
43
                        0,
44
                        iSize,
45
                        pabData);
46
}
47
48
49
static void _SaneiUsbReadControl(int fd, byte bValue, byte *pabData, int iSize)
50
{
51
  sanei_usb_control_msg(fd,
52
                        USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
53
                        (iSize > 1) ? 0x04 : 0x0C,
54
                        bValue,
55
                        0,
56
                        iSize,
57
                        pabData);
58
}
59
60
61
/* callback for sanei_usb_attach_matching_devices */
62
static SANE_Status _AttachUsb(SANE_String_Const devname)
63
{
64
  DBG(DBG_MSG, "_AttachUsb: found %s\n", devname);
65
66
  _pfnReportDevice(_pModel, (char *)devname);
67
68
  return SANE_STATUS_GOOD;
69
}
70
71
72
static void UsbInit(TFnReportDevice *pfnReportDevice)
73
{
74
  TScannerModel *pModels = ScannerModels;
75
76
  sanei_usb_init();
77
  _pfnReportDevice = pfnReportDevice;
78
79
  /* loop over all scanner models */
80
  while (pModels->pszName != NULL) {
81
    DBG(DBG_MSG, "Looking for %s...\n", pModels->pszName);
82
    _pModel = pModels;
83
    if (sanei_usb_find_devices((SANE_Int)pModels->iVendor,
84
      (SANE_Int)pModels->iProduct, _AttachUsb) != SANE_STATUS_GOOD) {
85
86
      DBG(DBG_ERR, "Error invoking sanei_usb_find_devices");
87
      break;
88
    }
89
    pModels++;
90
  }
91
}
92
93
94
static int UsbOpen(char *pszName, EScannerModel *peModel)
95
{
96
  SANE_Status status;
97
  SANE_Word   vendor, product;
98
  int fd;
99
  TScannerModel *pModel;
100
101
  DBG(DBG_MSG, "Trying to open %s...\n", pszName);
102
  
103
  status = sanei_usb_open(pszName, &fd);
104
  if (status != SANE_STATUS_GOOD) {
105
    return -1;
106
  }
107
108
  status = sanei_usb_get_vendor_product(fd, &vendor, &product);
109
  if (status == SANE_STATUS_GOOD) {
110
    MatchUsbDevice(vendor, product, &pModel);
111
    *peModel = pModel->eModel;
112
  }
113
114
  return fd;
115
}
116
117
118
static void UsbClose(int fd)
119
{
120
  /* close usb device */
121
  if (fd != -1) {
122
    sanei_usb_close(fd);
123
  }
124
}
125
126
127
static void UsbWriteReg(int fd, byte bReg, byte bData)
128
{
129
  _SaneiUsbWriteControl(fd, bReg, &bData, 1);
130
}
131
132
133
static void UsbReadReg(int fd, byte bReg, byte *pbData)
134
{
135
  _SaneiUsbReadControl(fd, bReg, pbData, 1);
136
}
137
138
139
static void UsbWriteBulk(int fd, byte *pabData, int iSize)
140
{
141
  /*  byte  abSetup[8] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
142
    HP3400 probably needs 0x01, 0x01 */
143
  byte  abSetup[8] = {0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
144
  size_t size;
145
146
  if (fd == -1) {
147
    return;
148
  }
149
150
  abSetup[4] = (iSize) & 0xFF;
151
  abSetup[5] = (iSize >> 8) & 0xFF;
152
  _SaneiUsbWriteControl(fd, USB_SETUP, abSetup, 8);
153
154
  size = iSize;
155
  if (sanei_usb_write_bulk(fd, pabData, &size) != SANE_STATUS_GOOD) {
156
    DBG(DBG_ERR, "ERROR: Bulk write failed\n");
157
  }
158
}
159
160
161
static void UsbReadBulk(int fd, byte *pabData, int iSize)
162
{
163
  byte  abSetup[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
164
  size_t size;
165
166
  if (fd == -1) {
167
    return;
168
  }
169
170
  abSetup[4] = (iSize) & 0xFF;
171
  abSetup[5] = (iSize >> 8) & 0xFF;
172
  _SaneiUsbWriteControl(fd, USB_SETUP, abSetup, 8);
173
174
  size = iSize;
175
  if (sanei_usb_read_bulk(fd, pabData, &size) != SANE_STATUS_GOOD) {
176
    DBG(DBG_ERR, "ERROR: Bulk read failed\n");
177
  }
178
}
179
180
181
XferModule SaneiUsbDev = {
182
    "Sanei_USB",
183
    UsbInit,
184
    UsbOpen,
185
    UsbClose,
186
    UsbWriteReg,
187
    UsbReadReg,
188
    UsbWriteBulk,
189
    UsbReadBulk
190
};
191
(-)sane-backends-1.0.12/backend/hp3300c_uscanner.c (+234 lines)
Line 0 Link Here
1
/*
2
  Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
3
4
  This program is free software; you can redistribute it and/or
5
  modify it under the terms of the GNU General Public License
6
  as published by the Free Software Foundation; either version 2
7
  of the License, or (at your option) any later version.
8
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18
  $Id: hp3300c_uscanner.c,v 1.4 2002/11/27 23:24:10 saperski Exp $
19
*/
20
21
/*
22
    Provides a simple interface to read and write data from the scanner,
23
    without any knowledge whether it's a parallel or USB scanner
24
*/
25
26
#ifdef USCANNER_SUPPORT
27
28
#include "hp3300c_xfer.h"
29
30
#include "mytypes.h"
31
32
#include <unistd.h>    /* read, open, write */
33
#include <fcntl.h>     /* open */
34
#include <stdio.h>     /* printf */
35
#include <errno.h>     /* better error reports */
36
#include <string.h>    /* better error reports */
37
#include <sys/ioctl.h>
38
#include <sys/stat.h>
39
#include <limits.h>
40
41
#include <dev/usb/usb.h>
42
43
44
/************************************************************************
45
  USB transfer routines implemented with uscanner calls
46
************************************************************************/
47
48
#define	MAX_DEV_TRY	16
49
50
static void
51
uscannerInit(TFnReportDevice *pfnReportDevice)
52
{
53
	struct usb_device_info usb_info;
54
	TScannerModel *pModel;
55
	struct stat fs;
56
	char	devname[PATH_MAX];
57
	int	i, fd, rc;
58
59
	/* open scanner's device file */
60
	for (rc = -1, i = 0; rc < 0  && i < MAX_DEV_TRY; i++) {
61
	     snprintf(devname, PATH_MAX, "/dev/uscanner%d", i);
62
	     rc = stat(devname, &fs);
63
             if (rc == 0) {
64
                 if ((fs.st_mode & S_IFCHR) == 0 ) {
65
     	             DBG(DBG_ERR, "Not a characted device: %s\n", devname);
66
                     rc = -1;
67
	         }
68
	     } else 
69
                 if (errno != ENOENT) 
70
     	             DBG(DBG_ERR, "Error accessing %s: %s\n", devname, strerror(errno));
71
72
	}
73
	if (rc < 0) {
74
	    DBG(DBG_ERR, "Cannot open any scanner device (/dev/uscanner*).\n");
75
	    return;
76
	}
77
	if ((fd = open(devname, O_RDWR)) >= 0) {
78
	    if (ioctl(fd, USB_GET_DEVICEINFO, &usb_info) >= 0) {
79
	        DBG(DBG_MSG, "VendorId %s (0x%04X), ProductId %s (0x%04X)\n",
80
	            usb_info.udi_vendor, usb_info.udi_vendorNo,
81
	            usb_info.udi_product, usb_info.udi_productNo);
82
	        if (MatchUsbDevice(usb_info.udi_vendorNo, 
83
	                           usb_info.udi_productNo, &pModel)) 
84
	            pfnReportDevice(pModel, devname);
85
	    } else 
86
	         DBG(DBG_ERR, "USB_GET_DEVICEINFO not supported, check version of the uscanner driver");
87
	} else
88
	         DBG(DBG_ERR, "Cannot open %s: %s", devname, strerror(errno));
89
	close(fd);
90
}
91
92
static int
93
uscannerOpen(char *devname, EScannerModel *peModel)
94
{
95
	int fd, rc = -1;
96
  	struct usb_device_info usb_info;
97
	TScannerModel *pModel;
98
	
99
	fd = open(devname, O_RDWR);
100
	if (fd > 0) 
101
	    if (ioctl(fd, USB_GET_DEVICEINFO, &usb_info) >= 0) 
102
	        if (MatchUsbDevice(usb_info.udi_vendorNo, 
103
	                 usb_info.udi_productNo, &pModel))  {
104
	            *peModel = pModel->eModel;
105
	            rc = fd;
106
		} else 
107
		    DBG(DBG_ERR, "Cannot match device at %s\n", devname);
108
	    else 
109
		    DBG(DBG_ERR, "USB_GET_INFO failed on %s: %s\n", devname, strerror(errno));
110
	else 
111
		    DBG(DBG_ERR, "Cannot open %s: %s\n", devname, strerror(errno));
112
113
	return fd;
114
}
115
116
static void
117
uscannerExit(int fd)
118
{
119
  /* close usb device */
120
  if (fd != -1) {
121
    close(fd);
122
  }
123
}
124
125
static void
126
_uscannerReadControl(int fd, byte bValue, byte *pabData, int iSize)
127
{
128
  struct usb_ctl_request req;
129
130
  if (fd < 0) {
131
    return;
132
  }
133
134
  req.ucr_addr = 0;
135
  req.ucr_data = pabData;
136
  req.ucr_flags = 0;
137
  req.ucr_actlen = 0;
138
  req.ucr_request.bmRequestType = UT_READ_VENDOR_DEVICE;
139
  req.ucr_request.bRequest      = (iSize > 1) ? 0x04 : 0x0C;
140
  USETW(req.ucr_request.wValue,  bValue);
141
  USETW(req.ucr_request.wIndex,  0);
142
  USETW(req.ucr_request.wLength, iSize);
143
144
  if (fd != -1) {
145
    ioctl(fd, USB_DO_REQUEST, &req);
146
  }
147
}
148
149
150
static void
151
_uscannerWriteControl(int fd, byte bValue, byte *pabData, int iSize)
152
{
153
  struct usb_ctl_request req;
154
155
  if (fd < 0) {
156
    return;
157
  }
158
159
  req.ucr_addr = 0;
160
  req.ucr_data = pabData;
161
  req.ucr_flags = 0;
162
  req.ucr_actlen = 0;
163
  req.ucr_request.bmRequestType = UT_WRITE_VENDOR_DEVICE;
164
  req.ucr_request.bRequest      = (iSize > 1) ? 0x04 : 0x0C;
165
  USETW(req.ucr_request.wValue,  bValue);
166
  USETW(req.ucr_request.wIndex,  0);
167
  USETW(req.ucr_request.wLength, iSize);
168
169
  if (fd != -1) {
170
    ioctl(fd, USB_DO_REQUEST, &req);
171
  }
172
}
173
174
static void
175
uscannerWriteReg(int fd, byte bReg, byte bData)
176
{
177
  _uscannerWriteControl(fd, bReg, &bData, 1);
178
}
179
180
181
static void
182
uscannerReadReg(int fd, byte bReg, byte *pbData)
183
{
184
  _uscannerReadControl(fd, bReg, pbData, 1);
185
}
186
187
188
static void
189
uscannerWriteBulk(int fd, byte *pabData, int iSize)
190
{
191
  byte  abSetup[8] = {0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
192
193
  if (fd < 0) {
194
    return;
195
  }
196
197
  abSetup[4] = (iSize) & 0xFF;
198
  abSetup[5] = (iSize >> 8) & 0xFF;
199
  _uscannerWriteControl(fd, USB_SETUP, abSetup, 8);
200
  if (write(fd, pabData, iSize) != iSize) {
201
    DBG(DBG_ERR, "ERROR: Bulk Write failed\n");
202
  }
203
}
204
205
206
static void
207
uscannerReadBulk(int fd, byte *pabData, int iSize)
208
{
209
  byte  abSetup[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
210
211
  if (fd < 0) {
212
    return;
213
  }
214
215
  abSetup[4] = (iSize) & 0xFF;
216
  abSetup[5] = (iSize >> 8) & 0xFF;
217
  _uscannerWriteControl(fd, USB_SETUP, abSetup, 8);
218
  if (read(fd, pabData, iSize) != iSize) {
219
    DBG(DBG_ERR, "ERROR: Bulk read failed\n");
220
  }
221
}
222
223
XferModule uscannerDev = {
224
  "BSD uscanner kernel module",
225
  uscannerInit,
226
  uscannerOpen,
227
  uscannerExit,
228
  uscannerWriteReg,
229
  uscannerReadReg,
230
  uscannerWriteBulk,
231
  uscannerReadBulk
232
};
233
234
#endif /* USCANNER_SUPPORT */
(-)sane-backends-1.0.12/backend/hp3300c_xfer.c (+275 lines)
Line 0 Link Here
1
/*
2
  Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
3
4
  This program is free software; you can redistribute it and/or
5
  modify it under the terms of the GNU General Public License
6
  as published by the Free Software Foundation; either version 2
7
  of the License, or (at your option) any later version.
8
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18
  $Id: hp3300c_xfer.c,v 1.31 2003/01/11 13:35:18 bertrik Exp $
19
*/
20
21
/*
22
    Provides a simple interface to read and write data from the scanner,
23
    without any knowledge whether it's a parallel or USB scanner
24
*/
25
26
#include "mytypes.h"
27
28
#include <unistd.h>    /* read, open, write */
29
#include <fcntl.h>     /* open */
30
#include <stdio.h>     /* printf */
31
#include <errno.h>     /* better error reports */
32
#include <string.h>    /* better error reports */
33
#include <stdlib.h>    /* malloc(), free() on FreeBSD */
34
35
#include "hp3300c_xfer.h"
36
37
#define MAX_XFER_MODULES 5
38
39
static XferModule *_aXferModules[MAX_XFER_MODULES];
40
static int        _iNrXferModules;
41
42
/* list of supported models */
43
TScannerModel ScannerModels[] = {
44
  {"Hewlett-Packard", "ScanJet 3300C",  0x3F0, 0x205, eHp3300c},
45
  {"Hewlett-Packard", "ScanJet 3400C",  0x3F0, 0x405, eHp3400c},
46
  {"Hewlett-Packard", "ScanJet 4300C",  0x3F0, 0x305, eHp4300c},
47
  {"Agfa",            "Snapscan Touch", 0x6BD, 0x100, eAgfaTouch},
48
/* last entry all zeros */
49
  {0, 0, 0, 0, 0}
50
};
51
52
53
/*
54
  MatchUsbDevice
55
  ==============
56
    Matches a given USB vendor and product id against a list of
57
    supported scanners.
58
59
  IN  iVendor   USB vendor ID
60
      iProduct  USB product ID
61
  OUT *ppModel  Pointer to TScannerModel structure
62
63
  Returns TRUE if a matching USB scanner was found
64
*/
65
bool MatchUsbDevice(int iVendor, int iProduct, TScannerModel **ppModel)
66
{
67
  TScannerModel *pModels = ScannerModels;
68
69
  DBG(DBG_MSG, "Matching USB device 0x%04X-0x%04X ... ", iVendor, iProduct);
70
  while (pModels->pszName != NULL) {
71
    if ((pModels->iVendor == iVendor) && (pModels->iProduct == iProduct)) {
72
      DBG(DBG_MSG, "found %s %s\n", pModels->pszVendor, pModels->pszName);
73
      *ppModel = pModels;
74
      return TRUE;
75
    }
76
    /* next model to match */
77
    pModels++;
78
  }
79
  DBG(DBG_MSG, "nothing found\n");
80
  return FALSE;
81
}
82
83
/************************************************************************
84
  Public functions
85
************************************************************************/
86
87
88
/*
89
  Hp3300cXferRegisterModule
90
  =========================
91
    installs a transfer method
92
93
  IN    pXferModule   Module to registers
94
95
  Returns a negative number when an error occurred.
96
*/
97
int Hp3300cXferRegisterModule(XferModule *pXferModule)
98
{
99
  DBG(DBG_MSG, "Registering transfer method %d: %s\n", _iNrXferModules, pXferModule->pszName);
100
101
  if (_iNrXferModules >= MAX_XFER_MODULES) {
102
    DBG(DBG_ERR, "Max. number of installed transfer methods reached\n");
103
    return -1;
104
  }
105
  _aXferModules[_iNrXferModules++] = pXferModule;
106
107
  return 0;
108
}
109
110
111
/*
112
  Hp3300cXferInit
113
  ===============
114
    Initialises all registered data transfer modules, which causes
115
    them to report any devices found through the pfnReport callback.
116
    
117
  IN  pfnReport Function to call to report a transfer device
118
*/
119
void Hp3300cXferInit(TFnReportDevice *pfnReport)
120
{
121
  int i;
122
123
  for (i = 0; i < _iNrXferModules; i++) {
124
    _aXferModules[i]->mfnInit(pfnReport);
125
  }
126
}
127
128
129
int  Hp3300cXferOpen  (char *pszName, EScannerModel *peModel)
130
{
131
  TXferDev *pDev;
132
  XferModule *pMod;
133
  int i, iHandle;
134
135
  DBG(DBG_MSG, "Hp3300cXferOpen '%s'\n", pszName);
136
137
  /* try each method */
138
  for (i = 0; i < _iNrXferModules; i++) {
139
    pMod = _aXferModules[i];
140
    DBG(DBG_MSG, "probing %s\n", pMod->pszName);
141
    *peModel = eUnknownModel;
142
    iHandle = pMod->mfnOpen(pszName, peModel);
143
    if (iHandle >= 0) {
144
      pDev = malloc(sizeof(TXferDev));
145
      pDev->iXferDev = pMod;
146
      pDev->iHandle = iHandle;
147
      return (int)pDev;
148
    }
149
  }
150
  return -1;
151
}
152
153
154
void Hp3300cXferClose(int iHandle)
155
{
156
  TXferDev *pDev;
157
158
  if (iHandle <= 0) {
159
    return;
160
  }
161
  pDev = (TXferDev *)iHandle;
162
163
  /* deinit the driver */
164
  if (pDev->iHandle >= 0) {
165
    pDev->iXferDev->mfnExit(pDev->iHandle);
166
    free((void *)iHandle);
167
  }
168
}
169
170
171
void Hp3300cRegWrite(int iHandle, byte bReg, byte bData)
172
{
173
  TXferDev *pDev;
174
175
  if (iHandle <= 0) {
176
    return;
177
  }
178
  pDev = (TXferDev *)iHandle;
179
180
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL,    0x14);
181
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, EPP_ADDR,       bReg);
182
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL,    0x14);
183
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, EPP_DATA_WRITE, bData);
184
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL,    0x14);
185
}
186
187
188
void Hp3300cRegRead(int iHandle, byte bReg, byte *pbData)
189
{
190
  TXferDev *pDev;
191
192
  if (iHandle <= 0) {
193
    return;
194
  }
195
  pDev = (TXferDev *)iHandle;
196
197
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL,    0x14);
198
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, EPP_ADDR,       bReg);
199
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL,    0x34);
200
  pDev->iXferDev->mfnReadReg (pDev->iHandle, EPP_DATA_READ,  pbData);
201
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL,    0x14);
202
}
203
204
205
void Hp3300cBulkWrite(int iHandle, byte *pabBuf, int iSize)
206
{
207
  TXferDev *pDev;
208
209
  if (iHandle <= 0) {
210
    return;
211
  }
212
  pDev = (TXferDev *)iHandle;
213
214
  /* select scanner register 0x24 */
215
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL,    0x14);
216
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, EPP_ADDR,       0x24);
217
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL,    0x14);
218
  /* do the bulk write */
219
  pDev->iXferDev->mfnWriteBulk(pDev->iHandle, pabBuf, iSize);
220
}
221
222
223
void Hp3300cBulkRead(int iHandle, byte *pabBuf, int iSize)
224
{
225
  TXferDev *pDev;
226
227
  if (iHandle <= 0) {
228
    return;
229
  }
230
  pDev = (TXferDev *)iHandle;
231
232
  /* select scanner register 0x24 */
233
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL,    0x14);
234
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, EPP_ADDR,       0x24);
235
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL,    0x14);
236
  /* do the bulk read */
237
  pDev->iXferDev->mfnReadBulk(pDev->iHandle, pabBuf, iSize);
238
}
239
240
241
void Hp3300cWakeup(int iHandle)
242
{
243
  TXferDev *pDev;
244
  byte  abMagic[] = { 0xA0, 0xA8, 0x50, 0x58, 0x90, 0x98, 0xC0, 0xC8,
245
                      0x90, 0x98, 0xE0, 0xE8};
246
  int   i;
247
248
  if (iHandle <= 0) {
249
    return;
250
  }
251
  pDev = (TXferDev *)iHandle;
252
253
  /* write magic startup sequence */
254
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14);
255
  for (i = 0; i < (int)sizeof(abMagic); i++) {
256
    pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_DATA, abMagic[i]);
257
  }
258
259
  /* write 0x04 to scanner register 0x00 the hard way */
260
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_DATA,    0x00);
261
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14);
262
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x15);
263
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x1D);
264
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x15);
265
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14);
266
267
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_DATA,    0x04);
268
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14);
269
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x15);
270
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x17);
271
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x15);
272
  pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14);
273
}
274
275
(-)sane-backends-1.0.12/backend/hp3300c_xfer.h (+132 lines)
Line 0 Link Here
1
/*
2
  Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
3
4
  This program is free software; you can redistribute it and/or
5
  modify it under the terms of the GNU General Public License
6
  as published by the Free Software Foundation; either version 2
7
  of the License, or (at your option) any later version.
8
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18
  $Id: hp3300c_xfer.h,v 1.16 2002/11/04 23:48:33 bertrik Exp $
19
*/
20
21
/*
22
    Provides a simple interface to read and write data from the scanner,
23
    without any knowledge whether it's a parallel or USB scanner
24
*/
25
26
#ifndef _HP3300C_XFER_H_
27
#define _HP3300C_XFER_H_
28
29
#include "mytypes.h"
30
#include <stdio.h> /* for FILE * */
31
32
33
/* register codes for the USB - IEEE1284 bridge */
34
#define USB_SETUP       0x82
35
#define EPP_ADDR        0x83
36
#define EPP_DATA_READ   0x84
37
#define EPP_DATA_WRITE  0x85
38
#define SPP_STATUS      0x86
39
#define SPP_CONTROL     0x87
40
#define SPP_DATA        0x88
41
42
43
typedef enum {
44
  eUnknownModel = 0,
45
  eHp3300c,
46
  eHp3400c,
47
  eHp4300c,
48
  eAgfaTouch
49
} EScannerModel;
50
51
52
typedef struct {
53
  char          *pszVendor;
54
  char          *pszName;
55
  int           iVendor;
56
  int           iProduct;
57
  EScannerModel eModel;
58
} TScannerModel;
59
60
61
typedef int (TFnReportDevice)(TScannerModel *pModel, char *pszDeviceName);
62
63
/* function pointer definitions */
64
/*
65
  The TFnInit function get passed a TFnReportDevice function pointer which is
66
  called for each scanner device.
67
  The TFnOpen function can then be called with one of the names as an argument
68
  and returns a handle > 0 if the open was successful.
69
*/
70
typedef void (TFnInit)(TFnReportDevice *pfnReportDevice);
71
typedef int  (TFnOpen)(char *pszDeviceName, EScannerModel *peModel);
72
typedef void (TFnWriteReg)(int iHandle, byte bReg, byte bData);
73
typedef void (TFnReadReg)(int iHandle, byte bReg, byte *pbData);
74
typedef void (TFnWriteBulk)(int iHandle, byte *pabBuf, int iSize);
75
typedef void (TFnReadBulk)(int iHandle, byte *pabBuf, int iSize);
76
typedef void (TFnExit)(int iHandle);
77
78
79
typedef struct {
80
  char          *pszName;
81
  TFnInit       *mfnInit;
82
  TFnOpen       *mfnOpen;
83
  TFnExit       *mfnExit;
84
  TFnWriteReg   *mfnWriteReg;
85
  TFnReadReg    *mfnReadReg;
86
  TFnWriteBulk  *mfnWriteBulk;
87
  TFnReadBulk   *mfnReadBulk;
88
} XferModule;
89
90
91
typedef struct {
92
  int        iHandle;
93
  XferModule *iXferDev;
94
} TXferDev;
95
96
97
/* Creates our own DBG definitions, externs are define in main.c*/
98
#ifndef WITH_NIASH
99
#define DBG fprintf
100
extern FILE * DBG_MSG;
101
extern FILE * DBG_ERR;
102
extern FILE * BG_ASSERT;
103
#endif /* NO WITH_NIASH */
104
105
106
/* USB device file name */
107
extern char * usb_devfile;
108
109
110
/* list of supported models, the actual list is in hp3300c_xfer.c */
111
extern TScannerModel ScannerModels[];
112
113
114
/*  The number returned by Hp3300cXferInit is a handle. This handle needs to
115
    be passed to all other transfer functions.
116
    Internally it is a pointer to structure containg function pointers
117
 */
118
int  Hp3300cXferRegisterModule(XferModule *pXferModule);
119
120
void Hp3300cXferInit  (TFnReportDevice *pfnReport);
121
int  Hp3300cXferOpen  (char *pszName, EScannerModel *peModel);
122
void Hp3300cXferClose (int iXferHandle);
123
124
void Hp3300cRegWrite  (int iXferHandle, byte bReg, byte bData);
125
void Hp3300cRegRead   (int iXferHandle, byte bReg, byte *pbData);
126
void Hp3300cBulkWrite (int iXferHandle, byte *pabBuf, int iSize);
127
void Hp3300cBulkRead  (int iXferHandle, byte *pabBuf, int iSize);
128
void Hp3300cWakeup    (int iXferHandle);
129
130
bool MatchUsbDevice(int iVendor, int iProduct, TScannerModel **ppeModel);
131
132
#endif /* _HP3300C_XFER_H_ */
(-)sane-backends-1.0.12/backend/hp3300c_xfer_cfg.h (+75 lines)
Line 0 Link Here
1
/*
2
  Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
3
4
  This program is free software; you can redistribute it and/or
5
  modify it under the terms of the GNU General Public License
6
  as published by the Free Software Foundation; either version 2
7
  of the License, or (at your option) any later version.
8
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18
  $Id: hp3300c_xfer_cfg.h,v 1.5 2002/11/03 17:58:59 bertrik Exp $
19
*/
20
21
/*
22
  This file defines which transfer methods are compiled into the SANE backend
23
  (Linux scanner kernel module, BSD uscanner kernel module, libusb, ieee1284,
24
  dummy for scanner emulation, etc.)
25
  
26
  To disable a transfer method, comment out the corresponding #define
27
28
  #define SANEI_USB_SUPPORT
29
    USB support using the SANE builtin functions from sanei_usb.h
30
    sanei_usb.h version 1.0.7 supports Linux only (in fact it uses
31
    the scanner kernel module internally).
32
33
  #define LINUX_USB_SUPPORT
34
    USB support using the 'scanner' kernel module for Linux.
35
    You need at least Linux kernel version 2.4.12 to use this.
36
37
  #define USCANNER_SUPPORT
38
    USB support using the 'uscanner' kernel module for BSD.
39
    This is obviously mutually exclusive with LINUX_USB_SUPPORT
40
41
  #define LIBUSB_SUPPORT
42
    USB support using libusb (should be platform independent)
43
    You need at least version 0.1.5 of libusb (+ devel package) to use this.
44
45
  #define LIBIEEE1284_SUPPORT
46
    Parallel port support using libieee1284 (should be platform independent).
47
    You need at least version ... of libieee1284 (+ devel package) to use this.
48
    *** This transfer method has not been tested yet ***
49
50
  #define DUMMY_SCAN_SUPPORT
51
    Dummy transfer method used for testing.
52
    This method very simply emulates a specific type of scanner.
53
54
  Any changes in this file will have no effect until you recompile & install:
55
  (in the sane-backends package, backend directory)
56
    touch niash.c
57
    make
58
    make install
59
*/
60
61
62
#define SANEI_USB_SUPPORT
63
64
/* #define LINUX_USB_SUPPORT */
65
66
/* #define USCANNER_SUPPORT */
67
68
/* #define LIBUSB_SUPPORT */
69
70
/* not tested yet */
71
/* #define LIBIEEE1284_SUPPORT */
72
73
/* not implemented yet */
74
/* #define DUMMY_SCAN_SUPPORT */
75
(-)sane-backends-1.0.12/backend/mytypes.h (+33 lines)
Line 0 Link Here
1
/*
2
	Defines my types
3
4
  $Id: mytypes.h,v 1.3 2001/12/18 03:10:41 aggression Exp $
5
*/
6
7
8
#ifndef _MYTYPES_H_
9
#define _MYTYPES_H_
10
11
#ifndef byte
12
typedef unsigned char byte;
13
#endif
14
15
#ifndef word
16
typedef int word;
17
#endif
18
19
#ifndef bool
20
typedef int bool;
21
#endif
22
23
#ifndef FALSE
24
#define FALSE 0
25
#endif
26
27
#ifndef TRUE
28
#define TRUE 1
29
#endif
30
31
#endif
32
33
(-)sane-backends-1.0.12/backend/niash.c (+869 lines)
Line 0 Link Here
1
/*
2
  Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
3
4
  This program is free software; you can redistribute it and/or
5
  modify it under the terms of the GNU General Public License
6
  as published by the Free Software Foundation; either version 2
7
  of the License, or (at your option) any later version.
8
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18
  $Id: niash.c,v 1.36 2003/03/24 19:14:47 bertrik Exp $
19
*/
20
21
/*
22
    Concept for a backend for scanners based on the NIASH chipset,
23
    such as HP3300C, HP3400C, HP4300C, Agfa Touch.
24
    Parts of this source were inspired by other backends.
25
*/
26
27
#include "sane/sane.h"
28
#include "sane/config.h"
29
#include "sane/sanei.h"
30
#include "sane/sanei_backend.h"
31
#include "sane/sanei_config.h"
32
#include "sane/saneopts.h"
33
34
#include <stdlib.h>         /* malloc, free */
35
#include <string.h>         /* memcpy */
36
#include <stdio.h>
37
38
/* definitions for debug */
39
#define BACKEND_NAME niash
40
#define BUILD 1
41
42
#define DBG_ASSERT  1
43
#define DBG_ERR     16
44
#define DBG_MSG     32
45
46
#define NIASH_CONFIG_FILE "niash.conf"
47
48
/* Just to avoid conflicts between niash backend and testtool */
49
#define WITH_NIASH 1
50
51
52
#include "hp3300c_xfer_cfg.h"
53
54
/* (source) includes for data transfer methods */
55
#include "hp3300c.c"
56
#include "hp3300c_xfer.c"
57
#include "hp3300c_saneiusb.c"
58
#if defined(LINUX_USB_SUPPORT)
59
  #include "hp3300c_linux.c"
60
#endif
61
#if defined(USCANNER_SUPPORT)
62
  #include "hp3300c_uscanner.c"
63
#endif
64
#if defined(LIBUSB_SUPPORT)
65
  #include "hp3300c_libusb.c"
66
#endif
67
#if defined(LIBIEEE1284_SUPPORT)
68
  #include "hp3300c_ieee1284.c"
69
#endif
70
71
72
#define ASSERT(cond) (!(cond) ? DBG(DBG_ASSERT, "!!! ASSERT(%S) FAILED!!!\n",STRINGIFY(cond));)
73
74
/* other definitions */
75
#define TRUE 1
76
#define FALSE 0
77
78
#define MM_TO_PIXEL(_mm_, _dpi_)    ((_mm_) * (_dpi_) / 25.4)
79
#define PIXEL_TO_MM(_pixel_, _dpi_) ((_pixel_) * 25.4 / (_dpi_))
80
81
/* Device filename for USB access */
82
char * usb_devfile = "/dev/usb/scanner0";
83
84
/* options enumerator */
85
typedef enum {
86
  optCount = 0,
87
88
  optGroupGeometry,
89
  optTLX, optTLY, optBRX, optBRY,
90
  optDPI,
91
92
  optGroupImage,
93
  optGammaTable,        /* gamma table */
94
95
  optGroupMisc,
96
  optLamp,
97
98
  optLast,
99
/* put temporarily disabled options here after optLast */
100
  optCalibrate,
101
  optGamma             /* analog gamma = single number */
102
103
} EOptionIndex;
104
105
106
typedef union {
107
  SANE_Word w;
108
  SANE_Word *wa;              /* word array */
109
  SANE_String s;
110
} TOptionValue;
111
112
113
typedef struct {
114
  SANE_Option_Descriptor  aOptions[optLast];
115
  TOptionValue            aValues[optLast];
116
117
  TScanParams             ScanParams;
118
  THWParams               HWParams;
119
120
  TDataPipe               DataPipe;
121
  int                     iLinesLeft;
122
123
  SANE_Int                aGammaTable[4096];    /* a 12-to-8 bit color lookup table */
124
125
  int                     fScanning;            /* TRUE if actively scanning */
126
  int                     fCanceled;
127
} TScanner;
128
129
130
/* linked list of SANE_Device structures */
131
typedef struct TDevListEntry {
132
  struct TDevListEntry *pNext;
133
  SANE_Device dev;
134
} TDevListEntry;
135
136
137
static TDevListEntry *_pFirstSaneDev = 0;
138
static int iNumSaneDev = 0;
139
static const SANE_Device **_pSaneDevList = 0;
140
141
142
/* option constraints */
143
static const SANE_Range rangeGammaTable = {0, 255, 1};
144
static const SANE_Int   setResolutions[] = {3, 150, 300, 600};
145
static const SANE_Range rangeGamma = {SANE_FIX(0.25), SANE_FIX(4.0),
146
 SANE_FIX(0.0)};
147
static const SANE_Range rangeXmm = {0, 220, 1};
148
static const SANE_Range rangeYmm = {0, 290, 1};
149
150
151
static void _InitOptions(TScanner *s)
152
{
153
  int i, j;
154
  SANE_Option_Descriptor *pDesc;
155
  TOptionValue *pVal;
156
157
  for (i = optCount; i < optLast; i++) {
158
159
    pDesc = &s->aOptions[i];
160
    pVal = &s->aValues[i];
161
162
    /* defaults */
163
    pDesc->name   = "";
164
    pDesc->title  = "";
165
    pDesc->desc   = "";
166
    pDesc->type   = SANE_TYPE_INT;
167
    pDesc->unit   = SANE_UNIT_NONE;
168
    pDesc->size   = sizeof(SANE_Word);
169
    pDesc->constraint_type = SANE_CONSTRAINT_NONE;
170
    pDesc->cap    = 0;
171
172
    switch (i) {
173
174
    case optCount:
175
      pDesc->title  = SANE_TITLE_NUM_OPTIONS;
176
      pDesc->desc   = SANE_DESC_NUM_OPTIONS;
177
      pDesc->cap    = SANE_CAP_SOFT_DETECT;
178
      pVal->w       = (SANE_Word)optLast;
179
      break;
180
181
    case optGroupGeometry:
182
      pDesc->title  = "Geometry";
183
      pDesc->type   = SANE_TYPE_GROUP;
184
      pDesc->size   = 0;
185
      break;
186
187
    case optTLX:
188
      pDesc->name   = SANE_NAME_SCAN_TL_X;
189
      pDesc->title  = SANE_TITLE_SCAN_TL_X;
190
      pDesc->desc   = SANE_DESC_SCAN_TL_X;
191
      pDesc->unit   = SANE_UNIT_MM;
192
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
193
      pDesc->constraint.range = &rangeXmm;
194
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
195
      pVal->w       = rangeXmm.min;
196
      break;
197
198
    case optTLY:
199
      pDesc->name   = SANE_NAME_SCAN_TL_Y;
200
      pDesc->title  = SANE_TITLE_SCAN_TL_Y;
201
      pDesc->desc   = SANE_DESC_SCAN_TL_Y;
202
      pDesc->unit   = SANE_UNIT_MM;
203
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
204
      pDesc->constraint.range = &rangeYmm;
205
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
206
      pVal->w       = rangeYmm.min;
207
      break;
208
209
    case optBRX:
210
      pDesc->name   = SANE_NAME_SCAN_BR_X;
211
      pDesc->title  = SANE_TITLE_SCAN_BR_X;
212
      pDesc->desc   = SANE_DESC_SCAN_BR_X;
213
      pDesc->unit   = SANE_UNIT_MM;
214
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
215
      pDesc->constraint.range = &rangeXmm;
216
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
217
      pVal->w       = rangeXmm.max;
218
      break;
219
220
    case optBRY:
221
      pDesc->name   = SANE_NAME_SCAN_BR_Y;
222
      pDesc->title  = SANE_TITLE_SCAN_BR_Y;
223
      pDesc->desc   = SANE_DESC_SCAN_BR_Y;
224
      pDesc->unit   = SANE_UNIT_MM;
225
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
226
      pDesc->constraint.range = &rangeYmm;
227
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
228
      pVal->w       = rangeYmm.max;
229
      break;
230
231
    case optDPI:
232
      pDesc->name   = SANE_NAME_SCAN_RESOLUTION;
233
      pDesc->title  = SANE_TITLE_SCAN_RESOLUTION;
234
      pDesc->desc   = SANE_DESC_SCAN_RESOLUTION;
235
      pDesc->unit   = SANE_UNIT_DPI;
236
      pDesc->constraint_type  = SANE_CONSTRAINT_WORD_LIST;
237
      pDesc->constraint.word_list = setResolutions;
238
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
239
      pVal->w       = setResolutions[1];
240
      break;
241
242
    case optGroupImage:
243
      pDesc->title  = SANE_I18N("Image");
244
      pDesc->type   = SANE_TYPE_GROUP;
245
      pDesc->size   = 0;
246
      break;
247
248
    case optGamma:
249
      pDesc->name   = SANE_NAME_ANALOG_GAMMA;
250
      pDesc->title  = SANE_TITLE_ANALOG_GAMMA;
251
      pDesc->desc   = SANE_DESC_ANALOG_GAMMA;
252
      pDesc->type   = SANE_TYPE_FIXED;
253
      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
254
      pDesc->constraint.range = &rangeGamma;
255
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
256
      pVal->w       = SANE_FIX(1.0);
257
      break;
258
259
    case optGammaTable:
260
      pDesc->name   = SANE_NAME_GAMMA_VECTOR;
261
      pDesc->title  = SANE_TITLE_GAMMA_VECTOR;
262
      pDesc->desc   = SANE_DESC_GAMMA_VECTOR;
263
      pDesc->size   = sizeof(s->aGammaTable);
264
      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
265
      pDesc->constraint.range = &rangeGammaTable;
266
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
267
      /* set a neutral gamma */
268
      for (j = 0; j < 4096; j++) {
269
        s->aGammaTable[j] = j / 16;
270
      }
271
      pVal->wa      = s->aGammaTable;
272
      break;
273
274
    case optGroupMisc:
275
      pDesc->title  = SANE_I18N("Miscellaneous");
276
      pDesc->type   = SANE_TYPE_GROUP;
277
      pDesc->size   = 0;
278
      break;
279
280
    case optLamp:
281
      pDesc->name   = "lamp";
282
      pDesc->title  = SANE_I18N("Lamp status");
283
      pDesc->desc   = SANE_I18N("Switches the lamp on or off.");
284
      pDesc->type   = SANE_TYPE_BOOL;
285
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
286
      /* switch the lamp on when starting for first the time */
287
      pVal->w       = SANE_TRUE;
288
      break;
289
290
    case optCalibrate:
291
      pDesc->name   = "calibrate";
292
      pDesc->title  = SANE_I18N("Calibrate");
293
      pDesc->desc   = SANE_I18N("Calibrates for black and white level.");
294
      pDesc->type   = SANE_TYPE_BUTTON;
295
      pDesc->cap    = SANE_CAP_SOFT_SELECT;
296
      pDesc->size   = 0;
297
      break;
298
299
    default:
300
      DBG(DBG_ERR, "Uninitialised option %d\n", i);
301
      break;
302
    }
303
  }
304
}
305
306
307
static int _ReportDevice(TScannerModel *pModel, char *pszDeviceName)
308
{
309
  TDevListEntry *pNew, *pDev;
310
311
  DBG(DBG_MSG, "niash: _ReportDevice '%s'\n", pszDeviceName);
312
313
  pNew = malloc(sizeof(TDevListEntry));
314
  if (!pNew) {
315
    DBG(DBG_ERR, "no mem\n");
316
    return -1;
317
  }
318
  
319
  /* add new element to the end of the list */
320
  if (_pFirstSaneDev == 0) {
321
    _pFirstSaneDev = pNew;
322
  }
323
  else {
324
    for (pDev = _pFirstSaneDev; pDev->pNext; pDev = pDev->pNext) {
325
      ;
326
    }
327
    pDev->pNext = pNew;
328
  }
329
330
  /* fill in new element */
331
  pNew->pNext = 0;
332
  pNew->dev.name = strdup(pszDeviceName);
333
  pNew->dev.vendor = pModel->pszVendor;
334
  pNew->dev.model = pModel->pszName;
335
  pNew->dev.type = "flatbed scanner";
336
337
  iNumSaneDev++;
338
339
  return 0;
340
}
341
342
/*****************************************************************************/
343
344
SANE_Status
345
sane_init(SANE_Int *piVersion, SANE_Auth_Callback pfnAuth)
346
{
347
  FILE * conf_fp; /* Config file stream  */
348
  SANE_Char line[PATH_MAX];
349
  SANE_Char * str = NULL;
350
  SANE_String_Const proper_str;
351
  int nline = 0;
352
353
  /* prevent compiler from complaing about unused parameters */
354
  pfnAuth = pfnAuth;
355
356
  DBG_INIT();
357
  DBG(DBG_MSG, "sane_init\n");
358
359
  /* install transfer methods */
360
#if defined(SANEI_USB_SUPPORT)
361
  Hp3300cXferRegisterModule(&SaneiUsbDev);
362
#endif
363
#if defined(LINUX_USB_SUPPORT)
364
  Hp3300cXferRegisterModule(&LnxUsbDev);
365
#endif
366
#if defined(USCANNER_SUPPORT)
367
  Hp3300cXferRegisterModule(&uscannerDev);
368
#endif
369
#if defined(LIBUSB_SUPPORT)
370
  Hp3300cXferRegisterModule(&LibUsbDev);
371
#endif
372
#if defined(LIBIEEE1284_SUPPORT)
373
  Hp3300cXferRegisterModule(&IEEE1284Dev);
374
#endif
375
376
  conf_fp = sanei_config_open (NIASH_CONFIG_FILE);
377
378
  if (conf_fp) {
379
    DBG(DBG_MSG, "Reading config file\n");
380
381
    while (sanei_config_read (line, sizeof (line), conf_fp)) {
382
      ++nline;
383
384
      if (str) {
385
        free(str);
386
      }
387
388
      proper_str = sanei_config_get_string (line, &str);
389
390
      /* Discards white lines and comments */
391
      if (!str || proper_str == line || str[0] == '#' ) {
392
        DBG(DBG_MSG, "Discarding line %d\n", nline);
393
      }
394
      else {
395
        /* If line's not blank or a comment, then it's the device
396
         * filename. usb_devfile is resized to hold the device filename string  */
397
        usb_devfile = malloc ( sizeof (line) * sizeof(SANE_Char) );
398
        if (usb_devfile == NULL) {
399
          DBG(DBG_ERR, "Unable to allocate memory for device filename string\n");
400
          DBG(DBG_MSG, "Using default built-in values\n");
401
          break;
402
        }
403
        strcpy (usb_devfile, line);
404
        DBG(DBG_MSG, "Using %s as device file\n", usb_devfile);
405
      }
406
    } /* while */
407
    fclose(conf_fp);
408
  }
409
  else {
410
    DBG (DBG_ERR, "Unable to read config file \"%s\": %s\n", NIASH_CONFIG_FILE,
411
        strerror(errno));
412
    DBG (DBG_MSG, "Using default built-in values\n");
413
  }
414
415
  if (piVersion != NULL) {
416
    *piVersion = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BUILD);
417
  }
418
419
  /* initialise transfer methods */
420
  iNumSaneDev = 0;
421
  Hp3300cXferInit(_ReportDevice);
422
423
  return SANE_STATUS_GOOD;
424
}
425
426
427
void
428
sane_exit(void)
429
{
430
  TDevListEntry *pDev, *pNext;
431
432
  DBG(DBG_MSG, "sane_exit\n");
433
434
  /* free device list memory */
435
  if (_pSaneDevList) {
436
    for (pDev = _pFirstSaneDev; pDev; pDev = pNext) {
437
      pNext = pDev->pNext;
438
      free((void *)pDev->dev.name);
439
      free(pDev);
440
    }
441
    _pFirstSaneDev = 0;
442
    free(_pSaneDevList);
443
    _pSaneDevList = 0;
444
  }
445
}
446
447
448
SANE_Status
449
sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only)
450
{
451
  TDevListEntry *pDev;
452
  int i;
453
454
  DBG(DBG_MSG, "sane_get_devices\n");
455
456
  local_only = local_only;
457
458
  if (_pSaneDevList) {
459
    free(_pSaneDevList);
460
  }
461
462
  _pSaneDevList = malloc(sizeof(*_pSaneDevList) * (iNumSaneDev + 1));
463
  if (!_pSaneDevList) {
464
    DBG(DBG_MSG, "no mem\n");
465
    return SANE_STATUS_NO_MEM;
466
  }
467
  i = 0;
468
  for (pDev = _pFirstSaneDev; pDev; pDev = pDev->pNext) {
469
    _pSaneDevList[i++] = &pDev->dev;
470
  }
471
  _pSaneDevList[i++] = 0; /* last entry is 0 */
472
473
  *device_list = _pSaneDevList;
474
475
  return SANE_STATUS_GOOD;
476
}
477
478
479
SANE_Status
480
sane_open(SANE_String_Const name, SANE_Handle *h)
481
{
482
  TScanner *s;
483
484
  DBG(DBG_MSG, "sane_open: %s\n", name);
485
486
  /* check the name */
487
  if (strlen(name) == 0) {
488
    /* default to first available device */
489
    name = _pFirstSaneDev->dev.name;
490
  }
491
492
  s = malloc(sizeof(TScanner));
493
  if (!s) {
494
    DBG(DBG_MSG, "malloc failed\n");
495
    return SANE_STATUS_NO_MEM;
496
  }
497
498
  if (Hp3300cOpen(&s->HWParams, (char *)name) < 0) {
499
    /* is this OK ? */
500
    DBG(DBG_ERR, "Hp3300cOpen failed\n");
501
    free((void *)s);
502
    return SANE_STATUS_DEVICE_BUSY;
503
  }
504
  _InitOptions(s);
505
  *h = s;
506
507
  /* Turn on lamp by default at startup */
508
  SetLamp(&s->HWParams, TRUE);
509
510
  return SANE_STATUS_GOOD;
511
}
512
513
514
void
515
sane_close(SANE_Handle h)
516
{
517
  TScanner *s;
518
519
  DBG(DBG_MSG, "sane_close\n");
520
521
  s = (TScanner *)h;
522
523
  /* turn off scanner lamp */
524
  SetLamp(&s->HWParams, FALSE);
525
526
  /* close scanner */
527
  Hp3300cClose(&s->HWParams);
528
529
  /* free scanner object memory */
530
  free((void *)s);
531
}
532
533
534
const SANE_Option_Descriptor *
535
sane_get_option_descriptor(SANE_Handle h, SANE_Int n)
536
{
537
  TScanner *s;
538
539
  DBG(DBG_MSG, "sane_get_option_descriptor %d\n", n);
540
541
  if ((n < optCount) || (n >= optLast)) {
542
    return NULL;
543
  }
544
545
  s = (TScanner *)h;
546
  return &s->aOptions[n];
547
}
548
549
550
SANE_Status
551
sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action Action, void *pVal,
552
                    SANE_Int *pInfo)
553
{
554
  TScanner    *s;
555
  int         fVal;
556
  static char szTable[15000];
557
  char        szTemp[16];
558
  int         *pi;
559
  int         i;
560
  SANE_Int    info;
561
  bool        fLampIsOn;
562
563
  DBG(DBG_MSG, "sane_control_option: option %d, action %d\n", n, Action);
564
565
  s = (TScanner *)h;
566
  info = 0;
567
568
  switch (Action) {
569
  case SANE_ACTION_GET_VALUE:
570
    switch (n) {
571
572
    /* Get options of type SANE_Word */
573
    case optCount:
574
    case optDPI:
575
    case optGamma:
576
    case optTLX: case optTLY: case optBRX: case optBRY:
577
      DBG(DBG_MSG, "sane_control_option: SANE_ACTION_GET_VALUE %d = %d\n", n,
578
          (int)s->aValues[n].w);
579
      *(SANE_Word*)pVal = s->aValues[n].w;
580
      break;
581
582
    /* Get options of type SANE_Word array */
583
    case optGammaTable:
584
      DBG(DBG_MSG, "Reading gamma table\n");
585
      memcpy(pVal, s->aValues[n].wa, s->aOptions[n].size);
586
      break;
587
588
    /* Get options of type SANE_Bool */
589
    case optLamp:
590
      GetLamp(&s->HWParams, &fLampIsOn);
591
      *(SANE_Bool *)pVal = fLampIsOn;
592
      break;
593
594
    case optCalibrate:
595
      /*  although this option has nothing to read,
596
          it's added here to avoid a warning when running scanimage --help */
597
      break;
598
599
    default:
600
      DBG(DBG_MSG, "SANE_ACTION_GET_VALUE: Invalid option (%d)\n", n);
601
    }
602
    break;
603
604
605
  case SANE_ACTION_SET_VALUE:
606
    if (s->fScanning) {
607
      DBG(DBG_ERR, "sane_control_option: SANE_ACTION_SET_VALUE not allowed during scan\n");
608
      return SANE_STATUS_INVAL;
609
    }
610
    switch (n) {
611
612
    case optCount:
613
      return SANE_STATUS_INVAL;
614
615
    case optDPI: case optTLX: case optTLY: case optBRX: case optBRY:
616
      info |= SANE_INFO_RELOAD_PARAMS;
617
      /* fall through */
618
619
    case optGamma:
620
      DBG(DBG_MSG, "sane_control_option: SANE_ACTION_SET_VALUE %d = %d\n", n,
621
          (int)s->aValues[n].w);
622
      s->aValues[n].w = *(SANE_Word *)pVal;
623
      break;
624
625
    case optGammaTable:
626
      DBG(DBG_MSG, "Writing gamma table\n");
627
      pi = (SANE_Int *)pVal;
628
      strcpy(szTable, "");
629
      for (i = 0; i < 4096; i++) {
630
        if ((i % 32) == 0) {
631
          sprintf(szTemp, " %04X", pi[i]);
632
          strcat(szTable, szTemp);
633
        }
634
      }
635
      memcpy(s->aValues[n].wa, pVal, s->aOptions[n].size);
636
      DBG(DBG_MSG, "Gamma table summary:\n%s\n", szTable);
637
      break;
638
639
    case optLamp:
640
      fVal = *(SANE_Bool *)pVal;
641
      DBG(DBG_MSG, "lamp %s\n", fVal ? "on" : "off");
642
      SetLamp(&s->HWParams, fVal);
643
      break;
644
645
    case optCalibrate:
646
/*       SimpleCalib(&s->HWParams); */
647
      break;
648
649
    default:
650
      DBG(DBG_ERR, "SANE_ACTION_SET_VALUE: Invalid option (%d)\n", n);
651
    }
652
    if (pInfo != NULL) {
653
      *pInfo = info;
654
    }
655
    break;
656
657
658
  case SANE_ACTION_SET_AUTO:
659
    return SANE_STATUS_UNSUPPORTED;
660
661
662
  default:
663
    DBG(DBG_ERR, "Invalid action (%d)\n", Action);
664
    return SANE_STATUS_INVAL;
665
  }
666
667
  return SANE_STATUS_GOOD;
668
}
669
670
671
672
SANE_Status
673
sane_get_parameters(SANE_Handle h, SANE_Parameters *p)
674
{
675
  TScanner *s;
676
  DBG(DBG_MSG, "sane_get_parameters\n");
677
678
  s = (TScanner *)h;
679
680
  /* first do some checks */
681
  if (s->aValues[optTLX].w >= s->aValues[optBRX].w) {
682
    DBG(DBG_ERR, "TLX should be smaller than BRX\n");
683
    return SANE_STATUS_INVAL; /* proper error code? */
684
  }
685
  if (s->aValues[optTLY].w >= s->aValues[optBRY].w) {
686
    DBG(DBG_ERR, "TLY should be smaller than BRY\n");
687
    return SANE_STATUS_INVAL; /* proper error code? */
688
  }
689
690
  /* return the data */
691
  p->format = SANE_FRAME_RGB;
692
  p->last_frame = SANE_TRUE;
693
694
  p->lines = MM_TO_PIXEL(s->aValues[optBRY].w - s->aValues[optTLY].w,
695
                         s->aValues[optDPI].w);
696
  p->depth = 8;
697
  p->pixels_per_line = MM_TO_PIXEL(s->aValues[optBRX].w - s->aValues[optTLX].w,
698
                                   s->aValues[optDPI].w);
699
  p->bytes_per_line = p->pixels_per_line * 3;
700
701
  return SANE_STATUS_GOOD;
702
}
703
704
705
SANE_Status
706
sane_start(SANE_Handle h)
707
{
708
  TScanner        *s;
709
  SANE_Parameters par;
710
  int             i, iLineCorr;
711
  static byte     abGamma[4096];
712
  static byte     abCalibTable[HW_PIXELS * 6];
713
714
  DBG(DBG_MSG, "sane_start\n");
715
716
  s = (TScanner *)h;
717
718
  if (sane_get_parameters(h, &par) != SANE_STATUS_GOOD) {
719
    DBG(DBG_MSG, "Invalid scan parameters\n");
720
    return SANE_STATUS_INVAL;
721
  }
722
  s->iLinesLeft = par.lines;
723
724
  /* fill in the scanparams using the option values */
725
  s->ScanParams.iDpi = s->aValues[optDPI].w;
726
  s->ScanParams.iLpi = s->aValues[optDPI].w;
727
728
  /* calculate correction for filling of circular buffer */
729
  iLineCorr = 3 * s->HWParams.iSensorSkew;     /* usually 16 motor steps */
730
  /* calculate correction for garbage lines */
731
  iLineCorr += s->HWParams.iSkipLines * (HW_LPI / s->ScanParams.iLpi);
732
733
  s->ScanParams.iTop =
734
    MM_TO_PIXEL(s->aValues[optTLY].w + s->HWParams.iTopLeftY, HW_LPI) - iLineCorr;
735
  s->ScanParams.iLeft =
736
    MM_TO_PIXEL(s->aValues[optTLX].w + s->HWParams.iTopLeftX, HW_DPI);
737
738
  s->ScanParams.iWidth = par.pixels_per_line;
739
  s->ScanParams.iHeight = par.lines;
740
  s->ScanParams.iBottom = 14200UL;
741
  s->ScanParams.fCalib = FALSE;
742
743
  /* perform a simple calibration just before scanning */
744
  SimpleCalib(&s->HWParams, abCalibTable);
745
746
  /* copy gamma table */
747
  for (i = 0; i < 4096; i++) {
748
    abGamma[i] = s->aValues[optGammaTable].wa[i];
749
  }
750
751
  WriteGammaCalibTable(abGamma, abGamma, abGamma, abCalibTable, 0, 0, &s->HWParams);
752
753
  /* prepare the actual scan */
754
  if (!InitScan(&s->ScanParams, &s->HWParams)) {
755
    DBG(DBG_MSG, "Invalid scan parameters\n");
756
    return SANE_STATUS_INVAL;
757
  }
758
759
  /* init data pipe */
760
  s->DataPipe.iSkipLines = s->HWParams.iSkipLines;
761
  /* on the hp3400 and hp4300 we cannot set the top of the scan area (yet),
762
     so instead we just scan and throw away the data until the top */
763
  if ((s->HWParams.eModel == eHp4300c) || (s->HWParams.eModel == eHp3400c)) {
764
    s->DataPipe.iSkipLines += MM_TO_PIXEL(s->aValues[optTLY].w + s->HWParams.iTopLeftY, s->aValues[optDPI].w);
765
  }
766
  s->DataPipe.iBytesLeft = 0;
767
  /* hack */
768
  s->DataPipe.pabLineBuf = (byte *)malloc(HW_PIXELS * 3);
769
  CircBufferInit( s->HWParams.iXferHandle, &s->DataPipe, par.bytes_per_line,
770
                  s->ScanParams.iLpi * s->HWParams.iSensorSkew / HW_LPI, s->HWParams.iReversedHead);
771
772
  s->fScanning = TRUE;
773
  return SANE_STATUS_GOOD;
774
}
775
776
777
SANE_Status
778
sane_read(SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len)
779
{
780
  TScanner  *s;
781
  TDataPipe *p;
782
783
  DBG(DBG_MSG, "sane_read: buf=%p, maxlen=%d, ", buf, maxlen);
784
785
  s = (TScanner *)h;
786
787
  /* sane_read only allowed after sane_start */
788
  if (!s->fScanning) {
789
    DBG(DBG_ERR, "sane_read: sane_read only allowed after sane_start\n");
790
    return SANE_STATUS_INVAL;
791
  }
792
793
  p = &s->DataPipe;
794
795
  /* anything left to read? */
796
  if ((s->iLinesLeft == 0) && (p->iBytesLeft == 0)) {
797
    CircBufferExit(&s->DataPipe);
798
    free(p->pabLineBuf);
799
    FinishScan(&s->HWParams);
800
    *len = 0;
801
    DBG(DBG_MSG, "sane_read: end of scan\n");
802
    s->fScanning = FALSE;
803
    return SANE_STATUS_EOF;
804
  }
805
806
  /* time to read the next line? */
807
  if (p->iBytesLeft == 0) {
808
    CircBufferGetLine(s->HWParams.iXferHandle, p, p->pabLineBuf, s->HWParams.iReversedHead);
809
    p->iBytesLeft = p->iBytesPerLine;
810
    s->iLinesLeft--;
811
  }
812
813
  /* copy (part of) a line */
814
  *len = MIN(maxlen, p->iBytesLeft);
815
  memcpy(buf, &p->pabLineBuf[p->iBytesPerLine - p->iBytesLeft], *len);
816
  p->iBytesLeft -= *len;
817
818
  DBG(DBG_MSG, " read=%d\n", *len);
819
820
  return SANE_STATUS_GOOD;
821
}
822
823
824
void
825
sane_cancel(SANE_Handle h)
826
{
827
  TScanner *s;
828
829
  DBG(DBG_MSG, "sane_cancel\n");
830
831
  s = (TScanner *)h;
832
833
  /* to be implemented more thoroughly */
834
835
  /* Make sure the scanner head returns home */
836
  FinishScan(&s->HWParams);
837
838
  s->fCanceled = TRUE;
839
  s->fScanning = FALSE;
840
}
841
842
843
SANE_Status
844
sane_set_io_mode(SANE_Handle h, SANE_Bool m)
845
{
846
  DBG(DBG_MSG, "sane_set_io_mode %s\n", m ? "non-blocking" : "blocking");
847
848
  /* prevent compiler from complaining about unused parameters */
849
  h = h;
850
851
  if (m) {
852
    return SANE_STATUS_UNSUPPORTED;
853
  }
854
  return SANE_STATUS_GOOD;
855
}
856
857
858
SANE_Status
859
sane_get_select_fd(SANE_Handle h, SANE_Int *fd)
860
{
861
  DBG(DBG_MSG, "sane_select_fd\n");
862
863
  /* prevent compiler from complaining about unused parameters */
864
  h = h;
865
  fd = fd;
866
867
  return SANE_STATUS_UNSUPPORTED;
868
}
869
(-)sane-backends-1.0.12/backend/niash.conf (+9 lines)
Line 0 Link Here
1
# Device filename to use for scanner access
2
# Uncomment the following line if you are using the SANE backend
3
# and want to use the kernel scanner module instead of libusb:
4
#
5
#Linux:
6
#/dev/usbscanner
7
#
8
#FreeBSD/NetBSD:
9
#/dev/uscanner0
(-)sane-backends-1.0.12/doc/Makefile.in (-2 / +2 lines)
Lines 38-44 Link Here
38
@SET_MAKE@
38
@SET_MAKE@
39
39
40
SECT1	= saned.1 scanimage.1 sane-config.1 sane-find-scanner.1 gamma4scanimage.1
40
SECT1	= saned.1 scanimage.1 sane-config.1 sane-find-scanner.1 gamma4scanimage.1
41
SECT5	= sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-as6e.5 sane-dll.5 \
41
SECT5	= sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-as6e.5 sane-dll.5 sane-niash.5 \
42
          sane-dc25.5 sane-dmc.5 sane-epson.5 sane-hp.5 sane-gphoto2.5 \
42
          sane-dc25.5 sane-dmc.5 sane-epson.5 sane-hp.5 sane-gphoto2.5 \
43
          sane-leo.5 sane-matsushita.5 sane-microtek.5 \
43
          sane-leo.5 sane-matsushita.5 sane-microtek.5 \
44
          sane-microtek2.5 sane-mustek.5 sane-nec.5 sane-net.5 sane-pie.5 \
44
          sane-microtek2.5 sane-mustek.5 sane-nec.5 sane-net.5 sane-pie.5 \
Lines 88-94 Link Here
88
  sane-artec.man sane-as6e.man sane-avision.man sane-bh.man \
88
  sane-artec.man sane-as6e.man sane-avision.man sane-bh.man \
89
  sane-canon.man sane-canon630u.man sane-config.man sane-coolscan.man \
89
  sane-canon.man sane-canon630u.man sane-config.man sane-coolscan.man \
90
  sane-coolscan2.man sane-dc210.man sane-dc240.man \
90
  sane-coolscan2.man sane-dc210.man sane-dc240.man \
91
  sane-dc25.man sane-dll.man sane-dmc.man sane-epson.man \
91
  sane-dc25.man sane-dll.man sane-niash.man sane-dmc.man sane-epson.man \
92
  sane-find-scanner.man sane-fujitsu.man sane-gphoto2.man sane-hp.man \
92
  sane-find-scanner.man sane-fujitsu.man sane-gphoto2.man sane-hp.man \
93
  sane-logo.png sane-logo2.jpg sane-matsushita.man sane-microtek.man \
93
  sane-logo.png sane-logo2.jpg sane-matsushita.man sane-microtek.man \
94
  sane-leo.man sane-microtek2.man \
94
  sane-leo.man sane-microtek2.man \
(-)sane-backends-1.0.12/doc/sane-niash.man (+113 lines)
Line 0 Link Here
1
.\" $Id: sane-niash.man,v 1.7 2002/02/07 03:28:53 aggression Exp $
2
.TH sane-niash 5 "17 Dec 2001"
3
.IX sane-niash
4
5
.SH NAME
6
sane-niash - SANE backend for scanners based on the NIASH chipset.
7
8
.SH DESCRIPTION
9
The
10
.B sane-niash
11
implements a SANE (Scanner Access Now Easy) backend that
12
provides access to NIASH chipset based scanners. This backend will try to support 
13
the following models:
14
15
MANUFACTURER:    MODEL:         USB ID:   
16
.br
17
---------------  --------------  ---------  
18
.br
19
Agfa             Snapscan Touch  06BD-0100 (1)(a)
20
.br
21
Hewlett-Packard  Scanjet 3300c   03F0-0205 (1)(a)(b)
22
.br
23
Hewlett-Packard  Scanjet 3400c   03F0-0405 (2)(b)
24
.br 
25
Hewlett-Packard  Scanjet 4300c   03F0-0305 (2)(a)
26
.PP
27
.br
28
ASIC: (1) - NIASH00014 / (2) - NIASH00019
29
.br
30
ANALOG FRONT-END: (a) - ESIC ES8100QA / (b) - WM8143-12
31
.br
32
33
.SH "DEVICE NAMES"
34
This backend expects device names of the form:
35
.PP
36
.RS
37
.I special
38
.RE
39
.PP
40
Where
41
.I special
42
is a path-name for the special device that corresponds to a USB scanner.
43
With GNU/Linux systems, such a device name could be
44
.I /dev/usb/scanner0
45
or
46
.IR /dev/usbscanner1 ,
47
for example.
48
49
50
.SH CONFIGURATION
51
The
52
.I niash.conf
53
file contains the device name that correspond to the NIASH
54
scanner.  Empty lines and lines starting with a hash mark (#) are
55
ignored.
56
.PP
57
A sample configuration file is shown below:
58
.PP
59
.RS
60
# Comment
61
.br
62
/dev/usbscanner
63
.RE
64
.PP
65
The first line is ignored. The second line is the device filename to use
66
in order to access the NIASH Scanner. If no device is given, the
67
backend will use libUSB.
68
69
.SH FILES
70
.TP
71
.I @CONFIGDIR@/niash.conf
72
The backend configuration file (see also description of SANE_CONFIG_DIR below).
73
74
.TP
75
.I @LIBDIR@/libsane-niash.a
76
The static library implementing this backend.
77
78
.TP
79
.I @LIBDIR@/libsane-niash.so
80
The shared library implementing this backend (present on systems that
81
support dynamic loading).
82
.SH ENVIRONMENT
83
84
.TP
85
.B SANE_CONFIG_DIR
86
This environment variable specifies the list of directories that may
87
contain the configuration file.  Under UNIX, the directories are
88
separated by a colon (`:'), under OS/2, they are separated by a
89
semi-colon (`;').  If this variable is not set, the configuration file
90
is searched in two default directories: first, the current working
91
directory (".") and then in @CONFIGDIR@.  If the value of the
92
environment variable ends with the directory separator character, then
93
the default directories are searched after the explicitly specified
94
directories.  For example, setting
95
.B SANE_CONFIG_DIR
96
to "/tmp/config:" would result in directories "tmp/config", ".", and
97
"@CONFIGDIR@" being searched (in this order).
98
.TP
99
100
.B SANE_DEBUG_NIASH
101
If the library was compiled with debug support enabled, this
102
environment variable controls the debug level for this backend.  Higher
103
debug levels increase the verbosity of the output. 
104
105
Example: 
106
export SANE_DEBUG_NIASH=255
107
108
.SH "SEE ALSO"
109
sane(7), sane\-usb(5)
110
.br
111
http://www.sourceforge.net/projects/hp3300backend
112
.SH AUTHOR
113
Bertrik Sikken <bertrik@zonnet.nl>

Return to bug 18479