📄 usbmsc.c
字号:
RegVal[0].Name = DLL_SZ;
RegVal[0].Type = REG_SZ;
RegVal[0].Size = MAX_DLL_LEN;
RegVal[0].Data = (PUCHAR)wsDriverName;
if ( !GetSetKeyValues( wsSubClassRegKey,
&RegVal[0],
GET,
FALSE ) ) {
if (0xFF == bTempInterfaceSubClass) {
// retry using SCSI
DEBUGMSG( ZONE_WARN, (TEXT("Retry SubClass:0x%x with 0x%x\n"), bInterfaceSubClass, USBMSC_SUBCLASS_SCSI));
bTempInterfaceSubClass = bInterfaceSubClass;
bInterfaceSubClass = USBMSC_SUBCLASS_SCSI;
goto _retryDefault;
} else {
DEBUGMSG( ZONE_ERR, (TEXT("GetSetKeyValues failed!\n")));
bRc = FALSE;
break;
}
}
if (0xFF != bTempInterfaceSubClass) {
bInterfaceSubClass = bTempInterfaceSubClass;
}
pUsbDevice->hDiskDriver = LoadDriver( wsDriverName );
if ( !pUsbDevice->hDiskDriver ) {
DEBUGMSG( ZONE_ERR, (TEXT("LoadDriver error:%d on %s\n"), GetLastError(), wsDriverName ));
bRc = FALSE;
break;
}
pUsbDevice->Index = InterlockedIncrement(&g_NumDevices);
//
// get DiskAttach
//
DiskAttach = (PUSBDISK_ATTACH)GetProcAddress( pUsbDevice->hDiskDriver, TEXT("UsbDiskAttach") );
if ( !DiskAttach ) {
DEBUGMSG( ZONE_ERR, (TEXT("GetProcAddress error:%d on %s\n"), GetLastError(), wsDriverName ));
bRc = FALSE;
break;
}
//
// Save DiskDetach callback & Context to call when we get the device Notify
//
pUsbDevice->DiskDetach = (PUSBDISK_DETACH)GetProcAddress( pUsbDevice->hDiskDriver, TEXT("UsbDiskDetach") );
if ( !pUsbDevice->DiskDetach ) {
DEBUGMSG( ZONE_ERR, (TEXT("GetProcAddress error:%d on %s\n"), GetLastError(), wsDriverName ));
bRc = FALSE;
break;
}
//
// register for USB callbacks
//
bRc = UsbFuncs->lpRegisterNotificationRoutine( hDevice,
UsbDeviceNotify,
pUsbDevice );
if ( !bRc ) {
DEBUGMSG( ZONE_ERR, (TEXT("RegisterNotificationRoutine error:%d\n"), GetLastError() ));
break;
}
// signal we can take I/O
pUsbDevice->Flags.AcceptIo = TRUE;
//
// Call the driver's DiskAttach.
// DiskAttach returns non-null Context on success, else null.
//
for (uiIndex=0;uiIndex<MAX_LUN;uiIndex++)
pUsbDevice->DiskContext[uiIndex]=NULL;
// Get Max LUN.
if (GetMaxLUN(pUsbDevice, &uMaxLun)!=ERROR_SUCCESS)
uMaxLun=1;// Using 1 as default;
pUsbDevice->dwMaxLun= uMaxLun;
ASSERT(pUsbDevice->dwMaxLun>=1);
for (uiIndex=0;uiIndex<uMaxLun;uiIndex++) {
__try {
pUsbDevice->DiskContext[uiIndex]= DiskAttach((HANDLE)pUsbDevice,
wsSubClassRegKey,
(DWORD)uiIndex,
bInterfaceSubClass);
if ( !pUsbDevice->DiskContext[uiIndex] ) {
DEBUGMSG( ZONE_ERR, (TEXT("DiskAttach error:%d on %s\n"), GetLastError(), wsDriverName ));
pUsbDevice->Flags.AcceptIo = FALSE;
bRc = FALSE;
break;
}
} __except ( EXCEPTION_EXECUTE_HANDLER ) {
DEBUGMSG(ZONE_ERR,(TEXT("USBMSC::DiskAttach:EXCEPTION:0x%x\n"), GetExceptionCode()));
TEST_TRAP();
bRc = FALSE;
}
}
} while(0);
if (!bRc) {
//
// If not our device, or error, then clean up
//
RemoveDeviceContext( pUsbDevice );
} else {
*AcceptControl = TRUE;
UsbDeviceTest( pUsbDevice );
}
DEBUGMSG( ZONE_USB_INIT, (TEXT("USBMSC<USBDeviceAttach:%d\n"), *AcceptControl ));
return bRc;
}
//
// Warning: do not assume that the USB stack will call this routine immediately after the device is unplugged.
// It could take some time for it to cleanup and get back to us.
//
BOOL WINAPI
UsbDeviceNotify(
LPVOID lpvNotifyParameter,
DWORD dwCode,
LPDWORD * dwInfo1,
LPDWORD * dwInfo2,
LPDWORD * dwInfo3,
LPDWORD * dwInfo4
)
{
PUSBMSC_DEVICE pUsbDevice = (PUSBMSC_DEVICE)lpvNotifyParameter;
UNREFERENCED_PARAMETER(dwInfo1);
UNREFERENCED_PARAMETER(dwInfo2);
UNREFERENCED_PARAMETER(dwInfo3);
UNREFERENCED_PARAMETER(dwInfo4);
DEBUGMSG( ZONE_USB_INIT, (TEXT("USBMSC>UsbDeviceNotify\n")));
if ( !VALID_CONTEXT( pUsbDevice ) ) {
DEBUGMSG( ZONE_ERR, (TEXT("Invalid Context!\n")));
TEST_TRAP();
return FALSE;
}
switch(dwCode) {
case USB_CLOSE_DEVICE:
DEBUGMSG( ZONE_USB_INIT, (TEXT("USB_CLOSE_DEVICE\n")));
if (pUsbDevice->Flags.AcceptIo) {
//
// set state that we are being removed
// and no longer accepting I/O
//
EnterCriticalSection( &pUsbDevice->Lock );
pUsbDevice->Flags.AcceptIo = FALSE;
pUsbDevice->Flags.DeviceRemoved = TRUE;
LeaveCriticalSection( &pUsbDevice->Lock );
//
// cancel any outstanding I/O
// ...
//
// call the Disk's DiskDetach callback. DiskDetach should be able to cope with NULL Context.
//
__try {
if ( pUsbDevice->DiskDetach ) {
DWORD dwIndex;
for (dwIndex=0;dwIndex<pUsbDevice->dwMaxLun;dwIndex++)
if (pUsbDevice->DiskContext[dwIndex]==NULL ||
!pUsbDevice->DiskDetach(pUsbDevice->DiskContext[dwIndex]) ) {
DEBUGMSG( ZONE_ERR, (TEXT("DiskDetach(Lun=%d) error:%d\n"),dwIndex, GetLastError() ));
}
}
} __except ( EXCEPTION_EXECUTE_HANDLER ) {
DEBUGMSG(ZONE_ERR,(TEXT("USBMSC::DiskDetach:EXCEPTION:0x%x\n"), GetExceptionCode()));
TEST_TRAP();
}
if (0 == InterlockedDecrement(&g_NumDevices) ) {
if ( pUsbDevice->hDiskDriver && !FreeLibrary( pUsbDevice->hDiskDriver) ) {
DEBUGMSG( ZONE_ERR, (TEXT("FreeLibrary error:%d\n"), GetLastError() ));
}
else
pUsbDevice->hDiskDriver=NULL;
}
ASSERT(g_NumDevices >= 0);
} else {
ASSERT(0);
}
//
// finally, cleanup this device context
//
RemoveDeviceContext( pUsbDevice );
return TRUE;
default:
DEBUGMSG( ZONE_ERR, (TEXT("Unhandled code:%d\n"), dwCode));
TEST_TRAP();
break;
}
DEBUGMSG( ZONE_USB_INIT, (TEXT("USBMSC<UsbDeviceNotify\n")));
return FALSE;
}
LPCUSB_INTERFACE
ParseUsbDescriptors(
USB_HANDLE hUsbDevice,
LPCUSB_FUNCS UsbFuncs,
LPCUSB_INTERFACE CurInterface,
LPUSHORT ConfigIndex
)
{
LPCUSB_DEVICE pDevice;
LPCUSB_INTERFACE pUsbInterface;
LPCUSB_INTERFACE pDesiredInterface = NULL;
DWORD dwNumInterfaces;
DWORD dwIndex;
DEBUGMSG( ZONE_USB_INIT, (TEXT("USBMSC>ParseUsbDescriptors\n")));
if ( !hUsbDevice || !UsbFuncs || !CurInterface || !ConfigIndex) {
DEBUGMSG( ZONE_ERR, (TEXT("Invalid parameter\n")));
return NULL;
}
//
// get the descriptors
//
pDevice = UsbFuncs->lpGetDeviceInfo( hUsbDevice );
if ( !pDevice ) {
DEBUGMSG( ZONE_ERR, (TEXT("GetDeviceInfo error:%d\n"), GetLastError() ));
return NULL;
}
DUMP_USB_DEVICE_DESCRIPTOR( pDevice->Descriptor );
DUMP_USB_CONFIGURATION_DESCRIPTOR( pDevice->lpActiveConfig->Descriptor );
// get config index
for ( *ConfigIndex = 0; *ConfigIndex < (USHORT)pDevice->Descriptor.bNumConfigurations; *ConfigIndex++) {
if (pDevice->lpActiveConfig == (pDevice->lpConfigs + *ConfigIndex)) {
DEBUGMSG( ZONE_USB_INIT, (TEXT("ConfigIndex:%d\n"), *ConfigIndex));
break;
}
}
pUsbInterface = pDevice->lpActiveConfig->lpInterfaces;
dwNumInterfaces = pDevice->lpActiveConfig->dwNumInterfaces;
// walk the interfaces searching for best fit
for ( dwIndex = 0; dwIndex < dwNumInterfaces; pUsbInterface++, dwIndex++)
{
DUMP_USB_INTERFACE_DESCRIPTOR( pUsbInterface->Descriptor, dwIndex );
if ( pUsbInterface->Descriptor.bInterfaceNumber == CurInterface->Descriptor.bInterfaceNumber )
{
if ( pUsbInterface->Descriptor.bInterfaceClass == USBMSC_INTERFACE_CLASS &&
((pUsbInterface->Descriptor.bInterfaceSubClass >= USBMSC_SUBCLASS_RBC && pUsbInterface->Descriptor.bInterfaceSubClass <= USBMSC_SUBCLASS_SCSI) || pUsbInterface->Descriptor.bInterfaceSubClass == USBMSC_SUBCLASS_RESERVED) &&
(pUsbInterface->Descriptor.bInterfaceProtocol == USBMSC_INTERFACE_PROTOCOL_CBIT || pUsbInterface->Descriptor.bInterfaceProtocol == USBMSC_INTERFACE_PROTOCOL_CBT || pUsbInterface->Descriptor.bInterfaceProtocol == USBMSC_INTERFACE_PROTOCOL_BOT) )
{
//
// if we do not already have an interface, or the selected Protocol is not Bulk-Only
// (I personally prefer Bulk-Only since it is well defined)
//
if ( !pDesiredInterface || pDesiredInterface->Descriptor.bInterfaceProtocol != USBMSC_INTERFACE_PROTOCOL_BOT)
{
pDesiredInterface = pUsbInterface;
DEBUGMSG( ZONE_USB_INIT, (TEXT("*** Found interface @ index: %d ***\n"), dwIndex));
}
}
}
}
DEBUGMSG( ZONE_USB_INIT, (TEXT("USBMSC<ParseUsbDescriptors:0x%x\n"), pDesiredInterface ));
return pDesiredInterface;
}
BOOL
SetUsbInterface(
PUSBMSC_DEVICE pUsbDevice,
LPCWSTR UniqueDriverId
)
{
USB_TRANSFER hTransfer = 0;
BOOL bRc = FALSE;
DWORD dwIndex;
DEBUGMSG( ZONE_USB_INIT, (TEXT("USBMSC>SetUsbInterface\n")));
if ( !VALID_CONTEXT( pUsbDevice ) || !pUsbDevice->pUsbInterface ) {
DEBUGMSG( ZONE_ERR, (TEXT("Invalid parameter\n")));
return FALSE;
}
if (pUsbDevice->pUsbInterface->Descriptor.bAlternateSetting != 0) {
hTransfer = pUsbDevice->UsbFuncs->lpSetInterface( pUsbDevice->hUsbDevice,
NULL,
NULL,
0, // Flags
pUsbDevice->pUsbInterface->Descriptor.bInterfaceNumber,
pUsbDevice->pUsbInterface->Descriptor.bAlternateSetting );
if ( !hTransfer ) {
DEBUGMSG( ZONE_ERR, (TEXT("SetUsbInterface error:%d\n"), GetLastError() ));
return FALSE;
}
}
//
// now parse the endpoints
//
for ( dwIndex = 0; dwIndex < pUsbDevice->pUsbInterface->Descriptor.bNumEndpoints; dwIndex++)
{
LPCUSB_ENDPOINT pEndpoint;
pEndpoint = pUsbDevice->pUsbInterface->lpEndpoints + dwIndex;
DUMP_USB_ENDPOINT_DESCRIPTOR( pEndpoint->Descriptor );
//
// Mass Storage Class supports 1 mandatory Bulk OUT, 1 mandatory Bulk IN, and 1 optional INTERRUPT
//
if ( USB_ENDPOINT_DIRECTION_OUT( pEndpoint->Descriptor.bEndpointAddress ) ) {
if ( NULL == pUsbDevice->BulkOut.hPipe &&
(pEndpoint->Descriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK)
{
//
// create the Bulk OUT pipe
//
pUsbDevice->BulkOut.hPipe = pUsbDevice->UsbFuncs->lpOpenPipe( pUsbDevice->hUsbDevice,
&pEndpoint->Descriptor );
if ( !pUsbDevice->BulkOut.hPipe ) {
DEBUGMSG( ZONE_ERR, (TEXT("OpenPipe error:%d\n"), GetLastError() ));
bRc = FALSE;
TEST_TRAP();
break;
}
//
// Set Async Content
pUsbDevice->BulkOut.pAsyncContent = CreateBulkTransferMgr(
pUsbDevice->UsbFuncs,pUsbDevice->BulkOut.hPipe,&pEndpoint->Descriptor,UniqueDriverId
);
if (!pUsbDevice->BulkOut.pAsyncContent) {
DEBUGMSG( ZONE_ERR, (TEXT("CreateBulkTransferMgr error:%d\n"), GetLastError() ));
bRc = FALSE;
TEST_TRAP();
break;
}
//
// setup any endpoint specific timers, buffers, context, etc.
//
pUsbDevice->BulkOut.hEvent = CreateEvent( NULL, MANUAL_RESET_EVENT, FALSE, NULL);
if ( !pUsbDevice->BulkOut.hEvent ) {
DEBUGMSG( ZONE_ERR, (TEXT("CreateEvent error:%d\n"), GetLastError() ));
bRc = FALSE;
TEST_TRAP();
break;
}
pUsbDevice->BulkOut.bIndex = pEndpoint->Descriptor.bEndpointAddress;
pUsbDevice->BulkOut.wMaxPacketSize = pEndpoint->Descriptor.wMaxPacketSize;
}
} else if (USB_ENDPOINT_DIRECTION_IN( pEndpoint->Descriptor.bEndpointAddress ) ) {
if ( NULL == pUsbDevice->BulkIn.hPipe &&
(pEndpoint->Descriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK)
{
//
// create the Bulk IN pipe
//
pUsbDevice->BulkIn.hPipe = pUsbDevice->UsbFuncs->lpOpenPipe( pUsbDevice->hUsbDevice,
&pEndpoint->Descriptor );
if ( !pUsbDevice->BulkIn.hPipe ) {
DEBUGMSG( ZONE_ERR, (TEXT("OpenPipe error: %d\n"), GetLastError() ));
bRc = FALSE;
TEST_TRAP();
break;
}
//
// Set Async Content
pUsbDevice->BulkIn.pAsyncContent = CreateBulkTransferMgr(
pUsbDevice->UsbFuncs,pUsbDevice->BulkIn.hPipe,&pEndpoint->Descriptor,UniqueDriverId
);
if (!pUsbDevice->BulkIn.pAsyncContent) {
DEBUGMSG( ZONE_ERR, (TEXT("CreateBulkTransferMgr error:%d\n"), GetLastError() ));
bRc = FALSE;
TEST_TRAP();
break;
} ;
//
// setup any endpoint specific timers, buffers, context, etc.
//
pUsbDevice->BulkIn.hEvent = CreateEvent( NULL, MANUAL_RESET_EVENT, FALSE, NULL);
if ( !pUsbDevice->BulkIn.hEvent ) {
DEBUGMSG( ZONE_ERR, (TEXT("CreateEvent error:%d\n"), GetLastError() ));
bRc = FALSE;
TEST_TRAP();
break;
}
pUsbDevice->BulkIn.bIndex = pEndpoint->Descriptor.bEndpointAddress;
pUsbDevice->BulkIn.wMaxPacketSize = pEndpoint->Descriptor.wMaxPacketSize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -