Tizen 2.1 base
[platform/upstream/hplip.git] / prnt / hpijs / dj8xx.cpp
1 /*****************************************************************************\
2   dj8xx.cpp : Implimentation for the DJ8xx class
3
4   Copyright (c) 1996 - 2001, Hewlett-Packard 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 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 #if defined(APDK_DJ8xx)|| defined(APDK_DJ9xx)
33
34 #include "header.h"
35 #include "io_defs.h"
36 #include "dj8xx.h"
37 #include "printerproxy.h"
38
39 APDK_BEGIN_NAMESPACE
40 extern BYTE* GetHT3x3_4();
41 extern BYTE* GetHT6x6_4();
42 APDK_END_NAMESPACE
43
44 APDK_BEGIN_NAMESPACE
45
46 extern uint32_t ulMapDJ895_KCMY[ 9 * 9 * 9 ];
47 extern uint32_t ulMapDJ600_CCM_K[ 9 * 9 * 9 ];
48 extern uint32_t ulMapDJ895_HB_KCMY[ 9 * 9 * 9 ];
49 extern uint32_t ulMapDJ895_Binary_KCMY[ 9 * 9 * 9 ];
50 extern uint32_t ulMapGRAY_K_6x6x1[9 * 9 * 9];
51
52 DJ895Mode1::DJ895Mode1()    // Normal Color
53 : PrintMode(ulMapDJ895_KCMY)
54 // 600x600x1 K
55 // 300x300x2 CMY
56 {
57
58     ColorDepth[K]=1;  // 600x600x1 K
59
60     for (int i=1; i < 4; i++)
61         ColorDepth[i]=2;    // 300x300x2 CMY
62
63     ResolutionX[K]=ResolutionY[K]=600;
64
65     MixedRes = TRUE;
66
67     ColorFEDTable = GetHT3x3_4();
68
69     bFontCapable = FALSE;       // DJ895 can't do fonts and hifipe at same time
70 }
71
72 DJ895Mode2::DJ895Mode2()    // Photo
73 : PrintMode(ulMapDJ895_HB_KCMY)
74 // 600x600x1 K
75 // 600x600x2 CMY
76 {
77     int i;
78     ColorDepth[K]=1;  // 600x600x1 K
79
80     for (i=1; i < 4; i++)
81         ColorDepth[i]=2;    // 600x600x2 CMY
82
83     for (i=0; i < 4; i++)
84         ResolutionX[i]=ResolutionY[i]=600;
85
86     BaseResX = BaseResY = 600;
87     MixedRes = FALSE;
88
89     medium     = mediaGlossy;
90     theQuality = qualityPresentation;
91
92     ColorFEDTable = GetHT6x6_4();
93
94      bFontCapable = FALSE;       // DJ895 can't do fonts and hifipe at same time
95
96 //     strcpy(ModeName, "Photo");
97
98      pmQuality   = QUALITY_BEST;
99      pmMediaType = MEDIA_PHOTO;
100 }
101
102 DJ895Mode3::DJ895Mode3()    // Draft Color
103 : PrintMode(ulMapDJ895_Binary_KCMY)
104 // 300x300x1 KCMY
105 {
106
107     theQuality = qualityDraft;
108 //    strcpy(ModeName,"Draft");
109     pmQuality = QUALITY_DRAFT;
110 }
111
112 DJ895Mode4::DJ895Mode4()    // Draft Gray K
113 : GrayMode(ulMapDJ600_CCM_K)
114 // 300x300x1 K
115 {
116     theQuality = qualityDraft;
117     pmQuality = QUALITY_DRAFT;
118 }
119
120 #ifdef APDK_EXTENDED_MEDIASIZE
121 DJ895Mode5::DJ895Mode5()    // Normal Gray K
122 : GrayMode(ulMapGRAY_K_6x6x1)
123 // 600x600x1 K
124 {
125     BaseResX = BaseResY = 600;
126     ResolutionX[K]=ResolutionY[K]=600;
127     bFontCapable = FALSE;
128 }
129 #endif
130
131 DJ8xx::DJ8xx(SystemServices* pSS,
132                        int numfonts, BOOL proto)
133     : Printer(pSS, numfonts, proto)
134 {
135
136     if ((!proto) && (IOMode.bDevID))
137     {
138         constructor_error = VerifyPenInfo();
139         CERRCHECK;
140     }
141     else ePen=BOTH_PENS;    // matches default mode
142
143 #ifdef APDK_EXTENDED_MEDIASIZE
144     pMode[GRAYMODE_INDEX]      = new DJ895Mode5 ();   // Normal Gray K
145 #else
146     pMode[GRAYMODE_INDEX]      = new GrayMode (ulMapDJ600_CCM_K);   // Normal Gray K
147 #endif
148     pMode[DEFAULTMODE_INDEX]   = new DJ895Mode1 ();   // Normal Color
149     pMode[SPECIALMODE_INDEX]   = new DJ895Mode2 ();   // Photo
150     pMode[SPECIALMODE_INDEX+1] = new DJ895Mode3 ();   // Draft Color
151     pMode[SPECIALMODE_INDEX+2] = new DJ895Mode4 ();   // Draft Gray K
152     ModeCount = 5;
153
154     CMYMap = ulMapDJ895_Binary_KCMY;
155
156     DBG1("DJ8xx created\n");
157 }
158
159
160 Header895::Header895(Printer* p,PrintContext* pc)
161     : Header(p,pc)
162 { }
163
164 DRIVER_ERROR Header895::Send()
165 {   DRIVER_ERROR err;
166
167     StartSend();
168
169     err = ConfigureRasterData();
170     ERRCHECK;
171
172     err=Graphics();     // start raster graphics and set compression mode
173
174     // this is the pre-pick command but it doesn't work.  hmm...
175     //    err = thePrinter->Send((const BYTE*)DJ895_Pre_Pick,sizeof(DJ895_Pre_Pick));
176
177 return err;
178 }
179
180 DRIVER_ERROR Header895::StartSend()
181 // common items gathered for code savings
182 {
183     DRIVER_ERROR err;
184
185     err = thePrinter->Send((const BYTE*)Reset,sizeof(Reset));
186     ERRCHECK;
187
188     err = thePrinter->Send((const BYTE*)UEL,sizeof(UEL));
189     ERRCHECK;
190
191     err = thePrinter->Send((const BYTE*)EnterLanguage,sizeof(EnterLanguage));
192     ERRCHECK;
193
194     if (!thePrinter->UseGUIMode(thePrintContext->CurrentMode))
195         err = thePrinter->Send((const BYTE*)PCL3,sizeof(PCL3));
196     else
197         err = thePrinter->Send((const BYTE*)PCLGUI,sizeof(PCLGUI));
198     ERRCHECK;
199
200     err = thePrinter->Send((const BYTE*)&LF,1);
201     ERRCHECK;
202
203     err=Modes();            // Set media source, type, size and quality modes.
204     ERRCHECK;
205
206 //  Now send media pre-load command
207     err = thePrinter->Send ((const BYTE *) "\033&l-2H", 6);   
208     ERRCHECK;
209
210     char uom[10];
211     sprintf(uom,"%c%c%c%d%c",ESC,'&','u',thePrintContext->EffectiveResolutionY(),'D');
212     err=thePrinter->Send((const BYTE*)uom, strlen (uom));
213     ERRCHECK;
214
215     if (!thePrinter->UseGUIMode(thePrintContext->CurrentMode))
216         err=Margins();          // set margins
217
218     else    // special GUI mode top margin set
219     {
220         CAPy = thePrintContext->GUITopMargin();
221     }
222
223     return err;
224 }
225
226 extern BYTE EscAmplCopy(BYTE *dest, int num, char end);
227
228
229 DRIVER_ERROR Header895::Graphics()
230 // variant due to compression problems
231 {
232     DRIVER_ERROR error= thePrinter->Send((const BYTE*)grafStart, sizeof(grafStart) );
233     if (error!=NO_ERROR)
234         return error;
235
236     if (thePrintMode->Config.bCompress)
237         {
238             error= thePrinter->Send((const BYTE*)grafMode2, sizeof(grafMode2) );
239             if (error!=NO_ERROR)
240                 return error;
241         }
242     else
243
244         error= thePrinter->Send((const BYTE*)grafMode0, sizeof(grafMode0) );
245
246 return error;
247 #define GRAPHICSIZE (sizeof(grafStart)+sizeof(grafMode9)+sizeof(SeedSame))
248 }
249
250
251 Header* DJ8xx::SelectHeader(PrintContext* pc)
252 {
253     return new Header895(this,pc);
254 }
255
256 DRIVER_ERROR DJ8xx::VerifyPenInfo()
257 {
258
259     DRIVER_ERROR err = NO_ERROR;
260
261     if(IOMode.bDevID == FALSE)
262     {
263         return err;
264     }
265
266     err = ParsePenInfo(ePen);
267
268     if(err == UNSUPPORTED_PEN) // probably Power Off - pens couldn't be read
269     {
270         DBG1("DJ8xx::Need to do a POWER ON to get penIDs\n");
271
272         // have to delay the POWER ON will be ignored
273         if (pSS->BusyWait((DWORD)2000) == JOB_CANCELED)
274         {
275             return JOB_CANCELED;
276         }
277
278         DWORD length = sizeof(DJ895_Power_On);
279         err = pSS->ToDevice(DJ895_Power_On,&length);
280         ERRCHECK;
281
282         err = pSS->FlushIO();
283         ERRCHECK;
284
285         // give the printer some time to power up
286         if (pSS->BusyWait ((DWORD) 2500) == JOB_CANCELED)
287         {
288             return JOB_CANCELED;
289         }
290
291         err = ParsePenInfo(ePen);
292     }
293
294     ERRCHECK;
295
296     // check for the normal case
297     if (ePen == BOTH_PENS)
298     {
299         return NO_ERROR;
300     }
301
302     while ( ePen != BOTH_PENS   )
303     {
304
305         switch (ePen)
306         {
307             case BLACK_PEN:
308                 // black pen installed, need to install color pen
309                 pSS->DisplayPrinterStatus(DISPLAY_NO_COLOR_PEN);
310                 break;
311             case COLOR_PEN:
312                 // color pen installed, need to install black pen
313                 pSS->DisplayPrinterStatus(DISPLAY_NO_BLACK_PEN);
314                 break;
315             case NO_PEN:
316                 // neither pen installed
317             default:
318                 pSS->DisplayPrinterStatus(DISPLAY_NO_PENS);
319                 break;
320         }
321
322         if (pSS->BusyWait(500) == JOB_CANCELED)
323         {
324             return JOB_CANCELED;
325         }
326
327         err =  ParsePenInfo(ePen);
328         ERRCHECK;
329     }
330
331     pSS->DisplayPrinterStatus(DISPLAY_PRINTING);
332
333     return NO_ERROR;
334 }
335
336 DRIVER_ERROR DJ8xx::ParsePenInfo(PEN_TYPE& ePen, BOOL QueryPrinter)
337 {
338     char* str;
339     DRIVER_ERROR err = SetPenInfo (str, QueryPrinter);
340     ERRCHECK;
341
342     if (*str != '$')
343     {
344         return BAD_DEVICE_ID;
345     }
346
347     // parse penID
348     PEN_TYPE temp_pen1;
349     // check pen1, assume it is black, pen2 is color
350     switch (str[1])
351     {
352         case 'H': // (H)obbes
353         case 'L': // (L)inus
354         case 'Z': // (Z)orro
355         {
356             temp_pen1 = BLACK_PEN;
357             break;
358         }
359         case 'X': return UNSUPPORTED_PEN;
360         default:  temp_pen1 = NO_PEN; break;
361     }
362
363     // now check pen2
364
365     int i = 2;
366     while ((i < DevIDBuffSize) && str[i] != '$') i++; // handles variable length penIDs
367     if (i == DevIDBuffSize)
368     {
369         return BAD_DEVICE_ID;
370     }
371
372     i++;
373
374     // need to be more forgiving of the color pen type because of
375     // the unknown chinookID for DJ970
376     // we can't guarantee the (F)lash color pen, but we can make sure
377     // the pen is not (X)Undefined, (A)Missing or (M)onet
378     if(str[i] != 'X' && str[i] != 'A' && str[i] != 'M')
379     // check what pen1 was
380     {
381         if (temp_pen1 == BLACK_PEN)
382         {
383             ePen = BOTH_PENS;
384         }
385         else
386         {
387             ePen = COLOR_PEN;
388         }
389     }
390     else // no color pen, just set what pen1 was
391     {
392         ePen = temp_pen1;
393     }
394
395     return NO_ERROR;
396 }
397
398
399 Compressor* DJ8xx::CreateCompressor(unsigned int RasterSize)
400 {
401     DBG1("Compression = Mode2\n");
402     return new Mode2(pSS,RasterSize);
403 }
404
405 BOOL DJ8xx::UseGUIMode(PrintMode* pPrintMode)
406 {
407     return (!pPrintMode->bFontCapable);
408 }
409
410 DRIVER_ERROR DJ8xx::CleanPen()
411 {
412     const BYTE DJ895_Diag_Page[] = {ESC, '%','P','u','i','f','p','.',
413         'm','u','l','t','i','_','b','u','t','t','o','n','_','p','u','s','h',' ','4',';',
414         'u','d','w','.','q','u','i','t',';',ESC,'%','-','1','2','3','4','5','X' };
415
416     const BYTE PEN_CLEAN_PML[]={0x1B,0x45,0x1B,0x26,0x62,0x31,0x36,0x57,
417                 0x50,0x4D,0x4C,0x20,  // EscE Esc&b16WPML{space}
418                 0x04,0x00,0x06,0x01,0x04,0x01,0x05,0x01,
419                 0x01,0x04,0x01,0x64}; // PML Marking-Agent-Maintenance=100
420
421     DWORD length = sizeof(DJ895_Power_On);
422     DRIVER_ERROR Error = pSS->ToDevice(DJ895_Power_On,&length);
423
424     pSS->BusyWait((DWORD)1000);
425
426     length = sizeof(PEN_CLEAN_PML);
427     Error = pSS->ToDevice(PEN_CLEAN_PML,&length);
428
429     length = sizeof(DJ895_Diag_Page);
430     return pSS->ToDevice(DJ895_Diag_Page,&length);
431 }
432
433
434
435
436 /*
437  *  Function name: ParseError
438  *
439  *  Owner: Darrell Walker
440  *
441  *  Purpose:  To determine what error state the printer is in.
442  *
443  *  Called by: Send()
444  *
445  *  Parameters on entry: status_reg is the contents of the centronics
446  *                      status register (at the time the error was
447  *                      detected)
448  *
449  *  Parameters on exit: unchanged
450  *
451  *  Return Values: The proper DISPLAY_STATUS to reflect the printer
452  *              error state.
453  *
454  */
455
456 /*  We have to override the base class's (Printer) ParseError function due
457     to the fact that the 8XX series returns a status byte of F8 when it's out of
458     paper.  Unfortunately, the 600 series returns F8 when they're turned off.
459     The way things are structured in Printer::ParseError, we used to check only
460     for DEVICE_IS_OOP.  This would return true even if we were connected to a
461     600 series printer that was turned off, causing the Out of paper status
462     message to be displayed.  This change also reflects a corresponding change
463     in IO_defs.h, where I split DEVICE_IS_OOP into DEVICE_IS_OOP, DJ400_IS_OOP, and
464     DJ8XX_IS_OOP and we now check for DJ8XX_IS_OOP in the DJ8xx class's
465     ParseError function below.  05/11/99 DGC.
466 */
467
468 DISPLAY_STATUS DJ8xx::ParseError(BYTE status_reg)
469 {
470     DBG1("DJ8xx: parsing error info\n");
471
472     DRIVER_ERROR err = NO_ERROR;
473     BYTE DevIDBuffer[DevIDBuffSize];
474  
475     char *pStr;
476     if(IOMode.bDevID)
477     {
478         // If a bi-di cable was plugged in and everything was OK, let's see if it's still
479         // plugged in and everything is OK
480         err = pSS->GetDeviceID(DevIDBuffer, DevIDBuffSize, TRUE);
481         if(err != NO_ERROR)
482             // job was bi-di but now something's messed up, probably cable unplugged
483             return DISPLAY_COMM_PROBLEM;
484
485         if ( TopCoverOpen(status_reg) )
486         {
487             DBG1("Top Cover Open\n");
488             return DISPLAY_TOP_COVER_OPEN;
489         }
490
491
492         if ( (pStr=(char *)strstr((const char*)DevIDBuffer+2,"VSTATUS:")) == NULL )
493         {
494             return DISPLAY_COMM_PROBLEM;
495         }
496
497         pStr+=8;   // skip "VSTATUS:"
498                 // Paper Jam or Paper Stall
499         if (strstr((char*)pStr,"PAJM") || strstr((char*)pStr,"PAPS"))
500         {
501             return DISPLAY_PAPER_JAMMED;
502         }
503
504                 // Power down or printing turning off
505         if (strstr((char*)pStr,"PWDN") || strstr((char*)pStr,"OFFF"))
506         {
507             return DISPLAY_OFFLINE;
508         }
509
510
511         // VerifyPenInfo will handle prompting the user
512         // if this is a problem
513         err = VerifyPenInfo();
514
515         if(err != NO_ERROR)
516             // VerifyPenInfo returned an error, which can only happen when ToDevice
517             // or GetDeviceID returns an error. Either way, it's BAD_DEVICE_ID or
518             // IO_ERROR, both unrecoverable.  This is probably due to the printer
519             // being turned off during printing, resulting in us not being able to
520             // power it back on in VerifyPenInfo, since the buffer still has a
521             // partial raster in it and we can't send the power-on command.
522             return DISPLAY_COMM_PROBLEM;
523     }
524
525     // check for errors we can detect from the status reg
526     if (IOMode.bStatus)
527     {
528         if ( DEVICE_IS_OOP(status_reg) )
529         {
530             DBG1("Out Of Paper\n");
531             return DISPLAY_OUT_OF_PAPER;
532         }
533
534         if (DEVICE_PAPER_JAMMED(status_reg))
535         {
536             DBG1("Paper Jammed\n");
537             return DISPLAY_PAPER_JAMMED;
538         }
539
540         if (DEVICE_IO_TRAP(status_reg))
541         {
542             DBG1("IO trap\n");
543             return DISPLAY_ERROR_TRAP;
544         }
545     }
546
547     // don't know what the problem is-
548     //  Is the PrinterAlive?
549     if (pSS->PrinterIsAlive())
550     {
551         iTotal_SLOW_POLL_Count += iMax_SLOW_POLL_Count;
552 #if defined(DEBUG) && (DBG_MASK & DBG_LVL1)
553         printf("iTotal_SLOW_POLL_Count = %d\n",iTotal_SLOW_POLL_Count);
554 #endif
555         // -Note that iTotal_SLOW_POLL_Count is a multiple of
556         //  iMax_SLOW_POLL_Count allowing us to check this
557         //  on an absolute time limit - not relative to the number
558         //  of times we happen to have entered ParseError.
559         // -Also note that we have different thresholds for uni-di & bi-di.
560         if(
561             ((IOMode.bDevID == FALSE) && (iTotal_SLOW_POLL_Count >= 60)) ||
562             ((IOMode.bDevID == TRUE)  && (iTotal_SLOW_POLL_Count >= 120))
563           )
564         {
565             return DISPLAY_BUSY;
566         }
567         else
568         {
569             return DISPLAY_PRINTING;
570         }
571     }
572     else
573     {
574         return DISPLAY_COMM_PROBLEM;
575     }
576 }
577
578 APDK_END_NAMESPACE
579
580 #endif  // defined APDK_DJ8xx or APDK_9xx