Tizen 2.1 base
[platform/upstream/hplip.git] / prnt / hpijs / hpiom.c
1 /*****************************************************************************\
2
3   hpiom.c - HP I/O message handler
4  
5   (c) 2003-2004 Copyright Hewlett-Packard 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 Hewlett-Packard 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
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
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
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
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
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
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
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  */
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