Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ДП.docx
Скачиваний:
11
Добавлен:
23.09.2019
Размер:
4.64 Mб
Скачать

2.4.6 Обработчик ConfigureDevice

Конфигурирование устройства (процедура OnConfigureDevice) состоит из следующих действий:

  1. передача запроса с достаточным размером;

  2. получение дескриптора;

  3. создание конечных точек;

  4. конфигурирование конечных точек.

NTSTATUS ConfigureDevice(

IN PDEVICE_OBJECT DeviceObject

)

// Инициализация экземпляра устройства USB, а также выбор (настройка)

// и сохранение конфигурации

{

PDEVICE_EXTENSION deviceExtension;

NTSTATUS ntStatus;

PURB urb;

ULONG siz;

deviceExtension = DeviceObject->DeviceExtension;

ASSERT( deviceExtension->UsbConfigurationDescriptor == NULL );

urb = ExAllocatePool(NonPagedPool,

sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));

if ( !urb )

return STATUS_INSUFFICIENT_RESOURCES;

Вызывающая сторона должна позаботиться о буфере достаточного размера, чтобы он мог вместить данные, в противном случае данные будет урезаны, но без возвращения ошибки. Поэтому переменная «siz» и задействуется в приведенном листинге

siz = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 128;

// Мы выйдем из цикла как только UsbBuildGetDescriptorRequest() получит

// буфер достаточного размера (deviceExtension-

// >UsbConfigurationDescriptor), чтобы вместить все данные

while( 1 ) {

deviceExtension->UsbConfigurationDescriptor = ExAllocatePool(NonPagedPool, siz);

if ( !deviceExtension->UsbConfigurationDescriptor ) {

ExFreePool(urb);

return STATUS_INSUFFICIENT_RESOURCES;

}

UsbBuildGetDescriptorRequest(urb,

(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), USB_CONFIGURATION_DESCRIPTOR_TYPE,

0,

0,

deviceExtension->UsbConfigurationDescriptor,

NULL,

siz,

NULL);

ntStatus = CallUSBD(DeviceObject, urb);

if (urb->UrbControlDescriptorRequest.TransferBufferLength>0 &&

deviceExtension->UsbConfigurationDescriptor->wTotalLength > siz)

{

siz = deviceExtension->UsbConfigurationDescriptor->wTotalLength;

ExFreePool(deviceExtension->UsbConfigurationDescriptor);

deviceExtension->UsbConfigurationDescriptor = NULL;

} else {

break;

}

}

ExFreePool(urb);

Теперь у нас есть конфигурационный дескриптор для той конфигурации, которая нам нужна. Теперь мы осуществляем вызов для конфигурирования каналов, ассоциируемых с конфигурацией.

ntStatus = SelectInterface(DeviceObject,

deviceExtension->UsbConfigurationDescriptor);

return ntStatus;

}

2.4.7 Обработчики запросов на чтение и запись

Процедуры USBRead и USBWrite обслуживают запросы на чтение запись данных для устройства.

NTSTATUS USBRead(

IN PDEVICE_OBJECT DeviceObject,

IN PIRP Irp

)

