úterý 17. června 2008

Vinculum: ovládání USB zařízení

V rámci jednoho z fakultních projektů jsem byl postaven před řešení problému, jak ovládat signálový generátor Rohde&Schwarz SM300. Požadavkem bylo řízení z autonomního systému (tedy bez PC jako prostředníka). Jako USB Host byl vybrán poměrně rozšířený a známý obvod Vinculum VNC1L firmy FTDI. Zapojení tohoto obvodu a zprovoznění není nijak extra záludné, pěkná série článků vyšla i v češtině na Pandatronu. Problémy se začnou objevovat ve chvíli, kdy chceme připojit zařízení, které není standardně podporováno, tj. nespadá mezi různé flashdisky, HID, tiskárny apod. Takovým zařízením je samozřejmě i zmíněný vektorový generátor.

Dalším problémem pak může být nezveřejněný/utajený komunikační protokol mezi USB periferií a počítačem. V tomto příspěvku bych rád nastínil vhodný software a postupy pro odhalení komunikačního protokolu neznámého zařízení a jeho implementaci do mikroprocesoru řídicího Vinculum. Nepředpokládám, že by někdo řešil komunikace konkrétně se SM300, stejně tak se rozhodně nesnažím o podrobný návod - spíš se jedná o náznaky, jaké postupy při tvorbě ovladačů realizujících komunikaci přes Vinculum použít.

Co bude potřeba: vhodný počítač, ke kterému lze požadované USB zařízení připojit, s nainstalovanými ovladači a aplikací k řízení tohoto zařízení, dále s programem UsbSnoop; bastldesku s Vinculem, připojeným přes RS232 k počítači; samotné USB zařízení a nějakou tu kabeláž. Z dokumentace pak rozhodně datasheet k VNC1L a k firmwaru VDAP, dále specifikaci USB 2.0 (ano, je to bible, ale občas se to toho člověk musí nakouknout) a samozřejmě Google. Mně zpočátku třeba velice pomohl dokument Reverse engineering Windows USB device drivers for the purpose of creating compatible device drivers for Linux.

Vinculum definuje ve firmwaru VDAP pro práci s obecným USB zařízením sadu příkazů, z nichž o komunikaci se starají Send/Read Data (DSD, DRD) a Send Setup Data (SSU). V první fázi je tedy nutné zjistit, jakým způsobem zařízení komunikuje. To lze vyčíst z logu programu UsbSnoop, ten je však extrémně rozsáhlý a nepřehledný. Pro první nástřel je lepší využít omezené demo některé z komerčních aplikací, např. SysNucleus USBTrace. Po vyfiltrování mnoha nepodstatných paketů se dostaneme k paketům, které odpovídají příkazům zadávaným z počítače. Pro zmíněný generátor SM300 jsou to pakety typu URB_FUNCTION_VENDOR_DEVICE, což představuje Setup pakety (SSU) s Request identifikátorem, který není definovaný standardem, viz USB 2.0 specifikace kap. 9.3 a Vinculum firmware manuál kap. 6.6.6. Ostatní pakety nejsou pro přenos podstatné, což se ovšem liší přístroj od přístroje - např. v ukázce komunikace s klávesnicí na Pandatronu se využívá klasického datového přenosu (DRD). Setup pakety představují vlastně "příkaz" (identifikátor Value), který může obsahovat další data, resp. o ně žádat.

Komunikaci pro jednotlivé příkazy lze zachytit programem UsbSnoop. Pro SM300 pak dojdeme např. při nastavení frekvence 300MHz k záznamu:

[1920707 ms]  >>>  URB 1618 going down  >>>
-- URB_FUNCTION_VENDOR_DEVICE:
TransferFlags = 00000002 (USBD_TRANSFER_DIRECTION_OUT, USBD_SHORT_TRANSFER_OK)
TransferBufferLength = 00000008
TransferBuffer = 00000000
TransferBufferMDL = 85c951f0
00000000: 00 00 00 00 a3 e1 b1 41
UrbLink = 00000000
RequestTypeReservedBits = 00000000
Request = 00000035
Value = 00002010
Index = 00000000

[1920711 ms] <<< URB 1618 coming back <<<
-- URB_FUNCTION_CONTROL_TRANSFER:
PipeHandle = 85e64748
TransferFlags = 0000000a (USBD_TRANSFER_DIRECTION_OUT, USBD_SHORT_TRANSFER_OK)
TransferBufferLength = 00000008
TransferBuffer = 00000000
TransferBufferMDL = 85c951f0
UrbLink = 00000000
SetupPacket =
00000000: 40 35 10 20 00 00 08 00

Z paketu je patrné, že nastavení frekvence je identifikováno pomocí vendor request 0x0035, value 0x2010, následované daty 00 00 00 00 a3 e1 b1 41, což je double reprezentace hodnoty 300 ve tvaru LSB first. Položka SetupPacket pak obsahuje celý zaslaný paket bez dat, odpovídající požadavek k nastavení frekvence, posílaný po USB, tedy bude: 40 35 10 20 00 00 08 00 00 00 00 00 a3 e1 b1 41. Tohle je jen jeden příklad z mnoha, pro SM300 dále musí následovat příkaz pro provedení nastavení (value 0x37ff).

