Skip to content

Universal Serial Bus

USB(범용 직렬 버스, 汎用直列 - , Universal Serial Bus, 문화어: 범용직렬모선, 일반직렬모선)는 컴퓨터와 주변 기기를 연결하는 데 쓰이는 입출력 표준 가운데 하나이다. 대표적인 버전으로는 USB 1.0, 1.1, 2.0, 3.0, 3.1 등이 있다.

USB는 다양한 기존의 직렬, 병렬 방식의 연결을 대체하기 위하여 만들어졌다. 키보드, 마우스, 게임패드, 조이스틱, 스캐너, 디지털 카메라, 프린터, PDA, 저장장치 와 같은 다양한 기기를 연결하는 데 사용되고 있다. 이러한 기기 연결의 대부분은 표준 연결 방식을 이용하여 이루어지고 있다. USB는 PC를 위하여 개발되었지만 지금은 PDA나 게임콘솔 등에서도 채택되어 사용되고 있고, USB의 전원 공급 기능을 이용하여 충전 용도로도 많이 사용되고 있다. 2008년에는 전 세계적으로 약 20억 개의 USB 장치가 있다.

USB는 USB표준을 결정하는 USB Implementers Forum에서 표준을 결정한다. 2010년 3월 현재 포럼 의장은 인텔사의 제프(Jeff Ravencraft)이다. 컴퓨터 메인보드 시장에서 인텔의 I/O칩 점유율이 압도적(메릴린치의 2004년 3사분기 보고서에 따르면 62.1%)이기 때문에 소비자 시장에서의 가장 큰 수요를 쥐고 포럼 내 영향력도 가장 큰 인텔사의 주도에 의해 만들어지고 있다.

경쟁 규격으로 언급되는 IEEE 1394가 주로 캠코더에 탑재되어 DV규격으로 주로 사용되는 반면 USB는 저가격의 다수의 기기에 채택되어 있다.

Categories

Types

USB Type A

Usb_type_a.png

USB Type B

Usb_type_b.png

USB Type C

Usb_type_c.jpg

How to mount in the Linux

리눅스에서 대부분 USB장치는 /dev/sda또는 /dev/sdb등의 장치명을 사용하는데 현재 리눅스서버에서 사용되고 있지 않은 장치명을 USB장치명으로 사용할수 있다. 어떤 장치명에 할당되었는가를 확인하기 위하여 fdisk -l명령으로 확인할 수 있다.

$ fdisk -l
## ...
## 이후 아래와 같이 마운트 한다.
$ mount -t vfat /dev/sdb1 /mnt/usb

USB 장치 확인 방법

lsusb로 USB 장치 목록을 확인할 수 있다:

$ lsusb
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 003: ID 04f2:b67a Chicony Electronics Co., Ltd LG HD WebCam
Bus 003 Device 004: ID 046d:c539 Logitech, Inc. USB Receiver
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 003: ID 2109:0817 VIA Labs, Inc. USB3.0 Hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 8087:0029 Intel Corp.
Bus 001 Device 019: ID 0bda:c811 Realtek Semiconductor Corp.
Bus 001 Device 015: ID 0853:0146 Topre Corporation USB2.0 Hub
Bus 001 Device 011: ID 2109:2812 VIA Labs, Inc. VL812 Hub
Bus 001 Device 009: ID 1a40:0101 Terminus Technology Inc. Hub
Bus 001 Device 010: ID 2109:8888 VIA Labs, Inc.
Bus 001 Device 008: ID 2109:2817 VIA Labs, Inc. USB2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

9번째 줄의 Realtek Semiconductor Corp을 확인하자.

중간에 ... ID 0bda:c811 ... 부분이 있는데, 앞 부분이 Vender ID, 뒷 부분이 Product ID 이다.

만약 터미널 환경이 거북하면 sysinfo 또는 hardinfo를 사용하여 확인하자.

Hardinfo_sample_screenshot.png

이 정보를 바탕으로 dmesg 유틸로 커널 메시지를 확인하자:

