USB HID kommunikáció
A fejezet tartalma:- Az USB HID eszközosztály
- Az USBHID objektumosztály
- Saját GUI alakalmazás készítése a 13_USBHID_demo projekthez
- Általános (generikus) tesztprogramok a HID kapcsolatok vizsgálatára
Az USB HID eszközosztály
Az USB eszközök funkció szerint elkülönülnek egymástól, ennek
megfelelően az USB 2.0 specifikációja
különféle osztályokba sorolja az eszközöket. Ilyen osztályok pl.
a hangeszköz (Audio), képeszköz (Image), kommunikációs eszköz
(Communication), Nyomtató, Tárolóeszköz (Mass Storage), stb. Egy
speciális osztály a HID (Human Interface Device). A HID eszközök
eredetileg olyan periféria csoportot jelentenek, amelyek
segítségével a
felhasználó képes vezérelni a számítógépet, illetve a számítógép
megjelenítheti a saját kimeneteit. Ilyen eszközök pl. a
billentyűzet,
egér, játékvezérlő, különböző kijelzők. Ezek a hardverek nagyon
elterjedtek, ezért az USB szabványban előre definiált
alosztályok
szerepelnek a fent említett eszközök számára. A HID kapcsolat főbb jellemzői:
- Minden tranzakció vezérlő vagy megszakítás típusú átvitelt használ.
- Tranzakciónként legfeljebb 64 bájt vihető át.
- A maximális átviteli sebesség 1 tranzakció/ms, ami
átszámítva legfeljebb 64 KB/s adatátviteli sebességet
jelent. Ez ugyan
elmarad az ömlesztett (bulk) átvitelnél elvileg elérhető 1
MB/s körüli
sebességtől, de sok alkalmazáshoz bőven elegendő, s a
robusztusabb
kapcsolat érdekében felvállalható.
- Csak egy kiviteli és egy beviteli végpont használható (a vezérlő csatorna mellett).
- A gazdagép periodikusan kérdezi le a HID eszközt.
Az általános (generic) HID eszközök alosztálya
Amikor egy USB eszközt csatlakoztatunk a számítógéphez, akkor egy "bemutatkozó párbeszéd" kezdődik, melynek során a gazdagép (ami esetünkben a PC) "kikérdezi" az USB eszközt (adatsebesség, eszközosztály, gyártó, VID/PID azonosítók stb.). Ezeket az információkat az eszköz firmware ún. eszközleíró táblába tárolja. A HID eszközök emellett még egy jelentésleíró táblát is tartalmaznak, amelyek a HID eszköz által küldött adatcsomagokról (az úgynevezett jelentésekről) nyújtanak tájékoztatást. A szabványos HID eszközöknél az ún. HID report descriptor (HID jelentés leíró tábla) megmondja, hogy az átvitt adatcsomag egyes bájtjai (vagy bitjei) mit jelentenek.A HID eszközosztály azonban nem korlátozódik kizárólag ilyen előre definiált, szabványos eszközökre, hanem teret nyújt az egyedileg készített eszközöknek is. A HID eszközosztály legáltalánosabb alosztálya az Általános HID Eszköz (Generic HID Device), amelynél nincs kötött protokoll. Ezeknél az eszközöknél a HID jelentésleíró tábla csak az átvitt adatok mennyiségét mondja meg, az adatok értelmezése azonban a mikrovezérlőbe töltött firmware-re és a PC-n futó alkalmazásra van bízva. Ebben az esetben tehát csak az átvitel mikéntje szabványos, az adatok felhasználása pedig gyártóspecifikus.
Az USBHID objektumosztály
Az USBHID objektumosztály a fentebb említett "Általános HID Eszközt" (Generic HID Device) valósítja meg. Az USBHID osztály tagfüggvényeivel üzeneteket küldhetünk és kaphatunk az USB buszon. Saját protokollt dolgozhatunk ki és eszerint kommunikálhatunk a mikrovezérlő és a számítógép között.A mikrovezérlő oldalon ehhez a kommunikációs típushoz az USBHID objektumosztályt kell használnunk. Az mbed API alapértelmezetten nem tartalmazza az USB kommunikációt kezelő programkönyvtárakat. Projektjeinkhez - eszközosztálytól függetlenül - az USBDevice programkönyvtárat kell hozzáadni a projekthez. Ehhez a Makefileban ezt írjuk:
USER_LIBS := $(GCC4MBED_DIR)/external/mbed-os/features/unsupported/USBDevice
Az USBHID objektumosztály legfontosabb tagfüggvényeit az alábbi táblázatban foglaltuk össze.
| Függvénynév |
Rövid leírás |
|---|---|
| USBHID (uint8_t
output_report_length=64, uint8_t input_report_length=64,
uint16_t
vendor_id=0x1234, uint16_t product_id=0x0006, uint16_t
product_release=0x0001, bool connect=true) |
Konstruktor
függvény.
Példányosítja és inicializálja az USBHID
objektumosztályt, megadja a
kimenő és bejövő adatblokk méretét, a VID/PID
azonosítót, s a connect
paraméter értékétől függően kapcsolódik (vagy nem) |
| read(HID_REPORT* report) |
Egy adatblokk fogadása
blokkoló várakozással |
| readNB(HID_REPORT* report) |
Egy adatblokk fogadása
nem blokkoló módon |
| send(HID_REPORT* report) |
Egy adatblokk küldése blokkoló várakozással |
| sendNB(HID_REPORT* report) | Egy adatblokk küldése nem blokkoló módon |
Megjegyzések:
- A read, readNB, send,
sendNB tagfüggvényeknél a logikai típusú
visszatérési érték jelzi, hogy sikeres volt-e a küldés vagy
fogadás.
- Az USB eszközöket a gyártó VID és a termék PID azonosító száma azonosítja. Az mbed USBHID alapértelmezett eszközazonosítója VID = 0x1234, PID = 0x0006. Ha ezt megváltoztatjuk (a konstruktor hívásánál), akkor a PC oldalon a kapcsolatot kezelő alkalmazásnál is módosítanunk kell a számokat!
- A konstruktor függvény első két paramétere a kimenő és bejövő adatcsomagok mérete, melyek maximális értéke 64 bájt lehet (ez az alapértelmezett érték).
- Az USBHID használatához a számítógépen szükségünk lesz egy olyan alkalmazásra, amely "szóba áll velünk", azaz képes kezelni az USBHID adatforgalmat. Ennek nem feltétlenül kell grafikus felhasználói felülettel rendelkeznie, lehet akár egy szkript is, amihez használhatjuk a Python értelmező pywinusb kiegészítését. Egy másik lehetőség a multiplatformos hidapi könyvtár használata, amelyet C/C++ konzol alkalmazásokból vagy grafikus alkalmazásokból is használhatunk.
Mintapélda: USB HID kommunikáció
Az alábbi programot a Cypress
AN82072 alkalmazási mintapéldájához igazítva készítettük el, hogy annak a letölthető ZIP csomagjában
található grafikus PC alkalmazását használni tudjuk. Ennek megfelelően
mindkét irányba 8 bájtos csomagokat küldünk, s az adatok értelmezése és
felhasználása az alábbiak szerint történik:
1. ábra: Az adatcsomagok értelmezése és felhasználása
Az Input/Output irány mindig a gazdagép szempontjából értendő. Az Input Report tehát a mikrovezérlő által küldött 8 bájtos csomagot jelenti, melynek első bájtja egy nyomógombhoz rendelt bemenet állapotát jelzi (1: lenyomva, 0: felengedve), a következő négy bájt pedig egy analóg bemenet jelének ADC-vel konvertált eredményét jelenti (a Cypress mikrovezérlőknél van 20 bites ADC is, ezért nem volt elég egy kétbájtos adatküldés az ADC-hez). A bájtsorrend úgynevezett Big Endian, azaz a legmagasabb helyiértékű bitek állnak elől.
Az Output Report (a gazdagép által kiküldött üzenetcsomag) pedig vezérlési funkciót lát el: az elsó bájt egy LED-et vezérel (0: ki, 1: be), a második bájt pedig egy másik LED fényerősségét vezérli (1 - 100 közötti értéket küldhetünk ki, ami a PWM jel százalékos kitöltését adja meg).
Esetünkben a D3 (belső felhúzásra kapcsolt) bemenet figyeli a nyomógomb állapotát, s az A0 bemenetre kapcsolt feszültséget mérjük meg. A kimeneti vezérlésnél LED1 (a piros LED) lesz a ki-be kapcsolható LED, s LED2 (a zöld LED) lesz az, melynek fényerősségét folyamatosan szabályozzuk (PWM).
Végeredményben tehát az egyszerű mintapéldán keresztül megmutatjuk, hogy az USB HID kapcsolat segítségével hogyan végezhetünk analóg és digitális adatgyűjtést/adatbeolvasást, és hogyan létesíthetünk digitális és (kvázi) analóg vezérlést.
Hardver követelmények:
- FRDM-KL25Z kártya
- Analóg jel az A0 (PTB0) bemenetre kötve
- Nyomógomb a D3 (PTA12)
digitális bemenet és a GND közé kötve.
- A KL25Z USB jelzésű
aljzat csatlakoztatása a számítógéphez
#include "mbed.h"
#include "USBHID.h"
USBHID hid(8, 8);
HID_REPORT send_report; // Buffer for transmission to Host (MCU -> PC)
HID_REPORT recv_report; // Buffer for data received from Host (PC -> MCU)
// Hardware Pin Configurations for FRDM-KL25Z Board
DigitalOut LED_1(LED1); // Onboard Red LED
PwmOut LED_2(LED2); // Onboard Green LED
DigitalIn SW1(D3, PullUp); // Push button with internal pull-up
AnalogIn adc(A0); // Analog Input on channel A0
int main(void)
{
// Set the report length explicitly (8 bytes payload)
send_report.length = 8;
LED_1 = 1; // Turn OFF LED_1 initially (Active-LOW hardware driver)
LED_2.period_ms(20); // Configure PWM base period to 20ms (50 Hz frame frequency)
while (1) {
uint16_t raw = adc.read_u16(); // Read 16-bit ADC data from pin A0
for (uint8_t i = 0; i < send_report.length; i++) {
send_report.data[i] = 0x00;
}
send_report.data[0] = !SW1.read(); // Button state: 0: released, 1: pressed
send_report.data[3] = (uint8_t)(raw >> 8); // Most Significant Byte of ADC
send_report.data[4] = (uint8_t)(raw & 0xFF); // Least Significant Byte of ADC
hid.send(&send_report); // Transmit the report (Blocking Call)
if (hid.readNB(&recv_report)) { // Non-blocking poll on USB OUT Endpoint.
LED_1 = !recv_report.data[0]; // Digital LED control (1: On, 0: off)
LED_2.write(1.0f - (recv_report.data[1] * 0.01f)); // PWM LED Control (0 to 100 %)
}
}
}
A 13_USBHID_demo projekt Makefile állománya:
PROJECT := 13_USBHID_demo
DEVICES := KL25Z
GCC4MBED_DIR := ../..
GCC4MBED_TYPE := Release
USER_LIBS := $(GCC4MBED_DIR)/external/mbed-os/features/unsupported/USBDevice
MBED_OS_ENABLE := 0
NEWLIB_NANO := 1
NO_FLOAT_SCANF := 1
NO_FLOAT_PRINTF := 1
include $(GCC4MBED_DIR)/build/gcc4mbed.mk
A program elején be kell csatolnunk az USBHID.h fejléc állományát.
Ezután példányosítanunk kell az USBHID
objektumosztályt. Programunkban csak az ki- és bemenő üzenetcsomag
méreténél tértünk el az alapértelmezett értékektől, tehát csak ezeket a paramétereket kell átadni a konstruktor
függvénynek. Az üzenetcsomagok tárolásához deklarálnunk kell egy-egy HID_REPORT
típusú tömböt is (a ki- és bemeneti buffer elnevezése itt a mikrovezérlő szempontjából értendő!). A program végtelen ciklusában az ADC mérés után automatikusan összeállítjuk és kiküldjük a gazdagépnek szánt csomagot. A nem használt bájtokat nullával töltjük fel.
A LED-ek vezérlése a bejövő üzenetcsomagok első két bájtja szerint történik. Ha az első bájt nullától különböző, akkor kigyújtjuk a piros LED-et. A második bájtot úgy konvertáljuk, hogy 100 esetén kapjuk a maximális kitöltést. Mindkét LED vezérlésénél invertálnunk kell a jelet a közös anódú LED-ek fordított logikája miatt.
Megjegyzések:
- A bejövő csomagok figyeléséhez a nem blokkoló típusú readNB() tagfüggvényt kell használnunk, különben "elakad" a programunk, és várakozik, amíg újabb üzenetcsomag nem érkezik!
- A PWM vezérlésnél nincs beépített védelem a 0-100 tartományon kívül eső értékek kezelésére, ennek figyelése a PC oldali program feladata.
- Vegyük figyelembe, hogy az AN82072
alkalmazási mintapélda közzétett programjai csak a Cypress termékekhez használható jogszerűen, ezért
a kipróbáláson és egyéni tanuláson kívül ne használjuk másra a
FRDM-KL25Z kártyánkkal!
- A program futtatásakor be kell állítanunk a VID és PID azonosítókat és rá kell kattintanunk a Set gombra. Ezután a zöld Connected felirat jelenik meg, ha a 13_USBHID_demo programmal felprogramozott kártya csatlakoztatva van.
- A piros LED-et a LED felirat melleti jelölőnégyzet kiválasztásával kapcsolható be és ki.
- A zöld LED fényereje a PWM Duty Cyle címke mellett állítható be 1 és 100 közötti értékre, de ennek kiküldése csak az Update gomb kattintásakor történik meg.
- A bejövő értékek (az ADC konverzió 16 bites eredménye és a D3
digitális bemenet állapota) a vezérlőelemek alatt látható. Az ON
kiírás a digitális bemenet magas szintjét, az OFF
pedig az alacsony szintjét jelenti. Mivel a nyomógombunk a GND felé
húz, ezért a fordított logika miatt a felirat a nyomógomb állapotát
fordítva jelzi ki.

