Книга: Интерфейс USB (практика использования и программирования). Практическое использование интерфейса USB в PIC контроллерах Программирование usb контроллера

Хорошая книга, многое объясняет. Пригодится тем, кто хочет понять как происходит передача данных по шине USB.

Введение 1
Для кого эта книга: 2
Что вы найдете в книге 2
Программные требования 3
Аппаратные требования 4
О программном коде 4
Краткое описание глав 4
Обозначения 6
Благодарности 7
ЧАСТЬ I. ВВЕДЕНИЕ В USB 9
Глава 1. Что такое USB 11
1.1. История USB 11
1.2. Сравнение USB с другими интерфейсами 14
1.3. Основные понятия USB 16
1.3.1. Общая архитектура шины 16
1.3.2. Физическая и логическая архитектура шины 16
1.3.3. Составляющие USB 18
1.3.4. Свойства USB-устройств 18
1.3.5. Свойства хабов 19
1.3.6. Свойства хоста 20
1.4. Примеры USB-устройств 20
1.4.1. Мышь и клавиатура., 21
1.4.2. Мониторы 21
1.4.3. Переходники USB-to-COM и USB-to-LPT 22
1.4.4. Сканеры 23
1.4.5. Модемы 23
1.4.6. Звуковые колонки 24
1.4.7. Флеш-диски 25
1.4.8. Хабы 28
1.4.9. Измерительная техника 28
1.4.10. Экзотические устройства 29
1.5. Сетевое соединение через USB 30
1.5.1. Конвертер USB-Ethernet 31
1.5.2. Прямое соединение через USB-порт 31
1.6. Передача данных 31
1.6.1. Принципы передачи данных 32
1.6.2. Механизм прерываний 32
1.6.3. Интерфейсы хост-адаптера 32
1.6.4. Возможность прямого доступа к памяти 34
1.6.5. Режимы передачи данных 34
1.7. Установка и конфигурирование USB-устройств 35
1.7.1. Настройки BIOS для USB 38
1.7.2. Устранение проблем 41
1.8. Ограничения USB 45
1.9. Если вы покупаете компьютер 46
1.9.1. HS и USB 2.0 - не одно и то же! 46
1.9.2. Системная плата 47
1.9.3. Корпус 48
1.9.4. USB для “старых” моделей компьютеров 48
1.10. Интернет-ресурсы к этой главе 49
Глава 2. Аппаратное обеспечение USB 51
2.1. Кабели и разъемы 51
2.1.1. Типы кабелей 52
2.1.2. Длина кабеля 53
2.1.3. Разъемы 53
2.2. Физический интерфейс 55
2.2.1. Кодирование данных 57
2.2.2. Идентификация устройств 58
2.3. Питание 59
2.3.1. Типы питания USB-устройств 59
2.3.2. Управление энергопотреблением 60
2.3.3. Вход в режим низкого энергопотребления 61
2.4. Интернет-ресурсы к этой главе 61
ЧАСТЬ II. ВНУТРЕННЯЯ ОРГАНИЗАЦИЯ USB 63
Глава 3. Внутренняя организация шины 65
3.1. Логические уровни обмена данными 65
3.1.1. Уровень клиентского ПО 66
3.1.2. Уровень системного драйвера USB 67
3.1.3. Уровень хост-контроллера интерфейса 68
3.1.4. Уровень шины периферийного устройства 68
3.1.5. Уровень логического USB-устройства 69
3.1.6. Функциональный уровень USB-устройства 69
3.2. Передача данных по уровням 69
3.3. Типы передач данных 71
3.4. Синхронизация при изохронной передаче 73
3.5. Кадры 77
3.6. Конечные точки 78
3.7. Каналы 79
3.8. Пакеты 81
3.8.1. Формат пакетов-маркеров IN, OUT, SETUP и PING 83
3.8.2. Формат пакета SOF 83
3.8.3. Формат пакета данных 84
3.8.4. Формат пакета подтверждения < 84
3.8.5. Формат пакета SPLIT * 84
3.9. Контрольная сумма 85
3.9.1. Алгоритм вычисления CRC 86
3.9.2. Программное вычисление CRC 87
3.10. Транзакции 90
3.10.1. Типы транзакций 91
3.10.2. Подтверждение транзакций и управление потоком 92
3.10.3. Протоколы транзакций 93
Глава 4. Внутренняя организация устройства 96
4.1. Запросы к USB-устройствам 96
4.1.1. Конфигурационный пакет 96
4.1.2. Стандартные запросы к устройствам 99
4.1.3. Дескрипторы устройства 105
Глава 5. Внутренняя организация хоста и хабов 123
5.1. Хабы 123
5.1.1. Взаимодействие хост-контроллера с хабом 126
5.1.2. Дескриптор хаба 127
5.1.3. Запросы хабов 129
5.1.4. Запрос CLEAR_HUB_FEATURE 130
5.1.5. Запрос CLEAR PORT_FEATURE 130
5.1.6. Запрос GET_BUS_STA ТЕ 131
5.1.7. Запрос GET_HUB_DESCRfPTOR 131
5.1.8. Запрос GET_HUB_STATUS 131
5.1.9. Запрос GET_PORT_STA TUS 132
5.1.10. Запрос SET_HUB_DESCRIPTOR 134
5.1.11. Запрос SET_HUB_FEATURE 134
5.1.12. Запрос SET PORT FEATURE. 134
5.2. Совместная работа устройств с разными скоростями 135
Глава 6. USB без ПК 137
6.1. Разъемы OTG 138
6.2. Типы OTG-устройств 138
6.3. Дескриптор OTG-устройства 139
6.4. Интернет-ресурсы к этой главе 140
ЧАСТЬ III. ПРАКТИКА ПРОГРАММИРОВАНИЯ 141
Глава 7. Поддержка USB в Windows 143
7.1. Модель WDM 144
7.2. Взаимодействие с USB-драйвером 146
Глава 8. HID-устройства * 149
8.1. Свойства HID-устройства 149
8.2. Порядок обмена данными с HID-устройством 151
8.3. Установка HID-устройства 152
8.4. Идентификация HID-устройства 152
8.4.1. Идентификация загрузочных устройств 153
8.4.2. Дескриптор конфигурации HID-устройства 153
8.4.3. HID-дескриптор 154
8.4.4. Дескриптор репорта 156
8.5. Структура дескриптора репорта 156
8.5.1. Структура элементов репорта 156
8.5.2. Типы элементов репорта 157
8.5.3. Примеры дескрипторов 165
8.6. Запросы к HID-устройству 168
8.6.1. Запрос GET_REPORT. 169
8.6.2. Запрос SET_REPORT 169
8.6.3. Запрос GETJDLE. 170
8.6.4. Запрос SETJDLE 170
8.6.5. Запрос GET_PROTOCOL 171
8.6.6. Запрос SET_PROTOCOL 171
8.7. Инструментальные средства 171
8.8. Взаимодействие с HID-драйвером 172
Глава 9. Введение в WDM 181
9.1. Драйверные слои 183
9.2. Символьные имена устройств 184
9.3. Основные процедуры драйвера WDM 189
9.3.1. Процедура DriverEntry 190
9.3.2. Процедура AddDevice 192
9.3.3. Процедура Unload 194
9.3.4. Рабочие процедуры драйвера 196
9.3.5. Обслуживание запросов IOCTL 203
9.4. Загрузка драйвера и обращение к процедурам драйвера 209
9.4.1. Процедура работы с драйвером 209
9.4.2. Регистрация драйвера 210
9.4.3. Обращение к рабочим процедурам 217
9.4.4. Хранение драйвера внутри исполняемого файла 218
9.5. Инструменты создания драйверов 220
9.5.1. NuMega Driver Studio 220
9.5.2. Jungo WinDriver 220
9.5.3. Jungo KernelDriver 220
Глава 10. Спецификация PnP для USB 221
10.1. Общие сведения о системе Plug and Play 221
10.1.1. Задачи и функции Plug and Play 221
10.1.2. Запуск процедуры PnP 222
10.1.3. Программные компоненты PnP 224
10.2. Plug and Play для USB 225
10.2.1. Конфигурирование устройств USB 226
10.2.2. Нумерация устройств USB 226
10.2.3. PnP-идентификаторы устройств USB 228
10.3. Получение списка USB-устройств 229
10.4. INF-файл 234
10.4.1. Структура INF-файла 234
10.4.2. Секция Version 235
10.4.3. Секция Manufacturer 237
10.4.4. Секция DestinationDirs 239
10.4.5. Секция описания модели 241
10.4.6. Секция xxx.AddReg и xxx.DelReg. 242
10.4.7. Секция ххх.LogConfig 244
10.4.8. Секция xxx.CopyFiles 244
10.4.9. Секция Strings 245
10.4.10. Связи секций 246
10.4.11. Создание и тестирование INF-файлов 247
10.4.12. Установка устройств с помощью INF-файла 248
10.5. Ветки реестра для USB 249
Глава 11. Функции BIOS 251
11.1. Сервис BIOS 1АН 251
11.1.1. Функция В101Н - определение наличия PCI BIOS 252
11.1.2. Функция В102Н - поиск PCI-устройства по идентификаторам
устройства и производителя 253
11.1.3. Функция В103Н - поиск PCI-устройства по коду класса 254
11.1.4. Функция В108Н - чтение регистра конфигурации (Byte) 255
11.1.5. Функция ВЮ9Н - чтение регистра конфигурации (Word) 256
11.1.6. Функция В10АН - чтение регистра конфигурации (DWord) 256
11.1.7. Функция В10ВН - запись регистра конфигурации (Byte) 257
11.1.8. Функция В10СН - запись регистра конфигурации (Word) 257
11.1.9. Функция B10DH - запись регистра конфигурации (DWord) 258
11.2. Пример использования 259
ЧАСТЬ IV. СОЗДАНИЕ USB-УСТРОЙСТВ 283
Глава 12. USB-периферия 285
12.1. Микросхемы Atmel 286
12.1.1. Микроконтроллеры с архитектурой MSC-51 286
12.1.2. Контроллеры хабов 289
12.1.3. Микропроцессоры-хабы с ядром AVR 289
12.1.4. Другие микросхемы Atmel 290
12.2. Микросхемы Cygnal 291
12.2.1. Микропроцессоры C8051F320 и C8051F321 291
12.2.2. Другие микросхемы Cygnal 293
12.3. Микросхемы FTDI 296
12.3.1. Микросхемы FT232AM и FT232BM 297
12.3.2. Микросхемы FT245AM и FT245BM 298
12.3.3. Микросхема FT2232BM 299
12.3.4. Микросхема FT8U100AX 300
12.3.5. Отладочные комплекты и модули 301
12.3.6. Драйверы 302
12.3.7. Дополнительные утилиты 303
12.3.8. Другие модули 304
12.4. Микросхемы Intel 304
12.5. Микросхемы Microchip 308
12.6. Микросхемы Motorola 308
12.7. Микросхемы Philips 309
12.7.1. Микросхемы USB 310
12.7.2. Хабы 311
12.7.3. Другие микросхемы Philips 313
12.8. Микросхемы Texas Instruments 314
12.9. Микросхемы Trans Dimension 317
12.10. Микросхемы защиты питания 318
12.11. Интернет-ресурсы к этой главе 319
Глава 13. HID-устройство на основе Atmel АТ89С5131 322
13.1. Структурная схема АТ89С5131 322
13.2. USB-регистры АТ89С5131 324
13.2.1. Регистр USBCON 324
13.2.2. Регистр USBADDR 326
13.2.3. Регистр USBINT 327
13.2.4. Регистр USBIEN 328
13.2.5. Регистр UEPNUM. 329
13.2.6. Регистр UEPCONX 330
13.2.7. Регистр UEPSTAX. 331
13.2.8. Регистр UEPRST. 334
13.2.9. Регистр UEPINT. 335
13.2.10. Регистр UEPIEN 336
13.2.11. Регистр UEPDATX 337
13.2.12. Регистр UBYCTLX 337
13.2.13. Регистр UFNUML 338
13.2.14. Регистр UFNUMH. 338
13.3. Схемотехника АТ89С5131 338
13.4. Инструменты программирования 339
13.4.1. Компилятор 341
13.4.2. Программатор 342
13.5. Программа для микропроцессора 349
13.5.1. Первая версия программы для АТ89С5131 349
13.5.2. Добавляем строковые дескрипторы 369
13.5.3. Добавление конечных точек 374
13.5.4. Создание HID-устройства 377
13.5.5. Обмен данными с HID-устройством 381
13.6. Чтение репортов в Windows 388
13.7. Дополнительные функции Windows ХР 396
13.8. Устройство с несколькими репортами 397
Глава 14. Создание USB-устройства на основе ATMEL АТ89С5131 402
14.1. He-HID-устройство 402
14.2. Создание драйвера с помощью Driver Studio 405
14.2.1. Несколько слов о библиотеке Driver Studio 407
14.2.2. Другие классы Driver Studio 411
14.2.3. Создание шаблона драйвера с помощью Driver Studio 412
14.2.4. Доработка шаблона драйвера 422
14.2.5. Базовые методы класса устройства 423
14.2.6. Реализация чтения данных 426
14.2.7. Установка драйвера 428
14.2.8. Программа чтения данных 429
14.2.9. Чтение данных с конечных точек других типов 438
14.2.10. “Чистый” USB-драйвер 439
Глава 15. Использование микросхем FTDI 457
15.1. Функциональная схема FT232BM 457
15.2. Схемотехника FT232BM 460
15.3. Функции D2XX 460
15.4. Переход от СОМ к USB 465
15.4.1. Описание схемы преобразователя 465
15.4.2. Установка скорости обмена 467
ЧАСТЬ V. СПРАВОЧНИК 469
Глава 16. Базовые функции Windows 471
16.1. Функции CreateFile и CloseHandle: открытие и закрытие объекта.471
16.1.1. Дополнительные сведения 472
16.1.2. Возвращаемое значение 472
16.1.3. Пример вызова 472
16.2. Функция Read File: чтение данных 473
16.2.1. Дополнительные сведения 474
16.2.2. Возвращаемое значение 474
16.2.3. Пример вызова 474
16.3. Функция WriteFile: передача данных 475
16.3.1. Дополнительные сведения 476
16.3.2. Возвращаемое значение 476
16.3.3. Пример вызова 476
16.4. Функция ReadFileEx. АРС-чтение данных 477
16.4.1. Возвращаемое значение 479
16.4.2. Дополнительные сведения 479
16.4.3. Пример вызова 479
16.5. Функция WriteFileEx: АРС-передача данных 480
16.5.1. Возвращаемое значение 481
16.5.2. Пример вызова 481
16.6. Функция WaitForSingleObject ожидание сигнального
состояния объекта 482
16.6.1. Возвращаемое значение 482
16.7. Функция WaitForMultipleObjects: ожидание сигнального
состояния объектов 483
16.7.1. Возвращаемое значение 484
16.8. Функция GetOverlappedResult результат асинхронной операции 484
16.8.1. Возвращаемое значение 485
16.9. Функция DeviceIoControl: прямое управление драйвером 485
16.9.1. Возвращаемое значение 487
16.10. Функция QueryDosDevice: получение имени устройства
по его DOS-имени 487
16.10.1. Возвращаемое значение 488
16.10.2. Пример вызова 488
16.11: Функция Define Dos Device: операции с DOS-именем устройства 489
16.11.1. Возвращаемое значение 490
16.11.2. Пример вызова 490
Глава 17. Функции HID API. 492
17.1. Функция HidD_Hello: проверка библиотеки 492
17.2. Функция HidD_GetHidGuid: получение GUID 492
17.3. Функция HidD_GetPreparsedData: создание описателя устройства 493
17.4. Функция HidD_FreePreparsedData: освобождение описателя устройства 493
17.5. Функция HidD_GetFeature: получение FEATURE-репорта 494
17.6. Функция HidD_SetFeature: передача FEATURE-репорта 494
17.7. Функция HidD_GetNumInputBuffers: получение числа буферов 495
17.8. Функция HidD_SetNumInputBuffers: установка числа буферов 495
17.9. Функция HidD_GetAttribntes: получение атрибутов устройства 495
17.10. Функция HidD_GetMamifactnrerStnng. получение строки производителя 496
17.11. Функция HidD_GetProductString. получение строки продукта 497
17.12. Функция HidD_ Get Serial MumberString. получение строки
серийного номера 497
17.13. Функция HidD_GetIndexedString. получение строки по индексу 498
17.14. Функция HidDjGetlnputReporr. получение INPUT-репорта 498
17.15. Функция HidD_SetOutputReport. передача OUTPUT-репорта 499
17.16. Функция HidP_GetCaps: получение свойств устройства 499
17.17. Функция HidP_MaxDataListLength: получение размеров репортов 500
Глава 18. Хост-контроллер UCH 502
18.1. Регистры управления хост-контроллером 502
18.1.1. Регистр команды USB (USBCMD) ..504
18.1.2. Регистр состояния USB (USBSTS) 506
18.1.3. Регистр управления прерываниями (USBINTR) 506
18.1.4. Регистр номера кадра (FRNUM) 507
18.1.5. Регистр базового адреса кадра (FLBASEADD) 508
18.1.6. Регистр модификатора начала кадра (SOFMOD) 508
18.1.7. Регистр состояния и управления порта (PORTSC) 509
18.2. Структуры данных хост-контроллера UCH 510
18.2.1. Список кадров 510
18.2.2. Дескриптор передачи i 511
18.2.3. Заголовок очереди 514
18.3. Обработка списка дескрипторов UCH 516
Глава 19. Инструменты 518
19.1. Средства Microsoft Visual Studio 518
19.1.1. Depends 518
19.1.2. Error Lookup 518
19.1.3. GuidGen 518
19.2. Средства Microsoft DDK 520
19.2.1. DeviceTree 520
19.2.2. DevCon .- 521
19.2.3. Chklnf и Genlnf. 526
19.3. Средства CompuWare Corporation 527
19.3.1. Monitor 527
19.3.2. SymLink 527
19.3.3. EzDriverlnstaller 527
19.3.4. WdmSniff 527
19.4. Средства Syslntemals 528
19.4.1. WinObj 528
19.5. Средства USB Forum 531
19.5.1. HID Descriptor Tool 531
19.6. Средства HDD Software 533
19.7. Средства Sourceforge 533
ПРИЛОЖЕНИЯ 535
Приложение 1. Дополнительные функции 537
Приложение 2. Таблица идентификаторов языков (LangID) 539
Приложение 3. Таблица кодов производителей (Vendor ID, Device ID) 543
Приложение 4. Описание компакт-диска 546
Литература 548
Предметный указатель 549

