USB Device Driver 작성 및 Linux Kernel에서 USB 인터페이스 사용 방법
이 글에서는 Embedded Linux 환경에서 USB Device Driver를 작성하고, Linux Kernel에서 USB 인터페이스를 사용하는 방법을 설명합니다. 또한, USB Touch Device를 예제로 들어 Input Report를 처리하는 방법까지 다룹니다. 이번 예제는 Rockchip RK3399 기반 시스템을 기준으로 작성되었습니다.
1. USB Device Driver란?
USB(Device Driver)는 USB 장치를 제어하고 커널과 사용자 공간에서 데이터를 주고받기 위한 소프트웨어 계층입니다. 이를 통해 USB 장치가 시스템에서 정상적으로 동작하도록 합니다.
USB 장치 드라이버는 보통 아래의 과정을 통해 작성됩니다:
- USB 장치의 Vendor ID(VID)와 Product ID(PID)를 확인
- USB 장치와의 데이터 전송 경로(Endpoint)를 정의
- USB 프로토콜에 맞는 데이터 처리 및 전송 구현
2. USB Device Driver 작성 방법
2.1 USB 장치 ID 매핑
Linux USB Subsystem은 장치 ID를 기반으로 장치를 식별합니다. 이를 위해 USB 장치의 VID, PID를 커널 모듈에 등록해야 합니다.
#include <linux/module.h>
#include <linux/usb.h>
#define USB_VENDOR_ID 0x1234 // 예시 Vendor ID
#define USB_PRODUCT_ID 0x5678 // 예시 Product ID
// 지원하는 장치 ID 테이블 정의
static struct usb_device_id usb_device_table[] = {
{ USB_DEVICE(USB_VENDOR_ID, USB_PRODUCT_ID) },
{} // 종료를 나타냄
};
MODULE_DEVICE_TABLE(usb, usb_device_table);
2.2 Probe와 Disconnect 함수 구현
USB 장치가 연결되거나 해제될 때 호출되는 콜백 함수를 작성합니다.
// Probe 함수: 장치가 연결될 때 호출
static int usb_probe(struct usb_interface *interface, const struct usb_device_id *id) {
printk(KERN_INFO "USB 장치가 연결되었습니다.\n");
return 0; // 성공 시 0 반환
}
// Disconnect 함수: 장치가 해제될 때 호출
static void usb_disconnect(struct usb_interface *interface) {
printk(KERN_INFO "USB 장치가 해제되었습니다.\n");
}
2.3 USB Driver 구조체 등록
위에서 작성한 Probe 및 Disconnect 함수를 USB Driver 구조체에 등록합니다.
static struct usb_driver usb_driver = {
.name = "usb_touch_driver",
.id_table = usb_device_table,
.probe = usb_probe,
.disconnect = usb_disconnect,
};
// 모듈 초기화 및 종료
static int __init usb_init(void) {
return usb_register(&usb_driver);
}
static void __exit usb_exit(void) {
usb_deregister(&usb_driver);
}
module_init(usb_init);
module_exit(usb_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("USB Device Driver Example");
3. Linux Kernel에서 USB Touch Device 사용 방법
3.1 Input Report 처리
USB Touch Device는 HID(Human Interface Device) Class의 일부로, Input Report를 통해 데이터를 주고받습니다.
주요 구조체:
usb_interface
usb_device
usb_endpoint_descriptor
#include <linux/hid.h>
#include <linux/input.h>
// Input Device 초기화
static struct input_dev *input_dev;
static int usb_touch_probe(struct usb_interface *interface, const struct usb_device_id *id) {
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
iface_desc = interface->cur_altsetting;
endpoint = &iface_desc->endpoint[0].desc;
if (!usb_endpoint_is_int_in(endpoint)) {
printk(KERN_ERR "Interrupt IN Endpoint가 아닙니다.\n");
return -ENODEV;
}
input_dev = input_allocate_device();
if (!input_dev) {
printk(KERN_ERR "Input Device 할당 실패\n");
return -ENOMEM;
}
input_dev->name = "USB Touch Device";
input_dev->id.bustype = BUS_USB;
input_register_device(input_dev);
printk(KERN_INFO "USB Touch Device가 초기화되었습니다.\n");
return 0;
}
3.2 Input Report 처리 및 데이터 읽기
Interrupt IN Endpoint를 통해 들어오는 데이터를 처리합니다.
static void usb_touch_irq(struct urb *urb) {
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
if (status) {
printk(KERN_ERR "URB 전송 실패: %d\n", status);
return;
}
printk(KERN_INFO "Touch Data: X=%d, Y=%d\n", data[0], data[1]);
input_report_abs(input_dev, ABS_X, data[0]);
input_report_abs(input_dev, ABS_Y, data[1]);
input_sync(input_dev);
}
4. Rockchip RK3399에서 USB Driver 포팅
Rockchip RK3399 플랫폼에서 위의 드라이버를 빌드하고 실행하려면, 다음 단계를 수행합니다:
4.1 Kernel Configuration
make menuconfig
를 실행합니다.- USB Subsystem 및 HID Device 지원을 활성화합니다.
4.2 드라이버 빌드 및 로드
- 드라이버 소스 파일을
drivers/usb/
디렉토리에 복사합니다. - Makefile에 해당 드라이버를 추가합니다:
obj-m += usb_touch_driver.o
- 드라이버 빌드:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- modules
- 드라이버 로드:
insmod usb_touch_driver.ko
4.3 드라이버 테스트
장치를 연결하고 dmesg
명령어를 사용해 드라이버 로그를 확인합니다:
dmesg | grep "USB Touch Device"
5. 결론
USB Device Driver 작성 및 Linux Kernel에서 USB 인터페이스를 사용하는 방법을 살펴보았습니다. Rockchip RK3399 플랫폼에서 USB Touch Device를 처리하는 실질적인 예제를 통해 개념과 구현 방법을 이해할 수 있었기를 바랍니다.
'Linux > Kernel Driver' 카테고리의 다른 글
DMA(Direct Memory Access) 처리: 개념과 사용법, 그리고 RK3399 예제 (0) | 2025.03.25 |
---|---|
Interrupt Handling in Embedded Linux (0) | 2025.03.24 |
USART Driver 작성 및 Linux Kernel에서의 USART 인터페이스 사용 방법 (0) | 2025.03.22 |
Embedded Linux에서 SPI Driver 작성하기 (Rockchip RK3399 기준) (0) | 2025.03.21 |
Embedded Linux Kernel: I2C 드라이버 작성 및 사용법 (0) | 2025.03.20 |