{

NTSTATUS ntStatus = STATUS_SUCCESS;

PUSBD_PIPE_INFORMATION pipeHandle;

PFILE_OBJECT fileObject;

PIO_STACK_LOCATION irpStack, nextStack;

PDEVICE_EXTENSION deviceExtension;

PURB urb;

PISOUSB_RW_CONTEXT context = NULL;

if ( !Irp->MdlAddress ) {

// NULL для запроса нулевой длины, поэтому просто возвращаем SUCCESS

Irp->IoStatus.Status = ntStatus;

Irp->IoStatus.Information = 0;

IoCompleteRequest (Irp,

IO_NO_INCREMENT

);

return ntStatus;

}

IncrementIoCount(DeviceObject);

deviceExtension = DeviceObject->DeviceExtension;

if ( ! CanAcceptIoRequests( DeviceObject ) )

{

ntStatus = STATUS_DELETE_PENDING;

Irp->IoStatus.Status = ntStatus;

DecrementIoCount(DeviceObject);

IoCompleteRequest (Irp, IO_NO_INCREMENT );

return ntStatus;

}

irpStack = IoGetCurrentIrpStackLocation (Irp);

fileObject = irpStack->FileObject;

pipeHandle = fileObject->FsContext;

if (!pipeHandle)

{

ntStatus = STATUS_INVALID_HANDLE;

Irp->IoStatus.Status = ntStatus;

Irp->IoStatus.Information = 0;

IoCompleteRequest (Irp,

IO_NO_INCREMENT

);

return ntStatus;

}

ASSERT( UsbdPipeTypeIsochronous == pipeHandle->PipeType );

//Вызов ResetPipe() сбрасывает канал USB.

ResetPipe(DeviceObject, pipeHandle, FALSE);

// BuildIsoRequest() используется для построения USBD запроса для

// IRP_MJ_READ и IRP_MJ_WRITE IOCTL-ов.

urb = BuildIsoRequest(DeviceObject,

Irp,

pipeHandle,

TRUE);

if (urb) {

nextStack = IoGetNextIrpStackLocation(Irp);

ASSERT(nextStack != NULL);

ASSERT(DeviceObject->StackSize>1);

nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;

nextStack->Parameters.Others.Argument1 = urb;

nextStack->Parameters.DeviceIoControl.IoControlCode =

IOCTL_INTERNAL_USB_SUBMIT_URB;

IoSetCompletionRoutine(Irp,

IsoUsb_IsoReadWrite_Complete,

urb,

TRUE,

TRUE,

TRUE);

ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,

Irp);

} else {

ntStatus = STATUS_INSUFFICIENT_RESOURCES;

}

return ntStatus;

}

NTSTATUS USBWrite(

IN PDEVICE_OBJECT DeviceObject,

IN PIRP Irp

)

{

NTSTATUS ntStatus = STATUS_SUCCESS;

PUSBD_PIPE_INFORMATION pipeHandle;

PFILE_OBJECT fileObject;

PIO_STACK_LOCATION irpStack, nextStack;

PDEVICE_EXTENSION deviceExtension;

PURB urb;

PISOUSB_RW_CONTEXT context = NULL;

if ( !Irp->MdlAddress )

{

Irp->IoStatus.Status = ntStatus;

Irp->IoStatus.Information = 0;

IoCompleteRequest (Irp,

IO_NO_INCREMENT

);

return ntStatus;

}

IncrementIoCount(DeviceObject);

deviceExtension = DeviceObject->DeviceExtension;

if ( ! CanAcceptIoRequests( DeviceObject ) )

{

ntStatus = STATUS_DELETE_PENDING;

Irp->IoStatus.Status = ntStatus;

DecrementIoCount(DeviceObject);

IoCompleteRequest(Irp, IO_NO_INCREMENT );

return ntStatus;

}

irpStack = IoGetCurrentIrpStackLocation(Irp);

fileObject = irpStack->FileObject;

pipeHandle = fileObject->FsContext;

if (!pipeHandle)

{

ntStatus = STATUS_INVALID_HANDLE;

Irp->IoStatus.Status = ntStatus;

Irp->IoStatus.Information = 0;

IoCompleteRequest (Irp,

IO_NO_INCREMENT

);

return ntStatus;

}

ResetPipe(DeviceObject, pipeHandle, FALSE);

urb = BuildIsoRequest(DeviceObject,

Irp,

pipeHandle,

FALSE);

if (urb)

{

nextStack = IoGetNextIrpStackLocation(Irp);

ASSERT(nextStack != NULL);

ASSERT(DeviceObject->StackSize>1);

nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;

nextStack->Parameters.Others.Argument1 = urb;

nextStack->Parameters.DeviceIoControl.IoControlCode =

IOCTL_INTERNAL_USB_SUBMIT_URB;

IoSetCompletionRoutine(Irp,

IsoUsb_IsoReadWrite_Complete,

urb,

TRUE,

TRUE,

TRUE);

ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,

Irp);

} else {

ntStatus = STATUS_INSUFFICIENT_RESOURCES;

}

return ntStatus;

}