Fixed 16-bit byte-order handling in sane_read() (patch from Michael Herder

<crapsite@gmx.net>).  New version: 1.0.7.
Henning Meier-Geinitz <henning@meier-geinitz.de>
DEVEL_2_0_BRANCH-1
Henning Geinitz 2002-03-24 21:51:04 +00:00
rodzic c01892818a
commit ee7b0e32f8
2 zmienionych plików z 114 dodań i 61 usunięć

Wyświetl plik

@ -42,7 +42,7 @@
/* Please increase version number with every change /* Please increase version number with every change
(don't forget to update net.desc) */ (don't forget to update net.desc) */
#define NET_VERSION "1.0.7" #define NET_VERSION "1.0.8"
#ifdef _AIX #ifdef _AIX
# include "../include/lalloca.h" /* MUST come first for AIX! */ # include "../include/lalloca.h" /* MUST come first for AIX! */
@ -91,8 +91,24 @@ static int saned_port;
static int client_big_endian; /* 1 == big endian; 0 == little endian */ static int client_big_endian; /* 1 == big endian; 0 == little endian */
static int server_big_endian; /* 1 == big endian; 0 == little endian */ static int server_big_endian; /* 1 == big endian; 0 == little endian */
static int depth; /* bits per pixel */ static int depth; /* bits per pixel */
static int hang_over; /* -1 == no hangover; otherwise cast value to
unsigned char */ /* This variable is only needed, if the depth is 16bit/channel and
client/server have different endianness. A value of -1 means, that there's
no hang over; otherwise the value has to be casted to SANE_Byte. hang_over
means, that there is a remaining byte from a previous call to sane_read,
which could not be byte-swapped, e.g. because the frontend requested an odd
number of bytes.
*/
static int hang_over;
/* This variable is only needed, if the depth is 16bit/channel and
client/server have different endianness. A value of -1 means, that there's
no left over; otherwise the value has to be casted to SANE_Byte. left_over
means, that there is a remaining byte from a previous call to sane_read,
which already is in the the correct byte order, but could not be returned,
e.g. because the frontend requested only one byte per call.
*/
static int left_over;
static SANE_Status static SANE_Status
add_device (const char *name, Net_Device ** ndp) add_device (const char *name, Net_Device ** ndp)
@ -1131,6 +1147,7 @@ sane_start (SANE_Handle handle)
DBG (3, "sane_start\n"); DBG (3, "sane_start\n");
hang_over = -1; hang_over = -1;
left_over = -1;
if (s->data >= 0) if (s->data >= 0)
{ {
@ -1173,6 +1190,7 @@ sane_start (SANE_Handle handle)
server_big_endian = 1; server_big_endian = 1;
DBG (1, "sane_start: server has big endian byte order\n"); DBG (1, "sane_start: server has big endian byte order\n");
} }
need_auth = (reply.resource_to_authorize != 0); need_auth = (reply.resource_to_authorize != 0);
if (need_auth) if (need_auth)
{ {
@ -1226,18 +1244,39 @@ sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length,
Net_Scanner *s = handle; Net_Scanner *s = handle;
ssize_t nread; ssize_t nread;
SANE_Int cnt; SANE_Int cnt;
SANE_Int start_cnt;
SANE_Int end_cnt;
SANE_Byte swap_buf; SANE_Byte swap_buf;
SANE_Byte temp_hang_over;
int is_even;
DBG (3, "sane_read: max_length = %d\n", max_length); DBG (3, "sane_read: handle=%p, data=%p, max_length=%d, length=%p\n",
handle, data, max_length, length);
if (!length) if (!length)
{ {
DBG (1, "sane_read: length == NULL\n"); DBG (1, "sane_read: length == NULL\n");
return SANE_STATUS_INVAL; return SANE_STATUS_INVAL;
} }
is_even = 1;
*length = 0; *length = 0;
/* If there's a left over, i.e. a byte already in the correct byte order,
return it immediately; otherwise read may fail with a SANE_STATUS_EOF and
the caller never can read the last byte */
if ((depth == 16) && (server_big_endian != client_big_endian))
{
if (left_over > -1)
{
DBG (3, "sane_read: left_over from previous call, return immediately\n");
/* return the byte, we've currently scanned; hang_over becomes left_over */
*data = (SANE_Byte) left_over;
left_over = -1;
*length = 1;
return SANE_STATUS_GOOD;
}
}
if (s->data < 0) if (s->data < 0)
{ {
DBG (1, "sane_read: data pipe doesn't exist, scan cancelled?\n"); DBG (1, "sane_read: data pipe doesn't exist, scan cancelled?\n");
@ -1307,44 +1346,8 @@ sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length,
if (max_length > (SANE_Int) s->bytes_remaining) if (max_length > (SANE_Int) s->bytes_remaining)
max_length = s->bytes_remaining; max_length = s->bytes_remaining;
/* If we are scanning with 16 bits/pixel, we must be sure to scan complete nread = read (s->data, data, max_length);
pixels. Otherwise it's impossible to swap the bytes, since we don't have s->bytes_remaining -= nread;
access to the previous data if sane_read is called the next
time. Therefore we check, whether an odd number ob bytes was read. If
this is true, the last byte is stored in hang_over and length is
decreased by 1.
*/
/* Check whether we are scanning with a depth of 16 bits/pixel and whether
server and client have different byte order. If this is true, then it's
neccessary to check whether there's a hang_over from a previous call to
sane_read.
*/
if ((depth == 16) && (server_big_endian != client_big_endian))
{
DBG (4, "sane_read: client/server have different byte order\n");
if (hang_over > -1)
{
DBG (4, "sane_read: hang_over from previous call to sane_read()\n");
*(data) = (unsigned char) hang_over;
DBG (4, "sane_read: reading image data now\n");
nread = read (s->data, data + 1, max_length - 1);
}
else
{
DBG (4, "sane_read: no hang_over from previous call to "
"sane_read()\n");
DBG (4, "sane_read: reading image data now\n");
nread = read (s->data, data, max_length);
}
}
else
{
DBG (4, "sane_read: reading image data now\n");
nread = read (s->data, data, max_length);
}
if (nread < 0) if (nread < 0)
{ {
@ -1359,6 +1362,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length,
} }
} }
*length = nread;
/* Check whether we are scanning with a depth of 16 bits/pixel and whether /* Check whether we are scanning with a depth of 16 bits/pixel and whether
server and client have different byte order. If this is true, then it's server and client have different byte order. If this is true, then it's
neccessary to check whether read returned an odd number. If an odd number neccessary to check whether read returned an odd number. If an odd number
@ -1368,31 +1372,80 @@ sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length,
{ {
DBG (1,"sane_read: client/server have different byte order; " DBG (1,"sane_read: client/server have different byte order; "
"must swap\n"); "must swap\n");
s->bytes_remaining -= nread; /* special case: 1 byte scanned and hang_over */
if (0 != nread % 2) if ((nread == 1) && (hang_over > -1))
{ {
DBG (1, "sane_read: number of bytes read is odd; store hang_over\n"); /* return the byte, we've currently scanned; hang_over becomes left_over */
*length = nread - 1; left_over = hang_over;
hang_over = *(data + nread); hang_over = -1;
return SANE_STATUS_GOOD;
}
/* check whether an even or an odd number of bytes has been scanned */
if ((nread % 2) == 0)
is_even = 1;
else
is_even = 0;
/* check, whether there's a hang over from a previous call;
in this case we memcopy the data up one byte */
if ((nread > 1) && (hang_over > -1))
{
/* store last byte */
temp_hang_over = *(data + nread - 1);
memmove (data + 1, data, nread - 1);
*data = (SANE_Byte) hang_over;
/* what happens with the last byte depends on whether the number of bytes
is even or odd */
if (is_even == 1)
{
/* number of bytes is even; no new hang_over, exchange last byte with
hang over; last byte becomes left_over */
left_over = *(data + nread - 1);
*(data + nread - 1) = temp_hang_over;
hang_over = -1;
start_cnt = 0;
/* last byte already swapped */
end_cnt = nread - 2;
}
else
{
/* number of bytes is odd; last byte becomes new hang_over */
hang_over = temp_hang_over;
left_over = -1;
start_cnt = 0;
end_cnt = nread - 1;
}
}
else if (nread == 1)
{
/* if only one byte has been read, save it as hang_over and return length=0 */
hang_over = (int) *data;
*length = 0;
return SANE_STATUS_GOOD;
} }
else else
{ {
*length = nread; /* no hang_over; test for even or odd byte number */
hang_over = -1; if(is_even == 1)
{
start_cnt = 0;
end_cnt = *length;
}
else
{
start_cnt = 0;
hang_over = *(data + *length - 1);
*length -= 1;
end_cnt = *length;
}
} }
/* Finally step through the buffer and swap bytes */ /* swap the bytes */
for (cnt = 0; cnt < *length - 1; cnt += 2) for (cnt = start_cnt; cnt < end_cnt - 1; cnt += 2)
{ {
swap_buf = *(data +cnt); swap_buf = *(data + cnt);
*(data + cnt) = *(data + cnt + 1); *(data + cnt) = *(data + cnt + 1);
*(data + cnt + 1) = swap_buf; *(data + cnt + 1) = swap_buf;
} }
} }
else
{
s->bytes_remaining -= nread;
*length = nread;
}
DBG (3, "sane_read: %d bytes read, %d remaining\n", nread, DBG (3, "sane_read: %d bytes read, %d remaining\n", nread,
s->bytes_remaining); s->bytes_remaining);

Wyświetl plik

@ -1,5 +1,5 @@
:backend "net" ; name of backend :backend "net" ; name of backend
:version "1.0.7" :version "1.0.8"
:status :beta :status :beta
:manpage "sane-net" :manpage "sane-net"
:url "http://home.nexgo.de/jochen.eisinger/saned/" :url "http://home.nexgo.de/jochen.eisinger/saned/"