// 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;
}