PC Review Forums Newsgroups Windows XP Windows XP Logo OpenHCI bug on Win2k?

Reply

OpenHCI bug on Win2k?

 
Thread Tools Rate Thread
Old 01-11-2004, 06:58 PM   #1
WT
Guest
 
Posts: n/a
Default OpenHCI bug on Win2k?


"Alexander Grigoriev" <alegr@earthlink.net> wrote in message
news:u0bmWZivEHA.3320@TK2MSFTNGP14.phx.gbl...
> Can you post code where you initialize URB and IRP?
>

The code to init IRP and URB are given below. I am wondering if OpenHCI will
handle data buffers bigger than the max packet size on the pipes. It appears
that it also does not like the buffer (512 bytes) I pass to the interrupt
pipe (with max packet size of 8 bytes). The usbport.sys, which my driver
calls on XP, handles bigger buffers just fine.
Now MS document on UsbBuildInterruptOrBulkTransferRequest does not put size
limit on the data buffer used. However, I am also highly suspicious that
this bug happens under special circustance--a bug like this would have been
spotted long time ago.

// routine to init and send URB
// Note: the call to read the response failed with
STATUS_INVALID_PARAMETER--the input buffer size (
// pReply->BufferSize is 0x120 (while my max packet size for the input pipe
is 64 bytes).

NTSTATUS
PcscSendSmartcardCommand(
PSMARTCARD_EXTENSION SmartcardExtension)
{
NTSTATUS status = STATUS_SUCCESS;

PSMARTCARD_REPLY pReply = &SmartcardExtension->SmartcardReply;
PSMARTCARD_REQUEST pRequest = &SmartcardExtension->SmartcardRequest;

PDEVICE_OBJECT fdo =
(PDEVICE_OBJECT)SmartcardExtension->OsData->DeviceObject;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;

#ifdef DEBUG
SmartcardDebug(DEBUG_INFO, ("%s!PcscSendSmartcardCommand: cmd = ",
DRIVERNAME));
for (ULONG j = 0; j < pRequest->BufferLength; j++) {
SmartcardDebug(DEBUG_INFO, ("/x%02X", pRequest->Buffer[j]));
}
SmartcardDebug(DEBUG_INFO, ("\n"));
#endif

URB urb;

// init URB to send command via bulk out pipe
UsbBuildInterruptOrBulkTransferRequest(
&urb, // URB to build
sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER), //
pdx->houtpipe, // pipe handle
pRequest->Buffer, // transfer buffer
NULL, // MDL
pRequest->BufferLength, // transfer buffer length
USBD_TRANSFER_DIRECTION_OUT, // transfer flags
NULL); //


// Send URB
status = SendAwaitUrb(fdo, &urb);

if (status == STATUS_SUCCESS) {
// Read response from bulk in pipe
// init URB to read response from bulk in pipe
UsbBuildInterruptOrBulkTransferRequest(
&urb, // URB to build
sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER), //
pdx->hinpipe, // pipe handle
pReply->Buffer, // transfer buffer
NULL, // MDL
pReply->BufferSize, // transfer buffer length
USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK, // transfer flags
NULL);
//
// Send URB
status = SendAwaitUrb(fdo, &urb);
if (status == STATUS_SUCCESS) {
pReply->BufferLength =
urb.UrbBulkOrInterruptTransfer.TransferBufferLength;
#ifdef DEBUG
SmartcardDebug(DEBUG_INFO, ("%s!PcscSendSmartcardCommand: resp = ",
DRIVERNAME));
for (ULONG j = 0; j < pReply->BufferLength; j++) {
SmartcardDebug(DEBUG_INFO, ("/x%02X", pReply->Buffer[j]));
}
SmartcardDebug(DEBUG_INFO, ("\n"));
#endif
}
else {
SmartcardDebug(DEBUG_ERROR,
("%s!PcscSendSmartcardCommand: error reading resp (%lX)\n",
DRIVERNAME, status));
}
}
else {
SmartcardDebug(DEBUG_ERROR,
("%s!PcscSendSmartcardCommand: error writing cmd (%lX)\n",
DRIVERNAME, status));
}

