1 /*****************************************************************************\
2 dj9xx.cpp : Implimentation for the DJ9xx class
4 Copyright (c) 1996 - 2001, Hewlett-Packard Co.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
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.
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 \*****************************************************************************/
38 #include "resources.h"
39 #include "printerproxy.h"
42 extern BYTE* GetHT3x3_4();
43 extern BYTE* GetHT6x6_4_970();
48 extern uint32_t ulMapDJ970_KCMY[ 9 * 9 * 9 ];
49 extern uint32_t ulMapDJ970_KCMY_3x3x2[ 9 * 9 * 9 ];
50 extern uint32_t ulMapDJ970_Gossimer_Normal_KCMY[ 9 * 9 * 9 ];
51 extern uint32_t ulMapDJ600_CCM_K[ 9 * 9 * 9 ];
52 extern uint32_t ulMapGRAY_K_6x6x1[9 * 9 * 9];
53 extern uint32_t ulMapDJ970_Draft_KCMY[9 * 9 * 9];
55 extern void AsciiHexToBinary(BYTE* dest, char* src, int count);
57 DJ9xx::DJ9xx(SystemServices* pSS, BOOL proto)
58 : Printer(pSS,NUM_DJ6XX_FONTS,proto)
62 bCheckForCancelButton = TRUE;
63 constructor_error = VerifyPenInfo();
66 else ePen=BOTH_PENS; // matches default mode
69 pMode[DEFAULTMODE_INDEX] = new DJ970Mode1(); // Normal Color
70 pMode[SPECIALMODE_INDEX] = new DJ970Mode2(); // Photo
72 #ifdef APDK_AUTODUPLEX
74 * When bidi is available, query printer for duplexer
75 * For now, this is available only on Linux which is unidi only.
78 bDuplexCapable = TRUE;
81 #ifdef APDK_EXTENDED_MEDIASIZE
82 pMode[GRAYMODE_INDEX] = new DJ970Mode3 (); // Draft Grayscale K
83 pMode[SPECIALMODE_INDEX+1] = new DJ970Mode4 (); // Normal Grayscale K
84 pMode[SPECIALMODE_INDEX+2] = new DJ970Mode5 (); // Draft Color
85 pMode[SPECIALMODE_INDEX+3] = new DJ970ModePres(); // Best Color
86 pMode[SPECIALMODE_INDEX+4] = new DJ970ModePhotoPres(); // HiRes
89 pMode[GRAYMODE_INDEX] = new GrayMode (ulMapDJ600_CCM_K);
93 CMYMap = ulMapDJ970_KCMY;
99 DJ970Mode1::DJ970Mode1() // Normal Color
100 : PrintMode(ulMapDJ970_KCMY_3x3x2)
105 ColorDepth[K]=1; // 600x600x1 K
107 for (int i=1; i < 4; i++)
108 ColorDepth[i]=2; // 300x300x2 CMY
110 ResolutionX[K]=ResolutionY[K]=600;
113 #ifdef APDK_AUTODUPLEX
114 bDuplexCapable = TRUE;
117 ColorFEDTable = (BYTE*) HT300x3004level970_open;
120 DJ970Mode2::DJ970Mode2() // Photo
121 : PrintMode(ulMapDJ970_Gossimer_Normal_KCMY)
126 ColorDepth[K]=1; // 600x600x1 K
128 for (i=1; i < 4; i++)
129 ColorDepth[i]=2; // 300x300x2 CMY
131 for (i=0; i < 4; i++)
132 ResolutionX[i]=ResolutionY[i]=600;
134 BaseResX = BaseResY = 600;
137 medium = mediaGlossy;
139 ColorFEDTable = GetHT6x6_4_970();
141 // strcpy(ModeName, "Photo");
143 #ifdef APDK_AUTODUPLEX
144 bDuplexCapable = FALSE;
147 pmQuality = QUALITY_BEST;
148 pmMediaType = MEDIA_PHOTO;
151 #ifdef APDK_EXTENDED_MEDIASIZE
152 DJ970Mode3::DJ970Mode3 () : GrayMode (ulMapDJ600_CCM_K) // Draft Grayscale K
154 #ifdef APDK_AUTODUPLEX
155 bDuplexCapable = TRUE;
157 pmQuality = QUALITY_DRAFT;
158 theQuality = qualityDraft;
161 DJ970Mode4::DJ970Mode4 () : PrintMode (ulMapGRAY_K_6x6x1) // Normal Grayscale K
163 bFontCapable = FALSE;
164 #ifdef APDK_AUTODUPLEX
165 bDuplexCapable = TRUE;
168 ResolutionY[0] = 600;
171 CompatiblePens[1] = BLACK_PEN;
172 pmQuality = QUALITY_NORMAL;
173 theQuality = qualityNormal;
178 DJ970Mode5::DJ970Mode5() // Draft Color
179 : PrintMode(ulMapDJ970_Draft_KCMY)
183 #ifdef APDK_AUTODUPLEX
184 bDuplexCapable = TRUE;
186 pmQuality = QUALITY_DRAFT;
187 theQuality = qualityDraft;
190 // 2001.06.14 mrb: Added Presentation Mode: 600x600x2 for color,
192 DJ970ModePres::DJ970ModePres() : PrintMode(ulMapDJ970_KCMY)
202 ResolutionX[K]=ResolutionY[K]=600;
203 ResolutionX[C]=ResolutionY[C]=600;
204 ResolutionX[M]=ResolutionY[M]=600;
205 ResolutionX[Y]=ResolutionY[Y]=600;
207 BaseResX = BaseResY = 600;
208 theQuality = qualityPresentation;
210 // 2001.07.09 mrb: Added for presentation mode of DJ970
211 ColorFEDTable = (BYTE*) HT600x600x4_Pres970_open;
213 #ifdef APDK_AUTODUPLEX
214 bDuplexCapable = TRUE;
216 pmQuality = QUALITY_BEST;
219 // 2001.06.14 mrb: Added Presentation Photo Mode: 1200x1200x1 for color.
220 DJ970ModePhotoPres::DJ970ModePhotoPres()
221 : PrintMode(ulMapDJ970_Gossimer_Normal_KCMY)
229 ResolutionX[K]=ResolutionY[K]=1200;
230 ResolutionX[C]=ResolutionY[C]=1200;
231 ResolutionX[M]=ResolutionY[M]=1200;
232 ResolutionX[Y]=ResolutionY[Y]=1200;
234 BaseResX = BaseResY = 1200;
236 medium = mediaGlossy;
237 theQuality = qualityPresentation;
239 // 2001.07.09 mrb: Added for presentation mode of DJ970
240 ColorFEDTable = (BYTE*) HT1200x1200x1_PhotoPres970_open;
243 pmQuality = QUALITY_HIGHRES_PHOTO;
244 pmMediaType = MEDIA_PHOTO;
246 #endif // APDK_EXTENDED_MEDIASIZE
248 BOOL DJ9xx::UseGUIMode(PrintMode* pPrintMode)
251 if ((!pPrintMode->bFontCapable)
252 #ifdef APDK_AUTODUPLEX
253 || pPrintMode->QueryDuplexMode ()
260 Compressor* DJ9xx::CreateCompressor(unsigned int RasterSize)
262 return new Mode2(pSS,RasterSize);
265 Header900::Header900(Printer* p,PrintContext* pc)
269 Header* DJ9xx::SelectHeader(PrintContext* pc)
271 return new Header900(this,pc);
274 DRIVER_ERROR Header900::Send()
277 //BOOL bDuplex = FALSE;
281 // this code will look for the duplexer enabled in the device ID and send the right
282 // escape to the printer to enable duplexing. At this time, however, we are not
283 // going to support duplexing. One, it is not supported with PCL3, which we need
284 // for device font support. Second, we don't have the resources to reformat the page
285 // for book duplexing and can only do tablet.
287 /*BYTE bDevIDBuff[DevIDBuffSize];
288 err = theTranslator->pSS->GetDeviceID(bDevIDBuff, DevIDBuffSize, TRUE);
291 // look for duplex code in bDevIDBuff
292 Duplex = DuplexEnabled(bDevIDBuff);
296 err = thePrinter->Send((const BYTE*)EnableDuplex,sizeof(EnableDuplex));
300 #ifdef APDK_AUTODUPLEX
301 if (thePrintContext->QueryDuplexMode () != DUPLEXMODE_NONE)
302 err = thePrinter->Send ((const BYTE *) EnableDuplex, sizeof (EnableDuplex));
305 err = ConfigureRasterData();
308 err=Graphics(); // start raster graphics and set compression mode
313 BOOL Header900::DuplexEnabled(BYTE* bDevIDBuff)
315 char* pStrVstatus = NULL;
316 char* pStrDuplex = NULL;
317 char* pStrSemicolon = NULL;
319 if((pStrVstatus = strstr((char*)bDevIDBuff + 2,"VSTATUS:")))
324 pStrDuplex = pStrVstatus;
325 pStrSemicolon = pStrVstatus;
327 // now parse VSTATUS parameters to find if we are in simplex or duplex
328 if (!(pStrSemicolon = strstr((char*)pStrVstatus,";")))
331 if ( (pStrDuplex = strstr((char*)pStrVstatus,"DP")) )
332 if(pStrDuplex < pStrSemicolon)
334 if ( (pStrDuplex = strstr((char*)pStrVstatus,"SM")) )
335 if(pStrDuplex < pStrSemicolon)
338 DBG1("didn't find SM or DP!!\n");
343 BYTE DJ9xx::PhotoTrayStatus
349 char* pStrVstatus = NULL;
350 char* pStrPhotoTray = NULL;
351 char* pStrSemicolon = NULL;
353 BYTE bDevIDBuff[DevIDBuffSize];
357 bQueryPrinter = FALSE;
360 err=pSS->GetDeviceID(bDevIDBuff, DevIDBuffSize, bQueryPrinter);
366 if((pStrVstatus = strstr((char*)bDevIDBuff + 2,"VSTATUS:")))
375 pStrPhotoTray = pStrVstatus;
376 pStrSemicolon = pStrVstatus;
378 // now parse VSTATUS parameters to find if we are in simplex or duplex
379 if (!(pStrSemicolon = strstr((char*)pStrVstatus,";")))
384 if ( (pStrPhotoTray = strstr((char*)pStrVstatus,"PH")) )
386 if(pStrPhotoTray < pStrSemicolon)
388 return '9'; // return same as VIP installed and engaged status
391 if ( (pStrPhotoTray = strstr((char*)pStrVstatus,"NR")) )
393 if(pStrPhotoTray < pStrSemicolon)
399 DBG1("didn't find PH or NR!!\n");
403 BOOL DJ9xx::PhotoTrayPresent
408 // present (and not engaged) == 8
409 return ((PhotoTrayStatus(bQueryPrinter) & 8) == 8);
410 } //PhotoTrayInstalled
413 PHOTOTRAY_STATE DJ9xx::PhotoTrayEngaged
418 // present and engaged == 9
419 return ((PHOTOTRAY_STATE) ((PhotoTrayStatus(bQueryPrinter) & 9) == 9));
423 PAPER_SIZE DJ9xx::MandatoryPaperSize()
425 if (PhotoTrayEngaged (TRUE))
431 return UNSUPPORTED_SIZE; // code for "nothing mandatory"
433 } //MandatoryPaperSize
436 DISPLAY_STATUS DJ9xx::ParseError(BYTE status_reg)
438 DBG1("DJ9XX, parsing error info\n");
440 DRIVER_ERROR err = NO_ERROR;
441 BYTE DevIDBuffer[DevIDBuffSize];
446 // If a bi-di cable was plugged in and everything was OK, let's see if it's still
447 // plugged in and everything is OK
448 err = pSS->GetDeviceID (DevIDBuffer, DevIDBuffSize, TRUE);
451 // job was bi-di but now something's messed up, probably cable unplugged
452 return DISPLAY_COMM_PROBLEM;
455 if ( (pStr=(char *)strstr((const char*)DevIDBuffer+2,"VSTATUS:")) == NULL )
457 return DISPLAY_COMM_PROBLEM;
460 pStr+=8; // skip "VSTATUS:"
462 // Paper Jam or Paper Stall
463 if (strstr((char*)pStr,"PAJM") || strstr((char*)pStr,"PAPS"))
465 return DISPLAY_PAPER_JAMMED;
469 if (strstr((char*)pStr,"CARS"))
471 return DISPLAY_ERROR_TRAP;
474 if (strstr((char*)pStr,"OOPA")) // OOP state
476 DBG1("Out of Paper [from Encoded DevID]\n");
477 return DISPLAY_OUT_OF_PAPER;
480 // Job Cancelled (AIO printer turn idle after job canceled)
481 if (strstr((char*)pStr,"CNCL")) // CNCL state
483 DBG1("Printing Canceled [from Encoded DevID]\n");
484 return DISPLAY_PRINTING_CANCELED;
487 if ( TopCoverOpen(status_reg) )
489 DBG1("Top Cover Open\n");
490 return DISPLAY_TOP_COVER_OPEN;
493 // VerifyPenInfo will handle prompting the user
494 // if this is a problem
495 err = VerifyPenInfo();
498 // VerifyPenInfo returned an error, which can only happen when ToDevice
499 // or GetDeviceID returns an error. Either way, it's BAD_DEVICE_ID or
500 // IO_ERROR, both unrecoverable. This is probably due to the printer
501 // being turned off during printing, resulting in us not being able to
502 // power it back on in VerifyPenInfo, since the buffer still has a
503 // partial raster in it and we can't send the power-on command.
504 return DISPLAY_COMM_PROBLEM;
507 // check for errors we can detect from the status reg
510 if ( DEVICE_IS_OOP(status_reg) )
512 DBG1("Out Of Paper\n");
513 return DISPLAY_OUT_OF_PAPER;
516 if (DEVICE_PAPER_JAMMED(status_reg))
518 DBG1("Paper Jammed\n");
519 return DISPLAY_PAPER_JAMMED;
521 if (DEVICE_IO_TRAP(status_reg))
524 return DISPLAY_ERROR_TRAP;
528 // don't know what the problem is-
529 // Is the PrinterAlive?
530 if (pSS->PrinterIsAlive())
532 iTotal_SLOW_POLL_Count += iMax_SLOW_POLL_Count;
533 #if defined(DEBUG) && (DBG_MASK & DBG_LVL1)
534 printf("iTotal_SLOW_POLL_Count = %d\n",iTotal_SLOW_POLL_Count);
536 // -Note that iTotal_SLOW_POLL_Count is a multiple of
537 // iMax_SLOW_POLL_Count allowing us to check this
538 // on an absolute time limit - not relative to the number
539 // of times we happen to have entered ParseError.
540 // -Also note that we have different thresholds for uni-di & bi-di.
542 ((IOMode.bDevID == FALSE) && (iTotal_SLOW_POLL_Count >= 60)) ||
543 ((IOMode.bDevID == TRUE) && (iTotal_SLOW_POLL_Count >= 120))
546 else return DISPLAY_PRINTING;
549 return DISPLAY_COMM_PROBLEM;
552 DRIVER_ERROR DJ9xx::VerifyPenInfo()
555 DRIVER_ERROR err=NO_ERROR;
557 if(IOMode.bDevID == FALSE)
560 err = ParsePenInfo(ePen);
562 if(err == UNSUPPORTED_PEN) // probably Power Off - pens couldn't be read
564 DBG1("DJ9xx::Need to do a POWER ON to get penIDs\n");
566 // have to delay for DJ9xx or the POWER ON will be ignored
567 if (pSS->BusyWait((DWORD)2000) == JOB_CANCELED)
570 DWORD length=sizeof(DJ895_Power_On);
571 err = pSS->ToDevice(DJ895_Power_On,&length);
574 err = pSS->FlushIO();
577 // give the printer some time to power up
578 if (pSS->BusyWait ((DWORD) 2500) == JOB_CANCELED)
581 err = ParsePenInfo(ePen);
586 // check for the normal case
587 if (ePen == BOTH_PENS)
590 while ( ePen != BOTH_PENS )
596 // black pen installed, need to install color pen
597 pSS->DisplayPrinterStatus(DISPLAY_NO_COLOR_PEN);
600 // color pen installed, need to install black pen
601 pSS->DisplayPrinterStatus(DISPLAY_NO_BLACK_PEN);
604 // neither pen installed
606 pSS->DisplayPrinterStatus(DISPLAY_NO_PENS);
610 if (pSS->BusyWait(500) == JOB_CANCELED)
613 err = ParsePenInfo(ePen);
617 pSS->DisplayPrinterStatus(DISPLAY_PRINTING);
623 DRIVER_ERROR DJ9xx::ParsePenInfo(PEN_TYPE& ePen, BOOL QueryPrinter)
626 DRIVER_ERROR err = SetPenInfo (str, QueryPrinter);
631 // DeskJet 9300 has DJ990 style devid string.
633 PEN_TYPE temp_pen1 = NO_PEN;
635 int iNumMissingPens = 0;
637 // the first byte indicates how many pens are supported
638 if ((str[0] >= '0') && (str[0] <= '9'))
640 num_pens = str[0] - '0';
642 else if ((str[0] >= 'A') && (str[0] <= 'F'))
644 num_pens = 10 + (str[0] - 'A');
648 return BAD_DEVICE_ID;
651 if ((int) strlen (str) < (num_pens * 8))
653 return BAD_DEVICE_ID;
658 if (pSS->GetVIPVersion () == 1)
662 return UNSUPPORTED_PEN;
665 // parse pen1 (should be black)
666 AsciiHexToBinary(penInfoBits, str+1, 4);
667 penInfoBits[1] &= 0xf8; // mask off ink level trigger bits
669 if ((penInfoBits[0] == 0xc1) && (penInfoBits[1] == 0x10))
671 temp_pen1 = BLACK_PEN;
673 else if (penInfoBits[0] == 0xc0)
680 return UNSUPPORTED_PEN;
683 // now check pen2 (should be color)
684 AsciiHexToBinary(penInfoBits, str+9, 4);
685 penInfoBits[1] &= 0xf8; // mask off ink level trigger bits
687 if ((penInfoBits[0] == 0xc2) && (penInfoBits[1] == 0x08))
689 if (temp_pen1 == BLACK_PEN)
698 else if (penInfoBits[0] == 0xc0)
705 return UNSUPPORTED_PEN;
711 // Check for missing pens
713 if (*(str - 1) == '1' && *(str - 2) == '1')
715 return UNSUPPORTED_PEN;
723 for (int i = 0; i < num_pens; i++, p += 8)
725 AsciiHexToBinary (penInfoBits, p, 8);
727 if ((penInfoBits[1] & 0xf8) == 0xf8)
730 // The high 5 bits in the 3rd and 4th nibble (second byte) identify the
731 // installed pen. If all 5 bits are on, user has installed an incompatible pen.
733 return UNSUPPORTED_PEN;
736 if ((penInfoBits[0] & 0x80) != 0x80) // if Bit 31 is 0, this is not a pen
740 penColor = penInfoBits[0] & 0x3F;
753 if (ePen == BLACK_PEN)
764 case 5: // magenta pen
765 case 6: // yellow pen
766 case 7: // low dye load cyan pen
767 case 8: // low dye load magenta pen
768 case 9: // low dye load yellow pen
769 if (ePen == BLACK_PEN || ePen == BOTH_PENS)
787 // check pen1, assume it is black, pen2 is color
793 temp_pen1 = BLACK_PEN;
795 case 'X': return UNSUPPORTED_PEN;
796 default: temp_pen1 = NO_PEN; break;
802 while ((i < DevIDBuffSize) && str[i]!='$') i++; // handles variable length penIDs
803 if (i == DevIDBuffSize)
805 return BAD_DEVICE_ID;
810 // need to be more forgiving of the color pen type because of
811 // the unknown chinookID for DJ970
812 // we can't guarantee the (F)lash color pen, but we can make sure
813 // the pen is not (X)Undefined, (A)Missing or (M)onet
814 if(str[i]!='X' && str[i]!='A' && str[i]!='M')
815 // check what pen1 was
817 if (temp_pen1 == BLACK_PEN)
824 else // no color pen, just set what pen1 was
830 #if defined(APDK_FONTS_NEEDED)
831 Font* DJ9xx::RealizeFont(const int index,const BYTE bSize,
832 const TEXTCOLOR eColor,
833 const BOOL bBold,const BOOL bItalic,
834 const BOOL bUnderline)
838 return Printer::RealizeFont(index,bSize,eColor,bBold,bItalic,bUnderline);
842 DRIVER_ERROR DJ9xx::CleanPen()
844 const BYTE DJ970_User_Output_Page[] = {ESC, '%','P','u','i','f','p','.',
845 'm','u','l','t','i','_','b','u','t','t','o','n','_','p','u','s','h',' ','3',';',
846 'u','d','w','.','q','u','i','t',';',ESC,'%','-','1','2','3','4','5','X' };
848 DWORD length = sizeof(PEN_CLEAN_PML);
849 DRIVER_ERROR err = pSS->ToDevice(PEN_CLEAN_PML, &length);
852 // send this page so that the user sees some output. If you don't send this, the
853 // pens get serviced but nothing prints out.
854 length = sizeof(DJ970_User_Output_Page);
855 return pSS->ToDevice(DJ970_User_Output_Page, &length);