Написать самый простой USB драйвер?
Код:
/*==================================================================================*/
#include <ntddk.h>
#include "testdrv.h"
//ИМЯ НАШЕГО ДРАЙВЕРА УСТРОЙСТВА
#define DEVICE_NAME_STRING L"testdriver"
/*==================================================================================*/
//ЗАГОЛОВКИ ФУНКЦИЙ-ОБРАБОТЧИКОВ
VOID OnUnloadHandle(IN PDRIVER_OBJECT);
NTSTATUS IrpHandler(IN PDEVICE_OBJECT, IN PIRP);
NTSTATUS OnDeviceControlHandle(IN PDEVICE_OBJECT, IN PIRP);
NTSTATUS OnAddDeviceHandle(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
/*==================================================================================*/
/*ТОЧКА ВХОДА В ДРАЙВЕР. ВЫПОЛНЯЕТСЯ ПРИ ЗАГРУЗКЕ.*/
void TestDriver(void)
{
/*======================================================================*/
DbgPrint("TestDriver");
/*======================================================================*/
}
/*==================================================================================*/
/*ПРОЦЕДУРА ВХОДА ДРАЙВЕРА. ЭТА ПРОЦЕДУРА ВЫЗЫВАЕТСЯ ТОЛЬКО РАЗ
ПОСЛЕ ЗАГРУЗКИ ДРАЙВЕРА В ПАМЯТЬ.*/
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT deviceObject;
NTSTATUS status;
int i;
WCHAR NameBuffer[] = L"\\Device\\" DEVICE_NAME_STRING;
WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING;
UNICODE_STRING uniNameString, uniDOSString;
/*======================================================================*/
DbgPrint("DriverEntry");
/*======================================================================*/
//СОЗДАНИЕ БУФЕРОВ ДЛЯ ИМЕН
RtlInitUnicodeString(&uniNameString, NameBuffer);
RtlInitUnicodeString(&uniDOSString, DOSNameBuffer);
//ИНИЦИАЛИЗАЦИЯ ОБЪЕКТА ДРАЙВЕРА
status = IoCreateDevice(DriverObject, 0, &uniNameString, FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject);
if(!NT_SUCCESS(status))
return status;
//СОЗДАНИЕ СИМВОЛЬНОГО ИМЕНИ ДРАЙВЕРА
status = IoCreateSymbolicLink(&uniDOSString, &uniNameString);
if(!NT_SUCCESS(status))
return status;
//ИНИЦИАЛИЗИРУЕМ ТОЧКИ ВХОДА ДРАЙВЕРА В ОБЪЕКТЕ ДРАЙВЕРА.
for (i=0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
DriverObject->MajorFunction[i]= IrpHandler;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = OnDeviceControlHandle;
DriverObject->DriverUnload = OnUnloadHandle;
DriverObject->DriverExtension->AddDevice = /*(PDRIVER_ADD_DEVICE)*/ OnAddDeviceHandle;/*???*/
return(STATUS_SUCCESS);
}
/*==================================================================================*/
/*ВЫЗЫВАЕТСЯ ПРИ ВЫЗОВЕ CreateProcess() ИЗ ПОЛЬЗОВАТЕЛЬСКОГО РЕЖИМА РАБОТЫ.
АДРЕС ЭТОЙ ПРОЦЕДУРЫ БЫЛ ЗАРЕГИСТРИРОВАН В ПРОЦЕДУРЕ DriverEntry,
КАК ОБРАБОТЧИК РАБОЧЕЙ ПРОЦЕДУРЫ IRP_MJ_CREATE.*/
NTSTATUS OnAddDeviceHandle(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject)
{
/*======================================================================*/
DbgPrint("OnAddDeviceHandle");
/*======================================================================*/
return(STATUS_SUCCESS);
}
/*==================================================================================*/
/*ВЫЗЫВАЕТСЯ ПРИ ОБРАБОТКЕ ЛЮБОЙ РАБОЧЕЙ ПРОЦЕДУРЫ, КРОМЕ
ПРОЦЕДУРЫ IRP_MJ_DEVICE_CONTROL, ОБРАБАТЫВАЕМОЙ ОТДЕЛЬНО*/
NTSTATUS IrpHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
/*======================================================================*/
DbgPrint("IrpHandle");
/*======================================================================*/
//ЗАВЕРШЕНИЕ ОБРАБОТКИ
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
/*==================================================================================*/
/*ВЫЗЫВАЕТСЯ ПРИ ВЫГРУЗКЕ ДРАЙВЕРА. АДРЕС ЭТОЙ ПРОЦЕДУРЫ БЫЛ ЗАРЕГИСТРИРОВАН В ПРОЦЕДУРЕ DriverEntry,
КАК ОБРАБОТЧИК СОБЫТИЯ DriverUnload.*/
VOID OnUnloadHandle(IN PDRIVER_OBJECT DriverObject)
{
//СИМВОЛЬНОЕ ИМЯ ДРАЙВЕРА
WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING;
UNICODE_STRING uniDOSString;
/*======================================================================*/
DbgPrint("OnUnloadHandle");
/*======================================================================*/
RtlInitUnicodeString(&uniDOSString, DOSNameBuffer);//ИНИЦИАЛИЗАЦИЯ БУФЕРА ДЛЯ СИМВОЛЬНОГО ИМЕНИ
IoDeleteSymbolicLink (&uniDOSString);//УДАЛЕНИЕ СИМВОЛЬНОГО ИМЕНИ
IoDeleteDevice(DriverObject->DeviceObject);//УДАЛЕНИЕ ОБЪЕКТА ДРАЙВЕРА
}
/*==================================================================================*/
/*ВЫЗЫВАЕТСЯ ПРИ ВЫЗОВЕ DeviceIoControl ИЗ ПОЛЬЗОВАТЕЛЬСКОГО РЕЖИМА РАБОТЫ.
АДРЕС ЭТОЙ ПРОЦЕДУРЫ БЫЛ ЗАРЕГИСТРИРОВАН В ПРОЦЕДУРЕ DriverEntry,
КАК ОБРАБОТЧИК РАБОЧЕЙ ПРОЦЕДУРЫ IRP_MJ_DEVICE_CONTROL.*/
NTSTATUS OnDeviceControlHandle(IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PIO_STACK_LOCATION irpSp;
ULONG inBufLength;//ДЛИНА ВХОДНОГО БУФЕРА
ULONG outBufLength;//ДЛИНА ВЫХОДНОГО БУФЕРА
PULONG ioBuffer;//УКАЗАТЕЛЬ НА ВХОДНОЙ И ВЫХОДНОЙ БУФЕР
/*======================================================================*/
DbgPrint("OnDeviceControlHandle");
/*======================================================================*/
irpSp = IoGetCurrentIrpStackLocation(pIrp);//УКАЗАТЕЛЬ НА ДРАЙВЕРНЫЙ СТЕК
//ВХОДНОЙ И ВЫХОДНОЙ БУФЕРА И ИХ ДЛИНЫ
inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
ioBuffer = (PULONG) pIrp->AssociatedIrp.SystemBuffer;
switch(irpSp->Parameters.DeviceIoControl.IoControlCode)
{
//ОБРАБОТКА КОДА ФУНКЦИИ IOCTL_IOPM_FUNCTION1
case IOCTL_IOPM_FUNCTION1:
{
/*======================================================================*/
DbgPrint(">IOCTL_IOPM_FUNCTION1");
/*======================================================================*/
if(inBufLength > 0)
{
/*======================================================================*/
DbgPrint(">IOCTL_IOPM_FUNCTION1 inBufLength > 0");
/*======================================================================*/
ioBuffer[0]++;
}
break;
}
//ОБРАБОТКА КОДА ФУНКЦИИ IOCTL_IOPM_FUNCTION2
case IOCTL_IOPM_FUNCTION2:
{
/*======================================================================*/
DbgPrint(">IOCTL_IOPM_FUNCTION1");
/*======================================================================*/
if(inBufLength > 0)
{
/*======================================================================*/
DbgPrint(">IOCTL_IOPM_FUNCTION2 inBufLength > 0");
/*======================================================================*/
ioBuffer[0]--;
}
break;
}
}
//ЗАВЕРШЕНИЕ РАБОЧЕЙ ПРОЦЕДУРЫ
pIrp->IoStatus.Information = inBufLength;/*РАЗМЕР ВЫХОДНОГО БУФЕРА*/
pIrp->IoStatus.Status = ntStatus;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return ntStatus;
}
/*==================================================================================*/
#include <ntddk.h>
#include "testdrv.h"
//ИМЯ НАШЕГО ДРАЙВЕРА УСТРОЙСТВА
#define DEVICE_NAME_STRING L"testdriver"
/*==================================================================================*/
//ЗАГОЛОВКИ ФУНКЦИЙ-ОБРАБОТЧИКОВ
VOID OnUnloadHandle(IN PDRIVER_OBJECT);
NTSTATUS IrpHandler(IN PDEVICE_OBJECT, IN PIRP);
NTSTATUS OnDeviceControlHandle(IN PDEVICE_OBJECT, IN PIRP);
NTSTATUS OnAddDeviceHandle(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
/*==================================================================================*/
/*ТОЧКА ВХОДА В ДРАЙВЕР. ВЫПОЛНЯЕТСЯ ПРИ ЗАГРУЗКЕ.*/
void TestDriver(void)
{
/*======================================================================*/
DbgPrint("TestDriver");
/*======================================================================*/
}
/*==================================================================================*/
/*ПРОЦЕДУРА ВХОДА ДРАЙВЕРА. ЭТА ПРОЦЕДУРА ВЫЗЫВАЕТСЯ ТОЛЬКО РАЗ
ПОСЛЕ ЗАГРУЗКИ ДРАЙВЕРА В ПАМЯТЬ.*/
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT deviceObject;
NTSTATUS status;
int i;
WCHAR NameBuffer[] = L"\\Device\\" DEVICE_NAME_STRING;
WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING;
UNICODE_STRING uniNameString, uniDOSString;
/*======================================================================*/
DbgPrint("DriverEntry");
/*======================================================================*/
//СОЗДАНИЕ БУФЕРОВ ДЛЯ ИМЕН
RtlInitUnicodeString(&uniNameString, NameBuffer);
RtlInitUnicodeString(&uniDOSString, DOSNameBuffer);
//ИНИЦИАЛИЗАЦИЯ ОБЪЕКТА ДРАЙВЕРА
status = IoCreateDevice(DriverObject, 0, &uniNameString, FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject);
if(!NT_SUCCESS(status))
return status;
//СОЗДАНИЕ СИМВОЛЬНОГО ИМЕНИ ДРАЙВЕРА
status = IoCreateSymbolicLink(&uniDOSString, &uniNameString);
if(!NT_SUCCESS(status))
return status;
//ИНИЦИАЛИЗИРУЕМ ТОЧКИ ВХОДА ДРАЙВЕРА В ОБЪЕКТЕ ДРАЙВЕРА.
for (i=0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
DriverObject->MajorFunction[i]= IrpHandler;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = OnDeviceControlHandle;
DriverObject->DriverUnload = OnUnloadHandle;
DriverObject->DriverExtension->AddDevice = /*(PDRIVER_ADD_DEVICE)*/ OnAddDeviceHandle;/*???*/
return(STATUS_SUCCESS);
}
/*==================================================================================*/
/*ВЫЗЫВАЕТСЯ ПРИ ВЫЗОВЕ CreateProcess() ИЗ ПОЛЬЗОВАТЕЛЬСКОГО РЕЖИМА РАБОТЫ.
АДРЕС ЭТОЙ ПРОЦЕДУРЫ БЫЛ ЗАРЕГИСТРИРОВАН В ПРОЦЕДУРЕ DriverEntry,
КАК ОБРАБОТЧИК РАБОЧЕЙ ПРОЦЕДУРЫ IRP_MJ_CREATE.*/
NTSTATUS OnAddDeviceHandle(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject)
{
/*======================================================================*/
DbgPrint("OnAddDeviceHandle");
/*======================================================================*/
return(STATUS_SUCCESS);
}
/*==================================================================================*/
/*ВЫЗЫВАЕТСЯ ПРИ ОБРАБОТКЕ ЛЮБОЙ РАБОЧЕЙ ПРОЦЕДУРЫ, КРОМЕ
ПРОЦЕДУРЫ IRP_MJ_DEVICE_CONTROL, ОБРАБАТЫВАЕМОЙ ОТДЕЛЬНО*/
NTSTATUS IrpHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
/*======================================================================*/
DbgPrint("IrpHandle");
/*======================================================================*/
//ЗАВЕРШЕНИЕ ОБРАБОТКИ
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
/*==================================================================================*/
/*ВЫЗЫВАЕТСЯ ПРИ ВЫГРУЗКЕ ДРАЙВЕРА. АДРЕС ЭТОЙ ПРОЦЕДУРЫ БЫЛ ЗАРЕГИСТРИРОВАН В ПРОЦЕДУРЕ DriverEntry,
КАК ОБРАБОТЧИК СОБЫТИЯ DriverUnload.*/
VOID OnUnloadHandle(IN PDRIVER_OBJECT DriverObject)
{
//СИМВОЛЬНОЕ ИМЯ ДРАЙВЕРА
WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING;
UNICODE_STRING uniDOSString;
/*======================================================================*/
DbgPrint("OnUnloadHandle");
/*======================================================================*/
RtlInitUnicodeString(&uniDOSString, DOSNameBuffer);//ИНИЦИАЛИЗАЦИЯ БУФЕРА ДЛЯ СИМВОЛЬНОГО ИМЕНИ
IoDeleteSymbolicLink (&uniDOSString);//УДАЛЕНИЕ СИМВОЛЬНОГО ИМЕНИ
IoDeleteDevice(DriverObject->DeviceObject);//УДАЛЕНИЕ ОБЪЕКТА ДРАЙВЕРА
}
/*==================================================================================*/
/*ВЫЗЫВАЕТСЯ ПРИ ВЫЗОВЕ DeviceIoControl ИЗ ПОЛЬЗОВАТЕЛЬСКОГО РЕЖИМА РАБОТЫ.
АДРЕС ЭТОЙ ПРОЦЕДУРЫ БЫЛ ЗАРЕГИСТРИРОВАН В ПРОЦЕДУРЕ DriverEntry,
КАК ОБРАБОТЧИК РАБОЧЕЙ ПРОЦЕДУРЫ IRP_MJ_DEVICE_CONTROL.*/
NTSTATUS OnDeviceControlHandle(IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PIO_STACK_LOCATION irpSp;
ULONG inBufLength;//ДЛИНА ВХОДНОГО БУФЕРА
ULONG outBufLength;//ДЛИНА ВЫХОДНОГО БУФЕРА
PULONG ioBuffer;//УКАЗАТЕЛЬ НА ВХОДНОЙ И ВЫХОДНОЙ БУФЕР
/*======================================================================*/
DbgPrint("OnDeviceControlHandle");
/*======================================================================*/
irpSp = IoGetCurrentIrpStackLocation(pIrp);//УКАЗАТЕЛЬ НА ДРАЙВЕРНЫЙ СТЕК
//ВХОДНОЙ И ВЫХОДНОЙ БУФЕРА И ИХ ДЛИНЫ
inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
ioBuffer = (PULONG) pIrp->AssociatedIrp.SystemBuffer;
switch(irpSp->Parameters.DeviceIoControl.IoControlCode)
{
//ОБРАБОТКА КОДА ФУНКЦИИ IOCTL_IOPM_FUNCTION1
case IOCTL_IOPM_FUNCTION1:
{
/*======================================================================*/
DbgPrint(">IOCTL_IOPM_FUNCTION1");
/*======================================================================*/
if(inBufLength > 0)
{
/*======================================================================*/
DbgPrint(">IOCTL_IOPM_FUNCTION1 inBufLength > 0");
/*======================================================================*/
ioBuffer[0]++;
}
break;
}
//ОБРАБОТКА КОДА ФУНКЦИИ IOCTL_IOPM_FUNCTION2
case IOCTL_IOPM_FUNCTION2:
{
/*======================================================================*/
DbgPrint(">IOCTL_IOPM_FUNCTION1");
/*======================================================================*/
if(inBufLength > 0)
{
/*======================================================================*/
DbgPrint(">IOCTL_IOPM_FUNCTION2 inBufLength > 0");
/*======================================================================*/
ioBuffer[0]--;
}
break;
}
}
//ЗАВЕРШЕНИЕ РАБОЧЕЙ ПРОЦЕДУРЫ
pIrp->IoStatus.Information = inBufLength;/*РАЗМЕР ВЫХОДНОГО БУФЕРА*/
pIrp->IoStatus.Status = ntStatus;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return ntStatus;
}
/*==================================================================================*/
это?
У меня получилось реализовать этот пример для ATmega8. Пример использует некую библиотеку состоящую из исходного кода на c++ и языке ассемблера. Прилагаю архив с проектом. Там много закомментированного кода, так как сначала управлял светодиодами, а потом экспериментировал с АЦП. Возможно тебе стоит проанализировать содержимое библиотеки.
Смотрел ли ты вот
У меня получилось реализовать этот пример для ATmega8. Пример использует некую библиотеку состоящую из исходного кода на c++ и языке ассемблера. Прилагаю архив с проектом. Там много закомментированного кода, так как сначала управлял светодиодами, а потом экспериментировал с АЦП. Возможно тебе стоит проанализировать содержимое библиотеки.
этой раздаче он есть.
Хотел дополнить. Прямо на твой вопрос ответить не смогу, т.к. не интересовался вопросом, но к книге прилагается диск с кучей рабочих примеров. В