return (status);
}

// routine to init and send IRP
NTSTATUS SendAwaitUrb(PDEVICE_OBJECT fdo, PURB urb)
{ // SendAwaitUrb
PAGED_CODE();
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

KEVENT event;
KeInitializeEvent(&event, NotificationEvent, FALSE);

IO_STATUS_BLOCK iostatus;
PIRP Irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->LowerDeviceObject, NULL, 0,
NULL, 0, TRUE, &event, &iostatus);

if (!Irp) {
KdPrint((DRIVERNAME " - Unable to allocate IRP for sending URB\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}

// Set up our completion routine
IoSetCompletionRoutine(Irp, SendUrbComplete, (PVOID)&event, TRUE, TRUE,
TRUE);

PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);
stack->Parameters.Others.Argument1 = (PVOID) urb;

// We will wait for 1 min before the reader returns
LARGE_INTEGER timeOut;
// 1 min = 60 sec, in units of 100 nano sec
timeOut.QuadPart = -60 * 1000 * 1000 * 10;

// Send URB to USBD
NTSTATUS status = IoCallDriver(pdx->LowerDeviceObject, Irp);

if (status == STATUS_PENDING) {
status = KeWaitForSingleObject(
&event, Executive, KernelMode, FALSE, &timeOut);
if (status == STATUS_TIMEOUT) {
SmartcardDebug(DEBUG_INFO,
("%s!SendAwaitUrb: cmd time out, cancelling IRP\n", DRIVERNAME));
// We timed out, need to cancel the IRP
IoCancelIrp(Irp);
// Now wait for our completion routine to signal us
KeWaitForSingleObject(
&event, Executive, KernelMode, FALSE, NULL);
}
else {
// Since our completion routine returned STATUS_MORE_PROCESSING_NEEDED
that
// prevents USBD to finish the IRP, we need to do it here
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}
else {
iostatus.Status = status;
}

status = iostatus.Status;

if (status != STATUS_SUCCESS)
SmartcardDebug(DEBUG_INFO,
("%s!SendAwaitUrb: err 0x%x\n", DRIVERNAME, status));

return status;
} // SendAwaitUrb

I traced the driver stack and found that the parameter validation happens in
openhci.sys. Here a dump from SoftICE:
:u openhci_queuetransfer l200

_OpenHCI_QueueTransfer

0008:EB6C3B3C PUSH EBP

0008:EB6C3B3D MOV EBP,ESP

0008:EB6C3B3F PUSH ECX

0008:EB6C3B40 PUSH ECX

0008:EB6C3B41 MOV EAX,[EBP+08]

0008:EB6C3B44 PUSH EBX

0008:EB6C3B45 PUSH ESI

0008:EB6C3B46 PUSH EDI

0008:EB6C3B47 MOV EDI,[EBP+0C] ; edi = IRP

0008:EB6C3B4A MOV EAX,[EAX+28]

0008:EB6C3B4D MOV DWORD PTR [EBP-04],00000103

0008:EB6C3B54 MOV [EBP-08],EAX

0008:EB6C3B57 MOV ECX,[EDI+60] ; ecx = IO_stack

0008:EB6C3B5A MOV ESI,[ECX+04] ; esi = URB

0008:EB6C3B5D MOV EBX,[ESI+28] ; HCA area, opapue to driver

0008:EB6C3B60 MOV [ESI+2C],EDI

0008:EB6C3B63 PUSH DWORD PTR [EAX+00000174]

0008:EB6C3B69 CALL [__imp__READ_REGISTER_ULONG]

0008:EB6C3B6F CMP EAX,-01

0008:EB6C3B72 JNZ EB6C3B85

0008:EB6C3B74 MOV DWORD PTR [EBP-04],C00000C0 ; STATUS_DEVICE_DOES_NOT_EXIST

0008:EB6C3B7B PUSH 80000500

0008:EB6C3B80 JMP EB6C3C09

0008:EB6C3B85 TEST BYTE PTR [EBX+10],02

0008:EB6C3B89 JZ EB6C3BA9

0008:EB6C3B8B TEST ESI,ESI

0008:EB6C3B8D JZ EB6C3CC5

0008:EB6C3B93 PUSH EBX

0008:EB6C3B94 PUSH ESI

0008:EB6C3B95 PUSH EDI

0008:EB6C3B96 PUSH DWORD PTR [EBP-08]

0008:EB6C3B99 PUSH DWORD PTR [EBP+08]

0008:EB6C3B9C CALL _OpenHCI_RootHubStartXfer

0008:EB6C3BA1 MOV ESI,[ESI+24]

0008:EB6C3BA4 MOV [EBP-04],EAX

0008:EB6C3BA7 JMP EB6C3B8B

0008:EB6C3BA9 CMP BYTE PTR [EBX+30],01

0008:EB6C3BAD JNZ EB6C3BF5

0008:EB6C3BAF TEST BYTE PTR [ESI+14],04

0008:EB6C3BB3 JNZ EB6C3BF5

0008:EB6C3BB5 PUSH DWORD PTR [EBP-08]

0008:EB6C3BB8 CALL _Get32BitFrameNumber

0008:EB6C3BBD MOV ECX,[ESI+48]

0008:EB6C3BC0 PUSH DWORD PTR [EBP-08]

0008:EB6C3BC3 SUB ECX,EAX

0008:EB6C3BC5 TEST ECX,ECX

0008:EB6C3BC7 JLE EB6C3BD5

0008:EB6C3BC9 CALL _Get32BitFrameNumber

0008:EB6C3BCE MOV ECX,[ESI+48]

0008:EB6C3BD1 SUB ECX,EAX

0008:EB6C3BD3 JMP EB6C3BDF

0008:EB6C3BD5 CALL _Get32BitFrameNumber

0008:EB6C3BDA MOV ECX,EAX

0008:EB6C3BDC SUB ECX,[ESI+48]

0008:EB6C3BDF CMP ECX,00000400

0008:EB6C3BE5 JLE EB6C3BF5

0008:EB6C3BE7 MOV DWORD PTR [EBP-04],C000000D ; STATUS_INVALID_PARAMETER

0008:EB6C3BEE PUSH C0000A00

0008:EB6C3BF3 JMP EB6C3C09

0008:EB6C3BF5 MOV EAX,[ESI+18] ;; NOTE: eax = input buffer size = 0x120

0008:EB6C3BF8 CMP EAX,[EBX+4C] ;; [ebx + 4c] = 0x40, ie 64 bytes, possibly
the max packet size for the pipe?

0008:EB6C3BFB JBE EB6C3C14 (NO JUMP)

0008:EB6C3BFD MOV DWORD PTR [EBP-04],C000000D ; STATUS_INVALID_PARAMETER <=
error code returned to IdtSp3Usb

0008:EB6C3C04 PUSH 80000300

0008:EB6C3C09 PUSH ESI

0008:EB6C3C0A CALL _OpenHCI_SetTranferError

0008:EB6C3C0F JMP EB6C3CC5

0008:EB6C3C14 LEA EAX,[EBP+0C]

0008:EB6C3C17 PUSH EAX

0008:EB6C3C18 CALL [__imp__IoAcquireCancelSpinLock]

0008:EB6C3C1E LEA ECX,[EBX+40]

0008:EB6C3C21 CALL [__imp_@KfAcquireSpinLock]

0008:EB6C3C27 CMP BYTE PTR [EDI+24],00

0008:EB6C3C2B MOV [EBP+08],AL

0008:EB6C3C2E JZ EB6C3C39

0008:EB6C3C30 MOV DWORD PTR [EBP-04],C0000120 ; STATUS_CANCELLED

0008:EB6C3C37 JMP EB6C3C46

0008:EB6C3C39 TEST BYTE PTR [EBX+10],01

0008:EB6C3C3D JZ EB6C3C5E

0008:EB6C3C3F MOV DWORD PTR [EBP-04],C000020F ; STATUS_TRANSACTION_ABORTED

0008:EB6C3C46 XOR EDX,EDX

0008:EB6C3C48 LEA ECX,[EDI+38]

0008:EB6C3C4B CALL [__imp_@InterlockedExchange]

0008:EB6C3C51 PUSH 00010000

0008:EB6C3C56 PUSH ESI

0008:EB6C3C57 CALL _OpenHCI_SetTranferError

0008:EB6C3C5C JMP EB6C3CA7

0008:EB6C3C5E TEST ESI,ESI

0008:EB6C3C60 JZ EB6C3C8B

0008:EB6C3C62 LEA ECX,[EBX+18]

0008:EB6C3C65 LEA EAX,[ESI+38]

0008:EB6C3C68 MOV [ESI+3C],EAX

0008:EB6C3C6B MOV [EAX],EAX

0008:EB6C3C6D MOV DWORD PTR [ESI+04],40404003

0008:EB6C3C74 MOV EDX,[ECX+04]

0008:EB6C3C77 LEA EAX,[ESI+30]

0008:EB6C3C7A MOV [ESI+34],EDX

0008:EB6C3C7D MOV [EAX],ECX

0008:EB6C3C7F MOV [EDX],EAX

0008:EB6C3C81 MOV [ECX+04],EAX

0008:EB6C3C84 MOV ESI,[ESI+24]

0008:EB6C3C87 TEST ESI,ESI

0008:EB6C3C89 JNZ EB6C3C65

0008:EB6C3C8B MOV EAX,[EDI+60]

0008:EB6C3C8E MOV DWORD PTR [EDI+18],00000103

0008:EB6C3C95 MOV EDX,_OpenHCI_CancelTransfer

0008:EB6C3C9A LEA ECX,[EDI+38]

0008:EB6C3C9D OR BYTE PTR [EAX+03],01

0008:EB6C3CA1 CALL [__imp_@InterlockedExchange]

0008:EB6C3CA7 MOV DL,[EBP+08]

0008:EB6C3CAA LEA ECX,[EBX+40]

0008:EB6C3CAD CALL [__imp_@KfReleaseSpinLock]

0008:EB6C3CB3 PUSH DWORD PTR [EBP+0C]

0008:EB6C3CB6 CALL [__imp__IoReleaseCancelSpinLock]

0008:EB6C3CBC PUSH EBX

0008:EB6C3CBD PUSH DWORD PTR [EBP-08]

0008:EB6C3CC0 CALL _OpenHCI_ProcessEndpoint

0008:EB6C3CC5 MOV EAX,[EBP-04]

0008:EB6C3CC8 POP EDI

0008:EB6C3CC9 POP ESI

0008:EB6C3CCA POP EBX

0008:EB6C3CCB LEAVE

0008:EB6C3CCC RET 0008

0008:EB6C3CCF INT 3

> "WT" <wyt168@earthlink.net> wrote in message
> news:Vgugd.5799$kM.5639@newsread3.news.pas.earthlink.net...
>>I developed a USB driver for smartcard reader and it was running fine on
>>WinXP. It works fine on Win2k too if my reader is connected through a
>>hispeed hub. However, if I connect the reader to the root hub directly,
>>the driver would fail to load. I snooped around with SoftICE into the
>>driver stack and discovered that it is in OpenHCI that my IRP, or URB,
>>failed a parameter validation. Turns out that it does not take a buffer
>>with size greater than 64 bytes (possibly because the max packet size of
>>of my bulk input pipe is 64 bytess) and rejected my URB with
>>STATUS_INVALID_PARAMETER (0xc000000D).
>> When a reader is connected through a hub, openhci is not involved. My
>> driver passes the URB to usbport.sys instead.
>> Anybody out there experienced the same problem? I can provide more
>> details if anybody is interested.
>> Winston



  Reply With Quote
Reply



Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off