/* * spool.c - WritePrinter hook. * * Need to be manipulate the spooler data for Canon CPCA architecture. */ #include "pdev.h" // NTRAID#NTBUG9-172276-2002/03/08-yasuho-: CPCA support #define MAX_CPCA_PACKET_SIZE 4096 // Must be <= 64KB-1 // CPCA Operation codes #define CPCA_JobStart 0x0011 #define CPCA_JobEnd 0x0013 #define CPCA_BinderStart 0x0014 #define CPCA_SetBinder 0x0015 #define CPCA_BinderEnd 0x0016 #define CPCA_DocumentStart 0x0017 #define CPCA_SetDocument 0x0018 #define CPCA_DocumentEnd 0x0019 #define CPCA_Send 0x001A #define CPCA_ExecutiveMethod 0x001D // CPCA Flags #define F_Cont 0x02 // CPCA Attributes #define ATT_DOCFORMAT 0x002E #define DOCFORMAT_LIPS 0x27 #define ATT_RESOLUTION 0x003A #define RESOLUTION_QUICK 0x05 #define RESOLUTION_FINE 0x06 #define RESOLUTION_SUPERFINE 0x07 #define ATT_COPIES 0x07D7 #define ATT_OUTPUT 0x07D8 #define OUTPUT_NO_COLLATE 0x08 #define OUTPUT_COLLATE 0x0B #define OUTPUT_GROUP_COLLATE 0x0F #define ATT_OUTPUTBIN 0x07D9 #define OUTPUTBIN_FACEUP 0x01 #define OUTPUTBIN_FACEDOWN 0x02 #define OUTPUTBIN_SORT 0x11 #define OUTPUTBIN_NUMBER 0x12 #define OUTPUTBIN_STACK 0x15 #define ATT_FINISHING 0x07DA #define FINISHING_STAPLE 0x0C #define FINISHING_COUNT_1 0x66 #define FINISHING_COUNT_2 0x67 #define ATT_OUTPUTPARTITION 0x084A #define OUTPART_JOBOFFSET 0x01 #define OUTPART_NONE 0x04 #define ATT_OUTPUTFACE 0x084B #define OUTPUTFACE_FACEUP 0x01 #define OUTPUTFACE_FACEDOWN 0x02 #define OUTPUTFACE_NONE 0x03 static WORD wStapleModes[] = { 0x00CA, // top_left 0x00D5, // top 0x00CC, // top_right 0x00D3, // left 0x00EE, // center (NOT USED) 0x00D4, // right 0x00CB, // bottom_left 0x00D6, // bottom 0x00CD, // bottom_right }; extern LIPSCmd cmdEndDoc4; extern LIPSCmd cmdEndDoc4C; /* * FlushCPCABuffer */ static BOOL FlushCPCABuffer(PDEVOBJ pdevobj, PLIPSPDEV pOEM) { DWORD dwCount; if (pOEM->CPCABcount == 0) return TRUE; if (!WritePrinter(pdevobj->hPrinter, pOEM->CPCABuf, pOEM->CPCABcount, &dwCount) || dwCount != pOEM->CPCABcount) return FALSE; pOEM->CPCABcount = 0; return TRUE; } /* * SendCPCAPacket */ static BOOL SendCPCAPacket( PDEVOBJ pdevobj, WORD wCmd, BYTE flags, PBYTE pParams, WORD nParams) { PLIPSPDEV pOEM; PBYTE pBuf; DWORD dwCount; pOEM = (PLIPSPDEV)pdevobj->pdevOEM; dwCount = pOEM->CPCABcount; if (dwCount + CPCA_PACKET_SIZE + nParams > CPCA_BUFFER_SIZE) { if (!FlushCPCABuffer(pdevobj, pOEM)) return FALSE; // NTRAID#NTBUG9-548450-2002/03/08-yasuho-: possible buffer overrun. dwCount = 0; } pBuf = pOEM->CPCAPKT; pBuf[3] = flags; pBuf[4] = HIBYTE(wCmd); pBuf[5] = LOBYTE(wCmd); pBuf[8] = HIBYTE(nParams); pBuf[9] = LOBYTE(nParams); CopyMemory(&pOEM->CPCABuf[dwCount], pOEM->CPCAPKT, CPCA_PACKET_SIZE); dwCount += CPCA_PACKET_SIZE; if (nParams) { CopyMemory(&pOEM->CPCABuf[dwCount], pParams, nParams); dwCount += nParams; } pOEM->CPCABcount = dwCount; return TRUE; } /* * CPCAInit */ VOID CPCAInit(PLIPSPDEV pOEM) { pOEM->CPCAPKT[0] = 0xCD; // Header ID pOEM->CPCAPKT[1] = 0xCA; pOEM->CPCAPKT[2] = 0x10; // Version pOEM->CPCABcount = 0; } /* * CPCAStart */ VOID CPCAStart(PDEVOBJ pdevobj) { PLIPSPDEV pOEM = (PLIPSPDEV)pdevobj->pdevOEM; WORD wTemp; BYTE param[32]; ZeroMemory(param, sizeof param); param[4] = 0x01; (VOID)SendCPCAPacket(pdevobj, CPCA_JobStart, 0, param, 13); // ZeroMemory(param, 4); (VOID)SendCPCAPacket(pdevobj, CPCA_BinderStart, 0, param, 4); param[0] = HIBYTE(ATT_COPIES); param[1] = LOBYTE(ATT_COPIES); // NTRAID#NTBUG9-501162-2002/03/08-yasuho-: Collate does not work if (pOEM->sorttype == SORTTYPE_SORT || pOEM->collate == COLLATE_ON) { param[2] = HIBYTE(pOEM->copies); param[3] = LOBYTE(pOEM->copies); } else { param[2] = 0x00; param[3] = 0x01; } (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 4); // NTRAID#NTBUG9-278671-2002/03/08-yasuho-: Finisher !work // NTRAID#NTBUG9-293002-2002/03/08-yasuho-: // Features are different from H/W options. if (pOEM->fCPCA2) { param[0] = HIBYTE(ATT_OUTPUT); param[1] = LOBYTE(ATT_OUTPUT); param[2] = OUTPUT_COLLATE; (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 3); } // NTRAID#NTBUG9-203340-2002/03/08-yasuho-: // Output tray could not selected correctly. // NTRAID#NTBUG9-293002-2002/03/08-yasuho-: // Features are different from H/W options. param[0] = HIBYTE(ATT_OUTPUTBIN); param[1] = LOBYTE(ATT_OUTPUTBIN); if (pOEM->tray == INIT || pOEM->tray == 100) { param[2] = OUTPUTBIN_FACEDOWN; ZeroMemory(¶m[3], 4); } else if (pOEM->tray == 0) { param[2] = OUTPUTBIN_STACK; ZeroMemory(¶m[3], 4); } else if (pOEM->tray == 101) { param[2] = OUTPUTBIN_FACEUP; ZeroMemory(¶m[3], 4); } else { param[2] = OUTPUTBIN_NUMBER; param[3] = (BYTE)pOEM->tray; ZeroMemory(¶m[4], 3); } (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 7); if (pOEM->method != INIT) { // Staple stacker param[0] = HIBYTE(ATT_OUTPUTPARTITION); param[1] = LOBYTE(ATT_OUTPUTPARTITION); param[2] = (pOEM->method == METHOD_JOBOFFSET) ? OUTPART_JOBOFFSET : OUTPART_NONE; (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 3); param[0] = HIBYTE(ATT_OUTPUTFACE); param[1] = LOBYTE(ATT_OUTPUTFACE); param[2] = (pOEM->method == METHOD_FACEUP) ? OUTPUTFACE_FACEUP : OUTPUTFACE_FACEDOWN; (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 3); if (pOEM->method == METHOD_STAPLE) { param[0] = HIBYTE(ATT_FINISHING); param[1] = LOBYTE(ATT_FINISHING); param[2] = 1; param[3] = FINISHING_STAPLE; wTemp = pOEM->staple; if (wTemp < 0 || wTemp >= 9) wTemp = 0; // NTRAID#NTBUG9-292998-2002/03/08-yasuho-: Stapling operate incorrectly. switch (wTemp) { default: param[4] = FINISHING_COUNT_1; break; case 1: // top case 3: // left case 5: // right case 7: // center param[4] = FINISHING_COUNT_2; break; } wTemp = wStapleModes[wTemp]; param[5] = HIBYTE(wTemp); param[6] = LOBYTE(wTemp); (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 7); } else { param[0] = HIBYTE(ATT_FINISHING); param[1] = LOBYTE(ATT_FINISHING); param[2] = 0; (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 3); } } else if (pOEM->sorttype != INIT) { // Sorter param[0] = HIBYTE(ATT_OUTPUTBIN); param[1] = LOBYTE(ATT_OUTPUTBIN); param[2] = (pOEM->sorttype == SORTTYPE_SORT) ? OUTPUTBIN_SORT : OUTPUTBIN_STACK; ZeroMemory(¶m[3], 4); (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 7); } ZeroMemory(param, 4); (VOID)SendCPCAPacket(pdevobj, CPCA_DocumentStart, 0, param, 4); param[0] = HIBYTE(ATT_DOCFORMAT); param[1] = LOBYTE(ATT_DOCFORMAT); param[2] = DOCFORMAT_LIPS; param[3] = 0; param[4] = 0; (VOID)SendCPCAPacket(pdevobj, CPCA_SetDocument, 0, param, 5); // NTRAID#NTBUG9-244001-2002/03/08-yasuho-: 1200dpi doesn't work on LBP-470. param[0] = HIBYTE(ATT_RESOLUTION); param[1] = LOBYTE(ATT_RESOLUTION); if (pOEM->resolution == 1200) param[2] = RESOLUTION_SUPERFINE; else if (pOEM->resolution == 600) param[2] = RESOLUTION_FINE; else param[2] = RESOLUTION_QUICK; ZeroMemory(¶m[3], 4); (VOID)SendCPCAPacket(pdevobj, CPCA_SetDocument, 0, param, 7); param[0] = HIBYTE(ATT_COPIES); param[1] = LOBYTE(ATT_COPIES); // NTRAID#NTBUG9-501162-2002/03/08-yasuho-: Collate does not work if (pOEM->sorttype != SORTTYPE_SORT && pOEM->collate != COLLATE_ON) { param[2] = HIBYTE(pOEM->copies); param[3] = LOBYTE(pOEM->copies); } else { param[2] = 0x00; param[3] = 0x01; } (VOID)SendCPCAPacket(pdevobj, CPCA_SetDocument, 0, param, 4); (VOID)FlushCPCABuffer(pdevobj, pOEM); } /* * CPCAEnd */ VOID CPCAEnd(PDEVOBJ pdevobj, BOOL fColor) { PLIPSPDEV pOEM = (PLIPSPDEV)pdevobj->pdevOEM; LIPSCmd *pCmd; BYTE param[32]; param[0] = 0x01; pCmd = fColor ? &cmdEndDoc4C : &cmdEndDoc4; CopyMemory(¶m[1], pCmd->pCmdStr, pCmd->cbSize); (VOID)SendCPCAPacket(pdevobj, CPCA_Send, 0, param, pCmd->cbSize + 1); (VOID)SendCPCAPacket(pdevobj, CPCA_DocumentEnd, 0, NULL, 0); (VOID)SendCPCAPacket(pdevobj, CPCA_BinderEnd, 0, NULL, 0); param[0] = 0x00; (VOID)SendCPCAPacket(pdevobj, CPCA_JobEnd, 0, param, 1); (VOID)FlushCPCABuffer(pdevobj, pOEM); } /* * OEMWritePrinter */ BOOL APIENTRY OEMWritePrinter( PDEVOBJ pdevobj, PVOID pBuf, DWORD cbBuffer, PDWORD pcbWritten) { PLIPSPDEV pOEM; PBYTE pTemp, pCmd; DWORD dwSize, dwCount, dwWritten; WORD wCount; BYTE cmd[CPCA_PACKET_SIZE+1]; // This is used for UNIDRV to detect the plug-in. if (pBuf == NULL && cbBuffer == 0) return TRUE; pOEM = (PLIPSPDEV)pdevobj->pdevOEM; // If printer is not CPCA, pass through to the spooler. if (!pOEM->fCPCA) return WritePrinter(pdevobj->hPrinter, pBuf, cbBuffer, pcbWritten) && cbBuffer == *pcbWritten; pTemp = (PBYTE)pBuf; dwSize = cbBuffer; while (dwSize > 0) { dwCount = min(dwSize, MAX_CPCA_PACKET_SIZE); // Build Send packet pCmd = pOEM->CPCAPKT; pCmd[3] = F_Cont; pCmd[4] = HIBYTE(CPCA_Send); pCmd[5] = LOBYTE(CPCA_Send); wCount = (WORD)(dwCount + 1); pCmd[8] = HIBYTE(wCount); pCmd[9] = LOBYTE(wCount); CopyMemory(cmd, pOEM->CPCAPKT, CPCA_PACKET_SIZE); cmd[CPCA_PACKET_SIZE] = 0x01; if (!WritePrinter(pdevobj->hPrinter, cmd, sizeof cmd, &dwWritten) || sizeof cmd != dwWritten) return FALSE; if (!WritePrinter(pdevobj->hPrinter, pTemp, dwCount, &dwWritten) || dwCount != dwWritten) return FALSE; pTemp += dwCount; dwSize -= dwCount; } *pcbWritten = cbBuffer; return TRUE; }