USB

EEEFFEE·2024년 1월 11일
0

임베디드 리눅스

목록 보기
13/14
post-thumbnail

24.01.10 최초 작성

1. USB 구조

USB HostUSB Device
master에 해당slave에 해당
  • wiring
VCCGNDData +Data -
전원접지Data + 끼리 연결Data - 끼리 연결
  • version
Known NameData RatePower Capabilities
usb v1.1X12Mbps150mA
usb v2.0High-Speed USB480Mbps500mA
usb v3.0SuperSpeed USB5Gbps1.5A
usb v3.1SuperSpeed+ USB10Gbps20A

HIDCDCMSCCustom Device Class

2. Endpoint

  • 각 장치 종류 마다 Host-Device간 사용하는 프로토콜을 달리함

  • USB 장치에 여러개의 Interface가 존재하고 Interface 내에 하나 혹은 여러개의 Endpoint가 존재

  • Endpoint0는 양방향 통신이 가능하며 EndpointInput/Output중 하나의 역할을 담당함

  • 여러 Endpoint를 모아 특정 장치와 통신하는 통로로 사용함

  • USB class 종류

HIDCDCMSCCustom Device Class

2.1 Endpoint 타입

  1. Control : enumeration에 사용

  2. Interrupt : 작은 크기의 데이터 통신 (마우스 ...)

  3. Bulk : 큰 크기의 데이터 통신에 사용하며 ACK체크 사용 (Network, Mass storage...)

  4. Isochronous : 큰 데이터 데이터 통신에 사용하며 ACK체크 하지 않음 (Audio, Video ...)

2.1.1 USB Enumeration

  1. 장치가 호스트에 연결되면 호스트가 장치를 감지하고 장치의 통신 속도를 알아냄

  2. 이후 device descriptor에서부터 장치 정보를 받아옴

  3. 장치를 초기화하고 주소를 할당, configuration descriptor를 통해 장치 설정 정보 가져옴

  4. interface descriptor가져와 USB class 정보를 가져옴

  5. 드라이버를 로드하면 장치 사용 준비 완료

descriptor

3. USB Device SW Terminology

  • USB Device : USB Gadget (USB class의 모음) + UDC (USB Device Controller의 드라이버)
  • linux-menuconfig에서

예제

wireshark

  • 네트워크 패킷 캡처 및 분석 (USB 패킷 분석 가능)

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");
}

0개의 댓글

관련 채용 정보