windows-nt/Source/XPSP1/NT/drivers/wdm/input/opos/posusb/escpos.h
2020-09-26 16:20:57 +08:00

389 lines
13 KiB
C

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
escpos.h
Abstract: ESC/POS (serial) interface for USB Point-of-Sale devices
Author:
ervinp
Environment:
Kernel mode
Revision History:
--*/
#include "ntddser.h"
/*
* Serial Status Emulation has been disabled for the time being.
*/
#define STATUS_ENDPOINT 0
/*
* Bit mask for the posFlag.
*/
#define SERIAL_EMULATION 0x0001
#define ODD_ENDPOINT 0x0002
/*
* Bit mask for the STATUS Endpoint on the USB.
*/
#define EMULSER_OE 0x0001
#define EMULSER_PE 0x0002
#define EMULSER_FE 0x0004
#define EMULSER_BI 0x0008
#define EMULSER_CTS 0x0010
#define EMULSER_DSR 0x0020
#define EMULSER_RI 0x0040
#define EMULSER_DCD 0x0080
#define EMULSER_DTR 0x0100
#define EMULSER_RTS 0x0200
/*
* Emulation of the bit mask on the MODEM STATUS REGISTER.
*/
#define SERIAL_MSR_DCTS 0x0001
#define SERIAL_MSR_DDSR 0x0002
#define SERIAL_MSR_TERI 0x0004
#define SERIAL_MSR_DDCD 0x0008
#define SERIAL_MSR_CTS 0x0010
#define SERIAL_MSR_DSR 0x0020
#define SERIAL_MSR_RI 0x0040
#define SERIAL_MSR_DCD 0x0080
/*
* These masks are used for smooth transition of the STATUS bits
* from the Endpoint to the Emulated Variables.
*/
#define MSR_DELTA_MASK 0x000F
#define MSR_GLOBAL_MSK 0x00F0
#define MSR_DELTA_SHFT 4
/*
* Emulation of the bit mask on the LINE STATUS REGISTER.
*/
#define SERIAL_LSR_DR 0x0001
#define SERIAL_LSR_OE 0x0002
#define SERIAL_LSR_PE 0x0004
#define SERIAL_LSR_FE 0x0008
#define SERIAL_LSR_BI 0x0010
#define SERIAL_LSR_THRE 0x0020
#define SERIAL_LSR_TEMT 0x0040
#define SERIAL_LSR_FIFOERR 0x0080
/*
* IOCTL CODE for applications to be able to get the device's pretty name.
*/
#define IOCTL_INDEX 0x0800
#define IOCTL_SERIAL_QUERY_DEVICE_NAME CTL_CODE(FILE_DEVICE_SERIAL_PORT, IOCTL_INDEX + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SERIAL_QUERY_DEVICE_ATTR CTL_CODE(FILE_DEVICE_SERIAL_PORT, IOCTL_INDEX + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define MAX_BUFFER 256
/*
* Run on prototype Epson printer ? // BUGBUG REMOVE
*/
#define EPSON_PRINTER 0
/*
* BUGBUG
*
* Is it ok to return a partial read buffer, or should we wait
* until the caller's buffer is completely full ?
*/
#define PARTIAL_READ_BUFFERS_OK 1
/*
* This is the default interface class value for interfaces of no defined class.
*/
#define USB_INTERFACE_CLASS_VENDOR 0x0ff
enum deviceState {
STATE_INITIALIZED,
STATE_STARTING,
STATE_STARTED,
STATE_START_FAILED,
STATE_STOPPED, // implies device was previously started successfully
STATE_SUSPENDED,
STATE_REMOVING,
STATE_REMOVED
};
#define DEVICE_EXTENSION_SIGNATURE 'PcsE'
typedef struct endpointInfo {
USBD_PIPE_HANDLE pipeHandle;
ULONG pipeLen;
BOOLEAN endpointIsBusy;
} ENDPOINTINFO;
typedef struct PARENT_FDO_EXTENSION {
/*
* Plug-and-play state of this device object.
*/
enum deviceState state;
PDRIVER_OBJECT driverObj;
/*
* Flag to notify that some special feature needs to be implemented.
*/
ULONG posFlag;
/*
* The device object that this driver created.
*/
PDEVICE_OBJECT functionDevObj;
/*
* The device object created by the next lower driver.
*/
PDEVICE_OBJECT physicalDevObj;
/*
* The device object at the top of the stack that we attached to.
* This is often (but not always) the same as physicalDevObj.
*/
PDEVICE_OBJECT topDevObj;
/*
* deviceCapabilities includes a
* table mapping system power states to device power states.
*/
DEVICE_CAPABILITIES deviceCapabilities;
/*
* pendingActionCount is used to keep track of outstanding actions.
* removeEvent is used to wait until all pending actions are
* completed before complete the REMOVE_DEVICE IRP and let the
* driver get unloaded.
*/
LONG pendingActionCount;
KEVENT removeEvent;
USB_DEVICE_DESCRIPTOR deviceDesc;
PUSB_CONFIGURATION_DESCRIPTOR configDesc;
USBD_CONFIGURATION_HANDLE configHandle;
PUSBD_INTERFACE_INFORMATION interfaceInfo;
KSPIN_LOCK devExtSpinLock;
PDEVICE_RELATIONS deviceRelations;
} PARENTFDOEXT;
/*
* Device extension for a PDO created by this driver.
* A POS PDO represents a single COM (serial) port interface
* which consists of a single input/output endpoint pair on the USB device.
*/
typedef struct POS_PDO_EXTENSION {
enum deviceState state;
PDEVICE_OBJECT pdo;
PARENTFDOEXT *parentFdoExt;
LONG comPortNumber;
UNICODE_STRING pdoName;
UNICODE_STRING symbolicLinkName;
LIST_ENTRY fileExtensionList;
ENDPOINTINFO inputEndpointInfo;
ENDPOINTINFO outputEndpointInfo;
LIST_ENTRY pendingReadIrpsList;
LIST_ENTRY pendingWriteIrpsList;
LIST_ENTRY completedReadPacketsList;
ULONG totalQueuedReadDataLength;
WORK_QUEUE_ITEM writeWorkItem;
WORK_QUEUE_ITEM readWorkItem;
FILE_BASIC_INFORMATION fileBasicInfo;
KSPIN_LOCK devExtSpinLock;
ULONG supportedBauds; // emulation of baud rates for the device
ULONG baudRate; // emulation of current baud rate
ULONG fakeDTRRTS; // emulation of DTR and RTS lines
ULONG fakeRxSize; // emulation of read buffer size
SERIAL_TIMEOUTS fakeTimeouts; // emulation of timeout controls
SERIAL_CHARS specialChars; // emulation of special characters
SERIALPERF_STATS fakePerfStats; // emulation of performance stats
SERIAL_LINE_CONTROL fakeLineControl; // emulation of the line control register
USHORT fakeLineStatus; // emulation of line status register
USHORT fakeModemStatus; // emulation of modem status register
LIST_ENTRY pendingWaitIrpsList; // queue of WAIT_ON_MASK irps
ULONG waitMask; // mask of events to be waited upon
ULONG currentMask; // mask of events that have occured
#if !STATUS_ENDPOINT
USB_DEVICE_DESCRIPTOR dummyPacket; // we simply get the desciptor for now
#endif
USHORT statusPacket; // buffer to read the status endpoint
URB statusUrb; // urb to read the status endpoint
ENDPOINTINFO statusEndpointInfo; // stores info about the status endpoint
} POSPDOEXT;
typedef struct DEVICE_EXTENSION {
/*
* Memory signature of a device extension, for debugging.
*/
ULONG signature;
BOOLEAN isPdo;
union {
PARENTFDOEXT parentFdoExt;
POSPDOEXT pdoExt;
};
} DEVEXT;
typedef struct fileExtension {
ULONG signature;
PFILE_OBJECT fileObject;
LIST_ENTRY listEntry;
} FILEEXT;
typedef struct readPacket {
#define READPACKET_SIG 'tPdR'
ULONG signature;
PUCHAR data;
ULONG length;
ULONG offset; // offset of first byte not yet returned to client
PVOID context;
PURB urb;
LIST_ENTRY listEntry;
} READPACKET;
#define NO_STATUS 0x80000000
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
/*
* Memory tag for memory blocks allocated by this driver
* (used in ExAllocatePoolWithTag() call).
* This DWORD appears as "Filt" in a little-endian memory byte dump.
*/
#define ESCPOS_TAG (ULONG)'UsoP'
#define ALLOCPOOL(pooltype, size) ExAllocatePoolWithTag(pooltype, size, ESCPOS_TAG)
#define FREEPOOL(ptr) ExFreePool(ptr)
/*
* Function prototypes
*/
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
NTSTATUS AddDevice(IN PDRIVER_OBJECT driverObj, IN PDEVICE_OBJECT pdo);
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS Dispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS FDO_PnP(PARENTFDOEXT *parentFdoExt, PIRP irp);
NTSTATUS FDO_Power(PARENTFDOEXT *parentFdoExt, PIRP irp);
NTSTATUS FDO_PowerComplete(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context);
NTSTATUS GetDeviceCapabilities(PARENTFDOEXT *parentFdoExt);
NTSTATUS CallNextDriverSync(PARENTFDOEXT *parentFdoExt, PIRP irp);
NTSTATUS CallDriverSync(PDEVICE_OBJECT devObj, PIRP irp);
NTSTATUS CallDriverSyncCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID Context);
VOID IncrementPendingActionCount(PARENTFDOEXT *parentFdoExt);
VOID DecrementPendingActionCount(PARENTFDOEXT *parentFdoExt);
NTSTATUS InitUSB(PARENTFDOEXT *parentFdoExt);
NTSTATUS GetConfigDescriptor(PARENTFDOEXT *parentFdoExt);
NTSTATUS GetDeviceDescriptor(PARENTFDOEXT *parentFdoExt);
NTSTATUS SubmitUrb(PDEVICE_OBJECT pdo, PURB urb, BOOLEAN synchronous, PVOID completionRoutine, PVOID completionContext);
NTSTATUS OpenComPort(POSPDOEXT *pdoExt, PIRP irp);
NTSTATUS CloseComPort(POSPDOEXT *pdoExt, PIRP irp);
NTSTATUS WriteComPort(POSPDOEXT *pdoExt, PIRP irp);
NTSTATUS ReadComPort(POSPDOEXT *pdoExt, PIRP irp);
NTSTATUS CreateSymbolicLink(POSPDOEXT *pdoExt);
NTSTATUS DestroySymbolicLink(POSPDOEXT *pdoExt);
PWCHAR CreateChildPdoName(PARENTFDOEXT *parentFdoExt, ULONG portNumber);
NTSTATUS CreateCOMPdo(PARENTFDOEXT *parentFdoExt, ULONG comInterfaceIndex, ENDPOINTINFO *inputEndpointInfo, ENDPOINTINFO *outputEndpointInfo, ENDPOINTINFO *statusEndpointInfo);
PDEVICE_RELATIONS CopyDeviceRelations(PDEVICE_RELATIONS deviceRelations);
NTSTATUS QueryDeviceRelations(PARENTFDOEXT *parentFdoExt, PIRP irp);
PVOID MemDup(PVOID dataPtr, ULONG length);
NTSTATUS PDO_PnP(POSPDOEXT *pdoExt, PIRP irp);
NTSTATUS QueryPdoID(POSPDOEXT *pdoExt, PIRP irp);
NTSTATUS ReadPipe(PARENTFDOEXT *parentFdoExt, USBD_PIPE_HANDLE pipeHandle, READPACKET *readPacket, BOOLEAN synchronous);
NTSTATUS ReadPipeCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context);
NTSTATUS WritePipe(PARENTFDOEXT *parentFdoExt, USBD_PIPE_HANDLE pipeHandle, PUCHAR data, ULONG dataLen);
NTSTATUS SelectConfiguration(PARENTFDOEXT *parentFdoExt);
NTSTATUS CleanupIO(POSPDOEXT *pdoExt, PIRP irp);
NTSTATUS QueryInfo(POSPDOEXT *pdoExt, PIRP irp);
NTSTATUS SetInfo(POSPDOEXT *pdoExt, PIRP irp);
NTSTATUS FlushBuffers(POSPDOEXT *pdoExt);
NTSTATUS Ioctl(POSPDOEXT *pdoExt, PIRP irp);
NTSTATUS InternalIoctl(POSPDOEXT *pdoExt, PIRP irp);
NTSTATUS SubstituteOneBusName(PWCHAR hwId);
NTSTATUS SubstituteBusNames(PWCHAR busNames);
ULONG WStrLen(PWCHAR str);
LONG WStrNCmpI(PWCHAR s1, PWCHAR s2, ULONG n);
VOID WorkItemCallback_Write(PVOID context);
VOID WorkItemCallback_Read(PVOID context);
VOID WriteCancelRoutine(PDEVICE_OBJECT devObj, PIRP irp);
NTSTATUS EnqueueReadIrp(POSPDOEXT *pdoExt, PIRP irp, BOOLEAN enqueueAtFront, BOOLEAN lockHeld);
PIRP DequeueReadIrp(POSPDOEXT *pdoExt, BOOLEAN lockHeld);
VOID ReadCancelRoutine(PDEVICE_OBJECT devObj, PIRP irp);
VOID IssueReadForClient(POSPDOEXT *pdoExt);
VOID SatisfyPendingReads(POSPDOEXT *pdoExt);
READPACKET* AllocReadPacket(PVOID data, ULONG dataLen, PVOID context);
VOID FreeReadPacket(READPACKET *readPacket);
LONG GetComPort(PARENTFDOEXT *parentFdoExt, ULONG comInterfaceIndex);
LONG GetFreeComPortNumber();
VOID ReleaseCOMPort(LONG comPortNumber);
void NumToHexString(PWCHAR String, USHORT Number, USHORT stringLen);
void NumToDecString(PWCHAR String, USHORT Number, USHORT stringLen);
ULONG LAtoX(PWCHAR wHexString);
ULONG LAtoD(PWCHAR string);
LONG MyLog(ULONG base, ULONG num);
NTSTATUS CreatePdoForEachEndpointPair(PARENTFDOEXT *parentFdoExt);
NTSTATUS TryWrite(POSPDOEXT *pdoExt, PIRP irp);
BOOLEAN IsWin9x();
PVOID PosMmGetSystemAddressForMdlSafe(PMDL MdlAddress);
VOID DeleteChildPdo(POSPDOEXT *pdoExt);
/*
* Function prototypes for Serial Emulation.
*/
NTSTATUS QuerySpecialFeature(PARENTFDOEXT *parentFdoExt);
VOID InitializeSerEmulVariables(POSPDOEXT *pdoExt);
NTSTATUS EnqueueWaitIrp(POSPDOEXT *pdoExt, PIRP irp);
VOID WaitMaskCancelRoutine(PDEVICE_OBJECT devObj, PIRP irp);
PIRP DequeueWaitIrp(POSPDOEXT *pdoExt);
VOID UpdateMask(POSPDOEXT *pdoExt);
VOID CompletePendingWaitIrps(POSPDOEXT *pdoExt, ULONG mask);
NTSTATUS StatusPipe(POSPDOEXT *pdoExt, USBD_PIPE_HANDLE pipeHandle);
NTSTATUS StatusPipeCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context);
NTSTATUS QueryDeviceName(POSPDOEXT *pdoExt, PIRP irp);
/*
* Externs
*/
extern BOOLEAN isWin9x;