2. ábra: A Cypress AN82072 alkalmazási mintapéldából "kölcsönvett" program futtatása
Saját GUI alakalmazás készítése a 13_USBHID_demo projekthez
A tananyag eredeti megírása után 6 évvel elérkezettnek láttuk az időt, hogy a mikrokontrolleres oldal mellé egy teljesen saját, nyílt forráskódú PC-s célszoftvert is letegyünk az asztalra. A választás a Python nyelvre esett: az USB HID csomagok alacsony szintű kezelését a pywinusb könyvtárra bíztuk, míg a grafikus kezelőfelületet (GUI) a Qt-alapú PySide6 segítségével építettük fel.
Hogy a PySide6 elrendezési képességeit és rugalmasságát élesben is próbára tegyük, a felület vizuális elrendezését szándékosan a Cypress tesztprogram mintájára alakítottuk ki. Így a felhasználó pontosan ugyanazokat a vezérlőelemeket (gomb állapot, PWM csúszka, ADC kijelzés) találja meg, de már egy modern, platformfüggetlen Python környezetben.
Az előzményekről és a technikai részletekről a 2022. őszi előadásokban esett szó:- A pywinusb Python bővítmény használata
- Python grafikus bővítmények használata - 1. rész
- Python grafikus bővítmények használata - 2. rész
- Az öröklés és inicializálás módját, illetve sorrendjét utólag meg kellett változtatni
- A Python interpereter és a grafikus könyvtárak olyan mértékben lassították a programot, hogy a mikrovezérlő felől másodpercenként érkező több száz USB HID adatcsomagot nem győzte feldolgozni és grafikus felületet frissíteni.
A problémákat csak 2026-ban sikerült végleg felszámolni egy szálbiztos Qt Signal architektúrával. A letölthető h2022_05.zip melléklet már ezt a kijavított HIDTest_app projektet tartalmazza.
A HIDTest_app alkalmazás futtatásához az alábbi szoftverkörnyezet szükséges: Python 3.10 (vagy újabb 64 bites kiadás) pywinusb 0.4.2, valamint PySide6 6.3.2

