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