Added documents created by UnКайF
git-svn-id: svn://kolibrios.org@3843 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
f8f9202a81
commit
012d01ec29
|
@ -0,0 +1,232 @@
|
|||
Дата последней правки 26/07/2013.
|
||||
Подсистема событий ядра может понадобиться при написании драйверов и сервисов, работающих в режиме ядра.
|
||||
Она не имеет отношения к подсистеме событий пользовательского интерфейса.
|
||||
С точки зрения ядра событие - объект ядра и принадлежит создавшему его потоку.
|
||||
|
||||
struc EVENT
|
||||
{
|
||||
.magic dd ? ; 'EVNT'
|
||||
.destroy dd ? ; internal destructor
|
||||
.fd dd ? ; next object in list
|
||||
.bk dd ? ; prev object in list
|
||||
.pid dd ? ; owner id. идентификатор владельца (потока)
|
||||
.id dd ? ; event uid. уникальный идентификатор события (просто номерок)
|
||||
.state dd ? ; internal flags; см. далее.
|
||||
.code dd ? ; старший байт класс события, ; следующий байт приоритет
|
||||
; (будет использоваться только внутри ядра, при чтении всегда 0),
|
||||
; Чем больше численное значение двойного слова тем важнее событие.
|
||||
; два младших байта код события.
|
||||
rd 5 ; .data - точная структура этого поля не определена и зависит
|
||||
; от поля .code. (Здесь можно передавать какие-то свои данные,
|
||||
; при необходимости :)
|
||||
.size = $ - .magic
|
||||
.codesize = $ - .code
|
||||
}
|
||||
|
||||
События реального времени получили класс 0хFF. Пока определёны только:
|
||||
EVENT.code= ;(Используется в звуковой подсистеме).
|
||||
RT_INP_EMPTY equ 0xFF000001
|
||||
RT_OUT_EMPTY equ 0xFF000002
|
||||
RT_INP_FULL equ 0xFF000003
|
||||
RT_OUT_FULL equ 0xFF000004
|
||||
|
||||
|
||||
Флаги поля EVENT.state определены в gui/event.inc.
|
||||
EVENT_SIGNALED equ 0x20000000 ;Бит 29 событие активно/неактивно;
|
||||
EVENT_WATCHED equ 0x10000000 ;бит 28, поток-владелец ожидает активации события;
|
||||
MANUAL_RESET equ 0x40000000 ;бит 30, не деактивировать событие автоматически по получении;
|
||||
MANUAL_DESTROY equ 0x80000000 ;бит 31, не возвращать событие в список свободных по получении.
|
||||
|
||||
На момент ревизии 3732 (и далее по тексту то же) определение находится в \kernel\trunk\const.inc
|
||||
и выглядит так:
|
||||
|
||||
struct APPOBJ ; common object header
|
||||
magic dd ? ;
|
||||
destroy dd ? ; internal destructor
|
||||
fd dd ? ; next object in list
|
||||
bk dd ? ; prev object in list
|
||||
pid dd ? ; owner id
|
||||
ends
|
||||
|
||||
struct EVENT APPOBJ
|
||||
id dd ? ;event uid
|
||||
state dd ? ;internal flags
|
||||
code dd ?
|
||||
rd 5 ; .data
|
||||
ends
|
||||
|
||||
Код находится в gui/event.inc.
|
||||
Сами события как обьекты существуют в памяти ядра в виде двусвязного списка (см. поля .bk и .fd).
|
||||
При инициализации ядро резервирует память и создает 512 таких обьектов, помещая их в список FreeEvents
|
||||
(свободных событий). При нехватке событий (все заняты, а нужно ещё) ядро создает ещё 512 свободных
|
||||
и т.д. Каждый поток имеет свои (двусвязные) списки (в которые может быть помещено событие):
|
||||
ObjList - список объектов ядра, ассоциированных с этим потоком;
|
||||
EventList - список событий ядра для потока.
|
||||
Сами события, физически, при перемещении между списками и смене очередности в списке не перемещаются
|
||||
и не копируются. Это происходит только благодаря модификации полей .fd и .bk. Принцип работы списков,
|
||||
как очередей - FIFO. Использутся неблокирующая отправка и блокирующее получение. Адресация - прямая
|
||||
(у события всегда есть поток-владелец), по идентификатору потока.
|
||||
|
||||
Жизненый цикл событий определяется флагами при создании. По умолчанию ядро использует значения
|
||||
MANUAL_RESET = 0 и MANUAL_DESTROY = 0. Такое событие является "одноразовым", и автоматически освобождается
|
||||
ядром, возвращаясь в список свободных событий после получения.
|
||||
Событие с флагом MANUAL_DESTROY = 1 после получения переходит в неактивное состояние, но остаётся в списке
|
||||
объектов потока и может использоваться снова. Событие с флагами MANUAL_DESTROY =1 и MANUAL_RESET = 1
|
||||
остаётся активным после получения и может быть сброшено вызовом ClearEvent.
|
||||
|
||||
Пример (вариант) жизненного цикла события из звуковой подсистемы:
|
||||
Для зукового буфера (их может быть несколько) драйвер создает событие в списке ObjList с помощью
|
||||
CreateEvent и флагом MANUAL_DESTROY. Далее драйвер вызывает WaitEvent для этого события (ожидает флага
|
||||
EVENT_SIGNALED в событии) и блокируется, в ожидании запроса на пополнение буфера. Запрос отправляется
|
||||
с помощью RaiseEvent из другого потока. Отправка (RaiseEvent) и получение (WaitEvent) циклически
|
||||
повторяются при опустошении буфера. При остановке воспроизведения драйвер деактивирует событие с помощью
|
||||
ClearEvent.
|
||||
|
||||
Вообще говоря, структура события приведена здесь только лишь для понимания принципов работы подсистемы.
|
||||
Самостоятельная работа с полями не приветствуется, ввиду возможных в будущем проблем с совместимостью.
|
||||
Работа должна производится только через API (функции подсистемы), с доступом только к тем полям, доступ к
|
||||
которым предоставляет функция. При этом пару "указатель на событие" и "уникальный идентификатор события"
|
||||
следует рассматривать как один 64-х битный уникальный идентификатор. (Если вы вызвали CreateEvent, напимер,
|
||||
его нужно запомнить где-нибудь [если это нужно] для дальнейшей работы с событием).
|
||||
|
||||
Функции для работы с событиями экспортитуемые ядром:
|
||||
(для драйверов и т.п.; вызываются в режиме ядра)
|
||||
|
||||
CreateEvent
|
||||
RaiseEvent
|
||||
ClearEvent
|
||||
SendEvent
|
||||
DestroyEvent
|
||||
WaitEvent
|
||||
WaitEventTimeout
|
||||
GetEvent
|
||||
Для пользовательских приложений Ф68.14 (GetEvent с обёрткой)
|
||||
|
||||
---------------------------------------------------------------------------------------------
|
||||
CreateEvent:
|
||||
Создаёт новое событие в очереди ObjList текущего потока.
|
||||
Устанавливает:
|
||||
EVENT.destroy <= внутренний деструктор по умолчанию;
|
||||
EVENT.pid <= текущий Process id;
|
||||
EVENT.id <= уникальный идентификатор;
|
||||
EVENT.state <= ecx - флаги;
|
||||
EVENT.code <= [esi], (если esi=0, то не копирует), размер 6*dword;
|
||||
Возвращает:
|
||||
eax - указатель на событие или 0 при ошибке.
|
||||
edx - Event.id.
|
||||
Портит: eax,ebx,edx,ecx,esi,edi
|
||||
---------------------------------------------------------------------------------------------
|
||||
RaiseEvent:
|
||||
Активирует уже существующее событие (может принадлежать другому потоку) установкой
|
||||
флага EVENT_SIGNALED. Если необходимо, - устанавливает данные EVENT.code.
|
||||
Если флаг EVENT_SIGNALED в самом событии уже активен - больше ничего не делает.
|
||||
Если EVENT_SIGNALED не установлен в самом событии, то он будет установлен, кроме случая
|
||||
{EVENT_WATCHED в edx=1 и EVENT_WATCHED в событии=0}.
|
||||
Т.е. при установке EVENT_WATCHED в edx, проверяется, ожидает ли поток-владелец активации
|
||||
события.
|
||||
Кроме EVENT_SIGNALED в событии никакие другие флаги не модифицируются.
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события;
|
||||
edx - флаги для операции (формат EVENT.state);
|
||||
EVENT.code <= [esi], (если esi=0, то не копирует), размер 6*dword;
|
||||
Возвращает: ?
|
||||
Портит: eax,ebx,edx,ecx,esi,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
ClearEvent:
|
||||
Перемещает событие в список ObjList потока-владельца. (Возможно оно там и находилось.)
|
||||
Сбрасывает флаги EVENT_SIGNALED, EVENT_WATCHED. С остальными полями (.code, .id),
|
||||
ничего не делает.
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события.
|
||||
Возвращает: ?
|
||||
Портит: eax,ebx,ecx,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
SendEvent:
|
||||
Создаёт новое событие в списке событий целевого потока. Устанавливает в событии
|
||||
флаг EVENT_SIGNALED.
|
||||
Принимает:
|
||||
EVENT.pid <= eax - pid, идентификатор целевого потока;
|
||||
EVENT.code <= [esi], (если esi=0, то не копирует), размер 6*dword;
|
||||
Возвращает:
|
||||
eax - указатель на событие или 0 при ошибке.
|
||||
edx - Event.id. уникальный идентификатор.
|
||||
Портит: eax,ebx,ecx,esi,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
DestroyEvent:
|
||||
Переносит EVENT в список FreeEvents, чистит поля .magic,.destroy,.pid,.id.
|
||||
Событие может принадлежать другому потоку.
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события.
|
||||
Возвращает:
|
||||
eax - 0 при ошибке, не 0 при успехе.
|
||||
Портит: eax,ebx,ecx .
|
||||
---------------------------------------------------------------------------------------------
|
||||
WaitEvent:
|
||||
Бесконечно ожидает установки флага EVENT_SIGNALED в конкретном событии, принадлежащем
|
||||
вызывающему WaitEvent потоку. Сигнализирующий поток устанавливат этот флаг через
|
||||
RaiseEvent. Ожидающий поток замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5.
|
||||
Перед заморозкой устанавливается флаг EVENT_WATCHED в событии.
|
||||
Если в полученном событии НЕ установлен MANUAL_RESET, то:
|
||||
{EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
|
||||
При неактивном MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
|
||||
а при активном - перемещается в список ObjList текущего слота.}
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события.
|
||||
Возвращает: ?
|
||||
Портит: eax,ebx,edx,ecx,esi,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
WaitEventTimeout:
|
||||
Ожидает с таймаутом установки флага EVENT_SIGNALED в конкретном событии, принадлежащем
|
||||
вызывающему WaitEventTimeout потоку. Сигнализирующий поток устанавливат этот флаг через
|
||||
RaiseEvent. Ожидающий поток замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5.
|
||||
Перед заморозкой устанавливается флаг EVENT_WATCHED в событии.
|
||||
Если в полученном событии НЕ установлен MANUAL_RESET, то:
|
||||
{EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
|
||||
При неактивном MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
|
||||
а при активном - перемещается в список ObjList текущего слота.}
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события.
|
||||
ecx - время ожидания в тиках системного таймера.
|
||||
Возвращает:
|
||||
eax - 0 - таймаут, если событие не активировалось, или
|
||||
не 0, если было активировано.
|
||||
Портит: eax,ebx,edx,ecx,esi,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
GetEvent:
|
||||
Бесконечно ожидает любое событие в очереди событий текущего потока. Поток замораживается
|
||||
путем перевода TASKDATA.state<=TSTATE_WAITING=5. Данные события (EVENT.code+5*dword)
|
||||
по получении копируются в указанный буфер. Сбрасывает байт приоритета (см. выше) в буфере.
|
||||
Если в полученном событии НЕ установлен MANUAL_RESET, то:
|
||||
{EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
|
||||
При неактивном MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
|
||||
а при активном - перемещается в список ObjList текущего слота.}
|
||||
Принимает:
|
||||
edi - указатель на буфер, куда копировать данные.
|
||||
Возвращает:
|
||||
буфер, содержащий следующую информацию:
|
||||
+0: (EVENT.code) dword: идентификатор последующих данных сигнала
|
||||
+4: (EVENT.data, поле формально не определено) данные принятого
|
||||
сигнала (5*dword), формат которых определяется первым dword-ом.
|
||||
Портит: eax,ebx,edx,ecx,esi,edi .
|
||||
--------------------------------------------------------------------------------------------
|
||||
Ф 68.14 для приложений: ;это тот же GetEvent, но с обёрткой.
|
||||
Бесконечно ожидает любое событие в очереди событий текущего потока. Ожидающий поток
|
||||
замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5. Данные события (EVENT.code+5*dword)
|
||||
копируются в указанный буфер. Сбрасывает байт приоритета (см. выше) в буфере.
|
||||
Принимает:
|
||||
eax - 68 - номер функции
|
||||
ebx - 14 - номер подфункции
|
||||
ecx - указатель на буфер для информации (размер 6*dword)
|
||||
Возвращает:
|
||||
буфер, на который указывает ecx, содержит следующую информацию:
|
||||
+0: (EVENT.code) dword: идентификатор последующих данных сигнала
|
||||
+4: (EVENT.data, поле формально не определено) данные принятого
|
||||
сигнала (5*dword), формат которых определяется первым dword-ом.
|
||||
Портит:
|
||||
eax .
|
||||
---------------------------------------------------------------------------------------------
|
|
@ -0,0 +1,249 @@
|
|||
Когда ядро обнаруживает подключенное устройство 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
|
Loading…
Reference in New Issue