📄 whusb20usb.c
字号:
TRACE1("***** bInterfaceNumber = %x *****", id->bInterfaceNumber);
TRACE1("***** bAlternateSetting = %x *****", id->bAlternateSetting);
TRACE1("***** bNumEndpoints = %x *****", id->bNumEndpoints);
TRACE1("***** bInterfaceClass = %x *****", id->bInterfaceClass);
TRACE1("***** bInterfaceSubClass = %x *****", id->bInterfaceSubClass);
TRACE1("***** bInterfaceProtocol = %x *****", id->bInterfaceProtocol);
TRACE1("***** iInterface = %x *****", id->iInterface);
// Build list of interfaces we are interested in
ilist[0].InterfaceDescriptor = id;
ilist[0].Interface = NULL; // Will point to urb->UrbUsbSelectConfiguration.Interface
ilist[1].InterfaceDescriptor = NULL;
// Create select configuration URB
urb = USBD_CreateConfigurationRequestEx( Descriptors, ilist);
//////In addition to creating a URB, USBD_CreateConfigurationRequestEx()
//////also initializes the "Interface" members of your USBD_INTERFACE_LIST
//////entries to point to USBD_INTERFACE_INFORMATION structures.
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
dx->hWhceb01ConfigurationHandle = urb->UrbSelectConfiguration.ConfigurationHandle;//保存配置句柄
InterfaceInfo = ilist[0].Interface;
dx->hWhceb01InterfaceHandle = InterfaceInfo->InterfaceHandle;//保存接口句柄
dx->Whceb01NumOfPipes = InterfaceInfo->NumberOfPipes;
TRACE1(" ----------InterfaceInfo = %x -------",ilist[0].Interface);
TRACE1(" ----------NumberOfPipes = %x -------",InterfaceInfo->NumberOfPipes);
TRACE1(" ----------ilist[1].InterfaceDescriptor = %x -------",ilist[1].InterfaceDescriptor);
TRACE1(" ----------ilist[1].Interface = %x -------",ilist[1].Interface);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Call the USB driver
for( i = 0 ; i < (dx->Whceb01NumOfPipes) ; i++ )
{
InterfaceInfo->Pipes[i].MaximumTransferSize = 1024*64;//设置最大传输长度为60K
}
TRACE0("Start to Select Configuration");
status = CallUSBDI( dx, urb,IOCTL_INTERNAL_USB_SUBMIT_URB,0);
// Check statuses
if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
{
TRACE0("==========Select Configuration failed!========");
TRACE2("status %x URB status %x", status, urb->UrbHeader.Status);
status = STATUS_UNSUCCESSFUL;
}
else
{
// Select config worked
TRACE0("---------Select Configuration Success --------------");
TRACE0("++++++++++++Get the Handle of pipe++++++++++++++++");
for(i=0;i<(dx->Whceb01NumOfPipes);i++ )
{
PUSBD_PIPE_INFORMATION pi = &InterfaceInfo->Pipes[i];
//通道0 入:0x86 出:0x02
if( ( pi->PipeType == UsbdPipeTypeBulk ) && ( pi->EndpointAddress == 0x86 ) )
dx->hWhceb01InterruptInHandle[0] = pi->PipeHandle;
else if( ( pi->PipeType == UsbdPipeTypeBulk ) && ( pi->EndpointAddress ==0x02 ) )
dx->hWhceb01InterruptOutHandle[0] = pi->PipeHandle;
//通道1 入:0x88 出:0x04
else if( ( pi->PipeType == UsbdPipeTypeBulk ) && ( pi->EndpointAddress == 0x88 ) )
dx->hWhceb01InterruptInHandle[1] = pi->PipeHandle;
else if( ( pi->PipeType == UsbdPipeTypeBulk ) && ( pi->EndpointAddress == 0x04 ) )
dx->hWhceb01InterruptOutHandle[1] = pi->PipeHandle;
TRACE5("Pipes[%d] : MaximumPacketSize %d EndpointAddress 0x%2x Interval %dms PipeType %d ",
i, pi->MaximumPacketSize, pi->EndpointAddress, pi->Interval, pi->PipeType );
TRACE1(" MaximumTransferSize %d", pi->MaximumTransferSize);
}
}
TRACE1 ("Configuration Handle = %x", dx->hWhceb01ConfigurationHandle);
TRACE1 ("Interface Handle = %x", dx->hWhceb01InterfaceHandle);
TRACE1 ("Pipe Num = %d", dx->Whceb01NumOfPipes);
TRACE1 ("InterruptIn Handle = %x", dx->hWhceb01InterruptInHandle[0]);
TRACE1 ("InterruptOut Handle = %x", dx->hWhceb01InterruptOutHandle[0]);
TRACE1 ("-----hWhceb01InterruptInHandle = %x", dx->hWhceb01InterruptInHandle[1]);
TRACE1 ("-----hWhceb01InterruptOutHandle = %x", dx->hWhceb01InterruptOutHandle[1]);
FreeIfAllocated(urb);
FreeIfAllocated( Descriptors );
return status;
}
/////////////////////////////////////////////////////////////////////////////
// UsbDeselectConfiguration: Turn off device by selecting no configuration
NTSTATUS UsbDeselectConfiguration( IN PWHCEB01_DEVICE_EXTENSION dx)
{
NTSTATUS status ;
USHORT UrbSize = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
PURB urb ;
ULONG i = 0;
urb = (PURB)ExAllocatePool(NonPagedPool, UrbSize);
for( i = 0 ; i < MAX_CHANNEL ; i ++ )
{
dx->hWhceb01InterruptInHandle[i] = NULL ;
dx->hWhceb01InterruptOutHandle[i] = NULL;
dx->ChannelisUsed[i] = FALSE;
}
// Allocate memory for URB
if( urb==NULL)
{
TRACE0("No URB memory");
return STATUS_INSUFFICIENT_RESOURCES;
}
// Build select configuration URB with NULL Config descriptor
UsbBuildSelectConfigurationRequest( urb, UrbSize, NULL);
// Call the USB driver
TRACE0("Deselecting configuration");
status = CallUSBDI( dx, urb,IOCTL_INTERNAL_USB_SUBMIT_URB,0);
// Check statuses
if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
{
TRACE2("status %x URB status %x", status, urb->UrbHeader.Status);
status = STATUS_UNSUCCESSFUL;
}
ExFreePool(urb);
return status;
}
/////////////////////////////////////////////////////////////////////////////
// UsbDoInterruptTransfer: Wait for non-zero 8 byte input report, or timeout
NTSTATUS UsbDoInterruptTransfer( IN PWHCEB01_DEVICE_EXTENSION dx, IN PVOID UserBuffer, ULONG* UserBufferSize)
{
ULONG InputBufferSize = *UserBufferSize;
NTSTATUS status = STATUS_SUCCESS;
ULONG OutputBufferSize = 8;
USHORT UrbSize = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
PURB urb ;
LARGE_INTEGER StartTickCount;
ULONG UnitsOf100ns ;
*UserBufferSize = 0;
// Check we're selected
if( dx->hWhceb01PipeHandle==NULL)
return STATUS_INVALID_HANDLE;
// Check input parameters
//liusf modified
if( UserBuffer==NULL || InputBufferSize<8)
return STATUS_INVALID_PARAMETER;
// Keyboard input reports are always 8 bytes long
// Allocate memory for URB
urb = (PURB)ExAllocatePool(NonPagedPool, UrbSize);
if( urb==NULL)
{
// DebugPrintMsg("No URB memory");
return STATUS_INSUFFICIENT_RESOURCES;
}
// Remember when we started
// Get start tick count and length of tick in 100ns units
KeQueryTickCount( &StartTickCount);
UnitsOf100ns = KeQueryTimeIncrement();
// DebugPrint("Time increment %d", UnitsOf100ns);
// Loop until non-zero report read, error, bad length, or timed out
// DebugPrintMsg("Reading Interrupt data");
while( TRUE )
{
LARGE_INTEGER TickCountNow;
ULONG ticks ;
__int64* pData;
// Build Do Bulk or Interrupt transfer request
UsbBuildInterruptOrBulkTransferRequest(
urb, UrbSize,
dx->hWhceb01PipeHandle,
UserBuffer, NULL, OutputBufferSize,
USBD_TRANSFER_DIRECTION_IN,
NULL);
// Call the USB driver
status = CallUSBDI( dx, urb,IOCTL_INTERNAL_USB_SUBMIT_URB,0);
// Check statuses
if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
{
// DebugPrint("status %x URB status %x", status, urb->UrbHeader.Status);
status = STATUS_UNSUCCESSFUL;
break;
}
// Give up if count of bytes transferred was not 8
//liusf modified
if( urb->UrbBulkOrInterruptTransfer.TransferBufferLength!=OutputBufferSize)
break;
// If data non-zero then exit as we have a keypress
pData = (__int64 *)UserBuffer;
if( *pData!=0i64)
{
// DebugPrint("Got some data");
break;
}
// Check for timeout
KeQueryTickCount( &TickCountNow);
ticks = (ULONG)(TickCountNow.QuadPart - StartTickCount.QuadPart);
if( ticks*UnitsOf100ns/10000000 >= dx->UsbTimeout)
{
TRACE1("Timeout %d 100ns", ticks*UnitsOf100ns);
status = STATUS_NO_MEDIA_IN_DEVICE;
break;
}
}
*UserBufferSize = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
// DebugPrint("Transfer length %d", urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
if( NT_SUCCESS(status))
{
PUCHAR bd = (PUCHAR)UserBuffer;
// DebugPrint("Transfer data %2x %2x %2x %2x %2x %2x %2x %2x",
// bd[0], bd[1], bd[2], bd[3], bd[4], bd[5], bd[6], bd[7]);
}
ExFreePool(urb);
return status;
}
/////////////////////////////////////////////////////////////////////////////
// UsbGetStatuses: Get device, interface and endpoint statuses
NTSTATUS UsbGetStatuses( IN PWHCEB01_DEVICE_EXTENSION dx,
OUT PUCHAR Statuses,
IN ULONG Size)
{
USHORT UrbSize = sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST);
PURB urb;
NTSTATUS status ;
// Input buffer must have 2 bytes for each status
if( Size!=6)
return STATUS_INVALID_PARAMETER;
// Allocate memory for URB
urb = (PURB)ExAllocatePool(NonPagedPool, UrbSize);
if( urb==NULL)
{
// DebugPrintMsg("No URB memory");
return STATUS_INSUFFICIENT_RESOURCES;
}
/////////////////////////////////////////////////////////////////////////
// Build URB to get device status
UsbBuildGetStatusRequest(
urb,
URB_FUNCTION_GET_STATUS_FROM_DEVICE, 0, // Op and Index
Statuses, NULL, // Transfer buffer
NULL); // Link URB
// Call the USB driver
// DebugPrintMsg("Getting device status");
status = CallUSBDI( dx, urb,IOCTL_INTERNAL_USB_SUBMIT_URB,0);
// Check statuses
if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
{
// DebugPrint("status %x URB status %x", status, urb->UrbHeader.Status);
status = STATUS_UNSUCCESSFUL;
goto fail;
}
Size = urb->UrbControlGetStatusRequest.TransferBufferLength;
if( Size!=2) goto fail;
/////////////////////////////////////////////////////////////////////////
// Build URB to get interface status
UsbBuildGetStatusRequest(
urb,
URB_FUNCTION_GET_STATUS_FROM_INTERFACE, 0, // Op and Index
Statuses+2, NULL, // Transfer buffer
NULL); // Link URB
// Call the USB driver
// DebugPrintMsg("Getting interface status");
status = CallUSBDI( dx, urb,IOCTL_INTERNAL_USB_SUBMIT_URB,0);
// Check statuses
if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
{
// DebugPrint("status %x URB status %x", status, urb->UrbHeader.Status);
status = STATUS_UNSUCCESSFUL;
goto fail;
}
Size = urb->UrbControlGetStatusRequest.TransferBufferLength;
if( Size!=2) goto fail;
/////////////////////////////////////////////////////////////////////////
// Build URB to get endpoint status
UsbBuildGetStatusRequest(
urb,
URB_FUNCTION_GET_STATUS_FROM_ENDPOINT, 0, // Op and Index
Statuses+4, NULL, // Transfer buffer
NULL); // Link URB
// Call the USB driver
// DebugPrintMsg("Getting endpoint status");
status = CallUSBDI( dx, urb,IOCTL_INTERNAL_USB_SUBMIT_URB,0);
// Check statuses
if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
{
// DebugPrint("status %x URB status %x", status, urb->UrbHeader.Status);
status = STATUS_UNSUCCESSFUL;
goto fail;
}
Size = urb->UrbControlGetStatusRequest.TransferBufferLength;
if( Size!=2) goto fail;
/////////////////////////////////////////////////////////////////////////
fail:
ExFreePool(urb);
return status;
}
/////////////////////////////////////////////////////////////////////////////
// UsbGetFrameInfo: Get current frame length and two frame numbers
NTSTATUS UsbGetFrameInfo( IN PWHCEB01_DEVICE_EXTENSION dx,
OUT ULONG* FrameLength,
OUT ULONG* FrameNumber,
OUT ULONG* FrameAlterNumber)
{
// Allocate memory for URB
USHORT UrbSize = sizeof(struct _URB_GET_FRAME_LENGTH);
PURB urb;
NTSTATUS status;
if( sizeof(struct _URB_GET_CURRENT_FRAME_NUMBER)>UrbSize)
UrbSize = sizeof(struct _URB_GET_CURRENT_FRAME_NUMBER);
urb = (PURB)ExAllocatePool(NonPagedPool, UrbSize);
if( urb==NULL)
{
// DebugPrintMsg("No URB memory");
return STATUS_INSUFFICIENT_RESOURCES;
}
/////////////////////////////////////////////////////////////////////////
// Get current frame number
// Build URB by hand
urb->UrbHeader.Length = UrbSize;
urb->UrbHeader.Function = URB_FUNCTION_GET_CURRENT_FRAME_NUMBER;
// Call the USB driver
// DebugPrintMsg("Getting current frame number");
status = CallUSBDI( dx, urb,IOCTL_INTERNAL_USB_SUBMIT_URB,0);
// Check statuses
if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
{
// DebugPrint("status %x URB status %x", status, urb->UrbHeader.Status);
status = STATUS_UNSUCCESSFUL;
goto fail;
}
*FrameNumber = urb->UrbGetCurrentFrameNumber.FrameNumber;
// DebugPrint("FrameNumber %d", FrameNumber);
/////////////////////////////////////////////////////////////////////////
// Get current frame length and frame number when length can be altered
// Build URB by hand
urb->UrbHeader.Length = UrbSize;
urb->UrbHeader.Function = URB_FUNCTION_GET_FRAME_LENGTH;
// Call the USB driver
// DebugPrintMsg("Getting frame info");
status = CallUSBDI( dx, urb,IOCTL_INTERNAL_USB_SUBMIT_URB,0);
// Check statuses
if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
{
// DebugPrint("status %x URB status %x", status, urb->UrbHeader.Status);
status = STATUS_UNSUCCESSFUL;
}
// Store info
*FrameLength = urb->UrbGetFrameLength.FrameLength;
*FrameAlterNumber = urb->UrbGetFrameLength.FrameNumber;
DebugPrint("FrameLength %d FrameAlterNumber %d", FrameLength, FrameAlterNumber);
fail:
ExFreePool(urb);
return status;
}
/////////////////////////////////////////////////////////////////////////////
// UsbSendOutputReport: Send one byte as a SET_REPORT control transfer
const UCHAR SET_REPORT = 0x09;
NTSTATUS UsbSendOutputReport( IN PWHCEB01_DEVICE_EXTENSION dx, IN UCHAR OutputData)
{
// Allocate memory for URB
USHORT UrbSize = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -