1 /*
2 * epsonds-ops.c - Epson ESC/I-2 driver, support routines.
3 *
4 * Copyright (C) 2015 Tower Technologies
5 * Author: Alessandro Zummo <a.zummo@towertech.it>
6 *
7 * This file is part of the SANE package.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2.
12 */
13
14 #define DEBUG_DECLARE_ONLY
15
16 #include "sane/config.h"
17
18 #include <unistd.h> /* sleep */
19 #ifdef HAVE_SYS_SELECT_H
20 #include <sys/select.h>
21 #endif
22
23 #include "epsonds.h"
24 #include "epsonds-io.h"
25 #include "epsonds-ops.h"
26 #include "epsonds-cmd.h"
27
28 extern struct mode_param mode_params[];
29
30 /* Define the different scan sources */
31 #define STRING_FLATBED SANE_I18N("Flatbed")
32 #define STRING_ADFFRONT SANE_I18N("ADF Front")
33 #define STRING_ADFDUPLEX SANE_I18N("ADF Duplex")
34
35 extern SANE_String_Const source_list[];
36
37 void
eds_dev_init(epsonds_device * dev)38 eds_dev_init(epsonds_device *dev)
39 {
40 dev->res_list = malloc(sizeof(SANE_Word));
41 dev->res_list[0] = 0;
42
43 dev->depth_list = malloc(sizeof(SANE_Word));
44 dev->depth_list[0] = 0;
45 }
46
47 SANE_Status
eds_dev_post_init(struct epsonds_device * dev)48 eds_dev_post_init(struct epsonds_device *dev)
49 {
50 SANE_String_Const *source_list_add = source_list;
51
52 DBG(10, "%s\n", __func__);
53
54 if (dev->has_fb)
55 *source_list_add++ = STRING_FLATBED;
56
57 if (dev->has_adf)
58 *source_list_add++ = STRING_ADFFRONT;
59
60 if (dev->adf_is_duplex)
61 *source_list_add++ = STRING_ADFDUPLEX;
62
63 if (source_list[0] == 0
64 || (dev->res_list[0] == 0 && dev->dpi_range.min == 0)
65 || dev->depth_list[0] == 0) {
66
67 DBG(1, "something is wrong in the discovery process, aborting.\n");
68 DBG(1, "sources: %ld, res: %d, depths: %d.\n",
69 source_list_add - source_list, dev->res_list[0], dev->depth_list[0]);
70
71 return SANE_STATUS_INVAL;
72 }
73
74 return SANE_STATUS_GOOD;
75 }
76
77 SANE_Bool
eds_is_model(epsonds_device * dev,const char * model)78 eds_is_model(epsonds_device *dev, const char *model)
79 {
80 if (dev->model == NULL)
81 return SANE_FALSE;
82
83 if (strncmp(dev->model, model, strlen(model)) == 0)
84 return SANE_TRUE;
85
86 return SANE_FALSE;
87 }
88
89 SANE_Status
eds_add_resolution(epsonds_device * dev,int r)90 eds_add_resolution(epsonds_device *dev, int r)
91 {
92 DBG(10, "%s: add (dpi): %d\n", __func__, r);
93
94 /* first element is the list size */
95 dev->res_list[0]++;
96 dev->res_list = realloc(dev->res_list,
97 (dev->res_list[0] + 1) *
98 sizeof(SANE_Word));
99 if (dev->res_list == NULL)
100 return SANE_STATUS_NO_MEM;
101
102 dev->res_list[dev->res_list[0]] = r;
103
104 return SANE_STATUS_GOOD;
105 }
106
107 SANE_Status
eds_set_resolution_range(epsonds_device * dev,int min,int max)108 eds_set_resolution_range(epsonds_device *dev, int min, int max)
109 {
110 DBG(10, "%s: set min/max (dpi): %d/%d\n", __func__, min, max);
111
112 dev->dpi_range.min = min;
113 dev->dpi_range.max = max;
114 dev->dpi_range.quant = 1;
115
116 return SANE_STATUS_GOOD;
117 }
118
119 void
eds_set_fbf_area(epsonds_device * dev,int x,int y,int unit)120 eds_set_fbf_area(epsonds_device *dev, int x, int y, int unit)
121 {
122 if (x == 0 || y == 0)
123 return;
124
125 dev->fbf_x_range.min = 0;
126 dev->fbf_x_range.max = SANE_FIX(x * MM_PER_INCH / unit);
127 dev->fbf_x_range.quant = 0;
128
129 dev->fbf_y_range.min = 0;
130 dev->fbf_y_range.max = SANE_FIX(y * MM_PER_INCH / unit);
131 dev->fbf_y_range.quant = 0;
132
133 DBG(5, "%s: %f,%f %f,%f %d [mm]\n",
134 __func__,
135 SANE_UNFIX(dev->fbf_x_range.min),
136 SANE_UNFIX(dev->fbf_y_range.min),
137 SANE_UNFIX(dev->fbf_x_range.max),
138 SANE_UNFIX(dev->fbf_y_range.max), unit);
139 }
140
141 void
eds_set_adf_area(struct epsonds_device * dev,int x,int y,int unit)142 eds_set_adf_area(struct epsonds_device *dev, int x, int y, int unit)
143 {
144 dev->adf_x_range.min = 0;
145 dev->adf_x_range.max = SANE_FIX(x * MM_PER_INCH / unit);
146 dev->adf_x_range.quant = 0;
147
148 dev->adf_y_range.min = 0;
149 dev->adf_y_range.max = SANE_FIX(y * MM_PER_INCH / unit);
150 dev->adf_y_range.quant = 0;
151
152 DBG(5, "%s: %f,%f %f,%f %d [mm]\n",
153 __func__,
154 SANE_UNFIX(dev->adf_x_range.min),
155 SANE_UNFIX(dev->adf_y_range.min),
156 SANE_UNFIX(dev->adf_x_range.max),
157 SANE_UNFIX(dev->adf_y_range.max), unit);
158 }
159
160 void
eds_set_tpu_area(struct epsonds_device * dev,int x,int y,int unit)161 eds_set_tpu_area(struct epsonds_device *dev, int x, int y, int unit)
162 {
163 dev->tpu_x_range.min = 0;
164 dev->tpu_x_range.max = SANE_FIX(x * MM_PER_INCH / unit);
165 dev->tpu_x_range.quant = 0;
166
167 dev->tpu_y_range.min = 0;
168 dev->tpu_y_range.max = SANE_FIX(y * MM_PER_INCH / unit);
169 dev->tpu_y_range.quant = 0;
170
171 DBG(5, "%s: %f,%f %f,%f %d [mm]\n",
172 __func__,
173 SANE_UNFIX(dev->tpu_x_range.min),
174 SANE_UNFIX(dev->tpu_y_range.min),
175 SANE_UNFIX(dev->tpu_x_range.max),
176 SANE_UNFIX(dev->tpu_y_range.max), unit);
177 }
178
179 SANE_Status
eds_add_depth(epsonds_device * dev,SANE_Word depth)180 eds_add_depth(epsonds_device *dev, SANE_Word depth)
181 {
182 DBG(5, "%s: add (bpp): %d\n", __func__, depth);
183
184 /* > 8bpp not implemented yet */
185 if (depth > 8) {
186 DBG(1, " not supported");
187 return SANE_STATUS_GOOD;
188 }
189
190 if (depth > dev->max_depth)
191 dev->max_depth = depth;
192
193 /* first element is the list size */
194 dev->depth_list[0]++;
195 dev->depth_list = realloc(dev->depth_list,
196 (dev->depth_list[0] + 1) *
197 sizeof(SANE_Word));
198
199 if (dev->depth_list == NULL)
200 return SANE_STATUS_NO_MEM;
201
202 dev->depth_list[dev->depth_list[0]] = depth;
203
204 return SANE_STATUS_GOOD;
205 }
206
207 SANE_Status
eds_init_parameters(epsonds_scanner * s)208 eds_init_parameters(epsonds_scanner *s)
209 {
210 int dpi, bytes_per_pixel;
211
212 memset(&s->params, 0, sizeof(SANE_Parameters));
213
214 /* setup depth according to our mode table */
215 if (mode_params[s->val[OPT_MODE].w].depth == 1)
216 s->params.depth = 1;
217 else
218 s->params.depth = s->val[OPT_DEPTH].w;
219
220 dpi = s->val[OPT_RESOLUTION].w;
221
222 if (SANE_UNFIX(s->val[OPT_BR_Y].w) == 0 ||
223 SANE_UNFIX(s->val[OPT_BR_X].w) == 0)
224 return SANE_STATUS_INVAL;
225
226 s->left = ((SANE_UNFIX(s->val[OPT_TL_X].w) / MM_PER_INCH) *
227 s->val[OPT_RESOLUTION].w) + 0.5;
228
229 s->top = ((SANE_UNFIX(s->val[OPT_TL_Y].w) / MM_PER_INCH) *
230 s->val[OPT_RESOLUTION].w) + 0.5;
231
232 s->params.pixels_per_line =
233 ((SANE_UNFIX(s->val[OPT_BR_X].w -
234 s->val[OPT_TL_X].w) / MM_PER_INCH) * dpi) + 0.5;
235 s->params.lines =
236 ((SANE_UNFIX(s->val[OPT_BR_Y].w -
237 s->val[OPT_TL_Y].w) / MM_PER_INCH) * dpi) + 0.5;
238
239 DBG(5, "%s: tlx %f tly %f brx %f bry %f [mm]\n",
240 __func__,
241 SANE_UNFIX(s->val[OPT_TL_X].w), SANE_UNFIX(s->val[OPT_TL_Y].w),
242 SANE_UNFIX(s->val[OPT_BR_X].w), SANE_UNFIX(s->val[OPT_BR_Y].w));
243
244 DBG(5, "%s: tlx %d tly %d brx %d bry %d [dots @ %d dpi]\n",
245 __func__, s->left, s->top,
246 s->params.pixels_per_line, s->params.lines, dpi);
247
248 /* center aligned? */
249 if (s->hw->alignment == 1) {
250
251 SANE_Int offset = ((SANE_UNFIX(s->hw->x_range->max) / MM_PER_INCH) * dpi) + 0.5;
252
253 s->left += ((offset - s->params.pixels_per_line) / 2);
254
255 DBG(5, "%s: centered to tlx %d tly %d brx %d bry %d [dots @ %d dpi]\n",
256 __func__, s->left, s->top,
257 s->params.pixels_per_line, s->params.lines, dpi);
258 }
259
260 /*
261 * Calculate bytes_per_pixel and bytes_per_line for
262 * any color depths.
263 *
264 * The default color depth is stored in mode_params.depth:
265 */
266
267 /* this works because it can only be set to 1, 8 or 16 */
268 bytes_per_pixel = s->params.depth / 8;
269 if (s->params.depth % 8) { /* just in case ... */
270 bytes_per_pixel++;
271 }
272
273 /* pixels_per_line is rounded to the next 8bit boundary */
274 s->params.pixels_per_line = s->params.pixels_per_line & ~7;
275
276 s->params.last_frame = SANE_TRUE;
277
278 switch (s->val[OPT_MODE].w) {
279 case MODE_BINARY:
280 case MODE_GRAY:
281 s->params.format = SANE_FRAME_GRAY;
282 s->params.bytes_per_line =
283 s->params.pixels_per_line * s->params.depth / 8;
284 break;
285 case MODE_COLOR:
286 s->params.format = SANE_FRAME_RGB;
287 s->params.bytes_per_line =
288 3 * s->params.pixels_per_line * bytes_per_pixel;
289 break;
290 }
291
292 if (s->params.bytes_per_line == 0) {
293 DBG(1, "bytes_per_line is ZERO\n");
294 return SANE_STATUS_INVAL;
295 }
296
297 /*
298 * If (s->top + s->params.lines) is larger than the max scan area, reset
299 * the number of scan lines:
300 * XXX: precalculate the maximum scanning area elsewhere (use dev max_y)
301 */
302
303 if (SANE_UNFIX(s->val[OPT_BR_Y].w) / MM_PER_INCH * dpi <
304 (s->params.lines + s->top)) {
305 s->params.lines =
306 ((int) SANE_UNFIX(s->val[OPT_BR_Y].w) / MM_PER_INCH *
307 dpi + 0.5) - s->top;
308 }
309
310 if (s->params.lines <= 0) {
311 DBG(1, "wrong number of lines: %d\n", s->params.lines);
312 return SANE_STATUS_INVAL;
313 }
314
315 return SANE_STATUS_GOOD;
316 }
317 #define min(A,B) (((A)<(B)) ? (A) : (B))
318
319 void
eds_copy_image_from_ring(epsonds_scanner * s,SANE_Byte * data,SANE_Int max_length,SANE_Int * length)320 eds_copy_image_from_ring(epsonds_scanner *s, SANE_Byte *data, SANE_Int max_length,
321 SANE_Int *length)
322 {
323 int lines, available;
324 int hw_line_size = (s->params.bytes_per_line + s->dummy);
325
326 available = eds_ring_avail(s->current);
327 if (max_length > available)
328 max_length = available;
329
330 lines = min(max_length / s->params.bytes_per_line, available / hw_line_size);
331
332 DBG(18, "copying %d lines (%d, %d, %d)\n", lines, s->params.bytes_per_line, s->dummy, s->params.depth);
333
334 /* need more data? */
335 if (lines == 0) {
336 *length = 0;
337 return;
338 }
339
340 *length = (lines * s->params.bytes_per_line);
341
342 /* we need to copy one line at time, skipping
343 * dummy bytes at the end of each line
344 */
345
346 /* lineart */
347 if (s->params.depth == 1) {
348
349 while (lines--) {
350
351 int i;
352 SANE_Byte *p;
353
354 eds_ring_read(s->current, s->line_buffer, s->params.bytes_per_line);
355 eds_ring_skip(s->current, s->dummy);
356
357 p = s->line_buffer;
358
359 for (i = 0; i < s->params.bytes_per_line; i++) {
360 *data++ = ~*p++;
361 }
362 }
363
364 } else { /* gray and color */
365
366 while (lines--) {
367
368 eds_ring_read(s->current, data, s->params.bytes_per_line);
369 eds_ring_skip(s->current, s->dummy);
370
371 data += s->params.bytes_per_line;
372
373 }
374 }
375 }
376
eds_ring_init(ring_buffer * ring,SANE_Int size)377 SANE_Status eds_ring_init(ring_buffer *ring, SANE_Int size)
378 {
379 ring->ring = realloc(ring->ring, size);
380 if (!ring->ring) {
381 return SANE_STATUS_NO_MEM;
382 }
383
384 ring->size = size;
385 ring->fill = 0;
386 ring->end = ring->ring + size;
387 ring->wp = ring->rp = ring->ring;
388
389 return SANE_STATUS_GOOD;
390 }
391
eds_ring_write(ring_buffer * ring,SANE_Byte * buf,SANE_Int size)392 SANE_Status eds_ring_write(ring_buffer *ring, SANE_Byte *buf, SANE_Int size)
393 {
394 SANE_Int tail;
395
396 if (size > (ring->size - ring->fill)) {
397 DBG(1, "ring buffer full, requested: %d, available: %d\n", size, ring->size - ring->fill);
398 return SANE_STATUS_NO_MEM;
399 }
400
401 tail = ring->end - ring->wp;
402 if (size < tail) {
403
404 memcpy(ring->wp, buf, size);
405
406 ring->wp += size;
407 ring->fill += size;
408
409 } else {
410
411 memcpy(ring->wp, buf, tail);
412 size -= tail;
413
414 ring->wp = ring->ring;
415 memcpy(ring->wp, buf + tail, size);
416
417 ring->wp += size;
418 ring->fill += (tail + size);
419 }
420
421 return SANE_STATUS_GOOD;
422 }
423
eds_ring_read(ring_buffer * ring,SANE_Byte * buf,SANE_Int size)424 SANE_Int eds_ring_read(ring_buffer *ring, SANE_Byte *buf, SANE_Int size)
425 {
426 SANE_Int tail;
427
428 DBG(18, "reading from ring, %d bytes available\n", (int)ring->fill);
429
430 /* limit read to available */
431 if (size > ring->fill) {
432 DBG(1, "not enough data in the ring, shouldn't happen\n");
433 size = ring->fill;
434 }
435
436 tail = ring->end - ring->rp;
437 if (size < tail) {
438
439 memcpy(buf, ring->rp, size);
440
441 ring->rp += size;
442 ring->fill -= size;
443
444 return size;
445
446 } else {
447
448 memcpy(buf, ring->rp, tail);
449 size -= tail;
450
451 ring->rp = ring->ring;
452 memcpy(buf + tail, ring->rp, size);
453
454 ring->rp += size;
455 ring->fill -= (size + tail);
456
457 return size + tail;
458 }
459 }
460
eds_ring_skip(ring_buffer * ring,SANE_Int size)461 SANE_Int eds_ring_skip(ring_buffer *ring, SANE_Int size)
462 {
463 SANE_Int tail;
464 /* limit skip to available */
465 if (size > ring->fill)
466 size = ring->fill;
467
468 tail = ring->end - ring->rp;
469 if (size < tail) {
470 ring->rp += size;
471 } else {
472
473 ring->rp = ring->ring + (size - tail);
474 }
475
476 ring->fill -= size;
477
478 return size;
479 }
480
eds_ring_avail(ring_buffer * ring)481 SANE_Int eds_ring_avail(ring_buffer *ring)
482 {
483 return ring->fill;
484 }
485
eds_ring_flush(ring_buffer * ring)486 void eds_ring_flush(ring_buffer *ring)
487 {
488 eds_ring_skip(ring, ring->fill);
489 }
490
eds_ring_destory(ring_buffer * ring)491 void eds_ring_destory(ring_buffer *ring)
492 {
493 if (ring->ring)
494 {
495 free(ring->ring);
496 ring->ring = NULL;
497 }
498 }
499