1 /*****************************************************************************\
2     services.cpp : HP Inkjet Server
3 
4     Copyright (c) 2001 - 2004, 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 
46 #if defined(HAVE_LIBHPIP) && defined(HAVE_DBUS)
47 #include <dbus/dbus.h>
48 #define DBUS_INTERFACE "com.hplip.StatusService"
49 #define DBUS_PATH "/"
50 static DBusError dbus_err;
51 static DBusConnection *dbus_conn;
52 void InitDbus (void);
53 void SendDbusMessage (const char *dev, const char *printer, int code,
54                       const char *username, const int jobid, const char *title);
55 #else
SendDbusMessage(const char * dev,const char * printer,int code,const char * username,const int jobid,const char * title)56 void SendDbusMessage (const char *dev, const char *printer, int code,
57                       const char *username, const int jobid, const char *title)
58 {
59 }
60 #endif
61 
InitDuplexBuffer()62 int UXServices::InitDuplexBuffer()
63 {
64     /* Free buffer if new page size in middle of print job. */
65     if (RastersOnPage)
66        delete [] RastersOnPage;
67     if (KRastersOnPage)
68        delete [] KRastersOnPage;
69 
70     /* Calculate duplex page buffer */
71     CurrentRaster = ph.height - 1;  /* Height = physical page in pixels */
72     RastersOnPage = (BYTE **) new BYTE[(ph.height) * sizeof (BYTE *)];
73     KRastersOnPage = (BYTE **) new BYTE[(ph.height) * sizeof (BYTE *)];
74     for (int i = 0; i < ph.height; i++)
75     {
76        RastersOnPage[i] = NULL;
77        KRastersOnPage[i] = NULL;
78     }
79     return 0;
80 }
81 
SendBackPage()82 int UXServices::SendBackPage()
83 {
84     DRIVER_ERROR    err;
85     int i = CurrentRaster+1;
86 
87     while (i < ph.height)
88     {
89        if (KRGB)
90        {
91           if ((err = pJob->SendRasters(KRastersOnPage[i], RastersOnPage[i])) != NO_ERROR)
92             return err;
93        }
94        else
95        {
96           if ((err = pJob->SendRasters(RastersOnPage[i])) != NO_ERROR)
97             return err;
98        }
99 
100        if (RastersOnPage[i])
101            delete [] RastersOnPage[i];
102        if (KRastersOnPage[i])
103            delete [] KRastersOnPage[i];
104        i++;
105     }
106 
107     CurrentRaster = ph.height - 1;   /* reset raster index */
108 
109     return 0;
110 }
111 
112 static unsigned char xmask[] =
113 {
114    0x80,    /* x=0 */
115    0x40,    /* 1 */
116    0x20,    /* 2 */
117    0x10,    /* 3 */
118    0x08,    /* 4 */
119    0x04,    /* 5 */
120    0x02,    /* 6 */
121    0x01     /* 7 */
122 };
123 
ProcessRaster(char * raster,char * k_raster)124 int UXServices::ProcessRaster(char *raster, char *k_raster)
125 {
126     if (!((pPC->QueryDuplexMode() == DUPLEXMODE_BOOK) && pPC->RotateImageForBackPage() && BackPage))
127     {
128        if (KRGB)
129           return pJob->SendRasters((unsigned char *)k_raster, (unsigned char *)raster);
130        else
131           return pJob->SendRasters((unsigned char *)raster);
132     }
133     else
134     {
135         if (CurrentRaster < 0)
136            return -1;
137 
138         BYTE   *new_raster;
139         int    new_raster_size;
140         int    i,w;
141 
142         if (raster == NULL)
143         {
144            RastersOnPage[CurrentRaster] = NULL;
145         }
146         else
147         {
148            new_raster_size = pPC->InputPixelsPerRow() * 3;
149            new_raster = new BYTE[new_raster_size];
150            if (new_raster == 0)
151            {
152                BUG("unable to create duplex buffer, size=%d: %m\n", new_raster_size);
153                return -1;
154            }
155            memset(new_raster, 0xFF, new_raster_size);
156            RastersOnPage[CurrentRaster] = new_raster;
157            BYTE *p = new_raster + new_raster_size - 3;
158            for (i = 0; i < new_raster_size; i += 3)
159            {
160                memcpy (p, raster+i, 3);  /* rotate rgb image */
161                p -= 3;
162            }
163         }
164 
165         if (k_raster == NULL)
166         {
167            KRastersOnPage[CurrentRaster] = NULL;
168         }
169         else
170         {
171            new_raster_size = (pPC->InputPixelsPerRow() + 7) >> 3;
172            new_raster = new BYTE[new_raster_size];
173            if (new_raster == 0)
174            {
175                BUG("unable to create black duplex buffer, size=%d: %m\n", new_raster_size);
176                return -1;
177            }
178            memset(new_raster, 0, new_raster_size);
179            KRastersOnPage[CurrentRaster] = new_raster;
180            w = pPC->InputPixelsPerRow();
181            for (i=0; i<w; i++)
182            {
183                if (k_raster[i>>3] & xmask[i&7])
184                   new_raster[(w-i)>>3] |= xmask[(w-i)&7];  /* rotate k image */
185            }
186 	   int    k = ((w + 7) / 8) * 8 - w;
187 	   BYTE   c = 0xff << k;
188 	   if (k != 0)
189 	       new_raster[0] = c & k_raster[new_raster_size-1];
190         }
191 
192         CurrentRaster--;
193 
194         return 0;
195     }
196 }
197 
198 
199 #ifdef HAVE_LIBHPIP
200 
201 /*
202  *  Check models.xml for bi-di flag and also check the
203  *  device id string for integrity. Some devices return
204  *  device id without some expected fields.
205  *
206  */
CanDoBiDi()207 BOOL UXServices::CanDoBiDi ()
208 {
209     char            *hpDev;
210     struct hpmud_model_attributes ma;
211     char            strDevID[512];
212 
213     // Check for CUPS environment
214 
215     if ((hpDev = getenv ("DEVICE_URI")) == NULL)
216     {
217         return FALSE;
218     }
219 
220     // Check for HP Backend
221 
222     if (strncmp (hpDev, "hp:", 3))
223     {
224         return FALSE;
225     }
226 
227     // Check io-mode in models.xml for this device
228 
229     hpmud_query_model(hpDev, &ma);
230 
231     if (ma.prt_mode == HPMUD_UNI_MODE)
232     {
233         return FALSE;
234     }
235     if (hpmud_open_device(hpDev, ma.prt_mode, &hpFD) != HPMUD_R_OK)
236     {
237         return FALSE;
238     }
239     memset (strDevID, 0, 512);
240     if ((ReadDeviceID ((BYTE *) strDevID, 512)) != NO_ERROR)
241     {
242         return FALSE;
243     }
244 
245     // Check if this is a laser device
246     if (strstr (strDevID, "Laser") || strstr (strDevID, "laser"))
247     {
248         return TRUE;
249     }
250 
251     // Check if device id is complete
252     if (!(strstr (strDevID, ";S:")) && !(strstr (strDevID, "VSTATUS")))
253     {
254         return FALSE;
255     }
256     return TRUE;
257 }
258 
259 #else
260 
CanDoBiDi()261 BOOL UXServices::CanDoBiDi ()
262 {
263     return FALSE;
264 }
265 
266 #endif  // HAVE_LIBHPIP
267 
UXServices()268 UXServices::UXServices():SystemServices()
269 {
270    constructor_error = NO_ERROR;
271    hpFD = -1;
272 
273    // instead of InitDeviceComm(), just do...
274    IOMode.bDevID = IOMode.bStatus = FALSE;   /* uni-di support is default */
275 
276 #if 0 // Old code
277 
278    /* Check for CUPS environment and HP backend. */
279    if ((hpDev = getenv("DEVICE_URI")) != NULL)
280    {
281       if (strncmp(hpDev, "hp:", 3) == 0)
282       {
283          hplip_Init();
284          hplip_ModelQuery(hpDev, &ma);      /* check io-mode in models.xml for this device */
285          if (ma.prt_mode != UNI_MODE)
286          {
287             if ((hpFD = hplip_OpenHP(hpDev, &ma)) >= 0)
288             {
289                 InitDeviceComm();            /* lets try bi-di support */
290             }
291             if(IOMode.bDevID == FALSE)
292                BUG("unable to set bi-di for hp backend\n");
293          }
294       }
295    }
296 
297 #endif // Old code
298 
299    if (CanDoBiDi ())
300    {
301        InitDeviceComm ();
302        if (IOMode.bDevID == FALSE)
303        {
304            BUG ("Unable to set bi-di for hp backend\n");
305        }
306    }
307 
308    Quality = QUALITY_NORMAL;
309    MediaType = MEDIA_PLAIN;
310    ColorMode = COLOR;
311    PenSet = DUMMY_PEN;
312 
313    RastersOnPage = 0;
314    KRastersOnPage = 0;
315    pPC = NULL;
316    pJob = NULL;
317    Duplex = 0;
318    Tumble = 0;
319    FullBleed = 0;
320    FirstRaster = 1;
321    MediaPosition = sourceTrayAuto;
322    Model = -1;
323    strcpy(ph.cs, "sRGB");
324    VertAlign = -1;
325    DisplayStatus = NODISPLAYSTATUS;
326    OutputPath = -1;
327    outfp = NULL;
328    m_iLogLevel = 0;
329 
330    m_pbyPclBuffer      = NULL;
331    m_iPclBufferSize    = BUFFER_CHUNK_SIZE;
332    m_iCurPclBufferPos  = 0;
333    m_iPageCount        = 0;
334    m_bSpeedMechEnabled = FALSE;
335 }
336 
~UXServices()337 UXServices::~UXServices()
338 {
339    if (m_bSpeedMechEnabled)
340    {
341        SendLastPage ();
342    }
343 
344    if (RastersOnPage)
345       delete [] RastersOnPage;
346    if (KRastersOnPage)
347       delete [] KRastersOnPage;
348 #ifdef HAVE_LIBHPIP
349    if (hpFD >= 0)
350       hpmud_close_device(hpFD);
351 #endif
352     if (outfp)
353     {
354         fclose (outfp);
355     }
356 }
357 
ToDevice(const BYTE * pBuffer,DWORD * Count)358 DRIVER_ERROR UXServices::ToDevice(const BYTE * pBuffer, DWORD * Count)
359 {
360     if (OutputPath == -1)
361     {
362         return IO_ERROR;
363     }
364 
365    if (m_bSpeedMechEnabled)
366    {
367        if ((CopyData (pBuffer, *Count)) == 0)
368        {
369            *Count = 0;
370 	   return NO_ERROR;
371        }
372    }
373 
374     if (outfp)
375     {
376         fwrite (pBuffer, 1, *Count, outfp);
377 	if (!(m_iLogLevel & SEND_TO_PRINTER))
378 	{
379 	    *Count = 0;
380 	    return NO_ERROR;
381 	}
382     }
383 
384    /* Write must be not-buffered, don't use streams */
385    if (write(OutputPath, pBuffer, *Count) != (ssize_t)*Count)
386    {
387       static int cnt=0;
388       if (cnt++ < 5)
389          BUG("unable to write to output, fd=%d, count=%d: %m\n", OutputPath, *Count);
390       return IO_ERROR;
391    }
392 
393    *Count = 0;
394    return NO_ERROR;
395 }
396 
GetStatusInfo(BYTE * bStatReg)397 BOOL UXServices::GetStatusInfo (BYTE * bStatReg)
398 {
399 #ifdef HAVE_LIBHPIP
400    unsigned int s;
401    if (hpmud_get_device_status(hpFD, &s) == HPMUD_R_OK)
402    {
403       *bStatReg = (BYTE)s;
404       return TRUE;
405    }
406 #endif
407    return FALSE;
408 }
409 
ReadDeviceID(BYTE * strID,int iSize)410 DRIVER_ERROR UXServices::ReadDeviceID (BYTE * strID, int iSize)
411 {
412 #ifdef HAVE_LIBHPIP
413    int len;
414    hpmud_get_device_id(hpFD, (char *)strID, iSize, &len);
415    if (len < 3)
416       return IO_ERROR;
417 #endif
418    return NO_ERROR;
419 }
420 
421 #ifdef HP_PRINTVIEW
422 const char *szPJLHeader = "@PJL SET JOBATTR=\"JobAcct7=HPPrintView.exe\"\012";
GetPJLHeaderBuffer(char ** szPJLBuffer)423 int UXServices::GetPJLHeaderBuffer (char **szPJLBuffer)
424 {
425     *szPJLBuffer = (char *) szPJLHeader;
426     return strlen (szPJLHeader);
427 }
428 #endif // HP_PRINTVIEW
429 
GetVerticalAlignmentValue(BYTE * cVertAlignVal)430 BOOL UXServices::GetVerticalAlignmentValue(BYTE* cVertAlignVal)
431 {
432    if (VertAlign == -1)
433       return FALSE;
434 
435    *cVertAlignVal = (BYTE)VertAlign;
436    return TRUE;
437 }
438 
GetVertAlignFromDevice()439 BOOL UXServices::GetVertAlignFromDevice()
440 {
441 #ifdef HAVE_LIBHPIP
442    if ((VertAlign = ReadHPVertAlign(hpFD)) == -1)
443       return FALSE;
444 #endif
445    return TRUE;
446 }
447 
DisplayPrinterStatus(DISPLAY_STATUS ePrinterStatus)448 void UXServices::DisplayPrinterStatus (DISPLAY_STATUS ePrinterStatus)
449 {
450    DisplayStatus = ePrinterStatus;
451 }
452 
BusyWait(DWORD msec)453 DRIVER_ERROR UXServices::BusyWait (DWORD msec)
454 {
455    switch (DisplayStatus)
456    {
457       case DISPLAY_ERROR_TRAP:
458       case DISPLAY_COMM_PROBLEM:
459       case DISPLAY_PRINTER_NOT_SUPPORTED:
460       case DISPLAY_OUT_OF_PAPER:
461       case DISPLAY_PHOTOTRAY_MISMATCH:
462       case DISPLAY_TOP_COVER_OPEN:
463       case DISPLAY_NO_COLOR_PEN:
464       case DISPLAY_NO_BLACK_PEN:
465       case DISPLAY_NO_PENS:
466          BUG("WARNING: printer bi-di error=%d\n", DisplayStatus);
467          DisplayStatus = DISPLAY_PRINTING_CANCELED;
468          return JOB_CANCELED;   /* bail-out otherwise APDK will wait forever */
469       default:
470          break;
471    }
472    return NO_ERROR;
473 }
474 
GetDriverMessage(DRIVER_ERROR err)475 const char * UXServices::GetDriverMessage (DRIVER_ERROR err)
476 {
477    const char *p=NULL;
478 
479 	/* Map driver error to text message. TODO: text needs to be localized. */
480    switch(err)
481    {
482       case(WARN_MODE_MISMATCH):
483          p = "printmode mismatch with pen, tray, etc.";
484          break;
485       case(WARN_LOW_INK_BOTH_PENS):
486          p = "both pens have low ink";
487          break;
488       case(WARN_LOW_INK_BLACK):
489          p = "black pen has low ink";
490          break;
491       case(WARN_LOW_INK_COLOR):
492          p = "color pen has low ink";
493          break;
494       case(WARN_LOW_INK_PHOTO):
495          p = "photo pen has low ink";
496          break;
497       case(WARN_LOW_INK_GREY):
498          p = "grey pen has low ink";
499          break;
500       case(WARN_LOW_INK_BLACK_PHOTO):
501          p = "black photo has low ink";
502          break;
503       case(WARN_LOW_INK_COLOR_PHOTO):
504          p = "color photo pen has low ink";
505          break;
506       case(WARN_LOW_INK_GREY_PHOTO):
507          p = "grey photo pen has low ink";
508          break;
509       case(WARN_LOW_INK_COLOR_GREY):
510          p = "grey pen has low ink";
511          break;
512       case(WARN_LOW_INK_COLOR_GREY_PHOTO):
513          p = "color grey photo pen has low ink";
514          break;
515       case(WARN_LOW_INK_COLOR_BLACK_PHOTO):
516          p = "color back pen has low ink";
517          break;
518       case(WARN_LOW_INK_CYAN):
519          p = "cyan has low ink";
520          break;
521       case(WARN_LOW_INK_MAGENTA):
522          p = "magenta has low ink";
523          break;
524       case(WARN_LOW_INK_YELLOW):
525          p = "yellow has low ink";
526          break;
527       case(WARN_LOW_INK_MULTIPLE_PENS):
528          p = "more that one ink is low";
529          break;
530       case(WARN_FULL_BLEED_UNSUPPORTED):
531          p = "fullbleed is not supported";
532          break;
533       case(WARN_FULL_BLEED_3SIDES):
534          p = "fullbleed is 3 sides";
535          break;
536       case(WARN_FULL_BLEED_PHOTOPAPER_ONLY):
537          p = "fullbleed photo paper only";
538          break;
539       case(WARN_FULL_BLEED_3SIDES_PHOTOPAPER_ONLY):
540          p = "fullbleed 3 sides photo paper only";
541          break;
542       case(WARN_ILLEGAL_PAPERSIZE):
543          p = "illegal paper size";
544          break;
545       case(WARN_INVALID_MEDIA_SOURCE):
546          p = "invalid media source";
547          break;
548       default:
549          p = "driver error";
550          BUG("driver error=%d\n", err);
551          break;
552    }
553    return p;
554 }
555 
MapPaperSize(float width,float height)556 int UXServices::MapPaperSize (float width, float height)
557 {
558     int    i, r, size;
559     float  dx, dy;
560 
561     /* Map gs paper sizes to APDK paper sizes, or do custom. */
562     size = CUSTOM_SIZE;
563     for (i=0; i<MAX_PAPER_SIZE; i++)
564     {
565         r = pPC->SetPaperSize ((PAPER_SIZE)i);
566 
567         if (r != NO_ERROR)
568             continue;
569 
570         dx = width  > pPC->PhysicalPageSizeX () ? width  - pPC->PhysicalPageSizeX () : pPC->PhysicalPageSizeX () - width;
571         dy = height > pPC->PhysicalPageSizeY () ? height - pPC->PhysicalPageSizeY () : pPC->PhysicalPageSizeY () - height;
572 
573         if ((dx < 0.05) && (dy < 0.05))
574         {
575             size = i;   /* found standard paper size */
576             break;
577         }
578     }
579 
580     if (size == CUSTOM_SIZE)
581         pPC->SetCustomSize (width, height);
582 
583     if ((r = pPC->SetPaperSize ((PAPER_SIZE)size, FullBleed)) != NO_ERROR)
584     {
585         if (r > 0)
586         {
587             BUG("unable to set paper size=%d, err=%d, width=%0.5g, height=%0.5g\n", size, r, width, height);
588         }
589         else
590         {
591             BUG("warning setting paper size=%d, err=%d, width=%0.5g, height=%0.5g\n", size, r, width, height);
592         }
593 /*
594  *      Call failed, reset our PaperWidth and PaperHeight values.
595  *      This ensures that we return correct values when gs queries for printable area.
596  */
597 
598         PaperWidth  = pPC->PhysicalPageSizeX ();
599         PaperHeight = pPC->PhysicalPageSizeY ();
600         return -1;
601     }
602 
603     PaperWidth  = pPC->PhysicalPageSizeX ();
604     PaperHeight = pPC->PhysicalPageSizeY ();
605 
606     return 0;
607 }
608 
ResetIOMode(BOOL bDevID,BOOL bStatus)609 void UXServices::ResetIOMode (BOOL bDevID, BOOL bStatus)
610 {
611     if (pPC)
612     {
613         IOMode.bDevID  = bDevID;
614         IOMode.bStatus = bStatus;
615         pPC->ResetIOMode (bDevID, bStatus);
616     }
617 }
618 
InitSpeedMechBuffer()619 void UXServices::InitSpeedMechBuffer ()
620 {
621     if (m_pbyPclBuffer)
622     {
623         return;
624     }
625     m_pbyPclBuffer = new BYTE[m_iPclBufferSize + 2];
626     if (m_pbyPclBuffer)
627     {
628         iSendBufferSize = 0;
629     }
630 }
631 
SendPreviousPage()632 int UXServices::SendPreviousPage ()
633 {
634     DRIVER_ERROR    err;
635     if (m_bSpeedMechEnabled == FALSE)
636     {
637         return 0;
638     }
639     m_iPageCount++;
640     if (m_iPageCount == 1)
641     {
642         return 0;
643     }
644     m_bSpeedMechEnabled = FALSE;
645     err = ToDevice (m_pbyPclBuffer, (DWORD *) &m_iCurPclBufferPos);
646     if (err != NO_ERROR)
647     {
648         return 1;
649     }
650     m_bSpeedMechEnabled = TRUE;
651     m_iCurPclBufferPos = 0;
652 
653 //  Request the printer to inject speed mech command. Also, let it know this is not the last page
654 
655     pPC->SetPrinterHint (SPEED_MECH_HINT, 0);
656     return 0;
657 }
658 
CopyData(const BYTE * pBuffer,DWORD iCount)659 int UXServices::CopyData (const BYTE *pBuffer, DWORD iCount)
660 {
661     if (m_iCurPclBufferPos + (int) iCount < m_iPclBufferSize)
662     {
663         memcpy (m_pbyPclBuffer + m_iCurPclBufferPos, pBuffer, iCount);
664         m_iCurPclBufferPos += iCount;
665        return 0;
666     }
667     BYTE    *p = new BYTE[m_iPclBufferSize + BUFFER_CHUNK_SIZE + 2];
668     if (p == NULL)
669     {
670         m_bSpeedMechEnabled = FALSE;
671 	return 1;
672     }
673     memcpy (p, m_pbyPclBuffer, m_iCurPclBufferPos);
674     delete [] m_pbyPclBuffer;
675     m_pbyPclBuffer = p;
676     memcpy (m_pbyPclBuffer + m_iCurPclBufferPos, pBuffer, iCount);
677     m_iCurPclBufferPos += iCount;
678     m_iPclBufferSize += BUFFER_CHUNK_SIZE;
679     return 0;
680 }
681 
682 //  Note that this is good only for VIP printers
683 const char *pbySpeedMechCmd = "\x1B*o5W\x0D\x02\x00";
684 
SendLastPage()685 void UXServices::SendLastPage ()
686 {
687     if (m_pbyPclBuffer == NULL)
688     {
689         return;
690     }
691     // Look for speed mech command in the buffer, set the page count and last page flag
692     int    i = 0;
693     BYTE   *p = m_pbyPclBuffer;
694     while (i < m_iPclBufferSize)
695     {
696         if (*p == '\x1B')
697 	{
698 	    if (!(memcmp (p, pbySpeedMechCmd, 8)))
699 	    {
700 	        p += 8;
701 		*p++ = (BYTE) ((m_iPageCount & 0xFF00) >> 8);
702 		*p++ = (BYTE) ((m_iPageCount & 0x00FF));
703 		*(p + 9) = 1;
704 		break;
705 	    }
706 	}
707         i++;
708 	p++;
709     }
710     m_bSpeedMechEnabled = FALSE;
711     ToDevice (m_pbyPclBuffer, (DWORD *) &m_iCurPclBufferPos);
712     delete [] m_pbyPclBuffer;
713 }
714 
715 #if defined(HAVE_LIBHPIP) && defined(HAVE_DBUS)
SendDbusMessage(const char * dev,const char * printer,int code,const char * username,const int jobid,const char * title)716 void SendDbusMessage (const char *dev, const char *printer, int code,
717                       const char *username, const int jobid, const char *title)
718 {
719     DBusMessage * msg = NULL;
720 
721     InitDbus ();
722     if (dbus_conn == NULL)
723         return;
724     msg = dbus_message_new_signal(DBUS_PATH, DBUS_INTERFACE, "Event");
725 
726     if (NULL == msg)
727     {
728         BUG("dbus message is NULL!\n");
729         return;
730     }
731 
732     dbus_message_append_args(msg,
733         DBUS_TYPE_STRING, &dev,
734         DBUS_TYPE_STRING, &printer,
735         DBUS_TYPE_UINT32, &code,
736         DBUS_TYPE_STRING, &username,
737         DBUS_TYPE_UINT32, &jobid,
738         DBUS_TYPE_STRING, &title,
739         DBUS_TYPE_INVALID);
740 
741     if (!dbus_connection_send(dbus_conn, msg, NULL))
742     {
743         BUG("dbus message send failed!\n");
744         return;
745     }
746 
747     dbus_connection_flush(dbus_conn);
748     dbus_message_unref(msg);
749 
750     return;
751 }
752 
InitDbus(void)753 void InitDbus (void)
754 {
755    dbus_error_init (&dbus_err);
756    dbus_conn = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_err);
757 
758    if (dbus_error_is_set (&dbus_err))
759    {
760       BUG ("dBus Connection Error (%s)!\n", dbus_err.message);
761       dbus_error_free (&dbus_err);
762    }
763 
764    return;
765 }
766 #endif  /* HAVE_DBUS */
767 
768 
769