012d01ec29
git-svn-id: svn://kolibrios.org@3843 a494cfbc-eb01-0410-851d-a64ba20cac60
249 lines
16 KiB
Plaintext
249 lines
16 KiB
Plaintext
Когда ядро обнаруживает подключенное устройство USB, оно настраивает его
|
||
согласно USB-протокола - SET_ADDRESS + SET_CONFIGURATION. Всегда
|
||
устанавливается первая конфигурация. Ядро также читает дескриптор
|
||
устройства, чтобы показать некоторую информацию, читает и анализирует
|
||
дескриптор конфигурации. Для каждого интерфейса ядро будет искать класс этого
|
||
интерфейса и попытается загрузить соответствующий драйвер COFF. В настоящее
|
||
время соответствие кодов классов и имен драйверов жестко прописано в коде ядра
|
||
и выглядит следующим образом:
|
||
3 = usbhid.obj,
|
||
7 = usbprint.obj,
|
||
8 = usbstor.obj,
|
||
9 = поддерживаются самим ядром,
|
||
другие = usbother.obj.
|
||
|
||
Драйвер должен быть стандартным драйвером в формате COFF, экспортирующим
|
||
процедуру под названием "START" и переменную "version". Загрузчик вызывает
|
||
процедуру "START" как STDCALL с одним параметром DRV_ENTRY = 1. При завершении
|
||
работы системы, если инициализация драйвера была успешна, "START" процедуру
|
||
также вызывает код остановки системы с одним параметром DRV_EXIT = -1.
|
||
|
||
Драйвер должен зарегистрировать себя в качестве драйвера USB в процедуре
|
||
"START". Это делается путем вызова экспортируемой ядром функции RegUSBDriver и
|
||
возврата её результата в качестве результата "START" процедуры.
|
||
|
||
void* __stdcall RegUSBDriver(
|
||
const char* name,
|
||
void* handler,
|
||
const USBFUNC* usbfunc
|
||
);
|
||
|
||
Параметр 'name' должен совпадать с именем драйвера, например "usbhid" для
|
||
usbhid.obj.
|
||
|
||
Параметр 'handler' является необязательным. Если он не NULL, то он должен
|
||
указывать на стандартный обработчик IOCTL интерфейса, как в обычном (не-USB)
|
||
драйвере.
|
||
|
||
Параметр "Usbfunc" представляет собой указатель на следующую структуру:
|
||
|
||
struc USBFUNC
|
||
{
|
||
.strucsize dd ? ; размер структуры, включая это поле
|
||
.add_device dd ? ; указатель на AddDevice процедуру в драйвере
|
||
; (необходимо)
|
||
.device_disconnect dd ? ; указатель на DeviceDisconnected процедуру в драйвере
|
||
; опционально, может быть NULL
|
||
; В будущем могут быть добавлены другие функции
|
||
}
|
||
|
||
Драйвер ДОЛЖЕН реализовать функцию:
|
||
|
||
void* __stdcall AddDevice(
|
||
void* pipe0,
|
||
void* configdescr,
|
||
void* interfacedescr
|
||
);
|
||
|
||
Параметр "Pipe0" - хэндл контрольного канала для нулевой конечной точки
|
||
устройства. Он может быть использован в качестве аргумента для
|
||
USBControlTransferAsync (см. далее).
|
||
|
||
Параметр 'configdescr' указывает на дескриптор конфигурации и все связанные с
|
||
ним данные, представленные так, как их возвращает запрос GET_DESCRIPTOR.
|
||
Полный размер данных содержится в поле Length самого дескриптора.
|
||
(см. USB2.0 spec.)
|
||
|
||
Параметр 'interfacedescr' указывает на дескриптор интерфейса инициализируемого
|
||
в данный момент. Это указатель на данные находящиеся внутри структуры
|
||
"configdescr". (Помним, что структура INTERFACE_DESCRIPTOR, находится внутри
|
||
структуры CONFIGURATION_DESCRIPTOR. См. USB2.0 Spec.) Обратите внимание, что
|
||
одно устройство может реализовывать много интерфейсов и AddDevice может быть
|
||
вызвана несколько раз с одним "configdescr" но разными "interfacedescr".
|
||
|
||
Возвращенное значение NULL показывает, что инициализация не была успешной.
|
||
Любое другое значение означает инициализацию устройства. Ядро не делает попыток
|
||
как-то интерпретировать это значение. Это может быть, например, указатель на
|
||
внутренние данные драйвера в памяти, выделенной с помощью Kmalloc или индексом
|
||
в какой-то своей таблице. (Помните, что Kmalloc() НЕ stdcall-функция! Она
|
||
портит регистр ebx!)
|
||
|
||
Драйвер МОЖЕТ реализовать функцию:
|
||
|
||
void __stdcall DeviceDisconnected(
|
||
void* devicedata
|
||
);
|
||
|
||
Если данная функция реализована, то ядро вызывает её, когда устройство
|
||
отключено, посылая ей в качестве параметра "devicedata" то, что было возвращено
|
||
ему функцией "AddDevice" при старте драйвера.
|
||
|
||
Драйвер может использовать следующие функции экспортируемые ядром:
|
||
|
||
void* __stdcall USBOpenPipe(
|
||
void* pipe0,
|
||
int endpoint,
|
||
int maxpacketsize,
|
||
int type,
|
||
int interval
|
||
);
|
||
|
||
Параметр "Pipe0" - хэндл контрольного канала для нулевой конечной точки
|
||
устройства. Используется для идентификации устройства.
|
||
|
||
Параметр "endpoint" номер конечной точки USB. Младшие 4 бита, собственно, номер
|
||
точки, а бит 7 имеет следующее значение: 0 - для OUT точки, 1 - для IN точки.
|
||
Остальные биты должны быть равны нулю.
|
||
|
||
Параметр "maxpacketsize" устанавливает максимальный размер пакета для канала.
|
||
|
||
Параметр "type" устанавливает тип передачи для конечной точки, как это прописано
|
||
в USB спецификации:
|
||
|
||
0 = control,
|
||
1 = isochronous (сейчас не поддерживается),
|
||
2 = bulk,
|
||
3 = interrupt.
|
||
|
||
Параметр "interval" игнорируется для control и bulk передач. Для конечных точек
|
||
по прерываниям устанавливает периодичность опроса в миллисекундах.
|
||
|
||
Функция возвращает хэндл канала при успешном его открытии либо NULL при ошибке.
|
||
Хэндл канала обращается в NULL когда:
|
||
а) канал будет явно закрыт функцией USBClosePipe (см. ниже);
|
||
б) была выполнена предоставленная драйвером функция "DeviceDisconnected".
|
||
|
||
void __stdcall USBClosePipe(
|
||
void* pipe
|
||
);
|
||
|
||
Освобождает все ресурсы, связанные с выбранным каналом. Единственный параметр -
|
||
указатель на хэндл, который был возвращен функцией USBOpenPipe при открытии
|
||
канала. Когда устройство отключается, все связанные с ним каналы закрываются
|
||
ядром; нет необходимости в самостоятельном вызове этой функции.
|
||
|
||
void* __stdcall USBNormalTransferAsync(
|
||
void* pipe,
|
||
void* buffer,
|
||
int size,
|
||
void* callback,
|
||
void* calldata,
|
||
int flags
|
||
);
|
||
void* __stdcall USBControlTransferAsync(
|
||
void* pipe,
|
||
void* setup,
|
||
void* buffer,
|
||
int size,
|
||
void* callback,
|
||
void* calldata,
|
||
int flags
|
||
);
|
||
|
||
Первая функция ставит в очередь bulk или interrupt передачу для выбранного
|
||
канала. Тип и направление передачи фиксированы для bulk и interrupt типов
|
||
конечных точек, как это было выбрано функцией USBOpenPipe.
|
||
Вторая функция ставит в очередь control передачу для выбранного канала.
|
||
Направление этой передачи определяется битом 7 байта 0 пакета "setup"
|
||
(0 - для OUT, 1 - для IN передачи). Эта функция возвращает управление немедленно.
|
||
По окончании передачи вызывается функция "callback" заданная как аргумент
|
||
USB______TransferAsync.
|
||
|
||
Параметр "pipe" - хэндл, возвращенный функцией USBOpenPipe.
|
||
|
||
Параметр 'setup' функции USBControlTransferAsync указывает на 8-байтный
|
||
конфигурационный пакет (см. USB2.0 Spec).
|
||
|
||
Параметр "buffer" - это указатель на буфер. Для IN передач он будет заполнен
|
||
принятыми данными. Для OUT передач он должен быть заполнен данными, которые мы
|
||
хотим передать. Указатель может быть NULL для пустых передач, либо для передач
|
||
control, если дополнительных данных не требуется.
|
||
|
||
Параметр "size" - это размер данных для передачи. Он может быть равен 0 для
|
||
пустых передач, либо для передач control, если дополнительных данных не требуется.
|
||
|
||
Параметр "callback" - это указатель на функцию, которая будет вызвана по
|
||
окончании передачи.
|
||
|
||
Параметр "calldata" будет передан функции "callback" вызываемой по окончании
|
||
передачи. Например, он может быть NULL или указывать на данные устройства или
|
||
указывать на данные используемые как дополнительные параметры, передаваемые от
|
||
вызывающей USB_____TransferAsync функции в callback функцию.
|
||
|
||
Другие данные, связанные с передачей, могут быть помещены до буфера (по смещению)
|
||
или после него. Они могут быть использованы из callback-функции, при необходимости.
|
||
|
||
Параметр "flags" - это битовое поле. Бит 0 игнорируется для OUT передач. Для IN
|
||
передач он означает, может ли устройство передать меньше данных (бит=1), чем
|
||
определено в "size" или нет (бит=0). Остальные биты не используются и должны
|
||
быть равны 0.
|
||
|
||
Возвращаемое функциями значение равно NULL в случае ошибки и не NULL если
|
||
передача успешно поставлена в очередь. Если происходит ошибка при передаче, то
|
||
callback функция будет об этом оповещена.
|
||
|
||
void __stdcall CallbackFunction(
|
||
void* pipe,
|
||
int status,
|
||
void* buffer,
|
||
int length,
|
||
void* calldata
|
||
);
|
||
|
||
Параметры 'pipe', 'buffer', 'calldata' значат то же, что и для
|
||
USB_____TransferAsync.
|
||
|
||
Параметр "length" это счетчик переданных байт. Для control передач он отражает
|
||
дополнительные 8 байт этапа SETUP. Т.е. 0 означает ошибку на этапе SETUP, а
|
||
"size"+8 успешную передачу.
|
||
|
||
Параметр "status" не равен 0 в случае ошибки:
|
||
USB_STATUS_OK = 0 ; без ошибок
|
||
USB_STATUS_CRC = 1 ; ошибка контрольной суммы
|
||
USB_STATUS_BITSTUFF = 2 ; ошибка инверсии битов (bitstuffing)
|
||
USB_STATUS_TOGGLE = 3 ; data toggle mismatch
|
||
; (Нарушение последовательности DAT0/DAT1)
|
||
USB_STATUS_STALL = 4 ; устройство возвратило STALL статус (остановлено)
|
||
USB_STATUS_NORESPONSE = 5 ; устройство не отвечает
|
||
USB_STATUS_PIDCHECK = 6 ; ошибка в поле PacketID (PID)
|
||
USB_STATUS_WRONGPID = 7 ; неожидаемое PacketID (PID) значение
|
||
USB_STATUS_OVERRUN = 8 ; слишком много данных от конечной точки
|
||
USB_STATUS_UNDERRUN = 9 ; слишком мало данных от конечной точки
|
||
USB_STATUS_BUFOVERRUN = 12 ; переполнение внутреннего буфера контроллера
|
||
; возможна только для изохронных передач
|
||
USB_STATUS_BUFUNDERRUN = 13 ; опустошение внутреннего буфера контроллера
|
||
; возможна только для изохронных передач
|
||
USB_STATUS_CLOSED = 16 ; канал закрыт либо через ClosePipe, либо в
|
||
; результате отключения устройства
|
||
|
||
Если несколько передач были поставлены в очередь для одного канала, то callback
|
||
функции для них будут вызываться в порядке постановки передач в очередь.
|
||
Если канал был закрыт ввиду USBClosePipe или отключения устройства, то callback
|
||
функции (если очередь передач не пуста) получат USB_STATUS_CLOSED.
|
||
Вызов DeviceDisconnected() последует после отработки всех оставшихся в очереди
|
||
callback функций.
|
||
|
||
void* __stdcall USBGetParam(void* pipe0, int param);
|
||
|
||
Возвращает указатель на некоторые параметры устройства запомненные ядром при
|
||
инициализации первой конфигурации. Не передает ничего устройству по шине.
|
||
|
||
pipe0 - хэндл контрольного канала для нулевой конечной точки устройства.
|
||
|
||
param - выбор возвращаемого параметра:
|
||
0 - возвратить указатель на дескриптор устройства;
|
||
1 - возвратить указатель на дескриптор конфигурации;
|
||
2 - возвратить режим шины устройства:
|
||
USB_SPEED_FS = 0 ; full-speed
|
||
USB_SPEED_LS = 1 ; low-speed
|
||
USB_SPEED_HS = 2 ; high-speed |