3. ábra: A saját GUI alkalmazás futtatása
Általános (generikus) tesztprogramok a HID kapcsolatok vizsgálatára
Az alábbiakban bemutatunk néhány további lehetőséget, amellyel gyorsan és egyszerűen kipróbálhatjuk mbed USB HID mikrovezérlő programjainkat. Ezek az úgynevezett generikus (általános) HID tesztprogramok nem ismerik az alkalmazásspecifikus protokollt, csupán „fatengelyes”, nyers, bájtszintű hozzáférést biztosítanak bármely USB HID eszközhöz, ami felbecsülhetetlen segítség, ha a firmware legelső lépéseit kell ellenőrizni és nincs kéznél egy előre megírt grafikus kezelői felület.
A legelterjedtebb általános teszteszközök:
- SimpleHidWrite: Egy klasszikus, pehelykönnyű és fapados Windows-os segédprogram. Semmi cicoma: megadjuk a VID/PID azonosítókat, ő pedig nyersen, hexadecimális bájtok formájában jeleníti meg a beérkező riportokat, és ugyancsak hexában küldhetünk vele tetszőleges adatsort az MCU-nak.
- HIDAPI – testgui: A népszerű, cross-platform hidapi könyvtár hivatalos grafikus tesztalkalmazása. Bár van GUI-ja, a működése célszerűen egyszerű: kilistázza a rendszerben talált összes HID eszközt, és lehetővé teszi a nyers ki- és bemeneti riportcsomagok manuális pötyögését és megtekintését Windows, Linux és macOS alatt.
- HIDAPI – hidtest: A hidapi parancssoros (CLI) változata. Még a testgui-nál is puritánabb: a terminálba ontja ki az érkező bájtokat, így kiválóan alkalmas automatizált tesztszkriptekhez vagy grafikus felület nélküli (headless) rendszereken való hibakeresésre.
SimpleHidWrite
A SimpleHidWrite alkalmazás egyszerű segédeszköz a HID eszközök kipróbálásához vagy felderítéséhez. Minimális HID és USB ismeretek kellenek a program megértéséhez. A grafikus alkalmazás ablakának felső részében található lista a pillanatnyilag elérhető HID eszközöket sorolja fel. A kattintással kiválasztott eszközt ismételten lekérdezi a program, s a beérkezett üzeneteket kilistázza a program ablakának középső részen látható szövegdobozban. A szövegdoboz alatti részben a kimenő üzeneteket állíthatjuk össze (a beírt számok hexadecimálisan lesznek értelmezve, az üresen hagyott mezők automatikusan nullával töltődnek fel), illetve a nyomógombok segítségével az alábbi tevékenységek indíthatók:- "Info" - a kiválasztott eszközről rendelkezésre álló információkat jeleníti meg
- "Save As..." - szöveges naplófájlba menti az addig beérkezett üzeneteket.
- "Playback..." - lehetővé teszi egy elmentett naplófájl újrajátszását (értelemszerűen csak az eszközkiválasztás és az eszközre írás hatásos).
- "Clear" - törli a naplózó ablakot.
- "Write" - adatküldés, ami akkor engedélyezett, ha az USB eszköz deklarál kimenő jelentést.
- "Get Report" és "Set Report" - Windows 98 esetén tiltottak, mivel a HID API abban
nem támogatja ezeket a funkciókat. A Get_Report
egyébként arra szolgál, hogy a vezérlő csatornán (EP0 végpont) kapjon
információt a gazdagép az USB eszköz állapotáról. A Set_Report pedig az
eszköz alaphelyzetbe állítására szolgál (pl. egy pointer eszköz esetén
a jelenlegi pozíció legyen az új viszonyítási helyzet).
- "Get Feature" és "Set Feature" akkor engedélyezettek, ha az USB eszköz deklarált "feature reportot".
- Töltsük le és bontsuk ki SimpleHIDWrite3.zip csomagot!
- Indítsuk el a SimpeHidWrite.exe alkalmazást!
- A megnyíló ablak felső részében kattintsunk a felismert HID eszközünk sorára (a HID DEVICE (Serial=0123456789) eszközt keressük)! A listázó ablakban ekkor elkezdenek pörögni a bejövő üzenetek. Figyeljünk rá, hogy az RD (olvasást) jelzést követő első szám még nem az üzenetcsomagunk része, hanem a jelentés alapértelmezett azonosítója (00)! Az ez követő bájt jelzi a nyomógombunk állapotát, a következő négy bájt pedig az ADC konverzió eredményét.
- Állítsunk össze egy adatcsomagot! A Report ID kötelezően 0, az alatta levő 8 bájt pedig a kiküldendő adatok. Csak a nullától különböző mezőket kell kitölteni! Például: 01 00 00 00 00 00 00 00 bekapcsolja a piros LED-et és leoltja a zöld LED-et. A 0064 00 00 00 00 00 00 csomag lekapcsolja a piros LED-et és teljes fényerőn (100 %-os kitöltés) kigyújtja a zöld LED-et.
- Küldjük ki az adatcsomagot a Write gombra kattintva!
- Mentsük el egy napló állományba a beérkezett és kiküldött csomagokat (Save As... gomb), majd tanulmányozzuk az adatokat! A kiküldött adatokat a WD kezdetű sorok tartalmazzák.

