Інтерфейс USB (практика використання та програмування). Програмування USB в Android. Використовуємо для зв'язку інтерфейс USB Програмування різних пристроїв через USB

Як уже згадувалося, операційні системи 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 пристрої із системи

Програмування через порт USB

Програмування приладу для налаштування супутникових антен SF-50 через порт USB відрізняється від програмування через порт RS-232 лише способом передачі даних із приладу на комп'ютер та комп'ютера на прилад. При програмуванні через USB працює портативний USB накопичувач (флешка). Це зручно коли, наприклад, ваш комп'ютер або частіше ноутбук (нетбук) не має на своєму шасі послідовного RS-232 порту.
Для програмування приладу з використанням USB накопичувача знадобляться:
- USB накопичувач (флешка), відформатована у файлову систему FAT-32;
- Програма-редактор AliEditor, знаходиться в папці Database_editor_new розділу софт приладу OPENBOX SF-50.

Перед початком програмування необхідно перенести базу даних з приладу на комп'ютер. Для цього увімкнути пристрій, підключити до порту USB флешку. Виконати MENU – Система – Зберегти на USB,

Вийти з меню натисканням кнопки MENU до появи поточного каналу, або до зображення головного меню, якщо канали поки відсутні і витягти флешку. Вставити флешку у комп'ютер.
Запустити програму Editor.exe з папки Database_editor_new та відкрити в ній імідж на флешці.

На запит про вибір бази даних вибрати User Data Base.

Натисніть кнопку ОК. Вибрати All Services, відкриється список всіх наявних у базі просканованих та збережених теле, радіо та сервісних каналів.

Відредагувати канали на власний розсуд, наприклад, залишити лише відкриті канали.
На клавіатурі комп'ютера затиснути кнопку Shift, натиснути "Стрілка вниз" та виділити канали, які потрібно видалити. Натиснути Delete для видалення вибраного.

Для редагування налаштувань на супутник, вибрати All Services – Satellite Information – EUTELSAT W4, W7, натиснути кнопку ENTER.

При необхідності відредагувати значення Antenna 1.
Для видалення транспондера стати на непотрібний і натиснути кнопку Delete на клавіатурі комп'ютера, підтвердити вибрану дію.

Для додавання транспондера стати на назву супутника, натиснути праву кнопку миші і вибрати Add Information (або виділивши супутник натиснути кнопку Insert на клавіатурі).

Ввести дані щодо нового транспондера, взявши їх, наприклад, на сайті lyngsat.com.

Натиснути ОК, переконатись, що транспондер прописався.

Щоб додати супутник, стати на рядок Satellite Information, натиснути клавішу Insert на клавіатурі та ввести параметри нового супутника.

закрити програму-редактор, витягти накопичувач.
Вставити накопичувач у пристрій OPENBOX SF-50, виконати послідовно MENU – Система – Оновлення з USB, вибрати режим «Список SAT&TP».

Вибрати Почати. Підтвердити свої наміри.

Прилад оновить базу та самостійно перезавантажиться. Після перезавантаження в налаштуваннях доведеться по-новому встановити російську мову меню. Скинути прилад у заводські налаштування.
Вийти з меню налаштувань, двічі натиснувши кнопку MENU. Натисніть кнопку ОК на поточному каналі та переконайтеся, що список каналів відредаговано.

Також можна переконатися, що відредаговано список транспондерів і супутників.
Програмування закінчено.

Хороша книга, багато що пояснює. Стане в нагоді тим, хто хоче зрозуміти як відбувається передача даних по шині 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
ЧАСТИНА ІІ. ВНУТРІШНЯ ОРГАНІЗАЦІЯ 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
ЧАСТИНА ІІІ. ПРАКТИКА ПРОГРАМУВАННЯ 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.
Дякую!