В прошлом уроке мы собирали прошивку для контроллера, чтобы он работал через USB. Но для взаимодействия с компьютером нам нужна еще и специальная программа, которая будет запускаться на компьютере.

Вот сейчас мы и будем ее создавать.

Опять же в пакете Microchip solutions есть пример, для нашего контроллера, но я переписал его по своему. Во-первых я сделал без использования графического интерфейса, и размер кода уменьшился раза в 3-4. Что намного лучше для изучения. Тем не менее, принцип работы один. код в стандартном примере от microchip работает так же как этот.

Программа написана в C++. Проект собран в бесплатной студенческой версии Visual C++ express 2010. Я буду давать общие идеи и комментарии по коду, но подразумеваю, что вы уже имеете хоть какой-то опыт программирования в C++.

Итак, начинаем

Здесь находится весь проект, включая исходный текст ссылка

Для того, чтобы читать и записывать данные через USB порт нам нужно получить указатель на наше устройство. Поскольку в отличие от старых портов, подключено может быть устройств свыше сотни, то получить этот указатель не так-то просто. Для того, чтобы это сделать мы будем обращаться к драйверам windows, а именно SetupAPI. Кстати, как только мы получим указатель, то будем общаться с USB портом, будто бы это файл.
Передача данных будет занимать лишь пару команд. Но вот подготовка!
Поскольку мы программируем в С++ то нам нужно быть очень аккуратными с типами данных.
Создаем консольный проект win32. И добавляем туда единственный файл main.cpp

