USB 서브시스템 심화

USB 프로토콜 기초부터 Linux 커널의 USB Core, URB, Host Controller Driver, Gadget Framework, 클래스 드라이버, Type-C/PD, 유저스페이스 접근, 전원 관리, 디버깅까지 종합 가이드.

관련 표준: USB 2.0 Specification, USB 3.2 Specification, USB4 Specification, USB Type-C Specification, USB Power Delivery Specification — Linux USB 서브시스템이 구현하는 버스 프로토콜 규격입니다.

USB 개요

USB (Universal Serial Bus)는 1996년 Intel, Compaq, Microsoft 등이 공동으로 제안한 범용 직렬 버스 규격입니다. 키보드, 마우스부터 외장 스토리지, 네트워크 어댑터, 비디오 캡처 장치까지 거의 모든 주변기기의 사실상 표준 인터페이스로 자리 잡았습니다. Linux 커널은 USB 서브시스템을 통해 호스트 컨트롤러 관리, 디바이스 열거, 드라이버 바인딩, 전원 관리를 통합적으로 처리합니다.

USB 버전 발전

규격연도최대 속도인코딩커넥터
USB 1.019961.5 Mbps (Low Speed)NRZIType-A/B
USB 1.1199812 Mbps (Full Speed)NRZIType-A/B
USB 2.02000480 Mbps (High Speed)NRZIType-A/B, Mini, Micro
USB 3.020085 Gbps (SuperSpeed)8b/10bType-A (청색), Type-B SS, Micro-B SS
USB 3.1201310 Gbps (SuperSpeed+)128b/132bType-C
USB 3.2201720 Gbps (2x2 레인)128b/132bType-C 전용
USB4201940 Gbps (Gen 3x2)PAM3 (64b/66b)Type-C 전용
USB4 v2.0202280 Gbps (Gen 4)PAM3Type-C 전용
USB4와 Thunderbolt: USB4는 Thunderbolt 3 프로토콜을 기반으로 하며, PCIe 터널링과 DisplayPort Alt Mode를 지원합니다. Linux 커널의 Thunderbolt 드라이버(drivers/thunderbolt/)가 USB4 호스트 컨트롤러도 함께 관리합니다.

프로토콜 계층 구조

USB 통신은 다음과 같은 계층으로 구성됩니다:

계층역할주요 요소
Client Software클래스/벤더 드라이버, 유저스페이스 앱usb_driver, libusb
USB System SoftwareUSB Core, 디바이스 열거, 대역폭 관리usb_device, usb_bus
USB Host Controller하드웨어 트랜잭션 스케줄링, 데이터 전송xHCI, EHCI, OHCI, UHCI
USB Bus Interface전기/물리 시그널링, 패킷 인코딩차동 시그널링, NRZI/8b10b

USB 프로토콜 기초

디스크립터 계층

USB 디바이스는 자신의 기능을 디스크립터(Descriptor) 계층 구조로 기술합니다. 호스트는 열거(Enumeration) 과정에서 이 디스크립터를 읽어 적절한 드라이버를 바인딩합니다:

Device Descriptor (1개)
 ├── Configuration Descriptor (1개 이상)
 │    ├── Interface Descriptor (1개 이상)
 │    │    ├── Endpoint Descriptor (0개 이상)
 │    │    └── Class-Specific Descriptor (선택)
 │    └── Interface Association Descriptor (복합 디바이스)
 └── String Descriptor (선택)
디스크립터bDescriptorType핵심 필드설명
Device0x01idVendor, idProduct, bDeviceClass디바이스 전체 정보, VID/PID로 드라이버 매칭
Configuration0x02bNumInterfaces, bMaxPower전원 특성, 인터페이스 구성
Interface0x04bInterfaceClass/SubClass/Protocol기능 단위, 클래스 드라이버 매칭 기준
Endpoint0x05bEndpointAddress, bmAttributes, wMaxPacketSize데이터 파이프 정의, 전송 타입/방향/크기
/* 커널 내부: USB Device Descriptor 구조체 */
/* include/uapi/linux/usb/ch9.h */
struct usb_device_descriptor {
    __u8  bLength;             /* 18 */
    __u8  bDescriptorType;     /* USB_DT_DEVICE (0x01) */
    __le16 bcdUSB;             /* USB 규격 버전 (BCD: 0x0200 = USB 2.0) */
    __u8  bDeviceClass;        /* 디바이스 클래스 (0x00이면 인터페이스 레벨) */
    __u8  bDeviceSubClass;
    __u8  bDeviceProtocol;
    __u8  bMaxPacketSize0;     /* EP0 최대 패킷 크기 (8/16/32/64) */
    __le16 idVendor;           /* Vendor ID */
    __le16 idProduct;          /* Product ID */
    __le16 bcdDevice;          /* 디바이스 릴리즈 번호 */
    __u8  iManufacturer;       /* 제조사 문자열 인덱스 */
    __u8  iProduct;            /* 제품명 문자열 인덱스 */
    __u8  iSerialNumber;       /* 시리얼 번호 문자열 인덱스 */
    __u8  bNumConfigurations;  /* Configuration 수 */
} __attribute__ ((packed));

전송 타입

USB는 4가지 전송 타입을 정의하며, 각각 다른 특성과 용도를 가집니다:

전송 타입특성대역폭 보장오류 재전송용도
Control양방향, 셋업+데이터+상태 단계예약됨 (10~20%)디바이스 설정, 디스크립터 읽기, 벤더 요청
Bulk대용량, 잔여 대역폭 사용없음 (잔여 사용)Mass Storage, 프린터, 네트워크 데이터
Interrupt소량, 폴링 주기 보장예약됨키보드, 마우스, 조이스틱, HID
Isochronous실시간, 일정 대역폭예약됨없음오디오, 비디오, 웹캠
Endpoint 방향: Endpoint 주소의 비트 7이 방향을 나타냅니다. 0x81은 IN (디바이스 → 호스트) Endpoint 1, 0x02는 OUT (호스트 → 디바이스) Endpoint 2입니다. Endpoint 0(EP0)은 항상 양방향 Control 전송에 사용됩니다.

열거 (Enumeration) 과정

