1 /*****************************************************************************\
2 
3   hpiom.c - HP I/O message handler
4 
5   (c) 2003-2004 Copyright HP Development Company, LP
6 
7   Redistribution and use in source and binary forms, with or without
8   modification, are permitted provided that the following conditions
9   are met:
10   1. Redistributions of source code must retain the above copyright
11      notice, this list of conditions and the following disclaimer.
12   2. Redistributions in binary form must reproduce the above copyright
13      notice, this list of conditions and the following disclaimer in the
14      documentation and/or other materials provided with the distribution.
15   3. Neither the name of HP nor the names of its
16      contributors may be used to endorse or promote products derived
17      from this software without specific prior written permission.
18 
19   THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
20   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
22   NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24   TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25   OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 \*****************************************************************************/
31 
32 #ifdef HAVE_LIBHPIP
33 
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <netdb.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <fcntl.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include "hpijs.h"
45 #include "hpiom.h"
46 
47 static const int gnMaxDataSize = 2048;
48 static const int gnMaxCmdOptionSize = 4;
49 
50 static const char gcFrameMarker                    = '$';
51 static const int  gnPadding                        = 255;
52 static const int  gnRequiredSize                   = 11;
53 static const int  gnMinCommandSize                 = 16;
54 static const int  gnMinDecodeSize                  = 10;   // needed six bytes to determine command number,
55                                                     // command length and data length
56 
57 static const int  gUV8FrameOffset                  = 0;
58 static const int  gUV16CommandLengthOffset         = 1;
59 static const int  gUV8UnitNumberOffset             = 3;
60 static const int  gE8PacketTypeOffset              = 4;
61 static const int  gUV8CommandNumberOffset          = 5;
62 static const int  gUV16ReferenceNumberOffset       = 6;
63 static const int  gUV16DataLengthOffset            = 8;
64 static const int  gUV8CommandOptionsOffset         = 10;
65 
66 static const int  gUV8RespFrameOffset              = 0;
67 static const int  gUV16RespCommandLengthOffset     = 1;
68 static const int  gUV8RespUnitNumberOffset         = 3;
69 static const int  gE8RespPacketTypeOffset          = 4;
70 static const int  gUV8RespCommandNumberOffset      = 5;
71 static const int  gUV16RespReferenceNumberOffset   = 6;
72 static const int  gUV16RespDataLengthOffset        = 8;
73 static const int  gE8RespCompleteOffset            = 10;
74 
75 // reserved reference number
76 //
77 static const int gnMinRefNum = 0xF000;
78 static const int gnMaxRefNum = 0xFFFD;
79 
80 unsigned short gwSynchRefNum                  = 0xFFEC;
81 unsigned short gwSynchCompleteRefNum          = 0xFFEB;
82 unsigned short gwResetRefNum                  = 0xFFEA;
83 
84 unsigned short gwPrinterVersionQueryRefNum      = 0xFFD0;
85 unsigned short gwPrinterStatusQueryRefNum       = 0xFFD1;
86 unsigned short gwPrinterAttributesQueryRefNum   = 0xFFD2;
87 unsigned short gwAlignmentQueryRefNum           = 0xFFD3;
88 unsigned short gwDeviceIdQueryRefNum            = 0xFFDD;
89 unsigned short gwHueCompensationQueryRefNum     = 0xFFDE;
90 
91 // command options
92 //
93 // printer query command options
94 //
95 static const int  gnPrinterQueryOptionsSize = 4;
96 
97 static unsigned char gpPrinterVersionQuery[]      = { 0x00, 0x00, 0x00, 0x00 };  //  0 - return UV32 version data
98 //static unsigned char gpPrinterStatusQuery[]       = { 0x01, 0x00, 0x00, 0x00 };  //  1 - return status string
99 //static unsigned char gpPrinterAttributesQuery[]   = { 0x02, 0x00, 0x00, 0x00 };  //  2 - return printer attributes
100 static unsigned char gpAlignmentQuery[]           = { 0x03, 0x00, 0x00, 0x00 };  //  3 - return primitive alignment value
101 //static unsigned char gpDeviceIdQuery[]            = { 0x0D, 0x00, 0x00, 0x00 };  // 13 - return device id
102 //static unsigned char gpHueCompensationQuery[]     = { 0x0E, 0x00, 0x00, 0x00 };  // 14 - return hue compensation
103 static unsigned char gpPenAlignmentQuery[]        = { 0x0F, 0x00, 0x00, 0x00 };  // 15 - return pen alignment value
104 
105 /*
106  * Lidil commands.
107  */
108 
EncodeCommand(unsigned char * lpBuffer,unsigned short wBufferSize,unsigned char unUnitNumber,int ePacketType,int eCommandNumber,char * lpData,unsigned short wDataLength,unsigned char * lpCommandOptions,unsigned short wCommandOptionsSize,int * dPacketSize,unsigned short wRefNum)109 int EncodeCommand
110 (
111    unsigned char *lpBuffer,
112    unsigned short wBufferSize,
113    unsigned char unUnitNumber,
114    int ePacketType,
115    int eCommandNumber,
116    char *lpData,
117    unsigned short wDataLength,
118    unsigned char *lpCommandOptions,
119    unsigned short wCommandOptionsSize,
120    int *dPacketSize,
121    unsigned short wRefNum
122 )
123 {
124    int x;
125    int lNumPaddingNeeded = 0;
126    unsigned char *lpTemp = NULL;
127 
128    memset( lpBuffer, 0, wBufferSize );
129    lpBuffer [ gUV8FrameOffset ]         = gcFrameMarker;
130    lpBuffer [ gUV8UnitNumberOffset ]    = unUnitNumber;
131    lpBuffer [ gE8PacketTypeOffset ]     = ePacketType;
132    lpBuffer [ gUV8CommandNumberOffset ] = eCommandNumber;
133    *(short *)(lpBuffer + gUV16DataLengthOffset) = htons(wDataLength);
134 
135    if ( wCommandOptionsSize > 0 )
136    {
137       if ( lpCommandOptions )
138       {
139          // copy command options to the buffer
140          memcpy(( lpBuffer + gUV8CommandOptionsOffset ), lpCommandOptions, wCommandOptionsSize);
141       }
142       else
143       {
144          // command option is null, fill the buffer with zeros
145          memset(( lpBuffer + gUV8CommandOptionsOffset ), 0, wCommandOptionsSize );
146       }
147    }
148 
149    // calculate command length and padding if needed
150    *dPacketSize = gnRequiredSize + wCommandOptionsSize;
151    lNumPaddingNeeded = gnMinCommandSize - *dPacketSize;
152 
153    if ( lNumPaddingNeeded > 0 )
154    {
155       // move the pointer to the beginning of the padding
156       lpTemp = lpBuffer + gUV8CommandOptionsOffset + wCommandOptionsSize;
157 
158       for (x = 0; x < lNumPaddingNeeded; x++, lpTemp++ )
159       {
160          *lpTemp = gnPadding;
161       }
162 
163       *dPacketSize = gnMinCommandSize;
164    }
165 
166    *(short *)(lpBuffer + gUV16CommandLengthOffset) = htons(*dPacketSize);
167    *(short *)(lpBuffer + gUV16ReferenceNumberOffset) = htons(wRefNum ? wRefNum : 1);
168 
169    // add the trailing frame marker
170    lpBuffer[ *dPacketSize - 1 ] = gcFrameMarker;
171 
172    if ( wDataLength )
173    {
174       if ((*dPacketSize + wDataLength) > wBufferSize)
175       {
176           BUG("unable to fill data buffer EncodeCommand size=%d\n", wDataLength);
177           return 1;
178       }
179 
180       if ( lpData )
181       {
182           // copy the data to the end of the command
183           memcpy( lpBuffer + *dPacketSize, lpData, wDataLength );
184       }
185       else
186       {
187           // NULL data pointer, fill the buffer with zeros
188           memset( lpBuffer + *dPacketSize, 0, wDataLength );
189       }
190 
191       *dPacketSize += wDataLength;
192    }
193 
194    return 0;
195 }
196 
Synch(int hd,int chan)197 int Synch(int hd, int chan)
198 {
199     int bRet = 0;
200     int dPacketSize = 0;
201     unsigned char buf[4096];
202 
203     // create the Synch command, send it to the device,
204     // and retrieve absolute credit data from the device.
205     EncodeCommand(buf, sizeof(buf)
206                      , 0
207                      , eSynch
208                      , eCommandUnknown
209                      , NULL
210                      , gnMaxDataSize
211                      , NULL
212                      , gnMaxCmdOptionSize
213                      , &dPacketSize
214                      , gwSynchRefNum
215                      );
216 
217     hpmud_write_channel(hd, chan, buf, dPacketSize, EXCEPTION_TIMEOUT, &bRet);
218 
219     return( bRet );
220 }
221 
SynchComplete(int hd,int chan)222 int SynchComplete(int hd, int chan)
223 {
224     int bRet = 0;
225     int dPacketSize = 0;
226     unsigned char buf[32];
227 
228         // create the SynchComplete command, send it to the device,
229         // and retrieve absolute credit data from the device.
230         EncodeCommand(buf, sizeof(buf)
231                      , 0
232                      , eSynchComplete
233                      , eCommandUnknown
234                      , NULL
235                      , 0
236                      , NULL
237                      , 0
238                      , &dPacketSize
239                      , gwSynchCompleteRefNum
240                      );
241 
242     hpmud_write_channel(hd, chan, buf, dPacketSize, EXCEPTION_TIMEOUT, &bRet);
243 
244     return( bRet );
245 }
246 
Reset(int hd,int chan)247 int Reset(int hd, int chan)
248 {
249     int bRet = 0;
250     int dPacketSize = 0;
251     unsigned char buf[32];
252 
253         // create the Reset command, send it to the device,
254         // and retrieve absolute credit data from the device.
255         //
256         EncodeCommand(buf, sizeof(buf)
257                      , 0
258                      , eResetLidil
259                      , eCommandUnknown
260                      , NULL
261                      , 0
262                      , NULL
263                      , 0
264                      , &dPacketSize
265                      , gwResetRefNum
266                      );
267 
268     hpmud_write_channel(hd, chan, buf, dPacketSize, EXCEPTION_TIMEOUT, &bRet);
269 
270     return( bRet );
271 }
272 
RetrieveAlignmentValues038(int hd,int chan,LDLGenAlign * pG)273 int RetrieveAlignmentValues038(int hd, int chan, LDLGenAlign *pG)
274 {
275    int n;
276    int dPacketSize = 0;
277    unsigned char buf[256];
278    LDLResponseAlign038 *pA;
279 
280    /* Enable responses. */
281    EncodeCommand(buf, sizeof(buf)
282                      , 0
283                      , eEnableResponses
284                      , eCommandUnknown
285                      , NULL
286                      , 0
287                      , NULL
288                      , 0
289                      , &dPacketSize
290                      , 0
291                      );
292    hpmud_write_channel(hd, chan, buf, dPacketSize, EXCEPTION_TIMEOUT, &n);
293 
294    /* Write alignment query. */
295    EncodeCommand(buf, sizeof(buf)
296                      , 0             // device 0
297                      , eCommand
298                      , eQuery
299                      , NULL
300                      , 0
301                      , gpAlignmentQuery
302                      , gnPrinterQueryOptionsSize
303                      , &dPacketSize
304                      , gwAlignmentQueryRefNum
305                      );
306    hpmud_write_channel(hd, chan, buf, dPacketSize, EXCEPTION_TIMEOUT, &n);
307 
308    /* Disable responses. */
309    EncodeCommand(buf, sizeof(buf)
310                      , 0
311                      , eDiableResponses
312                      , eCommandUnknown
313                      , NULL
314                      , 0
315                      , NULL
316                      , 0
317                      , &dPacketSize
318                      , 0
319                      );
320    hpmud_write_channel(hd, chan, buf, dPacketSize, EXCEPTION_TIMEOUT, &n);
321 
322    /* Read query response. */
323    hpmud_read_channel(hd, chan, buf, sizeof(buf), EXCEPTION_TIMEOUT, &n);
324    pA = (LDLResponseAlign038 *)buf;
325    memset(pG, 0, sizeof(LDLGenAlign));
326    if (pA->h.packet_type == 16)
327    {
328       pG->nPens = 2;
329       /* Except for bi, convert values from relative to black pen to relative to color. */
330       pG->pen[0].color = 0;
331       pG->pen[0].vert = -pA->c[0];
332       pG->pen[0].horz = -pA->c[1];
333       pG->pen[0].bi = pA->k[2];
334       pG->pen[1].color = 1;
335       pG->pen[1].vert = pA->k[0];
336       pG->pen[1].horz = pA->k[1];
337       pG->pen[1].bi = pA->c[2];
338    }
339 
340    return 0;
341 }
342 
RetrieveAlignmentValues043(int hd,int chan,LDLGenAlign * pG)343 int RetrieveAlignmentValues043(int hd, int chan, LDLGenAlign *pG)
344 {
345    int n=0;
346    int dPacketSize = 0;
347    unsigned char buf[256];
348    LDLResponseAlign043 *pA;
349 
350    /* Enable responses. */
351    EncodeCommand(buf, sizeof(buf)
352                      , 0
353                      , eEnableResponses
354                      , eCommandUnknown
355                      , NULL
356                      , 0
357                      , NULL
358                      , 0
359                      , &dPacketSize
360                      , 0
361                      );
362    hpmud_write_channel(hd, chan, buf, dPacketSize, EXCEPTION_TIMEOUT, &n);
363 
364    /* Write alignment query. */
365    EncodeCommand(buf, sizeof(buf)
366                      , 0             // device 0
367                      , eCommand
368                      , eQuery
369                      , NULL
370                      , 0
371                      , gpPenAlignmentQuery
372                      , gnPrinterQueryOptionsSize
373                      , &dPacketSize
374                      , gwAlignmentQueryRefNum
375                      );
376    hpmud_write_channel(hd, chan, buf, dPacketSize, EXCEPTION_TIMEOUT, &n);
377 
378    /* Disable responses. */
379    EncodeCommand(buf, sizeof(buf)
380                      , 0
381                      , eDiableResponses
382                      , eCommandUnknown
383                      , NULL
384                      , 0
385                      , NULL
386                      , 0
387                      , &dPacketSize
388                      , 0
389                      );
390    hpmud_write_channel(hd, chan, buf, dPacketSize, EXCEPTION_TIMEOUT, &n);
391 
392    hpmud_read_channel(hd, chan, buf, sizeof(buf), EXCEPTION_TIMEOUT, &n);
393    pA = (LDLResponseAlign043 *)buf;
394    memset(pG, 0, sizeof(LDLGenAlign));
395    if (pA->h.packet_type == 16)
396    {
397       memcpy(pG, &pA->g, sizeof(LDLGenAlign));
398    }
399 
400    return 0;
401 }
402 
RetrieveVersion(int hd,int chan)403 uint32_t RetrieveVersion(int hd, int chan)
404 {
405    int n, version=0;
406    int dPacketSize = 0;
407    unsigned char buf[256];
408    LDLResponseVersion *pV;
409 
410    /* Enable responses. */
411    EncodeCommand(buf, sizeof(buf)
412                      , 0
413                      , eEnableResponses
414                      , eCommandUnknown
415                      , NULL
416                      , 0
417                      , NULL
418                      , 0
419                      , &dPacketSize
420                      , 0
421                      );
422    hpmud_write_channel(hd, chan, buf, dPacketSize, EXCEPTION_TIMEOUT, &n);
423 
424    /* Write lidil version query. */
425    EncodeCommand(buf, sizeof(buf)
426                      , 0             // device 0
427                      , eCommand
428                      , eQuery
429                      , NULL
430                      , 0
431                      , gpPrinterVersionQuery
432                      , gnPrinterQueryOptionsSize
433                      , &dPacketSize
434                      , gwAlignmentQueryRefNum
435                      );
436    hpmud_write_channel(hd, chan, buf, dPacketSize, EXCEPTION_TIMEOUT, &n);
437 
438    /* Disable responses. */
439    EncodeCommand(buf, sizeof(buf)
440                      , 0
441                      , eDiableResponses
442                      , eCommandUnknown
443                      , NULL
444                      , 0
445                      , NULL
446                      , 0
447                      , &dPacketSize
448                      , 0
449                      );
450    hpmud_write_channel(hd, chan, buf, dPacketSize, EXCEPTION_TIMEOUT, &n);
451 
452    hpmud_read_channel(hd, chan, buf, sizeof(buf), EXCEPTION_TIMEOUT, &n);
453    pV = (LDLResponseVersion *)buf;
454    if (pV->h.packet_type == 16)
455    {
456       version = ntohl(pV->ldlversion);
457       fprintf(stdout, "lidil version = %x\n", version);
458    }
459 
460    return(version);
461 }
462 
463 /*
464  * Return value = (black | photo) to color vertical alignment offset, error = -1.
465  *
466  * All alignment values may be zero if pen(s) were never aligned. Valid values
467  * may range from -30 to +30.
468  */
ReadHPVertAlign(int hd)469 int ReadHPVertAlign(int hd)
470 {
471    int channel, n, i, x2colorVert=-1;
472    uint32_t ver;
473    LDLGenAlign ga;
474 
475    if (hpmud_open_channel(hd, "PRINT", &channel) != HPMUD_R_OK)
476    {
477       BUG("unable to open print channel ReadHPVertAlign\n");
478       goto bugout;
479    }
480 
481    if (Synch(hd, channel)==0)
482    {
483       BUG("unable to write sync ReadHPVertAlign\n");
484       goto bugout;
485    }
486 
487    if (SynchComplete(hd, channel)==0)
488    {
489       BUG("unable to write sync complete ReadHPVertAlign\n");
490       goto bugout;
491    }
492 
493    if (Reset(hd, channel)==0)
494    {
495       BUG("unable to write reset ReadHPVertAlign\n");
496       goto bugout;
497    }
498 
499    if ((ver = RetrieveVersion(hd, channel))==0)
500    {
501       BUG("unable to read version ReadHPVertAlign\n");
502       goto bugout;
503    }
504 
505    if (ver > 0x308)
506       RetrieveAlignmentValues043(hd, channel, &ga);
507    else
508       RetrieveAlignmentValues038(hd, channel, &ga);
509 
510    if (!(n = ga.nPens))
511       goto bugout;
512 
513    for (i=0; i<n; i++)
514    {
515       if (ga.pen[i].color == 0 || ga.pen[i].color == 2)
516       {
517          x2colorVert = ga.pen[i].vert;  /* (black | photo) to color offset */
518          BUG("%s alignment: vert=%d horz=%d bi=%d x2c=%d\n", (ga.pen[i].color==0) ? "black" : "photo", ga.pen[i].vert, ga.pen[i].horz, ga.pen[i].bi, x2colorVert);
519       }
520    }
521 
522    Reset(hd, channel);
523 
524 bugout:
525    if (channel >= 0)
526       hpmud_close_channel(hd, channel);
527 
528    return x2colorVert;
529 }
530 
531 #endif // HAVE_LIBHPIP
532 
533 
534