3. ábra: A SimpleHidWrite program használata
HIDAPI - testgui
Alan Ott multiplatformos programkönyvtára
Linux, Mac OS X és Windows alatt is kezelni tudja az USB, illetve
Bluetooth HID eszközöket. A programkönyvtár C/C++ alkalmazásainkból
meghívható, így egyszerűen készíthetünk USB HID eszközt kezelő saját
alkalmazásokat. A HIDAPI
programcsomag egy grafikus felületű tesztprogramot is tartalmaz,
amellyel egyszerűen kipróbálhatjuk és vizsgálhatjuk HID eszközeinket. A
programcsomag legegyszerűbben a Letöltések oldalról
tölthető le. Nekünk csak a legfrissebb hidapi-0.7.0.zip lesz szükségünk
(a hidapi-externals.zip csomag csupán a Windowsos testgui.exe újrafordításához vagy módosításához kellhet). A kibontott csomagból először a testgui.exe alkalmazást keressük meg és próbáljuk ki!
- A program elindításakor megnyíló ablak felső részén keressük meg az 1234:0006 - mbed.org eszközt!
- Ha a program elindítása után csatlakoztattuk a kártyánkat, akkor a Re-Scan devices gombra kattintva frissítsük az elérhető eszközök listáját!
- Válasszuk ki az 1234:0006 - mbed.org eszközt és kattintsunk a Connect gombra! Az ablak alsó részén, az Input szövegdobozban ekkor megjelennek a beérkező üzenetcsomagok (ezek mérete esetünkben 8 bájt, tehát a jelentés azonosítószáma (Report ID) nincs megjelenítve.
- A Output rovatban állítsunk össze egy üzenetet, és küldjük ki a Send Output Report gombra kattintva!
- Az Output rovatba a 8 db adatbájt elé be kell írnunk az alapértelmezett jelentés azonosítót (0) is, tehát szigorúan mindig 9 bájtot kell beírnunk, s az első bájt kötelezően nulla legyen! Minden más esetben hibajelzést kapunk.
- Az
általunk beírt adatokat alapértelmezetten decimálisnak veszi a program.
Hexadecimális bájtokat 0x prefix-szel adhatunk meg. A beérkezett
adatokat mindig hexadecimálisan jeleníti meg a program.
Példa adatok:
- A 0 0 0 0 0 0 0 0 0 kimenő adatcsomag (ebben már benne van a Report ID is!) lekapcsolja mindkét LED-et.
- A 0 1 0 0 0 0 0 0 0 kimenő adatcsomag bekapcsolja a piros LED-et.
- A 0 0 10 0 0 0 0 0 0 kimenő adatcsomag 10 %-os PWM kitöltéssel bekapcsolja a zöld LED-et.

4. ábra: A HIDAPI testgui.exe alkalmazás futtatása
HIDAPI - hidtest
Alan Ott multiplatformos programkönyvtárának legfontosabb része
a hidapi.dll, amelyet saját C/C++ programjainkból meghívhatjuk. A hidapi csomag windows mappájában
található egy Visual C++ 2008 Express Edition-nal lefordítható projekt
(a hidapi.sln állományt nyissuk meg!), amely a hidapi.dll mellett egy konzolos (nem grafikus felületű) mintaalkalmazást
is lefordít (hidtest.exe). Ennek forráskódját némileg módosítottuk. A
módosítások lényege:- Módosítottuk a Vid/Pid azonosítót (0x1234, 0x0001), és az üzenetcsomagok méretét (9 byte a Report ID-vel együtt).
- Összesen 20 adatcsomagot küldünk ki és fogadunk (minden küldés után 500 ms várakozást iktatunk be).
- A kiküldött adatokat úgy állítjuk elő, hogy a piros LED csak kétszer villan fel, a zöld LED fényereje pedig fokozatosan növekszik 5 %-os lépésekben.
- A kiküldött és a beérkező adatcsomagokat egymás mellé kiíratjuk.
2. lista: A módosított hidtest.c program listája
#include <stdio.h>
#include <wchar.h>
#include <string.h>
#include <stdlib.h>
#include "hidapi.h"
// Headers needed for sleeping.
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
int main(int argc, char* argv[])
{
int res;
unsigned char buf[9];// 1 extra byte for the report ID
#define MAX_STR 255
wchar_t wstr[MAX_STR];
hid_device *handle;
int i;
#ifdef WIN32
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
#endif
struct hid_device_info *devs, *cur_dev;
devs = hid_enumerate(0x0, 0x0);
cur_dev = devs;
while (cur_dev) {
printf("Device Found\n type: %04hx %04hx\n path: %s
\n serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id,
cur_dev->path, cur_dev->serial_number);
printf("\n");
printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string);
printf(" Product: %ls\n", cur_dev->product_string);
printf(" Release: %hx\n", cur_dev->release_number);
printf(" Interface: %d\n", cur_dev->interface_number);
printf("\n");
cur_dev = cur_dev->next;
}
hid_free_enumeration(devs);
// Set up the command buffer.
memset(buf,0x00,sizeof(buf));
buf[0] = 0x01;
buf[1] = 0x01;
buf[2] = 0x01;
// Open the device using the VID, PID,
// and optionally the Serial number.
////handle = hid_open(0x4d8, 0x3f, L"12345");
handle = hid_open(0x1234, 0x6, NULL);
if (!handle) {
printf("unable to open device\n");
return 1;
}
// Read the Manufacturer String
wstr[0] = 0x0000;
res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
if (res < 0)
printf("Unable to read manufacturer string\n");
printf("Manufacturer String: %ls\n", wstr);
// Read the Product String
wstr[0] = 0x0000;
res = hid_get_product_string(handle, wstr, MAX_STR);
if (res < 0)
printf("Unable to read product string\n");
printf("Product String: %ls\n", wstr);
// Read the Serial Number String
wstr[0] = 0x0000;
res = hid_get_serial_number_string(handle, wstr, MAX_STR);
if (res < 0)
printf("Unable to read serial number string\n");
printf("Serial Number String: (%d) %ls", wstr[0], wstr);
printf("\n");
// Read Indexed String 1
wstr[0] = 0x0000;
res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
if (res < 0)
printf("Unable to read indexed string 1\n");
printf("Indexed String 1: %ls\n", wstr);
// Set the hid_read() function to be non-blocking.
hid_set_nonblocking(handle, 1);
// send and receive 20 reports
for (int r = 0; r < 20; r++) {
// send some dummy data
buf[0] = 0; //Report ID
buf[1] = ((r%10)==8); //Only for 8 and 18
buf[2] = 5*r; //0,5,10,15...
buf[3] = 0;
buf[4] = 0;
res = hid_write(handle, buf, sizeof(buf));
if (res < 0) {
printf("Unable to write()\n");
printf("Error: %ls\n", hid_error(handle));
} else {
printf("Data sent: ");
// Print out the returned buffer.
for (i = 0; i < res; i++) printf("%02hhx ", buf[i]);
}
// Read requested state. hid_read() has been set to be
// non-blocking by the call to hid_set_nonblocking() above.
// This loop demonstrates the non-blocking nature of hid_read().
res = 0;
while (res == 0) {
res = hid_read(handle, buf, sizeof(buf));
if (res == 0)
printf("waiting...\n");
if (res < 0)
printf("Unable to read()\n");
#ifdef WIN32
Sleep(500);
#else
usleep(500*1000);
#endif
}
printf(" Data read: ");
// Print out the returned buffer.
for (i = 0; i < res; i++) printf("%02hhx ", buf[i]);
printf("\n");
}//end 20 reports
//close HID device
hid_close(handle);
/* Free static HIDAPI objects. */
hid_exit();
#ifdef WIN32
system("pause");
#endif
return 0;
}
A program futási eredménye az alábbi ábrán látható.
5. ábra: A módosított hidtest program futtatása
Megjegyzés: A testgui.exe programnál említett kettősség itt is megfigyelhető: A kimenő adatcsomagnál a Report ID is megjelenik, beolvasásnál viszont a HIDAPI "lenyeli" a Report ID-t, a bejövő csomagoknál csak a nyolc adatbájtot kapjuk meg!