USB 디바이스가 연결되면 호스트는 다음 순서로 디바이스를 인식합니다:

  1. 연결 감지 — Hub가 포트 상태 변경을 인터럽트로 호스트에 통보
  2. 포트 리셋 — 호스트가 해당 포트에 USB Reset 시그널 전송 (SE0, 10~50ms)
  3. 속도 감지 — D+/D- 풀업 저항 위치로 Low/Full/High Speed 결정
  4. 기본 주소 할당 — 디바이스는 주소 0으로 응답, 호스트가 SET_ADDRESS(1~127) 전송
  5. 디스크립터 읽기 — GET_DESCRIPTOR로 Device, Configuration, Interface, Endpoint 정보 수집
  6. Configuration 선택 — SET_CONFIGURATION으로 활성 Configuration 설정
  7. 드라이버 바인딩 — 커널이 VID/PID 또는 클래스 코드 기반으로 적합한 드라이버를 probe

Linux USB Core

Linux USB Core(drivers/usb/core/)는 호스트 컨트롤러와 디바이스 드라이버 사이의 중간 계층으로, 디바이스 열거, URB 관리, 전원 관리, 드라이버 매칭을 담당합니다.

핵심 자료구조

구조체헤더역할
struct usb_bus<linux/usb.h>USB 버스 인스턴스, HCD와 1:1 대응
struct usb_device<linux/usb.h>USB 디바이스 인스턴스 (디스크립터, 상태, 파이프 정보)
struct usb_interface<linux/usb.h>인터페이스 단위 — 드라이버가 바인딩하는 대상
struct usb_host_config<linux/usb.h>Configuration Descriptor 파싱 결과
struct usb_host_interface<linux/usb.h>Interface Descriptor + Endpoint 배열
struct usb_host_endpoint<linux/usb.h>Endpoint Descriptor + URB 큐
/* struct usb_device 주요 필드 (simplified) */
/* include/linux/usb.h */
struct usb_device {
    int                     devnum;          /* 버스 내 디바이스 주소 (1~127) */
    char                    devpath[16];     /* sysfs 경로 문자열 */
    enum usb_device_state   state;           /* 연결 상태 */
    enum usb_device_speed   speed;           /* Low/Full/High/Super/Super+ */

    struct usb_device_descriptor descriptor;  /* Device Descriptor 사본 */
    struct usb_host_config  *config;         /* 모든 Configuration 배열 */
    struct usb_host_config  *actconfig;      /* 현재 활성 Configuration */

    struct usb_host_endpoint ep0;            /* Endpoint 0 (Control) */
    struct usb_host_endpoint *ep_in[16];     /* IN Endpoint 배열 */
    struct usb_host_endpoint *ep_out[16];    /* OUT Endpoint 배열 */

    struct usb_device       *parent;         /* 부모 Hub (Root Hub는 NULL) */
    struct usb_bus          *bus;            /* 소속 버스 */
    struct device           dev;             /* 범용 디바이스 모델 */

    int                     maxchild;        /* Hub인 경우 하위 포트 수 */
    unsigned                can_submit:1;    /* URB 제출 가능 여부 */
    /* ... */
};
/* struct usb_interface — 드라이버가 bind하는 단위 */
struct usb_interface {
    struct usb_host_interface *altsetting;    /* Alternate Setting 배열 */
    struct usb_host_interface *cur_altsetting; /* 현재 활성 설정 */
    unsigned                num_altsetting;  /* Alternate Setting 개수 */

    struct usb_interface_cache *intf_cache;
    struct device           dev;             /* 디바이스 모델 (드라이버 바인딩 대상) */
    int                     minor;           /* USB minor 번호 (-1 = 미사용) */
    /* ... */
};
Interface vs Device: USB 드라이버는 usb_device 전체가 아니라 usb_interface에 바인딩됩니다. 하나의 USB 디바이스가 여러 인터페이스를 가질 수 있고, 각 인터페이스에 서로 다른 드라이버가 바인딩될 수 있습니다 (예: CDC-ACM은 Control + Data 두 개의 인터페이스를 가집니다).

USB 드라이버 모델

드라이버 골격

#include <linux/module.h>
#include <linux/usb.h>

#define MY_VENDOR_ID   0x1234
#define MY_PRODUCT_ID  0x5678

struct my_usb_dev {
    struct usb_device    *udev;       /* USB 디바이스 */
    struct usb_interface  *intf;       /* 바인딩된 인터페이스 */
    unsigned char        *bulk_in_buf; /* Bulk IN 수신 버퍼 */
    size_t               bulk_in_size;
    __u8                 bulk_in_ep;  /* Bulk IN endpoint 주소 */
    __u8                 bulk_out_ep; /* Bulk OUT endpoint 주소 */
};

static int my_usb_probe(struct usb_interface *intf,
                        const struct usb_device_id *id)
{
    struct usb_device *udev = interface_to_usbdev(intf);
    struct usb_host_interface *iface_desc;
    struct usb_endpoint_descriptor *ep;
    struct my_usb_dev *dev;
    int i;

    iface_desc = intf->cur_altsetting;

    /* private 데이터 할당 */
    dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    if (!dev)
        return -ENOMEM;

    dev->udev = usb_get_dev(udev);
    dev->intf = intf;

    /* Endpoint 탐색 */
    for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
        ep = &iface_desc->endpoint[i].desc;

        if (usb_endpoint_is_bulk_in(ep)) {
            dev->bulk_in_size = usb_endpoint_maxp(ep);
            dev->bulk_in_ep = ep->bEndpointAddress;
            dev->bulk_in_buf = kmalloc(dev->bulk_in_size,
                                       GFP_KERNEL);
        }
        if (usb_endpoint_is_bulk_out(ep))
            dev->bulk_out_ep = ep->bEndpointAddress;
    }

    usb_set_intfdata(intf, dev);

    dev_info(&intf->dev, "USB device probed: %04x:%04x\n",
             le16_to_cpu(udev->descriptor.idVendor),
             le16_to_cpu(udev->descriptor.idProduct));
    return 0;
}

static void my_usb_disconnect(struct usb_interface *intf)
{
    struct my_usb_dev *dev = usb_get_intfdata(intf);

    usb_set_intfdata(intf, NULL);
    usb_put_dev(dev->udev);
    kfree(dev->bulk_in_buf);
    kfree(dev);

    dev_info(&intf->dev, "USB device disconnected\n");
}

/* USB Device ID 테이블 — 드라이버가 지원하는 디바이스 목록 */
static const struct usb_device_id my_usb_ids[] = {
    { USB_DEVICE(MY_VENDOR_ID, MY_PRODUCT_ID) },
    { }  /* 종료 마커 */
};
MODULE_DEVICE_TABLE(usb, my_usb_ids);

