구리의 창고

USB 드라이버 인터럽트 통신에서 데이터 받아오기 본문

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를 적절히 조절해준다.
Comments