24.01.10 최초 작성
| USB Host | USB Device |
|---|---|
| master에 해당 | slave에 해당 |
wiring| VCC | GND | Data + | Data - |
|---|---|---|---|
| 전원 | 접지 | Data + 끼리 연결 | Data - 끼리 연결 |
version| Known Name | Data Rate | Power Capabilities | |
|---|---|---|---|
| usb v1.1 | X | 12Mbps | 150mA |
| usb v2.0 | High-Speed USB | 480Mbps | 500mA |
| usb v3.0 | SuperSpeed USB | 5Gbps | 1.5A |
| usb v3.1 | SuperSpeed+ USB | 10Gbps | 20A |
| HID | CDC | MSC | Custom Device Class |
|---|
각 장치 종류 마다 Host-Device간 사용하는 프로토콜을 달리함
USB 장치에 여러개의 Interface가 존재하고 Interface 내에 하나 혹은 여러개의 Endpoint가 존재
Endpoint0는 양방향 통신이 가능하며 Endpoint는 Input/Output중 하나의 역할을 담당함
여러 Endpoint를 모아 특정 장치와 통신하는 통로로 사용함
USB class 종류
| HID | CDC | MSC | Custom Device Class |
|---|
Control : enumeration에 사용
Interrupt : 작은 크기의 데이터 통신 (마우스 ...)
Bulk : 큰 크기의 데이터 통신에 사용하며 ACK체크 사용 (Network, Mass storage...)
Isochronous : 큰 데이터 데이터 통신에 사용하며 ACK체크 하지 않음 (Audio, Video ...)
장치가 호스트에 연결되면 호스트가 장치를 감지하고 장치의 통신 속도를 알아냄
이후 device descriptor에서부터 장치 정보를 받아옴
장치를 초기화하고 주소를 할당, configuration descriptor를 통해 장치 설정 정보 가져옴
interface descriptor가져와 USB class 정보를 가져옴
드라이버를 로드하면 장치 사용 준비 완료
descriptor
USB Device : USB Gadget (USB class의 모음) + UDC (USB Device Controller의 드라이버)linux-menuconfig에서 
sudo apt install wireshark
sudo modprobe usbmon //usb 통신 확인 가능하도록 설정
sudo wireshark
k_usb.c : usb에 장치가 감지되면 device descriptor, endpoint descriptor를 화면에 출력k_usb_table : 장치의 정보를 등록하고 연결된 장치가 이것과 일치하면 .probe에 등록한 함수 호출#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
#define USB_VENDOR_ID 0xc0f4
#define USB_PRODUCT_ID 0x01e0
const struct usb_device_id k_usb_table[] = {
{USB_DEVICE(USB_VENDOR_ID, USB_PRODUCT_ID)},
{},
};
MODULE_DEVICE_TABLE(usb, k_usb_table);
static struct usb_driver k_usb_driver = {
.name = "K USB Driver",
.probe = k_usb_probe,
.disconnect = k_usb_disconnect,
.id_table = k_usb_table,
};
k_usb_probe() : 장치에 할당된 endpoint의 갯수를 세고 descriptor 출력하는 함수 호출static int k_usb_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
unsigned int i;
unsigned int ep_count;
struct usb_host_interface *iface_desc = interface->cur_altsetting;
dev_info(&interface->dev, "Vendor ID : 0x%02x, Product ID : 0x%02x\n", id->idVendor, id->idProduct);
ep_count = iface_desc->desc.bNumEndpoints;
print_interface_descriptor(iface_desc->desc);
for (i = 0; i < ep_count; i++) {
print_usb_endpoint_descriptor(iface_desc->endpoint[i].desc);
}
return 0;
}
print_interface_descriptor(), print_usb_endpoint_descriptor() : 장치의 각 descriptor 출력void print_interface_descriptor(struct usb_interface_descriptor i)
{
pr_info("USB_INTERFACE_DESCRIPTOR:\n");
pr_info("bLength: 0x%x\n", i.bLength);
pr_info("bDescriptorType: 0x%x\n", i.bDescriptorType);
pr_info("bInterfaceNumber: 0x%x\n", i.bInterfaceNumber);
pr_info("bAlternateSetting: 0x%x\n", i.bAlternateSetting);
pr_info("bNumEndpoints: 0x%x\n", i.bNumEndpoints);
pr_info("bInterfaceClass: 0x%x\n", i.bInterfaceClass);
pr_info("bInterfaceSubClass: 0x%x\n", i.bInterfaceSubClass);
pr_info("bInterfaceProtocol: 0x%x\n", i.bInterfaceProtocol);
pr_info("iInterface: 0x%x\n", i.iInterface);
pr_info("\n");
}
void print_usb_endpoint_descriptor(struct usb_endpoint_descriptor e)
{
pr_info("USB_ENDPOINT_DESCRIPTOR:\n");
pr_info("bLength: 0x%x\n", e.bLength);
pr_info("bDescriptorType: 0x%x\n", e.bDescriptorType);
pr_info("bEndPointAddress: 0x%x\n", e.bEndpointAddress);
pr_info("bmAttributes: 0x%x\n", e.bmAttributes);
pr_info("wMaxPacketSize: 0x%x\n", e.wMaxPacketSize);
pr_info("bInterval: 0x%x\n", e.bInterval);
pr_info("\n");
}