static struct usb_driver my_usb_driver = {
    .name       = "my_usb",
    .id_table   = my_usb_ids,
    .probe      = my_usb_probe,
    .disconnect = my_usb_disconnect,
};
module_usb_driver(my_usb_driver);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Example USB driver");

USB ID 매칭 매크로

매크로매칭 기준
USB_DEVICE(vendor, product)Vendor + Product ID
USB_DEVICE_VER(vendor, product, lo, hi)+ bcdDevice 범위
USB_DEVICE_INTERFACE_CLASS(vend, prod, cl)+ Interface Class
USB_DEVICE_INTERFACE_PROTOCOL(vend, prod, pr)+ Interface Protocol
USB_INTERFACE_INFO(cl, sc, pr)Interface Class/SubClass/Protocol
USB_DEVICE_INFO(cl, sc, pr)Device Class/SubClass/Protocol

드라이버 라이프사이클

디바이스 연결
  │
  ▼
Hub 인터럽트 → khubd / hub_event()
  │
  ▼
usb_new_device() → 디스크립터 파싱
  │
  ▼
device_add() → bus_probe_device()
  │
  ▼
usb_device_match() → id_table 매칭
  │
  ▼
usb_probe_interface() → driver->probe()
  │
  ▼
[정상 동작]
  │
  ▼ (분리 시)
usb_disconnect() → driver->disconnect()
  │
  ▼
device_del() → 리소스 정리

URB (USB Request Block)

URB (USB Request Block)은 USB 드라이버가 데이터를 전송하기 위해 USB Core에 제출하는 요청 단위입니다. 네트워크의 sk_buff, 블록 I/O의 bio에 해당하는 USB 서브시스템의 핵심 자료구조입니다.

struct urb 주요 필드

/* include/linux/usb.h */
struct urb {
    struct list_head       urb_list;        /* HCD 내부 리스트 */
    struct usb_device      *dev;            /* 대상 디바이스 */
    unsigned int           pipe;            /* 파이프 (endpoint + 방향 + 타입) */
    int                    status;          /* 완료 상태 (0=성공) */
    unsigned int           transfer_flags;  /* URB 플래그 */
    void                   *transfer_buffer; /* 데이터 버퍼 (kmalloc) */
    dma_addr_t             transfer_dma;    /* DMA 주소 (선택) */
    u32                    transfer_buffer_length; /* 버퍼 크기 */
    u32                    actual_length;   /* 실제 전송된 바이트 수 */
    unsigned char          *setup_packet;   /* Control 전송용 SETUP 패킷 */
    int                    interval;        /* Interrupt/Isoc 폴링 간격 */
    int                    number_of_packets; /* Isoc 패킷 수 */
    struct usb_iso_packet_descriptor iso_frame_desc[]; /* Isoc 프레임 */
    usb_complete_t         complete;        /* 완료 콜백 함수 */
    void                   *context;        /* 콜백 컨텍스트 */
    /* ... */
};

URB 라이프사이클

usb_alloc_urb()          ← URB 할당
       │
       ▼
usb_fill_*_urb()         ← 전송 타입별 초기화
       │
       ▼
usb_submit_urb()         ← USB Core에 제출 → HCD 큐
       │
       ▼
[HCD가 하드웨어 전송 수행]
       │
       ▼
complete() 콜백 호출     ← 인터럽트 컨텍스트에서 실행
       │
       ▼
usb_free_urb()           ← URB 해제 (참조 카운트 기반)

URB 초기화 헬퍼

/* Bulk 전송 URB 초기화 */
static void usb_fill_bulk_urb(
    struct urb *urb,
    struct usb_device *dev,
    unsigned int pipe,           /* usb_sndbulkpipe() / usb_rcvbulkpipe() */
    void *transfer_buffer,
    int buffer_length,
    usb_complete_t complete_fn,
    void *context);

/* Interrupt 전송 URB 초기화 */
static void usb_fill_int_urb(
    struct urb *urb,
    struct usb_device *dev,
    unsigned int pipe,
    void *transfer_buffer,
    int buffer_length,
    usb_complete_t complete_fn,
    void *context,
    int interval);              /* 폴링 간격 (ms 또는 microframes) */

/* Control 전송 URB 초기화 */
static void usb_fill_control_urb(
    struct urb *urb,
    struct usb_device *dev,
    unsigned int pipe,
    unsigned char *setup_packet,  /* 8바이트 SETUP 데이터 */
    void *transfer_buffer,
    int buffer_length,
    usb_complete_t complete_fn,
    void *context);

비동기 Bulk 전송 예제

static void my_bulk_complete(struct urb *urb)
{
    struct my_usb_dev *dev = urb->context;

    if (urb->status) {
        if (urb->status == -ENOENT ||
            urb->status == -ECONNRESET ||
            urb->status == -ESHUTDOWN) {
            /* URB 취소됨 — 정상적인 종료 */
            return;
        }
        dev_err(&dev->intf->dev,
                "bulk read failed: %d\n", urb->status);
        return;
    }

    /* 수신 데이터 처리 */
    dev_info(&dev->intf->dev,
             "received %d bytes\n", urb->actual_length);

    /* 연속 수신을 위해 URB 재제출 */
    usb_submit_urb(urb, GFP_ATOMIC);
}

static int my_start_bulk_read(struct my_usb_dev *dev)
{
    struct urb *urb;
    int ret;

    urb = usb_alloc_urb(0, GFP_KERNEL);
    if (!urb)
        return -ENOMEM;

    usb_fill_bulk_urb(urb, dev->udev,
        usb_rcvbulkpipe(dev->udev, dev->bulk_in_ep),
        dev->bulk_in_buf,
        dev->bulk_in_size,
        my_bulk_complete,
        dev);

    ret = usb_submit_urb(urb, GFP_KERNEL);
    if (ret) {
        dev_err(&dev->intf->dev,
                "failed to submit URB: %d\n", ret);
        usb_free_urb(urb);
    }
    return ret;
}

동기 전송 래퍼

간단한 전송에는 URB를 직접 관리하지 않고 동기 래퍼를 사용할 수 있습니다:

/* 동기 Bulk 전송 */
int actual_len;
int ret = usb_bulk_msg(dev->udev,
    usb_rcvbulkpipe(dev->udev, dev->bulk_in_ep),
    dev->bulk_in_buf,
    dev->bulk_in_size,
    &actual_len,
    5000);  /* 타임아웃 (ms) */