$ sudo dmesg -H -w
...
[  +2.019060] usb 1-2.4.4: new high-speed USB device number 26 using xhci_hcd
[  +0.122475] usb 1-2.4.4: New USB device found, idVendor=0bda, idProduct=c811, bcdDevice= 2.00
[  +0.000010] usb 1-2.4.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  +0.000004] usb 1-2.4.4: Product: 802.11ac NIC
[  +0.000003] usb 1-2.4.4: Manufacturer: Realtek
[  +0.000002] usb 1-2.4.4: SerialNumber: 123456
...
[ +33.686931] usb 1-2.4.4: USB disconnect, device number 26
...

(참고로 -H옵션은 Human Readable, -w옵션은 Follow 를 뜻한다)

새로운 USB를 연결하면 usb 1-2.4.4와 같은 Prefix 와 함께, 위와 같이 출력된다. 4번째 줄의 Vender ID와 Product ID가 동일한지 확인하자.

usb 1-2.4.4 Prefix 부분을 따라가면 동일한 장치의 커널 메시지가 된다.

이 중 6번째 라인의 Product: 802.11ac NIC를 확인하면 된다. 따라서 이 장치는 "무선 wifi 동글이" 로 확인되었다.

USB 부팅 안된다면 일반적인 조치 방법

부팅이 안 되는 가장 흔한 원인입니다:

  • Secure Boot 비활성화 — BIOS에서 Secure Boot를 끄고 시도
  • Boot Mode 확인 — UEFI Only로 되어 있으면 Legacy/CSM도 활성화
  • Boot Order — USB가 부팅 순서 상위에 있는지 확인
  • Fast Boot 비활성화 — Fast Boot이 켜져 있으면 USB를 인식 못할 수 있음

GPT/MBR 파티션 테이블 문제

일부 구형 BIOS는 GPT를 인식 못합니다. 수동으로 부팅 가능한 USB를 만들려면:

# USB 초기화 후 수동 구성
sudo wipefs -a /dev/sdb

# MBR 파티션 테이블로 생성 (Legacy BIOS 호환)
sudo parted /dev/sdb --script mklabel msdos
sudo parted /dev/sdb --script mkpart primary fat32 1MiB 100%
sudo parted /dev/sdb --script set 1 boot on

# FAT32 포맷
sudo mkfs.vfat -F 32 /dev/sdb1

# ISO 마운트 후 파일 복사
sudo mkdir -p /mnt/{iso,usb}
sudo mount -o loop ubuntu-24.04-desktop-amd64.iso /mnt/iso
sudo mount /dev/sdb1 /mnt/usb
sudo cp -a /mnt/iso/. /mnt/usb/
sudo sync

# UEFI 부팅을 위한 부트로더 설치
sudo grub-install --target=i386-pc --boot-directory=/mnt/usb/boot /dev/sdb

sudo umount /mnt/{iso,usb}

사용자 공간 USB 드라이버 작성 입문

  • USB 드라이버 개발은 커널 수준의 작업으로 여겨지지만, 실제로는 소켓 프로그래밍과 유사한 난이도로 사용자 공간에서도 구현 가능함
  • libusb를 사용하면 커널 코드를 작성하지 않고도 장치 열거, 제어 전송, 데이터 송수신을 모두 수행할 수 있음
  • USB 통신은 Control, Bulk, Interrupt, Isochronous 네 가지 전송형과 IN/OUT 방향으로 구성되며, 각 엔드포인트는 단방향 통로로 동작함
  • Android 기기의 Fastboot 프로토콜을 예시로, Bulk 엔드포인트를 통해 명령과 응답을 주고받는 과정을 코드로 시연함
  • 사용자 공간에서도 완전한 USB 드라이버를 구현할 수 있으며, 모든 USB 프로토콜은 동일한 기본 구조를 공유함

소개

  • USB 장치용 드라이버는 커널 코드를 다뤄야 한다는 인식 때문에 어렵게 느껴지지만, 실제로는 소켓을 사용하는 애플리케이션 수준의 복잡도임
  • 하드웨어 경험이 많지 않은 개발자도 사용자 공간에서 USB를 다루는 방법을 익힐 수 있음
  • USB의 세부 동작을 다루는 자료가 존재하지만 초보자에게는 접근이 어려움
  • USB 사용에는 임베디드 시스템 수준의 지식이 필요하지 않으며, 네트워크 소켓처럼 접근 가능함