Poslední částí realizace je pak komunikace pomocí samotného Vincula. Po připojení VNC1L k počítači, napájení a USB zařízení ve vhodném terminálu zkontrolujeme uvítací hlášku Vincula (Ver něco On-Line) a pomocí příkazů IPH a SCS nastavíme binární zkrácený režim příkazů (viz kap. 6.6 manuálu k firmware Vincula). Dále přes 2c 0d (QP2 / Query Port 2) ověříme připojení "neznámého zařízení" na portu 2 a provedeme listing připojených zařízení přes 85 20 nn 0d (QD / Query Device), kde nn je index od 0 do 15. Vinculum vrací stavovou strukturu, obsahující VID a PID daného zařízení, při nalezení správného zařízení jej vybereme ke komunikaci pomocí 86 20 nn 0d (SC / Set Device). Vyhledání dle VID/PID je důležité zejména u komplexních zařízení, jako je zmíněný generátor SM300, které na USB sběrnici obsahují hub a více zařízení rozlišených podle PID.

Nyní již je možné komunikovat se samotným zařízením pomocí příkazů SSU, pro příklad zmíněný výše (nastavení frekvence) bude tedy příkaz vypadat: 9a 20 40 35 10 20 00 00 08 00 0d 00 00 00 00 a3 e1 b1 41. Červeně je značený příkaz Vinculu (SSU + CR), modře setup paket, zeleně zasílaná data. Při úspěšném provedení odpoví Vinculum promptem ('>' + CR), podobným tvarem lze také používat setup pakety na čtení z USB zařízení, potom před promptem vrátí Vinculum data přečtená z USB zařízení.

Jak bylo už řečeno na začátku, nejedná se o žádný návod ani konkrétní postup, vše je to o "hraní si" se zkoumaným zařízením, o jeho hackování v původním významu tohoto slova. Takže pokud budete tvořit vlastní ovladače do jednočipu, který přes Vinculum bude spolupracovat s USB zařízením, přeji hodně úspěchů!

4 komentáře:

Anonymní řekl(a)...

Cau,
Potrebuji propojit a nasledne ovladat webkameru. Jako usb host jsem se rozhodl pouzit Vinculum a poridil jsem si modul VDIP1.Zapojil jsem VDIP1 pres UART na COM1 do PC a prace s flashkami, HID jde bez problemu...Kdyz pripojim webkameru Trust WB-1400T (USB 1.1) tak to take funguje-mohu posilat prikazy...Ale kdyz pripojim webkameru Logitech webcam c200 kterou chci pouzit (USB 2.0 Hi-speed), ktera by mela byt UVC tak zustane svitit pouze LED1 a z hyperterminalu nemohu poslat nic...zasekne se to vse....pokud kameru odpojim a zapojim flasku tak uz take nenabehne...pomuze jen restart...Nevite prosim co stim??Napadlo me jestli neni problem je ze to Hi-speed a vinculum podporuje jen Full speed. Ale kamera jede i pres USB hub 1.1 takze by to melo byt kompatibilni...tak nevim...pls help :)...Dekuji!

alpov řekl(a)...

Ahoj, tak s tímhle neporadím, vypadá to na nějaký problém ve firmwaru Vincula. Máš nainstalovaný nejnovější firmware z jejich webu? Pokud ano a stejně dochází k mrznutí, zkusil bych kontaktovat jejich podporu, viz http://www.vinculum.com/support.html. Už jsem s nimi komunikoval, jsou celkem ochotní.

Anonymní řekl(a)...

takze jsem psal na tech. support FTDI a bylo mi napsano ze vetsina webkamer pouziva pro prenos izochronni prenosy...coz jsem nejak tak v podvedomi mel...ale zaroven take ze Vinculum tyto prenosy nepodporuje...takze asi i kdyby to nezamrzlo pri pripojeni tak by to stejne neslo... :(( ... ja teda potrebuju jen obrazek prenest ne stream videa takze je otazka jak se prenasi jeden obrazek ...napr. kdyz se zmackne tlacitko na kamere pro porizeni "fotky" ... nevite nekdo jaky prenos?asi take izochronni bych tipnul :)...popr. nemate nekdo tip na nejaky USB host obvod ktery by to zvladal...(max3421e by asi pripadal v uvahu ale asi se uz nevyrabi...a nahradu neznam)...Diky za rady ;)

alpov řekl(a)...

Přímo co se USB přenosů na webce ti neporadím, s tím nemám zkušenosti. Ale tipy na další USB obvody bych měl. Podívej se na AT90USB647 (prodává TME) a knihovnu LUFA, konkrétně demo Demos/Host/ClassDriver/StillImageHost. Další variantou by byl nějaký větší ARM s Linuxem - pokud je to na hraní, můžeš se podívat na RouterLinux, ten má USB i Ethernet a šel by použít určitě.