/* 동기 Control 전송 */
ret = usb_control_msg(dev->udev,
    usb_sndctrlpipe(dev->udev, 0),
    0x09,                        /* bRequest: SET_CONFIGURATION */
    USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
    1,                           /* wValue */
    0,                           /* wIndex */
    NULL,                        /* data */
    0,                           /* size */
    5000);                       /* 타임아웃 (ms) */

/* 동기 Interrupt 전송 */
ret = usb_interrupt_msg(dev->udev,
    usb_rcvintpipe(dev->udev, dev->int_in_ep),
    dev->int_buf, dev->int_buf_size,
    &actual_len, 5000);
주의: usb_bulk_msg(), usb_control_msg() 같은 동기 API는 내부에서 wait_for_completion()을 호출하므로 인터럽트 컨텍스트나 URB 완료 콜백 내에서 사용하면 안 됩니다. 이런 경우에는 비동기 URB를 사용해야 합니다.

파이프(Pipe) 매크로

매크로용도
usb_sndctrlpipe(dev, ep)Control OUT 파이프
usb_rcvctrlpipe(dev, ep)Control IN 파이프
usb_sndbulkpipe(dev, ep)Bulk OUT 파이프
usb_rcvbulkpipe(dev, ep)Bulk IN 파이프
usb_sndintpipe(dev, ep)Interrupt OUT 파이프
usb_rcvintpipe(dev, ep)Interrupt IN 파이프
usb_sndisocpipe(dev, ep)Isochronous OUT 파이프
usb_rcvisocpipe(dev, ep)Isochronous IN 파이프

Host Controller Driver (HCD)

HCD(Host Controller Driver)는 USB 호스트 컨트롤러 하드웨어를 직접 제어하는 최하위 계층 드라이버입니다. USB Core가 제출한 URB를 하드웨어 트랜잭션으로 변환하여 실행합니다.

호스트 컨트롤러 종류

HCD규격USB 속도특징커널 드라이버
UHCIIntelUSB 1.x (LS/FS)소프트웨어 스케줄링, CPU 부하 높음uhci-hcd
OHCICompaq/Microsoft/NSCUSB 1.x (LS/FS)하드웨어 스케줄링, 임베디드 주력ohci-hcd
EHCIIntelUSB 2.0 (HS)Companion Controller(UHCI/OHCI)와 쌍ehci-hcd
xHCIIntelUSB 1.x ~ 3.x모든 속도 통합, 스트림 지원xhci-hcd
xHCI 통합: xHCI(eXtensible Host Controller Interface)는 USB 1.x/2.0/3.x 전 속도를 단일 컨트롤러로 지원합니다. EHCI와 달리 Companion Controller가 필요 없으며, 현대 시스템의 표준 HCD입니다.

struct hc_driver

/* include/linux/usb/hcd.h */
struct hc_driver {
    const char  *description;
    const char  *product_desc;
    size_t      hcd_priv_size;   /* HCD private 데이터 크기 */

    /* HCD 생명주기 */
    int  (*reset)(struct usb_hcd *hcd);
    int  (*start)(struct usb_hcd *hcd);
    void (*stop)(struct usb_hcd *hcd);
    void (*shutdown)(struct usb_hcd *hcd);

    /* URB 관리 */
    int  (*urb_enqueue)(struct usb_hcd *hcd,
                        struct urb *urb, gfp_t mem_flags);
    int  (*urb_dequeue)(struct usb_hcd *hcd,
                        struct urb *urb, int status);

    /* Root Hub 조작 */
    int  (*hub_status_data)(struct usb_hcd *hcd,
                            char *buf);
    int  (*hub_control)(struct usb_hcd *hcd,
                        u16 typeReq, u16 wValue,
                        u16 wIndex, char *buf,
                        u16 wLength);

    /* Endpoint 관리 */
    void (*endpoint_reset)(struct usb_hcd *hcd,
                           struct usb_host_endpoint *ep);
    void (*endpoint_disable)(struct usb_hcd *hcd,
                            struct usb_host_endpoint *ep);
    /* ... */
};

xHCI 내부 구조

xHCI는 링 버퍼(Ring) 기반의 명령/전송 메커니즘을 사용합니다:

링 타입방향용도
Command RingSW → HWSlot 활성화/비활성화, Endpoint 구성, 주소 할당
Event RingHW → SW명령 완료, 전송 완료, 포트 상태 변경 알림
Transfer RingSW → HW데이터 전송 요청 (Endpoint별 1개)
xHCI 메모리 구조:
 ┌──────────────────────────────────────┐
 │ Device Context Base Address Array    │
 │   [0] Scratchpad Buffer Pointer      │
 │   [1] Slot 1 Device Context          │
 │   [2] Slot 2 Device Context          │
 │   ...                                │
 ├──────────────────────────────────────┤
 │ Device Context (Slot N)              │
 │   Slot Context                       │
 │   EP 0 Context (Control)             │
 │   EP 1 OUT Context + Transfer Ring   │
 │   EP 1 IN Context  + Transfer Ring   │
 │   ...                                │
 ├──────────────────────────────────────┤
 │ Command Ring                         │
 │   [TRB] [TRB] [TRB] ... [Link TRB]  │
 ├──────────────────────────────────────┤
 │ Event Ring (per Interrupter)         │
 │   [TRB] [TRB] [TRB] ...             │
 └──────────────────────────────────────┘

USB Gadget Framework

USB Gadget Framework는 Linux 시스템을 USB 디바이스 (Function)로 동작하게 하는 프레임워크입니다. 임베디드 시스템, SBC(Single Board Computer), 스마트폰 등에서 호스트에 연결될 때 다양한 USB 기능(Mass Storage, Ethernet, Serial 등)을 제공합니다.

Gadget 아키텍처

계층역할예시
Gadget Function DriverUSB 클래스 기능 구현f_mass_storage, f_ecm, f_acm, f_hid
Composite Framework여러 Function을 하나의 Configuration으로 합성usb_composite_driver
UDC (USB Device Controller)디바이스 컨트롤러 하드웨어 제어dwc3, musb, cdns3, fotg210
USB Gadget 스택 구조:

 ┌─────────────────────────────────────┐
 │  Gadget Function Drivers            │
 │  (f_mass_storage, f_ecm, f_acm...) │
 ├─────────────────────────────────────┤
 │  Composite Framework                │
 │  (usb_composite_driver)             │
 ├─────────────────────────────────────┤
 │  USB Gadget API                     │
 │  (usb_gadget_driver, usb_ep_ops)   │
 ├─────────────────────────────────────┤
 │  UDC Driver                         │
 │  (dwc3, musb, cdns3 ...)           │
 ├─────────────────────────────────────┤
 │  USB Device Controller Hardware     │
 └─────────────────────────────────────┘

ConfigFS Gadget

ConfigFS를 통해 유저스페이스에서 USB Gadget을 동적으로 구성할 수 있습니다. 커널 모듈 재컴파일 없이 USB 디바이스 기능을 조합합니다:

# ConfigFS USB Gadget 생성 예제: CDC ECM (Ethernet) + ACM (Serial)

# 1. Gadget 디렉토리 생성
cd /sys/kernel/config/usb_gadget
mkdir my_gadget && cd my_gadget

# 2. 디바이스 디스크립터 설정
echo 0x1d6b > idVendor     # Linux Foundation
echo 0x0104 > idProduct    # Multifunction Composite Gadget
echo 0x0100 > bcdDevice
echo 0x0200 > bcdUSB

# 3. 영문 문자열 설정
mkdir strings/0x409
echo "0123456789" > strings/0x409/serialnumber
echo "Linux"      > strings/0x409/manufacturer
echo "My Gadget"  > strings/0x409/product

# 4. Configuration 생성
mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "ECM + ACM" > configs/c.1/strings/0x409/configuration
echo 250 > configs/c.1/MaxPower   # 500mA (USB 2.0 단위: 2mA)

# 5. Function 인스턴스 생성
mkdir functions/ecm.usb0           # CDC ECM (Ethernet)
mkdir functions/acm.GS0            # CDC ACM (Serial)

# 6. Function을 Configuration에 링크
ln -s functions/ecm.usb0 configs/c.1/
ln -s functions/acm.GS0  configs/c.1/

# 7. UDC에 바인딩 (활성화)
ls /sys/class/udc                  # 사용 가능한 UDC 확인
echo "fe980000.usb" > UDC          # UDC 이름 기록 → 호스트에 연결됨

# 비활성화
echo "" > UDC

FunctionFS

FunctionFS는 USB Gadget Function의 로직을 유저스페이스에서 구현할 수 있게 하는 파일시스템입니다. 커널 드라이버 없이 사용자 정의 USB 프로토콜을 구현할 수 있습니다:

/* 유저스페이스 FunctionFS 사용 예제 (간략) */
#include <linux/usb/functionfs.h>

/* 1. FunctionFS 마운트 */
/* mount -t functionfs my_func /dev/ffs-my_func */

/* 2. ep0에 디스크립터 기록 */
int ep0_fd = open("/dev/ffs-my_func/ep0", O_RDWR);
write(ep0_fd, &descriptors, sizeof(descriptors));
write(ep0_fd, &strings, sizeof(strings));

/* 3. Endpoint 파일 열기 */
int ep1_fd = open("/dev/ffs-my_func/ep1", O_RDWR);  /* Bulk IN */
int ep2_fd = open("/dev/ffs-my_func/ep2", O_RDWR);  /* Bulk OUT */

/* 4. 데이터 송수신 */
read(ep2_fd, buf, sizeof(buf));   /* Bulk OUT에서 수신 */
write(ep1_fd, buf, len);           /* Bulk IN으로 송신 */

USB 클래스 드라이버

USB 클래스 드라이버는 USB-IF가 정의한 표준 디바이스 클래스를 구현합니다. VID/PID에 무관하게 클래스 코드만으로 드라이버가 매칭됩니다.

HID (Human Interface Device)

속성
Interface Class0x03
전송 타입Interrupt (IN/OUT)
커널 드라이버usbhid (drivers/hid/usbhid/)
디바이스 예시키보드, 마우스, 게임패드, 터치스크린
/* HID Report Descriptor 파싱 흐름 */
/* drivers/hid/usbhid/hid-core.c */
usbhid_probe()
  → hid_parse()            /* HID Report Descriptor 파싱 */hid_hw_start()         /* Input 디바이스 등록 */usb_fill_int_urb()     /* Interrupt IN URB 설정 */usb_submit_urb()       /* 입력 이벤트 수신 시작 */

Mass Storage

속성
Interface Class0x08
SubClass0x06 (SCSI transparent)
Protocol0x50 (Bulk-Only Transport, BOT)
전송 타입Bulk (IN + OUT)
커널 드라이버usb-storage, uas (UASP)
USB Mass Storage (Bulk-Only Transport) 프로토콜:

  호스트                    디바이스
    │                         │
    │── CBW (31 bytes) ──────→│  Command Block Wrapper
    │                         │    (SCSI 명령 포함)
    │                         │
    │←── Data (IN) ──────────│  또는
    │── Data (OUT) ──────────→│  데이터 단계 (선택)
    │                         │
    │←── CSW (13 bytes) ─────│  Command Status Wrapper
    │                         │    (성공/실패 상태)

CBW 구조:
  dCBWSignature    (4) = 0x43425355 ("USBC")
  dCBWTag          (4)   고유 태그
  dCBWDataLength   (4)   데이터 단계 바이트 수
  bmCBWFlags       (1)   0x80=IN, 0x00=OUT
  bCBWLUN          (1)   논리 장치 번호
  bCBWCBLength     (1)   SCSI 명령 길이
  CBWCB            (16)  SCSI 명령 블록
UAS (USB Attached SCSI): USB 3.0부터 지원되는 UAS(UASP) 프로토콜은 BOT 대비 명령 큐잉, 스트림 지원, 낮은 레이턴시로 성능이 크게 향상됩니다. 커널의 uas 드라이버(drivers/usb/storage/uas.c)가 담당합니다.

CDC (Communications Device Class)

서브클래스용도커널 드라이버호스트측 인터페이스
ACM (Abstract Control Model)가상 시리얼 포트cdc-acm/dev/ttyACM*
ECM (Ethernet Control Model)Ethernet 어댑터cdc_ethereth* / usb*
NCM (Network Control Model)고성능 Ethernet (USB 3.0+)cdc_ncmeth* / usb*
EEM (Ethernet Emulation Model)가상 Ethernet (Control IF 없음)cdc_eemusb*
MBIM모바일 광대역 (LTE/5G)cdc_mbimwwan*

Audio Class