Але мало лише фізично під'єднати пристрій до комп'ютера, потрібно ще й налагодити обмін даними між ними. Як вибрати порт і організувати підключення? Декілька років тому стандартним рішенням було використання COM-порту. До речі, досі різні фахівці довстановлюють на промислові комп'ютери по 8, по 16, а то й по 32 COM-порти (є ціла категорія різних PCI-плат розширення послідовних портів, контролерів тощо). Таким чином, якщо потрібно підключити кілька зовнішніх пристроїв з інтерфейсом RS-232, можуть знадобитися дорогі адаптери та екзотичні плати розширення, які за старою традицією пливуть тижнями в Росію на пароплавах. До речі, назва звичайного перехідника "адаптер DB9m/DB25f" у менеджера комп'ютерного магазину може викликати хіба що роздратування.

Що таке HID-пристрій

Сьогодні майже всі пристрої підключаються до комп'ютера через USB-інтерфейс. Тому у багатьох нових ПК COM-порт немає взагалі.

USB-інтерфейс - типове рішення щодо поєднання нового зовнішнього пристрою з комп'ютером, точніше, це HID-інтерфейс, що базується на протоколі USB 1.1.

Хоча багато хто й вважає, що HID-інтерфейс (Human Interface Device) призначений виключно для клавіатури, миші та джойстика, він підходить для безлічі рішень, пов'язаних зі сполученням зовнішніх пристроїв і комп'ютера.

Якщо користувачеві необхідно проводити низькошвидкісний обмін даними (до 64 кбіт/c) і бажано скоротити час на стомлюючій розробці власних драйверів, то йому цілком підійде HID. На виході вийде просте і сучасне рішення на базі стандартного програмного USB-інтерфейсу з гарантованою підтримкою на всіх поширених програмних платформах.

Властивості пристрою HID

З точки зору організації програмної підтримки HID-пристрою все виглядає досить привабливо: для роботи під керуванням Windows можна швидко створювати зрозумілий компактний код на базі готових перевірених алгоритмів. При цьому у розробника залишиться багато часу на реалізацію власного протоколу обміну даними верхнього рівня, оскільки необхідний рівень абстрагування вже організований за рахунок протоколу HID (див. таблицю). Крім того, програміст легко проводити налагодження написаного протоколу обміну (зрозуміло, за наявності працюючого HID-пристрою) - завдяки відносній жорсткості самого протоколу досить просто розробити програму підтримки пристрою комп'ютером. Ще б! Масу роботи вже взяв він творець HID-устройства.

Організація обміну даними між HID-пристроєм та комп'ютером

Щоб описати взаємодію HID-пристрою з комп'ютером, використаємо термін «хост». У цьому випадку під ним розуміється керуючий пристрій у загальній фізичній архітектурі взаємодії USB-протоколом. Так, усі порти в комп'ютері – хости. До них можна підключати різні USB-пристрої (флешки, миші, веб-камери, фотоапарати та ін.), які не мають хоста. Хост забезпечує виявлення, підключення, відключення, конфігурування пристроїв, а також збирання статистики та керування енергоспоживанням.

HID-пристрій може встановити частоту опитування, під час якого з'ясовується наявність у ньому будь-яких нових даних. Значить, навіть на такому низькому рівні програміст може довіритись системі, оскільки частота опитування та інші параметри обміну даними повинні бути заздалегідь задані у програмі контролера HID-пристрою. Цим протоколом HID відрізняється від загального опису USB 1.1 або USB 2.0, в якому немає жорстких вимог до організації протоколу. Однак при специфічних завданнях, що вимагають підвищеного рівня безпеки, може виявитися досить складно позбавитися циклічних опитувань, коли постійно передаються майже одні й ті самі блоки даних.

Особливості програмування HID-пристроїв

HID пристрої мають спеціальні дескриптори. Коли хост визначить, що пристрій належить до класу HID, він передає керування ним відповідного драйвера. Передбачається, що подальший обмін даними ведеться під його керівництвом.

У Windows за доступ до пристроїв HID відповідає системна служба HidServ. Докладніше про функції запитів до HID-пристроїв та інші особливості роботи з HID-драйвером розповідається в роботі П. Агурова «Інтерфейс USB. Практика використання та програмування »(СПб.: БХВ-Петербург, 2005).

