📄 dj3320.cpp
字号:
// First 10 bytes of m_pbyReadBuff are packet header. Status query from printer has $S: if ((pcStr = strstr((const char*)pLDLEncap->byStatusBuff + 10, "$S:")) == NULL) { m_dsCurrentStatus = DISPLAY_COMM_PROBLEM; return DISPLAY_COMM_PROBLEM; } // Point to first byte of Feature State. Skip 3 bytes for "$S:", 2 for version pcStr += 5; byStatus1 = *pcStr; if (byStatus1 == '9') { iTotal_SLOW_POLL_Count = 0; m_dsCurrentStatus = DISPLAY_TOP_COVER_OPEN; return DISPLAY_TOP_COVER_OPEN; } // Point to Printer State. Skip 14-byte Feature State pcStr += 14; byStatus1 = *pcStr++; byStatus2 = *pcStr++; // In any of the cases where we know what's wrong, reset the slow poll count, which we're // using as a "we know what's going on" variable, to 0 since we do know what's going on if ((byStatus1 == '0') && (byStatus2 == '5')) { // 05 = CNCL state iTotal_SLOW_POLL_Count = 0; m_dsCurrentStatus = DISPLAY_PRINTING_CANCELED; return DISPLAY_PRINTING_CANCELED; } if ((byStatus1 == '0') && (byStatus2 == '9')) { // 09 = OOP state iTotal_SLOW_POLL_Count = 0; m_dsCurrentStatus = DISPLAY_OUT_OF_PAPER_NEED_CONTINUE; return DISPLAY_OUT_OF_PAPER_NEED_CONTINUE; } if ((byStatus1 == '0') && (byStatus2 == 'E')) { // 0E = Paper jam iTotal_SLOW_POLL_Count = 0; m_dsCurrentStatus = DISPLAY_ERROR_TRAP; return DISPLAY_ERROR_TRAP; } if ((byStatus1 == '0') && (byStatus2 == 'F')) { // 0F = Carriage stall iTotal_SLOW_POLL_Count = 0; m_dsCurrentStatus = DISPLAY_ERROR_TRAP; return DISPLAY_ERROR_TRAP; } if ((byStatus1 == '1') && (byStatus2 == '0')) { // 10 = Paper stall iTotal_SLOW_POLL_Count = 0; m_dsCurrentStatus = DISPLAY_ERROR_TRAP; return DISPLAY_ERROR_TRAP; } // No problem detectable from status string. Set default condition m_dsCurrentStatus = DISPLAY_PRINTING; } // VerifyPenInfo will handle prompting the user if this is a problem err = VerifyPenInfo(); if(err) // VerifyPenInfo returned an error, which can only happen when ToDevice // or GetDeviceID returns an error. Either way, it's BAD_DEVICE_ID or // IO_ERROR, both unrecoverable. This is probably due to the printer // being turned off during printing return DISPLAY_COMM_PROBLEM; } // Don't know what the problem is. Increment wait count. i_Total_SLOW_POLL_Count // really has no meaning for the DJ3320, but since it's a printer class variable // and it's not used for the DJ3320 we'll use it here rather than create another // printer class variable iTotal_SLOW_POLL_Count++; // If we've exceeded our wait time and we still don't know what's wrong, return // a communication problem if(iTotal_SLOW_POLL_Count >= ERROR_WAIT) return DISPLAY_BUSY; else return m_dsCurrentStatus;}/* * Author: Don Castrapel */DRIVER_ERROR DJ3320::Send (const BYTE* pWriteBuff, DWORD dwWriteCount){ DRIVER_ERROR err = NO_ERROR; DISPLAY_STATUS eDisplayStatus = DISPLAY_PRINTING; DWORD dwResidual = 0; DWORD dwPrevResidual = 0; const BYTE *pWritePos = NULL; BYTE byPacketType = 0; BYTE byCommandNumber = 0; BYTE byCommandNumberOriginal = 0; BYTE byCreditWaitCount = 0; BYTE byCreditWaitCountOriginal = 0; BYTE byIOWaitCount = 0; BOOL bUpdateState = FALSE; BOOL bCreditForCommand = FALSE; BOOL bFlush = FALSE; BOOL bOriginalRequest = TRUE; // DJ3400 doesn't use a staus reg, but we need one for the call to ParseError BYTE byStatusReg = 0; // Buffering variables DWORD BytesToWrite = dwWriteCount; DWORD BytesToWriteOriginal = dwWriteCount; const BYTE *pWriteBuffOriginal = pWriteBuff; const BYTE *pBuffer = pWriteBuff; DWORD dwWriteCountOriginal = dwWriteCount; DWORD dwSendSize = dwWriteCount; // Retry, query, and cancel variables BOOL bPrinterCancelButton = FALSE; BOOL bCanceling = FALSE; BOOL bCanceled = FALSE;////////////////////////////////////////////////////////////////#ifdef NULL_IO // test imaging speed independent of printer I/O, will not // send any data to the device return NO_ERROR;#endif//////////////////////////////////////////////////////////////// if (!IOMode.bDevID) { return pSS->ToDevice (pWriteBuff, &dwSendSize); } if (ErrorTerminationState) { // Don't try any more I/O if we previously terminated in an error state return JOB_CANCELED; } // If EndJob is TRUE we don't want to return. The Job destructor is the only place that sets this // boolean and we have to flush the buffer if EndJob is TRUE. if (!EndJob) { if (dwWriteCount == 0) // Don't bother processing an empty Send call return NO_ERROR; // Get Packet Type. If Packet Type is a command, buffer it if buffering is turned on. If it's // a different Packet Type, send it directly to the printer byPacketType = pWriteBuff[PACKET_TYPE_BYTE]; // Get Command Number if packet is a command. If it is then we need to check for credit // before we send the command if(!byPacketType) { byCommandNumber = pWriteBuff[COMMAND_NUMBER_BYTE]; byCommandNumberOriginal = pWriteBuff[COMMAND_NUMBER_BYTE]; } } else { // Just flush whatever is in the buffer bFlush = TRUE; } do { // If it's a command, check to see if we have credit for it. If it's a special packet type, // we'll just send it directly to the printer if(!bCreditForCommand) { // Could be first time through do loop or could have not had credit and had to check. We'll // always get here since we don't change bCreditForCommand until here. if (!byPacketType) { // Check to see if we have credit for this command if (pLDLEncap->piCreditCount[byCommandNumber] > 0) { pLDLEncap->piCreditCount[byCommandNumber]--; bCreditForCommand = TRUE; byCreditWaitCount = 0; } else { byCreditWaitCount++; bUpdateState = pLDLEncap->UpdateState (FALSE); if(bUpdateState) { pSS->BusyWait(0); // Rechecking here will save us a trip through the do loop if (pLDLEncap->piCreditCount[byCommandNumber] > 0) { pLDLEncap->piCreditCount[byCommandNumber]--; bCreditForCommand = TRUE; byCreditWaitCount = 0; } } } } else { // Special packet types get a free pass bCreditForCommand = TRUE; } } // if(!bCreditForCommand) // If we don't have credit for the current command we don't want to put it in the // buffer. If, however, we have exceeded our credit wait limit and we need to check // for an error, we have to flush what's in our buffer if (bCreditForCommand || bFlush) { if (bCreditForCommand) { // We should bypass the buffering for a large Send, but don't lose what may // already be buffered if ((BytesToWrite >= (DWORD) iBuffSize) && (iCurrBuffSize == 0)) { pBuffer = pWriteBuff + (dwWriteCount - BytesToWrite); dwSendSize = BytesToWrite; BytesToWrite = 0; // This is checked for at the end of the outer loop } else // We will buffer this data { // If it'll fit then just copy everything to the buffer if (BytesToWrite <= (DWORD) iBuffSize - iCurrBuffSize) { memcpy ((void*) (pSendBuffer + iCurrBuffSize), (void*) (pWriteBuff + (dwWriteCount - BytesToWrite)), BytesToWrite); iCurrBuffSize += BytesToWrite; BytesToWrite = 0; } else // Copy what we can into the buffer, we'll get the rest later { memcpy ((void*) (pSendBuffer + iCurrBuffSize), (void*) (pWriteBuff + (dwWriteCount - BytesToWrite)), iBuffSize - iCurrBuffSize); BytesToWrite -= (iBuffSize - iCurrBuffSize); iCurrBuffSize = iBuffSize; } } // If this wasn't the original request, like a query, continue, prepare to // cancel, or cancel command, flush the buffer immediately if(!bOriginalRequest) { bFlush = TRUE; } } // if (bCreditForCommand) // If the buffer is now full (ready-to-send) or if we're at the end of the job, or // if the Packet Type is not a command then send what we have in the buffer. // otherwise just break (the buffer isn't ready to send) if ((EndJob == FALSE) && (iCurrBuffSize != iBuffSize) && (!byPacketType) && (!bFlush) ) { // We're not ready to send yet. Break out of do loop break; } else // Send this buffered data { if (bFlush) { bFlush = FALSE; } pBuffer = pSendBuffer; dwSendSize = iCurrBuffSize; } // Initialize our 'residual' to the full send size dwResidual = dwSendSize; // Code to check to see if user has pressed cancel button. DJ3320 front panel button, if // pressed during normal printing, will initiate a cancel in the printer. This will cause the // printer to just throw away data but not notify the host. We have to do that here if we // detect a cancel if(bCheckForCancelButton && (ulBytesSentSinceCancelCheck >= CANCEL_BUTTON_CHECK_THRESHOLD)) { ulBytesSentSinceCancelCheck = 0; if(ParseError(byStatusReg) == DISPLAY_PRINTING_CANCELED) bPrinterCancelButton = TRUE; } // If we have nothing to send, we need to bail to avoid spurious dialogs // at the end of the ::send function. I'd prefer a solution where we don't // bail from a while loop but in practice this shouldn't have any ill effects. if (dwResidual <= 0) { return NO_ERROR; } // While still data to send in this request while (dwResidual > 0) { // WritePort overwrites request count, need to save dwPrevResidual = dwResidual; pWritePos = (const BYTE *) &(pBuffer[dwSendSize - dwResidual]); err = pSS->ToDevice (pWritePos, &dwResidual); if(err) { ErrorTerminationState = TRUE; return err; } // No more data to send this time if (dwResidual == 0) { // For USB printer class drivers that have buffering we need to flush the buffer. // If we are sending a special packet type and can't wait for a full buffer we have // to flush err = pSS->FlushIO (); if (err) { ErrorTerminationState = TRUE; return err; } // We successfully sent the entire non-original request, so reset to original // request if(!bOriginalRequest && !bCanceled) { pWriteBuff = pWriteBuffOriginal; dwWriteCount = dwWriteCountOriginal; BytesToWrite = BytesToWriteOriginal; byCommandNumber = byCommandNumberOriginal; bOriginalRequest = TRUE; bCreditForCommand = FALSE; byCreditWaitCount = byCreditWaitCountOriginal; // We have to give the printer some time to update its status and send us a // new status packet pSS->BusyWait(500); } else { if(bOriginalRequest) { byIOWaitCount = 0; } iTotal_SLOW_POLL_Count = 0; } break; // Out of while loop } else { if (dwPrevResidual == dwResidual) { // The I/O didn't take any data, increment count byIOWaitCount++; } else { // The I/O took some data, although not the full request if(bOriginalRequest) byIOWaitCount = 0; } } // If I/O hasn't finished after our timeout limit, we have to bail. if (byIOWaitCount >= IO_WAIT) { ErrorTerminationState = TRUE; pSS->DisplayPrinterStatus (DISPLAY_COMM_PROBLEM); return IO_ERROR; } // Check for user cancel each time through loop if (pSS->BusyWait ((DWORD)0) == JOB_CANCELED) { pSS->DisplayPrinterStatus (DISPLAY_PRINTING_CANCELED); } } // while (residual > 0) iCurrBuffSize = 0; } // if(bCreditForCommand || bFlush) else { // If we can't get credit and we've exceeded our wait limit, check for an error if (byCreditWaitCount >= CREDIT_WAIT) { if(!bOriginalRequest) { // Something is wrong but we don't know what it is and we can't get credit // to Query, Continue, Prepare to Cancel, or Cancel, so we have to bail ErrorTerminationState = TRUE; return JOB_CANCELED; } // Flush our internal buffer so that we can send command such as query or continue if (iCurrBuffSize) { bFlush = TRUE; } else { // See if we can find out what's wrong eDisplayStatus = ParseError(byStatusReg); // For recoverable cases such as out of paper or top cover open, we just want to // display the error and break. For non-recoverable cases we'll wait for the // user to cancel the job and return. // If the user terminated in an error state we have to send the CancelJob, // unless the error state is a condition that would prevent a paper eject, such // as paper jam or error trap. In those cases we'll just return, since the // user has to power cycle the printer before he can continue switch (eDisplayStatus) { case DISPLAY_PRINTING_CANCELED: // User canceled in an error condition, break from here and let check // for cancel at end of do loop send Cancel Job to printer pSS->DisplayPrinterStatus (eDisplayStatus); ErrorTerminationState = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -