Choď na obsah Choď na menu
 

USB Enumerácia

 

Enumerace
Enumerace je proces počátečního vyjednávání, kdy hostitel a host komunikují za účelem vzájemného poznávání a nastavování. Během enumerace posílá zařízení informace o svých hardwarových a softwarových prostředcích hostiteli, zatímco hostitel poskytuje zařízení adresu a mění vnitřní stavy zařízení.
Pokud budeme chápat komunikaci mezi hostitelem a zařízením jako obousměrnou rouru, po které proudí užitečná data, nutně dojdeme k potřebě odlišit data, která jsou předmětem enumerace a ostatní data, která jsou závislá na funkci zařízení, kvůli které bylo sestrojeno. USB specifikace řeší potřebu více komunikačních kanálů zavedením tzv. endpointů. Endpoint je funkční celek, který má k dispozici obousměrnou rouru, po níž komunikuje s hostitelem. Endpoint může být jak konzument, tak producent datového toku. Jedno zařízení může mít až 7 endpointů (rour). Nultý endpoint je určen pro vyřizování enumerace a má vlastnosti pevně dané specifikací. Vlastnosti ostatních endpointů jsou předány hostiteli během enumerace ve speciálních datových strukturách.
Pokud by se komunikace po rouře skládala pouze z užitečných dat (například výsledků měření), neměl by hostitel k dispozici žádný nástroj, kterým by měnil vnitřní stavy zařízení a nemohl by ovlivňovat jeho chování. Aby mohl hostitel posílat kromě dat také příkazy, zavádí USB specifikace zvláštní druh paketů (setup packet), které říkají, že data předaná v následné transakci nejsou určena pro funkčnost zařízení, ale pro řízení stavů zařízení.
Endpoint 0 musí reagovat na setup pakety a odesílat informace, které jsou po zařízení požadovány. Abychom mohli navrhnout program, který bude požadavky vyřizovat, musíme si uvědomit, z jakých atomických operací se komunikace po USB skládá.

Transakce

Jak již bylo uvedeno v rozboru USB, přenosovou jednotkou na sběrnici je paket. Paket může obsahovat sdělení různé povahy:
  1. lichá část dat, sudá část dat (DATA0, DATA1)
  2. handshaková odpověď (ACK, NAK)
  3. oznámení, že následující data jsou příkazem (SETUP packet)
  4. výzva k odebrání dat (OUT packet)
  5. výzva k odeslání dat (IN packet)
Problém, který obecně nastává u datových přenosů, je konečná délka paketu. MTU (maximum transfer unit) udává počet bytů, které smějí být přeneseny v rámci jednoho paketu. MTU reflektuje hardwarová omezení, například nepřesnost synchronicity příjemce a odesílatele, velikosti vstupně/výstupních bufferů, účinnost CRC a podobně. Endpoint 0 má maximální délku dat stanovenu na 8 bytů. Jev, který nastává v důsledku omezení velikosti paketů, se nazývá fragmentace (dělení na části). Proces přenosu dat se zesložiťuje a přenos paketů musí být opatřen rozšířením nazvaným transakce.
Transakce je předpis, který stanoví posloupnost různých druhů paketů za účelem přenesení zprávy libovolné délky. Transakce budeme dělit na tři druhy:
  1. vstupní transakce - přenáší data ze zařízení k hostiteli
  2. výstupní transakce - přenáší data od hostitele do zařízení
  3. řídící transakce - posílá řídící data od hostitele do zařízení

Výstupní transakce

Hostitel nejprve uvědomí zařízení, do kterého chce zapisovat, vysláním OUT packetu. Data, která chce hostitel odeslat, si rozdělí na bloky pevné délky (poslední blok může být kratší). Hostitel bez čekání odešle první blok dat v paketu typu DATA0. Zařízení odpovídá handshakovým paketem (ACK nebo NAK). V případě, že zařízení pošle ACK, hostitel vysílá OUT packet následovaný bez prodlení paketem DATA1 s dalším blokem dat a znovu čeká na handshakovou odpověď zařízení. Střídavě se tak přenášejí OUT+DATA0 a OUT+DATA1, dokud nejsou přeneseny všechny části zprávy. Pokud zařízení odpoví na nějaký paket negativně (NAK), zopakuje hostitel své předchozí vysílání (v paketu stejného typu). Když hostitel odešle vše, co potřeboval, nastává posloupnost paketů ukončující celou transakci. Hostitel vyšle IN packet a očekává, že zařízení pošle paket DATA0 s nulovou délkou obsahu (prázdný paket). Hostitel takový paket potvrdí vysláním ACK paketu. Tím se ukončuje transakce a zpráva, která byla předmětem transakce, je považována za platnou. Pokud není dodržena posloupnost paketů jednou ze stran, transakce se ruší a dosud přenesená data se musí zahodit.

Vstupní transakce