Програмування пристроїв HID на «верхньому рівні»

Нелегке життя прикладних програмістів, що працюють на Паскалі, полегшує перевірений модуль HID. PAS, програмна оболонка для hid. dll (Hid User Library – як зазначено у властивостях файлу). У коментарях до файлу повідомляється, що в його основі лежать модулі hidsdi.h і hidpi.h корпорації Microsoft. Сам файл HID. PAS – частина пакету JEDI().

Для роботи з HID-пристроєм у середовищі Delphi for win32 застосовується компонент TJvHidDeviceController, що є зручним глобальним менеджером для доступу до HID-пристроїв. А вже на його базі можна отримати об'єктний екземпляр для роботи з конкретним пристроєм.

Основні властивості та події компоненту TJvHidDeviceController

Розглянемо компонент TJvHidDeviceController докладніше. Подія OnArrival спрацьовує на вступ (підключення) до системи HID-пристрою, доступ до пристрою надається в обробнику цієї події через екземпляр класу TJvHidDevice. Проста подія OnDeviceChange реагує на зміну стану пристрою, тільки сигналізує про зміни в системі. Подія OnDeviceData спрацьовує при надходженні даних від одного з пристроїв HID і передає обробникові наступне: HidDev: TJvHidDevice; - Пристрій, від якого були отримані дані;

Подія OnDeviceDataError повідомляє про помилку передачі даних, передаючи процедуру обробки параметри HidDev: TJvHidDevice; - HID-пристрій та Error: DWORD; - код помилки. Подія OnDeviceUnplug повідомляє про виймання пристрою зі списку встановлених у системі. Типи обробників подій на Plug та Unplug однакові (у вихідному тексті: TJvHidUnplugEvent = TJvHidPlugEvent). Обробник передає об'єкт класу TJvHidDevice, що відповідає HID-пристрою.

Для послідовного перерахування наявних у системі HID-пристроїв на виклик методу Enumerate призначено подію OnEnumerate, тобто в обробнику події знайдені пристрої послідовно передаються у вигляді об'єктів. Ця подія примусово ініціюється методом Enumerate, що використовується для «проведення» наявних пристроїв HID через обробник, наприклад при ревізії стану пристроїв HID з ініціативи хоста (комп'ютера).

Подія OnRemoval спрацьовує на фізичне вилучення пристрою із системи та має той же тип обробника TJvHidUnplugEvent, що і для OnDeviceUnplug. Функція CountByProductName видає кількість пристроїв, що задовольняють вказаний в аргументі імені продукту, а CountByVendorName - вказаний в аргументі імені виробника.

Основні властивості та події класу TJvHidDevice

Клас TJvHidDevice - віртуальна вистава окремо взятого HID-пристрою. Новий об'єкт цього класу можна отримати, як було сказано, з події OnArrival або OnEnumerate. Функціонал класів TJvHidDeviceController і TJvHidDevice частково дублюється, оскільки в першому з них інтегровані загальний інструментарій для роботи з набором наявних в системі пристроїв HID і механізм доступу до одного з них. Пристрій можна однозначно ідентифікувати за властивостями SerialNumber, ProductName та VendorName. Щоб отримати відомості про надходження даних із застосуванням такого об'єкта, можна скористатися подією OnData. Відсилання даних ведеться через метод WriteFile (у строгому сенсі – через функцію). WriteFile – це оболонка системної функції WriteFile (kernel32).

Щоб проконтролювати факт вилучення пристрою, слід присвоїти свій обробник події OnUnplug. Перед початком обміну даними з HID-пристроєм потрібно переконатися у можливості такого обміну за допомогою HasReadWriteAccess. У цьому класі виникнення помилки обміну даними навіть є окрема подія OnDataError.

А тепер розглянемо фрагменти коду із «живого» проекту, що реалізує тестовий клієнтський додаток для організації обміну даними з нестандартним пристроєм – пластиковими чіп-картами на базі HID. У боротьбі за реалізм автор взяв він сміливість не викидати з лістингів «зайві» технологічні обв'язки коду.

