/*++ 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;