Hostitel vyšle do endpointu, ze kterého chce číst zprávu, IN paket. Zařízení odpovídá první částí zprávy v paketu DATA0. Hostitel handshakuje (ACK nebo NAK). Hostitel opakuje IN packet a předpokládá, že zařízení mu nyní odpoví v paketu DATA1 (střídavě). Hostitel přijatá data opět potvrzuje a podle potřeby opakuje vysílání paketu tolikrát, dokud neobdrží buď prázdný paket nebo paket s menším počtem bytů, než je maximum. Tím se hostitel dozví, že zařízení již poslalo celou zprávu a nastane okamžik pro potvrzení platnosti celé transakce. Hostitel vysílá OUT packet a bez čekání pošle i DATA0 packet bez obsahu (prázdný DATA0 packet). Zařízení musí odpovědět ACK packetem.
U obou transakcí se vyskytuje potvrzení transakce, které je realizováno posláním prázdného datového paketu v opačném směru, než ve kterém probíhal přenos zprávy.

Řídící transakce

Řídící transakce začíná okamžikem, kdy hostitel pošle SETUP packet do endpointu. Poté pošle DATA0 packet o délce 8 bytů (rozumí se 8 bytů obsahu). Hostitel očekává ACK od zařízení. Obsah paketu DATA0 má přesně specifikovanou strukturu a zařízení se z ní dozví, zda bude následovat vstupní či výstupní transakce. Zařízení si buď připraví data k odeslání nebo uvolní vstupní buffer pro přijímání a pak provede standardní transakci podle toho, jak bylo uvedeno výše. Řídící transakce je tedy stejná jako vstupní či výstupní transakce s tím rozdílem, že užitečná data, která by byla normálně přenášena, jsou nahrazena daty, o které hostitel požádal v posloupnosti SETUP+DATA0 paketech.
Transakce je nejkomplexnějším útvarem při USB komunikaci. Transakce přenáší zprávy, které jsou připraveny ve vstupně/výstupních bufferech zařízení i hostitele a jejich obsah může být libovolný. Pouze při příchodu SETUP+DATA0 paketu do zařízení jsou tyto buffery nahrazeny odpovědí s přesně specifikovaným významem a strukturou. SETUP paket lze tedy chápat jako přepnutí vnitřního stavu zařízení.

Stavy zařízení

Program, který bude rozebírat přišlé pakety, rozhodovat se o jejich sdělení a odesílat zpět odpověď, bude pracovat podle schématu přijmi-vyhodnoť-odpověz. Rutiny tohoto analyzátoru (parseru) se zavolají jednou po příchodu paketu, provedou se a uvolní procesorový čas. Rutiny nebudou obsahovat žádné čekání. Vzhledem k omezeným možnostem procesorů AVR nebude nikde uložena celá zpráva, která je předmětem transakce. Každý blok (max. 8 bytů) bude do bufferu vložen těsně před odesláním a přijatá data budou ihned po přijetí zpracována. Parser bude tedy pracovat obdobně jako stavový automat, jehož vstupem je příchozí paket a výstupem odchozí paket a změna vnitřního stavu.
Požadavky, které musí zařízení plnit:
  1. užitečná data (rqData)
  2. device descriptor (rqDevDesc)
  3. configuration descriptor (rqConfDesc)
  4. set address (rqSetAddr)
Fáze transakce (x-action), kterými zařízení prochází:
  1. klid, výchozí stav (xaNone)
  2. požadavek na zápis (OUT paket) (xaOut)
  3. požadavek na čtení (IN paket) (xaIn)
  4. požadavek na nastavení (SETUP paket) (xaSetup)
  5. ukončení zápisové transakce (IN paket přicházející při zápisové transakci) (xaWriteEnd)
  6. ukončení čtecí transakce (OUT paket přicházející při čtecí transakci) (xaReadEnd)
  7. odmítnutí ukončení čtecí transakce (OUT paket přicházející při čtecí transakci, aniž by byla potvrzena poslední data) (xaReadEndFail)
  8. čekání na potvrzení datového paketu při čtecí transakci (xaInAckWait)
