• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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