//--------------------------------------------------------------------// // M e t h o d // // r e a d R e s p o n s e // //--------------------------------------------------------------------// // // // Read response from target. // // // // There should be TWO FormFeeds in the returned data: // // - first one after return of ECHO data; // // - second one after end of response data; // // // // With some printers, a minimum of two 'reads' are necessary with // // PJL Status Readback, because: // // - the first read reads the ECHO (identifying) data (terminated // // with a Form Feed byte). // // - the second read reads the actual response data (also terminated // // with a FormFeed byte). // // // // With other printers, the response data is concatenated with the // // echo data, so a single read may be all that is necessary. // // // // In each case, multiple reads may be required if the length of the // // returned data exceeds the read 'chunk' size. // // // // And some printers may respond with bits of data less than the // // 'chunk' size, if there is a lot to return, but it is still // // necessary to carry on reading until the terminating <FF> byte is // // found. // // // //--------------------------------------------------------------------// public static String readResponse() { const Int32 replyBufLen = 32768; Byte[] replyData = new Byte[replyBufLen]; Int32 replyLen = 0; Boolean readFF_A = false; // two <FF>s expected // Boolean OK = false; Boolean replyComplete = false; Int32 offset = 0; Int32 endOffset = 0; Int32 bufRem = replyBufLen; Int32 blockLen = 0; while (!replyComplete) { OK = TargetCore.responseReadBlock(offset, bufRem, ref replyData, ref blockLen); endOffset = offset + blockLen; if (!OK) { replyComplete = true; } else if (!readFF_A) { //--------------------------------------------------------// // // // Not yet found any <FF> bytes. // // Search buffer to see if first, or both first and // // second <FF> (as applicable) are present. // // // // This branch is expected to be entered since we include // // a PJL ECHO commmand in the job header. // // // //--------------------------------------------------------// for (Int32 i = offset; i < endOffset; i++) { if (replyData[i] == 0x0c) { if ((readFF_A) && (replyData[endOffset - 1] == 0x0c)) { replyComplete = true; } else { readFF_A = true; } } } } else { //--------------------------------------------------------// // // // <FF> at end of ECHO text is either not expected, or // // has been read in a previous read action. // // // //--------------------------------------------------------// if (replyData[endOffset - 1] == 0x0c) { //----------------------------------------------------// // // // Terminating <FF> found (as last byte of data // // returned by current read action). // // // //----------------------------------------------------// replyComplete = true; } } offset += blockLen; bufRem -= blockLen; if (bufRem <= 0) { replyComplete = true; } } replyLen = endOffset; TargetCore.responseCloseConnection(); return(System.Text.Encoding.ASCII.GetString(replyData, 0, replyLen)); }
//--------------------------------------------------------------------// // M e t h o d // // r e a d R e s p o n s e U p l o a d // //--------------------------------------------------------------------// // // // Read standard response from PJL FileSystem query; request types: // // - FSUPLOAD // // // // Response from printer expected - write this direct to the target // // file (it could be (much) larger than the standard reply buffer. // // // // The response terminates with a FormFeed byte, but the binary data // // returned may also include FormFeed bytes, so have to ignore those // // ones. // // // // Also, at least one printer (LaserJet M553x) appears to return // // extra bytes (sometimes hundreds or more) between the end of the // // upload (of a size determined by the SIZE parameter returned at the // // start of the response) and the terminating <FF>. // // This is presumably a firmware bug? // // // //--------------------------------------------------------------------// private static String readResponseUpload(String binTgtFilename) { const Int32 replyBufLen = 32768; String reply = ""; Boolean binFileOpen = false; binFileOpen = binTgtFileOpen(binTgtFilename); if (!binFileOpen) { reply = "Failed to open target binary file:\r\n\r\n" + binTgtFilename; } else { Int32 binSize = -1; Byte[] replyBlock = new Byte[replyBufLen]; // Boolean readFF_A = true; // only one <FF> expected // Boolean OK = true; Boolean replyComplete = false; Boolean firstBlock = true; Boolean supDataWritten = false; Int32 offset = 0; Int32 endOffset = 0; Int32 bufRem = replyBufLen; Int32 blockLen = 0; Int32 binLen = 0; Int32 binTot = 0; Int32 binRem = 0; Int32 supLen = 0; while (OK && !replyComplete) { OK = TargetCore.responseReadBlock(offset, bufRem, ref replyBlock, ref blockLen); endOffset = offset + blockLen; if (!OK) { replyComplete = true; } /*else if (!readFF_A) * { * //--------------------------------------------------------// * // // * // Not yet found any <FF> bytes. // * // Search buffer to see if first, or both first and // * // second <FF> (as applicable) are present. // * // // * // This branch will never be entered unless we include a // * // PJL ECHO commmand in the job header; included in case // * // we ever do this. // * // // * //--------------------------------------------------------// * * for (Int32 i = offset; i < endOffset; i++) * { * if (replyData[i] == 0x0c) * { * if ((readFF_A) && (replyData[endOffset - 1] == 0x0c)) * replyComplete = true; * else * readFF_A = true; * } * } * }*/ else { //--------------------------------------------------------// // // // <FF> at end of ECHO text is either not expected, or // // has been read in a previous read action. // // // //--------------------------------------------------------// if (replyBlock[endOffset - 1] == 0x0c) { //----------------------------------------------------// // // // Terminating <FF> found (as last byte of data // // returned by current read action). // // // //----------------------------------------------------// replyComplete = true; } } if (firstBlock) { //--------------------------------------------------------// // // // Assume that the first block of the response data will // // contain (at least) the complete PJL FSUPLOAD command // // with its parameters. // // // //--------------------------------------------------------// Int32 cmdLen; firstBlock = false; cmdLen = Array.IndexOf(replyBlock, PrnParseConstants.asciiLF, 0, blockLen); if (cmdLen != -1) { //----------------------------------------------------// // // // Terminating <LF> byte of PJL command found. // // Search for the value associated with the SIZE // // parameter. // // // //----------------------------------------------------// cmdLen += 1; // account for <LF> byte // binSize = readResponseUploadSize(replyBlock, cmdLen); reply = Encoding.ASCII.GetString(replyBlock, 0, cmdLen) + "\r\n" + binSize + " bytes will be written to the" + " target file:" + "\r\n\r\n" + binTgtFilename; binLen = blockLen - cmdLen; if (replyComplete) { // terminating <FF> found; ignore this in count binLen -= 1; } binRem = binSize; if (binRem > binLen) { supLen = 0; binRem = binRem - binLen; } else if (binRem < binLen) { supLen = binLen - binRem; binLen = binRem; binRem = 0; } else { supLen = 0; binRem = 0; } binTot = binLen; binTgtFileWrite(replyBlock, cmdLen, binLen); } else { //----------------------------------------------------// // // // Terminating <LF> byte of PJL command NOT found. // // Send response blocks to the binary file for // // diagnostic purposes. // // // //----------------------------------------------------// reply = "SIZE data not found at start of response" + "\r\n\r\n" + "All response data will be written to the" + " target file:" + "\r\n\r\n" + binTgtFilename; binSize = -1; binRem = 0; binTgtFileWrite(replyBlock, 0, blockLen); } } else { //--------------------------------------------------------// // // // Not the first response block. // // // //--------------------------------------------------------// if (binSize == -1) { // write everything to target file // binLen = blockLen; } else { binLen = blockLen; if (replyComplete) { // terminating <FF> found; ignore this in count binLen -= 1; } if (binRem > binLen) { binRem = binRem - binLen; } else if (binRem < binLen) { supLen += (binLen - binRem); binLen = binRem; binRem = 0; } else { binRem = 0; } } binTot += binLen; binTgtFileWrite(replyBlock, 0, binLen); } if ((supLen != 0) && (!supDataWritten)) { supDataWritten = true; reply += "\r\n\r\n" + "Response from device contains extra" + " bytes after the binary data of size " + binSize + " bytes.\r\n" + "Here are the first " + supLen + " such bytes:\r\n\r\n" + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + "\r\n" + Encoding.ASCII.GetString(replyBlock, binLen, supLen) + "\r\n" + "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"; } } //--------------------------------------------------------// // // // Response complete. // // Close connection and output binary file. // // // //--------------------------------------------------------// TargetCore.responseCloseConnection(); binTgtFileClose(); //--------------------------------------------------------// // // // Supplement reply data with details of any // // inconsistencies. // // // //--------------------------------------------------------// if (binTot < binSize) { reply += "\r\n\r\n" + "Response contains only " + binTot + " bytes of binary data, but " + binSize + " bytes were expected!"; } if (supLen != 0) { reply += "\r\n\r\n" + "Response from device contains an extra " + supLen + " bytes after the binary data!"; } } return(reply); }