Window Driver
USB 드라이버 인터럽트 통신에서 데이터 받아오기
구리z
2010. 2. 27. 15:10
일단.. 인터럽트 전송 전용 URB를 만든다.
지금부터 할 방법으로는 데이터를 받아오기 위해선 두 개의 함수가 필요하다
한 개는 urb를 생성하는과정이고, 한 개는 데이터를 처리하면서 다시 urb를 생성하게해준다.
UsbBuildInterruptOrBulkTransferRequest() 함수를 이용해 URB를 생성해준다.
그리고 IoSetCompletionRoutine() 함수를 이용해서, Irp와 인터럽트가 들어왔을 때 호출 할 함수를 등록해준다.
NTSTATUS StartInterruptUrb(
PDEVICE_EXTENSION pdx
)
{
// If the interrupt polling IRP is currently running, don't try to start
// it again.
BOOLEAN startirp;
KIRQL oldirql ;
PIRP Irp ;
PURB urb ;
PIO_STACK_LOCATION stack ;
DbgPrint("[!] StartInterruptUrb\n");
KeAcquireSpinLock(&pdx->polllock, &oldirql) ;
if (pdx->pollpending)
{
startirp = FALSE ;
}
else
{
startirp = TRUE, pdx->pollpending = TRUE ;
}
KeReleaseSpinLock(&pdx->polllock, oldirql) ;
if (!startirp)
{
return STATUS_DEVICE_BUSY ; // already pending
}
Irp = pdx->PollingIrp ;
urb = pdx->PollingUrb ;
ASSERT(Irp && urb);
// Initialize the URB we use for reading the interrupt pipe
UsbBuildInterruptOrBulkTransferRequest(
urb,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
pdx->hpipe,
&pdx->intdata,
NULL,
sizeof(pdx->intdata),
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
NULL
);
// Install "OnInterrupt" as the completion routine for the polling IRP.
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnInterrupt, pdx, TRUE, TRUE, TRUE);
// Initialize the IRP for an internal control request
stack = IoGetNextIrpStackLocation(Irp) ;
stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL ;
stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB ;
stack->Parameters.Others.Argument1 = urb ;
Irp->Cancel = FALSE;
return IoCallDriver(pdx->TopOfStackDeviceObject, Irp);
}
NTSTATUS OnInterrupt(
PDEVICE_OBJECT junk,
PIRP Irp,
PDEVICE_EXTENSION pdx
)
{
KIRQL oldirql ;
int i ;
KeAcquireSpinLock(&pdx->polllock, &oldirql) ;
pdx->pollpending = FALSE ;
KeReleaseSpinLock(&pdx->polllock, oldirql) ;
DbgPrint("[!] OnInterrupt Enter, Status : %x\n", Irp->IoStatus.Status);
if (NT_SUCCESS(Irp->IoStatus.Status)) {
DbgPrint("[!] Interrupt : %x %x %x %x\n", pdx->intdata[0], pdx->intdata[1], pdx->intdata[2], pdx->intdata[3]) ;
StartInterruptUrb(pdx); // issue next polling request
pdx->InitPolling = TRUE ;
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
헌데 문제가 발생한다.
실제로 전송되는 데이터가 버퍼크기보다 작으면 블루스크린이 뜨고만다...
USB 초기화 하는 부분에서 PIPE의 MaxPacketSize를 적절히 조절해준다.