Основи розробки та програмування найпростіших USB-пристроїв. Програмування USB в Android

Жарознижуючі засоби для дітей призначаються педіатром. Але бувають ситуації невідкладної допомоги при лихоманці, коли дитині потрібно дати ліки негайно. Тоді батьки беруть на себе відповідальність і застосовують жарознижуючі препарати. Що дозволено давати дітям грудного віку? Чим можна збити температуру у дітей старшого віку? Які ліки найбезпечніші?

Вступ
Для кого ця книга
Що ви знайдете в книзі
програмні вимоги
вимоги до апаратного забезпечення
Про програмному коді
Короткий опис глав
позначення
Подяки
Зворотній зв'язок
Частина 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. Опис компакт-диска
література
покажчик

Але ж мало тільки фізично під'єднати пристрій до комп'ютера, потрібно ще й налагодити обмін даними між ними. Як же вибрати порт і організувати підключення? Кілька років тому стандартним рішенням було використання 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.


рис.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 дозволяє істотно підвищити швидкість передачі даних і зробити цей процес зручним для користувача. Швидкість передачі, яка навіть в разі низькошвидкісних пристроїв (клавіатури, миші, джойстики), становить 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. посилання на вихідні додатки

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

Ось зараз ми і будемо її створювати.

Знову ж в пакеті 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.
Спасибі!

Підтримайте проект - поділіться посиланням, спасибі!
Читайте також
Сбебранк (він же Ощадбанк) Сбебранк (він же Ощадбанк) Рішення проблем з ліцензією у Autocad Чи не запускається autocad windows 7 Рішення проблем з ліцензією у Autocad Чи не запускається autocad windows 7 Інструкція з використання PIN коду КріптоПро, під час підписання кількох документів - Інструкції - АТ Інструкція з використання PIN коду КріптоПро, під час підписання кількох документів - Інструкції - АТ "ПЕК-Торг"