속성
Interface Class0x01
전송 타입Isochronous (오디오 스트림), Interrupt (MIDI)
커널 드라이버snd-usb-audio (sound/usb/)
디바이스 예시USB 헤드셋, DAC, 마이크, MIDI 컨트롤러

주요 USB 클래스 코드

Class이름예시
0x01AudioUSB 사운드 카드, 마이크
0x02CDC (Communications)모뎀, Ethernet, 시리얼
0x03HID키보드, 마우스, 게임패드
0x06Still Image디지털 카메라 (PTP)
0x07PrinterUSB 프린터
0x08Mass StorageUSB 메모리, 외장 하드
0x09HubUSB 허브
0x0ACDC-DataCDC 데이터 인터페이스
0x0EVideo웹캠, 비디오 캡처
0xE0Wireless ControllerBluetooth 어댑터
0xEFMiscellaneousIAD(Interface Association)
0xFEApplication SpecificDFU (Device Firmware Upgrade)
0xFFVendor Specific벤더 전용 프로토콜

USB Type-C와 Power Delivery

USB Type-C는 단순한 커넥터 규격을 넘어 전원 공급(PD), 대체 모드(Alt Mode), 역할 전환(DRP) 등 복잡한 기능을 제공합니다. Linux 커널은 Type-C 서브시스템을 통해 이를 관리합니다.

Type-C 서브시스템

구성 요소역할커널 경로
typec coreType-C 포트/파트너/케이블 모델링drivers/usb/typec/
UCSIUSB Type-C Connector System Software Interfacedrivers/usb/typec/ucsi/
TCPMType-C Port Manager (PD 상태 머신)drivers/usb/typec/tcpm/
tcpciType-C Port Controller Interface 드라이버drivers/usb/typec/tcpm/tcpci.c
Alt Mode driversDisplayPort, TBT3 등 대체 모드drivers/usb/typec/altmodes/

PD (Power Delivery) 협상

USB PD는 Type-C CC(Configuration Channel) 라인을 통해 전원 협상을 수행합니다:

PD 버전최대 전력전압 범위
USB 2.0/3.0 기본4.5W (5V/900mA)5V 고정
USB Type-C 기본15W (5V/3A)5V 고정
PD 2.0/3.0100W (20V/5A)5V, 9V, 15V, 20V
PD 3.1 (EPR)240W (48V/5A)최대 48V (Extended Power Range)
PD 협상 흐름:

  Source (전원 공급)           Sink (전원 수신)
    │                             │
    │── Source_Capabilities ─────→│  제공 가능 PDO 목록
    │                             │
    │←── Request ────────────────│  원하는 PDO 선택
    │                             │
    │── Accept ─────────────────→│
    │── PS_RDY ─────────────────→│  전압/전류 전환 완료
    │                             │
    [전원 계약 체결 완료]

PDO (Power Data Object) 타입:
  - Fixed Supply PDO: 고정 전압 (5V, 9V, 15V, 20V)
  - Variable Supply PDO: 가변 전압 범위
  - Battery PDO: 배터리 전원
  - PPS (Programmable Power Supply): 세밀한 전압/전류 조정
  - AVS (Adjustable Voltage Supply): PD 3.1 EPR
# sysfs에서 Type-C 정보 확인
ls /sys/class/typec/

# 포트 정보
cat /sys/class/typec/port0/data_role         # [host] device
cat /sys/class/typec/port0/power_role        # [source] sink
cat /sys/class/typec/port0/preferred_role    # sink / source / none
cat /sys/class/typec/port0/port_type         # dual / source / sink

# 연결된 파트너 정보
cat /sys/class/typec/port0-partner/type      # UFP / DFP
cat /sys/class/typec/port0-partner/usb_power_delivery/
ls /sys/class/typec/port0-partner/identity/  # VDM ID 정보

# 역할 전환 (DRP 포트)
echo "device" > /sys/class/typec/port0/data_role
echo "sink"   > /sys/class/typec/port0/power_role

usbfs와 libusb

usbfs는 유저스페이스에서 USB 디바이스에 직접 접근할 수 있게 하는 파일시스템입니다. 커널 드라이버 없이도 /dev/bus/usb/를 통해 Control, Bulk, Interrupt, Isochronous 전송을 수행할 수 있습니다.

usbfs 접근 구조

/dev/bus/usb/
├── 001/              ← Bus 1
│   ├── 001           ← Root Hub (Device 1)
│   ├── 002           ← 연결된 디바이스 (Device 2)
│   └── 003
├── 002/              ← Bus 2
│   └── 001
└── ...

각 디바이스 파일은 캐릭터 디바이스이며,
ioctl()을 통해 USB 트랜잭션을 수행합니다:
  USBDEVFS_CONTROL     ← Control 전송
  USBDEVFS_BULK        ← Bulk 전송
  USBDEVFS_SUBMITURB   ← 비동기 URB 제출
  USBDEVFS_REAPURB     ← 완료된 URB 수확
  USBDEVFS_CLAIMINTERFACE  ← 인터페이스 점유
  USBDEVFS_RELEASEINTERFACE ← 인터페이스 해제
  USBDEVFS_RESETEP     ← Endpoint 리셋
  USBDEVFS_RESET       ← 디바이스 리셋

libusb 사용 예제

libusb는 usbfs 위에 구축된 크로스 플랫폼 유저스페이스 USB 라이브러리입니다:

#include <libusb-1.0/libusb.h>
#include <stdio.h>

#define VENDOR_ID   0x1234
#define PRODUCT_ID  0x5678
#define EP_BULK_IN  0x81
#define EP_BULK_OUT 0x02