Итак, нам необходимо подключить некоторые библиотеки.
#include
#include
#include

Так же подключаем внешнюю библиотеку:
#pragma comment (lib, "Setupapi.lib")

Первая описанная функция в программе - это getUSBHandle(). Ее описание - в комментариях кода. Да и вообще основные комментарии приведены в коде. Она служит для того, чтобы найти наше устройство и подготовить указатели, чтобы мы могли записывать в устройство и читать из него.
Если в двух словах, то она использует стандартные windows функции для доступа к драйверам USB и через них получает указатель на само устройство.
Если интересно, что все эти функции делают и как, то обращайтесь к MSDN или к книге Агурова, что лежит в оглавлении. Что важно знать: у каждого устройства есть путь, и нам важно получить его. Мы сначала проверяем, совпадает ли ID с устройством, что мы ищем. А потом находим путь устройства.Мы ищем только среди устройств HID класса. это определяется в переменной Guid. Остальное см в комментариях программы
Следующая функция - writeReadUSB. Это просто вспомогательная функция, которая записывает в наше устройство. Обращаю внимание, что запись и чтение устройства после того, как мы создали указатель на него реализуется с помощью стандартных комманд WriteFile и ReadFile
И после этого уже мы видим функцию main с которой и начинается выполнение программы. Она вызывает getUSBHandle, пока мы не получим указатель на устройство, потом читает с клавиатуры комманду и в зависимости от нее, передает и читает данные с USB устройства.
В проекте по ссылке выше лежит исходный код с комментариями и сама скомпилированная программа. Удачи.

В процессе поиска ошибки я наткнулся на библиотеку hidapi. Она является кроссплатформенной. И Только для работы с hid устройствами. Очень проста в использовании. Привожу проект под нее. ссылка .
Hidapi скачан с официального сайта. Для того чтобы начать проект нужно добавить setupapi.lib в линковщик. project->properties->linker->input и подписать туда setupapi.lib;
Удачи.
Нашел пристойное описание библиотеки здесь: http://microsin.net/programming/PC/multi-platform-hid-api.html.
Спасибо!

Как уже упоминалось, операционные системы Windows обеспечивают программную под держку функционирования устройств, подключенных к шине USB. Обработку потоков данных устройств USB на уровне операционной системы выполняет стек стандартных драйверов, которые выполняют основные функции по управлению всеми устройствами USB и обмену данными между ними и системой.

Если вам необходимо написать программное обеспечение для какого либо устройства USB, которое расширяло бы его возможности по обработке данных, то можно избрать один из трех возможных путей:

написать собственный драйвер устройства, который бы обеспечивал все необходи мые функции управления и обмена данными, и программу, которая бы взаимодей ствовала с этим драйвером в пользовательском режиме. При этом можно полностью обойтись без стандартных драйверов системы;

написать драйвер фильтра, который бы обеспечивал требуемую функциональность, но располагался бы в стеке драйверов над системными драйверами. Таким образом, все стандартные функции обработки выполняли бы драйверы USB, установленные системой, а дополнительные функции обеспечивались бы вашим драйвером фильтра, с которым и взаимодействовала бы программа пользователя;

воспользоваться свободно распространяемыми библиотеками функций и драйвера

ми для доступа к USB устройству.

В большинстве случаев программный доступ к устройству USB может потребоваться, если данное устройство выполняет какую то очень специфичную функцию. Например, на базе USB разработаны «электронные осциллографы» или системы сбора данных, для работы с которы ми необходимо иметь доступ к самому устройству. В большинстве таких случаев можно вос пользоваться свободно распространяемыми библиотеками функций, которые будут работать практически во всех популярных средах программирования. Например, под эгидой GNU раз работано программное обеспечение, известное под названием LibUsb, включающее необхо димые драйверы и библиотеки функций для работы в операционных системах Windows и Linux. Эти библиотеки функций очень популярны и позволяют быстро разрабатывать про граммы, взаимодействующие с вашим устройством посредством набора стандартных функ ций. Это исключает необходимость написания собственного драйвера устройства, что суще ственно экономит время.

Кроме того, большинство пользователей не знакомо с методикой разработки драйверов,

а это очень сложная область программирования, поэтому наличие такого свободно распрос траняемого программного обеспечения окажет неоценимую помощь широкому кругу пользо вателей. На основе проекта LibUsb разработаны оболочки (wrappers) для работы с Visual Basic .NET и C# .NET, наиболее популярной из которых является LibUsbDotNet, также разра ботанная под эгидой свободно распространяемого программного обеспечения. Несмотря на кажущуюся сложность программирования USB устройств, перечисленное программное обес печение настолько упрощает эту задачу, что она становится под силу даже новичкам. Рас смотрим на практических примерах, как работать с вашими USB устройствами, и начнем с пакета программ LibUsb. Кстати, вышеперечисленное программное обеспечение можно бес платно загрузить с сайта www.sourceforge.net или из многочисленных дублирующих сайтов.

Как работать с библиотеками USB функций LibUsb? Библиотека построена таким обра

зом, чтобы можно было выполнять основные операции, связанные с USB устройством:

