Tizen 2.1 base
[platform/upstream/hplip.git] / scan / sane / mfpdtf.c
1 /************************************************************************************\
2
3   mfpdtf.c - HP Multi-Function Peripheral Data Transfer Format filter.
4
5   (c) 2001-2005 Copyright Hewlett-Packard Development Company, LP
6
7   Permission is hereby granted, free of charge, to any person obtaining a copy 
8   of this software and associated documentation files (the "Software"), to deal 
9   in the Software without restriction, including without limitation the rights 
10   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
11   of the Software, and to permit persons to whom the Software is furnished to do 
12   so, subject to the following conditions:
13
14   The above copyright notice and this permission notice shall be included in all
15   copies or substantial portions of the Software.
16
17   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
18   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 
19   FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
20   COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
21   IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
22   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24   Contributing Author(s): David Paschal, Don Welch, David Suffield
25
26 \************************************************************************************/
27
28 #include "common.h"
29 #include "mfpdtf.h"
30 #include "io.h"
31
32 #define DEBUG_DECLARE_ONLY
33 #include "sanei_debug.h"
34
35 static union MfpdtfVariantHeader_u * MfpdtfReadAllocateVariantHeader( Mfpdtf_t mfpdtf,
36                                                                int datalen )
37 {
38     if( mfpdtf->read.pVariantHeader )
39     {
40         free( mfpdtf->read.pVariantHeader );
41         mfpdtf->read.pVariantHeader = 0;
42     }
43     mfpdtf->read.lenVariantHeader = datalen;
44     if( datalen )
45     {
46         mfpdtf->read.pVariantHeader = malloc( datalen );
47     }
48     return mfpdtf->read.pVariantHeader;
49 }
50
51 static int MfpdtfReadSetTimeout( Mfpdtf_t mfpdtf, int seconds )
52 {
53     mfpdtf->read.timeout.tv_sec = seconds;
54     mfpdtf->read.timeout.tv_usec = 0;
55
56     return seconds;
57 }
58
59 Mfpdtf_t __attribute__ ((visibility ("hidden"))) MfpdtfAllocate( int deviceid, int channelid )
60 {
61     int size = sizeof( struct Mfpdtf_s );
62     Mfpdtf_t mfpdtf = malloc( size );
63     
64     if( mfpdtf )
65     {
66         memset( mfpdtf, 0, size );
67         mfpdtf->channelid = channelid;
68         mfpdtf->deviceid = deviceid;
69         mfpdtf->fdLog = -1;
70         MfpdtfReadSetTimeout( mfpdtf, 30 );
71         MfpdtfReadStart( mfpdtf );
72     }
73     
74     return mfpdtf;
75 }
76
77 int __attribute__ ((visibility ("hidden"))) MfpdtfDeallocate( Mfpdtf_t mfpdtf )
78 {
79     if( !mfpdtf )
80     {
81         return ERROR;
82     }
83     MfpdtfLogToFile( mfpdtf, 0 );
84     MfpdtfReadAllocateVariantHeader( mfpdtf, 0 );
85     free( mfpdtf );
86     return OK;
87 }
88
89 int __attribute__ ((visibility ("hidden"))) MfpdtfSetChannel( Mfpdtf_t mfpdtf, int channelid )
90 {
91     mfpdtf->channelid = channelid;
92     /* If necessary, we can query the device ID string using the
93      * channel's device pointer. */
94     return OK;
95 }
96
97 int __attribute__ ((visibility ("hidden"))) MfpdtfLogToFile( Mfpdtf_t mfpdtf, char * filename )
98 {
99     if( mfpdtf->fdLog != -1 )
100     {
101         close( mfpdtf->fdLog );
102         mfpdtf->fdLog = -1;
103     }
104     mfpdtf->logOffset = 0;
105     if( filename )
106     {
107         int fd = creat( filename, 0600 );
108         if( fd < 0 )
109         {
110             return ERROR;
111         }
112         mfpdtf->fdLog = fd;
113     }
114     return OK;
115 }
116
117 int __attribute__ ((visibility ("hidden"))) MfpdtfReadGetSimulateImageHeaders( Mfpdtf_t mfpdtf )
118 {
119     return mfpdtf->read.simulateImageHeaders;
120 }
121
122 int __attribute__ ((visibility ("hidden"))) MfpdtfReadSetSimulateImageHeaders( Mfpdtf_t mfpdtf,
123                                        int simulateImageHeaders )
124 {
125     mfpdtf->read.simulateImageHeaders = simulateImageHeaders;
126     return simulateImageHeaders;
127 }
128
129 int __attribute__ ((visibility ("hidden"))) MfpdtfReadStart( Mfpdtf_t mfpdtf )
130 {
131     mfpdtf->read.lastServiceResult = 0;
132     mfpdtf->read.dataType = ERROR;
133     mfpdtf->read.arrayRecordCount = mfpdtf->read.arrayRecordSize;
134     mfpdtf->read.fixedBlockBytesRemaining = 0;
135     mfpdtf->read.innerBlockBytesRemaining = 0;
136     mfpdtf->read.dontDecrementInnerBlock = 0;
137     MfpdtfReadAllocateVariantHeader( mfpdtf, 0 );
138
139     return OK;
140 }
141
142 static int MfpdtfReadIsImageData( Mfpdtf_t mfpdtf )
143 {
144     return ( ( MFPDTF_DT_MASK_IMAGE & ( 1 << mfpdtf->read.dataType ) ) !=
145              0 );
146 }
147
148 static int MfpdtfReadIsArrayData( Mfpdtf_t mfpdtf )
149 {
150     return ( !MfpdtfReadIsImageData( mfpdtf ) );
151 }
152
153 #define READ(buffer,datalen) \
154     do { \
155         int r=MfpdtfReadGeneric(mfpdtf, \
156             (unsigned char *)(buffer),datalen); \
157         if (r!=datalen) { \
158             if (r<0) return MFPDTF_RESULT_READ_ERROR; \
159             return MFPDTF_RESULT_READ_TIMEOUT; \
160         } \
161     } while(0)
162
163 #define RETURN(_result) \
164     return (mfpdtf->read.lastServiceResult=(_result));
165
166 static int MfpdtfReadGeneric( Mfpdtf_t mfpdtf, unsigned char * buffer, int datalen )
167 {
168     int r = 0;
169
170     /* Don't read past the currently-defined fixed block. */
171     if( datalen > mfpdtf->read.fixedBlockBytesRemaining )
172     {
173         datalen = mfpdtf->read.fixedBlockBytesRemaining;
174     }
175
176     /* Read the data. */
177     if( datalen > 0 )
178     {        
179         r = ReadChannelEx(mfpdtf->deviceid, 
180                            mfpdtf->channelid, 
181                            buffer, 
182                            datalen, 
183                            EXCEPTION_TIMEOUT);
184
185         if( r > 0 )
186         {
187             /* Account for and log what was read. */
188             mfpdtf->read.fixedBlockBytesRemaining -= r;
189             
190             if( !mfpdtf->read.dontDecrementInnerBlock )
191             {
192                 mfpdtf->read.innerBlockBytesRemaining -= r;
193             }
194             
195             mfpdtf->read.dontDecrementInnerBlock = 0;
196         }
197         
198         if( r != datalen )
199         {
200             mfpdtf->read.lastServiceResult = r < 0 ?
201                                              MFPDTF_RESULT_READ_ERROR :
202                                              MFPDTF_RESULT_READ_TIMEOUT;
203         }
204     }
205
206     return r;
207 }
208
209 int __attribute__ ((visibility ("hidden"))) MfpdtfReadService( Mfpdtf_t mfpdtf )
210 {
211     int result = 0;
212     int datalen, blockLength, headerLength;
213
214     if( mfpdtf->read.fixedBlockBytesRemaining <= 0 )
215     {
216         /* Read fixed header. */
217         datalen = sizeof( mfpdtf->read.fixedHeader );
218         mfpdtf->read.fixedBlockBytesRemaining = datalen;
219         //        DBG( 0, "********************************** FIXED HEADER **********************************.\n" );
220         mfpdtf->read.dontDecrementInnerBlock = 1;
221         
222         //READ( &mfpdtf->read.fixedHeader, datalen );
223         
224         int r = MfpdtfReadGeneric( mfpdtf, (unsigned char *)&mfpdtf->read.fixedHeader, datalen );
225
226         if( r!= datalen )
227         {
228             if( r < 0 )
229                 return MFPDTF_RESULT_READ_ERROR;
230             
231             return MFPDTF_RESULT_READ_TIMEOUT;
232         }
233         
234         /* Parse fixed header. */
235         blockLength = LEND_GET_LONG( mfpdtf->read.fixedHeader.blockLength );
236         mfpdtf->read.fixedBlockBytesRemaining = blockLength - datalen;
237         headerLength = LEND_GET_SHORT( mfpdtf->read.fixedHeader.headerLength );
238
239         /* Scan data type? */
240         if(mfpdtf->read.fixedHeader.dataType != DT_SCAN)
241         {
242             bug("invalid mfpdtf fixed header datatype=%d\n", mfpdtf->read.fixedHeader.dataType);
243             return MFPDTF_RESULT_READ_ERROR;
244         }
245
246         /* Is this a new data type? */
247         if( mfpdtf->read.dataType != mfpdtf->read.fixedHeader.dataType )
248         {
249             mfpdtf->read.dataType = mfpdtf->read.fixedHeader.dataType;
250             result |= MFPDTF_RESULT_NEW_DATA_TYPE;
251         }
252
253         DBG(6, "fixed header page_flags=%x: %s %d\n", mfpdtf->read.fixedHeader.pageFlags, __FILE__, __LINE__);
254
255         /* Read variant header (if any). */
256         datalen = headerLength - sizeof( mfpdtf->read.fixedHeader );
257         
258         if( datalen > 0 )
259         {
260             DBG(6, "reading variant header size=%d: %s %d\n", datalen, __FILE__, __LINE__);
261             
262             if( !MfpdtfReadAllocateVariantHeader( mfpdtf, datalen ) )
263             {
264                 RETURN( MFPDTF_RESULT_OTHER_ERROR );
265             }
266             mfpdtf->read.dontDecrementInnerBlock = 1;
267             
268             int r = MfpdtfReadGeneric( mfpdtf, (unsigned char *)mfpdtf->read.pVariantHeader, datalen );
269     
270             if( r!= datalen )
271             {
272                 if( r < 0 )
273                     return MFPDTF_RESULT_READ_ERROR;
274                 
275                 return MFPDTF_RESULT_READ_TIMEOUT;
276             
277             }
278             
279             //            DBG( 0, "********************************** VARIANT HEADER **********************************.\n" );
280             
281             result |= MFPDTF_RESULT_NEW_VARIANT_HEADER;
282
283             /* Is this a valid array variant header? */
284             mfpdtf->read.arrayRecordSize = 0;
285             mfpdtf->read.arrayRecordCount = 0;
286             mfpdtf->read.innerBlockBytesRemaining = 0;
287             
288             if( MfpdtfReadIsArrayData( mfpdtf ) &&
289                 mfpdtf->read.lenVariantHeader >=
290                 sizeof( mfpdtf->read.pVariantHeader->array ) )
291             {
292                 mfpdtf->read.arrayRecordCount = LEND_GET_SHORT( mfpdtf->read.pVariantHeader->array.recordCount );
293                 mfpdtf->read.arrayRecordSize = LEND_GET_SHORT( mfpdtf->read.pVariantHeader->array.recordSize );
294                 mfpdtf->read.innerBlockBytesRemaining = mfpdtf->read.arrayRecordCount * mfpdtf->read.arrayRecordSize;
295             }
296         }
297     }
298     else if( MfpdtfReadIsImageData( mfpdtf ) )
299     {
300         if( mfpdtf->read.innerBlockBytesRemaining > 0 )
301         {
302             result |= MFPDTF_RESULT_IMAGE_DATA_PENDING;
303         }
304         else if( mfpdtf->read.simulateImageHeaders )
305         {
306             mfpdtf->read.innerBlockBytesRemaining = mfpdtf->read.fixedBlockBytesRemaining;
307             
308             if( mfpdtf->read.innerBlockBytesRemaining > 0 )
309             {
310                 result |= MFPDTF_RESULT_IMAGE_DATA_PENDING;
311             }
312         }
313         else
314         {
315             unsigned char id;
316             datalen = 1;
317             
318             //READ( &id, datalen );
319             
320             int r = MfpdtfReadGeneric( mfpdtf, (unsigned char *)&id, datalen );
321     
322             if( r!= datalen )
323             {
324                 if( r < 0 )
325                     return MFPDTF_RESULT_READ_ERROR;
326                 
327                 return MFPDTF_RESULT_READ_TIMEOUT;
328             
329             }
330
331             if( id == MFPDTF_ID_RASTER_DATA )
332             {
333                 datalen = sizeof( mfpdtf->read.imageRasterDataHeader );
334                 //                DBG( 0, "Reading raster data header.\n" );
335                 
336                 //                DBG( 0, "********************************** RASTER RECORD **********************************.\n" );
337                 int r = MfpdtfReadGeneric( mfpdtf, (unsigned char *)&mfpdtf->read.imageRasterDataHeader, datalen );
338     
339                 if( r!= datalen )
340                 {
341                     if( r < 0 )
342                         return MFPDTF_RESULT_READ_ERROR;
343                     
344                     return MFPDTF_RESULT_READ_TIMEOUT;
345                 
346                 }
347
348                 
349                 mfpdtf->read.innerBlockBytesRemaining = LEND_GET_SHORT( mfpdtf->read.imageRasterDataHeader.byteCount );
350                 result |= MFPDTF_RESULT_IMAGE_DATA_PENDING;
351             }
352             else if( id == MFPDTF_ID_START_PAGE )
353             {
354                 datalen = sizeof( mfpdtf->read.imageStartPageRecord );
355                 //                DBG( 0, "Reading start of page record.\n" );
356                 //                DBG( 0, "********************************** SOP RECORD **********************************.\n" );
357                 int r = MfpdtfReadGeneric( mfpdtf, (unsigned char *)&mfpdtf->read.imageStartPageRecord, datalen );
358     
359                 if( r!= datalen )
360                 {
361                     if( r < 0 )
362                         return MFPDTF_RESULT_READ_ERROR;
363                     
364                     return MFPDTF_RESULT_READ_TIMEOUT;
365                 
366                 }
367                 
368                 result |= MFPDTF_RESULT_NEW_START_OF_PAGE_RECORD;
369             }
370             else if( id == MFPDTF_ID_END_PAGE )
371             {
372                 datalen = sizeof( mfpdtf->read.imageEndPageRecord );
373                 //                DBG( 0, "Reading end of page record.\n" );
374                 //                DBG( 0, "********************************** EOP RECORD **********************************.\n" );
375                 int r = MfpdtfReadGeneric( mfpdtf, (unsigned char *)&mfpdtf->read.imageEndPageRecord, datalen );
376     
377                 if( r!= datalen )
378                 {
379                     if( r < 0 )
380                         return MFPDTF_RESULT_READ_ERROR;
381                     
382                     return MFPDTF_RESULT_READ_TIMEOUT;
383                 
384                 }
385                 
386                 
387                 result |= MFPDTF_RESULT_NEW_END_OF_PAGE_RECORD;
388             }
389             else
390             {
391                 RETURN( MFPDTF_RESULT_OTHER_ERROR );
392             }
393         }
394     }
395     else if( MfpdtfReadIsArrayData( mfpdtf ) )
396     {
397         if( mfpdtf->read.innerBlockBytesRemaining > 0 )
398         {
399             result |= MFPDTF_RESULT_ARRAY_DATA_PENDING;
400         }
401     }
402
403     if( mfpdtf->read.fixedBlockBytesRemaining > 0 )
404     {
405         result |= MFPDTF_RESULT_GENERIC_DATA_PENDING;
406     }
407
408     RETURN( ( result | mfpdtf->read.fixedHeader.pageFlags ) );
409 }
410
411 int __attribute__ ((visibility ("hidden"))) MfpdtfReadGetLastServiceResult( Mfpdtf_t mfpdtf )
412 {
413     return mfpdtf->read.lastServiceResult;
414 }
415
416 int __attribute__ ((visibility ("hidden"))) MfpdtfReadGetVariantHeader( Mfpdtf_t mfpdtf,
417                                 union MfpdtfVariantHeader_u * buffer,
418                                 int maxlen )
419 {
420     if( !mfpdtf->read.pVariantHeader )
421     {
422         return 0;
423     }
424     if( !buffer )
425     {
426         return mfpdtf->read.lenVariantHeader;
427     }
428     if( maxlen > mfpdtf->read.lenVariantHeader )
429     {
430         maxlen = mfpdtf->read.lenVariantHeader;
431     }
432     memcpy( buffer, mfpdtf->read.pVariantHeader, maxlen );
433     return maxlen;
434 }
435
436 int __attribute__ ((visibility ("hidden"))) MfpdtfReadGetStartPageRecord( Mfpdtf_t mfpdtf,
437                                   struct MfpdtfImageStartPageRecord_s * buffer,
438                                   int maxlen )
439 {
440     int len = sizeof( struct MfpdtfImageStartPageRecord_s );
441     if( maxlen > len )
442     {
443         maxlen = len;
444     }
445     memcpy( buffer, &mfpdtf->read.imageStartPageRecord, maxlen );
446     return maxlen;
447 }
448
449 int __attribute__ ((visibility ("hidden"))) MfpdtfReadInnerBlock( Mfpdtf_t mfpdtf,
450                           unsigned char * buffer,
451                           int countdown )
452 {
453     int r, countup = 0;
454
455     while( 1 )
456     {
457         if( countdown > mfpdtf->read.innerBlockBytesRemaining )
458         {
459             countdown = mfpdtf->read.innerBlockBytesRemaining;
460         }
461         
462         if( countdown <= 0 )
463         {
464             break;
465         }
466         
467         r = MfpdtfReadGeneric( mfpdtf, buffer, countdown );
468         
469         if( MfpdtfReadGetLastServiceResult( mfpdtf ) & MFPDTF_RESULT_ERROR_MASK )
470         {
471             break;
472         }
473
474         if( mfpdtf->fdLog >= 0 )
475         {
476             write( mfpdtf->fdLog, buffer, r );  /* log raw rgb data, use imagemagick to display */
477         }
478
479         buffer += r;
480         countdown -= r;
481         countup += r;       
482
483         if( countdown <= 0 )
484         {
485             break;
486         }
487         
488         r = MfpdtfReadService( mfpdtf );
489         
490         if( r & ( MFPDTF_RESULT_ERROR_MASK |
491                   MFPDTF_RESULT_NEW_DATA_TYPE |
492                   MFPDTF_RESULT_NEW_VARIANT_HEADER ) )
493         {
494             break;
495         }
496     }
497
498     return countup;
499 }
500
501 /*
502  * Phase 2 rewrite. des
503  */
504
505 int __attribute__ ((visibility ("hidden"))) read_mfpdtf_block(int device, int channel, char *buf, int bufSize, int timeout)
506 {
507    MFPDTF_FIXED_HEADER *phd = (MFPDTF_FIXED_HEADER *)buf;
508    int size, bsize=0, len;
509
510    /* Read fixed header with timeout in seconds. */
511    size = sizeof(MFPDTF_FIXED_HEADER);
512    if ((len = ReadChannelEx(device, channel, (unsigned char *)buf, size, timeout)) != size)
513       goto bugout;
514
515    bsize = le32toh(phd->BlockLength);
516    if (bsize > bufSize)
517    {
518       bug("invalid bufsize: size=%d max=%d ReadMfpdtfBlock %s %d\n", bsize, bufSize, __FILE__, __LINE__);
519       bsize = -1;
520       goto bugout;
521    }
522
523    size = bsize - sizeof(MFPDTF_FIXED_HEADER);
524    //   if ((len = ReadChannelEx(device, channel, (unsigned char *)buf+sizeof(MFPDTF_FIXED_HEADER), size, 5)) != size)
525    if ((len = ReadChannelEx(device, channel, (unsigned char *)buf+sizeof(MFPDTF_FIXED_HEADER), size, 10)) != size)
526    {
527       bug("invalid read: exp=%d act=%d ReadMfpdtfBlock %s %d\n", size, len, __FILE__, __LINE__);
528       bsize = -1;
529       goto bugout;
530    }
531
532 bugout:
533    return bsize;
534 }
535