Разработка драйвера, распознающего USB-устройство как виртуальный COM-порт в системе Windows NT
Архитектура ввода/вывода Windows NT. Внутренняя организация шины USB. Сущностная характеристика драйверной модели WDM. Точки входа разрабатываемого драйвера, размещение кода в памяти, установка драйвера в системе. Реализация кода драйвера на языке C.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 27.09.2014 |
Размер файла | 1,2 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
}
if (NT_SUCCESS (status))
{ // Если возврат пакета удачен, тов первую очередь установим состояние в Started.
SET_NEW_PNP_STATE(deviceExtension, Started);
}
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
return status;
// Удаление устройства
case IRP_MN_REMOVE_DEVICE:
// Ждем завершения всех ставшихся запросов
IoReleaseRemoveLockAndWait(&deviceExtension->RemoveLock, Irp);
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(deviceExtension->NextLowerDriver, Irp);
SET_NEW_PNP_STATE(deviceExtension, Deleted);
// Удаление объекта устройства
IoDetachDevice(deviceExtension->NextLowerDriver);
IoDeleteDevice(DeviceObject);
return status;
// Остановка устройства для обновления состояния ресурсов
case IRP_MN_QUERY_STOP_DEVICE:
SET_NEW_PNP_STATE(deviceExtension, StopPending);
status = STATUS_SUCCESS;
break;
// Отмена останова устройства
case IRP_MN_CANCEL_STOP_DEVICE:
if (StopPending == deviceExtension->DevicePnPState)
{
// мы получили стоповую последовательность, восстанавление предыдущего состояния
RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
}
// Этот пакет обязательно должен быть обработан.
status = STATUS_SUCCESS;
break;
case IRP_MN_STOP_DEVICE:
SET_NEW_PNP_STATE(deviceExtension, Stopped);
status = STATUS_SUCCESS;
break;
// Останов устройства
case IRP_MN_QUERY_REMOVE_DEVICE:
SET_NEW_PNP_STATE(deviceExtension, RemovePending);
status = STATUS_SUCCESS;
break;
// Сообщаем драйверу что устройство более не доступно для I/O
case IRP_MN_SURPRISE_REMOVAL:
SET_NEW_PNP_STATE(deviceExtension, SurpriseRemovePending);
status = STATUS_SUCCESS;
break;
// Устройство не будет удалено
case IRP_MN_CANCEL_REMOVE_DEVICE:
if (RemovePending == deviceExtension->DevicePnPState)
{
//При получении стоповой последовательности проводим восстановление предыдущего состояния.
RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
}
status = STATUS_SUCCESS;
break;
// Сообщение драйверу о специальноых данных(страницы, дампы, и т.д.)
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
// Если над нами нет других драйверов, просто флаг страничной передачи.
if ((DeviceObject->AttachedDevice == NULL) ||
(DeviceObject->AttachedDevice->Flags & DO_POWER_PAGABLE)) {
DeviceObject->Flags |= DO_POWER_PAGABLE;
}
// Копируем текущую очередь ниже и завершаем запрос
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(
Irp,
FilterDeviceUsageNotificationCompletionRoutine,
NULL,
TRUE,
TRUE,
TRUE
);
return IoCallDriver(deviceExtension->NextLowerDriver, Irp);
default:
// если мы не обрабатываем никакой IRP пакет, то оставляем текущий статус неизменным
status = Irp->IoStatus.Status;
break;
}
// Отправляем пакет IRP вниз и забываем про него.
Irp->IoStatus.Status = status;
// Модифицируем текущий указатель на IRP пакет
IoSkipCurrentIrpStackLocation (Irp);
// Вызываем нижестоящий драйвер
status = IoCallDriver (deviceExtension->NextLowerDriver, Irp);
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
return status;
}
NTSTATUS
FilterStartCompletionRoutine(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp,
__in PVOID Context
)
/*++
Функция завершения для нижестоящих объектов устройств
к которым прикреплен наш объект фильтр-драйвера
--*/
{
PKEVENT event = (PKEVENT)Context;
UNREFERENCED_PARAMETER (DeviceObject);
// Если нижний драйвер не вернул STATUS_PENDING, нам не нужно ждать появления нового события. Это позволяет избежать захвата блокировки диспетчера.
if (Irp->PendingReturned == TRUE) {
KeSetEvent (event, IO_NO_INCREMENT, FALSE);
}
// Процедура отправки обязана вызвать IoCompleteRequest
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
FilterDeviceUsageNotificationCompletionRoutine(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp,
__in PVOID Context
)
/*++
Функция обработки специальных данных
--*/
{
PDEVICE_EXTENSION deviceExtension;
UNREFERENCED_PARAMETER(Context);
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
// При отправке выше страница очищается
if (!(deviceExtension->NextLowerDriver->Flags & DO_POWER_PAGABLE)) {
DeviceObject->Flags &= ~DO_POWER_PAGABLE;
}
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
return STATUS_CONTINUE_COMPLETION;
}
NTSTATUS
FilterDispatchPower(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
)
/*++
Функция обработки power IRP пакетов.
--*/
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS status;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, Irp);
if (!NT_SUCCESS (status)) {
Irp->IoStatus.Status = status;
PoStartNextPowerIrp(Irp);
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
/*++
Подготовка передачи нижестоящему драйверу расположение пакета в стеке и вызов нижестоящего драйвера физического устройства--*/
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
status = PoCallDriver(deviceExtension->NextLowerDriver, Irp);
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
return status;
}
VOID
FilterUnload(
__in PDRIVER_OBJECT DriverObject
)
/*++
Функция выгружает драйвер, освобождая все занятые рускрсы из DriverEntry
--*/
{
PAGED_CODE ();
// Объекты устройств должны быть в состоянии NULL Все объекты устройств, ассоциируемые с этим драйвером должны быть удалены
ASSERT(DriverObject->DeviceObject == NULL);
// Нельзя выгружаться пока все подконтрольные устройства не удалены из очереди
return;
}
NTSTATUS
FilterDispatchIoXp(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
)
/*++
Функция обработки поддерживаемых пакетов для Windows XP. Если пакет удовлетворяет условиям, то запрос он будет обработан и завершен, если нет, то отправим его вниз по стеку драйверов.
--*/
{
PDEVICE_EXTENSION deviceExtension;
PURB urb = URB_FROM_IRP(Irp);
NTSTATUS status;
static UCHAR intr_addr;
PAGED_CODE ();
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, Irp);
// Проверка подключения устройства
if (!NT_SUCCESS (status)) { Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
// Получение адреса канала прерывания
if( URB_FUNCTION_SELECT_CONFIGURATION==urb->UrbHeader.Function ) {
USB_CONFIGURATION_DESCRIPTOR *pdsc;
UCHAR *ptr;
UCHAR *pend;
pdsc = urb->UrbSelectConfiguration.ConfigurationDescriptor;
ptr = (UCHAR *)pdsc;
for( pend=ptr+pdsc->wTotalLength,ptr+=*ptr; ptr<pend; ptr+=*ptr ) {
if( *(ptr+1)==USB_ENDPOINT_DESCRIPTOR_TYPE && *(ptr+3)==USB_ENDPOINT_TYPE_INTERRUPT ) {
intr_addr = *(ptr+2);
break;
}
}
}
// Игнорировать неиспользуемые запросы прерываний
if( URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER==urb->UrbHeader.Function &&
*((UCHAR *)urb->UrbBulkOrInterruptTransfer.PipeHandle+6)==intr_addr ) {
IoSkipCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = status = STATUS_INTERNAL_ERROR;
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
return status;
}
IoSkipCurrentIrpStackLocation (Irp);
status = IoCallDriver (deviceExtension->NextLowerDriver, Irp);
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
return status;
}
NTSTATUS
FilterDispatchIoVista(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
)
/*++
Функция обработки поддерживаемых пакетов для Windows Vista - 7.Если пакет удовлетворяет условиям, то запрос он будет обработан и завершен, если нет, то отправим его вниз по стеку драйверов.
--*/
{
PDEVICE_EXTENSION deviceExtension;
PURB urb = URB_FROM_IRP(Irp);
NTSTATUS status;
static UCHAR intr_addr;
static BOOLEAN use_bulk;
PAGED_CODE ();
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, Irp);
//Проверка подключения устройства
if (!NT_SUCCESS (status)) {
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
// Исправление дескриптора конфигурации
if( URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE==urb->UrbHeader.Function &&
USB_CONFIGURATION_DESCRIPTOR_TYPE==urb->UrbControlDescriptorRequest.DescriptorType ) {
KEVENT event;
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
(PIO_COMPLETION_ROUTINE) FilterStartCompletionRoutine,
&event,
TRUE,
TRUE,
TRUE
);
status = IoCallDriver (deviceExtension->NextLowerDriver, Irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event,
Executive, // Ожидать событие
KernelMode, // обязательно находиться в режиме ядра для предотвращения выхода стека за пределы страницы
FALSE,
NULL
);
status = Irp->IoStatus.Status;
}
if( NT_SUCCESS(status) &&
urb->UrbControlDescriptorRequest.TransferBuffer!=NULL &&
urb->UrbControlDescriptorRequest.TransferBufferLength<256 ) {
UCHAR *pdsc, *ptr, *pend, *p0, *p1, buf[256];
ULONG len;
// Заменяем классы дескрипторов для интерфейса данных/коммуникации
pdsc = urb->UrbControlDescriptorRequest.TransferBuffer;
len = urb->UrbControlDescriptorRequest.TransferBufferLength;
memcpy( buf, pdsc, len );
p0 = NULL;
p1 = NULL;
for( ptr=buf,pend=ptr+len; ptr<pend; ptr+=*ptr ) {
if( *(ptr+1)==USB_INTERFACE_DESCRIPTOR_TYPE ) {
if( *(ptr+5)==2 ) // Калсс коммуникации
p0 = ptr;
else if( *(ptr+5)==10 ) // Класс данных
p1 = ptr;
if( p0!=NULL && p1!=NULL && p0<p1 ) {
memcpy( pdsc+(p0-buf), p1, len-(p1-buf) );
memcpy( pdsc+(len-(p1-p0)), p0, p1-p0 );
break;
}
}
}
}
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
return status;
}
#define MAX_NUMBER_OF_ENDPOINTS 8
// Установить канал массива как прерывание
if( URB_FUNCTION_SELECT_CONFIGURATION==urb->UrbHeader.Function ) {
USB_CONFIGURATION_DESCRIPTOR *pdsc;
UCHAR *ptr;
UCHAR *pend;
int i, j, bulk_count = 0;
UCHAR bulk_addr[MAX_NUMBER_OF_ENDPOINTS];
// Присваиваем переменной конфигурацию дескриптора
pdsc = urb->UrbSelectConfiguration.ConfigurationDescriptor;
// Проверка ключа в регистре
use_bulk = RtlCheckRegistryKey(RTL_REGISTRY_SERVICES,USE_BULK)==STATUS_SUCCESS;
// Собственно замена канала массива на прерывание
ptr = (UCHAR *)pdsc;
for( pend=ptr+pdsc->wTotalLength,ptr+=*ptr; ptr<pend; ptr+=*ptr ) {
if( *(ptr+1)==USB_ENDPOINT_DESCRIPTOR_TYPE ) {
if( *(ptr+3)==USB_ENDPOINT_TYPE_BULK ) {
*(ptr+3) = USB_ENDPOINT_TYPE_INTERRUPT;
if( !use_bulk ) {
if( *(ptr+4)<8 )
*(ptr+4) = 8;
}
*(ptr+6) = 10;
if( bulk_count<MAX_NUMBER_OF_ENDPOINTS )
bulk_addr[bulk_count++] = *(ptr+2);
}
else if( *(ptr+3)==USB_ENDPOINT_TYPE_INTERRUPT )
intr_addr = *(ptr+2);
}
}
// Модифицируем текущий указатель на IRP пакет
IoSkipCurrentIrpStackLocation (Irp);
// Вызываем нижестоящий драйвер
status = IoCallDriver (deviceExtension->NextLowerDriver, Irp);
if( NT_SUCCESS(status) && bulk_count ) {
USBD_INTERFACE_INFORMATION *interface_info;
interface_info = (USBD_INTERFACE_INFORMATION *)&urb
->UrbSelectConfiguration.Interface;
if( interface_info!=NULL ) {
for( i=0; i<(int)interface_info->NumberOfPipes; i++ ) {
USBD_PIPE_INFORMATION *pipe_info = &interface_info->Pipes[i];
// Извлекаем перемещенные конечные точки
if( pipe_info!=NULL ) {
for( j=0; j<bulk_count; j++ ) {
if( pipe_info->EndpointAddress==bulk_addr[j] ) {
if(pipe_info->PipeHandle!=NULL) {
if( use_bulk ) {
UCHAR *ph = (UCHAR *)pipe_info->PipeHandle;
if( *(ph+7)==UsbdPipeTypeInterrupt ) {
*(ph+7) = UsbdPipeTypeBulk;
*(ph+10) = 0;
}
}
pipe_info->PipeType = UsbdPipeTypeBulk;
pipe_info->Interval = 0;
}
break;
}
}
}
}
}
}
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
return status;
}
// Игнорировать неиспользуемые запросы прерываний
if( URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER==urb->UrbHeader.Function &&
*((UCHAR *)urb->UrbBulkOrInterruptTransfer.PipeHandle+6)==intr_addr ) {
IoSkipCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = status = STATUS_INTERNAL_ERROR;
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
return status;
}
// Модифицируем текущий указатель на IRP пакет
IoSkipCurrentIrpStackLocation (Irp);
// Вызываем нижестоящий драйвер
status = IoCallDriver (deviceExtension->NextLowerDriver, Irp);
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
return status;
}
Заключение
В ходе проектирования драйвера были выполнены задачи подключения и отключения USB-устройства в системе в общей устройств Windows. Реализованы алгоритмы загрузки и выгрузки драйвера с освобождением памяти, основные запросы IRP пакетов, распределение не идентифицированных пакетов нижестоящим драйверам, а также возможность подключения нескольких подобных USB-устройств.
Установка драйвера осуществляется использованием Мастера установки устройств PnP Windows с использованием .inf файла настроек. Для компиляции самого драйвера мной применялся пакет WDK (Windows Driver Kit 7600.1). Отладка драйвера осуществлялась применением средств WDK и Windbg.
Список использованных источников
1. Солдатов В.П. Интерфейсы USB. Практика использования и программирования. -- СПб.: БХВ-Петербург, 2010.--576 с.
2. Комиссарова В. - Программирование драйверов для Windows 2008
3. Агуров, П.В. Интерфейс USB. Практика использования и программирование/ П.В. Агуров. - СПб:БХВ-Петербург, 2011. - 576с.
4. Материалы сайта www.microsoft.com
5. Developing a WDF USB Kernel Mode Driver [электронный ресурс]. - Режим доступа: http://www.codeproject.com/Articles/13620/Developing-a-WDF-USB-Kernel-Mode-Driver-for-the-OS
Размещено на Allbest.ru
Подобные документы
Архитектура Windows NT 5. Приоритеты выполнения программного кода. Описание формата MIDI-данных. Установка драйвера в системе. Выбор средств разработки программного обеспечения. Обработка запросов драйверной модели WDM. Использование библиотеки DirectKS.
курсовая работа [498,8 K], добавлен 24.06.2009Разработка драйвера под Linux, отслеживающего выделение и освобождение процессами виртуальной памяти и выделение физических страниц при страничных отказах. Компиляция драйвера и работа с ним. Экспериментальная проверка работоспособности драйвера.
курсовая работа [43,5 K], добавлен 18.06.2009Использование драйвера режима ядра и управляющего приложения для создания системных потоков. Имитация обработки данных и организация задержек. Разработка драйвера на языке C++. Конфигурация тестового стенда. Точность изменения задержек и работы таймера.
курсовая работа [182,4 K], добавлен 24.06.2009Повышение быстродействия операционной системы. Разработка драйверов для средств хранения данных, управление работой устройства командами PnP. Создание, настройка параметров и установка классового драйвера виртуального диска, его структура и свойства.
курсовая работа [163,2 K], добавлен 18.06.2009Механизмы взаимодействия драйвера режима ядра и пользовательского приложения: многослойная драйверная архитектура, алгоритм сокрытия данных, взаимодействие драйвера и приложения, пользовательский интерфейс программы фильтрации доступа к файлам.
курсовая работа [1023,3 K], добавлен 23.06.2009Описание принципа работы драйвера. Установка и регистрация драйвера. Назначение и возможности утилиты TestTerminals.exe. Использование редактора форм. Создание форм с помощью редактора задач. Последовательность выполнения операций и обработок данных.
курсовая работа [843,6 K], добавлен 09.11.2011Разработка драйверов ядра Windows. Драйвер виртуальных устройств Windows - компьютерная программа, с помощью которой другая программа получает доступ к аппаратному обеспечению стандартным образом. Доступ к драйверам из приложений пользовательского режима.
курсовая работа [436,1 K], добавлен 25.10.2012Зростання ролі світлодіодного освітлення. Застосування надяскравих світлодіодів. Огляд драйверів живлення світлодіодних світильників. Опис роботи мікроконтролера на мікросхемі VIPer17 по схемі функціональній. Схема принципова драйвера білих світлодіодів.
дипломная работа [2,2 M], добавлен 22.04.2011Инициализация графического драйвера и режима. Функции доступа к видеопамяти. Подключение графической библиотеки. Инициализация графического режима. Включение драйвера, шрифтов в исполняемый файл. Рисование геометрических фигур. Вывод числовой информации.
лабораторная работа [77,2 K], добавлен 06.07.2009Призначення драйверів та порядок роботи з драйверами в MS-DOS. Розробка драйверів консолі. Структура драйвера та призначення компонентів. Розробка структури алгоритму, програми налагодження драйвера. Опис змінних програми та роботи модулів програми.
курсовая работа [1,0 M], добавлен 22.06.2012