идентификацию или, по–другому, перечисление (enumeration). При выполнении этой операции происходит обнаружение устройств, подключенных к шине USB, что выпол няется с помощью соответствующих функций библиотеки libusb;

получение параметров устройства (идентификаторов устройства, данных о произво дителе и характеристиках устройства), для чего в библиотеке имеется целый ряд функций;

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

Все перечисленные возможности могут быть реализованы посредством вызова соответ ствующих функций библиотеки libusb, но здесь они не будут перечисляться, поскольку это заняло бы слишком много места; мы посмотрим, как использовать некоторые из этих функ

Рис. 6.10

Расположение драйвера libusb0.sys в стеке драйверов устройства

ций на практических примерах. Описание всех функций читатели смогут найти в со ответствующей документации. Напомню, что мы рассматриваем применение функций биб лиотеки libusb в операционных системах Windows.

При инсталляции дистрибутива с libusb в операционной системе Windows в системе инсталлируется драйвер фильтра libusb0.sys. Этот драйвер будет находиться в вершине сте ка драйверов системы, что легко увидеть, на пример, посмотрев сведения о драйверах для любого USB устройства (рис. 6.10).

Кроме того, для обращения к драйверу из программ пользователя в систему инсталли руется библиотека libusb0.dll, используя кото рую можно разрабатывать пользовательские программы.

Рис. 6.17

Вид окна приложения при удалении

USB устройства из системы