Метод ScanDevices (листинг 1) призначений для ініціювання процесу пошуку в системі необхідного пристрою HID. Більшість коду, крім виклику методу Enumerate, необов'язкова і забезпечує гнучкість програми, наприклад, у тому, щоб у цю саму тестову програму можна було додати можливість роботи з інтерфейсу, відмінному від HID. Метод AddError виводить у вікно налагоджувальну інформацію в процесі роботи програми.

У лістингу 2 наведено обробник події OnEnumerate для пошуку необхідного зовнішнього пристрою. Для простоти вважатимемо, що програма може працювати лише з одним пристроєм потрібного їй типу.

Перш ніж розглядати подальшу реалізацію проекту, слід трохи розповісти про прийнятий формат обміну даними верхнього рівня, тобто про структуру, покликану бути посередником між методами прийому-передачі даних та конкретним розв'язуваним прикладним завданням. Справа в тому, що тут розробнику надається можливість реалізувати свої творчі здібності. Точніше, розробникам, бо процес створення нового протоколу дуже часто буває двостороннім, і при цьому першу скрипку грає той, кому важче реалізовувати алгоритм обміну. Загалом, хоч би яким був протокол обміну, завжди приємно робити кожну програмну сутність максимально наочною та самодостатньою, хай навіть на шкоду деяким загальноприйнятим традиціям. Бо найкраще рішення - те, яке буде реалізовано в стислий термін з мінімальною прив'язкою до програмного середовища та з великими можливостями подальшого розвитку. На основі цих принципів було створено протокол обміну верхнього рівня, де головне поняття – «команда». З лістингу 3 видно, наскільки автор любить рядкові дані, які неодноразово рятували його при налагодженні програмних модулів. Як же чудово, що у нас взагалі є тип String! Усі команди протоколу діляться на категорії (класи), у яких існує код команди, однозначно характеризує її призначення. Параметр edParam служить для надсилання даних у пристрій, а параметр edAnswerData містить у собі отримані від пристрою дані. Рядковий тип описаних членів запису дозволяє вільно та наочно маніпулювати даними у форматі HEX-рядка. І що найприємніше, формат описаного запису ідеологічно стоїть десь посередині між його безпосереднім призначенням та різними формами її подання (INI, HEX, XML тощо).

Виконання команди, тобто відсилання даних пристрій, реалізовано із застосуванням відсилання пакетів даних довжиною 8 байт (листинг 4). Ця довжина не єдине рішення, такий вибір продиктований вимогами протоколу верхнього рівня і в кожному конкретному випадку може бути іншим. Це, як то кажуть, справа смаку. Дивний прапор IsUSBMode у методі ExecuteCommand (листинг 5 на «Світ ПК-диску») залишений як нагадування про те, що замість роботи з USB нам може знадобитися використовувати COM-порт або інший інтерфейс. На початку відсилається групи даних пристрій передається синхросерія довільно вибраного формату (наприклад, 3E3E3E2B), повідомляє пристрою, що у нього на вході цілком легальні дані. Нагадаю, що в даному випадку йдеться не стільки про HID, скільки про специфічний протокол верхнього рівня, ідеологічно відірваний від «заліза» і призначений для вирішення особливих прикладних завдань.

В обробнику GetDataExecutor отриманих від пристрою даних (пакет по 8 байт) використано спеціально створену подію OnNewInputData для передачі первинно оброблених даних на подальшу обробку, причому із зазначенням їх старого та нового значень (листинг 6 на «Світ ПК-диску»). Таким чином, події надходження необроблених даних та вказівку на подальшу обробку розв'язуються, дозволяючи додавати якийсь специфічний алгоритм попередження на ранньому етапі помилкової, повторної чи непотрібної вхідної інформації.

Представлені приклади роботи з HID-пристроєм ілюструють загальну ідею статті - відносну простоту програмування нестандартних HID-пристроїв засобами Delphi.