// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved // // File Name: // // USBMON_Bidi_JavaScript_File.js // // Abstract: // // Sample USBMON Javascript extension file for v4 printer drivers. // /// Make PJL Command /// /// @param Query - PJL String /// /// @return String - added prefix and postfix data /// function GetPJLCommand(Query) { var Prefix = [0x1B, 0x25, 0x2D, 0x31, 0x32, 0x33, 0x34, 0x35, 0x58, 0x40, 0x50, 0x4A, 0x4C, 0x0D, 0x0A]; var Postfix = [0x1B, 0x25, 0x2D, 0x31, 0x32, 0x33, 0x34, 0x35, 0x58]; var Command = Prefix.concat(Query, Postfix); return Command; } /// Read Command from device /// /// @param printerStream - Printer stream for communication /// @Param Header - Command Header /// @Param bufferSize - Minimum Buffer Size /// /// @return String - read data that exclude Header data. /// function ReadString(printerStream, Header, bufferSize) { var nBufferSize = 50; if (bufferSize > nBufferSize) nBufferSize = bufferSize; var ReadData = ""; for (var index = 0; index < 3; index++) { var readBuffer = printerStream.read(nBufferSize); if ((null === readBuffer) || (0 >= readBuffer.length)) break; if (readBuffer.length <= Header.length) continue; var Data = ""; for (var i = 0; i < readBuffer.length; i++) { Data += String.fromCharCode(readBuffer[i]); } var nPos = -1; if ("" !== Header) nPos = Data.search(Header); if (-1 < nPos) { ReadData = Data.substring(Header.length); break; } } return ReadData; } /// /// Get the requested Schema(s). /// /// The script can use the 'schemaRequests' object to iterate through the Query Keys requested by the user. Based on the query keys, /// the script should use the 'printerStream' object to communicate with the USB print device and determine the values of one or more Bidi /// Schema elements. For each Bidi Schema element the new value can be returned to the caller by using functions of the 'printerBidiSchemaResponses' /// object. Once all query keys have been processed and all values added to the 'printerBidiSchemaResponses' object the script can return. /// /// It is possible the attached device is not ready to return some of the requested data. In this case the function can return a value of 1 to indicate the call /// should be retried after a wait. /// /// /// Script context object. /// /// /// Allows the script to Write/Read data from the attached USB device. /// /// /// Array of strings that contains all the requested Query Keys. /// /// /// Object the script will use to store all responses to query keys. /// /// /// Integer value indicating function completion status. /// 1 - The attached device was not ready to provide some requested information. Call the function again using any Requery Keys added during processing. /// 0 - The script completed successfuly. /// function getSchemas( scriptContext, printerStream, schemaRequests, printerBidiSchemaResponses ) { var retVal = 0; var i = 0; debugger; var bag = scriptContext.QueueProperties; var queueProperty = bag.GetString("Config:Win8Support"); //Loop through all the QueryKeys provided in the schemaRequests object for ( var index = 0; index < schemaRequests.length; index++ ) { var key = schemaRequests[index]; if (("On" !== queueProperty) && ("DEVICEID" !== key)) { if ("Off" !== queueProperty) { retVal = 1; printerBidiSchemaResponses.addRequeryKey(key); } continue; } if (key === "DEVICEID") { //Request: @PJL INFO ID //Response: @PJL INFO ID\n"Dell ML-375x Series" var bId = false; var Id = ""; var Data = [0x40, 0x50, 0x4A, 0x4C, 0x20, 0x49, 0x4E, 0x46, 0x4F, 0x20, 0x49, 0x44, 0x0D, 0x0A]; var writeData = GetPJLCommand(Data); var bytesWritten = printerStream.write(writeData); if (bytesWritten === writeData.length) { var result = ReadString(printerStream, "@PJL INFO ID", 128); if ("" !== result) { var nStart = result.indexOf('\"'); var nEnd = result.lastIndexOf('\"'); Id = result.substring(nStart+1, nEnd); if ("" !== Id) bId = true; } } if (false === bId) { continue; } printerBidiSchemaResponses.addString("\\Printer.DeviceInfo:Id", Id); //Request: @PJL GETDEVICEID //Response: @PJL GETDEVICEID "deviceid.." var bDeviceId = false; var DeviceId = ""; var Data = [0x40, 0x50, 0x4A, 0x4C, 0x20, 0x47, 0x45, 0x54, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x49, 0x44, 0x0D, 0x0A]; var writeData = GetPJLCommand(Data); var bytesWritten = printerStream.write( writeData ); if (bytesWritten === writeData.length) { var result = ReadString(printerStream, "@PJL GETDEVICEID=", 512); DeviceId = result.replace(/\"/g, ''); if ("" !== DeviceId) { bDeviceId = true; if (-1 < DeviceId.search(/win8/i)) printerBidiSchemaResponses.addBool("\\Printer.Dell.AutoConfiguration:Supported", true); } } if (false === bDeviceId) { if (bId) printerBidiSchemaResponses.addBool("\\Printer.Dell.AutoConfiguration:Supported", false); } printerBidiSchemaResponses.addString("\\Printer.DeviceInfo:DeviceId", DeviceId); } } return retVal; } /// /// Set a requested Bidi Schema Value in the device /// /// @param scriptContext - Script context object which allows access to IPrinterScriptablePropertyBag for printer driver and queue properties /// @param printerStream - Allows the script to Write/Read data from the attached USB device /// @param printerBidiSchemaElement - Contains all the data associated with the Bidi Schema Value to set /// /// @return Integer value - currently only JavaScript exceptions are expected for failures /// /// The script can interpret the incoming Bidi Schema value to either set data in the device or perform an action on the device. /// /// The scriptContext object provides access to the Driver and Queue prorperty bags associated with the current device. These property bags support read-only access. /// function setSchema( scriptContext, printerStream, printerBidiSchemaElement ) { return 0; } /// /// Retrieve unsolicited Bidi Schema value updates from the USB device during printing. /// /// This function is only called when a job is printing. A device can provide data on the read channel which this script can interpret into /// Bidi Schema values and returned to USBMon. /// /// This function will be called repeatedly during printing. It is expected the device will only return data if it is available and the script can understand it. /// If the device does not support querying for unsolicited status or the script can determine that there is no need to call this function again, the script can return /// a value of 2 which will tell the getStatus execution thread in USBMon to exit successfully. /// /// If the print device does not support retrieving status during a print job this function should be left out of the driver's JavaScipt file altogether. This will inform /// USBMon to skip invocation of the function. /// /// /// Accessor for PropertyBags for printer driver and queue properties. /// /// /// Allows the script to read data from the attached USB device. Calling the write function will fail. This device is opened read-only for this function. /// /// /// Object the script will use to store all status responses. /// /// /// Integer value indicating function completion status. /// 2 - The device no longer (if ever) supports unsolicited status so no need for USBMon to make more calls to this function. /// 0 - The script completed successfuly. /// function getStatus( scriptContext, printerStream, printerBidiSchemaResponses ) { var retVal = 0; debugger; var bag = scriptContext.QueueProperties; var queueProperty = bag.GetString("Config:Win8Support"); if ("Off" === queueProperty) { return 2; } //sample: @PJL DRIVERSTATUS STATUSCODE=00040002 var bReadStatus = false; var readBuffer = printerStream.read(50); if (null !== readBuffer) { var bytesRead = readBuffer.length; var Header = "@PJL DRIVERSTATUS STATUSCODE="; if (bytesRead > Header.length) { var Read = ""; for (i = 0; i < bytesRead; i++) Read += String.fromCharCode(readBuffer[i]); if (-1 < Read.search(Header)) { var Category = Read.substr(Header.length, 4).toUpperCase(); var Status = Read.substr(Header.length + 4, 4).toUpperCase(); if (Category === "0001") { //None if (Status === "0001") printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "None"); } else if (Category === "0002") { //Door if (Status === "0001") printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "DoorOpen"); } else if (Category === "0003") { //Marker if (Status === "0001") printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "MarkerSupplyLow"); else if (Status === "0002") printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "MarkerFailure"); else if (Status === "0003") printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "MarkerSupplyEmpty"); } else if (Category === "0004") { //Media if (Status === "0001") printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "MediaLow"); else if (Status === "0002") printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "MediaEmpty"); else if (Status === "0003") printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "MediaJam"); else if (Status === "0004") printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "MediaNeeded"); } else if (Category === "0005") { //Output if (Status === "0001") printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "OutputAreaAlmostFull"); else if (Status === "0002") printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "OutputAreaFull"); } else if (Category === "F000") { //AttentionRequired if (Status === "0001") printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "AttentionRequired"); } else if (Category === "F100") { //Paused if (Status === "0001") printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "Paused"); } else if (Category === "FFFF") { //Job End if (Status === "FFFF") { printerBidiSchemaResponses.addString("\\Printer.Status.Summary:StateReason", "None"); retVal = 2; } } bReadStatus = true; } } } if ("None" === queueProperty) { if (bReadStatus) { printerBidiSchemaResponses.addBool("\\Printer.Dell.AutoConfiguration:Supported", true); } else { printerBidiSchemaResponses.addBool("\\Printer.Dell.AutoConfiguration:Supported", false); retVal = 2; } } return retVal; }