📄 usbprn.c
字号:
DEBUGMSG( ZONE_USB_INIT, (TEXT(">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 ( bProtocol = 0, dwIndex = 0; dwIndex < dwNumInterfaces; pUsbInterface++, dwIndex++) {
DUMP_USB_INTERFACE_DESCRIPTOR( pUsbInterface->Descriptor, dwIndex );
if ( pUsbInterface->Descriptor.bInterfaceNumber == CurInterface->Descriptor.bInterfaceNumber ) {
if (pUsbInterface->Descriptor.bInterfaceClass == USB_PRN_INTERFACE_CLASS &&
pUsbInterface->Descriptor.bInterfaceSubClass == USB_PRN_INTERFACE_SUBCLASS &&
(pUsbInterface->Descriptor.bInterfaceProtocol == USB_PRN_INTERFACE_PROTOCOL_BI ||
pUsbInterface->Descriptor.bInterfaceProtocol == USB_PRN_INTERFACE_PROTOCOL_UNI) )
{
if (pUsbInterface->Descriptor.bInterfaceProtocol > bProtocol) {
pDesiredInterface = pUsbInterface;
bProtocol = pUsbInterface->Descriptor.bInterfaceProtocol;
DEBUGMSG( ZONE_USB_INIT, (TEXT("*** Found interface @ index: %d ***\n"), dwIndex));
}
}
}
}
DEBUGMSG( ZONE_USB_INIT, (TEXT("<ParseUsbDescriptors:0x%x\n"), pDesiredInterface ));
return pDesiredInterface;
}
BOOL
SetUsbInterface(
PUSBPRN_CONTEXT pUsbPrn,
LPCUSB_INTERFACE UsbInterface
)
{
USB_TRANSFER hTransfer;
BOOL bRc = FALSE;
DWORD dwIndex;
DEBUGMSG( ZONE_USB_INIT, (TEXT(">SetUsbInterface\n")));
if ( !VALID_CONTEXT( pUsbPrn ) || !UsbInterface ) {
DEBUGMSG( ZONE_ERR, (TEXT("Invalid parameter\n")));
return FALSE;
}
hTransfer = pUsbPrn->UsbFuncs->lpSetInterface( pUsbPrn->hUsbDevice,
NULL,
NULL,
0, // synchronous
UsbInterface->Descriptor.bInterfaceNumber,
UsbInterface->Descriptor.bAlternateSetting );
if ( !hTransfer ) {
DEBUGMSG( ZONE_ERR, (TEXT("SetUsbInterface error:%d\n"), GetLastError() ));
return FALSE;
}
//
// now parse the endpoints
//
for ( dwIndex = 0; dwIndex < UsbInterface->Descriptor.bNumEndpoints; dwIndex++) {
LPCUSB_ENDPOINT pEndpoint;
pEndpoint = UsbInterface->lpEndpoints + dwIndex;
DUMP_USB_ENDPOINT_DESCRIPTOR(pEndpoint->Descriptor);
//
// Printer Class supports 1 mandatory Bulk OUT and 1 optional Bulk IN
//
if ( USB_ENDPOINT_DIRECTION_OUT( pEndpoint->Descriptor.bEndpointAddress ) ) {
if ( NULL == pUsbPrn->BulkOut.hPipe &&
(pEndpoint->Descriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK) {
//
// create the Bulk OUT pipe
//
pUsbPrn->BulkOut.hPipe = pUsbPrn->UsbFuncs->lpOpenPipe( pUsbPrn->hUsbDevice,
&pEndpoint->Descriptor );
if ( !pUsbPrn->BulkOut.hPipe ) {
DEBUGMSG( ZONE_ERR, (TEXT("OpenPipe error:%d\n"), GetLastError() ));
bRc = FALSE;
TEST_TRAP();
break;
}
//
// setup any endpoint specific timers, buffers, context, etc.
//
pUsbPrn->BulkOut.hEvent = CreateEvent( NULL, MANUAL_RESET_EVENT, FALSE, NULL);
if ( !pUsbPrn->BulkOut.hEvent ) {
DEBUGMSG( ZONE_ERR, (TEXT("CreateEvent error:%d\n"), GetLastError() ));
bRc = FALSE;
TEST_TRAP();
break;
}
pUsbPrn->BulkOut.bIndex = pEndpoint->Descriptor.bEndpointAddress;
}
} else if (USB_ENDPOINT_DIRECTION_IN( pEndpoint->Descriptor.bEndpointAddress ) ) {
if ( NULL == pUsbPrn->BulkIn.hPipe &&
USB_PRN_INTERFACE_PROTOCOL_BI == UsbInterface->Descriptor.bInterfaceProtocol &&
(pEndpoint->Descriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK) {
//
// create the Bulk IN pipe
//
pUsbPrn->BulkIn.hPipe = pUsbPrn->UsbFuncs->lpOpenPipe( pUsbPrn->hUsbDevice,
&pEndpoint->Descriptor );
if ( !pUsbPrn->BulkIn.hPipe ) {
DEBUGMSG( ZONE_ERR, (TEXT("OpenPipe error: %d\n"), GetLastError() ));
bRc = FALSE;
TEST_TRAP();
break;
}
//
// setup any endpoint specific timers, buffers, context, etc.
//
pUsbPrn->BulkIn.hEvent = CreateEvent( NULL, MANUAL_RESET_EVENT, FALSE, NULL);
if ( !pUsbPrn->BulkIn.hEvent ) {
DEBUGMSG( ZONE_ERR, (TEXT("CreateEvent error:%d\n"), GetLastError() ));
bRc = FALSE;
TEST_TRAP();
break;
}
pUsbPrn->BulkIn.bIndex = pEndpoint->Descriptor.bEndpointAddress;
}
} else {
DEBUGMSG( ZONE_WARN, (TEXT("Unsupported Endpoint:0x%x\n"), pEndpoint->Descriptor.bEndpointAddress));
}
}
//
// did we find our endpoints?
//
if ( USB_PRN_INTERFACE_PROTOCOL_UNI == UsbInterface->Descriptor.bInterfaceProtocol ) {
bRc = pUsbPrn->BulkOut.hPipe ? TRUE : FALSE;
} else {
bRc = (pUsbPrn->BulkOut.hPipe && pUsbPrn->BulkIn.hPipe) ? TRUE : FALSE;
}
CloseTransferHandle(pUsbPrn->UsbFuncs, hTransfer);
//
// if we failed to find all of our endpoints then cleanup will occur later
//
DEBUGMSG( ZONE_USB_INIT, (TEXT("<SetUsbInterface:%d\n"), bRc));
return (bRc);
}
BOOL WINAPI
DeviceNotify(
LPVOID lpvNotifyParameter,
DWORD dwCode,
LPDWORD * dwInfo1,
LPDWORD * dwInfo2,
LPDWORD * dwInfo3,
LPDWORD * dwInfo4
)
{
PUSBPRN_CONTEXT pUsbPrn = (PUSBPRN_CONTEXT )lpvNotifyParameter;
DWORD dwWaitReturn;
BOOL bRc;
UNREFERENCED_PARAMETER(dwInfo1);
UNREFERENCED_PARAMETER(dwInfo2);
UNREFERENCED_PARAMETER(dwInfo3);
UNREFERENCED_PARAMETER(dwInfo4);
DEBUGMSG( ZONE_USB_INIT, (TEXT(">DeviceNotify\n")));
if ( !VALID_CONTEXT( pUsbPrn ) ) {
DEBUGMSG( ZONE_ERR, (TEXT("Invalid Context!\n")));
return FALSE;
}
switch(dwCode) {
case USB_CLOSE_DEVICE:
DEBUGMSG( ZONE_USB_INIT, (TEXT("USB_CLOSE_DEVICE\n")));
if (pUsbPrn->Flags.Open) {
//
// When an app has an open handle to this device and then the user unplugs the USB cable
// the driver will unload here. However, the app can a) hang on a removed handle, or
// b) pass a call to a removed function, e.g., CloseHandle and cause an AV.
// Set state to reject all I/O and wait for cleanup signal.
//
EnterCriticalSection( &pUsbPrn->Lock );
pUsbPrn->Flags.Open = FALSE;
pUsbPrn->Flags.UnloadPending = TRUE;
LeaveCriticalSection( &pUsbPrn->Lock );
DEBUGMSG( ZONE_USB_INIT, (TEXT("Waiting for CloseEvent...\n")));
dwWaitReturn = WaitForSingleObject( pUsbPrn->hCloseEvent, INFINITE );
switch (dwWaitReturn) {
case WAIT_OBJECT_0:
DEBUGMSG( ZONE_USB_INIT, (TEXT("...CloseEvent signalled\n")));
break;
case WAIT_FAILED:
DEBUGMSG( ZONE_ERR, (TEXT("CloseEvent error:%d\n"), GetLastError()));
TEST_TRAP();
break;
default:
DEBUGMSG( ZONE_ERR, (TEXT("Unhandled WaitReason:%d\n"), dwWaitReturn ));
TEST_TRAP();
break;
}
//
// Warning: DeactivateDevice forces Device Manager to call our LPT_Deinit, which then
// causes COREDLL!xxX_CloseHandle to AV when PRNPORT!PrinterSend calls CloseHandle(hPrinter).
// So, give it a chance to clean up.
//
Sleep(1000);
}
DEBUGMSG( ZONE_USB_INIT, (TEXT("DeactivateDevice\n")));
bRc = DeactivateDevice( pUsbPrn->hStreamDevice );
if ( !bRc ) {
DEBUGMSG( ZONE_ERR, (TEXT("DeactivateDevice error: %d\n"), GetLastError() ));
TEST_TRAP();
}
RemoveDeviceContext( pUsbPrn );
return TRUE;
default:
DEBUGMSG( ZONE_ERR, (TEXT("Unhandled code:%d\n"), dwCode));
TEST_TRAP();
break;
}
DEBUGMSG( ZONE_USB_INIT, (TEXT("<DeviceNotify\n")));
return FALSE;
}
/*++
Class specific command:
GET_DEVICE_ID
Return: number of bytesin the Device ID string.
--*/
DWORD
GetDeviceId(
PUSBPRN_CONTEXT pUsbPrn,
PBYTE pBuffer,
DWORD dwLen
)
{
USB_DEVICE_REQUEST ControlHeader;
DWORD dwBytesTransferred = 0;
DWORD dwErr = ERROR_SUCCESS;
DWORD dwUsbErr = USB_NO_ERROR;
DEBUGMSG( ZONE_USB_CONTROL, (TEXT(">GetDeviceId\n")));
if ( !VALID_CONTEXT( pUsbPrn ) || !pBuffer || dwLen <= 2) {
DEBUGMSG( ZONE_ERR, (TEXT("Invalid parameter\n")));
} else {
ControlHeader.bmRequestType = USB_REQUEST_DEVICE_TO_HOST | USB_REQUEST_CLASS | USB_REQUEST_FOR_INTERFACE;
ControlHeader.bRequest = 0;
ControlHeader.wValue = pUsbPrn->ConfigIndex;
ControlHeader.wIndex = pUsbPrn->bInterfaceNumber*0x100 + pUsbPrn->bAlternateSetting;
ControlHeader.wLength = (USHORT)dwLen;
dwErr = IssueVendorTransfer( pUsbPrn->UsbFuncs,
pUsbPrn->hUsbDevice,
DefaultTransferComplete,
pUsbPrn->hEP0Event,
(USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK),
&ControlHeader,
pBuffer, 0,
&dwBytesTransferred,
pUsbPrn->UsbTimeouts.DeviceIdTimeout,
&dwUsbErr );
if ( ERROR_SUCCESS == dwErr && USB_NO_ERROR == dwUsbErr && dwBytesTransferred ) {
//
// remove the 2 byte IEEE-1284 Device ID string length for Port Monitor
//
if ( dwBytesTransferred > 2) {
dwBytesTransferred -= 2;
memmove( pBuffer, pBuffer + 2, dwBytesTransferred);
pBuffer[dwBytesTransferred] = 0;
} else {
dwBytesTransferred = 0;
};
} else {
DEBUGMSG( ZONE_ERR, (TEXT("IssueVendorTransfer ERROR:%d 0x%x\n"), dwErr, dwUsbErr));
IoErrorHandler( pUsbPrn, NULL, 0, dwUsbErr);
}
}
DEBUGMSG( ZONE_USB_CONTROL, (TEXT("<GetDeviceId:%d\n"), dwBytesTransferred));
return dwBytesTransferred;
}
/*++
Class specific command:
GET_PORT_STATUS
Return: printer status bits.
--*/
USHORT
GetPortStatus(
PUSBPRN_CONTEXT pUsbPrn
)
{
USB_DEVICE_REQUEST ControlHeader;
DWORD dwBytesTransferred = 0;
DWORD dwUsbErr = USB_NO_ERROR;
DWORD dwErr = ERROR_SUCCESS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -