검색결과 리스트
USB Client 만들기에 해당되는 글 2건
글
앞서 USB Client Device 에 대해서 다소 추상적인 개념들을 살펴 보았습니다. 이제는 본격적으로 어떤것들이 어떻게 오가는지에 대해서 알아보겠습니다.
USB Device Descriptor
USB Clinet 가 USB Host 에 연결되면, USB Host(PC)는 해당 Client 에게 Descriptor 를 요청합니다. 통신을 하려면 이게 어떤 놈이지 알아야 되지 않겠습니까? 이 정보가 들어있는 Descriptor 가 필요하지요. Descriptor 의 구조는 아래 그림과 같습니다.
출처:http://howusbworks.blogspot.kr/
제가 처음 이 그림을 보았을 때, 무슨 의미인지 잘 몰랐습니다. Device 의 Architecture 에 대한 것인지 추상적인 개념인건지 감이 잘 안 오더라고요. 이건 말 그대로 descriptor 의 구조입니다. ^-^;
개발을 하면서 각종 미디어나 프로토콜의 header 를 많이 보셨을거라고 생각합니다. 맨 처음에는 ID3 ASCII 값으로 시작하고, 뒤에 4 바이트는 데이터 길이고...... 이런 식으로 되어 있지요. 대게 이런 헤더들은 serial 하게 나옵니다. 그런데 지금 살펴볼 Device Descriptor 는 병렬구조입니다. A 다음에 B 가 나오고, 이 뒤에 C 가 나오는것이 아니라, A 다음에 B 가 n 개가 나오고, 각 B 에 대해서 C 가 n 개가 존재하는 형태인 것이죠. 그래서 그림을 그리면 보시는것처럼 다소 복잡하게 표현됩니다. 트리 형태로 말이죠. :)
하나씩 살펴보기에 앞서, 모든 descriptor 들은 아래와 같은 구조로 되어 있습니다.
Offset |
Field |
Size |
Value |
Description |
0 |
bLength |
1 |
Number |
해당 Descriptor 의 바이트 길이 |
1 |
bDescription Type |
1 |
Constant |
Descriptor 타입 |
2 |
... |
n |
|
... |
Device Descriptor
가장 먼저 나오는 Descriptor 로서 전반적인 Device 의 설명이 포함됩니다.
Offset | Field | Size | Value | Description |
0 | bLength | 1 | Number | 해당 Descriptor 의 바이트 길이 (18 bytes) |
1 | bDescription Type | 1 | Constant | Device Descriptor (0x01) |
2 | bcdUSB | 2 | BCD | 해당 USB 가 지원하는 최대버전을 표시 USB 1.0 은 0x0100, USB 1.1 은 0x0110, USB 2.0 은 0x0200 처럼 표시함 |
4 | bDeviceClass | 1 | Class | Host(PC)가 해당 USB 를 위한 class driver 를 찾을때 사용함. Device Class 라는것은 USB Org 에 정의되어 있음. 만약 이어서 나오는 Interface Descriptor 에서 class 를 정의하려면 0x00 을 사용합니다. 만약 vendor 가 직접 명시한 class code 를 쓰려면, 0xff 를 사용합니다. |
5 | bDeviceSubClass | 1 | SubClass | USB Org 에서 지정된 subclass code |
6 | bDeviceProtocol | 1 | Protocol | USB Org 에서 지정한 protocol code |
7 | bMaxPacketSize | 1 | Number | Zero Endpoint 의 최대 패킷 사이즈 8, 16, 32, 64 중 택 1 |
8 | idVendor | 2 | ID | USB Org 에서 지정한 제공자(vendor) ID |
10 | idProduct | 2 | ID | 제조사에서 지정한 Product ID |
12 | bcdDevice | 2 | BCD | Device 의 릴리즈 번호 |
14 | iManufacturer | 1 | Index | 제조사의 문자열 descriptor 의 index |
15 | iProduct | 1 | Index | 제품의 문자열 descriptor 의 index |
16 | iSerialNumber | 1 | Index | 시리얼 번호의 문자열 descriptor 의 index |
17 | bNumConfigurations | 1 | Integer | 이어서 나오는 Configuration Descriptor 의 갯수 |
Field 에 보면 직감하시겠지만, b 로 시작하는것은 Binary 를 의미합니다. 그리고 bcd 는 BCD 를, i 는 index 를 의미하지요. 이 index 에 대해서는 밑에서 설명 드리겠습니다. class 니 SubClass 니 하는 것들이 나옵니다. 이것은 무엇일까요?
Class 는 말 그대로 클래스입니다. -_-; 비슷한 성격끼리 묶어놓은 거라고 생각하시면 쉬울것 같네요. http://www.usb.org 에 보면 정의된 class 목록을 볼 수 있습니다. (http://www.usb.org/developers/defined_class)
앞서 Descriptor 의 구조를 보셔서 아시겠지만, 모두가 특정 포맷에 맞추어져 있습니다. 각 offset 에 있는 데이터가 의미하는 정보가 있지요. 만약 제조사의 이름이나 디바이스의 제품명은 어떻게 넣어야 할까요? 제조사가 "crystalcube" 라면 어디에 어떻게 넣어야 할까요? 일반적으로 어떤 포멧들은 [string byte length] + [ASCII] 형태로 넣곤 합니다. 그런데 이런 형태의 경우 다음 데이터(정보)의 offset 이 고정되지 않습니다. 예를들어 위 Device Descriptor 에서 offset 14 인 'iManufacturer' 를 보죠. 제조사 이름이 "crystalcube" 인 경우 11 byte 이므로, 0x0B, 'c', 'r', 'y', 's', 't', 'a', 'l', 'c', 'u', 'b', 'e' 가 들어갈 것입니다. 총 12 byte 가 되겠네요. 그 다음 나오는 iProduct 는 offsset 이 15 가 아니라, 14 + 12 인 26 이 됩니다. 제조사 이름이 "ms" 라면, iProduct 의 offset 은 14 + 3 인 17 이 되고요. 다시말해 iManufacturer 의 값에 따라 다음 정보의 offset 이 변동됩니다. 이런 단점을 막기 위해서 USB 에서는 index 라는 개념을 사용합니다.
전체 Descriptor 를 보면 'Device Descriptor' -> ('Configuration Descriptor' -> ('Interface Descriptor' -> 'Endpoint Descriptor'*)*)* -> 'String Descriptor'* 형태로 되어 있습니다. 직렬로 Serialize 했을 때 그렇다는 이야깁니다. * 표시가 붙은 것은 1개 이상 나올 수 있다는 이야기 입니다. index 라는 것이 바로, 마지막에 나오는 'String Descriptor' 의 index 입니다. 이 string descriptor 는 아래와 같은 구조로 되어 있고, 여러개가 나올 수 있습니다.
Offset | Field | Size | Value | Description |
0 | bLength | 1 | Number | 데이터의 길이 |
1 | bType | 1 | Constant | 타입 (string 은 0x03) |
2 | String | n | Unicode | 유니코드로서 한 문자당 2 바이트 |
이런 구조의 String Descriptor 가 Array 형태로 여러개 존재합니다. index 라는 것은 각 Descriptor 가 string descriptor array 에서 몇 번째냐는 말이죠. index 는 당연히 0 부터 시작합니다.
.NETMF Code
이제 해당 descriptor 의 코드를 살펴보겠습니다. 먼저 코드는 아래와 같습니다.
Configuration.DeviceDescriptor deviceDescriptor = new Configuration.DeviceDescriptor(0x04D8, 0x0009, 0x0100);
deviceDescriptor.bcdUSB = 0x0200;
deviceDescriptor.bDeviceClass = 0x00;
deviceDescriptor.bDeviceSubClass = 0x00;
deviceDescriptor.bDeviceProtocol = 0x00;
deviceDescriptor.bMaxPacketSize0 = 0x40;
deviceDescriptor.iManufacturer = 1;
deviceDescriptor.iProduct = 2;
deviceDescriptor.iSerialNumber = 3;
위 페이지에 해당 클래스에 대해서 자세히 나와 있습니다.
작성한 Descriptor 를 살펴보면, 생성자에 들어간 0x04D8 은 Vendor ID, 0x0009 는 Product ID, 0x0100 은 USB 버전을 의미합니다. vendor ID 0x04D8 은 'Microchip Technology, Inc.' 입니다. 즉, 그냥 굴러다니는거 주워다가 썼습니다. 만약 자신의 vendor ID 를 가지고 싶으시다면, usb.org 에서 신청하시면 됩니다. 물론 유료입니다. -_-; Product ID 도 역시 그냥 아무거나 넣었습니다. 마지막 0x0100 은 이 디바이스의 version 입니다. 그냥 1.0 이라고 넣어보았습니다.
이후 나오는 프로퍼티들은 표에서 설명한 그대로입니다. iManufacturer, iPoduct, iSerialNumber 는 각각 1, 2, 3 으로 값을 넣었는데, 나중에 String Descriptor 를 해당 index 에 맞게 넣을 예정입니다. :)
나머지 Descriptor 는 다음 포스팅에서 다루도록 하겠습니다.
'USB Client 만들기' 카테고리의 다른 글
.NET Micro Framework 에서 USB Client 만들기 1부 (0) | 2015.05.07 |
---|
RECENT COMMENT