int main(void)
{
    libusb_device_handle *handle;
    int ret, transferred;
    unsigned char buf[64];

    /* 1. 라이브러리 초기화 */
    libusb_init(NULL);

    /* 2. 디바이스 열기 */
    handle = libusb_open_device_with_vid_pid(
        NULL, VENDOR_ID, PRODUCT_ID);
    if (!handle) {
        fprintf(stderr, "Device not found\n");
        return 1;
    }

    /* 3. 커널 드라이버 분리 (필요 시) */
    if (libusb_kernel_driver_active(handle, 0) == 1)
        libusb_detach_kernel_driver(handle, 0);

    /* 4. 인터페이스 점유 */
    libusb_claim_interface(handle, 0);

    /* 5. Bulk OUT 전송 (호스트 → 디바이스) */
    unsigned char tx_data[] = {0x01, 0x02, 0x03};
    ret = libusb_bulk_transfer(handle, EP_BULK_OUT,
        tx_data, sizeof(tx_data), &transferred, 5000);
    printf("Sent %d bytes\n", transferred);

    /* 6. Bulk IN 전송 (디바이스 → 호스트) */
    ret = libusb_bulk_transfer(handle, EP_BULK_IN,
        buf, sizeof(buf), &transferred, 5000);
    printf("Received %d bytes\n", transferred);

    /* 7. 정리 */
    libusb_release_interface(handle, 0);
    libusb_close(handle);
    libusb_exit(NULL);
    return 0;
}
권한 설정: usbfs 접근에는 root 권한이 필요합니다. udev 규칙으로 특정 VID/PID에 대해 일반 사용자 접근을 허용할 수 있습니다:
SUBSYSTEM=="usb", ATTR{idVendor}=="1234", ATTR{idProduct}=="5678", MODE="0666"

USB 전원 관리

USB 전원 관리는 사용하지 않는 디바이스를 저전력 상태(Suspend)로 전환하여 전력 소모를 줄입니다. Linux 커널은 USB 디바이스 레벨과 인터페이스 레벨 모두에서 전원 관리를 지원합니다.

Autosuspend

Autosuspend는 디바이스가 일정 시간 유휴 상태이면 자동으로 Suspend하는 메커니즘입니다:

# autosuspend 설정 (sysfs)
# 디바이스별 경로: /sys/bus/usb/devices/<busnum>-<port>/power/

# autosuspend 활성화
echo "auto" > /sys/bus/usb/devices/1-2/power/control

# autosuspend 비활성화 (항상 활성)
echo "on" > /sys/bus/usb/devices/1-2/power/control

# autosuspend 대기 시간 (초) — 0이면 즉시 suspend
echo 2 > /sys/bus/usb/devices/1-2/power/autosuspend_delay_ms

# 현재 전원 상태 확인
cat /sys/bus/usb/devices/1-2/power/runtime_status
# active / suspended / suspending

# USB autosuspend 전역 기본값 (커널 파라미터)
# usbcore.autosuspend=2  (2초 후 자동 suspend)
# usbcore.autosuspend=-1 (autosuspend 비활성화)

Remote Wakeup

Remote Wakeup은 Suspend된 디바이스가 이벤트 발생 시 호스트를 깨울 수 있는 기능입니다 (예: 마우스 움직임, 키보드 입력):

/* 드라이버에서 autosuspend / remote wakeup 지원 */
static int my_usb_probe(struct usb_interface *intf,
                        const struct usb_device_id *id)
{
    struct usb_device *udev = interface_to_usbdev(intf);

    /* ... 드라이버 초기화 ... */

    /* Remote Wakeup 허용 */
    device_set_wakeup_enable(&udev->dev, 1);

    /* autosuspend 활성화 */
    usb_enable_autosuspend(udev);

    return 0;
}

/* Suspend 콜백 */
static int my_usb_suspend(struct usb_interface *intf,
                          pm_message_t message)
{
    struct my_usb_dev *dev = usb_get_intfdata(intf);

    /* 진행 중인 URB 취소 */
    usb_kill_urb(dev->bulk_urb);

    return 0;
}

/* Resume 콜백 */
static int my_usb_resume(struct usb_interface *intf)
{
    struct my_usb_dev *dev = usb_get_intfdata(intf);

    /* URB 재제출 */
    usb_submit_urb(dev->bulk_urb, GFP_NOIO);

    return 0;
}

static struct usb_driver my_usb_driver = {
    .name       = "my_usb",
    .id_table   = my_usb_ids,
    .probe      = my_usb_probe,
    .disconnect = my_usb_disconnect,
    .suspend    = my_usb_suspend,
    .resume     = my_usb_resume,
    .supports_autosuspend = 1,  /* autosuspend 지원 선언 */
};

Selective Suspend

용어설명
Global Suspend전체 USB 버스 Suspend (시스템 Sleep 시)
Selective Suspend개별 디바이스만 Suspend (런타임 PM)
L1 (LPM)USB 2.0 Link Power Management — 빠른 진입/탈출
U1/U2/U3USB 3.x Link States — U1/U2(저전력), U3(Suspend)
Autosuspend 주의: 모든 USB 디바이스가 Suspend/Resume을 올바르게 구현하는 것은 아닙니다. 일부 디바이스는 Suspend 후 응답하지 않거나 데이터를 잃을 수 있습니다. 문제가 있는 디바이스는 echo "on" > power/control로 autosuspend를 비활성화하거나, 커널의 USB quirks 테이블에 등록합니다.

디버깅

lsusb

# 연결된 USB 디바이스 목록
lsusb

# 트리 구조 (토폴로지)
lsusb -t

# 특정 디바이스 상세 정보 (모든 디스크립터 덤프)
lsusb -v -d 1234:5678

# 특정 버스/디바이스
lsusb -v -s 001:003

# 출력 예시 (lsusb -t)
# /:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 10000M
#     |__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=uas, 5000M
# /:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/12p, 480M
#     |__ Port 3: Dev 5, If 0, Class=HID, Driver=usbhid, 12M
#     |__ Port 3: Dev 5, If 1, Class=HID, Driver=usbhid, 12M
#     |__ Port 9: Dev 3, If 0, Class=Wireless, Driver=btusb, 12M

usbmon

usbmon은 USB 트래픽을 모니터링하는 커널 기능입니다. /sys/kernel/debug/usb/usbmon/을 통해 접근합니다:

# usbmon 모듈 로드
modprobe usbmon

# debugfs 마운트 확인
mount -t debugfs none /sys/kernel/debug 2>/dev/null

# 텍스트 형식 모니터링 (Bus 1)
cat /sys/kernel/debug/usb/usbmon/1t

# 모든 버스 모니터링
cat /sys/kernel/debug/usb/usbmon/0t

# 바이너리 형식 (Wireshark용)
cat /sys/kernel/debug/usb/usbmon/1u > capture.bin

# usbmon 텍스트 출력 형식:
# URB_TAG TIMESTAMP EVENT_TYPE ADDRESS:EP STATUS LENGTH DATA
# d5ea8c00 3575914555 S Bi:1:003:1 -115 31 = 55534253 ...
#   S = Submit, C = Complete
#   Bi = Bulk IN, Bo = Bulk OUT, Ci = Control IN