USB 장치

  • 예제로 부트로더 모드의 Android 스마트폰을 사용
    • 쉽게 구할 수 있고, 프로토콜이 단순하며, OS에 기본 드라이버가 없어 실험에 적합함
  • 부트로더 모드 진입은 기기마다 다르며, 일반적으로 전원 버튼과 볼륨 버튼 조합으로 가능함

장치 수동 열거

  • 열거(Enumeration) 는 호스트가 장치 정보를 요청해 자신을 식별하는 과정으로, 장치 연결 시 자동 수행됨
  • 표준 장치는 USB 클래스를 기반으로 드라이버를 자동 로드하고, 벤더 전용 장치는 VID(Vendor ID)와 PID(Product ID)를 사용함
  • Linux에서는 lsusb 명령으로 장치 정보를 확인 가능
    • 예시: ID 18d1:4ee0 Google Inc. Nexus/Pixel Device (fastboot)
    • 18d1은 Google의 VID, 4ee0은 Nexus/Pixel 부트로더의 PID
  • lsusb -t 명령으로 클래스와 드라이버 상태를 확인 가능
    • Class=Vendor Specific Class, Driver=[none]으로 표시되어 OS가 드라이버를 로드하지 않음
  • Windows에서는 Device Manager나 USB Device Tree Viewer로 동일한 정보 확인 가능

libusb로 장치 열거

  • libusb 라이브러리를 사용하면 커널 코드를 작성하지 않고 사용자 공간에서 USB 장치와 통신 가능
  • libusb_hotplug_register_callback()으로 특정 VID:PID 조합의 장치가 연결될 때 콜백을 실행하도록 설정
  • 프로그램 실행 후 장치 연결 시 "Device plugged in!" 메시지 출력
  • Linux에서는 기본적으로 작동하며, 필요 시 libusb_detach_kernel_driver()로 커널 드라이버를 분리 가능
  • Windows에서는 Winusb.sys 드라이버가 필요하며, 없을 경우 Zadig 도구로 수동 교체 가능

장치와의 통신

  • USB 장치와의 첫 통신은 Control 엔드포인트(주소 0x00) 를 통해 수행
  • libusb_control_transfer()로 표준 요청(GET_STATUS) 을 전송해 장치 상태를 읽음
    • 예시 응답: 01 00 → 첫 바이트는 Self-Powered, 두 번째는 Remote Wakeup 미지원
  • 이후 GET_DESCRIPTOR 요청으로 장치 디스크립터를 가져올 수 있음
    • 반환된 데이터에는 idVendor, idProduct, bDeviceClass 등 장치 정보가 포함됨
  • lsusb -v 명령으로 모든 디스크립터(장치, 구성, 인터페이스, 엔드포인트 등)를 상세히 확인 가능
    • 예시: Android Fastboot 인터페이스에 Bulk IN(0x81), Bulk OUT(0x02) 엔드포인트 존재

엔드포인트

  • 엔드포인트는 네트워크 포트와 유사한 개념으로, 장치가 데이터를 송수신하는 통로
  • 디스크립터에 각 엔드포인트의 종류와 방향이 정의되어 있음
  • Control 전송형
    • 모든 장치에 하나 존재하며 주소는 항상 0x00
    • 초기 설정 및 장치 정보 요청에 사용
    • 인터페이스에 속하지 않고 장치 자체의 일부로 존재
  • Bulk 전송형
    • 대용량 비실시간 데이터 전송에 사용
    • 예: Mass Storage, CDC-ACM(시리얼), RNDIS(이더넷)
    • 대역폭은 높지만 우선순위는 낮음
  • Interrupt 전송형
    • 소량의 저지연 데이터 전송에 사용
    • 키보드, 마우스 등에서 버튼 입력을 빠르게 폴링
    • 실제 하드웨어 인터럽트는 아니며, 호스트가 주기적으로 요청함
  • Isochronous 전송형
    • 시간 민감한 대용량 데이터(오디오, 비디오 스트리밍)에 사용
    • 지연이 발생하면 품질 저하가 즉시 드러남
    • libusb에서는 비동기 방식으로 처리
  • IN / OUT 방향
    • USB는 호스트 중심 구조로, 장치는 요청을 받기 전에는 데이터를 전송하지 않음
    • IN: 호스트가 데이터를 받는 방향
    • OUT: 호스트가 데이터를 보내는 방향
    • 엔드포인트 주소의 최상위 비트(MSB)가 1이면 IN, 0이면 OUT
    • 최대 127개의 사용자 정의 엔드포인트 사용 가능 (0x00은 Control 전용)
    • 엔드포인트는 단방향이며, Fastboot 인터페이스처럼 IN/OUT 쌍으로 구성됨

