1 /************************************************************************************\
3 mfpdtf.c - HP Multi-Function Peripheral Data Transfer Format filter.
5 (c) 2001-2005 Copyright Hewlett-Packard Development Company, LP
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:
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
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.
24 Contributing Author(s): David Paschal, Don Welch, David Suffield
26 \************************************************************************************/
32 #define DEBUG_DECLARE_ONLY
33 #include "sanei_debug.h"
35 static union MfpdtfVariantHeader_u * MfpdtfReadAllocateVariantHeader( Mfpdtf_t mfpdtf,
38 if( mfpdtf->read.pVariantHeader )
40 free( mfpdtf->read.pVariantHeader );
41 mfpdtf->read.pVariantHeader = 0;
43 mfpdtf->read.lenVariantHeader = datalen;
46 mfpdtf->read.pVariantHeader = malloc( datalen );
48 return mfpdtf->read.pVariantHeader;
51 static int MfpdtfReadSetTimeout( Mfpdtf_t mfpdtf, int seconds )
53 mfpdtf->read.timeout.tv_sec = seconds;
54 mfpdtf->read.timeout.tv_usec = 0;
59 Mfpdtf_t __attribute__ ((visibility ("hidden"))) MfpdtfAllocate( int deviceid, int channelid )
61 int size = sizeof( struct Mfpdtf_s );
62 Mfpdtf_t mfpdtf = malloc( size );
66 memset( mfpdtf, 0, size );
67 mfpdtf->channelid = channelid;
68 mfpdtf->deviceid = deviceid;
70 MfpdtfReadSetTimeout( mfpdtf, 30 );
71 MfpdtfReadStart( mfpdtf );
77 int __attribute__ ((visibility ("hidden"))) MfpdtfDeallocate( Mfpdtf_t mfpdtf )
83 MfpdtfLogToFile( mfpdtf, 0 );
84 MfpdtfReadAllocateVariantHeader( mfpdtf, 0 );
89 int __attribute__ ((visibility ("hidden"))) MfpdtfSetChannel( Mfpdtf_t mfpdtf, int channelid )
91 mfpdtf->channelid = channelid;
92 /* If necessary, we can query the device ID string using the
93 * channel's device pointer. */
97 int __attribute__ ((visibility ("hidden"))) MfpdtfLogToFile( Mfpdtf_t mfpdtf, char * filename )
99 if( mfpdtf->fdLog != -1 )
101 close( mfpdtf->fdLog );
104 mfpdtf->logOffset = 0;
107 int fd = creat( filename, 0600 );
117 int __attribute__ ((visibility ("hidden"))) MfpdtfReadGetSimulateImageHeaders( Mfpdtf_t mfpdtf )
119 return mfpdtf->read.simulateImageHeaders;
122 int __attribute__ ((visibility ("hidden"))) MfpdtfReadSetSimulateImageHeaders( Mfpdtf_t mfpdtf,
123 int simulateImageHeaders )
125 mfpdtf->read.simulateImageHeaders = simulateImageHeaders;
126 return simulateImageHeaders;
129 int __attribute__ ((visibility ("hidden"))) MfpdtfReadStart( Mfpdtf_t mfpdtf )
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 );
142 static int MfpdtfReadIsImageData( Mfpdtf_t mfpdtf )
144 return ( ( MFPDTF_DT_MASK_IMAGE & ( 1 << mfpdtf->read.dataType ) ) !=
148 static int MfpdtfReadIsArrayData( Mfpdtf_t mfpdtf )
150 return ( !MfpdtfReadIsImageData( mfpdtf ) );
153 #define READ(buffer,datalen) \
155 int r=MfpdtfReadGeneric(mfpdtf, \
156 (unsigned char *)(buffer),datalen); \
158 if (r<0) return MFPDTF_RESULT_READ_ERROR; \
159 return MFPDTF_RESULT_READ_TIMEOUT; \
163 #define RETURN(_result) \
164 return (mfpdtf->read.lastServiceResult=(_result));
166 static int MfpdtfReadGeneric( Mfpdtf_t mfpdtf, unsigned char * buffer, int datalen )
170 /* Don't read past the currently-defined fixed block. */
171 if( datalen > mfpdtf->read.fixedBlockBytesRemaining )
173 datalen = mfpdtf->read.fixedBlockBytesRemaining;
179 r = ReadChannelEx(mfpdtf->deviceid,
187 /* Account for and log what was read. */
188 mfpdtf->read.fixedBlockBytesRemaining -= r;
190 if( !mfpdtf->read.dontDecrementInnerBlock )
192 mfpdtf->read.innerBlockBytesRemaining -= r;
195 mfpdtf->read.dontDecrementInnerBlock = 0;
200 mfpdtf->read.lastServiceResult = r < 0 ?
201 MFPDTF_RESULT_READ_ERROR :
202 MFPDTF_RESULT_READ_TIMEOUT;
209 int __attribute__ ((visibility ("hidden"))) MfpdtfReadService( Mfpdtf_t mfpdtf )
212 int datalen, blockLength, headerLength;
214 if( mfpdtf->read.fixedBlockBytesRemaining <= 0 )
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;
222 //READ( &mfpdtf->read.fixedHeader, datalen );
224 int r = MfpdtfReadGeneric( mfpdtf, (unsigned char *)&mfpdtf->read.fixedHeader, datalen );
229 return MFPDTF_RESULT_READ_ERROR;
231 return MFPDTF_RESULT_READ_TIMEOUT;
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 );
239 /* Scan data type? */
240 if(mfpdtf->read.fixedHeader.dataType != DT_SCAN)
242 bug("invalid mfpdtf fixed header datatype=%d\n", mfpdtf->read.fixedHeader.dataType);
243 return MFPDTF_RESULT_READ_ERROR;
246 /* Is this a new data type? */
247 if( mfpdtf->read.dataType != mfpdtf->read.fixedHeader.dataType )
249 mfpdtf->read.dataType = mfpdtf->read.fixedHeader.dataType;
250 result |= MFPDTF_RESULT_NEW_DATA_TYPE;
253 DBG(6, "fixed header page_flags=%x: %s %d\n", mfpdtf->read.fixedHeader.pageFlags, __FILE__, __LINE__);
255 /* Read variant header (if any). */
256 datalen = headerLength - sizeof( mfpdtf->read.fixedHeader );
260 DBG(6, "reading variant header size=%d: %s %d\n", datalen, __FILE__, __LINE__);
262 if( !MfpdtfReadAllocateVariantHeader( mfpdtf, datalen ) )
264 RETURN( MFPDTF_RESULT_OTHER_ERROR );
266 mfpdtf->read.dontDecrementInnerBlock = 1;
268 int r = MfpdtfReadGeneric( mfpdtf, (unsigned char *)mfpdtf->read.pVariantHeader, datalen );
273 return MFPDTF_RESULT_READ_ERROR;
275 return MFPDTF_RESULT_READ_TIMEOUT;
279 // DBG( 0, "********************************** VARIANT HEADER **********************************.\n" );
281 result |= MFPDTF_RESULT_NEW_VARIANT_HEADER;
283 /* Is this a valid array variant header? */
284 mfpdtf->read.arrayRecordSize = 0;
285 mfpdtf->read.arrayRecordCount = 0;
286 mfpdtf->read.innerBlockBytesRemaining = 0;
288 if( MfpdtfReadIsArrayData( mfpdtf ) &&
289 mfpdtf->read.lenVariantHeader >=
290 sizeof( mfpdtf->read.pVariantHeader->array ) )
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;
298 else if( MfpdtfReadIsImageData( mfpdtf ) )
300 if( mfpdtf->read.innerBlockBytesRemaining > 0 )
302 result |= MFPDTF_RESULT_IMAGE_DATA_PENDING;
304 else if( mfpdtf->read.simulateImageHeaders )
306 mfpdtf->read.innerBlockBytesRemaining = mfpdtf->read.fixedBlockBytesRemaining;
308 if( mfpdtf->read.innerBlockBytesRemaining > 0 )
310 result |= MFPDTF_RESULT_IMAGE_DATA_PENDING;
318 //READ( &id, datalen );
320 int r = MfpdtfReadGeneric( mfpdtf, (unsigned char *)&id, datalen );
325 return MFPDTF_RESULT_READ_ERROR;
327 return MFPDTF_RESULT_READ_TIMEOUT;
331 if( id == MFPDTF_ID_RASTER_DATA )
333 datalen = sizeof( mfpdtf->read.imageRasterDataHeader );
334 // DBG( 0, "Reading raster data header.\n" );
336 // DBG( 0, "********************************** RASTER RECORD **********************************.\n" );
337 int r = MfpdtfReadGeneric( mfpdtf, (unsigned char *)&mfpdtf->read.imageRasterDataHeader, datalen );
342 return MFPDTF_RESULT_READ_ERROR;
344 return MFPDTF_RESULT_READ_TIMEOUT;
349 mfpdtf->read.innerBlockBytesRemaining = LEND_GET_SHORT( mfpdtf->read.imageRasterDataHeader.byteCount );
350 result |= MFPDTF_RESULT_IMAGE_DATA_PENDING;
352 else if( id == MFPDTF_ID_START_PAGE )
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 );
362 return MFPDTF_RESULT_READ_ERROR;
364 return MFPDTF_RESULT_READ_TIMEOUT;
368 result |= MFPDTF_RESULT_NEW_START_OF_PAGE_RECORD;
370 else if( id == MFPDTF_ID_END_PAGE )
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 );
380 return MFPDTF_RESULT_READ_ERROR;
382 return MFPDTF_RESULT_READ_TIMEOUT;
387 result |= MFPDTF_RESULT_NEW_END_OF_PAGE_RECORD;
391 RETURN( MFPDTF_RESULT_OTHER_ERROR );
395 else if( MfpdtfReadIsArrayData( mfpdtf ) )
397 if( mfpdtf->read.innerBlockBytesRemaining > 0 )
399 result |= MFPDTF_RESULT_ARRAY_DATA_PENDING;
403 if( mfpdtf->read.fixedBlockBytesRemaining > 0 )
405 result |= MFPDTF_RESULT_GENERIC_DATA_PENDING;
408 RETURN( ( result | mfpdtf->read.fixedHeader.pageFlags ) );
411 int __attribute__ ((visibility ("hidden"))) MfpdtfReadGetLastServiceResult( Mfpdtf_t mfpdtf )
413 return mfpdtf->read.lastServiceResult;
416 int __attribute__ ((visibility ("hidden"))) MfpdtfReadGetVariantHeader( Mfpdtf_t mfpdtf,
417 union MfpdtfVariantHeader_u * buffer,
420 if( !mfpdtf->read.pVariantHeader )
426 return mfpdtf->read.lenVariantHeader;
428 if( maxlen > mfpdtf->read.lenVariantHeader )
430 maxlen = mfpdtf->read.lenVariantHeader;
432 memcpy( buffer, mfpdtf->read.pVariantHeader, maxlen );
436 int __attribute__ ((visibility ("hidden"))) MfpdtfReadGetStartPageRecord( Mfpdtf_t mfpdtf,
437 struct MfpdtfImageStartPageRecord_s * buffer,
440 int len = sizeof( struct MfpdtfImageStartPageRecord_s );
445 memcpy( buffer, &mfpdtf->read.imageStartPageRecord, maxlen );
449 int __attribute__ ((visibility ("hidden"))) MfpdtfReadInnerBlock( Mfpdtf_t mfpdtf,
450 unsigned char * buffer,
457 if( countdown > mfpdtf->read.innerBlockBytesRemaining )
459 countdown = mfpdtf->read.innerBlockBytesRemaining;
467 r = MfpdtfReadGeneric( mfpdtf, buffer, countdown );
469 if( MfpdtfReadGetLastServiceResult( mfpdtf ) & MFPDTF_RESULT_ERROR_MASK )
474 if( mfpdtf->fdLog >= 0 )
476 write( mfpdtf->fdLog, buffer, r ); /* log raw rgb data, use imagemagick to display */
488 r = MfpdtfReadService( mfpdtf );
490 if( r & ( MFPDTF_RESULT_ERROR_MASK |
491 MFPDTF_RESULT_NEW_DATA_TYPE |
492 MFPDTF_RESULT_NEW_VARIANT_HEADER ) )
502 * Phase 2 rewrite. des
505 int __attribute__ ((visibility ("hidden"))) read_mfpdtf_block(int device, int channel, char *buf, int bufSize, int timeout)
507 MFPDTF_FIXED_HEADER *phd = (MFPDTF_FIXED_HEADER *)buf;
508 int size, bsize=0, len;
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)
515 bsize = le32toh(phd->BlockLength);
518 bug("invalid bufsize: size=%d max=%d ReadMfpdtfBlock %s %d\n", bsize, bufSize, __FILE__, __LINE__);
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)
527 bug("invalid read: exp=%d act=%d ReadMfpdtfBlock %s %d\n", size, len, __FILE__, __LINE__);