Wireshark를 이용한 USB 분석

# Wireshark에서 USB 캡처 (usbmon 인터페이스 선택)
# 또는 tcpdump로 캡처 파일 생성
tcpdump -i usbmon1 -w usb_capture.pcap

# Wireshark에서 열기
wireshark usb_capture.pcap

# Wireshark 필터 예시:
# usb.transfer_type == URB_BULK
# usb.device_address == 3
# usb.endpoint_address == 0x81
# usb.idVendor == 0x1234

sysfs USB 정보

/sys/bus/usb/devices/1-2/
├── idVendor              # Vendor ID (예: 0x046d)
├── idProduct             # Product ID (예: 0xc52b)
├── manufacturer          # 제조사 문자열
├── product               # 제품명 문자열
├── serial                # 시리얼 번호
├── bDeviceClass          # 디바이스 클래스
├── bDeviceSubClass
├── bDeviceProtocol
├── bcdDevice             # 디바이스 릴리즈 번호
├── speed                 # 연결 속도 (1.5/12/480/5000/10000)
├── version               # USB 규격 버전
├── maxchild              # 하위 포트 수 (Hub)
├── bNumConfigurations    # Configuration 수
├── bNumInterfaces        # 활성 Configuration의 인터페이스 수
├── bMaxPacketSize0       # EP0 최대 패킷 크기
├── bMaxPower             # 최대 전류 (mA)
├── configuration         # 활성 Configuration 문자열
├── authorized            # 디바이스 인가 상태
├── avoid_reset_quirk     # 리셋 회피 quirk
├── removable             # 물리적 분리 가능 여부
├── urbnum                # 누적 URB 제출 수
├── power/
│   ├── control           # auto / on
│   ├── autosuspend_delay_ms
│   ├── runtime_status    # active / suspended
│   ├── wakeup            # enabled / disabled
│   └── connected_duration
├── 1-2:1.0/             # Interface 0
│   ├── bInterfaceClass
│   ├── bInterfaceSubClass
│   ├── bInterfaceProtocol
│   ├── bNumEndpoints
│   ├── driver/           # 바인딩된 드라이버
│   └── ep_81/            # Endpoint 0x81
│       ├── type          # Interrupt / Bulk / ...
│       ├── direction     # in / out
│       ├── wMaxPacketSize
│       └── interval
└── 1-2:1.1/             # Interface 1

커널 디버깅

# USB 관련 커널 메시지
dmesg | grep -i usb

# Dynamic Debug 활성화
echo 'module usbcore +p' > /sys/kernel/debug/dynamic_debug/control
echo 'module xhci_hcd +p' > /sys/kernel/debug/dynamic_debug/control
echo 'module usbhid +p' > /sys/kernel/debug/dynamic_debug/control

# USB 디바이스 수동 리셋
echo 0 > /sys/bus/usb/devices/1-2/authorized
echo 1 > /sys/bus/usb/devices/1-2/authorized

# USB 바인딩/언바인딩
echo "1-2:1.0" > /sys/bus/usb/drivers/usbhid/unbind
echo "1-2:1.0" > /sys/bus/usb/drivers/usbhid/bind

# quirks 설정 (모듈 파라미터)
# usbcore.quirks=VID:PID:flags
# 예: usbcore.quirks=0x1234:0x5678:gn  (RESET_RESUME + NO_SET_INTF)

디버깅 도구 요약

도구용도설치
lsusbUSB 디바이스 목록 및 디스크립터 덤프usbutils
usbmon커널 레벨 USB 트래픽 모니터링커널 내장 (CONFIG_USB_MON)
WiresharkGUI USB 프로토콜 분석wireshark
usbhid-dumpHID Report Descriptor 덤프usbutils
usb-devices텍스트 기반 디바이스 정보usbutils
usbipUSB over IP (원격 디바이스 공유)usbip

커널 소스 구조

경로설명
drivers/usb/core/USB Core (열거, URB, Hub, 드라이버 매칭)
drivers/usb/host/HCD 드라이버 (xhci, ehci, ohci, uhci)
drivers/usb/gadget/USB Gadget Framework (UDC, composite, function)
drivers/usb/storage/USB Mass Storage 드라이버 (usb-storage, uas)
drivers/usb/class/USB 클래스 드라이버 (cdc-acm, usblp)
drivers/usb/serial/USB-Serial 어댑터 드라이버
drivers/usb/typec/Type-C 서브시스템 (TCPM, UCSI, Alt Mode)
drivers/hid/usbhid/USB HID 드라이버
sound/usb/USB Audio 드라이버
drivers/net/usb/USB 네트워크 드라이버 (cdc_ether, cdc_ncm, rndis)
drivers/media/usb/USB 미디어 드라이버 (UVC 웹캠 등)
include/linux/usb.hUSB Core API 헤더
include/linux/usb/hcd.hHCD API 헤더
include/linux/usb/gadget.hGadget API 헤더
include/linux/usb/ch9.hUSB Chapter 9 상수/구조체 (uapi)

주요 Kconfig 옵션

옵션설명
CONFIG_USBUSB 서브시스템 활성화
CONFIG_USB_XHCI_HCDxHCI 호스트 컨트롤러 드라이버
CONFIG_USB_EHCI_HCDEHCI 호스트 컨트롤러 드라이버
CONFIG_USB_OHCI_HCDOHCI 호스트 컨트롤러 드라이버
CONFIG_USB_STORAGEUSB Mass Storage 드라이버
CONFIG_USB_UASUSB Attached SCSI (UASP) 드라이버
CONFIG_USB_HIDUSB HID 드라이버
CONFIG_USB_ACMCDC ACM (가상 시리얼) 드라이버
CONFIG_USB_NET_CDCETHERCDC Ethernet 드라이버
CONFIG_USB_NET_CDC_NCMCDC NCM 네트워크 드라이버
CONFIG_SND_USB_AUDIOUSB Audio 드라이버
CONFIG_USB_GADGETUSB Gadget Framework
CONFIG_USB_CONFIGFSConfigFS 기반 USB Gadget 구성
CONFIG_USB_FUNCTIONFSFunctionFS (유저스페이스 Gadget)
CONFIG_TYPECUSB Type-C 서브시스템
CONFIG_TYPEC_TCPMType-C Port Manager
CONFIG_TYPEC_UCSIUCSI Type-C 인터페이스
CONFIG_USB_MONusbmon (USB 트래픽 모니터링)