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