Kompozytowe urządzenia USB na mikrokontrolerach z serii LPC134x

Wprowadzenie IAD spowodowało problem, polegający na tym, że starsze systemy nie rozumiały nowego deskryptora. Był on wprawdzie ignorowany, jednak urządzenia korzystające z niego mogły nie działać poprawnie z powodu błędnych powiązań interfejsów ze sterownikami. Problem ten został rozwiązany poprzez wprowadzenie do deskryptorów urządzenia urządzeń wykorzystujących IAD trzech nowych pól, które pozwalają zidentyfikować urządzenia korzystające z nowego rozwiązania w czasie procesu enumeracji i wymusić instalację specjalnego sterownika potrafiącego odczytać konfigurację urządzenia i zlokalizować potrzebne sterowniki.

W tabeli 2 przedstawiono fragment struktury deskryptora urządzenia, zawierający trzy nowe pola, charakterystyczne dla urządzeń wykorzystujących IAD oraz podaje ich wymagane wartości.

 

Tab. 2. Fragment struktury deskryptora urządzenia

Offset Nazwa pola Wartość Opis
4 bDeviceClass 0xEF Klasa Miscellaneous Device Class
5 bDeviceSubClass 0x02 Klasa Common Class
6 bDeviceProtocol 0x01 Interface Association Descriptor

 

Kolejność i organizacja deskryptorów dla urządzeń wykorzystujących IAD

Podstawowa specyfikacja USB nie podaje wymagań organizacyjnych dotyczących wzajemnego położenia deskryptorów zwracanych przez żądanie GetDescriptor(Configuration).
W dokumencie USB Interface Association Descriptor Device Class Code and Use Model została zaproponowana struktura ułatwiająca systemowi hosta parsowanie otrzymanych deskryptorów i odpowiednie przypisanie sterowników do funkcji urządzenia. Generalną zasadą jest grupowanie zestawów deskryptorów  według funkcji urządzenia. Oznacza to zasadniczo, że wszystkie deskryptory dotyczące jednej funkcji powinny być zlokalizowane „razem”, jak to jest przedstawione na rysunku 3. Rysunek ten pokazuje przykład tego, jak zestawy deskryptorów powinny być powiązane ze sterownikami.

 

 

 

Przykładowy schemat organizacji deskryptorów z użyciem deskryptora Interface Association Descriptor przedstawiono na rysunku 4.

 

Rys. 4. Przykładowy schemat organizacji deskryptorów z użyciem deskryptora <EM>Interface Association Descriptor</EM>

Rys. 4. Przykładowy schemat organizacji deskryptorów z użyciem deskryptora Interface Association Descriptor

 

 

Pierwszą widoczną na schemacie rzeczą jest to, że deskryptor urządzenia zawiera opisane w poprzednim rozdziale pola klasy, podklasy i protokołu, specyficzne dla urządzenia Multi-Interface Function Device Class wykorzystującego IAD. Następnie widać ustawienie deskryptora konfiguracji. Ten konkretny przykład zawiera trzy funkcje urządzenia. Wszelkie deskryptory między deskryptorem konfiguracji i pierwszym interfejsem lub IAD należy traktować jako „globalne” i dostarczyć je dla sterownika każdej funkcji urządzenia.

Pierwsze przypisanie funkcji dotyczy dwóch interfejsów (włączając wszystkie deskryptory specyficzne dla klasy i alternatywne ustawienia). Druga funkcja urządzenia ma jeden interfejs i nie potrzebuje IAD. Trzecia jest podobna do pierwszej. Dla każdej funkcji urządzenia, oprogramowanie systemowe musi dostarczyć sterownikowi urządzenia wszystkie deskryptory z ramki „Association” oraz wszystkie opisane wcześniej jako „globalne”.

Wartość pola bInterfaceCount określa liczbę interfejsów skojarzonych z daną funkcją. Na przykład, zakładając że mamy funkcję o interfejsach ponumerowanych od N do M, pole bFirstInterface otrzymuje wartość N, a bInterfaceCount – wartość (M-N)+1. Należy pamiętać, że każdy interfejs może mieć zero lub więcej alternatywnych ustawień, ale ustawienia te nie wliczają się do bInterfaceCount.
Dla funkcji urządzenia wykorzystujących IAD (jak pierwsza i trzecia w przykładzie), oprogramowanie systemowe USB powinno (przy użyciu pól idVendor i idProduct z deskryptora urządzenia i pola bFirstInterface z IAD) skonstruować „identyfikatory sprzętowe”, używane do zlokalizowania i załadowania sterownika urządzenia. Oprócz tego, oprogramowanie systemowe powinno zbudować „identyfikatory kompatybilności”, używając pól identyfikujących klasę (bFunctionClass, bFunctionSubClass, bFunctionProtocol) z deskryptora IAD.

Architektura przykładowego sterownika

Urządzenie kompozytowe, którego sterownik zostanie przedstawiony jako przykład w niniejszym tekście składa się z dwóch niezależnych interfejsów:

  • wirtualnego portu COM,
  • pamięci masowej (klasy Mass Storage Device).

Sterownik został stworzony z połączenia kodu dwóch przykładowych projektów dla środowiska LPCXpresso – usbcdc (port COM) oraz usbmsd (pamięć masowa). Jako że przykłady te są bardzo podobne do siebie, połączenie ich wymagało nieznacznych zmian, dotyczących przede wszystkim deskryptorów. Omówimy teraz wybrane fragmenty deskryptorów i sposób ich organizacji, które sprawiają, że urządzenie jest urządzeniem kompozytowym.

Typy i kolejność deskryptorów w przykładzie

Sterownik urządzenie generuje swój deskryptor z kodu klasy Miscellaneous Device Class, pojedynczego deskryptora konfiguracji, pojedynczego deskryptora Interface Association Descriptor (IAD) i trzech deskryptorów interfejsu. Kolejność tych deskryptorów w pamięci jest istotna i wygląda następująco:

  1. Deskryptor urządzenia
  2. Deskryptor konfiguracji
  3. Deskryptor interfejsu pamięci masowej (MSD)
  4. Interface Association Descriptor (dla CDC)
  5. Interface Descriptor (klasa komunikacji CDC)
  6. Interface Descriptor (klasa danych CDC)

Do pobrania

O autorze