Stavy musejí být rozšířeny o počítadlo odeslaných bytů a o další pomocné proměnné (spánek, stav bez adresy, úsporný režim).
Stav Příchozí paket Nový stav Odchozí paket
cokoliv SETUP xaSetup -
xaNone (klid) OUT xaOut -
IN xaInWaitAck DATA1
ACK, NAK xaNone -
DATAn xaNone NAK
xaIn OUT xaReadEnd -
IN xaInWaitAck DATA0 nebo DATA1
ACK, NAK xaNone (transakce zrušena) -
DATAn xaIn NAK
xaInWaitAck OUT xaReadEndFail -
IN xaInWaitAck DATA0 nebo DATA1 (opakované odeslání)
ACK xaIn (+připravit další paket) -
NAK xaIn -
DATAn xaNone (transakce zrušena) NAK
xaReadEndFail OUT xaOut (transakce zrušena) -
IN xaInWaitAck (transakce zrušena) DATA1
ACK, NAK xaNone (transakce zrušena) -
DATAn xaNone (transakce zrušena) NAK
xaOut OUT xaOut -
IN xaWriteEnd zero DATA
ACK, NAK xaNone (transakce zrušena) -
DATAn xaOut (paket přijat v pořádku) ACK
xaWriteEnd OUT xaOut (transakce zrušena) -
IN xaWriteEnd zero DATA
ACK xaNone (data odeslána v pořádku) -
NAK xaNone (transakce zrušena) -
DATAn xaNone (transakce zrušena) NAK
xaReadEnd OUT xaOut (transakce zrušena) -
IN xaInWaitAck (transakce zrušena) DATA1
ACK,NAK xaNone (transakce zrušena) -
DATAn xaNone (transakce potvrzena) ACK
xaSetup OUT xaOut (setup zrušen) -
IN xaInWaitAck (setup zrušen) DATA1
ACK, NAK xaNone (setup zrušen) -
DATAn xaOut nebo xaIn (dle obsahu dat) ACK

Požadavky

Zařízení musí na požádání zasílat dvě datové struktury (dvě zprávy). První je popisovač zařízení (Device Descriptor) a druhý je popisovač nastavení (Configuration Descriptor). Obě datové struktury mají více než 8 bytů a proto se rozpadají na více paketů. Dalším požadavkem, který je posílán hositelem je nastavení adresy, ale odpověď je zařízením signalizována tak, že úspěšně ukončí transakci (prázdný paket, zero DATA) a takovou odpověď zařídí stavový automat sám od sebe.

Device Descriptor

 
Offset Popis Hodnota
0 bLength 0x12
1 bDescriptorType 0x01
2,3 bcdUSB 0x0100
4 bDeviceClass 0x00
5 bDeviceSubClass 0x00
6 bDeviceProtocol 0x00
7 bMaxPacketSize 0x08
8,9 idVendor 0x065d
10,11 idProduct 0x1031
12,13 bcdDevice 0x0004
14 iManufacturer 0x00
15 iProduct 0x00
16 iSerialNumber 0x00
17 bNumConfigurations 0x01


Configuration Descriptor (spojení Configuration, Interface a Endpoint descriptoru)
 
Offset Popis Hodnota
Configuration Descriptor
0 bLength 0x09
1 bDescriptorType 0x02
2,3 wTotalLenght 0x0020
4 bNumInterfaces 0x01
5 bConfigurationValue 0x01
6 iConfiguration 0x00
7 bmAttributes 0x80
8 bMaxPower 0x32
Interface Descriptor
9 bLength 0x09
10 bDescriptorType 0x04
11 bInterfaceNumber 0x00
12 bAlternateSetting 0x00
13 bNumEndpoints 0x02
14 bInterfaceClass 0x00
15 bInterfaceSubClass 0x00
16 bInterfaceProtocol 0x00
17 iInterface 0x00
Endpoint 1 Descriptor
18 bLength 0x07
19 bDescriptionType 0x05
20 bEndpointAddress 0x01
21 bmAttributes 0x00
22,23 wMaxPacketSize 0x0001
24 bInterval 0x00
Endpoint 2 Descriptor
25 bLength 0x07
26 bDescriptionType 0x05
27 bEndpointAddress 0x82
28 bmAttributes 0x00
29,30 wMaxPacketSize 0x0001
31 bInterval 0x00


Deskriptory budou odeslány v následujících paketech:

Device Descriptor:
DATA1 packet - CRC 0xe713 - Device Descriptor
80 4b 12 01 00 01 00 00 00 08 13 e7 eop
DATA0 packet - CRC 0x83d9 - Device Descriptor
80 c3 5d 06 31 10 04 00 00 00 d9 83 eop
DATA1 packet - CRC 0x8f3f - Device Descriptor
80 4b 00 01 3f 8f eop



Configuration Descriptors:
DATA1 packet - CRC 0xa20a - Configuration Descriptor
80 4b 09 02 20 00 01 01 00 80 0a a2 eop
DATA0 packet - CRC 0x7d04 - Configuration Descriptor a Interface Descriptor
80 c3 32 09 04 00 00 02 00 00 04 7d eop
DATA1 packet - CRC 0x2f72 - Interface Descriptor a Endpoint 1 Descriptor
80 4b 00 00 07 05 01 00 01 00 72 2f eop
DATA0 packet - CRC 0xbfe0 - Endpoint 1 Descriptor a Endpoint 2 Descriptor
80 c3 00 07 05 82 00 01 00 00 e0 bf eop
DATA1 packet - CRC 0x0000 - konec
80 4b 00 00 eop