kopia lustrzana https://gitlab.com/sane-project/backends
Merge branch 'master' into 'master'
Fix hpljm1005 #723 See merge request sane-project/backends!819merge-requests/569/merge
commit
bff8d25007
|
@ -46,16 +46,11 @@
|
||||||
#define BUILD 1
|
#define BUILD 1
|
||||||
|
|
||||||
#include "../include/sane/config.h"
|
#include "../include/sane/config.h"
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#define BACKEND_NAME hpljm1005
|
#define BACKEND_NAME hpljm1005
|
||||||
|
@ -110,10 +105,10 @@ static int cur_idx;
|
||||||
#define RGB 1
|
#define RGB 1
|
||||||
#define GRAY 0
|
#define GRAY 0
|
||||||
|
|
||||||
#define MAX_X_H 0x350
|
#define MAX_X_H 0x351
|
||||||
#define MAX_Y_H 0x490
|
#define MAX_Y_H 0x490
|
||||||
#define MAX_X_S 220
|
#define MAX_X_S 216
|
||||||
#define MAX_Y_S 330
|
#define MAX_Y_S 297
|
||||||
|
|
||||||
#define OPTION_MAX 9
|
#define OPTION_MAX 9
|
||||||
|
|
||||||
|
@ -144,6 +139,12 @@ static const SANE_String_Const mode_list[] = {
|
||||||
#define STATUS_SCANNING 1
|
#define STATUS_SCANNING 1
|
||||||
#define STATUS_CANCELING 2
|
#define STATUS_CANCELING 2
|
||||||
|
|
||||||
|
struct buffer_s {
|
||||||
|
char *buffer;
|
||||||
|
size_t w_offset;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
struct device_s
|
struct device_s
|
||||||
{
|
{
|
||||||
struct device_s *next;
|
struct device_s *next;
|
||||||
|
@ -151,15 +152,16 @@ struct device_s
|
||||||
int idx; /* Index in the usbid array */
|
int idx; /* Index in the usbid array */
|
||||||
int dn; /* Usb "Handle" */
|
int dn; /* Usb "Handle" */
|
||||||
SANE_Option_Descriptor optiond[OPTION_MAX];
|
SANE_Option_Descriptor optiond[OPTION_MAX];
|
||||||
char *buffer;
|
struct buffer_s buf_r; /* also for gray mode */
|
||||||
int bufs;
|
struct buffer_s buf_g;
|
||||||
|
struct buffer_s buf_b;
|
||||||
int read_offset;
|
int read_offset;
|
||||||
int write_offset_r;
|
|
||||||
int write_offset_g;
|
|
||||||
int write_offset_b;
|
|
||||||
int status;
|
int status;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
int height_h;
|
||||||
|
int data_width; /* width + some padding 0xFF which should be ignored */
|
||||||
|
int scanned_pixels;
|
||||||
SANE_Word optionw[OPTION_MAX];
|
SANE_Word optionw[OPTION_MAX];
|
||||||
uint32_t conf_data[512];
|
uint32_t conf_data[512];
|
||||||
uint32_t packet_data[512];
|
uint32_t packet_data[512];
|
||||||
|
@ -186,58 +188,6 @@ round2(double x)
|
||||||
return (double)(x >= 0.0) ? (int)(x+0.5) : (int)(x-0.5);
|
return (double)(x >= 0.0) ? (int)(x+0.5) : (int)(x-0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
update_img_size (struct device_s *dev)
|
|
||||||
{
|
|
||||||
int dx, dy;
|
|
||||||
|
|
||||||
/* Only update the width when not scanning,
|
|
||||||
* otherwise the scanner give us the correct width */
|
|
||||||
if (dev->status == STATUS_SCANNING)
|
|
||||||
{
|
|
||||||
dev->height = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dx = dev->optionw[X2_OFFSET] - dev->optionw[X1_OFFSET];
|
|
||||||
dy = dev->optionw[Y2_OFFSET] - dev->optionw[Y1_OFFSET];
|
|
||||||
|
|
||||||
switch (dev->optionw[RES_OFFSET])
|
|
||||||
{
|
|
||||||
case 75:
|
|
||||||
dev->width = round2 ((dx / ((double) MAX_X_S)) * 640);
|
|
||||||
dev->height = round2 ((dy / ((double) MAX_Y_S)) * 880);
|
|
||||||
break;
|
|
||||||
case 100:
|
|
||||||
dev->width = round2 ((dx / ((double) MAX_X_S)) * 848);
|
|
||||||
dev->height = round2 ((dy / ((double) MAX_Y_S)) * 1180);
|
|
||||||
break;
|
|
||||||
case 150:
|
|
||||||
dev->width = round2 ((dx / ((double) MAX_X_S)) * 1264);
|
|
||||||
dev->height = round2 ((dy / ((double) MAX_Y_S)) * 1775);
|
|
||||||
break;
|
|
||||||
case 200:
|
|
||||||
dev->width = round2 ((dx / ((double) MAX_X_S)) * 1696);
|
|
||||||
dev->height = round2 ((dy / ((double) MAX_Y_S)) * 2351);
|
|
||||||
break;
|
|
||||||
case 300:
|
|
||||||
dev->width = round2 ((dx / ((double) MAX_X_S)) * 2528);
|
|
||||||
dev->height = round2 ((dy / ((double) MAX_Y_S)) * 3510);
|
|
||||||
break;
|
|
||||||
case 600:
|
|
||||||
dev->width = round2 ((dx / ((double) MAX_X_S)) * 5088);
|
|
||||||
dev->height = round2 ((dy / ((double) MAX_Y_S)) * 7020);
|
|
||||||
break;
|
|
||||||
case 1200:
|
|
||||||
dev->width = round2 ((dx / ((double) MAX_X_S)) * 10208);
|
|
||||||
dev->height = round2 ((dy / ((double) MAX_Y_S)) * 14025);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG(2,"New image size: %dx%d\n",dev->width, dev->height);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function is copy/pasted from the Epson backend */
|
/* This function is copy/pasted from the Epson backend */
|
||||||
static size_t
|
static size_t
|
||||||
max_string_size (const SANE_String_Const strings[])
|
max_string_size (const SANE_String_Const strings[])
|
||||||
|
@ -721,7 +671,6 @@ sane_get_parameters (SANE_Handle h, SANE_Parameters * p)
|
||||||
p->last_frame = SANE_TRUE;
|
p->last_frame = SANE_TRUE;
|
||||||
p->depth = 8;
|
p->depth = 8;
|
||||||
|
|
||||||
update_img_size (dev);
|
|
||||||
p->pixels_per_line = dev->width;
|
p->pixels_per_line = dev->width;
|
||||||
p->lines = dev->height;
|
p->lines = dev->height;
|
||||||
p->bytes_per_line = p->pixels_per_line;
|
p->bytes_per_line = p->pixels_per_line;
|
||||||
|
@ -805,7 +754,7 @@ send_conf (struct device_s *dev)
|
||||||
dev->conf_data[21] = 0;
|
dev->conf_data[21] = 0;
|
||||||
dev->conf_data[22] = htonl (0x491);
|
dev->conf_data[22] = htonl (0x491);
|
||||||
dev->conf_data[23] = htonl (0x352);
|
dev->conf_data[23] = htonl (0x352);
|
||||||
|
dev->height_h = y2 - y1;
|
||||||
if (dev->optionw[COLOR_OFFSET] == RGB)
|
if (dev->optionw[COLOR_OFFSET] == RGB)
|
||||||
{
|
{
|
||||||
dev->conf_data[15] = htonl (0x2);
|
dev->conf_data[15] = htonl (0x2);
|
||||||
|
@ -821,116 +770,151 @@ send_conf (struct device_s *dev)
|
||||||
sanei_usb_write_bulk (dev->dn, (unsigned char *) dev->conf_data, &size);
|
sanei_usb_write_bulk (dev->dn, (unsigned char *) dev->conf_data, &size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SANE_Status
|
static SANE_Status create_buffer(struct buffer_s *buf, int buffer_size) {
|
||||||
get_data (struct device_s *dev)
|
if (buf->buffer)
|
||||||
|
{
|
||||||
|
free(buf->buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf->buffer = malloc(buffer_size);
|
||||||
|
if (!buf->buffer)
|
||||||
|
return SANE_STATUS_NO_MEM;
|
||||||
|
buf->size = buffer_size;
|
||||||
|
buf->w_offset = 0;
|
||||||
|
return SANE_STATUS_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SANE_Status create_buffers(struct device_s *dev, int buf_size) {
|
||||||
|
if (create_buffer(&dev->buf_r, buf_size) != SANE_STATUS_GOOD)
|
||||||
|
return SANE_STATUS_NO_MEM;
|
||||||
|
if (dev->optionw[COLOR_OFFSET] == RGB)
|
||||||
|
{
|
||||||
|
if (create_buffer(&dev->buf_g, buf_size) != SANE_STATUS_GOOD)
|
||||||
|
return SANE_STATUS_NO_MEM;
|
||||||
|
if (create_buffer(&dev->buf_b, buf_size) != SANE_STATUS_GOOD)
|
||||||
|
return SANE_STATUS_NO_MEM;
|
||||||
|
}
|
||||||
|
return SANE_STATUS_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SANE_Status remove_buffers(struct device_s *dev) {
|
||||||
|
if (dev->buf_r.buffer)
|
||||||
|
free(dev->buf_r.buffer);
|
||||||
|
if (dev->buf_g.buffer)
|
||||||
|
free(dev->buf_g.buffer);
|
||||||
|
if (dev->buf_b.buffer)
|
||||||
|
free(dev->buf_b.buffer);
|
||||||
|
dev->buf_r.w_offset = dev->buf_g.w_offset = dev->buf_b.w_offset = 0;
|
||||||
|
dev->buf_r.size = dev->buf_g.size = dev->buf_b.size = 0;
|
||||||
|
dev->buf_r.buffer = dev->buf_g.buffer = dev->buf_b.buffer = NULL;
|
||||||
|
dev->read_offset = 0;
|
||||||
|
return SANE_STATUS_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SANE_Status get_data (struct device_s *dev)
|
||||||
{
|
{
|
||||||
int color;
|
int color;
|
||||||
size_t size;
|
size_t size;
|
||||||
int packet_size;
|
int packet_size;
|
||||||
unsigned char *buffer = (unsigned char *) dev->packet_data;
|
unsigned char *buffer = (unsigned char *) dev->packet_data;
|
||||||
if (dev->status == STATUS_IDLE)
|
if (dev->status == STATUS_IDLE)
|
||||||
|
{
|
||||||
|
DBG(101, "STATUS == IDLE\n");
|
||||||
return SANE_STATUS_IO_ERROR;
|
return SANE_STATUS_IO_ERROR;
|
||||||
|
}
|
||||||
/* first wait a standard data pkt */
|
/* first wait a standard data pkt */
|
||||||
do
|
do
|
||||||
|
{
|
||||||
|
size = 32;
|
||||||
|
sanei_usb_read_bulk (dev->dn, buffer, &size);
|
||||||
|
if (size)
|
||||||
{
|
{
|
||||||
size = 32;
|
if (ntohl (dev->packet_data[0]) == MAGIC_NUMBER)
|
||||||
sanei_usb_read_bulk (dev->dn, buffer, &size);
|
{
|
||||||
if (size)
|
if (ntohl (dev->packet_data[1]) == PKT_DATA)
|
||||||
{
|
break;
|
||||||
if (ntohl (dev->packet_data[0]) == MAGIC_NUMBER)
|
if (ntohl (dev->packet_data[1]) == PKT_END_DATA)
|
||||||
{
|
{
|
||||||
if (ntohl (dev->packet_data[1]) == PKT_DATA)
|
dev->status = STATUS_IDLE;
|
||||||
break;
|
DBG(100,"End of scan encountered on device %s\n",dev->devname);
|
||||||
if (ntohl (dev->packet_data[1]) == PKT_END_DATA)
|
send_pkt (PKT_GO_IDLE, 0, dev);
|
||||||
{
|
wait_ack (dev, NULL);
|
||||||
dev->status = STATUS_IDLE;
|
wait_ack (dev, NULL);
|
||||||
DBG(100,"End of scan encountered on device %s\n",dev->devname);
|
send_pkt (PKT_UNKNOW_1, 0, dev);
|
||||||
send_pkt (PKT_GO_IDLE, 0, dev);
|
wait_ack (dev, NULL);
|
||||||
wait_ack (dev, NULL);
|
send_pkt (PKT_RESET, 0, dev);
|
||||||
wait_ack (dev, NULL);
|
sleep (2); /* Time for the scanning head to go back home */
|
||||||
send_pkt (PKT_UNKNOW_1, 0, dev);
|
return SANE_STATUS_EOF;
|
||||||
wait_ack (dev, NULL);
|
}
|
||||||
send_pkt (PKT_RESET, 0, dev);
|
}
|
||||||
sleep (2); /* Time for the scanning head to go back home */
|
|
||||||
return SANE_STATUS_EOF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
while (1);
|
} while (1);
|
||||||
packet_size = ntohl (dev->packet_data[5]);
|
packet_size = ntohl (dev->packet_data[5]);
|
||||||
if (!dev->buffer)
|
if (! dev->buf_r.buffer)
|
||||||
{
|
{
|
||||||
dev->bufs = packet_size - 24 /* size of header */ ;
|
/*
|
||||||
if (dev->optionw[COLOR_OFFSET] == RGB)
|
For some reason scanner sends packets in order:
|
||||||
dev->bufs *= 3;
|
<start> R G B ... R G B R G B RRR GGG BBB <end>
|
||||||
dev->buffer = malloc (dev->bufs);
|
To hanle the last triple portion create a triple size buffer
|
||||||
if (!dev->buffer)
|
*/
|
||||||
return SANE_STATUS_NO_MEM;
|
int buf_size = (packet_size - 24) * 3; /* 24 - size of header */ ;
|
||||||
dev->write_offset_r = 0;
|
if (create_buffers(dev, buf_size) != SANE_STATUS_GOOD)
|
||||||
dev->write_offset_g = 1;
|
return SANE_STATUS_NO_MEM;
|
||||||
dev->write_offset_b = 2;
|
}
|
||||||
|
|
||||||
}
|
|
||||||
/* Get the "data header" */
|
/* Get the "data header" */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
size = 24;
|
size = 24;
|
||||||
sanei_usb_read_bulk (dev->dn, buffer, &size);
|
sanei_usb_read_bulk (dev->dn, buffer, &size);
|
||||||
}
|
} while (!size);
|
||||||
while (!size);
|
|
||||||
color = ntohl (dev->packet_data[0]);
|
color = ntohl (dev->packet_data[0]);
|
||||||
packet_size -= size;
|
packet_size -= size;
|
||||||
dev->width = ntohl (dev->packet_data[5]);
|
dev->width = ntohl (dev->packet_data[4]);
|
||||||
DBG(100,"Got data size %d on device %s. Scan width: %d\n",packet_size, dev->devname, dev->width);
|
dev->height = dev->height_h * dev->optionw[RES_OFFSET] / 100;
|
||||||
|
dev->data_width = ntohl (dev->packet_data[5]);
|
||||||
|
DBG(100,"Got data size %d on device %s. Scan width: %d, data width: %d\n",packet_size, dev->devname, dev->width, dev->data_width);
|
||||||
/* Now, read the data */
|
/* Now, read the data */
|
||||||
do
|
do
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
do
|
||||||
{
|
{
|
||||||
int j;
|
size = packet_size > 512 ? 512 : packet_size;
|
||||||
int i;
|
ret = sanei_usb_read_bulk (dev->dn, buffer, &size);
|
||||||
int ret;
|
} while (!size || ret != SANE_STATUS_GOOD);
|
||||||
do
|
packet_size -= size;
|
||||||
{
|
struct buffer_s * current_buf;
|
||||||
size = packet_size > 512 ? 512 : packet_size;
|
char color_char;
|
||||||
ret = sanei_usb_read_bulk (dev->dn, buffer, &size);
|
switch (color)
|
||||||
}
|
{
|
||||||
while (!size || ret != SANE_STATUS_GOOD);
|
case GRAY_LAYER:
|
||||||
packet_size -= size;
|
color_char = 'g';
|
||||||
switch (color)
|
current_buf = &dev->buf_r;
|
||||||
{
|
break;
|
||||||
case RED_LAYER:
|
case RED_LAYER:
|
||||||
DBG(101,"Got red layer data on device %s\n",dev->devname);
|
color_char = 'R';
|
||||||
i = dev->write_offset_r + 3 * size;
|
current_buf = &dev->buf_r;
|
||||||
if (i > dev->bufs)
|
break;
|
||||||
i = dev->bufs;
|
case GREEN_LAYER:
|
||||||
for (j = 0; dev->write_offset_r < i; dev->write_offset_r += 3)
|
color_char = 'G';
|
||||||
dev->buffer[dev->write_offset_r] = buffer[j++];
|
current_buf = &dev->buf_g;
|
||||||
break;
|
break;
|
||||||
case GREEN_LAYER:
|
case BLUE_LAYER:
|
||||||
DBG(101,"Got green layer data on device %s\n",dev->devname);
|
color_char = 'B';
|
||||||
i = dev->write_offset_g + 3 * size;
|
current_buf = &dev->buf_b;
|
||||||
if (i > dev->bufs)
|
break;
|
||||||
i = dev->bufs;
|
default:
|
||||||
for (j = 0; dev->write_offset_g < i; dev->write_offset_g += 3)
|
DBG(101, "Unknown color code: %d \n", color);
|
||||||
dev->buffer[dev->write_offset_g] = buffer[j++];
|
return SANE_STATUS_IO_ERROR;
|
||||||
break;
|
|
||||||
case BLUE_LAYER:
|
|
||||||
DBG(101,"Got blue layer data on device %s\n",dev->devname);
|
|
||||||
i = dev->write_offset_b + 3 * size;
|
|
||||||
if (i > dev->bufs)
|
|
||||||
i = dev->bufs;
|
|
||||||
for (j = 0; dev->write_offset_b < i; dev->write_offset_b += 3)
|
|
||||||
dev->buffer[dev->write_offset_b] = buffer[j++];
|
|
||||||
break;
|
|
||||||
case GRAY_LAYER:
|
|
||||||
DBG(101,"Got gray layer data on device %s\n",dev->devname);
|
|
||||||
if (dev->write_offset_r + (int)size >= dev->bufs)
|
|
||||||
size = dev->bufs - dev->write_offset_r;
|
|
||||||
memcpy (dev->buffer + dev->write_offset_r, buffer, size);
|
|
||||||
dev->write_offset_r += size;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
DBG(101,"Got %c layer data on device %s\n", color_char, dev->devname);
|
||||||
|
if (current_buf->w_offset + size > current_buf->size) {
|
||||||
|
DBG(100, "buffer overflow\n");
|
||||||
|
return SANE_STATUS_IO_ERROR;
|
||||||
|
}
|
||||||
|
memcpy(current_buf->buffer + current_buf->w_offset, buffer, size);
|
||||||
|
current_buf->w_offset += size;
|
||||||
|
}
|
||||||
while (packet_size > 0);
|
while (packet_size > 0);
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
@ -943,13 +927,8 @@ sane_start (SANE_Handle h)
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
dev->read_offset = 0;
|
dev->read_offset = 0;
|
||||||
dev->write_offset_r = 0;
|
dev->scanned_pixels = 0;
|
||||||
dev->write_offset_g = 1;
|
remove_buffers(dev);
|
||||||
dev->write_offset_b = 2;
|
|
||||||
|
|
||||||
free (dev->buffer);
|
|
||||||
dev->buffer = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
send_pkt (PKT_RESET, 0, dev);
|
send_pkt (PKT_RESET, 0, dev);
|
||||||
send_pkt (PKT_READ_STATUS, 0, dev);
|
send_pkt (PKT_READ_STATUS, 0, dev);
|
||||||
|
@ -992,16 +971,12 @@ static void
|
||||||
do_cancel(struct device_s *dev)
|
do_cancel(struct device_s *dev)
|
||||||
{
|
{
|
||||||
while (get_data (dev) == SANE_STATUS_GOOD);
|
while (get_data (dev) == SANE_STATUS_GOOD);
|
||||||
free (dev->buffer);
|
remove_buffers(dev);
|
||||||
dev->buffer = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
min3 (int r, int g, int b)
|
min3 (int r, int g, int b)
|
||||||
{
|
{
|
||||||
/* Optimize me ! */
|
|
||||||
g--;
|
|
||||||
b -= 2;
|
|
||||||
if (r < g && r < b)
|
if (r < g && r < b)
|
||||||
return r;
|
return r;
|
||||||
if (b < r && b < g)
|
if (b < r && b < g)
|
||||||
|
@ -1009,57 +984,83 @@ min3 (int r, int g, int b)
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
min_buf_w_offset (struct device_s * dev)
|
||||||
|
{
|
||||||
|
if (dev->optionw[COLOR_OFFSET] == RGB)
|
||||||
|
return min3 (dev->buf_r.w_offset, dev->buf_g.w_offset, dev->buf_b.w_offset);
|
||||||
|
return dev->buf_r.w_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_buf_synchronized(struct device_s * dev) {
|
||||||
|
if (dev->optionw[COLOR_OFFSET] == RGB)
|
||||||
|
return dev->buf_r.w_offset == dev->buf_g.w_offset
|
||||||
|
&& dev->buf_r.w_offset == dev->buf_b.w_offset;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
SANE_Status
|
SANE_Status
|
||||||
sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
|
sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
|
||||||
{
|
{
|
||||||
struct device_s *dev = (struct device_s *) h;
|
struct device_s *dev = (struct device_s *) h;
|
||||||
int available;
|
int available;
|
||||||
int ret;
|
int ret;
|
||||||
|
if (dev->optionw[COLOR_OFFSET] == RGB) {
|
||||||
|
maxlen /= 3;
|
||||||
|
}
|
||||||
*len = 0;
|
*len = 0;
|
||||||
if (dev->status == STATUS_IDLE)
|
if (dev->status == STATUS_IDLE)
|
||||||
|
{
|
||||||
|
DBG(101, "STATUS == IDLE\n");
|
||||||
return SANE_STATUS_IO_ERROR;
|
return SANE_STATUS_IO_ERROR;
|
||||||
if (dev->optionw[COLOR_OFFSET] == RGB)
|
}
|
||||||
|
while (min_buf_w_offset(dev) <= dev->read_offset)
|
||||||
|
{
|
||||||
|
ret = get_data (dev);
|
||||||
|
if (ret != SANE_STATUS_GOOD)
|
||||||
{
|
{
|
||||||
while (min3 (dev->write_offset_r, dev->write_offset_g,
|
if (min_buf_w_offset(dev) <= dev->read_offset) {
|
||||||
dev->write_offset_b) <= dev->read_offset)
|
return ret;
|
||||||
{
|
}
|
||||||
ret = get_data (dev);
|
|
||||||
if (ret != SANE_STATUS_GOOD)
|
|
||||||
{
|
|
||||||
if (min3 (dev->write_offset_r,
|
|
||||||
dev->write_offset_g,
|
|
||||||
dev->write_offset_b) <= dev->read_offset)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
available = min3 (dev->write_offset_r, dev->write_offset_g,
|
|
||||||
dev->write_offset_b);
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
available = min_buf_w_offset(dev);
|
||||||
|
int pixel_len = available - dev->read_offset;
|
||||||
|
if (pixel_len > maxlen)
|
||||||
|
pixel_len = maxlen;
|
||||||
|
int img_size = dev->width * dev->height;
|
||||||
|
for(int i=0; i<pixel_len; ++i)
|
||||||
|
{
|
||||||
|
int pos = dev->read_offset+i;
|
||||||
|
if (pos % dev->data_width >= dev->width)
|
||||||
|
continue;
|
||||||
|
if (dev->scanned_pixels >= img_size)
|
||||||
{
|
{
|
||||||
while (dev->write_offset_r <= dev->read_offset)
|
DBG(101, "Extra pixels received.\n");
|
||||||
{
|
break;
|
||||||
ret = get_data (dev);
|
|
||||||
if (ret != SANE_STATUS_GOOD)
|
|
||||||
if (dev->write_offset_r <= dev->read_offset)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
available = dev->write_offset_r;
|
|
||||||
}
|
}
|
||||||
*len = available - dev->read_offset;
|
dev->scanned_pixels++;
|
||||||
if (*len > maxlen)
|
buf[(*len)++] = dev->buf_r.buffer[pos];
|
||||||
*len = maxlen;
|
if (dev->optionw[COLOR_OFFSET] == RGB)
|
||||||
memcpy (buf, dev->buffer + dev->read_offset, *len);
|
|
||||||
dev->read_offset += *len;
|
|
||||||
if (dev->read_offset == dev->bufs)
|
|
||||||
{
|
{
|
||||||
free (dev->buffer);
|
buf[(*len)++] = dev->buf_g.buffer[pos];
|
||||||
dev->buffer = NULL;
|
buf[(*len)++] = dev->buf_b.buffer[pos];
|
||||||
dev->read_offset = 0;
|
|
||||||
dev->write_offset_r = 0;
|
|
||||||
dev->write_offset_g = 1;
|
|
||||||
dev->write_offset_b = 2;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
DBG(101, "Moved %d pixels to buffer. Total pixel scanned: %d \n", *len, dev->scanned_pixels);
|
||||||
|
if (dev->scanned_pixels == img_size)
|
||||||
|
DBG(100, "Full image received\n");
|
||||||
|
dev->read_offset += pixel_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
If w_offset is the same in all buffers and has already been completely transferred
|
||||||
|
to the common buffer - flush buffer. It will be recreated in get_data with a reserve
|
||||||
|
for the last triple portions
|
||||||
|
*/
|
||||||
|
if (is_buf_synchronized(dev) && available == dev->read_offset)
|
||||||
|
{
|
||||||
|
remove_buffers(dev);
|
||||||
|
}
|
||||||
|
|
||||||
/* Special case where sane_cancel is called while scanning */
|
/* Special case where sane_cancel is called while scanning */
|
||||||
if (dev->status == STATUS_CANCELING)
|
if (dev->status == STATUS_CANCELING)
|
||||||
|
@ -1082,8 +1083,7 @@ sane_cancel (SANE_Handle h)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
free (dev->buffer);
|
remove_buffers(dev);
|
||||||
dev->buffer = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SANE_Status
|
SANE_Status
|
||||||
|
|
Ładowanie…
Reference in New Issue