1 /*****************************************************************************\
2 hpijs.cpp : HP Inkjet Server
3
4 Copyright (c) 2001 - 2008, HP Co.
5 All rights reserved.
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 the 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
20 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 NOT LIMITED TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
28 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
30 \*****************************************************************************/
31
32 #include <sys/stat.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <syslog.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 #include "header.h"
41 #include "ijs.h"
42 #include "ijs_server.h"
43 #include "hpijs.h"
44 #include "services.h"
45 #include "utils.h"
46
47 extern void SendDbusMessage (const char *dev, const char *printer, int code,
48 const char *username, const int jobid, const char *title);
49
50 #ifdef HAVE_LIBHPIP
51 extern int hpijsFaxServer (int argc, char **argv);
52 #endif
53
54 #if 0
55 int bug(const char *fmt, ...)
56 {
57 char buf[256];
58 va_list args;
59 int n;
60
61 va_start(args, fmt);
62
63 if ((n = vsnprintf(buf, 256, fmt, args)) == -1)
64 buf[255] = 0; /* output was truncated */
65
66 fprintf(stderr, buf);
67 syslog(LOG_WARNING, buf);
68
69 fflush(stderr);
70 va_end(args);
71 return n;
72 }
73 #endif
74
setLogLevel(UXServices * pSS,char * user_name)75 void setLogLevel(UXServices *pSS, char*user_name)
76 {
77 FILE *fp;
78 char str[258];
79 char *p;
80 fp = fopen ("/usr/local/etc/cups/cupsd.conf", "r");
81 if (fp == NULL)
82 return;
83 while (!feof (fp))
84 {
85 if (!fgets (str, 256, fp))
86 {
87 break;
88 }
89 if ((p = strstr (str, "hpLogLevel")))
90 {
91 p += strlen ("hpLogLevel") + 1;
92 pSS->m_iLogLevel = atoi (p);
93 break;
94 }
95 }
96 fclose (fp);
97
98 if (pSS->m_iLogLevel & SAVE_PCL_FILE)
99 {
100 char szFileName[MAX_FILE_PATH_LEN];
101 snprintf (szFileName,sizeof(szFileName), "%s/hp_%s_ijs_%d_XXXXXX", CUPS_TMP_DIR, user_name, getpid());
102 createTempFile(szFileName, &pSS->outfp);
103
104 // pSS->outfp = fopen (szFileName, "w");
105 if (pSS->outfp)
106 {
107 chmod (szFileName, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
108 }
109 }
110 }
111
112 /* Set Print Context. */
hpijs_set_context(UXServices * pSS)113 int hpijs_set_context(UXServices *pSS)
114 {
115 int r;
116
117 if (pSS->PenSet != DUMMY_PEN)
118 {
119 if ((r = pSS->pPC->SetPenSet((PEN_TYPE)pSS->PenSet)) != NO_ERROR)
120 BUG("unable to SetPenSet set=%d, err=%d\n", pSS->PenSet, r);
121 }
122
123 if ((r = pSS->pPC->SelectPrintMode((QUALITY_MODE)pSS->Quality, (MEDIATYPE)pSS->MediaType, (COLORMODE)pSS->ColorMode)) != NO_ERROR)
124 {
125 BOOL bDevText;
126 BUG("unable to set Quality=%d, ColorMode=%d, MediaType=%d, err=%d\n", pSS->Quality, pSS->ColorMode, pSS->MediaType, r);
127 pSS->pPC->GetPrintModeSettings((QUALITY_MODE &)pSS->Quality, (MEDIATYPE &)pSS->MediaType, (COLORMODE &)pSS->ColorMode, bDevText);
128 BUG("following will be used Quality=%d, ColorMode=%d, MediaType=%d\n", pSS->Quality, pSS->ColorMode, pSS->MediaType);
129 }
130
131 /* Map ghostscript paper size to APDK paper size. */
132 pSS->MapPaperSize(pSS->PaperWidth, pSS->PaperHeight);
133
134 /* Do duplex stuff now, since we have a valid print mode. */
135 if (pSS->Duplex && !pSS->Tumble)
136 {
137 if (pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_BOOK) != TRUE)
138 BUG("unable to set duplex mode=book\n");
139 }
140 else if (pSS->Duplex && pSS->Tumble)
141 {
142 if (pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_TABLET) != TRUE)
143 BUG("unable to set duplex mode=tablet\n");
144 }
145 else
146 {
147 pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_NONE);
148 }
149
150 if (pSS->MediaPosition != sourceTrayAuto)
151 {
152 if (pSS->pPC->SetMediaSource((MediaSource)pSS->MediaPosition) != NO_ERROR)
153 BUG("unable to set MediaPosition=%d\n", pSS->MediaPosition);
154 }
155
156 return 0;
157 }
158
hpijs_status_cb(void * status_cb_data,IjsServerCtx * ctx,IjsJobId job_id)159 int hpijs_status_cb(void *status_cb_data, IjsServerCtx *ctx, IjsJobId job_id)
160 {
161 return 0;
162 }
163
hpijs_list_cb(void * list_cb_data,IjsServerCtx * ctx,IjsJobId job_id,char * val_buf,int val_size)164 int hpijs_list_cb(void *list_cb_data, IjsServerCtx *ctx, IjsJobId job_id,
165 char *val_buf, int val_size)
166 {
167 return snprintf(val_buf, val_size, "OutputFD,DeviceManufacturer,DeviceModel,PageImageFormat,Dpi,Width,Height,BitsPerSample,ColorSpace,PaperSize,PrintableArea,PrintableTopLeft,DryTime,PS:Duplex,PS:Tumble,Quality:Quality,Quality:MediaType,Quality:ColorMode,Quality:PenSet,Quality:FullBleed,PS:MediaPosition");
168 }
169
hpijs_enum_cb(void * enum_cb_data,IjsServerCtx * ctx,IjsJobId job_id,const char * key,char * val_buf,int val_size)170 int hpijs_enum_cb(void *enum_cb_data, IjsServerCtx *ctx, IjsJobId job_id,
171 const char *key, char *val_buf, int val_size)
172 {
173 UXServices *pSS = (UXServices*)enum_cb_data;
174
175 if (!strcmp (key, "ColorSpace"))
176 {
177 if (pSS->pPC->SupportSeparateBlack())
178 return snprintf(val_buf, val_size, "sRGB,KRGB");
179 else
180 return snprintf(val_buf, val_size, "sRGB");
181 }
182 else if (!strcmp (key, "DeviceManufacturer"))
183 return snprintf(val_buf, val_size, "HEWLETT-PACKARD,APOLLO,HP");
184 else if (!strcmp (key, "PageImageFormat"))
185 return snprintf(val_buf, val_size, "Raster");
186 else if (!strcmp (key, "BitsPerSample"))
187 return snprintf(val_buf, val_size, "8");
188 else if (!strcmp (key, "PS:Duplex"))
189 {
190 if (pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_BOOK) == TRUE)
191 return snprintf(val_buf, val_size, "true");
192 else
193 return snprintf(val_buf, val_size, "false");
194 pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_NONE);
195 }
196 else if (!strcmp (key, "PS:Tumble"))
197 {
198 if (pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_TABLET) == TRUE)
199 return snprintf(val_buf, val_size, "true");
200 else
201 return snprintf(val_buf, val_size, "false");
202 pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_NONE);
203 }
204 else
205 BUG("unable to enum key=%s\n", key);
206 return IJS_ERANGE;
207 }
208
209 /*
210 * Set parameter (in the server) call back. Note, OutputFD is the only call that can be
211 * preceded by set DeviceManufacturer and DeviceModel.
212 */
hpijs_set_cb(void * set_cb_data,IjsServerCtx * ctx,IjsJobId job_id,const char * key,const char * value,int value_size)213 int hpijs_set_cb (void *set_cb_data, IjsServerCtx *ctx, IjsJobId job_id,
214 const char *key, const char *value, int value_size)
215 {
216 UXServices *pSS = (UXServices*)set_cb_data;
217 int fd, r;
218 char *tail;
219 int status = 0;
220 char svalue[IJS_MAX_PARAM+1];
221 float w, h, dx, dy;
222 int iVal;
223
224 /* Sanity check input value. */
225 if (value_size > IJS_MAX_PARAM)
226 {
227 memcpy(svalue, value, IJS_MAX_PARAM);
228 svalue[IJS_MAX_PARAM] = 0;
229 }
230 else
231 {
232 memcpy(svalue, value, value_size);
233 svalue[value_size] = 0;
234 }
235
236 if (!strcmp (key, "OutputFD"))
237 {
238 fd = strtol(svalue, &tail, 10);
239 pSS->OutputPath = fd; /* set prn_stream as output of SS::ToDevice */
240 }
241 else if (!strcmp (key, "DeviceManufacturer"))
242 {
243 if ((strncasecmp(svalue, "HEWLETT-PACKARD", 15) != 0) &&
244 (strncasecmp(svalue, "APOLLO", 6) != 0) && (strncasecmp(svalue, "HP", 2) != 0))
245 {
246 BUG("unable to set DeviceManufacturer=%s\n", svalue);
247 status = -1;
248 }
249 }
250 else if (!strcmp (key, "DeviceModel"))
251 {
252 if ((r = pSS->pPC->SelectDevice(svalue)) != NO_ERROR)
253 {
254 if (r == PLUGIN_LIBRARY_MISSING)
255 {
256 // call dbus here
257 const char *user_name = " ";
258 const char *title = " ";
259 const char *device_uri = getenv ("DEVICE_URI");
260 const char *printer = getenv ("PRINTER");
261 int job_id = 0;
262
263 if (device_uri == NULL)
264 device_uri = "";
265 if (printer == NULL)
266 printer = "";
267
268 SendDbusMessage (device_uri, printer,
269 EVENT_PRINT_FAILED_MISSING_PLUGIN,
270 user_name, job_id, title);
271 BUG("unable to set device=%s, err=%d\n", svalue, r);
272 status = -1;
273 }
274 else
275 {
276 /* OfficeJet LX is not very unique, do separate check here. */
277 if (!strncmp(svalue,"OfficeJet", 10))
278 r = pSS->pPC->SelectDevice("DESKJET 540");
279 }
280 }
281
282 if (r == NO_ERROR)
283 {
284 pSS->Model = 1;
285
286 /* Got a valid device class, let's set some print mode defaults. */
287 BOOL bDevText;
288 pSS->pPC->GetPrintModeSettings((QUALITY_MODE &)pSS->Quality, (MEDIATYPE &)pSS->MediaType, (COLORMODE &)pSS->ColorMode, bDevText);
289 }
290 else
291 {
292 BUG("unable to set device=%s, err=%d\n", svalue, r);
293 status = -1;
294 }
295 }
296 else if ((strcmp (key, "PS:Duplex") == 0) || (strcmp (key, "Duplex") == 0))
297 {
298 if (strncmp(svalue, "true", 4) == 0)
299 pSS->Duplex = 1;
300 else
301 pSS->Duplex = 0;
302 }
303 else if ((strcmp (key, "PS:Tumble") == 0) || (strcmp (key, "Tumble") == 0))
304 {
305 if (strncmp(svalue, "true", 4) == 0)
306 pSS->Tumble = 1;
307 else
308 pSS->Tumble = 0;
309 }
310 else if (!strcmp (key, "PaperSize"))
311 {
312 w = (float)strtod(svalue, &tail);
313 h = (float)strtod(tail+1, &tail);
314
315 if (pSS->FirstRaster)
316 {
317 /* Normal start of print Job. */
318 pSS->PaperWidth = w;
319 pSS->PaperHeight = h;
320 hpijs_set_context(pSS);
321 }
322 else
323 {
324
325 dx = w > pSS->PaperWidth ? w - pSS->PaperWidth : pSS->PaperWidth - w;
326 dy = h > pSS->PaperHeight ? h - pSS->PaperHeight : pSS->PaperHeight - h;
327
328 /* Middle of print Job, ignore paper size if same. */
329 if ((dx > 0.25) || (dy > 0.25))
330 {
331 pSS->FirstRaster = 1; /* force new Job */
332 pSS->PaperWidth = w; /* set new paper size */
333 pSS->PaperHeight = h;
334 hpijs_set_context(pSS);
335 }
336 }
337 }
338 else if (!strcmp (key, "TopLeft"))
339 {
340 /* not currently used */
341 }
342 else if (!strcmp (key, "Quality:Quality"))
343 {
344 pSS->Quality = (QUALITY_MODE) strtol(svalue, &tail, 10);
345 }
346 else if (!strcmp (key, "Quality:MediaType"))
347 {
348 pSS->MediaType = (MEDIATYPE) strtol(svalue, &tail, 10);
349 }
350 else if (!strcmp (key, "Quality:ColorMode"))
351 {
352 pSS->ColorMode = (COLORMODE) strtol(svalue, &tail, 10);
353 }
354 else if (!strcmp (key, "Quality:PenSet"))
355 {
356 pSS->PenSet = (PEN_TYPE) strtol(svalue, &tail, 10);
357 }
358 else if (!strcmp (key, "Quality:FullBleed"))
359 {
360 pSS->FullBleed = strtol(svalue, &tail, 10);
361 }
362 else if (!strcmp (key, "PS:MediaPosition"))
363 {
364 pSS->MediaPosition = strtol(svalue, &tail, 10);
365 }
366 else if (!strcmp (key, "DryTime"))
367 {
368 iVal = strtol (svalue, &tail, 10);
369 pSS->pPC->SetPrinterHint (EXTRA_DRYTIME_HINT, iVal);
370 }
371 else if (!strcmp (key, "RedEye"))
372 {
373 iVal = strtol (svalue, &tail, 10);
374 pSS->pPC->SetPrinterHint (RED_EYE_REMOVAL_HINT, iVal);
375 }
376 else if (!strcmp (key, "PhotoFix"))
377 {
378 iVal = strtol (svalue, &tail, 10);
379 pSS->pPC->SetPrinterHint (PHOTO_FIX_HINT, iVal);
380 }
381 else if (!strcmp (key, "MaxJpegFileSize"))
382 {
383 iVal = strtol (svalue, &tail, 10);
384 pSS->pPC->SetPrinterHint (MAX_FILE_SIZE_HINT, iVal);
385 }
386 else if (!strcmp (key, "Quality:SpeedMech") && !pSS->Duplex)
387 {
388 pSS->pPC->SetPrinterHint (PAGES_IN_DOC_HINT, 512);
389 pSS->EnableSpeedMech (TRUE);
390 }
391 else if (!strcmp (key, "Quality:MediaSubtype"))
392 {
393 iVal = strtol (svalue, &tail, 10);
394 pSS->pPC->SetMediaSubtype (iVal);
395 }
396 // The next 5 values are passed in as inch * 1000
397 else if (!strcmp (key, "Margin:TopPadding"))
398 {
399 iVal = strtol (svalue, &tail, 10);
400 pSS->pPC->SetMechOffset (iVal);
401 }
402 else if (!strcmp (key, "Overspray:Left"))
403 {
404 iVal = strtol (svalue, &tail, 10);
405 pSS->pPC->SetPrinterHint (LEFT_OVERSPRAY_HINT, iVal);
406 }
407 else if (!strcmp (key, "Overspray:Top"))
408 {
409 iVal = strtol (svalue, &tail, 10);
410 pSS->pPC->SetPrinterHint (TOP_OVERSPRAY_HINT, iVal);
411 }
412 else if (!strcmp (key, "Overspray:Right"))
413 {
414 iVal = strtol (svalue, &tail, 10);
415 pSS->pPC->SetPrinterHint (RIGHT_OVERSPRAY_HINT, iVal);
416 }
417 else if (!strcmp (key, "Overspray:Bottom"))
418 {
419 iVal = strtol (svalue, &tail, 10);
420 pSS->pPC->SetPrinterHint (BOTTOM_OVERSPRAY_HINT, iVal);
421 }
422 else
423 BUG("unable to set key=%s, value=%s\n", key, svalue);
424
425 return status;
426 }
427
428 /* Get parameter (from the server) call back. Note, all calls must be preceded by set DeviceName. */
hpijs_get_cb(void * get_cb_data,IjsServerCtx * ctx,IjsJobId job_id,const char * key,char * value_buf,int value_size)429 int hpijs_get_cb(void *get_cb_data, IjsServerCtx *ctx, IjsJobId job_id, const char *key, char *value_buf, int value_size)
430 {
431 UXServices *pSS = (UXServices*)get_cb_data;
432 float fX;
433 float fY;
434
435 if (!strcmp (key, "PrintableArea"))
436 {
437 fY = pSS->pPC->PrintableHeight ();
438 /* If duplexing, adjust printable height to 1/2 inch top/bottom margins, except laserjets. */
439 if ((pSS->pPC->QueryDuplexMode() != DUPLEXMODE_NONE) && pSS->pPC->RotateImageForBackPage() && (FALSE == pSS->pPC->IsBorderless()))
440 {
441 // User has requested fullbleed printing and printer supports 4-sided fullbleed or
442 // top and bottom margin are equal (0.125"), then
443 // don't need top and bottom margins to be 0.5" each. In other words, if physical page size -
444 // printable height is more than 0.25 inches, adjustment is required for symmetry.
445 // Update - 11/22/05: Not so, the autoduplexer still requires a half inch margin.
446 #if 0
447 if ((pSS->pPC->PrintableHeight () + 0.28) < pSS->pPC->PhysicalPageSizeY ())
448 {
449 fY = pSS->pPC->PhysicalPageSizeY () - 1.0;
450 }
451 #endif
452 fY = pSS->pPC->PhysicalPageSizeY () - 1.0;
453
454 // SuperB size paper requires larger margins
455 if (pSS->pPC->PhysicalPageSizeY () > 18.0)
456 {
457 fY = 1.5;
458 }
459
460 }
461
462 /*
463 * Fullbleed printing is requested and printer supports it, then
464 * return the unadjusted physical width and height.
465 */
466
467 if ((fX = pSS->pPC->PrintableWidth ()) > pSS->PaperWidth)
468 {
469 fX = pSS->PaperWidth;
470 fY = pSS->PaperHeight;
471 }
472
473 return (snprintf (value_buf, value_size, "%.4fx%.4f", fX, fY));
474 }
475 else if (!strcmp (key, "PrintableTopLeft"))
476 {
477 fY = pSS->pPC->PrintableStartY ();
478 /* If duplexing, adjust printable top to 1/2 inch top margin, except laserjets. */
479 if ((pSS->pPC->QueryDuplexMode() != DUPLEXMODE_NONE) && pSS->pPC->RotateImageForBackPage() && (FALSE == pSS->pPC->IsBorderless()))
480 {
481 #if 0
482 if ((pSS->pPC->PrintableHeight () + 0.28) < pSS->pPC->PhysicalPageSizeY ())
483 {
484 fY = 0.5;
485 }
486 #endif
487 fY = 0.5;
488 // SuperB size paper requires larger margins
489 if (pSS->pPC->PhysicalPageSizeY () > 18.0)
490 {
491 fY = 0.75;
492 }
493
494 }
495
496 return snprintf (value_buf, value_size, "%.4fx%.4f", pSS->pPC->PrintableStartX (), fY);
497 }
498 else if ((!strcmp (key, "Duplex")) || (!strcmp (key, "PS:Duplex")))
499 {
500 if (pSS->pPC->QueryDuplexMode() == DUPLEXMODE_NONE)
501 return snprintf(value_buf, value_size, "false");
502 else
503 return snprintf(value_buf, value_size, "true");
504 }
505 else if ((!strcmp (key, "Tumble")) || (!strcmp (key, "PS:Tumble")))
506 {
507 if (pSS->pPC->QueryDuplexMode() == DUPLEXMODE_TABLET)
508 return snprintf(value_buf, value_size, "true");
509 else
510 return snprintf(value_buf, value_size, "false");
511 }
512 else if (!strcmp (key, "PaperSize"))
513 {
514 return snprintf(value_buf, value_size, "%.4fx%.4f", pSS->pPC->PhysicalPageSizeX(), pSS->pPC->PhysicalPageSizeY());
515 }
516 else if (!strcmp (key, "Dpi"))
517 {
518 return snprintf(value_buf, value_size, "%dx%d", pSS->pPC->EffectiveResolutionX(), pSS->pPC->EffectiveResolutionY());
519 }
520 else if (!strcmp (key, "DeviceModel"))
521 {
522 return snprintf(value_buf, value_size, "%s", pSS->pPC->PrinterModel());
523 }
524 else if (!strcmp (key, "Quality:Quality"))
525 {
526 return snprintf(value_buf, value_size, "%d", pSS->Quality);
527 }
528 else if (!strcmp (key, "Quality:ColorMode"))
529 {
530 return snprintf(value_buf, value_size, "%d", pSS->ColorMode);
531 }
532 else if (!strcmp (key, "Quality:MediaType"))
533 {
534 return snprintf(value_buf, value_size, "%d", pSS->MediaType);
535 }
536 else if (!strcmp (key, "ColorSpace"))
537 {
538 return snprintf(value_buf, value_size, "%s", pSS->ph.cs);
539 }
540 else if (!strcmp (key, "PageImageFormat"))
541 {
542 return snprintf(value_buf, value_size, "Raster");
543 }
544 else if (!strcmp (key, "BitsPerSample"))
545 {
546 return snprintf(value_buf, value_size, "8");
547 }
548 else if (!strcmp (key, "PS:MediaPosition"))
549 {
550 return snprintf(value_buf, value_size, "%d", pSS->MediaPosition);
551 }
552 else
553 BUG("unable to get key=%s\n", key);
554
555 return IJS_EUNKPARAM;
556 }
557
558 /* Get raster from the client. */
hpijs_get_client_raster(IjsServerCtx * ctx,char * buf,int size,char white)559 int hpijs_get_client_raster(IjsServerCtx *ctx, char *buf, int size, char white)
560 {
561 int status, clean=1, i;
562
563 status = ijs_server_get_data(ctx, (char *)buf, size);
564
565 if (status < 0)
566 return status; /* error */
567
568 /* Check for blank raster. */
569 for (i = 0; i < size; i++)
570 {
571 if (buf[i] != white)
572 {
573 clean = 0;
574 break;
575 }
576 }
577
578 if (clean)
579 return 0;
580
581 return size;
582 }
583
main(int argc,char * argv[],char * evenp[])584 int main (int argc, char *argv[], char *evenp[])
585 {
586 UXServices *pSS = NULL;
587 IjsServerCtx *ctx = NULL;
588 char *raster = NULL, *k_raster = NULL;
589 int status = EXIT_FAILURE;
590 int ret, n, i, kn=0, width, k_width;
591 char user_name[32]={0,};
592
593 openlog("hpijs", LOG_PID, LOG_DAEMON);
594
595 if (argc > 1)
596 {
597 const char *arg = argv[1];
598 if ((arg[0] == '-') && (arg[1] == 'h'))
599 {
600 fprintf(stdout, "\nHP Co. Inkjet Server %s\n", VERSION);
601 fprintf(stdout, "Copyright (c) 2001-2004, HP Co.\n");
602 exit(0);
603 }
604 }
605
606 if (argc > 2)
607 strncpy(user_name, argv[2], sizeof(user_name));
608
609 #ifdef HAVE_LIBHPIP
610 char *pDev;
611 if ((pDev = getenv ("DEVICE_URI")) &&
612 ((strncmp (pDev, "hpfax:", 6)) == 0))
613 {
614 exit ( hpijsFaxServer (argc, argv));
615 }
616 #endif
617
618 ctx = ijs_server_init();
619 if (ctx == NULL)
620 {
621 BUG("unable to init hpijs server\n");
622 goto BUGOUT;
623 }
624
625 pSS = new UXServices();
626 if (pSS->constructor_error != NO_ERROR)
627 {
628 BUG("unable to open Services object err=%d\n", pSS->constructor_error);
629 goto BUGOUT;
630 }
631
632 setLogLevel(pSS, user_name);
633
634 #ifdef CAPTURE
635 char szCapOutFile[MAX_FILE_PATH_LEN];
636 snprintf(szCapOutFile, sizeof(szCapOutFile),"%s/hp_%s_ijs_capout_XXXXXX",CUPS_TMP_DIR, user_name);
637 if ((pSS->InitScript(szCapOutFile, TRUE)) != NO_ERROR)
638 BUG("unable to init capture");
639 #endif
640
641
642 pSS->pPC = new PrintContext (pSS, 0, 0);
643
644 /* Ignore JOB_CANCELED. This a bi-di hack that allows the job to continue even if bi-di communication failed. */
645 if (pSS->pPC->constructor_error > 0 && pSS->DisplayStatus != DISPLAY_PRINTING_CANCELED)
646 {
647 BUG("unable to open PrintContext object err=%d\n", pSS->pPC->constructor_error);
648 goto BUGOUT;
649 }
650
651 /*
652 * Ignore the WARN_MODE_MISMATCH warning. This will happen if we are talking to a monochrome printer.
653 * We will select the correct printmode later.
654 */
655
656 if (pSS->pPC->constructor_error < 0 &&
657 pSS->pPC->constructor_error != WARN_MODE_MISMATCH)
658 {
659 BUG ("WARNING: %s\n", pSS->GetDriverMessage (pSS->pPC->constructor_error));
660 switch (pSS->pPC->constructor_error)
661 {
662 case WARN_LOW_INK_BOTH_PENS:
663 case WARN_LOW_INK_BLACK:
664 case WARN_LOW_INK_COLOR:
665 case WARN_LOW_INK_PHOTO:
666 case WARN_LOW_INK_GREY:
667 case WARN_LOW_INK_BLACK_PHOTO:
668 case WARN_LOW_INK_COLOR_PHOTO:
669 case WARN_LOW_INK_GREY_PHOTO:
670 case WARN_LOW_INK_COLOR_GREY:
671 case WARN_LOW_INK_COLOR_GREY_PHOTO:
672 case WARN_LOW_INK_COLOR_BLACK_PHOTO:
673 case WARN_LOW_INK_CYAN:
674 case WARN_LOW_INK_MAGENTA:
675 case WARN_LOW_INK_YELLOW:
676 case WARN_LOW_INK_MULTIPLE_PENS:
677 {
678 fputs("STATE: +marker-supply-low-warning\n", stderr);
679 break;
680 }
681 default:
682 fputs("STATE: +marker-supply-low-warning\n", stderr);
683 }
684 }
685
686 #if 0
687 BUG("device model=%s\n", pSS->pPC->PrinterModel());
688 BUG("device class=%s\n", pSS->pPC->PrintertypeToString(pSS->pPC->SelectedDevice()));
689 BUG("default pen=%d\n", pSS->pPC->GetDefaultPenSet());
690 BUG("installed pen=%d\n", pSS->pPC->GetInstalledPens());
691 #endif
692
693 ijs_server_install_status_cb (ctx, hpijs_status_cb, pSS);
694 ijs_server_install_list_cb (ctx, hpijs_list_cb, pSS);
695 ijs_server_install_enum_cb (ctx, hpijs_enum_cb, pSS);
696 ijs_server_install_set_cb (ctx, hpijs_set_cb, pSS);
697 ijs_server_install_get_cb (ctx, hpijs_get_cb, pSS);
698
699 while (1)
700 {
701 if ((ret = ijs_server_get_page_header(ctx, &pSS->ph)) < 0)
702 {
703 BUG("unable to read client data err=%d\n", ret);
704 goto BUGOUT;
705 }
706
707 if (pSS->Model == -1)
708 goto BUGOUT; /* no device selected */
709
710 if (ret)
711 {
712 status = 0; /* normal exit */
713 break;
714 }
715
716 if (pSS->FirstRaster)
717 {
718 char *pEnv = getenv ("COPY_COUNT");
719 if (pEnv)
720 {
721 i = atoi (pEnv);
722 pSS->pPC->SetCopyCount (i);
723 }
724
725 pSS->FirstRaster = 0;
726
727 width = (int)(pSS->ph.xres * pSS->pPC->PrintableWidth() + 0.5);
728
729 /* Desensitize input width, may be off by one due to paper size conversions. */
730 if (pSS->ph.width < width)
731 width = pSS->ph.width;
732
733 if ((ret = pSS->pPC->SetPixelsPerRow(width, width)) != NO_ERROR)
734 {
735 BUG("unable to SetPixelsPerRow width=%d, err=%d\n", pSS->ph.width, ret);
736 }
737
738 /* Turn off any bi-di support. Allow bi-di for printer capabilities only. */
739 // pSS->IOMode.bDevID = pSS->IOMode.bStatus = FALSE;
740 pSS->ResetIOMode (FALSE, FALSE);
741
742 // Turn off SpeedMech in duplex printing mode
743 if (pSS->Duplex)
744 {
745 pSS->EnableSpeedMech (FALSE);
746 }
747
748 if (pSS->IsSpeedMechEnabled ())
749 {
750 pSS->InitSpeedMechBuffer ();
751 }
752
753 if (pSS->pJob != NULL)
754 delete pSS->pJob;
755 pSS->pJob = new Job(pSS->pPC);
756 if (pSS->pJob->constructor_error != NO_ERROR)
757 {
758 BUG("unable to create Job object err=%d\n", pSS->pJob->constructor_error);
759 goto BUGOUT;
760 }
761
762 if (pSS->pPC->QueryDuplexMode() != DUPLEXMODE_NONE)
763 {
764 if ((pSS->pPC->QueryDuplexMode() == DUPLEXMODE_BOOK) && pSS->pPC->RotateImageForBackPage())
765 pSS->InitDuplexBuffer();
766 pSS->BackPage = FALSE;
767 }
768
769 pSS->KRGB=0;
770 if (strcmp(pSS->ph.cs, "KRGB") == 0)
771 pSS->KRGB=1;
772
773 #if 0
774 BUG("papersize=%d\n", pSS->pPC->GetPaperSize());
775 BUG("width=%d, height=%d\n", pSS->ph.width, pSS->ph.height);
776 BUG("EffResX=%d, EffResY=%d, InPixelsPerRow=%d, OutPixelsPerRow=%d\n",
777 pSS->pPC->EffectiveResolutionX(), pSS->pPC->EffectiveResolutionY(),
778 pSS->pPC->InputPixelsPerRow(), pSS->pPC->OutputPixelsPerRow());
779 BUG("device=%s\n", pSS->pPC->PrinterModel());
780 #endif
781 } // pSS->FirstRaster
782
783 if ((raster = (char *)malloc(pSS->ph.width*3)) == NULL)
784 {
785 BUG("unable to allocate raster buffer size=%d: %m\n", pSS->ph.width*3);
786 goto BUGOUT;
787 }
788
789 k_width = (pSS->ph.width + 7) >> 3; /* width of k plane in bytes, byte aligned */
790
791 if ((k_raster = (char *)malloc(k_width)) == NULL)
792 {
793 BUG("unable to allocate black raster buffer size=%d: %m\n", k_width);
794 goto BUGOUT;
795 }
796 memset(k_raster, 0, k_width);
797
798 pSS->SendPreviousPage ();
799 for (i=0; i < pSS->ph.height; i++)
800 {
801 if ((n = hpijs_get_client_raster(ctx, raster, pSS->ph.width*3, 0xff)) < 0)
802 break; /* error */
803 if (pSS->KRGB)
804 {
805 if ((kn = hpijs_get_client_raster(ctx, k_raster, k_width, 0)) < 0)
806 break; /* error */
807 }
808 if (n == 0 && kn == 0)
809 pSS->ProcessRaster((char *)0, (char *)0); /* blank raster */
810 else if (kn == 0)
811 pSS->ProcessRaster(raster, (char *)0);
812 else if (n == 0)
813 pSS->ProcessRaster((char *)0, k_raster);
814 else
815 pSS->ProcessRaster(raster, k_raster);
816 }
817
818 free(raster);
819 raster = NULL;
820 free(k_raster);
821 k_raster = NULL;
822
823 if (pSS->pPC->QueryDuplexMode() != DUPLEXMODE_NONE)
824 {
825 if ((pSS->pPC->QueryDuplexMode() == DUPLEXMODE_BOOK) && pSS->pPC->RotateImageForBackPage() && pSS->BackPage)
826 {
827 pSS->SendBackPage();
828 }
829 pSS->BackPage = (BOOL)((int)pSS->BackPage + 1) % 2;
830 }
831
832 pSS->pJob->NewPage();
833
834
835 } /* end while (1) */
836
837 if (pSS->pPC->QueryDuplexMode() != DUPLEXMODE_NONE)
838 {
839 if (pSS->BackPage)
840 {
841 /* Send extra blank line & newpage to eject the page. (for VIP printers). */
842 /* For malibu send enough blank lines to cause at least two blank rasters in Job::sendrasters(). 5/1/03, des */
843 // for (int i = 0; i < 201; i++)
844 for (int i = 0; i < 401; i++)
845 pSS->pJob->SendRasters((unsigned char *)0);
846 pSS->pJob->NewPage();
847 }
848 }
849
850 BUGOUT:
851 if (pSS != NULL)
852 {
853 if (pSS->pJob != NULL)
854 delete pSS->pJob;
855 if (pSS->pPC != NULL)
856 delete pSS->pPC;
857 #ifdef CAPTURE
858 pSS->EndScript();
859 #endif
860 delete pSS;
861 }
862 if (raster != NULL)
863 free(raster);
864 if (k_raster != NULL)
865 free(k_raster);
866 if (ctx != NULL)
867 ijs_server_done(ctx);
868
869 exit(status);
870 }
871
872