~ubuntu-branches/ubuntu/saucy/hplip/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/try_libhpmud.so.0.dpatch/scan/sane/marvell.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2012-05-26 11:20:39 UTC
  • mfrom: (1.5.6) (31.1.3 precise)
  • Revision ID: package-import@ubuntu.com-20120526112039-bevxczegxnbyr5m7
Tags: 3.12.4-1
* New upstream release
* Switch to source/format 3.0 (quilt) - drop dpatch
* Refreshed debian/patches
* dh_autoreconf debian/autogen.sh & set local-options single-debian-patch
* Update to debian/compat -> 9
* Fix "hardened build flags" patch from Moritz - thanks (Closes: #667828)
* Fix "duplex descriptor uninitialized" patch from Matej (Closes: #583273)
* Fix "please migrate to kde-runtime" patch from Pino (Closes: #666544)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************************\
 
2
 
 
3
  marvell.c - HP SANE backend support for Marvell based multi-function peripherals
 
4
 
 
5
  (c) 2008 Copyright Hewlett-Packard Development Company, LP
 
6
 
 
7
  Permission is hereby granted, free of charge, to any person obtaining a copy 
 
8
  of this software and associated documentation files (the "Software"), to deal 
 
9
  in the Software without restriction, including without limitation the rights 
 
10
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
 
11
  of the Software, and to permit persons to whom the Software is furnished to do 
 
12
  so, subject to the following conditions:
 
13
 
 
14
  The above copyright notice and this permission notice shall be included in all
 
15
  copies or substantial portions of the Software.
 
16
 
 
17
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 
18
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 
 
19
  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
 
20
  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
 
21
  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
 
22
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
23
 
 
24
  Author: David Suffield, Yashwant Sahu
 
25
 
 
26
\************************************************************************************/
 
27
 
 
28
#ifndef _GNU_SOURCE
 
29
#define _GNU_SOURCE
 
30
#endif
 
31
 
 
32
#include <sys/socket.h>
 
33
#include <netdb.h>
 
34
#include <stdarg.h>
 
35
#include <syslog.h>
 
36
#include <stdio.h>
 
37
#include <string.h>
 
38
#include <sys/types.h>
 
39
#include <fcntl.h>
 
40
#include <unistd.h>
 
41
#include <math.h>
 
42
#include <dlfcn.h>
 
43
#include "sane.h"
 
44
#include "saneopts.h"
 
45
#include "hpmud.h"
 
46
#include "hpip.h"
 
47
#include "common.h"
 
48
#include "marvell.h"
 
49
#include "marvelli.h"
 
50
#include "io.h"
 
51
 
 
52
#define DEBUG_DECLARE_ONLY
 
53
#include "sanei_debug.h"
 
54
 
 
55
static struct marvell_session *session = NULL;   /* assume one sane_open per process */
 
56
 
 
57
static int bb_load(struct marvell_session *ps, const char *so)
 
58
{
 
59
   char home[128];
 
60
   char sz[255]; 
 
61
   int stat=1;
 
62
 
 
63
   /* Load hpmud manually with symbols exported. Otherwise the plugin will not find it. */ 
 
64
   if ((ps->hpmud_handle = dlopen("libhpmud.so", RTLD_LAZY|RTLD_GLOBAL)) == NULL)
 
65
   {
 
66
      BUG("unable to load restricted library: %s\n", dlerror());
 
67
      goto bugout;
 
68
   } 
 
69
 
 
70
   /* Load math library manually with symbols exported (Ubuntu 8.04). Otherwise the plugin will not find it. */ 
 
71
   if ((ps->math_handle = dlopen("libm.so", RTLD_LAZY|RTLD_GLOBAL)) == NULL)
 
72
   {
 
73
      if ((ps->math_handle = dlopen("libm.so.6", RTLD_LAZY|RTLD_GLOBAL)) == NULL)
 
74
      {
 
75
         BUG("unable to load restricted library: %s\n", dlerror());
 
76
         goto bugout;
 
77
      }
 
78
   } 
 
79
 
 
80
   if (hpmud_get_conf("[dirs]", "home", home, sizeof(home)) != HPMUD_R_OK)
 
81
      goto bugout;
 
82
   snprintf(sz, sizeof(sz), "%s/scan/plugins/%s", home, so);
 
83
   if ((ps->bb_handle = dlopen(sz, RTLD_NOW|RTLD_GLOBAL)) == NULL)
 
84
   {
 
85
      BUG("unable to load restricted library %s: %s\n", sz, dlerror());
 
86
      SendScanEvent(ps->uri, EVENT_PLUGIN_FAIL);
 
87
      goto bugout;
 
88
   } 
 
89
   
 
90
   if ((ps->bb_open = dlsym(ps->bb_handle, "bb_open")) == NULL)
 
91
   {
 
92
      BUG("unable to load restricted library %s: %s\n", sz, dlerror());
 
93
      goto bugout;
 
94
   } 
 
95
   if ((ps->bb_close = dlsym(ps->bb_handle, "bb_close")) == NULL)
 
96
   {
 
97
      BUG("unable to load restricted library %s: %s\n", sz, dlerror());
 
98
      goto bugout;
 
99
   } 
 
100
   if ((ps->bb_get_parameters = dlsym(ps->bb_handle, "bb_get_parameters")) == NULL)
 
101
   {
 
102
      BUG("unable to load restricted library %s: %s\n", sz, dlerror());
 
103
      goto bugout;
 
104
   } 
 
105
   if ((ps->bb_is_paper_in_adf = dlsym(ps->bb_handle, "bb_is_paper_in_adf")) == NULL)
 
106
   {
 
107
      BUG("unable to load restricted library %s: %s\n", sz, dlerror());
 
108
      goto bugout;
 
109
   } 
 
110
   if ((ps->bb_start_scan = dlsym(ps->bb_handle, "bb_start_scan")) == NULL)
 
111
   {
 
112
      BUG("unable to load restricted library %s: %s\n", sz, dlerror());
 
113
      goto bugout;
 
114
   } 
 
115
   if ((ps->bb_end_scan = dlsym(ps->bb_handle, "bb_end_scan")) == NULL)
 
116
   {
 
117
      BUG("unable to load restricted library %s: %s\n", sz, dlerror());
 
118
      goto bugout;
 
119
   } 
 
120
   if ((ps->bb_get_image_data = dlsym(ps->bb_handle, "bb_get_image_data")) == NULL)
 
121
   {
 
122
      BUG("unable to load restricted library %s: %s\n", sz, dlerror());
 
123
      goto bugout;
 
124
   } 
 
125
   if ((ps->bb_end_page = dlsym(ps->bb_handle, "bb_end_page")) == NULL)
 
126
   {
 
127
      BUG("unable to load restricted library %s: %s\n", sz, dlerror());
 
128
      goto bugout;
 
129
   } 
 
130
 
 
131
   stat=0;
 
132
 
 
133
bugout:
 
134
   return stat;
 
135
}
 
136
 
 
137
static int bb_unload(struct marvell_session *ps)
 
138
{
 
139
   if (ps->bb_handle)
 
140
   {   
 
141
      dlclose(ps->bb_handle);
 
142
      ps->bb_handle = NULL;
 
143
   }  
 
144
   if (ps->hpmud_handle)
 
145
   {   
 
146
      dlclose(ps->hpmud_handle);
 
147
      ps->hpmud_handle = NULL;
 
148
   }  
 
149
   if (ps->math_handle)
 
150
   {   
 
151
      dlclose(ps->math_handle);
 
152
      ps->math_handle = NULL;
 
153
   }  
 
154
   return 0;
 
155
}
 
156
 
 
157
/* Get raw data (ie: uncompressed data) from image processor. */
 
158
static int get_ip_data(struct marvell_session *ps, SANE_Byte *data, SANE_Int maxLength, SANE_Int *length)
 
159
{
 
160
   int ip_ret=IP_INPUT_ERROR;
 
161
   unsigned int outputAvail=maxLength, outputUsed=0, outputThisPos;
 
162
   unsigned char *input, *output = data;
 
163
   unsigned int inputAvail, inputUsed=0, inputNextPos;
 
164
 
 
165
   if (!ps->ip_handle)
 
166
   {
 
167
      BUG("invalid ipconvert state\n");
 
168
      goto bugout;
 
169
   }
 
170
   
 
171
   if (ps->bb_get_image_data(ps, outputAvail))
 
172
      goto bugout;
 
173
 
 
174
   if (ps->cnt > 0)
 
175
   {
 
176
      inputAvail = ps->cnt;
 
177
      input = ps->buf;
 
178
   }
 
179
   else
 
180
   {
 
181
      input = NULL;   /* no more scan data, flush ipconvert pipeline */
 
182
      inputAvail = 0;
 
183
   }
 
184
 
 
185
   /* Transform input data to output. Note, output buffer may consume more bytes than input buffer (ie: jpeg to raster). */
 
186
   ip_ret = ipConvert(ps->ip_handle, inputAvail, input, &inputUsed, &inputNextPos, outputAvail, output, &outputUsed, &outputThisPos);
 
187
 
 
188
   DBG6("input=%p inputAvail=%d inputUsed=%d inputNextPos=%d output=%p outputAvail=%d outputUsed=%d outputThisPos=%d ret=%x\n", input, 
 
189
         inputAvail, inputUsed, inputNextPos, output, outputAvail, outputUsed, outputThisPos, ip_ret);
 
190
 
 
191
   if (data)
 
192
      *length = outputUsed;
 
193
 
 
194
   /* For sane do not send output data simultaneously with IP_DONE. */
 
195
   if (ip_ret & IP_DONE && outputUsed)
 
196
      ip_ret &= ~IP_DONE;                               
 
197
 
 
198
bugout:
 
199
   return ip_ret;
 
200
}
 
201
 
 
202
static int init_options(struct marvell_session *ps)
 
203
{
 
204
   ps->option[MARVELL_OPTION_COUNT].name = "option-cnt";
 
205
   ps->option[MARVELL_OPTION_COUNT].title = SANE_TITLE_NUM_OPTIONS;
 
206
   ps->option[MARVELL_OPTION_COUNT].desc = SANE_DESC_NUM_OPTIONS;
 
207
   ps->option[MARVELL_OPTION_COUNT].type = SANE_TYPE_INT;
 
208
   ps->option[MARVELL_OPTION_COUNT].unit = SANE_UNIT_NONE;
 
209
   ps->option[MARVELL_OPTION_COUNT].size = sizeof(SANE_Int);
 
210
   ps->option[MARVELL_OPTION_COUNT].cap = SANE_CAP_SOFT_DETECT;
 
211
   ps->option[MARVELL_OPTION_COUNT].constraint_type = SANE_CONSTRAINT_NONE;
 
212
 
 
213
   ps->option[MARVELL_OPTION_GROUP_SCAN_MODE].name = "mode-group";
 
214
   ps->option[MARVELL_OPTION_GROUP_SCAN_MODE].title = SANE_TITLE_SCAN_MODE;
 
215
   ps->option[MARVELL_OPTION_GROUP_SCAN_MODE].type = SANE_TYPE_GROUP;
 
216
 
 
217
   ps->option[MARVELL_OPTION_SCAN_MODE].name = SANE_NAME_SCAN_MODE;
 
218
   ps->option[MARVELL_OPTION_SCAN_MODE].title = SANE_TITLE_SCAN_MODE;
 
219
   ps->option[MARVELL_OPTION_SCAN_MODE].desc = SANE_DESC_SCAN_MODE;
 
220
   ps->option[MARVELL_OPTION_SCAN_MODE].type = SANE_TYPE_STRING;
 
221
   ps->option[MARVELL_OPTION_SCAN_MODE].unit = SANE_UNIT_NONE;
 
222
   ps->option[MARVELL_OPTION_SCAN_MODE].size = MAX_STRING_SIZE;
 
223
   ps->option[MARVELL_OPTION_SCAN_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 
224
   ps->option[MARVELL_OPTION_SCAN_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
 
225
   ps->option[MARVELL_OPTION_SCAN_MODE].constraint.string_list = ps->scan_mode_list;
 
226
 
 
227
   ps->option[MARVELL_OPTION_INPUT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
 
228
   ps->option[MARVELL_OPTION_INPUT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
 
229
   ps->option[MARVELL_OPTION_INPUT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
 
230
   ps->option[MARVELL_OPTION_INPUT_SOURCE].type = SANE_TYPE_STRING;
 
231
   ps->option[MARVELL_OPTION_INPUT_SOURCE].unit = SANE_UNIT_NONE;
 
232
   ps->option[MARVELL_OPTION_INPUT_SOURCE].size = MAX_STRING_SIZE;
 
233
   ps->option[MARVELL_OPTION_INPUT_SOURCE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 
234
   ps->option[MARVELL_OPTION_INPUT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
 
235
   ps->option[MARVELL_OPTION_INPUT_SOURCE].constraint.string_list = ps->input_source_list;
 
236
 
 
237
   ps->option[MARVELL_OPTION_SCAN_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
 
238
   ps->option[MARVELL_OPTION_SCAN_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
 
239
   ps->option[MARVELL_OPTION_SCAN_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
 
240
   ps->option[MARVELL_OPTION_SCAN_RESOLUTION].type = SANE_TYPE_INT;
 
241
   ps->option[MARVELL_OPTION_SCAN_RESOLUTION].unit = SANE_UNIT_DPI;
 
242
   ps->option[MARVELL_OPTION_SCAN_RESOLUTION].size = sizeof(SANE_Int);
 
243
   ps->option[MARVELL_OPTION_SCAN_RESOLUTION].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 
244
   ps->option[MARVELL_OPTION_SCAN_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
 
245
   ps->option[MARVELL_OPTION_SCAN_RESOLUTION].constraint.word_list = ps->resolution_list;
 
246
 
 
247
   ps->option[MARVELL_OPTION_GROUP_ADVANCED].name = "advanced-group";
 
248
   ps->option[MARVELL_OPTION_GROUP_ADVANCED].title = STR_TITLE_ADVANCED;
 
249
   ps->option[MARVELL_OPTION_GROUP_ADVANCED].type = SANE_TYPE_GROUP;
 
250
   ps->option[MARVELL_OPTION_GROUP_ADVANCED].cap = SANE_CAP_ADVANCED;
 
251
 
 
252
   ps->option[MARVELL_OPTION_CONTRAST].name = SANE_NAME_CONTRAST;
 
253
   ps->option[MARVELL_OPTION_CONTRAST].title = SANE_TITLE_CONTRAST;
 
254
   ps->option[MARVELL_OPTION_CONTRAST].desc = SANE_DESC_CONTRAST;
 
255
   ps->option[MARVELL_OPTION_CONTRAST].type = SANE_TYPE_INT;
 
256
   ps->option[MARVELL_OPTION_CONTRAST].unit = SANE_UNIT_NONE;
 
257
   ps->option[MARVELL_OPTION_CONTRAST].size = sizeof(SANE_Int);
 
258
   ps->option[MARVELL_OPTION_CONTRAST].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
 
259
   ps->option[MARVELL_OPTION_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
 
260
   ps->option[MARVELL_OPTION_CONTRAST].constraint.range = &ps->contrast_range;
 
261
   ps->contrast_range.min = MARVELL_CONTRAST_MIN;
 
262
   ps->contrast_range.max = MARVELL_CONTRAST_MAX;
 
263
   ps->contrast_range.quant = 0;
 
264
 
 
265
   ps->option[MARVELL_OPTION_GROUP_GEOMETRY].name = "geometry-group";
 
266
   ps->option[MARVELL_OPTION_GROUP_GEOMETRY].title = STR_TITLE_GEOMETRY;
 
267
   ps->option[MARVELL_OPTION_GROUP_GEOMETRY].type = SANE_TYPE_GROUP;
 
268
   ps->option[MARVELL_OPTION_GROUP_GEOMETRY].cap = SANE_CAP_ADVANCED;
 
269
 
 
270
   ps->option[MARVELL_OPTION_TL_X].name = SANE_NAME_SCAN_TL_X;
 
271
   ps->option[MARVELL_OPTION_TL_X].title = SANE_TITLE_SCAN_TL_X;
 
272
   ps->option[MARVELL_OPTION_TL_X].desc = SANE_DESC_SCAN_TL_X;
 
273
   ps->option[MARVELL_OPTION_TL_X].type = SANE_TYPE_FIXED;
 
274
   ps->option[MARVELL_OPTION_TL_X].unit = SANE_UNIT_MM;
 
275
   ps->option[MARVELL_OPTION_TL_X].size = sizeof(SANE_Int);
 
276
   ps->option[MARVELL_OPTION_TL_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 
277
   ps->option[MARVELL_OPTION_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
 
278
   ps->option[MARVELL_OPTION_TL_X].constraint.range = &ps->tlxRange;
 
279
   ps->tlxRange.min = 0;
 
280
   ps->tlxRange.quant = 0;
 
281
 
 
282
   ps->option[MARVELL_OPTION_TL_Y].name = SANE_NAME_SCAN_TL_Y;
 
283
   ps->option[MARVELL_OPTION_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
 
284
   ps->option[MARVELL_OPTION_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
 
285
   ps->option[MARVELL_OPTION_TL_Y].type = SANE_TYPE_FIXED;
 
286
   ps->option[MARVELL_OPTION_TL_Y].unit = SANE_UNIT_MM;
 
287
   ps->option[MARVELL_OPTION_TL_Y].size = sizeof(SANE_Int);
 
288
   ps->option[MARVELL_OPTION_TL_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 
289
   ps->option[MARVELL_OPTION_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
 
290
   ps->option[MARVELL_OPTION_TL_Y].constraint.range = &ps->tlyRange;
 
291
   ps->tlyRange.min = 0;
 
292
   ps->tlyRange.quant = 0;
 
293
 
 
294
   ps->option[MARVELL_OPTION_BR_X].name = SANE_NAME_SCAN_BR_X;
 
295
   ps->option[MARVELL_OPTION_BR_X].title = SANE_TITLE_SCAN_BR_X;
 
296
   ps->option[MARVELL_OPTION_BR_X].desc = SANE_DESC_SCAN_BR_X;
 
297
   ps->option[MARVELL_OPTION_BR_X].type = SANE_TYPE_FIXED;
 
298
   ps->option[MARVELL_OPTION_BR_X].unit = SANE_UNIT_MM;
 
299
   ps->option[MARVELL_OPTION_BR_X].size = sizeof(SANE_Int);
 
300
   ps->option[MARVELL_OPTION_BR_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 
301
   ps->option[MARVELL_OPTION_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
 
302
   ps->option[MARVELL_OPTION_BR_X].constraint.range = &ps->brxRange;
 
303
   ps->brxRange.min = 0;
 
304
   ps->brxRange.quant = 0;
 
305
 
 
306
   ps->option[MARVELL_OPTION_BR_Y].name = SANE_NAME_SCAN_BR_Y;
 
307
   ps->option[MARVELL_OPTION_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
 
308
   ps->option[MARVELL_OPTION_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
 
309
   ps->option[MARVELL_OPTION_BR_Y].type = SANE_TYPE_FIXED;
 
310
   ps->option[MARVELL_OPTION_BR_Y].unit = SANE_UNIT_MM;
 
311
   ps->option[MARVELL_OPTION_BR_Y].size = sizeof(SANE_Int);
 
312
   ps->option[MARVELL_OPTION_BR_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 
313
   ps->option[MARVELL_OPTION_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
 
314
   ps->option[MARVELL_OPTION_BR_Y].constraint.range = &ps->bryRange;
 
315
   ps->bryRange.min = 0;
 
316
   ps->bryRange.quant = 0;
 
317
 
 
318
   return 0;
 
319
}
 
320
 
 
321
/* Verify current x/y extents and set effective extents. */ 
 
322
static int set_extents(struct marvell_session *ps)
 
323
{
 
324
   int stat = 0;
 
325
 
 
326
   if ((ps->currentBrx > ps->currentTlx) && (ps->currentBrx - ps->currentTlx >= ps->min_width) && (ps->currentBrx - ps->currentTlx <= ps->tlxRange.max))
 
327
   {
 
328
     ps->effectiveTlx = ps->currentTlx;
 
329
     ps->effectiveBrx = ps->currentBrx;
 
330
   }
 
331
   else
 
332
   {
 
333
     ps->effectiveTlx = 0;  /* current setting is not valid, zero it */
 
334
     ps->effectiveBrx = 0;
 
335
     stat = 1;
 
336
   }
 
337
   if ((ps->currentBry > ps->currentTly) && (ps->currentBry - ps->currentTly > ps->min_height) && (ps->currentBry - ps->currentTly <= ps->tlyRange.max))
 
338
   {
 
339
     ps->effectiveTly = ps->currentTly;
 
340
     ps->effectiveBry = ps->currentBry;
 
341
   }
 
342
   else
 
343
   {
 
344
     ps->effectiveTly = 0;  /* current setting is not valid, zero it */
 
345
     ps->effectiveBry = 0;
 
346
     stat = 1;
 
347
   }
 
348
   return stat;
 
349
}
 
350
 
 
351
static struct marvell_session *create_session()
 
352
{
 
353
   struct marvell_session *ps;
 
354
 
 
355
   if ((ps = malloc(sizeof(struct marvell_session))) == NULL)
 
356
   {
 
357
      BUG("malloc failed: %m\n");
 
358
      return NULL;
 
359
   }
 
360
   memset(ps, 0, sizeof(struct marvell_session));
 
361
   ps->tag = "MARVELL";
 
362
   ps->dd = -1;
 
363
   ps->cd = -1;
 
364
 
 
365
   return ps;
 
366
}
 
367
 
 
368
/*
 
369
 * SANE APIs.
 
370
 */
 
371
 
 
372
SANE_Status marvell_open(SANE_String_Const device, SANE_Handle *handle)
 
373
{
 
374
   struct hpmud_model_attributes ma;
 
375
   int stat = SANE_STATUS_IO_ERROR;
 
376
   int i;
 
377
 
 
378
   DBG8("sane_hpaio_open(%s)\n", device);
 
379
 
 
380
   if (session)
 
381
   {
 
382
      BUG("session in use\n");
 
383
      return SANE_STATUS_DEVICE_BUSY;
 
384
   }
 
385
      
 
386
   if ((session = create_session()) == NULL)
 
387
      return SANE_STATUS_NO_MEM;
 
388
    
 
389
   /* Set session to specified device. */
 
390
   snprintf(session->uri, sizeof(session->uri)-1, "hp:%s", device);   /* prepend "hp:" */
 
391
 
 
392
   /* Get actual model attributes from models.dat. */
 
393
   hpmud_query_model(session->uri, &ma);
 
394
   session->scan_type = ma.scantype;
 
395
   session->scansrc = ma.scansrc;
 
396
   
 
397
   switch (ma.scantype)
 
398
   {
 
399
      case HPMUD_SCANTYPE_MARVELL:
 
400
         session->version = MARVELL_1;
 
401
                 break;
 
402
          case HPMUD_SCANTYPE_MARVELL2:
 
403
         session->version = MARVELL_2;
 
404
                 break;
 
405
          default:
 
406
         session->version = MARVELL_1;
 
407
   };
 
408
 
 
409
   if (hpmud_open_device(session->uri, ma.mfp_mode, &session->dd) != HPMUD_R_OK)
 
410
   {
 
411
      BUG("unable to open device %s\n", session->uri);
 
412
      goto bugout;
 
413
 
 
414
      free(session);
 
415
      session = NULL;
 
416
      return SANE_STATUS_IO_ERROR;
 
417
   }
 
418
 
 
419
   if (hpmud_open_channel(session->dd, HPMUD_S_MARVELL_SCAN_CHANNEL, &session->cd) != HPMUD_R_OK)
 
420
   {
 
421
      BUG("unable to open %s channel %s\n", HPMUD_S_MARVELL_SCAN_CHANNEL, session->uri);
 
422
      stat = SANE_STATUS_DEVICE_BUSY;
 
423
      goto bugout;
 
424
   }
 
425
 
 
426
   if (bb_load(session, "bb_marvell.so"))
 
427
   {
 
428
      stat = SANE_STATUS_IO_ERROR;
 
429
      goto bugout;
 
430
   }
 
431
 
 
432
   /* Init sane option descriptors. */
 
433
   init_options(session);  
 
434
 
 
435
   if (session->bb_open(session))
 
436
   {
 
437
      stat = SANE_STATUS_IO_ERROR;
 
438
      goto bugout;
 
439
   }
 
440
 
 
441
   /* Set supported Scan Modes and set sane option. */
 
442
   i=0;
 
443
   session->scan_mode_list[i] = SANE_VALUE_SCAN_MODE_LINEART;
 
444
   session->scan_mode_map[i++] = CE_BLACK_AND_WHITE1;
 
445
   session->scan_mode_list[i] = SANE_VALUE_SCAN_MODE_GRAY;
 
446
   session->scan_mode_map[i++] = CE_GRAY8;
 
447
   session->scan_mode_list[i] = SANE_VALUE_SCAN_MODE_COLOR;
 
448
   session->scan_mode_map[i++] = CE_RGB24;
 
449
   marvell_control_option(session, MARVELL_OPTION_SCAN_MODE, SANE_ACTION_SET_AUTO, NULL, NULL); /* set default option */
 
450
 
 
451
 
 
452
   /* Determine scan input source. */
 
453
   i=0;
 
454
   /* Some of the marvell devices supports both flatbed and ADF, No command to get the src types supported */
 
455
   /* Getting from the model file */
 
456
   if ( session->scansrc & HPMUD_SCANSRC_ADF)
 
457
   {
 
458
         session->input_source_list[i] = STR_ADF_MODE_ADF;
 
459
         session->input_source_map[i++] = IS_ADF;
 
460
         DBG8("scan src  HPMUD_SCANSRC_ADF \n"); 
 
461
   }
 
462
   if ( session->scansrc & HPMUD_SCANSRC_FLATBED)
 
463
   {
 
464
         session->input_source_list[i] = STR_ADF_MODE_FLATBED;
 
465
         session->input_source_map[i++] = IS_PLATEN;
 
466
         DBG8("scan src  HPMUD_SCANSRC_FLATBED \n");
 
467
    }
 
468
    /* Values if un specified in the, value is 0,  get ADF state from the printer */   
 
469
   if (session->scansrc == HPMUD_SCANSRC_NA)
 
470
   {
 
471
     if (session->bb_is_paper_in_adf(session) == 2) 
 
472
     {
 
473
       session->input_source_list[i] = STR_ADF_MODE_FLATBED;
 
474
       session->input_source_map[i++] = IS_PLATEN;
 
475
       DBG8("scan src  b_is_paper_in_adf value  2 \n");
 
476
     }
 
477
     else
 
478
     {
 
479
       session->input_source_list[i] = STR_ADF_MODE_ADF;
 
480
       session->input_source_map[i++] = IS_ADF;
 
481
       DBG8("scan src  b_is_paper_in_adf value not 2 \n");
 
482
     }
 
483
    }
 
484
 
 
485
   marvell_control_option(session, MARVELL_OPTION_INPUT_SOURCE, SANE_ACTION_SET_AUTO, NULL, NULL); /* set default option */  
 
486
 
 
487
   /* Set supported resolutions. */
 
488
   i=1;
 
489
   session->resolution_list[i++] = 75;
 
490
   session->resolution_list[i++] = 100;
 
491
   session->resolution_list[i++] = 150;
 
492
   session->resolution_list[i++] = 200;
 
493
   session->resolution_list[i++] = 300;
 
494
   session->resolution_list[i++] = 600;
 
495
   session->resolution_list[i++] = 1200;
 
496
   session->resolution_list[0] = i-1;    /* length of word_list */
 
497
   marvell_control_option(session, MARVELL_OPTION_SCAN_RESOLUTION, SANE_ACTION_SET_AUTO, NULL, NULL); /* set default option */
 
498
 
 
499
   /* Set supported contrast. */
 
500
   marvell_control_option(session, MARVELL_OPTION_CONTRAST, SANE_ACTION_SET_AUTO, NULL, NULL); /* set default option */
 
501
 
 
502
   /* Set x,y extents. See bb_open(). */
 
503
   marvell_control_option(session, MARVELL_OPTION_TL_X, SANE_ACTION_SET_AUTO, NULL, NULL); /* set default option */
 
504
   marvell_control_option(session, MARVELL_OPTION_TL_Y, SANE_ACTION_SET_AUTO, NULL, NULL); /* set default option */
 
505
   marvell_control_option(session, MARVELL_OPTION_BR_X, SANE_ACTION_SET_AUTO, NULL, NULL); /* set default option */
 
506
   marvell_control_option(session, MARVELL_OPTION_BR_Y, SANE_ACTION_SET_AUTO, NULL, NULL); /* set default option */
 
507
 
 
508
   *handle = (SANE_Handle *)session;
 
509
 
 
510
   stat = SANE_STATUS_GOOD;
 
511
 
 
512
bugout:
 
513
 
 
514
   if (stat != SANE_STATUS_GOOD)
 
515
   {
 
516
      if (session)
 
517
      {
 
518
         bb_unload(session);
 
519
         if (session->cd > 0)
 
520
            hpmud_close_channel(session->dd, session->cd);
 
521
         if (session->dd > 0)
 
522
            hpmud_close_device(session->dd);
 
523
         free(session);
 
524
         session = NULL;
 
525
      }
 
526
   }
 
527
 
 
528
   return stat;
 
529
}
 
530
 
 
531
void marvell_close(SANE_Handle handle)
 
532
{
 
533
   struct marvell_session *ps = (struct marvell_session *)handle;
 
534
 
 
535
   DBG8("sane_hpaio_close()\n"); 
 
536
 
 
537
   if (ps == NULL || ps != session)
 
538
   {
 
539
      BUG("invalid sane_close\n");
 
540
      return;
 
541
   }
 
542
 
 
543
   ps->bb_close(ps);
 
544
   bb_unload(ps);
 
545
 
 
546
   if (ps->dd > 0)
 
547
   {
 
548
      if (ps->cd > 0)
 
549
         hpmud_close_channel(ps->dd, ps->cd);
 
550
      hpmud_close_device(ps->dd);
 
551
   }
 
552
    
 
553
   free(ps);
 
554
   session = NULL;
 
555
}
 
556
 
 
557
const SANE_Option_Descriptor *marvell_get_option_descriptor(SANE_Handle handle, SANE_Int option)
 
558
{
 
559
   struct marvell_session *ps = (struct marvell_session *)handle;
 
560
 
 
561
   DBG8("sane_hpaio_get_option_descriptor(option=%s)\n", ps->option[option].name);
 
562
 
 
563
   if (option < 0 || option >= MARVELL_OPTION_MAX)
 
564
      return NULL;
 
565
 
 
566
   return &ps->option[option];
 
567
}
 
568
 
 
569
SANE_Status marvell_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int *set_result)
 
570
{
 
571
   struct marvell_session *ps = (struct marvell_session *)handle;
 
572
   SANE_Int *int_value = value, mset_result=0;
 
573
   int i, stat=SANE_STATUS_INVAL;
 
574
   char sz[64];
 
575
 
 
576
   switch(option)
 
577
   {
 
578
      case MARVELL_OPTION_COUNT:
 
579
         if (action == SANE_ACTION_GET_VALUE)
 
580
         {
 
581
            *int_value = MARVELL_OPTION_MAX;
 
582
            stat = SANE_STATUS_GOOD;
 
583
         }
 
584
         break;
 
585
      case MARVELL_OPTION_SCAN_MODE:
 
586
         if (action == SANE_ACTION_GET_VALUE)
 
587
         {
 
588
            for (i=0; ps->scan_mode_list[i]; i++)
 
589
            {
 
590
               if (ps->current_scan_mode == ps->scan_mode_map[i])
 
591
               {
 
592
                  strcpy(value, ps->scan_mode_list[i]);
 
593
                  stat = SANE_STATUS_GOOD;
 
594
                  break;
 
595
               }
 
596
            }
 
597
         }
 
598
         else if (action == SANE_ACTION_SET_VALUE)
 
599
         {
 
600
            for (i=0; ps->scan_mode_list[i]; i++)
 
601
            {
 
602
               if (strcasecmp(ps->scan_mode_list[i], value) == 0)
 
603
               {
 
604
                  ps->current_scan_mode = ps->scan_mode_map[i];
 
605
                  mset_result |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
 
606
                  stat = SANE_STATUS_GOOD;
 
607
                  break;
 
608
               }
 
609
            }
 
610
         }
 
611
         else
 
612
         {  /* Set default. */
 
613
            ps->current_scan_mode = ps->scan_mode_map[0];
 
614
            stat = SANE_STATUS_GOOD;
 
615
         }
 
616
         break;
 
617
      case MARVELL_OPTION_INPUT_SOURCE:
 
618
         if (action == SANE_ACTION_GET_VALUE)
 
619
         {
 
620
            for (i=0; ps->input_source_list[i]; i++)
 
621
            {
 
622
               if (ps->current_input_source == ps->input_source_map[i])
 
623
               {
 
624
                  strcpy(value, ps->input_source_list[i]);
 
625
                  stat = SANE_STATUS_GOOD;
 
626
                  break;
 
627
               }
 
628
            }
 
629
         }
 
630
         else if (action == SANE_ACTION_SET_VALUE)
 
631
         {
 
632
            for (i=0; ps->input_source_list[i]; i++)
 
633
            {
 
634
               if (strcasecmp(ps->input_source_list[i], value) == 0)
 
635
               {
 
636
                  ps->current_input_source = ps->input_source_map[i];
 
637
                  stat = SANE_STATUS_GOOD;
 
638
                  break;
 
639
               }
 
640
            }
 
641
         }
 
642
         else
 
643
         {  /* Set default. */
 
644
            ps->current_input_source = ps->input_source_map[0];
 
645
            stat = SANE_STATUS_GOOD;
 
646
         }
 
647
         break;
 
648
      case MARVELL_OPTION_SCAN_RESOLUTION:
 
649
         if (action == SANE_ACTION_GET_VALUE)
 
650
         {
 
651
            *int_value = ps->current_resolution;
 
652
            stat = SANE_STATUS_GOOD;
 
653
         }
 
654
         else if (action == SANE_ACTION_SET_VALUE)
 
655
         {
 
656
            for (i=1; i <= ps->resolution_list[0]; i++)
 
657
            {
 
658
               if (ps->resolution_list[i] == *int_value)
 
659
               {
 
660
                  ps->current_resolution = *int_value;
 
661
                  mset_result |= SANE_INFO_RELOAD_PARAMS;
 
662
                  stat = SANE_STATUS_GOOD;
 
663
                  break;
 
664
               }
 
665
            }
 
666
         }
 
667
         else
 
668
         {  /* Set default. */
 
669
            ps->current_resolution = 75;
 
670
            stat = SANE_STATUS_GOOD;
 
671
         }
 
672
         break;
 
673
      case MARVELL_OPTION_CONTRAST:
 
674
         if (action == SANE_ACTION_GET_VALUE)
 
675
         {
 
676
            *int_value = ps->current_contrast;
 
677
            stat = SANE_STATUS_GOOD;
 
678
         }
 
679
         else if (action == SANE_ACTION_SET_VALUE)
 
680
         {
 
681
            if (*int_value >= MARVELL_CONTRAST_MIN && *int_value <= MARVELL_CONTRAST_MAX)
 
682
            {
 
683
               ps->current_contrast = *int_value;
 
684
               stat = SANE_STATUS_GOOD;
 
685
               break;
 
686
            }
 
687
         }
 
688
         else
 
689
         {  /* Set default. */
 
690
            ps->current_contrast = MARVELL_CONTRAST_DEFAULT;
 
691
            stat = SANE_STATUS_GOOD;
 
692
         }
 
693
         break;
 
694
      case MARVELL_OPTION_TL_X:
 
695
         if (action == SANE_ACTION_GET_VALUE)
 
696
         {
 
697
            *int_value = ps->currentTlx;
 
698
            stat = SANE_STATUS_GOOD;
 
699
         }
 
700
         else if (action == SANE_ACTION_SET_VALUE)
 
701
         {
 
702
            if (*int_value >= ps->tlxRange.min && *int_value <= ps->tlxRange.max)
 
703
            {
 
704
               ps->currentTlx = *int_value;
 
705
               mset_result |= SANE_INFO_RELOAD_PARAMS;
 
706
               stat = SANE_STATUS_GOOD;
 
707
               break;
 
708
            }
 
709
         }
 
710
         else
 
711
         {  /* Set default. */
 
712
            ps->currentTlx = ps->tlxRange.min;
 
713
            stat = SANE_STATUS_GOOD;
 
714
         }
 
715
         break;
 
716
      case MARVELL_OPTION_TL_Y:
 
717
         if (action == SANE_ACTION_GET_VALUE)
 
718
         {
 
719
            *int_value = ps->currentTly;
 
720
            stat = SANE_STATUS_GOOD;
 
721
         }
 
722
         else if (action == SANE_ACTION_SET_VALUE)
 
723
         {
 
724
            if (*int_value >= ps->tlyRange.min && *int_value <= ps->tlyRange.max)
 
725
            {
 
726
               
 
727
               ps->currentTly = *int_value;
 
728
               mset_result |= SANE_INFO_RELOAD_PARAMS;
 
729
               stat = SANE_STATUS_GOOD;
 
730
               break;
 
731
            }
 
732
         }
 
733
         else
 
734
         {  /* Set default. */
 
735
            ps->currentTly = ps->tlyRange.min;
 
736
            stat = SANE_STATUS_GOOD;
 
737
         }
 
738
         break;
 
739
      case MARVELL_OPTION_BR_X:
 
740
         if (action == SANE_ACTION_GET_VALUE)
 
741
         {
 
742
            *int_value = ps->currentBrx;
 
743
            stat = SANE_STATUS_GOOD;
 
744
         }
 
745
         else if (action == SANE_ACTION_SET_VALUE)
 
746
         {
 
747
            if (*int_value >= ps->brxRange.min && *int_value <= ps->brxRange.max)
 
748
            {
 
749
               ps->currentBrx = *int_value;
 
750
               mset_result |= SANE_INFO_RELOAD_PARAMS;
 
751
               stat = SANE_STATUS_GOOD;
 
752
               break;
 
753
            }
 
754
         }
 
755
         else
 
756
         {  /* Set default. */
 
757
            ps->currentBrx = ps->brxRange.max;
 
758
            stat = SANE_STATUS_GOOD;
 
759
         }
 
760
         break;
 
761
      case MARVELL_OPTION_BR_Y:
 
762
         if (action == SANE_ACTION_GET_VALUE)
 
763
         {
 
764
            *int_value = ps->currentBry;
 
765
            stat = SANE_STATUS_GOOD;
 
766
         }
 
767
         else if (action == SANE_ACTION_SET_VALUE)
 
768
         {
 
769
            if (*int_value >= ps->bryRange.min && *int_value <= ps->bryRange.max)
 
770
            {
 
771
               ps->currentBry = *int_value;
 
772
               mset_result |= SANE_INFO_RELOAD_PARAMS;
 
773
               stat = SANE_STATUS_GOOD;
 
774
               break;
 
775
            }
 
776
            BUG("value=%d brymin=%d brymax=%d\n", *int_value, ps->bryRange.min, ps->bryRange.max);
 
777
         }
 
778
         else
 
779
         {  /* Set default. */
 
780
            ps->currentBry = ps->bryRange.max;
 
781
            stat = SANE_STATUS_GOOD;
 
782
         }
 
783
         break;
 
784
      default:
 
785
         break;
 
786
   }
 
787
 
 
788
   if (set_result)
 
789
      *set_result = mset_result;
 
790
 
 
791
   if (stat != SANE_STATUS_GOOD)
 
792
   {
 
793
      BUG("control_option failed: option=%s action=%s\n", ps->option[option].name, 
 
794
                  action==SANE_ACTION_GET_VALUE ? "get" : action==SANE_ACTION_SET_VALUE ? "set" : "auto");
 
795
   }
 
796
 
 
797
   DBG8("sane_hpaio_control_option (option=%s action=%s value=%s)\n", ps->option[option].name, 
 
798
                        action==SANE_ACTION_GET_VALUE ? "get" : action==SANE_ACTION_SET_VALUE ? "set" : "auto",
 
799
     value ? ps->option[option].type == SANE_TYPE_STRING ? (char *)value : psnprintf(sz, sizeof(sz), "%d", *(int *)value) : "na");
 
800
 
 
801
   return stat;
 
802
}
 
803
 
 
804
SANE_Status marvell_get_parameters(SANE_Handle handle, SANE_Parameters *params)
 
805
{
 
806
   struct marvell_session *ps = (struct marvell_session *)handle;
 
807
 
 
808
   set_extents(ps);
 
809
 
 
810
   ps->bb_get_parameters(ps, params, ps->ip_handle ? 1 : 0);
 
811
 
 
812
   DBG8("sane_hpaio_get_parameters(): format=%d, last_frame=%d, lines=%d, depth=%d, pixels_per_line=%d, bytes_per_line=%d\n",
 
813
                    params->format, params->last_frame, params->lines, params->depth, params->pixels_per_line, params->bytes_per_line);
 
814
 
 
815
   return SANE_STATUS_GOOD;
 
816
}
 
817
 
 
818
SANE_Status marvell_start(SANE_Handle handle)
 
819
{
 
820
   struct marvell_session *ps = (struct marvell_session *)handle;
 
821
   SANE_Parameters pp;
 
822
   IP_IMAGE_TRAITS traits;
 
823
   IP_XFORM_SPEC xforms[IP_MAX_XFORMS], *pXform=xforms;
 
824
   int stat, ret;
 
825
//   int tmo=EXCEPTION_TIMEOUT*2;
 
826
 
 
827
   DBG8("sane_hpaio_start()\n");
 
828
   ps->is_user_cancel = 0;
 
829
   
 
830
   if (set_extents(ps))
 
831
   {
 
832
      BUG("invalid extents: tlx=%d brx=%d tly=%d bry=%d minwidth=%d minheight%d maxwidth=%d maxheight=%d\n",
 
833
         ps->currentTlx, ps->currentTly, ps->currentBrx, ps->currentBry, ps->min_width, ps->min_height, ps->tlxRange.max, ps->tlyRange.max);
 
834
      stat = SANE_STATUS_INVAL;
 
835
      goto bugout;
 
836
   }   
 
837
 
 
838
   /* If input is ADF and ADF is empty, return SANE_STATUS_NO_DOCS. */
 
839
   if (ps->current_input_source == IS_ADF)
 
840
   {
 
841
      ret = ps->bb_is_paper_in_adf(ps);   /* 0 = no paper in adf, 1 = paper in adf, 2 = no adf, -1 = error */
 
842
      if (ret == 0)
 
843
      {
 
844
         stat = SANE_STATUS_NO_DOCS;     /* done scanning */
 
845
         SendScanEvent(ps->uri, EVENT_SCAN_ADF_NO_DOCS);
 
846
         goto bugout;
 
847
      }
 
848
      else if (ret < 0)
 
849
      {
 
850
         stat = SANE_STATUS_IO_ERROR;
 
851
         goto bugout;
 
852
      }
 
853
   }
 
854
   /* Start scan and get actual image traits. */
 
855
   if (ps->bb_start_scan(ps))
 
856
   {
 
857
      stat = SANE_STATUS_IO_ERROR;
 
858
      goto bugout;
 
859
   }
 
860
 
 
861
   SendScanEvent(ps->uri, EVENT_START_SCAN_JOB);
 
862
   memset(xforms, 0, sizeof(xforms));    
 
863
 
 
864
   /* Setup image-processing pipeline for xform. */
 
865
   if (ps->current_scan_mode == CE_BLACK_AND_WHITE1)
 
866
   {
 
867
      pXform->aXformInfo[IP_GRAY_2_BI_THRESHOLD].dword = 127;
 
868
      ADD_XFORM(X_GRAY_2_BI);
 
869
   }
 
870
 
 
871
   /* Setup x/y cropping for xform. (Actually we let cm1017 do it's own cropping) */
 
872
   pXform->aXformInfo[IP_CROP_LEFT].dword = 0;
 
873
   pXform->aXformInfo[IP_CROP_RIGHT].dword = 0;
 
874
   pXform->aXformInfo[IP_CROP_TOP].dword = 0;
 
875
   pXform->aXformInfo[IP_CROP_MAXOUTROWS].dword = 0;
 
876
   ADD_XFORM(X_CROP);
 
877
 
 
878
   /* Setup x/y padding for xform. (Actually we let cm1017 do it's own padding) */
 
879
   pXform->aXformInfo[IP_PAD_LEFT].dword = 0; /* # of pixels to add to left side */
 
880
   pXform->aXformInfo[IP_PAD_RIGHT].dword = 0; /* # of pixels to add to right side */
 
881
   pXform->aXformInfo[IP_PAD_TOP].dword = 0; /* # of rows to add to top */
 
882
   pXform->aXformInfo[IP_PAD_BOTTOM].dword = 0;  /* # of rows to add to bottom */
 
883
   pXform->aXformInfo[IP_PAD_VALUE].dword = ps->current_scan_mode == CE_BLACK_AND_WHITE1 ? 0 : -1;   /* lineart white = 0, rgb white = -1 */ 
 
884
   pXform->aXformInfo[IP_PAD_MIN_HEIGHT].dword = 0;
 
885
   ADD_XFORM(X_PAD);
 
886
 
 
887
   /* Open image processor. */
 
888
   if ((ret = ipOpen(pXform-xforms, xforms, 0, &ps->ip_handle)) != IP_DONE)
 
889
   {
 
890
      BUG("unable open image processor: err=%d\n", ret);
 
891
      stat = SANE_STATUS_INVAL;
 
892
      goto bugout;
 
893
   }
 
894
 
 
895
   /* Get actual input image attributes. See bb_start_scan(). */
 
896
   ps->bb_get_parameters(ps, &pp, 1);
 
897
 
 
898
   /* Now set known input image attributes. */
 
899
   traits.iPixelsPerRow = pp.pixels_per_line;
 
900
   switch(ps->current_scan_mode)
 
901
   {
 
902
      case CE_BLACK_AND_WHITE1:         /* lineart */
 
903
      case CE_GRAY8:
 
904
         traits.iBitsPerPixel = 8;     /* grayscale */
 
905
         break;
 
906
      case CE_RGB24:
 
907
      default:
 
908
         traits.iBitsPerPixel = 24;      /* color */
 
909
         break;
 
910
   }
 
911
   traits.lHorizDPI = ps->current_resolution << 16;
 
912
   traits.lVertDPI = ps->current_resolution << 16;
 
913
   traits.lNumRows = pp.lines;
 
914
   traits.iNumPages = 1;
 
915
   traits.iPageNum = 1;
 
916
   traits.iComponentsPerPixel = ((traits.iBitsPerPixel % 3) ? 1 : 3);
 
917
   ipSetDefaultInputTraits(ps->ip_handle, &traits);
 
918
 
 
919
   /* Get output image attributes from the image processor. */
 
920
   ipGetImageTraits(ps->ip_handle, NULL, &ps->image_traits);  /* get valid image traits */
 
921
 
 
922
   stat = SANE_STATUS_GOOD;
 
923
 
 
924
bugout:
 
925
   if (stat != SANE_STATUS_GOOD)
 
926
   {
 
927
      if (ps->ip_handle)
 
928
      {
 
929
         ipClose(ps->ip_handle); 
 
930
         ps->ip_handle = 0;
 
931
      }
 
932
      ps->bb_end_scan(ps, stat == SANE_STATUS_IO_ERROR ? 1: 0);
 
933
   }
 
934
 
 
935
   return stat;
 
936
}
 
937
 
 
938
SANE_Status marvell_read(SANE_Handle handle, SANE_Byte *data, SANE_Int maxLength, SANE_Int *length)
 
939
{
 
940
   struct marvell_session *ps = (struct marvell_session *)handle;
 
941
   int ret, stat=SANE_STATUS_IO_ERROR;
 
942
//   int tmo=EXCEPTION_TIMEOUT;
 
943
 
 
944
   DBG8("sane_hpaio_read() handle=%p data=%p maxLength=%d\n", (void *)handle, data, maxLength);
 
945
 
 
946
   ret = get_ip_data(ps, data, maxLength, length);
 
947
 
 
948
   if(ret & (IP_INPUT_ERROR | IP_FATAL_ERROR))
 
949
   {
 
950
      BUG("ipConvert error=%x\n", ret);
 
951
      goto bugout;
 
952
   }
 
953
 
 
954
   if (ret & IP_DONE)
 
955
   {
 
956
      stat = SANE_STATUS_EOF;
 
957
      SendScanEvent(ps->uri, EVENT_END_SCAN_JOB);
 
958
   }
 
959
   else
 
960
      stat = SANE_STATUS_GOOD;
 
961
 
 
962
bugout:
 
963
   if (stat != SANE_STATUS_GOOD)
 
964
   {
 
965
      if (ps->ip_handle)
 
966
      {
 
967
           /* Note always call ipClose when SANE_STATUS_EOF, do not depend on sane_cancel because sane_cancel is only called at the end of a batch job. */ 
 
968
         ipClose(ps->ip_handle);  
 
969
         ps->ip_handle = 0;
 
970
      } 
 
971
       //If user has cancelled scan from device
 
972
      if (ps->is_user_cancel)
 
973
      {
 
974
          //Don't do anything. sane_hpaio_cancel() will be invoked automatically
 
975
          SendScanEvent(ps->uri, EVENT_SCAN_CANCEL);
 
976
          return SANE_STATUS_CANCELLED;
 
977
 
 
978
       }
 
979
       else 
 
980
           {
 
981
               ps->bb_end_page(ps, stat == SANE_STATUS_IO_ERROR ? 1: 0);
 
982
           }
 
983
   }
 
984
 
 
985
   DBG8("-sane_hpaio_read() output=%p bytes_read=%d maxLength=%d status=%d\n", data, *length, maxLength, stat);
 
986
 
 
987
   return stat;
 
988
}
 
989
 
 
990
void marvell_cancel(SANE_Handle handle)
 
991
{
 
992
   struct marvell_session *ps = (struct marvell_session *)handle;
 
993
 
 
994
   DBG8("sane_hpaio_cancel()\n"); 
 
995
 
 
996
   /*
 
997
    * Sane_cancel is always called at the end of the scan job. Note that on a multiple page scan job 
 
998
    * sane_cancel is called only once.
 
999
    */
 
1000
   ps->is_user_cancel = 1 ;
 
1001
   
 
1002
   if (ps->ip_handle)
 
1003
   {
 
1004
      ipClose(ps->ip_handle); 
 
1005
      ps->ip_handle = 0;
 
1006
   }
 
1007
   ps->bb_end_scan(ps, 0);
 
1008
}
 
1009