1 /*
2 sane - Scanner Access Now Easy.
3 Copyright (C) 2006 Jon Chambers <jon@jon.demon.co.uk>
4
5 This file is part of the SANE package.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>.
19
20 As a special exception, the authors of SANE give permission for
21 additional uses of the libraries contained in this release of SANE.
22
23 The exception is that, if you link a SANE library with other files
24 to produce an executable, this does not by itself cause the
25 resulting executable to be covered by the GNU General Public
26 License. Your use of that executable is in no way restricted on
27 account of linking the SANE library code into it.
28
29 This exception does not, however, invalidate any other reasons why
30 the executable file might be covered by the GNU General Public
31 License.
32
33 If you submit changes to SANE to the maintainers to be included in
34 a subsequent release, you agree by submitting the changes that
35 those changes may be distributed with this exception intact.
36
37 If you write modifications of your own for SANE, it is your choice
38 whether to permit this exception to apply to your modifications.
39 If you do not wish that, delete this exception notice.
40
41 Dell 1600n network scan driver for SANE.
42
43 To debug:
44 SANE_DEBUG_DELL1600N_NET=255 scanimage --verbose 2>scan.errs 1>scan.png
45 */
46
47 /***********************************************************
48 * INCLUDES
49 ***********************************************************/
50
51 #include "../include/sane/config.h"
52 #include "../include/sane/sane.h"
53 #include "../include/sane/sanei.h"
54
55 #define BACKEND_NAME dell1600n_net
56 #include "../include/sane/sanei_backend.h"
57 #include "../include/sane/sanei_config.h"
58
59 #include <stdlib.h>
60 #include <string.h>
61 #include <stdio.h>
62 #include <math.h>
63 #include <unistd.h>
64
65 /* :NOTE: these are likely to be platform-specific! */
66 #include <sys/types.h>
67 #include <sys/socket.h>
68 #include <sys/time.h>
69 #include <netinet/in.h>
70 #include <netdb.h>
71
72 #include <jpeglib.h>
73 #include <tiffio.h>
74
75 /* OS/2... */
76 #ifndef SHUT_RDWR
77 #define SHUT_RDWR 2
78 #endif
79
80
81 /***********************************************************
82 * DEFINITIONS
83 ***********************************************************/
84
85 /* Maximum number of scanners */
86 #define MAX_SCANNERS 32
87
88 /* version number */
89 #define DRIVER_VERSION SANE_VERSION_CODE( SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0 )
90
91 /* size of buffer for socket communication */
92 #define SOCK_BUF_SIZE 2048
93
94 /* size of registation name */
95 #define REG_NAME_SIZE 64
96
97 struct DeviceRecord
98 {
99 SANE_Device m_device;
100 char * m_pName; /* storage of name */
101 char * m_pModel; /* storage of model */
102 };
103
104 /* a buffer struct to store "stuff" */
105 struct ComBuf
106 {
107 size_t m_capacity; /* current allocated size in bytes */
108 size_t m_used; /* current used size in bytes */
109 unsigned char *m_pBuf; /* storage (or NULL if none allocated) */
110 };
111
112 /* state data for a single scanner connection */
113 struct ScannerState
114 {
115 int m_udpFd; /* file descriptor to UDP socket */
116 int m_tcpFd; /* file descriptor to TCP socket */
117 struct sockaddr_in m_sockAddr; /* printer address */
118 struct ComBuf m_buf; /* buffer for network data */
119 struct ComBuf m_imageData; /* storage for decoded image data */
120 int m_numPages; /* number of complete pages (host byte order) */
121 struct ComBuf m_pageInfo; /* "array" of numPages PageInfo structs */
122 int m_bFinish; /* set non-0 to signal that we are finished */
123 int m_bCancelled; /* set non-0 that bFinish state arose from cancellation */
124 char m_regName[REG_NAME_SIZE]; /* name with which to register */
125 unsigned short m_xres; /* x resolution (network byte order) */
126 unsigned short m_yres; /* y resolution (network byte order) */
127 unsigned int m_composition; /* composition (0x01=>TIFF/PDF,0x40=>JPEG) (network byte order) */
128 unsigned char m_brightness; /* brightness */
129 unsigned int m_compression; /* compression (0x08=>CCIT Group 4,0x20=>JPEG) (network byte order) */
130 unsigned int m_fileType; /* file type (2=>TIFF,4=>PDF,8=>JPEG)(network byte order) */
131 unsigned int m_pixelWidth; /* width in pixels (network byte order) */
132 unsigned int m_pixelHeight; /* height in pixels (network byte order) */
133 unsigned int m_bytesRead; /* bytes read by SANE (host byte order) */
134 unsigned int m_currentPageBytes;/* number of bytes of current page read (host byte order) */
135 };
136
137 /* state data for a single page
138 NOTE: all ints are in host byte order
139 */
140 struct PageInfo
141 {
142 int m_width; /* pixel width */
143 int m_height; /* pixel height */
144 int m_totalSize; /* total page size (bytes) */
145 int m_bytesRemaining; /* number of bytes not yet passed to SANE client */
146 };
147
148 /* struct for in-memory jpeg decompression */
149 struct JpegDataDecompState
150 {
151 struct jpeg_decompress_struct m_cinfo; /* base struct */
152 unsigned char *m_pData; /* data pointer */
153 unsigned int m_bytesRemaining; /* amount of unprocessed data */
154 };
155
156 /* initial ComBuf allocation */
157 #define INITIAL_COM_BUF_SIZE 1024
158
159 /***********************************************************
160 * FUNCTION PROTOTYPES
161 ***********************************************************/
162
163 /* print hex buffer to stdout */
164 static void HexDump (int debugLevel, const unsigned char *buf,
165 size_t bufSize);
166
167 /* clears gKnownDevices array */
168 static void ClearKnownDevices (void);
169
170 /* initialise a ComBuf struct */
171 static int InitComBuf (struct ComBuf *pBuf);
172
173 /* free a ComBuf struct */
174 static void FreeComBuf (struct ComBuf *pBuf);
175
176 /* add data to a ComBuf struct */
177 static int AppendToComBuf (struct ComBuf *pBuf, const unsigned char *pData,
178 size_t datSize);
179
180 /* remove data from the front of a ComBuf struct */
181 static int PopFromComBuf (struct ComBuf *pBuf, size_t datSize);
182
183 /* initialise a packet */
184 static int InitPacket (struct ComBuf *pBuf, char type);
185
186 /* append message to a packet */
187 static int AppendMessageToPacket (struct ComBuf *pBuf,
188 char messageType,
189 char *messageName,
190 char valueType,
191 void *pValue, size_t valueLen);
192
193 /* write length data to packet header */
194 static void FinalisePacket (struct ComBuf *pBuf);
195
196 /* \return 1 if message is complete, 0 otherwise */
197 static int MessageIsComplete (unsigned char *pData, size_t size);
198
199 /* process a registration broadcast response
200 \return DeviceRecord pointer on success (caller frees), NULL on failure
201 */
202 static struct DeviceRecord *ProcessFindResponse (unsigned char *pData, size_t size);
203
204 /* frees a scanner state struct stored in gOpenScanners */
205 static void FreeScannerState (int iHandle);
206
207 /* \return 1 if iHandle is a valid member of gOpenScanners, 0 otherwise */
208 static int ValidScannerNumber (int iHandle);
209
210 /* process UDP responses, \return 0 in success, >0 otherwise */
211 static int ProcessUdpResponse (unsigned char *pData, size_t size,
212 struct ScannerState *pState);
213
214 /* process TCP responses, \return 0 in success, >0 otherwise */
215 static int ProcessTcpResponse (struct ScannerState *pState,
216 struct ComBuf *pTcpBufBuf);
217
218 /* Process the data from a single scanned page, \return 0 in success, >0 otherwise */
219 static int ProcessPageData (struct ScannerState *pState);
220
221 /* Libjpeg decompression interface */
222 static void JpegDecompInitSource (j_decompress_ptr cinfo);
223 static boolean JpegDecompFillInputBuffer (j_decompress_ptr cinfo);
224 static void JpegDecompSkipInputData (j_decompress_ptr cinfo, long numBytes);
225 static void JpegDecompTermSource (j_decompress_ptr cinfo);
226
227 /***********************************************************
228 * GLOBALS
229 ***********************************************************/
230
231 /* Results of last call to sane_get_devices */
232 static struct DeviceRecord *gKnownDevices[MAX_SCANNERS];
233
234 /* Empty list for when network devices are not wanted */
235 static const SANE_Device *gEmptyDeviceList[1];
236
237 /* Array of open scanner device states.
238 :NOTE: (int)SANE_Handle is an offset into this array */
239 static struct ScannerState *gOpenScanners[MAX_SCANNERS];
240
241 /* scanner port */
242 static unsigned short gScannerPort = 1124;
243
244 /* ms to wait for registration replies */
245 static unsigned short gRegReplyWaitMs = 300;
246
247 /***********************************************************
248 * FUNCTION IMPLEMENTATIONS
249 ***********************************************************/
250
251 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback __sane_unused__ authorize)252 sane_init (SANE_Int * version_code,
253 SANE_Auth_Callback __sane_unused__ authorize)
254 {
255
256 /* init globals */
257 memset (gKnownDevices, 0, sizeof (gKnownDevices));
258 memset (gOpenScanners, 0, sizeof (gOpenScanners));
259
260 /* report version */
261 *version_code = DRIVER_VERSION;
262
263 /* init debug */
264 DBG_INIT ();
265
266 return SANE_STATUS_GOOD;
267
268 } /* sane_init */
269
270 /***********************************************************/
271
272 void
sane_exit(void)273 sane_exit (void)
274 {
275
276 int iHandle;
277
278 /* clean up */
279 ClearKnownDevices ();
280
281 for (iHandle = 0; iHandle < MAX_SCANNERS; ++iHandle)
282 {
283 if (gOpenScanners[iHandle])
284 FreeScannerState (iHandle);
285 }
286
287 } /* sane_exit */
288
289 /***********************************************************/
290
291 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)292 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
293 {
294
295 int ret;
296 unsigned char sockBuf[SOCK_BUF_SIZE];
297 int sock, optYes;
298 struct DeviceRecord *pDevice;
299 struct ComBuf queryPacket;
300 struct sockaddr_in remoteAddr;
301 unsigned char ucVal;
302 fd_set readFds;
303 struct timeval selTimeVal;
304 int nread, iNextDevice;
305 FILE *fConfig;
306 char configBuf[ 256 ];
307 const char *pVal;
308 int valLen;
309
310 if (local_only) {
311 *device_list = gEmptyDeviceList;
312 return SANE_STATUS_GOOD;
313 }
314
315 /* init variables */
316 ret = SANE_STATUS_GOOD;
317 sock = 0;
318 pDevice = NULL;
319 optYes = 1;
320
321 InitComBuf (&queryPacket);
322
323 /* clear previous results */
324 ClearKnownDevices ();
325 iNextDevice = 0;
326
327 /* look for a config file */
328 fConfig = sanei_config_open( "dell1600n_net.conf" );
329 if ( fConfig )
330 {
331 while ( ! feof( fConfig ) )
332 {
333 if ( ! sanei_config_read ( configBuf, sizeof( configBuf ), fConfig ) ) break;
334
335 /* skip whitespace */
336 pVal = sanei_config_skip_whitespace ( configBuf );
337
338 /* skip comments */
339 if ( *pVal == '#' ) continue;
340
341 /* process named_scanner */
342 valLen = strlen( "named_scanner:" );
343 if ( ! strncmp( pVal, "extra_scanner:", valLen ) ){
344
345 pVal = sanei_config_skip_whitespace ( pVal + valLen );
346
347 pDevice = malloc (sizeof (struct DeviceRecord));
348 if (!pDevice)
349 {
350 DBG (1, "sane_get_devices: memory allocation failure\n");
351 break;
352 }
353
354 pDevice->m_pName = strdup (pVal);
355 pDevice->m_device.vendor = "Dell";
356 pDevice->m_pModel = strdup( "1600n" );
357 pDevice->m_device.type = "multi-function peripheral";
358
359 pDevice->m_device.name = pDevice->m_pName;
360 pDevice->m_device.model = pDevice->m_pModel;
361
362 /* add to list */
363 gKnownDevices[iNextDevice++] = pDevice;
364
365 continue;
366 } /* if */
367
368 } /* while */
369
370 /* Close the file */
371 fclose( fConfig );
372 }
373
374 /* open UDP socket */
375 sock = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
376 if (sock == -1)
377 {
378 DBG (1, "Error creating socket\n");
379 ret = SANE_STATUS_NO_MEM;
380 goto cleanup;
381 }
382 setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &optYes, sizeof (optYes));
383
384 /* prepare select mask */
385 FD_ZERO (&readFds);
386 FD_SET (sock, &readFds);
387 selTimeVal.tv_sec = 0;
388 selTimeVal.tv_usec = gRegReplyWaitMs * 1000;
389
390 /* init a packet */
391 InitPacket (&queryPacket, 0x01);
392
393 /* add query */
394 ucVal = 0;
395 AppendMessageToPacket (&queryPacket, 0x25, "std-scan-discovery-all",
396 0x02, &ucVal, sizeof (ucVal));
397
398 FinalisePacket (&queryPacket);
399
400 DBG (10, "Sending:\n");
401 HexDump (10, queryPacket.m_pBuf, queryPacket.m_used);
402
403
404 remoteAddr.sin_family = AF_INET;
405 remoteAddr.sin_port = htons (gScannerPort);
406 remoteAddr.sin_addr.s_addr = 0xFFFFFFFF; /* broadcast */
407
408 if (sendto (sock, queryPacket.m_pBuf, queryPacket.m_used, 0,
409 (struct sockaddr *) &remoteAddr, sizeof (remoteAddr)) == -1)
410 {
411 DBG (1, "Error sending broadcast packet\n");
412 ret = SANE_STATUS_NO_MEM;
413 goto cleanup;
414 }
415
416 /* process replies */
417 while (select (sock + 1, &readFds, NULL, NULL, &selTimeVal))
418 {
419
420 /* break if we've got no more storage space in array */
421 if (iNextDevice >= MAX_SCANNERS)
422 {
423 DBG (1, "sane_get_devices: more than %d devices, ignoring\n",
424 MAX_SCANNERS);
425 break;
426 }
427
428 nread = read (sock, sockBuf, sizeof (sockBuf));
429 DBG (5, "Got a broadcast response, (%d bytes)\n", nread);
430
431 if (nread <= 0)
432 break;
433
434 HexDump (10, sockBuf, nread);
435
436 /* process response (skipping bad ones) */
437 if (!(pDevice = ProcessFindResponse (sockBuf, nread))) continue;
438
439 /* add to list */
440 gKnownDevices[iNextDevice++] = pDevice;
441
442 } /* while */
443
444 /* report our finds */
445 *device_list = (const SANE_Device **) gKnownDevices;
446
447 cleanup:
448
449 if (sock)
450 close (sock);
451 FreeComBuf (&queryPacket);
452
453 return ret;
454
455 } /* sane_get_devices */
456
457 /***********************************************************/
458
459 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)460 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
461 {
462
463 int iHandle = -1, i;
464 SANE_Status status = SANE_STATUS_GOOD;
465 struct hostent *pHostent;
466 char *pDot;
467
468 DBG( 5, "sane_open: %s\n", devicename );
469
470 /* find the next available scanner pointer in gOpenScanners */
471 for (i = 0; i < MAX_SCANNERS; ++i)
472 {
473
474 if (gOpenScanners[i]) continue;
475
476 iHandle = i;
477 break;
478
479 } /* for */
480 if (iHandle == -1)
481 {
482 DBG (1, "sane_open: no space left in gOpenScanners array\n");
483 status = SANE_STATUS_NO_MEM;
484 goto cleanup;
485 }
486
487 /* allocate some space */
488 if (!(gOpenScanners[iHandle] = malloc (sizeof (struct ScannerState))))
489 {
490 status = SANE_STATUS_NO_MEM;
491 goto cleanup;
492 }
493
494 /* init data */
495 memset (gOpenScanners[iHandle], 0, sizeof (struct ScannerState));
496 InitComBuf (&gOpenScanners[iHandle]->m_buf);
497 InitComBuf (&gOpenScanners[iHandle]->m_imageData);
498 InitComBuf (&gOpenScanners[iHandle]->m_pageInfo);
499 gOpenScanners[iHandle]->m_xres = ntohs (200);
500 gOpenScanners[iHandle]->m_yres = ntohs (200);
501 gOpenScanners[iHandle]->m_composition = ntohl (0x01);
502 gOpenScanners[iHandle]->m_brightness = 0x80;
503 gOpenScanners[iHandle]->m_compression = ntohl (0x08);
504 gOpenScanners[iHandle]->m_fileType = ntohl (0x02);
505
506
507 /* look up scanner name */
508 pHostent = gethostbyname (devicename);
509 if ((!pHostent) || (!pHostent->h_addr_list))
510 {
511 DBG (1, "sane_open: error looking up scanner name %s\n", devicename);
512 status = SANE_STATUS_INVAL;
513 goto cleanup;
514 }
515
516 /* open a UDP socket */
517 if (!(gOpenScanners[iHandle]->m_udpFd =
518 socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)))
519 {
520 DBG (1, "sane_open: error opening socket\n");
521 status = SANE_STATUS_IO_ERROR;
522 goto cleanup;
523 }
524
525 /* connect to the scanner */
526 memset (&gOpenScanners[iHandle]->m_sockAddr, 0,
527 sizeof (gOpenScanners[iHandle]->m_sockAddr));
528 gOpenScanners[iHandle]->m_sockAddr.sin_family = AF_INET;
529 gOpenScanners[iHandle]->m_sockAddr.sin_port = htons (gScannerPort);
530 memcpy (&gOpenScanners[iHandle]->m_sockAddr.sin_addr,
531 pHostent->h_addr_list[0], pHostent->h_length);
532 if (connect (gOpenScanners[iHandle]->m_udpFd,
533 (struct sockaddr *) &gOpenScanners[iHandle]->m_sockAddr,
534 sizeof (gOpenScanners[iHandle]->m_sockAddr)))
535 {
536 DBG (1, "sane_open: error connecting to %s:%d\n", devicename,
537 gScannerPort);
538 status = SANE_STATUS_IO_ERROR;
539 goto cleanup;
540 }
541
542 /* set fallback registration name */
543 sprintf (gOpenScanners[iHandle]->m_regName, "Sane");
544
545 /* try to fill in hostname */
546 gethostname (gOpenScanners[iHandle]->m_regName, REG_NAME_SIZE);
547
548 /* just in case... */
549 gOpenScanners[iHandle]->m_regName[REG_NAME_SIZE - 1] = 0;
550
551 /* chop off any domain (if any) */
552 if ((pDot = strchr (gOpenScanners[iHandle]->m_regName, '.')))
553 *pDot = 0;
554
555 DBG (5, "sane_open: connected to %s:%d as %s\n", devicename, gScannerPort,
556 gOpenScanners[iHandle]->m_regName);
557
558
559 /* set the handle */
560 *handle = (SANE_Handle) (unsigned long)iHandle;
561
562 return status;
563
564 cleanup:
565
566 if (iHandle != -1)
567 FreeScannerState (iHandle);
568
569 return status;
570
571 } /* sane_open */
572
573 /***********************************************************/
574
575 void
sane_close(SANE_Handle handle)576 sane_close (SANE_Handle handle)
577 {
578
579 DBG( 5, "sane_close: %lx\n", (unsigned long)handle );
580
581 FreeScannerState ((unsigned long) handle);
582
583 } /* sane_close */
584
585 /***********************************************************/
586
587 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle __sane_unused__ handle,SANE_Int option)588 sane_get_option_descriptor (SANE_Handle __sane_unused__ handle,
589 SANE_Int option)
590 {
591
592 static SANE_Option_Descriptor numOptions = {
593 "num_options",
594 "Number of options",
595 "Number of options",
596 SANE_TYPE_INT,
597 SANE_UNIT_NONE,
598 1,
599 0,
600 0,
601 {0}
602 };
603
604 if (option == 0)
605 return &numOptions;
606 else
607 return NULL;
608
609 } /* sane_get_option_descriptor */
610
611 /***********************************************************/
612
613 SANE_Status
sane_control_option(SANE_Handle __sane_unused__ handle,SANE_Int option,SANE_Action action,void * value,SANE_Int __sane_unused__ * info)614 sane_control_option (SANE_Handle __sane_unused__ handle, SANE_Int option,
615 SANE_Action action, void *value,
616 SANE_Int __sane_unused__ * info)
617 {
618
619 static int numOptions = 1;
620
621 if (action == SANE_ACTION_GET_VALUE && option == 0)
622 *(int *) value = numOptions;
623
624 return SANE_STATUS_GOOD;
625
626 } /* sane_control_option */
627
628 /***********************************************************/
629
630 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)631 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
632 {
633 int iHandle = (int) (unsigned long)handle;
634 unsigned int width, height, imageSize;
635 struct PageInfo pageInfo;
636
637 if (!gOpenScanners[iHandle])
638 return SANE_STATUS_INVAL;
639
640 /* fetch page info */
641 memcpy( & pageInfo, gOpenScanners[iHandle]->m_pageInfo.m_pBuf, sizeof( pageInfo ) );
642
643 width = pageInfo.m_width;
644 height = pageInfo.m_height;
645 imageSize = width * height * 3;
646
647 DBG( 5, "sane_get_parameters: bytes remaining on this page: %d, num pages: %d, size: %dx%d\n",
648 pageInfo.m_bytesRemaining,
649 gOpenScanners[iHandle]->m_numPages,
650 width,
651 height );
652
653 DBG (5,
654 "sane_get_parameters: handle %x: bytes outstanding: %lu, image size: %d\n",
655 iHandle, (unsigned long)gOpenScanners[iHandle]->m_imageData.m_used, imageSize);
656
657 /* check for enough data */
658 /*
659 if (gOpenScanners[iHandle]->m_imageData.m_used < imageSize)
660 {
661 DBG (1, "sane_get_parameters: handle %d: not enough data: %d < %d\n",
662 iHandle, gOpenScanners[iHandle]->m_imageData.m_used, imageSize);
663 return SANE_STATUS_INVAL;
664 }
665 */
666
667
668 params->format = SANE_FRAME_RGB;
669 params->last_frame = SANE_TRUE;
670 params->lines = height;
671 params->depth = 8;
672 params->pixels_per_line = width;
673 params->bytes_per_line = width * 3;
674
675 return SANE_STATUS_GOOD;
676
677 } /* sane_get_parameters */
678
679 /***********************************************************/
680
681 SANE_Status
sane_start(SANE_Handle handle)682 sane_start (SANE_Handle handle)
683 {
684
685 SANE_Status status = SANE_STATUS_GOOD;
686 struct ComBuf buf;
687 unsigned char sockBuf[SOCK_BUF_SIZE];
688 int iHandle, nread;
689 int errorCheck = 0;
690 struct sockaddr_in myAddr;
691 socklen_t addrSize;
692 fd_set readFds;
693 struct timeval selTimeVal;
694
695 iHandle = (int) (unsigned long)handle;
696
697 DBG( 5, "sane_start: %x\n", iHandle );
698
699 /* fetch and check scanner index */
700 if (!ValidScannerNumber (iHandle))
701 return SANE_STATUS_INVAL;
702
703 /* check if we still have outstanding pages of data on this handle */
704 if (gOpenScanners[iHandle]->m_imageData.m_used){
705
706 /* remove empty page */
707 PopFromComBuf ( & gOpenScanners[iHandle]->m_pageInfo, sizeof( struct PageInfo ) );
708 return SANE_STATUS_GOOD;
709
710 }
711
712 /* determine local IP address */
713 addrSize = sizeof (myAddr);
714 if (getsockname (gOpenScanners[iHandle]->m_udpFd, (struct sockaddr *) &myAddr, &addrSize))
715 {
716 DBG (1, "sane_start: Error getting own IP address\n");
717 return SANE_STATUS_IO_ERROR;
718 }
719
720 /* init a buffer for our registration message */
721 errorCheck |= InitComBuf (&buf);
722
723 /* build packet */
724 errorCheck |= InitPacket (&buf, 1);
725 errorCheck |=
726 AppendMessageToPacket (&buf, 0x22, "std-scan-subscribe-user-name", 0x0b,
727 gOpenScanners[iHandle]->m_regName,
728 strlen (gOpenScanners[iHandle]->m_regName));
729 errorCheck |=
730 AppendMessageToPacket (&buf, 0x22, "std-scan-subscribe-ip-address", 0x0a,
731 &myAddr.sin_addr, 4);
732 FinalisePacket (&buf);
733
734 /* check nothing went wrong along the way */
735 if (errorCheck)
736 {
737 status = SANE_STATUS_NO_MEM;
738 goto cleanup;
739 }
740
741 /* send the packet */
742 send (gOpenScanners[iHandle]->m_udpFd, buf.m_pBuf, buf.m_used, 0);
743
744
745 /* loop until done */
746 gOpenScanners[iHandle]->m_bFinish = 0;
747 while (!gOpenScanners[iHandle]->m_bFinish)
748 {
749
750 /* prepare select mask */
751 FD_ZERO (&readFds);
752 FD_SET (gOpenScanners[iHandle]->m_udpFd, &readFds);
753 selTimeVal.tv_sec = 1;
754 selTimeVal.tv_usec = 0;
755
756
757
758 DBG (5, "sane_start: waiting for scan signal\n");
759
760 /* wait again if nothing received */
761 if (!select (gOpenScanners[iHandle]->m_udpFd + 1,
762 &readFds, NULL, NULL, &selTimeVal))
763 continue;
764
765 /* read from socket */
766 nread =
767 read (gOpenScanners[iHandle]->m_udpFd, sockBuf, sizeof (sockBuf));
768
769 if (nread <= 0)
770 {
771 DBG (1, "sane_start: read returned %d\n", nread);
772 break;
773 }
774
775 /* process the response */
776 if (ProcessUdpResponse (sockBuf, nread, gOpenScanners[iHandle]))
777 {
778 status = SANE_STATUS_IO_ERROR;
779 goto cleanup;
780 }
781
782 } /* while */
783
784 /* check whether we were cancelled */
785 if ( gOpenScanners[iHandle]->m_bCancelled ) status = SANE_STATUS_CANCELLED;
786
787 cleanup:
788
789 FreeComBuf (&buf);
790
791 return status;
792
793 } /* sane_start */
794
795 /***********************************************************/
796
797 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * data,SANE_Int max_length,SANE_Int * length)798 sane_read (SANE_Handle handle, SANE_Byte * data,
799 SANE_Int max_length, SANE_Int * length)
800 {
801
802 int iHandle = (int) (unsigned long)handle;
803 int dataSize;
804 struct PageInfo pageInfo;
805
806 DBG( 5, "sane_read: %x (max_length=%d)\n", iHandle, max_length );
807
808 *length = 0;
809
810 if (!gOpenScanners[iHandle])
811 return SANE_STATUS_INVAL;
812
813 /* check for end of data (no further pages) */
814 if ( ( ! gOpenScanners[iHandle]->m_imageData.m_used )
815 || ( ! gOpenScanners[iHandle]->m_numPages ) )
816 {
817 /* remove empty page if there are no more cached pages */
818 PopFromComBuf ( & gOpenScanners[iHandle]->m_pageInfo, sizeof( struct PageInfo ) );
819
820 return SANE_STATUS_EOF;
821 }
822
823 /* fetch page info */
824 memcpy( & pageInfo, gOpenScanners[iHandle]->m_pageInfo.m_pBuf, sizeof( pageInfo ) );
825
826 /* check for end of page data (we still have further cached pages) */
827 if ( pageInfo.m_bytesRemaining < 1 ) return SANE_STATUS_EOF;
828
829 /* send the remainder of the current image */
830 dataSize = pageInfo.m_bytesRemaining;
831
832 /* unless there's not enough room in the output buffer */
833 if (dataSize > max_length)
834 dataSize = max_length;
835
836 /* update the data sent counters */
837 gOpenScanners[iHandle]->m_bytesRead += dataSize;
838 pageInfo.m_bytesRemaining -= dataSize;
839
840 /* update counter */
841 memcpy( gOpenScanners[iHandle]->m_pageInfo.m_pBuf, & pageInfo, sizeof( pageInfo ) );
842
843 /* check for end of page */
844 if ( pageInfo.m_bytesRemaining < 1 ){
845
846 /* yes, so remove page info */
847 gOpenScanners[iHandle]->m_numPages--;
848
849 } /* if */
850
851 DBG (5,
852 "sane_read: sending %d bytes, image total %d, %d page bytes remaining, %lu total remaining, image: %dx%d\n",
853 dataSize, gOpenScanners[iHandle]->m_bytesRead, pageInfo.m_bytesRemaining ,
854 (unsigned long)(gOpenScanners[iHandle]->m_imageData.m_used - dataSize),
855 pageInfo.m_width,
856 pageInfo.m_height);
857
858 /* copy the data */
859 memcpy (data, gOpenScanners[iHandle]->m_imageData.m_pBuf, dataSize);
860 if (PopFromComBuf (&gOpenScanners[iHandle]->m_imageData, dataSize))
861 return SANE_STATUS_NO_MEM;
862
863 *length = dataSize;
864
865 return SANE_STATUS_GOOD;
866
867 } /* sane_read */
868
869 /***********************************************************/
870
871 void
sane_cancel(SANE_Handle handle)872 sane_cancel (SANE_Handle handle)
873 {
874 int iHandle = (int) (unsigned long)handle;
875
876 DBG( 5, "sane_cancel: %x\n", iHandle );
877
878 /* signal that bad things are afoot */
879 gOpenScanners[iHandle]->m_bFinish = 1;
880 gOpenScanners[iHandle]->m_bCancelled = 1;
881
882 } /* sane_cancel */
883
884 /***********************************************************/
885
886 SANE_Status
sane_set_io_mode(SANE_Handle __sane_unused__ handle,SANE_Bool __sane_unused__ non_blocking)887 sane_set_io_mode (SANE_Handle __sane_unused__ handle,
888 SANE_Bool __sane_unused__ non_blocking)
889 {
890
891 return SANE_STATUS_UNSUPPORTED;
892
893 } /* sane_set_io_mode */
894
895 /***********************************************************/
896
897 SANE_Status
sane_get_select_fd(SANE_Handle __sane_unused__ handle,SANE_Int __sane_unused__ * fd)898 sane_get_select_fd (SANE_Handle __sane_unused__ handle,
899 SANE_Int __sane_unused__ * fd)
900 {
901
902 return SANE_STATUS_UNSUPPORTED;
903
904 } /* sane_get_select_fd */
905
906 /***********************************************************/
907
908 /* Clears the contents of gKnownDevices and zeros it */
909 void
ClearKnownDevices()910 ClearKnownDevices ()
911 {
912
913 int i;
914
915 for (i = 0; i < MAX_SCANNERS; ++i)
916 {
917
918 if (gKnownDevices[i])
919 {
920 if (gKnownDevices[i]->m_pName) free ( gKnownDevices[i]->m_pName );
921 if (gKnownDevices[i]->m_pModel) free ( gKnownDevices[i]->m_pModel );
922 free ( gKnownDevices[i] );
923 }
924 gKnownDevices[i] = NULL;
925
926 }
927
928 } /* ClearKnownDevices */
929
930 /***********************************************************/
931
932 /* print hex buffer to debug output */
933 void
HexDump(int debugLevel,const unsigned char * buf,size_t bufSize)934 HexDump (int debugLevel, const unsigned char *buf, size_t bufSize)
935 {
936
937 unsigned int i, j;
938 size_t lineBufFree;
939
940 char itemBuf[16] = { 0 }, lineBuf[256] = { 0 };
941
942 if (DBG_LEVEL < debugLevel)
943 return;
944
945 for (i = 0; i < bufSize; ++i)
946 {
947
948 if (!(i % 16))
949 sprintf (lineBuf, "%p: ", (void *) &buf[i]);
950
951 sprintf (itemBuf, "%02x ", (const unsigned int) buf[i]);
952
953 lineBufFree = sizeof (lineBuf) - strlen (lineBuf) - 1;
954 strncat (lineBuf, itemBuf, lineBufFree);
955
956 if ((i + 1) % 16)
957 continue;
958
959 /* print string equivalent */
960 for (j = i - 15; j <= i; ++j)
961 {
962
963 if ((buf[j] >= 0x20) && (!(buf[j] & 0x80)))
964 {
965 sprintf (itemBuf, "%c", buf[j]);
966 }
967 else
968 {
969 sprintf (itemBuf, ".");
970 }
971 lineBufFree = sizeof (lineBuf) - strlen (lineBuf) - 1;
972 strncat (lineBuf, itemBuf, lineBufFree);
973
974 } /* for j */
975
976 DBG (debugLevel, "%s\n", lineBuf);
977 lineBuf[0] = 0;
978
979 } /* for i */
980
981 if (i % 16)
982 {
983
984 for (j = (i % 16); j < 16; ++j)
985 {
986 lineBufFree = sizeof (lineBuf) - strlen (lineBuf) - 1;
987 strncat (lineBuf, " ", lineBufFree);
988 }
989 for (j = 1 + i - ((i + 1) % 16); j < i; ++j)
990 {
991 if ((buf[j] >= 0x20) && (!(buf[j] & 0x80)))
992 {
993 sprintf (itemBuf, "%c", buf[j]);
994 }
995 else
996 {
997 strcpy (itemBuf, ".");
998 }
999 lineBufFree = sizeof (lineBuf) - strlen (lineBuf) - 1;
1000 strncat (lineBuf, itemBuf, lineBufFree);
1001 }
1002 DBG (debugLevel, "%s\n", lineBuf);
1003 }
1004 } /* HexDump */
1005
1006 /***********************************************************/
1007
1008 /* initialise a ComBuf struct
1009 \return 0 on success, >0 on failure
1010 */
1011 int
InitComBuf(struct ComBuf * pBuf)1012 InitComBuf (struct ComBuf *pBuf)
1013 {
1014
1015 memset (pBuf, 0, sizeof (struct ComBuf));
1016
1017 pBuf->m_pBuf = malloc (INITIAL_COM_BUF_SIZE);
1018 if (!pBuf->m_pBuf)
1019 return 1;
1020
1021 pBuf->m_capacity = INITIAL_COM_BUF_SIZE;
1022 pBuf->m_used = 0;
1023
1024 return 0;
1025
1026 } /* InitComBuf */
1027
1028 /***********************************************************/
1029
1030 /* free a ComBuf struct */
1031 void
FreeComBuf(struct ComBuf * pBuf)1032 FreeComBuf (struct ComBuf *pBuf)
1033 {
1034
1035 if (pBuf->m_pBuf)
1036 free (pBuf->m_pBuf);
1037 memset (pBuf, 0, sizeof (struct ComBuf));
1038
1039 } /* FreeComBuf */
1040
1041 /***********************************************************/
1042
1043 /* add data to a ComBuf struct
1044 \return 0 on success, >0 on failure
1045 \note If pData is NULL then buffer size will be increased but no copying will take place
1046 \note In case of failure pBuf will be released using FreeComBuf
1047 */
1048 int
AppendToComBuf(struct ComBuf * pBuf,const unsigned char * pData,size_t datSize)1049 AppendToComBuf (struct ComBuf *pBuf, const unsigned char *pData,
1050 size_t datSize)
1051 {
1052
1053 size_t newSize;
1054
1055 /* check we have enough space */
1056 if (pBuf->m_used + datSize > pBuf->m_capacity)
1057 {
1058 /* nope - allocate some more */
1059 newSize = pBuf->m_used + datSize + INITIAL_COM_BUF_SIZE;
1060 pBuf->m_pBuf = realloc (pBuf->m_pBuf, newSize);
1061 if (!pBuf->m_pBuf)
1062 {
1063 DBG (1, "AppendToComBuf: memory allocation error");
1064 FreeComBuf (pBuf);
1065 return (1);
1066 }
1067 pBuf->m_capacity = newSize;
1068 } /* if */
1069
1070 /* add data */
1071 if (pData)
1072 memcpy (pBuf->m_pBuf + pBuf->m_used, pData, datSize);
1073 pBuf->m_used += datSize;
1074
1075 return 0;
1076
1077 } /* AppendToComBuf */
1078
1079 /***********************************************************/
1080
1081 /* append message to a packet
1082 \return 0 if ok, 1 if bad */
1083 int
AppendMessageToPacket(struct ComBuf * pBuf,char messageType,char * messageName,char valueType,void * pValue,size_t valueLen)1084 AppendMessageToPacket (struct ComBuf *pBuf, /* packet to which to append */
1085 char messageType, /* type of message */
1086 char *messageName, /* name of message */
1087 char valueType, /* type of value */
1088 void *pValue, /* pointer to value */
1089 size_t valueLen /* length of value (bytes) */
1090 )
1091 {
1092
1093 unsigned short slen;
1094
1095 /* message type */
1096 AppendToComBuf (pBuf, (void *) &messageType, 1);
1097
1098 /* message length */
1099 slen = htons (strlen (messageName));
1100 AppendToComBuf (pBuf, (void *) &slen, 2);
1101
1102 /* and name */
1103 AppendToComBuf (pBuf, (void *) messageName, strlen (messageName));
1104
1105 /* and value type */
1106 AppendToComBuf (pBuf, (void *) &valueType, 1);
1107
1108 /* value length */
1109 slen = htons (valueLen);
1110 AppendToComBuf (pBuf, (void *) &slen, 2);
1111
1112 /* and value */
1113 return (AppendToComBuf (pBuf, (void *) pValue, valueLen));
1114
1115 } /* AppendMessageToPacket */
1116
1117 /***********************************************************/
1118
1119 /* Initialise a packet
1120 \param pBuf : An initialise ComBuf
1121 \param type : either 0x01 ("normal" ) or 0x02 ("reply" )
1122 \return 0 on success, >0 otherwise
1123 */
1124 int
InitPacket(struct ComBuf * pBuf,char type)1125 InitPacket (struct ComBuf *pBuf, char type)
1126 {
1127
1128 char header[8] = { 2, 0, 0, 2, 0, 0, 0, 0 };
1129
1130 header[2] = type;
1131
1132 /* reset size */
1133 pBuf->m_used = 0;
1134
1135 /* add header */
1136 return (AppendToComBuf (pBuf, (void *) &header, 8));
1137
1138 } /* InitPacket */
1139
1140 /***********************************************************/
1141
1142 /* write length data to packet header
1143 */
1144 void
FinalisePacket(struct ComBuf * pBuf)1145 FinalisePacket (struct ComBuf *pBuf)
1146 {
1147
1148 /* sanity check */
1149 if (pBuf->m_used < 8)
1150 return;
1151
1152 /* set the size */
1153 *((unsigned short *) (pBuf->m_pBuf + 6)) = htons (pBuf->m_used - 8);
1154
1155 DBG (20, "FinalisePacket: outgoing packet:\n");
1156 HexDump (20, pBuf->m_pBuf, pBuf->m_used);
1157
1158 } /* FinalisePacket */
1159
1160 /***********************************************************/
1161
1162 /* \return 1 if message is complete, 0 otherwise */
1163 int
MessageIsComplete(unsigned char * pData,size_t size)1164 MessageIsComplete (unsigned char *pData, size_t size)
1165 {
1166 unsigned short dataSize;
1167
1168 /* sanity check */
1169 if (size < 8)
1170 return 0;
1171
1172 /* :NOTE: we can't just cast to a short as data may not be aligned */
1173 dataSize = (((unsigned short) pData[6]) << 8) | pData[7];
1174
1175 DBG (20, "MessageIsComplete: data size = %d\n", dataSize);
1176
1177 if (size >= (size_t) (dataSize + 8))
1178 return 1;
1179 else
1180 return 0;
1181
1182 } /* MessageIsComplete */
1183
1184 /***********************************************************/
1185
1186 /* process a registration broadcast response
1187 \return struct DeviceRecord pointer on success (caller frees), NULL on failure
1188 */
1189 struct DeviceRecord *
ProcessFindResponse(unsigned char * pData,size_t size)1190 ProcessFindResponse (unsigned char *pData, size_t size)
1191 {
1192
1193 struct DeviceRecord *pDevice = NULL;
1194 unsigned short messageSize, nameSize, valueSize;
1195 unsigned char *pItem, *pEnd, *pValue;
1196 char printerName[256] = { 0 };
1197 char printerModel[256] = "1600n";
1198 char *pModel, *pName;
1199
1200
1201 DBG (10, "ProcessFindResponse: processing %lu bytes, pData=%p\n",
1202 (unsigned long) size, (void *) pData);
1203
1204 /* check we have a complete packet */
1205 if (!MessageIsComplete (pData, size))
1206 {
1207 DBG (1, "ProcessFindResponse: Ignoring incomplete packet\n");
1208 return NULL;
1209 }
1210
1211 /* extract data size */
1212 messageSize = (((unsigned short) (pData[6])) << 8) | pData[7];
1213
1214 /* loop through items in message */
1215 pItem = pData + 8;
1216 pEnd = pItem + messageSize;
1217 while (pItem < pEnd)
1218 {
1219
1220 pItem++;
1221 nameSize = (((unsigned short) pItem[0]) << 8) | pItem[1];
1222 pItem += 2;
1223 pName = (char *) pItem;
1224
1225 pItem += nameSize;
1226
1227 pItem++;
1228 valueSize = (((unsigned short) pItem[0]) << 8) | pItem[1];
1229 pItem += 2;
1230
1231 pValue = pItem;
1232
1233 pItem += valueSize;
1234
1235 /* process the item */
1236 if (!strncmp ("std-scan-discovery-ip", pName, nameSize))
1237 {
1238
1239 snprintf (printerName, sizeof (printerName), "%d.%d.%d.%d",
1240 (int) pValue[0],
1241 (int) pValue[1], (int) pValue[2], (int) pValue[3]);
1242 DBG (2, "%s\n", printerName);
1243
1244 }
1245 else if (!strncmp ("std-scan-discovery-model-name", pName, nameSize))
1246 {
1247
1248 memset (printerModel, 0, sizeof (printerModel));
1249 if (valueSize > (sizeof (printerModel) - 1))
1250 valueSize = sizeof (printerModel) - 1;
1251 memcpy (printerModel, pValue, valueSize);
1252 DBG (2, "std-scan-discovery-model-name: %s\n", printerModel);
1253
1254 }
1255
1256 } /* while pItem */
1257
1258 /* just in case nothing sensible was found */
1259 if ( ! strlen( printerName ) ) return NULL;
1260
1261 pDevice = malloc (sizeof (struct DeviceRecord));
1262 if (!pDevice)
1263 {
1264 DBG (1, "ProcessFindResponse: memory allocation failure\n");
1265 return NULL;
1266 }
1267
1268 /* knock off "Dell " from start of model name */
1269 pModel = printerModel;
1270 if ( ! strncmp( pModel, "Dell ", 5 ) )
1271 pModel += 5;
1272
1273 pDevice->m_pName = strdup( printerName );
1274 pDevice->m_device.vendor = "Dell";
1275 pDevice->m_pModel = strdup (pModel);
1276 pDevice->m_device.type = "multi-function peripheral";
1277
1278 pDevice->m_device.name = pDevice->m_pName;
1279 pDevice->m_device.model = pDevice->m_pModel;
1280
1281 return pDevice;
1282
1283 } /* ProcessFindResponse */
1284
1285 /***********************************************************/
1286
1287 /* frees a scanner state struct stored in gOpenScanners */
1288 void
FreeScannerState(int iHandle)1289 FreeScannerState (int iHandle)
1290 {
1291
1292 /* check range etc */
1293 if (!ValidScannerNumber (iHandle))
1294 return;
1295
1296 /* close UDP handle */
1297 if (gOpenScanners[iHandle]->m_udpFd)
1298 close (gOpenScanners[iHandle]->m_udpFd);
1299
1300 /* free m_buf */
1301 FreeComBuf (&gOpenScanners[iHandle]->m_buf);
1302
1303 /* free m_imageData */
1304 FreeComBuf (&gOpenScanners[iHandle]->m_imageData);
1305
1306 /* free the struct */
1307 free (gOpenScanners[iHandle]);
1308
1309 /* set pointer to NULL */
1310 gOpenScanners[iHandle] = NULL;
1311
1312 } /* FreeScannerState */
1313
1314 /***********************************************************/
1315
1316 /* \return 1 if iHandle is a valid member of gOpenScanners, 0 otherwise */
1317 int
ValidScannerNumber(int iHandle)1318 ValidScannerNumber (int iHandle)
1319 {
1320 /* check range */
1321 if ((iHandle < 0) || (iHandle >= MAX_SCANNERS))
1322 {
1323 DBG (1, "ValidScannerNumber: invalid scanner index %d", iHandle);
1324 return 0;
1325 }
1326
1327 /* check non-NULL pointer */
1328 if (!gOpenScanners[iHandle])
1329 {
1330 DBG (1, "ValidScannerNumber: NULL scanner struct %d", iHandle);
1331 return 0;
1332 }
1333
1334 /* OK */
1335 return 1;
1336
1337 } /* ValidScannerNumber */
1338
1339 /***********************************************************/
1340
1341 /* process UDP responses
1342 \return 0 in success, >0 otherwise */
1343 static int
ProcessUdpResponse(unsigned char * pData,size_t size,struct ScannerState * pState)1344 ProcessUdpResponse (unsigned char *pData, size_t size,
1345 struct ScannerState *pState)
1346 {
1347
1348 unsigned short messageSize, nameSize, valueSize;
1349 unsigned char *pItem, *pEnd;
1350 char sockBuf[SOCK_BUF_SIZE], *pName;
1351 struct ComBuf tcpBuf;
1352 int nread;
1353 unsigned int numUsed;
1354
1355 HexDump (15, pData, size);
1356
1357 DBG (10, "ProcessUdpResponse: processing %lu bytes, pData=%p\n",
1358 (unsigned long) size, (void *) pData);
1359
1360 /* check we have a complete packet */
1361 if (!MessageIsComplete (pData, size))
1362 {
1363 DBG (1, "ProcessUdpResponse: Ignoring incomplete packet\n");
1364 return 1;
1365 }
1366
1367 /* init a com buf for use in tcp communication */
1368 InitComBuf (&tcpBuf);
1369
1370 /* extract data size */
1371 messageSize = (((unsigned short) (pData[6])) << 8) | pData[7];
1372
1373 /* loop through items in message */
1374 pItem = pData + 8;
1375 pEnd = pItem + messageSize;
1376 while (pItem < pEnd)
1377 {
1378
1379 pItem++;
1380 nameSize = (((unsigned short) pItem[0]) << 8) | pItem[1];
1381 pItem += 2;
1382 pName = (char *) pItem;
1383
1384 pItem += nameSize;
1385
1386 pItem++;
1387 valueSize = (((unsigned short) pItem[0]) << 8) | pItem[1];
1388 pItem += 2;
1389
1390 pItem += valueSize;
1391
1392 /* process the item */
1393 if (!strncmp ("std-scan-request-tcp-connection", pName, nameSize))
1394 {
1395
1396 /* open TCP socket to scanner */
1397 if (!(pState->m_tcpFd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)))
1398 {
1399 DBG (1, "ProcessUdpResponse: error opening TCP socket\n");
1400 return 2;
1401 }
1402 if (connect (pState->m_tcpFd,
1403 (struct sockaddr *) &pState->m_sockAddr,
1404 sizeof (pState->m_sockAddr)))
1405 {
1406 DBG (1,
1407 "ProcessUdpResponse: error connecting to scanner TCP port\n");
1408 goto cleanup;
1409 }
1410
1411 DBG (1, "ProcessUdpResponse: opened TCP connection to scanner\n");
1412
1413 /* clear read buf */
1414 tcpBuf.m_used = 0;
1415
1416 /* TCP read loop */
1417 while (1)
1418 {
1419
1420 nread = read (pState->m_tcpFd, sockBuf, sizeof (sockBuf));
1421
1422 if (nread <= 0)
1423 {
1424 DBG (1, "ProcessUdpResponse: TCP read returned %d\n",
1425 nread);
1426 break;
1427 }
1428
1429 /* append message to buffer */
1430 if (AppendToComBuf (&tcpBuf, (unsigned char *) sockBuf, nread))
1431 goto cleanup;
1432
1433 /* process all available responses */
1434 while (tcpBuf.m_used)
1435 {
1436
1437 /* note the buffer size before the call */
1438 numUsed = tcpBuf.m_used;
1439
1440 /* process the response */
1441 if (ProcessTcpResponse (pState, &tcpBuf))
1442 goto cleanup;
1443
1444 /* if the buffer size has not changed then assume no more processing is possible */
1445 if (numUsed == tcpBuf.m_used)
1446 break;
1447
1448 } /* while */
1449
1450 } /* while */
1451
1452 close (pState->m_tcpFd);
1453 DBG (1, "ProcessUdpResponse: closed TCP connection to scanner\n");
1454
1455 /* signal end of session */
1456 pState->m_bFinish = 1;
1457
1458 } /* if */
1459
1460 } /* while pItem */
1461
1462 return 0;
1463
1464 cleanup:
1465
1466 FreeComBuf (&tcpBuf);
1467 close (pState->m_tcpFd);
1468 return 3;
1469
1470 } /* ProcessUdpResponse */
1471
1472 /***********************************************************/
1473
1474 /* process TCP responses, \return 0 in success, >0 otherwise */
1475 int
ProcessTcpResponse(struct ScannerState * pState,struct ComBuf * pTcpBuf)1476 ProcessTcpResponse (struct ScannerState *pState, struct ComBuf *pTcpBuf)
1477 {
1478
1479 struct ComBuf buf;
1480 unsigned short messageSize = 0, nameSize, valueSize, dataChunkSize;
1481 unsigned char *pItem, *pEnd, *pValue;
1482 unsigned char *pData = pTcpBuf->m_pBuf;
1483 char *pName;
1484 unsigned int uiVal;
1485 int errorCheck = 0;
1486 int bProcessImage = 0;
1487
1488 DBG (10, "ProcessTcpResponse: processing %lu bytes, pData=%p\n",
1489 (unsigned long) pTcpBuf->m_used, (void *) pData);
1490 HexDump (15, pData, pTcpBuf->m_used);
1491
1492 /* if message not complete then wait for more to arrive */
1493 if (!MessageIsComplete (pData, pTcpBuf->m_used))
1494 {
1495 DBG (10, "ProcessTcpResponse: incomplete message, returning\n");
1496 return 0;
1497 }
1498
1499 /* init a buffer for our outbound messages */
1500 if (InitComBuf (&buf))
1501 {
1502 errorCheck |= 1;
1503 goto cleanup;
1504 }
1505
1506 /* extract data size */
1507 messageSize = (((unsigned short) (pData[6])) << 8) | pData[7];
1508
1509 /* loop through items in message */
1510 pItem = pData + 8;
1511 pEnd = pItem + messageSize;
1512 while (pItem < pEnd)
1513 {
1514
1515 pItem++;
1516 nameSize = (((unsigned short) pItem[0]) << 8) | pItem[1];
1517 pItem += 2;
1518 pName = (char *) pItem;
1519
1520 pItem += nameSize;
1521
1522 pItem++;
1523 valueSize = (((unsigned short) pItem[0]) << 8) | pItem[1];
1524 pItem += 2;
1525
1526 pValue = pItem;
1527
1528 pItem += valueSize;
1529
1530 /* process the item */
1531 if (!strncmp ("std-scan-session-open", pName, nameSize))
1532 {
1533
1534 errorCheck |= InitPacket (&buf, 0x02);
1535 uiVal = 0;
1536 errorCheck |=
1537 AppendMessageToPacket (&buf, 0x22,
1538 "std-scan-session-open-response", 0x05,
1539 &uiVal, sizeof (uiVal));
1540 FinalisePacket (&buf);
1541 send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0);
1542
1543 }
1544 else if (!strncmp ("std-scan-getclientpref", pName, nameSize))
1545 {
1546
1547 errorCheck |= InitPacket (&buf, 0x02);
1548 uiVal = 0;
1549 errorCheck |=
1550 AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-x1",
1551 0x05, &uiVal, sizeof (uiVal));
1552 errorCheck |=
1553 AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-x2",
1554 0x05, &uiVal, sizeof (uiVal));
1555 errorCheck |=
1556 AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-y1",
1557 0x05, &uiVal, sizeof (uiVal));
1558 errorCheck |=
1559 AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-y2",
1560 0x05, &uiVal, sizeof (uiVal));
1561 errorCheck |=
1562 AppendMessageToPacket (&buf, 0x22,
1563 "std-scan-getclientpref-xresolution", 0x04,
1564 &pState->m_xres, sizeof (pState->m_xres));
1565 errorCheck |=
1566 AppendMessageToPacket (&buf, 0x22,
1567 "std-scan-getclientpref-yresolution", 0x04,
1568 &pState->m_yres, sizeof (pState->m_yres));
1569 errorCheck |=
1570 AppendMessageToPacket (&buf, 0x22,
1571 "std-scan-getclientpref-image-composition",
1572 0x06, &pState->m_composition,
1573 sizeof (pState->m_composition));
1574 errorCheck |=
1575 AppendMessageToPacket (&buf, 0x22,
1576 "std-scan-getclientpref-brightness", 0x02,
1577 &pState->m_brightness,
1578 sizeof (pState->m_brightness));
1579 errorCheck |=
1580 AppendMessageToPacket (&buf, 0x22,
1581 "std-scan-getclientpref-image-compression",
1582 0x06, &pState->m_compression,
1583 sizeof (pState->m_compression));
1584 errorCheck |=
1585 AppendMessageToPacket (&buf, 0x22,
1586 "std-scan-getclientpref-file-type", 0x06,
1587 &pState->m_fileType,
1588 sizeof (pState->m_fileType));
1589 errorCheck |=
1590 AppendMessageToPacket (&buf, 0x22,
1591 "std-scan-getclientpref-paper-size-detect",
1592 0x06, &uiVal, sizeof (uiVal));
1593 errorCheck |=
1594 AppendMessageToPacket (&buf, 0x22,
1595 "std-scan-getclientpref-paper-scanner-type",
1596 0x06, &uiVal, sizeof (uiVal));
1597 FinalisePacket (&buf);
1598 send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0);
1599
1600 }
1601 else if (!strncmp ("std-scan-document-start", pName, nameSize))
1602 {
1603 errorCheck |= InitPacket (&buf, 0x02);
1604 uiVal = 0;
1605 errorCheck |=
1606 AppendMessageToPacket (&buf, 0x22,
1607 "std-scan-document-start-response", 0x05,
1608 &uiVal, sizeof (uiVal));
1609 FinalisePacket (&buf);
1610 send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0);
1611 }
1612 else if (!strncmp ("std-scan-document-file-type", pName, nameSize))
1613 {
1614 memcpy (&pState->m_fileType, pValue, sizeof (pState->m_fileType));
1615 DBG (5, "File type: %x\n", ntohl (pState->m_fileType));
1616 }
1617 else
1618 if (!strncmp ("std-scan-document-image-compression", pName, nameSize))
1619 {
1620 memcpy (&pState->m_compression, pValue,
1621 sizeof (pState->m_compression));
1622 DBG (5, "Compression: %x\n", ntohl (pState->m_compression));
1623
1624 }
1625 else if (!strncmp ("std-scan-document-xresolution", pName, nameSize))
1626 {
1627 memcpy (&pState->m_xres, pValue, sizeof (pState->m_xres));
1628 DBG (5, "X resolution: %d\n", ntohs (pState->m_xres));
1629 }
1630 else if (!strncmp ("std-scan-document-yresolution", pName, nameSize))
1631 {
1632 memcpy (&pState->m_yres, pValue, sizeof (pState->m_yres));
1633 DBG (5, "Y resolution: %d\n", ntohs (pState->m_yres));
1634 }
1635 else if (!strncmp ("std-scan-page-widthpixel", pName, nameSize))
1636 {
1637 if (1 || !pState->m_pixelWidth)
1638 {
1639 memcpy (&pState->m_pixelWidth, pValue,
1640 sizeof (pState->m_pixelWidth));
1641 DBG (5, "Width: %d\n", ntohl (pState->m_pixelWidth));
1642 }
1643 else
1644 {
1645 DBG (5, "Ignoring width (already have a value)\n");
1646 }
1647 }
1648 else if (!strncmp ("std-scan-page-heightpixel", pName, nameSize))
1649 {
1650 if (1 || !pState->m_pixelHeight)
1651 {
1652 memcpy (&pState->m_pixelHeight, pValue,
1653 sizeof (pState->m_pixelHeight));
1654 DBG (5, "Height: %d\n", ntohl (pState->m_pixelHeight));
1655 }
1656 else
1657 {
1658 DBG (5, "Ignoring height (already have a value)\n");
1659 }
1660 }
1661 else if (!strncmp ("std-scan-page-start", pName, nameSize))
1662 {
1663 errorCheck |= InitPacket (&buf, 0x02);
1664 uiVal = 0;
1665 errorCheck |=
1666 AppendMessageToPacket (&buf, 0x22, "std-scan-page-start-response",
1667 0x05, &uiVal, sizeof (uiVal));
1668 FinalisePacket (&buf);
1669 send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0);
1670
1671 /* reset the data buffer ready to store a new page */
1672 pState->m_buf.m_used = 0;
1673
1674 /* init current page size */
1675 pState->m_currentPageBytes = 0;
1676
1677 pState->m_pixelWidth = 0;
1678 pState->m_pixelHeight = 0;
1679 }
1680 else if (!strncmp ("std-scan-page-end", pName, nameSize))
1681 {
1682 bProcessImage = 1;
1683
1684 errorCheck |= InitPacket (&buf, 0x02);
1685 uiVal = 0;
1686 errorCheck |=
1687 AppendMessageToPacket (&buf, 0x22, "std-scan-page-end-response",
1688 0x05, &uiVal, sizeof (uiVal));
1689 FinalisePacket (&buf);
1690 send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0);
1691 }
1692 else if (!strncmp ("std-scan-document-end", pName, nameSize))
1693 {
1694 errorCheck |= InitPacket (&buf, 0x02);
1695 uiVal = 0;
1696 errorCheck |=
1697 AppendMessageToPacket (&buf, 0x22,
1698 "std-scan-document-end-response", 0x05,
1699 &uiVal, sizeof (uiVal));
1700 FinalisePacket (&buf);
1701 send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0);
1702
1703 /* reset the data buffer ready to store a new page */
1704 pState->m_buf.m_used = 0;
1705 }
1706 else if (!strncmp ("std-scan-session-end", pName, nameSize))
1707 {
1708 errorCheck |= InitPacket (&buf, 0x02);
1709 uiVal = 0;
1710 errorCheck |=
1711 AppendMessageToPacket (&buf, 0x22,
1712 "std-scan-session-end-response", 0x05,
1713 &uiVal, sizeof (uiVal));
1714 FinalisePacket (&buf);
1715 send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0);
1716
1717 /* initialise a shutodwn of the socket */
1718 shutdown (pState->m_tcpFd, SHUT_RDWR);
1719 }
1720 else if (!strncmp ("std-scan-scandata-error", pName, nameSize))
1721 {
1722 /* determine the size of data in this chunk */
1723 dataChunkSize = (pItem[6] << 8) + pItem[7];
1724
1725 pItem += 8;
1726
1727 DBG (10, "Reading %d bytes of scan data\n", dataChunkSize);
1728
1729 /* append message to buffer */
1730 errorCheck |= AppendToComBuf (&pState->m_buf, pItem, dataChunkSize);
1731
1732 pItem += dataChunkSize;
1733
1734 DBG (10, "Accumulated %lu bytes of scan data so far\n",
1735 (unsigned long)pState->m_buf.m_used);
1736 } /* if */
1737 } /* while */
1738
1739 /* process page data if required */
1740 if ( bProcessImage ) errorCheck |= ProcessPageData (pState);
1741
1742 cleanup:
1743
1744 /* remove processed data (including 8 byte header) from start of tcp buffer */
1745 PopFromComBuf (pTcpBuf, messageSize + 8);
1746
1747 /* free com buf */
1748 FreeComBuf (&buf);
1749
1750 return errorCheck;
1751
1752 } /* ProcessTcpResponse */
1753
1754 /***********************************************************/
1755
1756 /* remove data from the front of a ComBuf struct
1757 \return 0 if successful, >0 otherwise
1758 */
1759 int
PopFromComBuf(struct ComBuf * pBuf,size_t datSize)1760 PopFromComBuf (struct ComBuf *pBuf, size_t datSize)
1761 {
1762
1763 /* check if we're trying to remove more data than is present */
1764 if (datSize > pBuf->m_used)
1765 {
1766 pBuf->m_used = 0;
1767 return 1;
1768 }
1769
1770 /* check easy cases */
1771 if ((!datSize) || (datSize == pBuf->m_used))
1772 {
1773 pBuf->m_used -= datSize;
1774 return 0;
1775 }
1776
1777 /* move remaining memory contents to start */
1778 memmove (pBuf->m_pBuf, pBuf->m_pBuf + datSize, pBuf->m_used - datSize);
1779
1780 pBuf->m_used -= datSize;
1781 return 0;
1782
1783 } /* PopFromComBuf */
1784
1785 /***********************************************************/
1786
1787 /* Process the data from a single scanned page, \return 0 in success, >0 otherwise */
1788 int
ProcessPageData(struct ScannerState * pState)1789 ProcessPageData (struct ScannerState *pState)
1790 {
1791
1792 FILE *fTmp;
1793 int fdTmp;
1794 struct jpeg_source_mgr jpegSrcMgr;
1795 struct JpegDataDecompState jpegCinfo;
1796 struct jpeg_error_mgr jpegErr;
1797 int numPixels, iPixel, width, height, scanLineSize, imageBytes;
1798 int ret = 0;
1799 struct PageInfo pageInfo;
1800
1801 JSAMPLE *pJpegLine = NULL;
1802 uint32_t *pTiffRgba = NULL;
1803 unsigned char *pOut;
1804 char tiffErrBuf[1024];
1805
1806 TIFF *pTiff = NULL;
1807
1808 /* If there's no data then there's nothing to write */
1809 if (!pState->m_buf.m_used)
1810 return 0;
1811
1812 DBG (1, "ProcessPageData: Got compression %x\n",
1813 ntohl (pState->m_compression));
1814
1815 switch (ntohl (pState->m_compression))
1816 {
1817
1818 case 0x20:
1819 /* decode as JPEG if appropriate */
1820 {
1821
1822 jpegSrcMgr.resync_to_restart = jpeg_resync_to_restart;
1823 jpegSrcMgr.init_source = JpegDecompInitSource;
1824 jpegSrcMgr.fill_input_buffer = JpegDecompFillInputBuffer;
1825 jpegSrcMgr.skip_input_data = JpegDecompSkipInputData;
1826 jpegSrcMgr.term_source = JpegDecompTermSource;
1827
1828 jpegCinfo.m_cinfo.err = jpeg_std_error (&jpegErr);
1829 jpeg_create_decompress (&jpegCinfo.m_cinfo);
1830 jpegCinfo.m_cinfo.src = &jpegSrcMgr;
1831 jpegCinfo.m_bytesRemaining = pState->m_buf.m_used;
1832 jpegCinfo.m_pData = pState->m_buf.m_pBuf;
1833
1834 jpeg_read_header (&jpegCinfo.m_cinfo, TRUE);
1835 jpeg_start_decompress (&jpegCinfo.m_cinfo);
1836
1837 /* allocate space for a single scanline */
1838 scanLineSize = jpegCinfo.m_cinfo.output_width
1839 * jpegCinfo.m_cinfo.output_components;
1840 DBG (1, "ProcessPageData: image dimensions: %d x %d, line size: %d\n",
1841 jpegCinfo.m_cinfo.output_width,
1842 jpegCinfo.m_cinfo.output_height, scanLineSize);
1843
1844 pJpegLine = calloc (scanLineSize, sizeof (JSAMPLE));
1845 if (!pJpegLine)
1846 {
1847 DBG (1, "ProcessPageData: memory allocation error\n");
1848 ret = 1;
1849 goto JPEG_CLEANUP;
1850 } /* if */
1851
1852 /* note dimensions - may be different from those previously reported */
1853 pState->m_pixelWidth = htonl (jpegCinfo.m_cinfo.output_width);
1854 pState->m_pixelHeight = htonl (jpegCinfo.m_cinfo.output_height);
1855
1856 /* decode scanlines */
1857 while (jpegCinfo.m_cinfo.output_scanline
1858 < jpegCinfo.m_cinfo.output_height)
1859 {
1860 DBG (20, "Reading scanline %d of %d\n",
1861 jpegCinfo.m_cinfo.output_scanline,
1862 jpegCinfo.m_cinfo.output_height);
1863
1864 /* read scanline */
1865 jpeg_read_scanlines (&jpegCinfo.m_cinfo, &pJpegLine, 1);
1866
1867 /* append to output buffer */
1868 ret |= AppendToComBuf (&pState->m_imageData,
1869 pJpegLine, scanLineSize);
1870
1871 } /* while */
1872
1873 /* update info for this page */
1874 pageInfo.m_width = jpegCinfo.m_cinfo.output_width;
1875 pageInfo.m_height = jpegCinfo.m_cinfo.output_height;
1876 pageInfo.m_totalSize = pageInfo.m_width * pageInfo.m_height * 3;
1877 pageInfo.m_bytesRemaining = pageInfo.m_totalSize;
1878
1879 DBG( 1, "Process page data: page %d: JPEG image: %d x %d, %d bytes\n",
1880 pState->m_numPages, pageInfo.m_width, pageInfo.m_height, pageInfo.m_totalSize );
1881
1882 ret |= AppendToComBuf( & pState->m_pageInfo, (unsigned char*)& pageInfo, sizeof( pageInfo ) );
1883 ++( pState->m_numPages );
1884
1885 JPEG_CLEANUP:
1886 jpeg_finish_decompress (&jpegCinfo.m_cinfo);
1887 jpeg_destroy_decompress (&jpegCinfo.m_cinfo);
1888
1889 if (pJpegLine)
1890 free (pJpegLine);
1891
1892 return ret;
1893 } /* case JPEG */
1894
1895 case 0x08:
1896 /* CCITT Group 4 Fax data */
1897 {
1898 /* get a temp file
1899 :TODO: 2006-04-18: Use TIFFClientOpen and do everything in RAM
1900 */
1901 fTmp = tmpfile ();
1902 fdTmp = fileno (fTmp);
1903
1904 pTiff = TIFFFdOpen (fdTmp, "tempfile", "w");
1905 if (!pTiff)
1906 {
1907 DBG (1, "ProcessPageData: Error opening temp TIFF file");
1908 ret = SANE_STATUS_IO_ERROR;
1909 goto TIFF_CLEANUP;
1910 }
1911
1912 /* create a TIFF file */
1913 width = ntohl (pState->m_pixelWidth);
1914 height = ntohl (pState->m_pixelHeight);
1915 TIFFSetField (pTiff, TIFFTAG_IMAGEWIDTH, width);
1916 TIFFSetField (pTiff, TIFFTAG_IMAGELENGTH, height);
1917 TIFFSetField (pTiff, TIFFTAG_BITSPERSAMPLE, 1);
1918 TIFFSetField (pTiff, TIFFTAG_PHOTOMETRIC, 0); /* 0 is white */
1919 TIFFSetField (pTiff, TIFFTAG_COMPRESSION, 4); /* CCITT Group 4 */
1920 TIFFSetField (pTiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1921
1922 TIFFWriteRawStrip (pTiff, 0, pState->m_buf.m_pBuf,
1923 pState->m_buf.m_used);
1924
1925 if (0 > TIFFRGBAImageOK (pTiff, tiffErrBuf))
1926 {
1927 DBG (1, "ProcessPageData: %s\n", tiffErrBuf);
1928 ret = SANE_STATUS_IO_ERROR;
1929 goto TIFF_CLEANUP;
1930 }
1931
1932 /* allocate space for RGBA representation of image */
1933 numPixels = height * width;
1934 DBG (20, "ProcessPageData: num TIFF RGBA pixels: %d\n", numPixels);
1935 if (!(pTiffRgba = calloc (numPixels, sizeof (u_long))))
1936 {
1937 ret = SANE_STATUS_NO_MEM;
1938 goto TIFF_CLEANUP;
1939 }
1940
1941 /* make space in image buffer to store the results */
1942 imageBytes = width * height * 3;
1943 ret |= AppendToComBuf (&pState->m_imageData, NULL, imageBytes);
1944 if (ret)
1945 goto TIFF_CLEANUP;
1946
1947 /* get a pointer to the start of the output data */
1948 pOut = pState->m_imageData.m_pBuf
1949 + pState->m_imageData.m_used - imageBytes;
1950
1951 /* read RGBA image */
1952 DBG (20, "ProcessPageData: setting up read buffer\n");
1953 TIFFReadBufferSetup (pTiff, NULL, width * height * sizeof (u_long));
1954 DBG (20, "ProcessPageData: reading RGBA data\n");
1955 TIFFReadRGBAImageOriented (pTiff, width, height, pTiffRgba,
1956 ORIENTATION_TOPLEFT, 0);
1957
1958 /* loop over pixels */
1959 for (iPixel = 0; iPixel < numPixels; ++iPixel)
1960 {
1961
1962 *(pOut++) = TIFFGetR (pTiffRgba[iPixel]);
1963 *(pOut++) = TIFFGetG (pTiffRgba[iPixel]);
1964 *(pOut++) = TIFFGetB (pTiffRgba[iPixel]);
1965
1966 } /* for iRow */
1967
1968
1969
1970 /* update info for this page */
1971 pageInfo.m_width = width;
1972 pageInfo.m_height = height;
1973 pageInfo.m_totalSize = pageInfo.m_width * pageInfo.m_height * 3;
1974 pageInfo.m_bytesRemaining = pageInfo.m_totalSize;
1975
1976 DBG( 1, "Process page data: page %d: TIFF image: %d x %d, %d bytes\n",
1977 pState->m_numPages, width, height, pageInfo.m_totalSize );
1978
1979 ret |= AppendToComBuf( & pState->m_pageInfo, (unsigned char*)& pageInfo, sizeof( pageInfo ) );
1980 ++( pState->m_numPages );
1981
1982 TIFF_CLEANUP:
1983 if (pTiff)
1984 TIFFClose (pTiff);
1985 if (fTmp)
1986 fclose (fTmp);
1987 if (pTiffRgba)
1988 free (pTiffRgba);
1989 return ret;
1990
1991 } /* case CCITT */
1992 default:
1993 /* this is not expected or very useful */
1994 {
1995 DBG (1, "ProcessPageData: Unexpected compression flag %d\n", ntohl (pState->m_compression));
1996 ret = SANE_STATUS_IO_ERROR;
1997 }
1998 } /* switch */
1999
2000 return ret;
2001 } /* ProcessPageData */
2002
2003 /***********************************************************/
2004
2005 void
JpegDecompInitSource(j_decompress_ptr cinfo)2006 JpegDecompInitSource (j_decompress_ptr cinfo)
2007 /* Libjpeg decompression interface */
2008 {
2009 cinfo->src->bytes_in_buffer = 0;
2010
2011 } /* JpegDecompInitSource */
2012
2013 /***********************************************************/
2014
2015 boolean
JpegDecompFillInputBuffer(j_decompress_ptr cinfo)2016 JpegDecompFillInputBuffer (j_decompress_ptr cinfo)
2017 /* Libjpeg decompression interface */
2018 {
2019 struct JpegDataDecompState *pState = (struct JpegDataDecompState *) cinfo;
2020 static const unsigned char eoiByte[] = {
2021 0xFF, JPEG_EOI
2022 };
2023
2024 DBG (10, "JpegDecompFillInputBuffer: bytes remaining: %d\n",
2025 pState->m_bytesRemaining);
2026
2027 if (!pState->m_bytesRemaining)
2028 {
2029
2030 /* no input data available so return dummy data */
2031 cinfo->src->bytes_in_buffer = 2;
2032 cinfo->src->next_input_byte = (const JOCTET *) eoiByte;
2033
2034 }
2035 else
2036 {
2037
2038 /* point to data */
2039 cinfo->src->bytes_in_buffer = pState->m_bytesRemaining;
2040 cinfo->src->next_input_byte = (const JOCTET *) pState->m_pData;
2041
2042 /* note that data is now gone */
2043 pState->m_bytesRemaining = 0;
2044
2045 } /* if */
2046
2047 return TRUE;
2048
2049 } /* JpegDecompFillInputBuffer */
2050
2051 /***********************************************************/
2052
2053 void
JpegDecompSkipInputData(j_decompress_ptr cinfo,long numBytes)2054 JpegDecompSkipInputData (j_decompress_ptr cinfo, long numBytes)
2055 /* Libjpeg decompression interface */
2056 {
2057 DBG (10, "JpegDecompSkipInputData: skipping %ld bytes\n", numBytes);
2058
2059 cinfo->src->bytes_in_buffer -= numBytes;
2060 cinfo->src->next_input_byte += numBytes;
2061
2062 } /* JpegDecompSkipInputData */
2063
2064 /***********************************************************/
2065
2066 void
JpegDecompTermSource(j_decompress_ptr __sane_unused__ cinfo)2067 JpegDecompTermSource (j_decompress_ptr __sane_unused__ cinfo)
2068 /* Libjpeg decompression interface */
2069 {
2070 /* nothing to do */
2071
2072 } /* JpegDecompTermSource */
2073
2074 /***********************************************************/
2075