1 /* sane - Scanner Access Now Easy.
2 
3    pieusb_buffer.c
4 
5    Copyright (C) 2012-2015 Jan Vleeshouwers, Michael Rickmann, Klaus Kaempf
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; either version 2 of the
12    License, or (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful, but
15    WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <https://www.gnu.org/licenses/>.
21 
22    As a special exception, the authors of SANE give permission for
23    additional uses of the libraries contained in this release of SANE.
24 
25    The exception is that, if you link a SANE library with other files
26    to produce an executable, this does not by itself cause the
27    resulting executable to be covered by the GNU General Public
28    License.  Your use of that executable is in no way restricted on
29    account of linking the SANE library code into it.
30 
31    This exception does not, however, invalidate any other reasons why
32    the executable file might be covered by the GNU General Public
33    License.
34 
35    If you submit changes to SANE to the maintainers to be included in
36    a subsequent release, you agree by submitting the changes that
37    those changes may be distributed with this exception intact.
38 
39    If you write modifications of your own for SANE, it is your choice
40    whether to permit this exception to apply to your modifications.
41    If you do not wish that, delete this exception notice.  */
42 
43 /* =========================================================================
44  *
45  * Read buffer
46  *
47  * Data obtained from the scanner cannot be presented to the frontend immediately.
48  * The scanner returns data in the 'index' or 'line' color format, which means it
49  * returns data in batches which contain a single color of a scan line.
50  *
51  * These must finally be converted into the SANE data format (data for a single
52  * pixel in consecutive bytes). Apart from that, sane_read() must be able to
53  * return any amount of data bytes.
54  *
55  * In between, data processing may be necessary, usually requiring the whole
56  * image to be available.
57  *
58  * To accommodate all this, the buffer stores all samples as 16-bit values, even
59  * if the original values are 8-bit or even 1 bit. This is a waste of space, but
60  * makes processing much easier, and it is only temporary.
61  *
62  * The read buffer is constructed by a call to buffer_create(), which initializes
63  * the buffer based on width, height, number of colors and depth. The buffer
64  * contains data organized in color planes, with each plane consisting of lines,
65  * each line of a fixed number of (single color) pixels, and each pixel of a fixed
66  * number of bits (or bytes).
67  *
68  * The buffer maintains read and write pointers.
69  *
70  * Multi-color data with a bit depth of 1 are packed in single color bytes, so
71  * the data obtained from the scanner does not need conversion.
72  *
73  * ========================================================================= */
74 
75 #define DEBUG_DECLARE_ONLY
76 
77 /* Configuration defines */
78 #include "../include/sane/config.h"
79 
80 /* SANE includes */
81 #include "../include/sane/sane.h"
82 #include "../include/sane/saneopts.h"
83 #include "../include/sane/sanei_usb.h"
84 #include "../include/sane/sanei_config.h"
85 
86 /* Backend includes */
87 #define BACKEND_NAME pieusb
88 #include "../include/sane/sanei_backend.h"
89 #include "pieusb.h"
90 
91 #include "pieusb_specific.h"
92 #include "pieusb_buffer.h"
93 
94 #ifdef HAVE_ALLOCA_H
95 #include <alloca.h>
96 #endif
97 
98 #include <stdio.h>
99 #include <fcntl.h>
100 #include <sys/mman.h>
101 
102 #include "byteorder.h"
103 
104 static void buffer_update_read_index(struct Pieusb_Read_Buffer* buffer, int increment);
105 
106 /* READER */
107 
108 /**
109  * Initialize the buffer.
110  * A scanner has a Pieusb_Read_Buffer struct as one of its members.
111  *
112  * @param buffer the buffer to initialize
113  * @param width number of pixels on a line (row)
114  * @param height number of lines in the buffer (pixels in a column)
115  * @param colors bitmap specifying the colors in the scanned data (bitmap: 0000 IBGR)
116  * @param depth number of bits of a color
117  * @param bigendian how to store multi-byte values: bigendian if true
118  * @param maximum_size maximum size of buffer (-1 = size of image)
119  */
120 
121 SANE_Status
sanei_pieusb_buffer_create(struct Pieusb_Read_Buffer* buffer, SANE_Int width, SANE_Int height, SANE_Byte color_spec, SANE_Byte depth)122 sanei_pieusb_buffer_create(struct Pieusb_Read_Buffer* buffer, SANE_Int width, SANE_Int height, SANE_Byte color_spec, SANE_Byte depth)
123 {
124     int k, result;
125     unsigned int buffer_size_bytes;
126     unsigned char g;
127 
128     /* Base parameters */
129     buffer->width = width;
130     buffer->height = height;
131     buffer->colors = 0;
132     if (color_spec & 0x01) { buffer->color_index_red = 0; buffer->colors++; } else { buffer->color_index_red = -1; }
133     if (color_spec & 0x02) { buffer->color_index_green = 1; buffer->colors++; } else { buffer->color_index_green = -1; }
134     if (color_spec & 0x04) { buffer->color_index_blue = 2; buffer->colors++; } else { buffer->color_index_blue = -1; }
135     if (color_spec & 0x08) { buffer->color_index_infrared = 3; buffer->colors++; } else { buffer->color_index_infrared = -1; }
136     if (buffer->colors == 0) {
137         DBG(DBG_error, "sanei_pieusb_buffer_create(): no colors specified\n");
138         return SANE_STATUS_INVAL;
139     }
140     buffer->depth = depth;
141     if (depth < 1 || depth > 16) {
142         DBG(DBG_error, "sanei_pieusb_buffer_create(): unsupported depth %d\n", depth);
143         return SANE_STATUS_INVAL;
144     }
145     buffer->packing_density = (depth == 1) ? 8 : 1; /* These are all the situations we have */
146 
147     /* Derived*/
148     buffer->packet_size_bytes = (buffer->depth * buffer->packing_density + 7) / 8;
149     buffer->line_size_packets = (buffer->width + buffer->packing_density -1) / buffer->packing_density;
150     buffer->line_size_bytes = buffer->line_size_packets * buffer->packet_size_bytes;
151     buffer->image_size_bytes = buffer->colors * buffer->height * buffer->line_size_bytes;
152 
153     /* Create empty file */
154     snprintf(buffer->buffer_name, L_tmpnam, "/tmp/sane.XXXXXX");
155     if (buffer->data_file != 0) /* might still be open from previous invocation */
156       close(buffer->data_file);
157     buffer->data_file = mkstemp(buffer->buffer_name);
158     if (buffer->data_file == -1) {
159         buffer->data_file = 0;
160         buffer->data = NULL;
161 	perror("sanei_pieusb_buffer_create(): error opening image buffer file");
162         return SANE_STATUS_IO_ERROR;
163     }
164     /* Stretch the file size */
165     buffer_size_bytes = buffer->width * buffer->height * buffer->colors * sizeof(SANE_Uint);
166     if (buffer_size_bytes == 0) {
167         close(buffer->data_file);
168         buffer->data_file = 0;
169         DBG(DBG_error, "sanei_pieusb_buffer_create(): buffer_size is zero: width %d, height %d, colors %d\n", buffer->width, buffer->height, buffer->colors);
170         return SANE_STATUS_INVAL;
171     }
172     result = lseek(buffer->data_file, buffer_size_bytes-1, SEEK_SET);
173     if (result == -1) {
174 	close(buffer->data_file);
175         buffer->data_file = 0;
176         buffer->data = NULL;
177         DBG(DBG_error, "sanei_pieusb_buffer_create(): error calling lseek() to 'stretch' the file to %d bytes\n", buffer_size_bytes-1);
178 	perror("sanei_pieusb_buffer_create(): error calling lseek()");
179         return SANE_STATUS_INVAL;
180     }
181     /* Write one byte at the end */
182     g = 0x00;
183     result = write(buffer->data_file, &g, 1);
184     if (result < 0) {
185 	close(buffer->data_file);
186         buffer->data_file = 0;
187         buffer->data = NULL;
188 	perror("sanei_pieusb_buffer_create(): error writing a byte at the end of the file");
189         return SANE_STATUS_IO_ERROR;
190     }
191 #ifdef HAVE_MMAP
192     /* Create memory map */
193     buffer->data = mmap(NULL, buffer_size_bytes, PROT_WRITE | PROT_READ, MAP_SHARED, buffer->data_file, 0);
194     if (buffer->data == MAP_FAILED) {
195         close(buffer->data_file);
196         buffer->data = NULL;
197         perror("sanei_pieusb_buffer_create(): error mapping file");
198         return SANE_STATUS_INVAL;
199     }
200 #else
201 #error mmap(2) not available, aborting
202 #endif
203     buffer->data_size = buffer_size_bytes;
204     /* Reading and writing */
205     buffer->p_read = calloc(buffer->colors, sizeof(SANE_Uint*));
206     if (buffer->p_read == NULL)
207       return SANE_STATUS_NO_MEM;
208     buffer->p_write = calloc(buffer->colors, sizeof(SANE_Uint*));
209     if (buffer->p_write == NULL)
210       return SANE_STATUS_NO_MEM;
211     for (k = 0; k < buffer->colors; k++) {
212         buffer->p_write[k] = buffer->data + k * buffer->height * buffer->width;
213         buffer->p_read[k] = buffer->p_write[k];
214     }
215     buffer->read_index[0] = 0;
216     buffer->read_index[1] = 0;
217     buffer->read_index[2] = 0;
218     buffer->read_index[3] = 0;
219 
220     /* Statistics */
221     buffer->bytes_read = 0;
222     buffer->bytes_written = 0;
223     buffer->bytes_unread = 0;
224 
225     DBG(DBG_info,"pieusb: Read buffer created: w=%d h=%d ncol=%d depth=%d in file %s\n",
226       buffer->width, buffer->height, buffer->colors, buffer->depth, buffer->buffer_name);
227   return SANE_STATUS_GOOD;
228 }
229 
230 /**
231  * Delete buffer and free its resources
232  *
233  * @param buffer
234  */
235 void
sanei_pieusb_buffer_delete(struct Pieusb_Read_Buffer* buffer)236 sanei_pieusb_buffer_delete(struct Pieusb_Read_Buffer* buffer)
237 {
238 #ifdef HAVE_MMAP
239     munmap(buffer->data, buffer->data_size);
240 #else
241 #error mmap(2) not available, aborting
242 #endif
243     /* ftruncate(buffer->data_file,0); Can we delete given a file-descriptor? */
244     close(buffer->data_file);
245     /* remove fs entry */
246     unlink(buffer->buffer_name);
247     buffer->data_file = 0;
248     buffer->data_size = 0;
249     free(buffer->p_read);
250     free(buffer->p_write);
251     buffer->data = 0;
252     buffer->width = 0;
253     buffer->height = 0;
254     buffer->depth = 0;
255     buffer->colors = 0;
256     buffer->packing_density = 0;
257 
258     DBG(DBG_info,"pieusb: Read buffer deleted\n");
259 }
260 
261 /**
262  * Add a line to the reader buffer, for the given color.
263  * The buffer checks and decides how to interpret the data.
264  *
265  * @param buffer
266  * @param color Color code for line
267  * @param line
268  * @param size Number of bytes in line
269  * @return 1 if successful, 0 if not
270  */
271 SANE_Int
sanei_pieusb_buffer_put_single_color_line(struct Pieusb_Read_Buffer* buffer, SANE_Byte color, void* line, SANE_Int size)272 sanei_pieusb_buffer_put_single_color_line(struct Pieusb_Read_Buffer* buffer, SANE_Byte color, void* line, SANE_Int size)
273 {
274 
275     SANE_Int c, k, m, n;
276 
277     /* Check index code */
278     c = -1;
279     switch (color) {
280         case 'R':
281             c = buffer->color_index_red;
282             break;
283         case 'G':
284             c = buffer->color_index_green;
285             break;
286         case 'B':
287             c = buffer->color_index_blue;
288             break;
289         case 'I':
290             c = buffer->color_index_infrared;
291             break;
292     }
293     if (c == -1) {
294         DBG(DBG_error, "sanei_pieusb_buffer_put_single_color_line(): color '%c' not specified when buffer was created\n", color);
295         return 0;
296     }
297     DBG(DBG_info_buffer, "sanei_pieusb_buffer_put_single_color_line() line color = %d (0=R, 1=G, 2=B, 3=I)\n",c);
298 
299     /* Check line size (for a line with a single color) */
300     if (buffer->line_size_bytes != size) {
301         DBG(DBG_error, "sanei_pieusb_buffer_put_single_color_line(): incorrect line size, expecting %d, got %d\n", buffer->line_size_bytes, size);
302         return 0;
303     }
304 
305     /* The general approach for all densities and packet sizes
306      * - process packet_size_bytes at a time
307      * - use packing_density to decode the full packet into separate values
308      * - now save these values as neighbouring pixels on the current line
309      * Use custom code for the 1-byte and 2-byte single sample cases,
310      * because the general approach is a bit overkill for them.
311      */
312 
313     if (buffer->packet_size_bytes == 1 && buffer->packing_density == 1) {
314         uint8_t* p_packet = (uint8_t*)line;
315         n = 0;
316         while (n < size) {
317             /* Get next packet data & store in buffer */
318             *buffer->p_write[c]++ = *p_packet++;
319             n++;
320         }
321     } else if (buffer->packet_size_bytes == 2 && buffer->packing_density == 1) {
322         uint16_t* p_packet = (uint16_t*)line;
323         n = 0;
324         while (n < size) {
325             /* Get next packet data & store in buffer */
326             *buffer->p_write[c]++ = le16toh (*p_packet++);
327             n += 2;
328         }
329     } else {
330         uint8_t* p_packet = (uint8_t*)line;
331         uint8_t *packet = (uint8_t *)alloca(buffer->packet_size_bytes * sizeof(uint8_t));
332         SANE_Uint val;
333         uint8_t mask = ~(0xFF >> buffer->depth); /* byte with depth most significant bits set */
334         n = 0;
335         while (n < size) {
336             /* Get next packet data */
337             for (k = 0; k < buffer->packet_size_bytes; k++) packet[k] = *p_packet++;
338             /* Unpack packing_density samples from packet. Of course,
339              * buffer->depth * packing_density <= # bits in packet.
340              * That is checked at buffer creation. */
341             for (k = 0; k < buffer->packing_density; k++) {
342                 /* Take 1st depth bits and store in val */
343                 val = (packet[0] & mask) >> (8-buffer->depth);
344                 /* Now shift packet bytes depth bits left */
345                 for (m = 0; m < buffer->packet_size_bytes; m++) {
346                     /* Shift left one sample */
347                     packet[m] <<= buffer->depth;
348                     if (m < buffer->packet_size_bytes-1) {
349                         /* If there are more bytes, insert 1st depth bits of next byte */
350                         packet[m] |= (packet[m+1] >> (8-buffer->depth));
351                     }
352                 }
353                 /* Store in buffer */
354                 *buffer->p_write[c]++ = val;
355             }
356             n += buffer->packet_size_bytes;
357         }
358     }
359 
360     /* Update state & statistics */
361     buffer->bytes_written += size;
362     buffer->bytes_unread += size;
363 
364     /* Output current buffer state */
365     /* buffer_output_state(buffer); */
366 
367     return 1;
368 }
369 
370 /**
371  * Write line of full color pixels to the buffer.
372  *
373  * @param buffer Read buffer
374  * @param pixel array of full color pixel data
375  * @param size Number of bytes in the line
376  * @return 1 if successful, 0 if not
377  */
378 /**
379  *
380  */
381 SANE_Int
sanei_pieusb_buffer_put_full_color_line(struct Pieusb_Read_Buffer* buffer, void* line, int size)382 sanei_pieusb_buffer_put_full_color_line(struct Pieusb_Read_Buffer* buffer, void* line, int size)
383 {
384     int k, c, m, n;
385 
386     DBG(DBG_info_buffer, "sanei_pieusb_buffer_put_full_color_line() entered\n");
387 
388     /* Check line size */
389     if (buffer->line_size_bytes * buffer->colors != size) {
390         DBG(DBG_error, "sanei_pieusb_buffer_put_full_color_line(): incorrect line size, expecting %d, got %d\n", buffer->line_size_bytes * buffer->colors, size);
391         return 0;
392     }
393 
394     /* The general approach for all densities and packet sizes
395      * - process packet_size_bytes at a time
396      * - use packing_density to decode the full packet into separate values
397      * - now save these values as neighbouring pixels on the current line
398      * Use custom code for the 1-byte and 2-byte single sample cases,
399      * because the general approach is a bit overkill for them.
400      */
401 
402     if (buffer->packet_size_bytes == 1 && buffer->packing_density == 1) {
403         uint8_t* p_packet = (uint8_t*)line;
404         n = 0;
405         while (n < size) {
406             /* Get next packet data & store in buffer */
407             for (c = 0; c < buffer->colors; c++) {
408                 *buffer->p_write[c]++ = *p_packet++;
409                 n++;
410             }
411         }
412     } else if (buffer->packet_size_bytes == 2 && buffer->packing_density == 1) {
413         uint16_t* p_packet = (uint16_t*)line;
414         n = 0;
415         while (n < size) {
416             /* Get next packet data & store in buffer */
417             for (c = 0; c < buffer->colors; c++) {
418                 *buffer->p_write[c]++ = le16toh (*p_packet++);
419                 n += 2;
420             }
421         }
422     } else {
423         uint8_t* p_packet = (uint8_t*)line;
424         uint8_t *packet = (uint8_t *)alloca(buffer->packet_size_bytes * sizeof(uint8_t));
425         SANE_Uint val;
426         uint8_t mask = ~(0xFF >> buffer->depth); /* byte with depth most significant bits set */
427         /* DBG(DBG_info,"buffer_put_full_color_line(): mask %02x\n",mask); */
428         n = 0;
429         while (n < size) {
430             /* Get next packet data */
431             for (c = 0; c < buffer->colors; c++) {
432                 for (k = 0; k < buffer->packet_size_bytes; k++) {
433                     packet[k] = *p_packet++;
434                     /* DBG(DBG_info,"buffer_put_full_color_line(): packet[%d] = %02x\n",k,packet[k]); */
435                 }
436                 /* Unpack packing_density samples from packet. Of course,
437                  * buffer->depth * packing_density <= # bits in packet.
438                  * That is checked at buffer creation. */
439                 for (k = 0; k < buffer->packing_density; k++) {
440                     /* Take 1st depth bits and store in val */
441                     val = (packet[0] & mask) >> (8-buffer->depth);
442                     /* DBG(DBG_info,"buffer_put_full_color_line(): val[%d] = %02x\n",k,val); */
443                     /* Now shift packet bytes depth bits left */
444                     for (m = 0; m < buffer->packet_size_bytes; m++) {
445                         /* Shift left one sample */
446                         packet[m] <<= buffer->depth;
447                         /* DBG(DBG_info,"buffer_put_full_color_line(): shift packet[%d] = %02x\n",m,packet[m]); */
448                         if (m < buffer->packet_size_bytes-1) {
449                             /* If there are more bytes, insert 1st depth bits of next byte */
450                             packet[m] |= (packet[m+1] >> (8-buffer->depth));
451                             /* DBG(DBG_info,"buffer_put_full_color_line(): shift packet[%d] = %02x\n",m,packet[m]); */
452                         }
453                     }
454                     /* Store in buffer */
455                     *buffer->p_write[c]++ = val;
456                 }
457                 n += buffer->packet_size_bytes;
458             }
459         }
460     }
461 
462     /* Update state & statistics */
463     buffer->bytes_written += size;
464     buffer->bytes_unread += size;
465 
466     /* Output current buffer state */
467     /* buffer_output_state(buffer); */
468 
469     return 1;
470 }
471 
472 /**
473  * Return bytes from the buffer. Do not mind pixel boundaries.
474  * Since the image data is organized in color planes, return bytes from the
475  * planes in the defined order. Take care to return multi-byte values after
476  * each other. Pack unpacked values.
477  *
478  * @param buffer Buffer to return bytes from.
479  * @param data Byte array to return bytes in
480  * @param max_len Maximum number of bytes returned
481  * @param len Actual number of bytes returned
482  */
483 void
sanei_pieusb_buffer_get(struct Pieusb_Read_Buffer* buffer, SANE_Byte* data, SANE_Int max_len, SANE_Int* len)484 sanei_pieusb_buffer_get(struct Pieusb_Read_Buffer* buffer, SANE_Byte* data, SANE_Int max_len, SANE_Int* len)
485 {
486     SANE_Byte *pdata;
487     SANE_Int n, i, n_bits, N;
488 
489     DBG(DBG_info_buffer, "sanei_pieusb_buffer_get() entered\n");
490 
491     /* Read from the p_read locations */
492     pdata = data;
493     n = 0;
494     N = buffer->width * buffer->height;
495     /* Determine bytes to return */
496     if (buffer->packet_size_bytes == 1 && buffer->packing_density == 1) {
497         /* Single byte values in buffer */
498         while (n < max_len && buffer->bytes_read < buffer->image_size_bytes) {
499             /* Return byte*/
500             *pdata++ = *(buffer->data + N*buffer->read_index[0] + buffer->width*buffer->read_index[1] + buffer->read_index[2]) & 0xFF;
501             /* Update read indices */
502             buffer_update_read_index(buffer,1);
503             /* Update number of bytes read */
504             buffer->bytes_read++;
505             n++;
506         }
507     } else if (buffer->packet_size_bytes == 1 && buffer->packing_density == 8) {
508         /* Unpacked bits in buffer: repack */
509         while (n < max_len && buffer->bytes_read < buffer->image_size_bytes) {
510             uint8_t val = 0;
511             /* How many bits to pack? At the end of a line it may be less than 8 */
512             n_bits = 8;
513             if (buffer->width - buffer->read_index[2] < 8) {
514                 n_bits = buffer->width - buffer->read_index[2];
515             }
516             /* Pack n_bits samples from same color plane */
517             for (i = 0; i < n_bits; i++) {
518                 if (*(buffer->data + N*buffer->read_index[0] + buffer->width*buffer->read_index[1] + buffer->read_index[2] + i) > 0) {
519                     val |= (0x80 >> i);
520                 }
521             }
522             /* Return byte */
523             *pdata++ = val;
524             /* Update read indices */
525             buffer_update_read_index(buffer,n_bits);
526             /* Update number of bytes read */
527             buffer->bytes_read++;
528             n++;
529         }
530     } else if (buffer->packet_size_bytes == 2) {
531         /* Two-byte values in buffer */
532         while (n < max_len && buffer->bytes_read < buffer->image_size_bytes) {
533             /* Pointer to byte to return */
534             SANE_Uint val = *(buffer->data + N*buffer->read_index[0] + buffer->width*buffer->read_index[1] + buffer->read_index[2]);
535             /* Return byte */
536             if (buffer->read_index[3] == 0) {
537                 *pdata++ = *((SANE_Byte*)(&val));
538             } else {
539                 *pdata++ = *((SANE_Byte*)(&val)+1);
540             }
541             /* Update read indices */
542             buffer_update_read_index(buffer,1);
543             /* Update number of bytes read */
544             buffer->bytes_read++;
545             n++;
546         }
547     } else {
548         /* not implemented */
549         DBG(DBG_error, "buffer_put(): paccket size & density of %d/%d not implemented\n", buffer->packet_size_bytes, buffer->packing_density);
550         return;
551     }
552     *len = n;
553 
554     /* Update statistics */
555     buffer->bytes_unread -= n;
556 
557     /* Output current buffer state */
558     /* buffer_output_state(buffer); */
559 }
560 
561 /**
562  * Update read index to point a given number of bytes past the current position.
563  *
564  * @param buffer the buffer to initialize
565  * @param increment the amount of bytes to move the index
566  */
buffer_update_read_index(struct Pieusb_Read_Buffer* buffer, int increment)567 static void buffer_update_read_index(struct Pieusb_Read_Buffer* buffer, int increment)
568 {
569     /* Update read indices
570      * [3] = byte-index in 2-byte value: increased first, if we have 2-byte data
571      * [2] = index of pixel on line: increased after color plane
572      * [1] = index of line: increased after line is complete
573      * [0] = color index: increased first since SANE requires full color pixels */
574     if (buffer->read_index[3] == 0 && buffer->packet_size_bytes == 2) {
575         buffer->read_index[3] = 1;
576     } else {
577         buffer->read_index[3] = 0;
578         buffer->read_index[0]++;
579         if (buffer->read_index[0] == buffer->colors) {
580             buffer->read_index[0] = 0;
581             buffer->read_index[2] += increment;
582             if (buffer->read_index[2] >= buffer->width) {
583                 buffer->read_index[2] = 0;
584                 buffer->read_index[1]++;
585             }
586         }
587     }
588 }
589 
590 #if 0
591 /**
592  * Display the buffer state.
593  *
594  * @param buffer the buffer to initialize
595  */
596 
597 static void buffer_output_state(struct Pieusb_Read_Buffer* buffer)
598 {
599     SANE_Int line_size;
600     SANE_Int N, k, loc[4];
601 
602     line_size = buffer->line_size_bytes * buffer->colors; /* Full line size in bytes */
603 
604     DBG(DBG_info_buffer, "Buffer data\n");
605     DBG(DBG_info_buffer,"  width/height/colors/depth = %d %d %d %d (buffer size %d)\n",
606         buffer->width, buffer->height, buffer->colors, buffer->depth, buffer->image_size_bytes);
607 
608     /* Summary */
609     N = buffer->width * buffer->height;
610     for (k = 0; k < buffer->colors; k++) {
611         loc[k] = buffer->p_read[k] - buffer->data - k*N;
612     }
613     for (k = buffer->colors; k < 4; k++) {
614         loc[k] = 0;
615     }
616     DBG(DBG_info_buffer, "  reading at: lines = %d:%d:%d:%d\n", loc[0], loc[1], loc[2], loc[3]);
617     for (k = 0; k < buffer->colors; k++) {
618         loc[k] = buffer->p_write[k] - buffer->data - k*N;
619     }
620     for (k = buffer->colors; k < 4; k++) {
621         loc[k] = 0;
622     }
623     DBG(DBG_info_buffer, "  writing at: lines = %d:%d:%d:%d\n", loc[0], loc[1], loc[2], loc[3]);
624 
625     /* Progress */
626     double fdata = (double)buffer->bytes_unread/buffer->image_size_bytes*100;
627     double fread = (double)buffer->bytes_read/buffer->image_size_bytes*100;
628     double fwritten = (double)buffer->bytes_written/buffer->image_size_bytes*100;
629     DBG(DBG_info_buffer, "  byte counts: image = %d, data = %d (%.0f%%), read = %d (%.0f%%), written = %d (%.0f%%)\n",
630         buffer->image_size_bytes, buffer->bytes_unread, fdata, buffer->bytes_read, fread, buffer->bytes_written, fwritten);
631     DBG(DBG_info_buffer, "  line counts: image = %.1f, data = %.1f, read = %.1f, written = %.1f\n",
632         (double)buffer->image_size_bytes/line_size, (double)buffer->bytes_unread/line_size, (double)buffer->bytes_read/line_size, (double)buffer->bytes_written/line_size);
633 
634 }
635 #endif
636