рис.1 Иллюстрация работы Android устройства в режимах USB Host и Accessory (рисунок с сайта http://developer.android.com)

Отметим, что использование USB - не единственный способ связи с тем же самодельным устройством. Android позволяет использовать еще , NFC, Wi-Fi P2P, SIP, а также стандартное сетевое подключение . Так что в арсенале разработчика достаточно возможностей для осуществления своих самых смелых замыслов.

Другим распространенным вариантом связи с различными устройствами до сих пор является использование переходника USB-COM. Материал в сети по применению переходника USB-COM в Android есть - см., например, . Популярность такого подключения обусловлена наличием большого количества уже разработанных с использованием различных микроконтроллеров устройств, связь с которыми осуществляется с помощью COM-порта (последовательного порта), что лет 10 назад являлось почти стандартным способом передать данные от компьютера к самодельной «железке».

В сравнении с COM-портом, использование USB позволяет существенно повысить скорость передачи данных и сделать этот процесс удобным для пользователя. Cкорость передачи, которая даже в случае низкоскоростных устройств (клавиатуры, мыши, джойстики), составляет 10-1500 Кбит/c, простота и невысокая стоимость кабельной системы и подключений, самоидентификация устройств с автоматическим конфигурированием, скрытие подробностей электрического подключения от конечного пользователя (плюс возможность отключения кабеля без выключения устройств), контроль ошибок и их восстановление на уровне протокола - вот неоспоримые преимущества данной технологии (см. , с.12).

Вообще, говоря об использовании USB для передачи данных, нелишним будет упомянуть книгу П.Агурова «Интерфейс USB» . Она, хотя часто критикуется в сети и выпущена последний раз в 2006 году, не раз помогла найти верное решение при поиске информации по различным аспектам применения этой технологии. В книге рассмотрены вопросы: от выбора микросхемы и схемотехники для контроллера до написания программы микроконтроллера и примеров программирования передачи данных по протоколу USB со стороны компьютера. Нельзя не указать и "первоисточник" данных по этому вопросу - сайт некоммерческой организации USB IF (USB Implementers Forum), занимающейся разработкой спецификаций этого интерфейса - , правда данный материал на английском языке. Однако именно там вы найдете исчерпывающие сведения об устройстве интерфейса USB. Есть неплохой перевод частей спецификации - . Интересующимся программными решениями со стороны микроконтроллера также можно посмотреть ссылку .

Данная статья адресована прежде всего тем, у кого есть какое-либо электронное устройство (разработанное самостоятельно или кем-то еще), протокол обмена данными с которым хорошо известен (например, уже есть программа, работающая с этим устройством в Windows/Linux) и хотелось бы иметь программу, работающую с ним в Android.

Немного о классах USB-устройств

Необходимо отметить, что разработка программного обеспечения для обмена данными с конкретным устройством сильно зависит от его реализации на уровне микроконтроллера. Привести примеры программ связи для всех типов USB-устройств в рамках одной статьи, по понятным причинам, невозможно (начальные сведения о программировании различных типов устройств можно почерпнуть в ). Однако, мы ограничимся тем, что приведем код, реализующий поиск устройства и доступ к его контрольным точкам для обмена информацией. Также разберем отправку данных на примере одного из типов USB-устройств, а именно, класса устройств HID (human interface device - класс устройств для взаимодействия с человеком). Этот класс включает в себя «медленные» устройства, такие как клавиатура, мышь, джойстик и примеров его реализации с помощью различных микроконтроллеров в сети достаточно (есть, например, и в ).

Почему именно класс HID так полюбился изготовителям различных самодельных устройств? Процитируем Википедию : «Помимо детальных спецификаций классических устройств ввода (типа клавиатур и мышек) стандарт HID определяет особый класс устройств без детальных спецификаций. Этот класс именуется USB HID Consumer Control и представляет собой по сути нерегламентированный канал связи с устройством. При этом устройство пользуется теми же стандартными для операционной системы драйверами что и мышка с клавиатурой. Таким образом, можно создать USB устройство которое не требует создания и инсталляции специальных драйверов в большинстве распространенных компьютерных операционных систем». Остается добавить только, что работает эта спецификация и в ОС Android (не исключая прошивок CyanogenMod).

Одним из вариантов обмена данными с HID-устройством является передача по прерываниям (interrupt transfer), которая используется в том случае, когда необходимо передать пакеты данных небольшого размера (максимальный размер пакета зависит от скорости передачи и составляет от 64 до 1024 байт) через заданный временной интервал. Пакет для передачи называется репортом (англ. - report, см. с.71, 95). Такой длины репорта обычно вполне хватает для обмена информацией с самодельным устройством, 64 байта информации в одном пакете, например, - это довольно много для контроллера, ведь для передачи состояний светодиода или простейшего датчика достаточно 1 бита информации.

Необходимые инструменты

Итак, нам понадобятся - планшет или телефон с Android версии не ниже 3.1. Здесь необходимо отметить, что вышеуказанный USB Host API полностью реализован не на всех мобильных устройствах (об этом упоминается и на сайте developer.android.com, см. ссылку ). В некоторых планшетах/телефонах разъем USB используется только для зарядки и связи с персональным компьютером. Еще раз отправлю читателя к списку мобильных устройств, пригодных или непригодных для наших опытов (см. ).

Понадобится также какое-либо USB-устройство (для первых опытов будет достаточно обычного USB-флеш-накопителя), переходник OTG (On-The-Go - см. рис. 2) и/или шнур USB для связи с устройством. В Википедии по поводу OTG говорится: «При подключении через USB OTG ранг устройства (ведущий или ведомый) определяется наличием или отсутствием перемычки между контактами 4 и 5 в штекере соединительного кабеля. В USB OTG кабеле такая перемычка устанавливается лишь в одном из двух разъемов (см. ).» Соответственно, нам необходима такая перемычка со стороны мобильного устройства.


Рис.2 Различия в схеме обычного USB-кабеля и OTG-кабеля (рисунок с сайта http://tech.firstpost.com)

Такой OTG-кабель для Вашего устройства можно спаять и самостоятельно. Для этого необходимо купить в радиомагазине подходящий разъем, плюс автор, например, использовал старый кабель от переносного жесткого диска:

Неплохим подспорьем в работе будет также программа USB Device Info, установленная из хранилища Google Play Market. Программа умеет определять подключенные к USB-разъему планшета/телефона устройства как с помощью Java API так и с помощью ядра Linux. То есть, если Ваше устройство не определилось с помощью Java USB Host API в USB Device Info, то, с большой вероятностью, тщетно будет использовать для этого мобильного устройства какую-либо (в том числе и свою) Android-программу, написанную с помощью Java и USB Host API.

Иногда, также, очень полезной бывает информация, выводимая командой lsusb операционной системы Linux. С ключами -v и -d lsusb выводит о USB-устройстве все, или почти все, что необходимо разработчику программного обеспечения для устройств этого класса (см. рис.3).


Рис.3 Пример вывода команд lsusb и lsusb -v -d

Далее, необходим компьютер с установленным Android SDK и интегрированной средой разработки (IDE) Eclipse с плагином ADT (хотя можно обойтись и только SDK). Как создать и установить приложение для Android можно посмотреть, например, в , или в сети Интернет.

Ну и, конечно, необходимо хотя бы а также желание добиться результата, без него никак! Отмечу, что на выяснение некоторых технических вопросов применения USB в Android автором, потребовались недели кропотливого поиска информации.

Классы Java для работы с USB в Android API

Итак, как говорится на сайте разработчиков USB Host API для Android (см. ) - «прежде чем начать, важно понять какие классы вы будете использовать в работе». В таблице 1 приведено описание важнейших классов для работы с USB Host API (попытка перевода информации с http://developer.android.com).

Таблица 1. Описание классов для работы с USB в Android

Название класса Описание
UsbManager Allows you to enumerate and communicate with connected USB devices.
Позволяет определять подключенное USB-устройство и обмениваться с ним данными.
UsbDevice Represents a connected USB device and contains methods to access its identifying information, interfaces, and endpoints.
Представляет подключенное USB-устройство и содержит методы для доступа к его идентификационной информации, интерфейсам, и конечным точкам.
UsbInterface Represents an interface of a USB device, which defines a set of functionality for the device. A device can have one or more interfaces on which to communicate on.
Представляет «интерфейс» USB-устройства, который определяет набор функций для данного устройства. Одно устройство может иметь один или несколько интерфейсов для обмена информацией.
UsbEndpoint Represents an interface endpoint, which is a communication channel for this interface. An interface can have one or more endpoints, and usually has input and output endpoints for two-way communication with the device.
Представляет «конечную точку» интерфейса, которая и является каналом связи для этого интерфейса. Интерфейс может иметь одну и более конечных точек, и обычно имеет конечные точки для получения информации и для ее передачи.
UsbDeviceConnection Represents a connection to the device, which transfers data on endpoints. This class allows you to send data back and forth sychronously or asynchronously.
Представляет «подключение» к данному устройству. Необходимо для передачи данных в конечную точку. Этот класс позволяет получать данные или передавать синхронно или асинхронно.
UsbRequest Represents an asynchronous request to communicate with a device through a UsbDeviceConnection.
Представляет асинхронный запрос на обмен данными с устройством через UsbDeviceConnection.
UsbConstants Defines USB constants that correspond to definitions in linux/usb/ch9.h of the Linux kernel..
Определяет константы, которые соответствуют определениям в linux/usb/ch9.h ядра Linux.

Практически во всех случаях применения USB Host API программист использует эти классы в своей работе. Алгоритм их применения выглядит примерно так: определяем устройства (цель - программный доступ к классу UsbDevice), подключенные к хосту (мобильному устройству), с помощью UsbManager. Когда программный доступ устройству получен, необходимо определить соответствующие UsbInterface и UsbEndpoint для общения с ним. Как только вы получили в свое распоряжение конечную точку, откройте UsbDeviceConnection, чтобы общаться с USB-устройством. Если конечная точка работает в режиме асинхронной передачи, используем класс UsbRequest.

Давайте попробуем со всем этим разобраться создав простое приложение, которое, используя этот API, определит подключенное к хосту с ОС Android устройство и выведет о нем некоторую информацию на экран телефона или планшета.

Создаем проект

В Eclipse проект создается с помощью пунктов меню File->New->Android Application Project. Заметим также, что код, приведенный ниже заимствован из приложений-примеров, поставляемых с Android SDK (папка android sdk samples/android-N(API Level)/USB) речь идет о программе управления USB-игрушкой Missile Launcher (см. рис. 4) Примеры приложений загружаются через Android SDK Manager (нужно отметить пункт - Samples for SDK ). В листингах, приведенных ниже, примеры кода снабжены комментариями, которые объясняют суть происходяшего.


Рис.4 Забавная игрушка "Ракетозапускалка"

Создавая проект не забудьте отметить нужный API Level в опции Minimum Requared SDK (API Level 12, соответствующий версии Android 3.1 /Honeycomb/, или выше). В проекте будет очень простой интерфейс пользователя - главное окно (Activity) и TextView для вывода информации. Подобный проект подробно рассмотрен в .

В созданном автоматически классе для Activity нашего проекта необходимо определить следующие экземпляры классов для работы с USB:

private TextView lgView;
private UsbManager mUsbManager;
private UsbDevice mDevice;
private UsbDeviceConnection mConnection;
private UsbEndpoint mEndpointIntr;

LgView = (TextView) findViewById(R.id .logTextView ) ;

и получаем доступ к классу UsbManager

MUsbManager = (UsbManager) getSystemService(Context .USB_SERVICE ) ;

Создадим еще обработчик события onResume(). Добьемся цели - чтобы информация о подключенных устройствах обновлялась при активизации окна нашего приложения (см. Листинг 1).

Листинг 1. Обработчик события onResume()

public void onResume() {
super .onResume () ;

//заполняем контейнер списком устройств
HashMap< String , UsbDevice> deviceList = mUsbManager.getDeviceList () ;
Iterator< UsbDevice> deviceIterator = deviceList.values () .iterator () ;

lgView.setText ( "Devices Count:" + deviceList.size () ) ;

while (deviceIterator.hasNext () ) {
UsbDevice device = (UsbDevice) deviceIterator.next () ;

//пример определения ProductID устройства
\n " + "Device ProductID: " + device.getProductId () ) ;
}
//определяем намерение, описанное в фильтре
// намерений AndroidManifest.xml
Intent intent = getIntent() ;
lgView.setText ( lgView.getText () + "\n " + "intent: " + intent) ;
String action = intent.getAction () ;

//если устройство подключено, передаем ссылку в
//в функцию setDevice()
UsbDevice device = (UsbDevice) intent.getParcelableExtra (UsbManager.EXTRA_DEVICE ) ;
if (UsbManager.ACTION_USB_DEVICE_ATTACHED .equals (action) ) {
setDevice(device) ;
lgView.setText ( lgView.getText () + "\n " + "UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action) is TRUE" ) ;
} else if (UsbManager.ACTION_USB_DEVICE_DETACHED .equals (action) ) {
if (mDevice != null && mDevice.equals (device) ) {
setDevice(null ) ;
lgView.setText ( lgView.getText () + "\n " + "UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action) is TRUE" ) ;
}
}

Далее, для Activity создадим функцию setDevice(), необходимую для работы с нашим устройством (см. Листинг 2). В обработчике onResume() и в функции setDevice() мы в точности выполнили алгоритм применения USB Host API, описанный в предыдущем разделе.

Листинг 2. Функция setDevice()

private void setDevice(UsbDevice device) {
lgView.setText ( lgView.getText () + "\n " + "setDevice " + device) ;

//определяем доступные интерфейсы устройства
if (device.getInterfaceCount () != 1 ) {

LgView.setText ( lgView.getText () + "\n " + "could not find interface" ) ;
return ;
}
UsbInterface intf = device.getInterface (0 ) ;

//определяем конечные точки устройства
if (intf.getEndpointCount () == 0 ) {

LgView.setText ( lgView.getText () + "\n " + "could not find endpoint" ) ;
return ;
} else {
lgView.setText ( lgView.getText () + "\n " + "Endpoints Count: " + intf.getEndpointCount () ) ;
}

UsbEndpoint epIN = null ;
UsbEndpoint epOUT = null ;

//ищем конечные точки для передачи по прерываниям
for (int i = 0 ; i < intf.getEndpointCount () ; i++ ) {
if (intf.getEndpoint (i) .getType () == UsbConstants.USB_ENDPOINT_XFER_INT ) {
if (intf.getEndpoint (i) .getDirection () == UsbConstants.USB_DIR_IN ) {
epIN = intf.getEndpoint (i) ;
lgView.setText ( lgView.getText () + "\n " + "IN endpoint: " + intf.getEndpoint (i) ) ;
}
else {
epOUT = intf.getEndpoint (i) ;
lgView.setText ( lgView.getText () + "\n " + "OUT endpoint: " + intf.getEndpoint (i) ) ;
}
} else { lgView.setText ( lgView.getText () + "\n " + "no endpoints for INTERRUPT_TRANSFER" ) ; }
}

MDevice = device;
mEndpointIntr = epOUT;

//открываем устройство для передачи данных
if (device != null ) {
UsbDeviceConnection connection = mUsbManager.openDevice (device) ;
if (connection != null && connection.claimInterface (intf, true ) ) {

LgView.setText ( lgView.getText () + "\n " + "open device SUCCESS!" ) ;
mConnection = connection;

} else {

LgView.setText ( lgView.getText () + "\n " + "open device FAIL!" ) ;
mConnection = null ;
}
}
}
}

В дополнение к приведенному коду, который, как уже наверняка догадался внимательный читатель, открывает устройство для приема-передачи данных, остается лишь задействовать протокол обмена данными, который, повторюсь, должен быть хорошо известен разработчику. Приведем лишь, как было обещано, код, который отправит HID устройству некоторый пакет данных message используя передачу по прерываниям, класс UsbRequest и соответствующую конечную точку - см. Листинг 3.

Листинг 3. Пример кода для отправки данных устройству

//определение размера буфера для отправки
//исходя из максимального размера пакета
int bufferDataLength = mEndpointIntr.getMaxPacketSize () ;

lgView.setText ( lgView.getText () + "\n " + mEndpointIntr.getMaxPacketSize () ) ;

ByteBuffer buffer = ByteBuffer.allocate (bufferDataLength + 1 ) ;

UsbRequest request = new UsbRequest() ;

buffer.put (message) ;

request.initialize (mConnection, mEndpointIntr) ;

request.queue (buffer, bufferDataLength) ;

if (request.equals (mConnection.requestWait () ) )

//отправка прошла успешно
//lgView.setText(lgView.getText() + "\n" + "sending CLEAR!!!");

catch (Exception ex)

//что-то не так...
//lgView.setText(lgView.getText() + "\n" + "sending not clear...");

Фильтрация устройств в AndroidManifest.xml

Хотя в нашем приложении нет нужды в поиске конкретного устройства с известными VID (Vendor-ID) и PID (Product-ID), инженеры Google не приводят примеров приложений без секции intent-filter в манифест файле, и автору не удалось добиться работы программы без фильтрации устройств в AndroidManifest.xml .

Напомню, что Vendor-ID и Product-ID это уникальные идентификаторы USB-устройств. То есть, используя фильтрацию, можно создать приложение, которое взаимодействует лишь с определенным устройством или каким-то классом устройств. Отметим, что производители устройств должны согласовать эти номера с организацией USB IF.

Приложение, манифест файл которого приведен в листинге 4, а файл с условием фильтрации в листинге 5, например, с успехом распознает подключенные к мобильному устройству USB-флеш-накопители, но не распознает клавиатуру и мыши, имеющиеся у автора. Это приложение вместе с исходным кодом можно скачать по ссылке .

Листинг 4. Файл AndroidManifest.xml


" > http://schemas.android.com/apk/res/android"
> package="ru.learn2prog.usbhostexample"
android:versionCode="1"
android:versionName="1.0" >


android:minSdkVersion ="12"
android:targetSdkVersion ="14" />


android:allowBackup ="true"
android:icon ="@drawable/ic_launcher"
android:label ="@string/app_name"
android:theme ="@style/AppTheme" >

android:name ="ru.learn2prog.usbhostexample.MainActivity"
android:label ="@string/app_name" >
>

"android.intent.category.DEFAULT" />

"android.intent.category.LAUNCHER" />

>

>

>
"android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource ="@xml/device_filter" />
>
>

>

Листинг 5. Файл фильтра device_filter.xml (каталог /res/xml)

>

>

Операции по сборке и установке нашего приложения ничем не отличаются от обычных (см. примеры в , ). Хочу обратить внимание на действия фильтра намерений - при подключении устройства к хосту ОС запрашивает пользователя о запуске нашего приложения.

Литература/Ссылки: 11.
12.
13. http://developer.android.com/guide/topics/connectivity/usb/host.html - обзор классов, необходимых для работы с USB в Android
14. ссылка на исходники приложения

Введение
Для кого эта книга
Что вы найдете в книге
Программные требования
Аппаратные требования
О программном коде
Краткое описание глав
Обозначения
Благодарности
Обратная связь
Часть I. Общие сведения о USB
Глава 1. Спецификация USB
1.1. Что такое USB и зачем это надо
1.1.1. Общая архитектура USB
1.1.2. Физическая и логическая архитектура USB
1.1.3. Составляющие USB
1.1.4. Свойства USB-устройств
1.1.5. Принципы передачи данных
1.1.6. Механизм прерываний
1.1.7. Режимы передачи данных
1.1.8. Логические уровни обмена данными
1.1.8.1. Уровень клиентского ПО
1.1.8.2. Уровень системного драйвера USB
1.1.8.3. Уровень хост-контроллера интерфейса
1.1.8.4. Уровень шины периферийного USB-устройства
1.1.8.5. Уровень логического USB-устройства
1.1.8.6. Функциональный уровень USB-устройства
1.1.9. Передача данных по уровням
1.1.10. Типы передач данных
1.1.11. Кадры
1.1.12. Конечные точки
1.1.13. Каналы
1.1.14. Пакеты
1.1.14.1. Формат маркер-пакетов IN, OUT, SETUP и PING
1.1.14.2. Формат пакета SOF
1.1.14.3. Формат пакета данных
1.1.14.4. Формат пакета подтверждения
1.1.14.5. Формат пакета SPLIT
1.1.15. Контрольная сумма
1.1.15.1. Алгоритм вычисления CRC
1.1.15.2. Программное вычисление CRC
1.1.16. Транзакции
1.1.16.1. Типы транзакций
1.1.16.2. Подтверждение транзакций и управление потоком
1.1.16.3. Протоколы транзакций
1.2. Запросы к USB-устройствам
1.2.1. Конфигурационный пакет
1.2.2. Стандартные запросы к USB-устройствам
1.2.2.1. Получение состояния GET_STATUS
1.2.2.2. Сброс свойства CLEAR_FEATURE
1.2.2.3. Разрешение свойства SET_FEATURE
1.2.2.4. Задание адреса на шине SET_ADDRESS
1.2.2.5. Получение дескриптора GET_DESCRIPTOR
1.2.2.6. Передача дескриптора SET_DESCRIPTOR
1.2.2.7. Получение кода конфигурации GET_CONFIGURATION
1.2.2.8. Задание кода конфигурации SET_CONFIGURATION
1.2.2.9. Получение кода настройки интерфейса GET_INTERFACE
1.2.2.10. Задание кода настройки интерфейса SET_INTERFACE
1.2.2.11. Задание номера кадра синхронизации SYNC_FRAME
1.2.2.12. Обработка стандартных запросов
1.2.3. Дескриптор устройства
1.2.3.1. Дескриптор устройства
1.2.3.2. Уточняющий дескриптор устройства
1.2.3.3. Дескриптор конфигурации
1.2.3.4. Дескриптор интерфейса
1.2.3.5. Дескриптор конечной точки
1.2.3.6. Дескриптор строки
1.2.3.7. Специфические дескрипторы
1.2.3.8. Порядок получения дескрипторов
1.3. Система Plug and Play (PnP)
1.3.1. Конфигурирование USB-устройств
1.3.2. Нумерация USB-устройств
1.3.3. PnP-идентификаторы USB-устройств
1.3.4. Символьные имена устройств
1.4. Модель WDM
Глава 2. Программирование на языке C для микроконтроллера
2.1. Общие сведения о языке С для микроконтроллеров
2.2. Использование стандартных библиотек
2.3. Программирование для АТ89С5131
2.3.1. Файл инициализации
2.3.2. Структуры дескрипторов
2.3.3. Структура проекта
Глава 3. Инструменты
3.1. Программаторы
3.1.1. Программатор Flip
3.1.2. Программатор ER-Tronik
3.2. Инструменты создания драйверов
3.2.1. NuMega Driver Studio
3.2.2. Jungo WinDriver
3.2.3. Jungo KernelDriver
3.3. Средства Microsoft Visual Studio
3.3.1. Depends (Dependency Walker)
3.3.2. Error Lookup
3.3.3. GuidGen
3.4. Средства Microsoft DDK
3.4.1. DeviceTree
3.4.2. DevCon
3.4.2.1. Ключ classes
3.4.2.2. Ключ driverfiles
3.4.2.3. Ключ hwids
3.4.2.4. Ключ rescan
3.4.2.5. Ключ stack
3.4.2.6. Ключ status
3.4.3. Chklnf и Genlnf
3.5. Средства CompuWare Corporation
3.5.1. Monitor
3.5.2. SymLink
3.5.3. EzDriverlnstaller
3.5.4. WdmSniff
3.6. Средства Syslnternals
3.6.1. WinObj
3.7. Средства USB Forum
3.7.1. HID Descriptor Tool
3.8. USB Command Verifier
3.9. Средства HDD Software
3.10. Средства Sourceforge
3.11. Программа мониторинга Bus Hound
Глава 4. Принципы использования функций Win32 в.NET
4.1. Общие сведения
4.2. Импорт функций Win32
4.3. Структуры
4.3.1. Атрибут StructLayout
4.3.2. Атрибут MarshalAs
4.4. Прямой доступ к данным
4.5. Обработка сообщений Windows
4.6. Общие сведения о WMI
4.7. Интернет-ресурсы к этой главе
Часть II. Классы USB
Глава 5. Класс CDC
5.1. Методы преобразования интерфейсов USB/RS-232
5.2. Общие сведения об интерфейсе RS-232
5.2.1. Линии обмена
5.2.1.1. Передаваемые данные (BA/TxD/TD)
5.2.1.2. Принимаемые данные (BB/RxD/RD)
5.2.1.3. Запрос передачи (CA/RTS)
5.2.1.4. Готовность к передаче (CB/CTS)
5.2.1.5. Готовность DCE (CC/DSR)
5.2.1.6. Готовность DTE (CD/DTR)
5.2.1.7. Индикатор вызова (CE/RI)
5.2.1.8. Обнаружение несущей (CF/DCD)
5.2.1.9. Готовность к приему (CJ)
5.3. Спецификация CDC
5.3.1. Стандартные дескрипторы
5.3.2. Функциональные дескрипторы
5.3.2.1. Заголовочный функциональный дескриптор
5.3.2.2. Дескриптор режима команд
5.3.2.3. Дескриптор абстрактного устройства
5.3.2.4. Дескриптор группирования
5.3.3. Специальные запросы
5.3.3.1. Запрос SET_LINE_CODING
5.3.3.2. Запрос GET_LINE_CODING
5.3.3.3. Запрос SET_CONTROL_LINE_STATE
5.3.3.4. Запрос SEND_BREAK
5.3.4. Нотификации
5.3.4.1. Нотификация RING^DETECT
5.3.4.2. Нотификация SERIAL_STATE
5.4. Поддержка CDC в Windows
5.4.1. Обзор функций Windows для работы с последовательными портами
5.4.1.1. Основные операции с портом
5.4.1.2. Функции настройки порта
5.4.1.3. Специальная настройка порта
5.4.1.4. Получение состояния линий модема
5.4.1.5. Работа с CDC на платформе. NET
5.4.2. Соответствие функций Windows и USB-запросов
Глава 6. Класс HID
6.1. Спецификация HID-устройств
6.2. Порядок обмена данными с HID-устройством
6.3. Установка драйвера HID-устройства
6.4. Идентификация HID-устройства
6.4.1. Идентификация загрузочных устройств
6.4.2. Дескриптор конфигурации HID-устройства
6.4.3. HID-дескриптор
6.4.4. Дескриптор репорта
6.5. Структура дескриптора репорта
6.5.1. Элементы репорта
6.5.1.1. Элементы короткого типа
6.5.1.2. Элементы длинного типа
6.5.2. Типы элементов репорта
6.5.2.1. Основные элементы
6.5.2.2. Глобальные элементы
6.5.2.3. Локальные элементы
6.5.3. Примеры дескрипторов
6.6. Запросы к НID-устройству
6.6.1. Запрос GET_REPORT
6.6.2. Запрос SET_REPORT
6.6.3. Запрос GET_IDLE
6.6.4. Запрос SET_IDLE
6.6.5. Запрос GET_PROTOCOL
6.6.6. Запрос SET_PROTOCOL
6.7. Инструменты
6.8. Драйверы для HID-устройств в Windows
Глава 7. Другие классы USB
Часть III. Практика программирования USB
Глава 8. Создание USB-устройства на основе АТ89С5131
8.1. Общая информация об АТ89С5131
8.2. Структурная схема АТ89С5131
8.3. USB-регистры AT89C5131
8.3.1. Регистр USBCON
8.3.2. Регистр USBADDR
8.3.3. Регистр USBINT
8.3.4. Регистр USBIEN
8.3.5. Регистр UEPNUM
8.3.6. Регистр UEPCONX
8.3.7. Регистр UEPSTAX
8.3.8. Регистр UEPRST
8.3.9. Регистр UEPINT
8.3.10. Регистр UEPIEN
8.3.11. Регистр UEPDATX
8.3.12. Регистр UBYCTLX
8.3.13. Регистр UFNUML
8.3.14. Регистр UFNUMH
8.4. Схемотехника АТ89С5131
8.5. Базовый проект для АТ89С5131
8.5.1. Первая версия программы для АТ89С5131
8.5.2. Добавляем строковые дескрипторы
8.5.3. Добавление конечных точек
8.6. Загрузка программы
Глава 9. Реализация класса CDC
9.1. Реализация CDC
9.2. Дескрипторы устройства
9.2.1. Инициализация конечных точек
9.2.2. Обработка CDC-запросов
9.2.3. Конфигурирование RS-порта и CDC-линии
9.2.4. Прием и передача данных
9.3. Установка драйвера
9.4. Программирование обмена данными с CDC-устройством на языке Delphi
9.5. Программирование обмена с CDC-устройством на языке С#
9.5.1. Использование компонента MSCOMM
9.5.2. Использование функций Win32
9.6. Проблемы CDC
Глава 10. Реализация класса HID
10.1. Реализация HID на АТ89С5131
10.2. Передача нескольких байтов
10.3. Feature-репорты
10.4. Передача данных от хоста (SET_REPORT)
10.5. Установка HID-устройства
10.6. Обмен данными с HID-устройством
10.6.1. Получение имени HID-устройства
10.6.2. Получение атрибутов устройства и чтение репортов
10.6.3. Передача данных от хоста к HID-устройству
10.7. Примеры HID-устройств
10.7.1. Реализация устройства "мышь"
10.7.2. Реализация устройства "клавиатура"
10.8. Использование HID-протокола
10.8.1. Интерпретация данных
10.8.2. Коллекции
10.8.3. Массивы и кнопки
10.9. HID-устройство с несколькими репортами
Глава 11. Специальные функции Windows
11.1. Функции Setup API
11.1.1. Перечисление USB-устройств
11.1.2. Получение состояния USB-устройства
11.2. Перечисление USB-устройств с помощью WMI
11.3. Специальные функции Windows XP
11.3.1. HidD_GetInputReport - чтение HID-репортов
11.3.2. Получение данных Raw Input
11.4. Функции DirectX
11.5. Диалог добавления нового оборудования
11.6. Работа с символьными именами устройств
11.7. Безопасное извлечение флэш-дисков
11.8. Обнаружение добавления и удаления устройств
11.9. Интернет-ресурсы
Глава 12. Разработка драйвера
12.1. Основные процедуры драйвера WDM
12.1.1. Процедура DriverEntry
12.1.2. Процедура AddDevice
12.1.3. Процедура Unload
12.1.4. Рабочие процедуры драйвера
12.1.4.1. Заголовок пакета
12.1.4.2. Ячейки стека ввода/вывода
12.4.1.3. Рабочие процедуры драйвера
12.1.5. Обслуживание запросов IOCTL
12.2. Загрузка драйвера и обращение к процедурам драйвера
12.2.1. Процедура работы с драйвером
12.2.2. Регистрация драйвера
12.2.2.1. Регистрация с помощью SCM-менеджера
12.2.2.2. Параметры драйвера в реестре
12.2.3. Обращение к рабочим процедурам
12.2.4. Хранение драйвера внутри исполняемого файла
12.3. Создание драйвера с помощью Driver Studio
12.3.1. Несколько слов о библиотеке Driver Studio
12.3.1.1. Класс KDriver
12.3.1.2. Класс KDevice
12.3.1.3. Класс Klrp
12.3.1.4. Класс KRegistryKey
12.3.1.5. Класс KLowerDevice
12.3.1.6. Классы USB
12.3.2. Другие классы Driver Studio
12.3.3. Создание шаблона драйвера с помощью Driver Studio
12.3.3.1. Шаг 1. Задание имени и пути проекта
12.3.3.2. Шаг 2. Выбор архитектуры драйвера
12.3.3.3. Шаг 3. Выбор шины
12.3.3.4. Шаг 4. Задание набора конечных точек
12.3.3.5. Шаг 5. Задание имени класса и файла
12.3.3.6. Шаг 6. Выбор функций драйвера
12.3.3.7. Шаг 7. Выбор способа обработки запросов
12.3.3.8. Шаг 8. Создание сохраняемых параметров драйвера
12.3.3.9. Шаг 9. Свойства драйвера
12.3.3.10. Шаг 10. Задание кодов IOCTL
12.3.3.11. Шаг 11. Дополнительные настройки
12.3.4. Доработка шаблона драйвера
12.3.5. Базовые методы класса устройства
12.3.6. Реализация чтения данных
12.3.7. Установка драйвера
12.3.8. Программа чтения данных
12.3.9. Чтение данных с конечных точек других типов
12.3.10. "Чистый" драйвер USB-устройства
Часть IV. Справочник
Глава 13. Формат INF-файла
13.1. Структура INF-файла
13.1.1. Секция Version
13.1.2. Секция Manufacturer
13.1.3. Секция DestinationDirs
13.1.3.1. Ключ DefaultDescDir
13.1.3.2. Ключи file-list-section
13.1.3.3. Ключ dirid
13.1.3.4. Ключ subdir
13.1.4. Секция описания модели
13.1.5. Секция xxx. AddRegw xxx. DelReg
13.1.6. Секция xxx. LogConfig
13.1.7. Секция xxx. CopyFiles
13.1.8. Секция Strings
13.1.9. Связи секций
13.2. Создание и тестирование INF-файлов
13.3. Установка устройств с помощью INF-файла
13.4. Ветки реестра для USB
Глава 14. Базовые функции Windows
14.1. Функции CreateFile и CloseHandle: открытие и закрытие объекта
14.1.1. Дополнительные сведения
14.1.2. Возвращаемое значение
14.1.3. Пример вызова
14.2. Функция ReadFile: чтение данных
14.2.1. Дополнительные сведения
14.2.2. Возвращаемое значение
14.2.3. Пример вызова
14.3. Функция Write File: передача данных
14.3.1. Дополнительные сведения
14.3.2. Возвращаемое значение
14.3.3. Пример вызова
14.4. Функция ReadFileEx. АРС-чтение данных
14.4.1. Возвращаемое значение
14.4.2. Дополнительные сведения
14.4.3. Пример вызова
14.5. Функция WriteFiieEx: АРС-передача данных
14.5.1. Возвращаемое значение
14.5.2. Пример вызова
14.6. Функция WaitForSingieObject ожидание сигнального состояния объекта
14.6.1. Возвращаемое значение
14.7. Функция WaitForMultipleObjects: ожидание сигнального состояния объектов
14.7.1. Возвращаемое значение
14.8. Функция GetOverlapped Result: результат асинхронной операции
14.8.1. Возвращаемое значение
14.9. Функция DeviceloControl: прямое управление драйвером
14.9.1. Возвращаемое значение
14.10. Функция Cancel/o: прерывание операции
14.10.1. Возвращаемое значение
14.11. Функция Query Dos Device, получение имени устройства по его DOS-имени
14.11.1. Возвращаемое значение
14.11.2. Пример вызова
14.12. Функция Define Dos Device: операции с DOS-именем устройства
14.12.1. Возвращаемое значение
14.12.2. Пример вызова
Глава 15. Структуры и функции Windows для последовательных портов
15.1. Структура настроек порта COMMCONFIG
15.2. Структура свойств порта COMMPROP
15.3. Структура тайм-аутов COMMTIMEOUTS
15.4. Структура статуса порта COMSTAT
15.5. Структура DCB
15.6. Функция BuildCommDCB: создание структуры DCB из строки
15.6.1. Дополнительные сведения
15.6.2. Возвращаемое значение
15.6.3. Пример вызова
15.7. Функция BuildCommDCBAndTimeouts: создание структуры DCB и тайм-аутов из строки
15.8. Функции SetCommBreak и ClearCommBreak: управление выводом данных
15.8.1. Возвращаемое значение
15.9. Функция ClearCommError: получение и сброс ошибок порта
15.9.1. Возвращаемое значение
15.10. Функция EscapeCommFunction: управление портом
15.10.1. Возвращаемое значение
15.11. Функции GetCommMask и SetCommMask: маска вызова событий
15.11.1. Возвращаемое значение
15.12. Функция WaitCommEvent ожидание события СОМ-порта
15.12.1. Возвращаемое значение
15.12.2. Дополнительные сведения
15.12.3. Пример вызова
15.13. Функции GetCommConfig и SetCommConfig: конфигурирование параметров порта
15.13.1. Возвращаемое значение
15.13.2. Пример вызова
15.14. Функция CommConfigDialog: диалог конфигурирования порта
15.14.1. Возвращаемое значение
15.14.2. Дополнительные сведения
15.14.3. Пример вызова
15.15. Функция GetCommProperties: прочитать свойства порта
15.15.1. Возвращаемое значение
15.15.2. Пример вызова
15.16. Функции GetCommState и SetCommState: состояние порта
15.16.1. Возвращаемое значение
15.16.2. Пример вызова
15.17. Функции GetCommTimeouts и SetComniTimeouts: тайм-ауты порта
15.17.1. Возвращаемое значение
15.17.2. Пример вызова
15.18. Функция PurgeComm: сброс буферов порта
15.18.1. Возвращаемое значение
15.18.2. Пример вызова
15.19. Функция SetupComm: конфигурирование размеров буферов
15.19.1. Возвращаемое значение
15.20. Функции GetDefaultCommConfig и SetDefaitltCommConfig: настройки порта по умолчанию
15.20.1. Возвращаемое значение
15.21. Функция TransmitCommChar. передача специальных символов
15.21.1. Возвращаемое значение
15.22. Функция GetCommModemStatus: статус модема
15.22.1. Возвращаемое значение
15.22.2. Пример вызова
15.23. Функция EnumPorts: перечисление портов
15.23.1. Дополнительные сведения
15.23.2. Возвращаемое значение
15.23.3. Пример вызова
Глава 16. Структуры и функции Windows Setup API
16.1. Функция Setup DiGetCiassDevs: перечисление устройств
16.1.1. Возвращаемое значение
16.2. Функция SetupDiDestroyDevicelnfoList освобождение блока описания устройства
16.2.1. Возвращаемое значение
16.3. Функция SetupDiEnumDevicelnterfaces: информация об устройстве
16.3.1. Возвращаемое значение
16.4. Функция SetupDiGetDevicelnterfaceDetaii: детальная информация об устройстве
16.5. Функция SetupDiEnumDevicelnfo: информация об устройстве
16.6. Функция SetupDiGetDeviceRegistryProperty: получение Plug and Play свойств устройства
16.7. Функция CM_Get_DevNode_Status: статус устройства
16.8. Функция CM_Request_Device_Eject безопасное извлечение устройства
Глава 17. Структуры и функции Windows HID API
17.1. Функция HidD_Hello: проверка библиотеки
17.2. Функция HidD_JetHidGuid: получение GUID
17.3. Функция HidD_GetPreparsedData: создание описателя устройства
17.4. Функция HidD_EreePreparsedData: освобождение описателя устройства
17.5. Функция HidD_Get Feature: получение Feature-репорта
17.6. Функция HidD_SetFeature: передача Feature-репорта
17.7. Функция HidD_GetNumlnputBuffers: получение числа буферов
17.8. Функция HidD_SetNumlnputBuffers: установка числа буферов
17.9. Функция HidD_GetAttributes: получение атрибутов устройства
17.10. Функция HidD_GetManufacturerString. получение строки производителя
17.11. Функция HidD_GetProductString получение строки продукта
17.12. Функция HidD_GetSerialNumberString. получение строки серийного номера
17.13. Функция HidD_GetIndexedString. получение строки по индексу
17.14. Функция HidD_Jetlnput Report получение Input-репорта
17.15. Функция HidD_SetOutputReport. передача Output-репорта
17.16. Функция HidP_GetCaps: получение свойств устройства
17.17. Функция HidP_MaxDataListLength: получение размеров репортов
17.18. Функция HidD_FIushQueue: сброс буферов
17.19. Функция HidP_GetLinkColiectionNodes: дерево коллекций
17.20. Функции HidP_GetScaledUsageValue u HidP_SetScaledUsage Value: получение и задание преобразованных значений
17.21. Функция HidF_MaxUsageListLength: размер буфера для кодов клавиш
17.22. Функция HidP_UsageListDifference: различие между массивами
Приложения
Приложение 1. Дополнительные функции
Приложение 2. Компиляция примеров в других версиях Delphi
Приложение 3. Таблица идентификаторов языков (LangID)
Приложение 4. Таблица кодов производителей (Vendor ID, Device ID)
Приложение 5. Как создать ярлык Device Manager
Приложение 6. Часто задаваемые вопросы
Приложение 7. Описание компакт-диска
Литература
Предметный указатель