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