Fastboot 프로토콜

  • Fastboot는 Android 부트로더 통신 프로토콜로, 명령 문자열을 보내고 4바이트 상태 코드와 데이터를 받는 구조
    • 예:
      • Host: "getvar:version" → Client: "OKAY0.4"
      • Host: "getvar:nonexistant" → Client: "OKAY"
  • libusb를 이용해 Fastboot 명령을 전송하는 코드 예시
    • 인터페이스 0을 libusb_claim_interface()로 확보
    • "getvar:version" 명령을 Bulk OUT(0x02) 엔드포인트로 전송
    • Bulk IN(0x81) 엔드포인트로 응답 수신
    • OKAY는 성공 상태, 0.4는 Fastboot 버전

마무리

  • 커널 코드를 작성하지 않고 사용자 공간에서 완전한 USB 드라이버를 구현 가능
  • 모든 USB 드라이버는 동일한 기본 원리를 따르며, 프로토콜만 다름
  • 복잡한 프로토콜(MTP 등)도 기본 구조는 동일하며, 소켓 통신과 유사한 개념으로 접근 가능함

Libraries

Bootable USB

Troubleshooting

Ubuntu 에서 /dev/ttyUSB0 연결이 저절로 끊기는 현상

sudo dmesg -w 으로 로그를 확인하면:

[  208.805626] usb 1-1.2.3: new full-speed USB device number 8 using xhci_hcd
[  208.909682] usb 1-1.2.3: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.64
[  208.909696] usb 1-1.2.3: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[  208.909700] usb 1-1.2.3: Product: USB Serial
[  208.946567] ch341 1-1.2.3:1.0: ch341-uart converter detected
[  208.960853] usb 1-1.2.3: ch341-uart converter now attached to ttyUSB0
[  209.540161] input: BRLTTY 6.4 Linux Screen Driver Keyboard as /devices/virtual/input/input42
[  209.780667] usb 1-1.2.3: usbfs: interface 0 claimed by ch341 while 'brltty' sets config #1
[  209.783648] ch341-uart ttyUSB0: ch341-uart converter now disconnected from ttyUSB0
[  209.783689] ch341 1-1.2.3:1.0: device disconnected

중요 라인들을 번역하면:

  • [208.960853] usb 1-1.2.3: ch341-uart 변환기가 이제 ttyUSB0에 연결됨
  • [209.540161] input: BRLTTY 6.4 Linux 화면 드라이버 키보드 /devices/virtual/input/input42
  • [209.780667] usb 1-1.2.3: usbfs: 인터페이스 0이 ch341에 의해 요청됨, 'brltty'가 구성 #1을 설정함
  • [209.783648] ch341-uart ttyUSB0: ch341-uart 변환기가 이제 ttyUSB0에서 연결 해제됨
  • [209.783689] ch341 1-1.2.3:1.0: 장치 연결 해제됨

요약하면 brltty를 삭제하면 된다.

sudo apt purge brltty

brltty라는 녀석이 실행되면서 USB 인터페이스 0번을 선점하려고 함. 이로 인해 연결이 끊기는 결과를 보임.

See also

Favorite site

References


  1. USB-Device-Tracking-Artifacts.pdf