windows-nt/Source/XPSP1/NT/net/rndis/usb8023/usb8023.h
2020-09-26 16:20:57 +08:00

430 lines
13 KiB
C

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
usb8023.h
Author:
ervinp
Environment:
Kernel mode
Revision History:
--*/
/*
* If this flag is defined TRUE, then when an endpoint on the device stalls,
* we will do a full USB port reset
* and then restore the device to a running state.
* Otherwise, we just send the RNDIS Reset message to the control pipe.
*/
#define DO_FULL_RESET TRUE
#define DRIVER_SIG '208U'
#define GUARD_WORD 'draG'
#define NUM_BYTES_PROTOCOL_RESERVED_SECTION 16
#define DEFAULT_MULTICAST_SIZE 16
/*
* Total number of our irp/urb packets for sending/receiving
* ethernet frames to/from the device.
*/
#define USB_PACKET_POOL_SIZE 32
#define PACKET_BUFFER_SIZE 0x4000
/*
* The USB host controller can typically schedule 2 URBs at a time.
* To keep the hardware busy, keep twice this many read URBs in the pipe.
*/
#define NUM_READ_PACKETS (2*2)
/*
* - Ethernet 14-byte Header
*/
#define ETHERNET_ADDRESS_LENGTH 6
#pragma pack(1)
typedef struct {
UCHAR Destination[ETHERNET_ADDRESS_LENGTH];
UCHAR Source[ETHERNET_ADDRESS_LENGTH];
USHORT TypeLength; // note: length appears as big-endian in packet.
} ETHERNET_HEADER;
#pragma pack()
#define MINIMUM_ETHERNET_PACKET_SIZE 60 // from e100bex driver
#define MAXIMUM_ETHERNET_PACKET_SIZE (1500+sizeof(ETHERNET_HEADER)) // 1514 == 0x05EA
/*
* This is the size of a read on the control pipe.
* It needs to be large enough for the init-complete message and response to
* OID_GEN_SUPPORTED_LIST.
*/
#define MAXIMUM_DEVICE_MESSAGE_SIZE 0x400
typedef struct {
ULONG sig;
LIST_ENTRY adaptersListEntry;
KSPIN_LOCK adapterSpinLock;
PDEVICE_OBJECT physDevObj;
PDEVICE_OBJECT nextDevObj;
/*
* All USB structures and handles must be declared as neutral types in order
* to compile with the NDIS/RNDIS sources.
*/
PVOID deviceDesc; // PUSB_DEVICE_DESCRIPTOR
PVOID configDesc; // PUSB_CONFIGURATION_DESCRIPTOR
PVOID configHandle; // USBD_CONFIGURATION_HANDLE
PVOID interfaceInfo; // PUSBD_INTERFACE_INFORMATION
PVOID interfaceInfoMaster; // PUSBD_INTERFACE_INFORMATION
BOOLEAN initialized;
BOOLEAN halting;
BOOLEAN resetting;
BOOLEAN gotPacketFilterIndication;
PVOID readPipeHandle; // USBD_PIPE_HANDLE
PVOID writePipeHandle; // USBD_PIPE_HANDLE
PVOID notifyPipeHandle; // USBD_PIPE_HANDLE
ULONG readPipeLength;
ULONG writePipeLength;
ULONG notifyPipeLength;
UCHAR readPipeEndpointAddr;
UCHAR writePipeEndpointAddr;
UCHAR notifyPipeEndpointAddr;
LIST_ENTRY usbFreePacketPool; // free packet pool
LIST_ENTRY usbPendingReadPackets; // reads down in the USB stack
LIST_ENTRY usbPendingWritePackets; // writes down in the usb stack
LIST_ENTRY usbCompletedReadPackets; // completed read buffers being indicated to NDIS
/*
* Keep statistics on packet states for throttling, etc.
* Some fields are used only to provide history for debugging,
* and we want these for retail as well as debug version.
*/
ULONG numFreePackets;
ULONG numActiveReadPackets;
ULONG numActiveWritePackets;
ULONG numIndicatedReadPackets;
ULONG numHardResets;
ULONG numSoftResets;
ULONG numConsecutiveReadFailures;
PVOID notifyIrpPtr;
PVOID notifyUrbPtr;
PUCHAR notifyBuffer;
ULONG notifyBufferCurrentLength;
BOOLEAN notifyStopped;
BOOLEAN cancellingNotify;
KEVENT notifyCancelEvent;
/*
* All NDIS handles must be declared as neutral types
* in order to compile with the USB sources.
*/
PVOID ndisAdapterHandle;
PVOID rndisAdapterHandle; // RNDIS_HANDLE
ULONG rndismpMajorVersion;
ULONG rndismpMinorVersion;
ULONG rndismpMaxTransferSize;
ULONG currentPacketFilter;
UCHAR MAC_Address[ETHERNET_ADDRESS_LENGTH];
ULONG dbgCurrentOid;
ULONG readDeficit;
PIO_WORKITEM ioWorkItem;
BOOLEAN workItemOrTimerPending;
KEVENT workItemOrTimerEvent;
KTIMER backoffTimer;
KDPC backoffTimerDPC;
ULONG readReentrancyCount; // used to prevent infinite loop in ReadPipeCompletion()
#if DO_FULL_RESET
BOOLEAN needFullReset;
#endif
#if DBG
BOOLEAN dbgInLowPacketStress;
#endif
#ifdef RAW_TEST
BOOLEAN rawTest;
#endif
} ADAPTEREXT;
typedef struct {
ULONG sig;
LIST_ENTRY listEntry;
/*
* All WDM and USB structures must be declared as neutral types
* in order to compile with the NDIS/RNDIS sources.
*/
PVOID irpPtr; // PIRP
PVOID urbPtr; // PURB
PUCHAR dataBuffer;
ULONG dataBufferMaxLength; // Actual size of the data buffer
ULONG dataBufferCurrentLength; // Length of data currently in buffer
PMDL dataBufferMdl; // MDL for this packet's dataBuffer
PMDL ndisSendPktMdl; // Pointer to NDIS' MDL for a packet being sent.
ULONG packetId;
ADAPTEREXT *adapter;
BOOLEAN cancelled;
KEVENT cancelEvent;
PVOID rndisMessageHandle; // RNDIS_HANDLE
#ifdef RAW_TEST
BOOLEAN dataPacket;
ULONG rcvDataOffset;
ULONG rcvByteCount;
#endif
#if DBG
ULONG timeStamp; // Time placed in current queue.
#endif
} USBPACKET;
#define USB_DEVICE_CLASS_CDC 0x02
#define USB_DEVICE_CLASS_DATA 0x0A
/*
* Formats of CDC functional descriptors
*/
#pragma pack(1)
struct cdcFunctionDescriptor_CommonHeader {
UCHAR bFunctionLength;
UCHAR bDescriptorType;
UCHAR bDescriptorSubtype;
// ...
};
struct cdcFunctionDescriptor_Ethernet {
UCHAR bFunctionLength;
UCHAR bDescriptorType;
UCHAR bDescriptorSubtype;
UCHAR iMACAddress; // string index of MAC Address string
ULONG bmEthernetStatistics;
USHORT wMaxSegmentSize;
USHORT wNumberMCFilters;
UCHAR bNumberPowerFilters;
};
#pragma pack()
#define CDC_REQUEST_SET_ETHERNET_PACKET_FILTER 0x43
#define CDC_ETHERNET_PACKET_TYPE_PROMISCUOUS (1 << 0)
#define CDC_ETHERNET_PACKET_TYPE_ALL_MULTICAST (1 << 1)
#define CDC_ETHERNET_PACKET_TYPE_DIRECTED (1 << 2)
#define CDC_ETHERNET_PACKET_TYPE_BROADCAST (1 << 3)
#define CDC_ETHERNET_PACKET_TYPE_MULTICAST_ENUMERATED (1 << 4)
enum notifyRequestType {
CDC_NOTIFICATION_NETWORK_CONNECTION = 0x00,
CDC_NOTIFICATION_RESPONSE_AVAILABLE = 0x01,
CDC_NOTIFICATION_AUX_JACK_HOOK_STATE = 0x08,
CDC_NOTIFICATION_RING_DETECT = 0x09,
CDC_NOTIFICATION_SERIAL_STATE = 0x20,
CDC_NOTIFICATION_CALL_STATE_CHANGE = 0x28,
CDC_NOTIFICATION_LINE_STATE_CHANGE = 0x29,
CDC_NOTIFICATION_CONNECTION_SPEED_CHANGE = 0x2A
};
#define CDC_RNDIS_NOTIFICATION 0xA1
#define CDC_RNDIS_RESPONSE_AVAILABLE 0x01
#pragma pack(1)
struct cdcNotification_CommonHeader {
UCHAR bmRequestType;
UCHAR bNotification;
USHORT wValue;
USHORT wIndex;
USHORT wLength;
UCHAR data[0];
};
#pragma pack()
/*
*
****************************************************************************
*/
/*
****************************************************************************
*
* Native RNDIS codes
*
*/
#define NATIVE_RNDIS_SEND_ENCAPSULATED_COMMAND 0x00
#define NATIVE_RNDIS_GET_ENCAPSULATED_RESPONSE 0x01
#define NATIVE_RNDIS_RESPONSE_AVAILABLE 0x01
/*
*
****************************************************************************
*/
#define MAX(a, b) (((a) >= (b)) ? (a) : (b))
#define MIN(a, b) (((a) <= (b)) ? (a) : (b))
#ifndef EXCEPTION_NONCONTINUABLE_EXCEPTION
// from winbase.h
#define EXCEPTION_NONCONTINUABLE_EXCEPTION STATUS_NONCONTINUABLE_EXCEPTION
#endif
// from ntos\inc\ex.h
NTKERNELAPI VOID NTAPI ExRaiseException(PEXCEPTION_RECORD ExceptionRecord);
/*
* Function prototypes
*/
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
ADAPTEREXT *NewAdapter(PDEVICE_OBJECT pdo);
VOID FreeAdapter(ADAPTEREXT *adapter);
VOID EnqueueAdapter(ADAPTEREXT *adapter);
VOID DequeueAdapter(ADAPTEREXT *adapter);
VOID HaltAdapter(ADAPTEREXT *adapter);
PVOID AllocPool(ULONG size);
VOID FreePool(PVOID ptr);
PVOID MemDup(PVOID dataPtr, ULONG length);
VOID DelayMs(ULONG numMillisec);
BOOLEAN GetRegValue(ADAPTEREXT *adapter, PWCHAR wValueName, OUT PULONG valuePtr, BOOLEAN hwKey);
BOOLEAN SetRegValue(ADAPTEREXT *adapter, PWCHAR wValueName, ULONG newValue, BOOLEAN hwKey);
VOID ByteSwap(PUCHAR buf, ULONG len);
BOOLEAN AllocateCommonResources(ADAPTEREXT *adapter);
VOID MyInitializeMdl(PMDL mdl, PVOID buf, ULONG bufLen);
PVOID GetSystemAddressForMdlSafe(PMDL MdlAddress);
ULONG CopyMdlToBuffer(PUCHAR buf, PMDL mdl, ULONG bufLen);
ULONG GetMdlListTotalByteCount(PMDL mdl);
BOOLEAN InitUSB(ADAPTEREXT *adapter);
NTSTATUS GetDeviceDescriptor(ADAPTEREXT *adapter);
NTSTATUS GetConfigDescriptor(ADAPTEREXT *adapter);
NTSTATUS SelectConfiguration(ADAPTEREXT *adapter);
NTSTATUS FindUSBPipeHandles(ADAPTEREXT *adapter);
VOID StartUSBReadLoop(ADAPTEREXT *adapter);
VOID TryReadUSB(ADAPTEREXT *adapter);
USBPACKET *NewPacket(ADAPTEREXT *adapter);
VOID FreePacket(USBPACKET *packet);
VOID EnqueueFreePacket(USBPACKET *packet);
USBPACKET *DequeueFreePacket(ADAPTEREXT *adapter);
VOID EnqueuePendingReadPacket(USBPACKET *packet);
VOID DequeuePendingReadPacket(USBPACKET *packet);
VOID EnqueuePendingWritePacket(USBPACKET *packet);
VOID DequeuePendingWritePacket(USBPACKET *packet);
VOID EnqueueCompletedReadPacket(USBPACKET *packet);
VOID DequeueCompletedReadPacket(USBPACKET *packet);
VOID CancelAllPendingPackets(ADAPTEREXT *adapter);
NTSTATUS SubmitUSBReadPacket(USBPACKET *packet);
NTSTATUS SubmitUSBWritePacket(USBPACKET *packet);
NTSTATUS SubmitNotificationRead(ADAPTEREXT *adapter, BOOLEAN synchronous);
NTSTATUS SubmitPacketToControlPipe(USBPACKET *packet, BOOLEAN synchronous, BOOLEAN simulated);
BOOLEAN RegisterRNDISMicroport(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
VOID IndicateSendStatusToRNdis(USBPACKET *packet, NTSTATUS status);
NTSTATUS KLSIWeirdInit(ADAPTEREXT *adapter);
BOOLEAN KLSIStagePartialPacket(ADAPTEREXT *adapter, USBPACKET *packet);
NTSTATUS KLSISetEthernetPacketFilter(ADAPTEREXT *adapter, USHORT packetFilterMask);
VOID RNDISProcessNotification(ADAPTEREXT *adapter);
NTSTATUS IndicateRndisMessage(USBPACKET *packet, BOOLEAN bIsData);
#ifdef RAW_TEST
PMDL AddDataHeader(IN PMDL pMessageMdl);
VOID FreeDataHeader(IN USBPACKET * packet);
VOID SkipRcvRndisPacketHeader(IN USBPACKET * packet);
VOID UnskipRcvRndisPacketHeader(IN USBPACKET * packet);
#endif
NTSTATUS ReadPacketFromControlPipe(USBPACKET *packet, BOOLEAN synchronous);
VOID AdapterFullResetAndRestore(ADAPTEREXT *adapter);
NTSTATUS GetUSBPortStatus(ADAPTEREXT *adapter, PULONG portStatus);
NTSTATUS ResetPipe(ADAPTEREXT *adapter, PVOID pipeHandle);
NTSTATUS AbortPipe(ADAPTEREXT *adapter, PVOID pipeHandle);
NTSTATUS SimulateRNDISHalt(ADAPTEREXT *adapter);
NTSTATUS SimulateRNDISInit(ADAPTEREXT *adapter);
NTSTATUS SimulateRNDISSetPacketFilter(ADAPTEREXT *adapter);
NTSTATUS SimulateRNDISSetCurrentAddress(ADAPTEREXT *adapter);
VOID ServiceReadDeficit(ADAPTEREXT *adapter);
VOID QueueAdapterWorkItem(ADAPTEREXT *adapter);
VOID AdapterWorkItemCallback(IN PDEVICE_OBJECT devObj, IN PVOID context);
VOID BackoffTimerDpc(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
VOID ProcessWorkItemOrTimerCallback(ADAPTEREXT *adapter);
/*
* The Win98SE kernel does not expose IoWorkItems, so implement them internally.
* This introduces a slight race condition on unload, but there is no fix without externally-implemented workitems.
*/
#if SPECIAL_WIN98SE_BUILD
typedef struct _IO_WORKITEM {
WORK_QUEUE_ITEM WorkItem;
PIO_WORKITEM_ROUTINE Routine;
PDEVICE_OBJECT DeviceObject;
PVOID Context;
#if DBG
ULONG Size;
#endif
} IO_WORKITEM, *PIO_WORKITEM;
PIO_WORKITEM MyIoAllocateWorkItem(PDEVICE_OBJECT DeviceObject);
VOID MyIoFreeWorkItem(PIO_WORKITEM IoWorkItem);
VOID MyIoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context);
VOID MyIopProcessWorkItem(IN PVOID Parameter);
#endif
/*
* Externs
*/
extern LIST_ENTRY allAdaptersList;
extern KSPIN_LOCK globalSpinLock;