>  기사  >  시스템 튜토리얼  >  Linux USB 드라이버 작업 흐름에 대한 자세한 설명

Linux USB 드라이버 작업 흐름에 대한 자세한 설명

王林
王林앞으로
2024-02-09 18:40:26637검색

Linux 커널 드라이버는 Linux 시스템의 가장 중요한 구성 요소 중 하나입니다. 운영 체제가 하드웨어를 올바르게 식별하고 사용할 수 있도록 하드웨어 장치와 통신하는 일을 담당합니다. 그러나 Linux 커널 드라이버를 개발하는 것은 쉬운 일이 아닙니다. 이 기사에서는 Linux 커널 드라이버의 구현 방법을 자세히 살펴보고 독자에게 포괄적인 이해와 지침을 제공할 것입니다.

详解Linux USB驱动工作流程

1. USB 호스트

Linux 드라이버에서 USB 드라이버의 하위 계층은 USB 호스트 컨트롤러 하드웨어입니다. 그 위에서 실행되는 것은 USB 호스트 컨트롤러 드라이버입니다. 호스트 컨트롤러 위에는 USB 코어 계층이 있고 상위 계층은 USB 장치 드라이버입니다. 레이어(호스트에 U 디스크, 마우스, USB를 직렬 포트 및 기타 장치 드라이버에 삽입).

따라서 호스트 측 계층 구조에서 구현되는 USB 드라이버에는 USB 호스트 컨트롤러 드라이버와 USB 장치 드라이버라는 두 가지 범주가 포함됩니다. 전자는 삽입된 USB 장치를 제어하고, 후자는 USB 장치가 USB 장치와 통신하는 방식을 제어합니다. 주인. Linux 커널 USB 코어는 USB 드라이버 관리 및 프로토콜 처리의 주요 작업을 담당합니다. 호스트 컨트롤러 드라이버와 장치 드라이버 사이의 USB 코어는 매우 중요합니다. 그 기능은 다음과 같습니다: 일부 데이터 구조, 매크로 및 기능을 정의하여 위쪽으로 장치 드라이버에 대한 프로그래밍 인터페이스를 제공하고 USB 호스트 컨트롤러에 대한 프로그래밍 인터페이스를 제공합니다. 드라이버 하향; 전역 변수는 전체 시스템의 USB 장치 정보를 유지하며 장치 핫 플러그 ​​제어, 버스 데이터 전송 제어 등을 수행합니다.

2. USB 장치

Linux 커널의 USB 장치 측 드라이버는 UDC 드라이버, Gadget API 및 Gadget 드라이버의 세 가지 수준으로 나뉩니다. UDC 드라이버는 하드웨어에 직접 액세스하고 USB 장치와 호스트 간의 기본 통신을 제어하며 하드웨어 관련 작업에 대한 콜백 기능을 상위 계층에 제공합니다. 현재 Gadget API는 UDC 드라이버 콜백 함수를 둘러싼 간단한 래퍼입니다. Gadget 드라이버는 USB 장치 기능의 구현을 구체적으로 제어하여 장치가 "네트워크 연결", "프린터" 또는 "USB 대용량 저장소"와 같은 기능을 표시할 수 있도록 합니다. Gadget API를 사용하여 위의 기능을 구현하기 위해 UDC를 제어합니다. Gadget API는 상위 계층 Gadget 드라이버에서 하위 계층 UDC 드라이버를 분리하여 Linux 시스템에서 USB 장치 측 드라이버를 작성할 때 기능 구현을 기본 통신과 분리할 수 있도록 합니다.

3. USB 장치 조직 구조는 위에서 아래로 장치(device), 구성(config), 인터페이스(interface), 엔드포인트(endpoint)의 네 가지 수준으로 나뉩니다. USB 장치 프로그램이 인터페이스에 바인딩됩니다.

이 네 가지 레벨에 대한 간략한 설명은 다음과 같습니다.
장치에는 일반적으로 하나 이상의 구성이 있습니다
구성에는 종종 하나 이상의 인터페이스가 있습니다
인터페이스에는 엔드포인트가 없거나 두 개 이상 있습니다

详解Linux USB驱动工作流程

4 가장 기본적인 형태의 USB 통신은 엔드포인트를 통한 것입니다(USB 엔드포인트는 인터럽트, 벌크, ISO 및 제어의 네 가지 유형으로 구분되며 각각 용도가 다름). USB 엔드포인트는 한 방향으로만 데이터를 전송할 수 있습니다. 호스트에서 장치로 또는 장치에서 호스트로의 끝점은 단방향 파이프로 간주될 수 있습니다. 드라이버는 USB 하위 시스템에 드라이버 개체를 등록하고 나중에 제조업체 및 장치 ID를 사용하여 하드웨어가 설치되었는지 확인합니다. USB 코어는 목록(제조업체 ID와 장치 ID가 포함된 구조)을 사용하여 장치에 사용할 드라이버를 결정하고 핫플러그 스크립트는 이를 사용하여 특정 장치가 시스템에 연결되는 시기를 결정합니다. 자동으로 실행됩니다.

5. 데이터 구조

1) USB 장치: 해당 데이터 구조 struct usb_device

2) 구성: struct usb_host_config (언제든지 하나의 구성만 적용 가능)

3) USB 인터페이스: struct usb_interface (USB 코어는 이를 USB 장치 드라이버에 전달하고 USB 장치 드라이버는 후속 제어를 담당합니다. USB 인터페이스는 기본 기능을 나타내며 각 USB 드라이버는 인터페이스를 제어합니다. 따라서 물리적인 하드웨어 장치에는 두 개 이상의 드라이버가 필요할 수 있습니다 )

.

4) 엔드포인트: struct usb_host_endpoint, 여기에 포함된 실제 엔드포인트 정보는 다른 구조인 struct usb_endpoint_descriptor(엔드포인트 설명자, 모든 USB 관련 데이터 포함)에 있습니다.

6. USB 엔드포인트 분류

가장 기본적인 형태의 USB 통신은 엔드포인트를 통한 통신입니다. USB 엔드포인트는 한 방향(호스트에서 장치로(출력 엔드포인트라고 함) 또는 장치에서 호스트로(입력 엔드포인트라고 함))로만 데이터를 전송할 수 있습니다. 끝점은 단방향 파이프로 생각할 수 있습니다.

USB 엔드포인트에는 4가지 유형이 있으며 각각 데이터 전송 방법이 다릅니다.

1) 제어
제어 엔드포인트는 USB 장치의 다양한 부분에 대한 액세스를 제어하는 ​​데 사용됩니다. 일반적으로 장치를 구성하고, 장치 정보를 얻고, 장치에 명령을 보내거나 장치 상태 보고서를 얻는 데 사용됩니다. 이러한 끝점은 일반적으로 더 작습니다. 모든 USB 장치에는 "Endpoint 0"이라는 제어 끝점이 있으며, 이는 USB 코어가 연결될 때 장치를 구성하는 데 사용됩니다. USB 프로토콜은 제어 엔드포인트가 장치에 데이터를 전송하는 데 항상 충분한 대역폭이 남아 있도록 보장합니다.

2) 중단
USB 호스트가 장치로부터 데이터를 요청할 때마다 인터럽트 엔드포인트는 고정된 속도로 소량의 데이터를 전송합니다. 이는 USB 키보드 및 마우스의 기본 데이터 전송 방법입니다. 또한 장치를 제어하기 위해 USB 장치로 데이터를 전송하는 데에도 사용됩니다. 일반적으로 대량의 데이터를 전송하는 데 사용되지 않습니다. USB 프로토콜은 인터럽트 엔드포인트가 장치에 데이터를 전송하는 데 항상 충분한 대역폭이 남아 있도록 보장합니다.

3) 일괄 대량
대량 엔드포인트는 대량의 데이터를 전송하는 데 사용됩니다. 이러한 끝점은 일반적으로 인터럽트 끝점보다 훨씬 큽니다. 데이터 손실이 없는 상황에서 일반적으로 사용됩니다. USB 프로토콜은 특정 시간 내에 전송이 완료된다는 것을 보장하지 않습니다. 버스에 전체 BULK 패킷을 전송할 공간이 충분하지 않은 경우 여러 패킷으로 분할하여 전송합니다. 이러한 끝점은 프린터, USB 대용량 저장소 및 USB 네트워크 장치에서 일반적으로 사용됩니다.

4) ISOCHRONOUS
등시성 엔드포인트도 대량의 데이터를 일괄적으로 전송하지만 이 데이터의 전달이 보장되지는 않습니다. 이러한 엔드포인트는 데이터 손실을 처리하고 지속적인 데이터 흐름을 유지하는 데 더 많이 의존할 수 있는 장치에 사용됩니다. 오디오 및 비디오 장비 등.

제어 및 배치 엔드포인트는 비동기 데이터 전송에 사용되는 반면, 인터럽트 및 등시성 엔드포인트는 주기적입니다. 이는 이러한 엔드포인트가 고정된 시간에 지속적으로 데이터를 전송하도록 설정되고 USB 코어가 해당 엔드포인트를 위해 해당 대역폭을 예약한다는 의미입니다.

7.엔드포인트

으아악

USB 장치 드라이버가 호출되어 urb 요청을 제출하기 위해 usb_submit_urb를 호출하면 int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb)가 호출되어 이 urb를 urb_list의 꼬리에 추가합니다. (hcd: 호스트 컨트롤러 드라이버, 해당 데이터 구조 struct usb_hcd)

8.urb

모든 USB 통신은 요청->응답 모드이며 USB 장치는 적극적으로 호스트에 데이터를 전송하지 않습니다. 데이터 쓰기: USB 장치 드라이버는 USB 장치에 urb 요청을 보내고 USB 장치는 데이터를 반환할 필요가 없습니다. 데이터 읽기: USB 장치 드라이버는 USB 장치에 urb 요청을 보내고 USB 장치는 데이터를 반환해야 합니다.

USB 장치 드라이버는 urb를 통해 모든 USB 장치와 통신합니다. urb는 urb 구조(include/linux/usb.h)로 설명됩니다.
urb는 특정 USB 장치의 특정 끝점에 비동기 방식으로 데이터를 보내거나 받습니다. USB 장치 드라이버는 드라이버의 요구 사항에 따라 여러 urb를 단일 엔드포인트에 할당하거나 단일 urb를 여러 다른 엔드포인트에 재사용할 수 있습니다. 장치의 각 엔드포인트는 urb 대기열을 처리하므로 대기열이 비워지기 전에 여러 urb를 동일한 엔드포인트로 보낼 수 있습니다.

URB의 일반적인 수명 주기는 다음과 같습니다.
(1) 생성됨
(2) 특정 USB 장치에 할당된 특정 엔드포인트
(3) USB 코어에 제출됨
(4) USB 코어가 특정 장치용 특정 USB 호스트 컨트롤러 드라이버에 제출합니다. (5) USB 호스트 컨트롤러 드라이버에 의해 처리되어 장치로 전송됩니다. (6) 위의 작업이 완료된 후 USB 호스트 컨트롤러 드라이버는 USB 장치 드라이버에 알립니다.

urb는 제출한 드라이버에 의해 언제든지 취소될 수 있습니다. 장치가 제거되면 USB 코어로 urb가 취소될 수 있습니다. urbs는 동적으로 생성되며 내부 참조 횟수를 포함하므로 마지막 사용자가 이를 릴리스할 때 자동으로 릴리스될 수 있습니다.

8.1 urb 제출

urb가 제대로 생성되고 초기화되면 USB 코어에 제출하여 USB 장치로 보낼 수 있습니다. 이는 sb_submit_urb 함수를 호출하여 달성됩니다.

int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
매개변수:
struct urb *urb: 제출된 urb에 대한 포인터
gfp_t mem_flags: kmalloc 호출에 전달된 동일한 매개변수를 사용하여 적시에 메모리 버퍼를 할당하는 방법을 USB 코어에 알려줍니다

usb_submit_urb 함수는 언제든지 호출될 수 있으므로(인터럽트 컨텍스트 포함) mem_flags 변수는 usb_submit_urb 호출 시점에 따라 3개의 유효한 값만 사용할 수 있습니다.

GFP_ATOMIC
다음 조건이 충족되는 한 이 값을 사용해야 합니다.
1) 호출자는 urb 끝 핸들러, 인터럽트 핸들러, 하단 절반, 태스크릿 또는 타이머 콜백 함수에 있습니다.
2) 호출자가 스핀 잠금 또는 읽기-쓰기 잠금을 보유하고 있는 경우 세마포어가 보유 중인 경우 이 값은 필요하지 않습니다.
3) 현재->상태는 TASK_RUNNING이 아닙니다. 드라이버가 스스로 현재 상태를 변경하지 않은 이상 상태는 항상 TASK_RUNNING이어야 합니다.

GFP_NOIO
드라이버는 블록 I/O 처리 중에 사용되며 모든 저장소 유형에 대한 오류 처리 중에도 사용해야 합니다.

GFP_KERNEL
앞서 언급한 상황에 속하지 않는 기타 모든 상황

urb가 USB 코어에 성공적으로 제출된 후에는 최종 처리 루틴 함수가 호출될 때까지 urb 구조의 어떤 구성원에도 액세스할 수 없습니다

8.2 urb 종료 처리 루틴

usb_submit_urb가 성공적으로 호출되어 urb 제어권을 USB 코어로 전송하면 함수는 0을 반환합니다. 그렇지 않으면 음수 오류 코드가 반환됩니다. 함수가 성공적으로 호출되면 urb가 종료될 때 종료 핸들러 루틴이 한 번 호출됩니다. .이 함수가 호출되면 USB 코어가 urb를 완료하고 이에 대한 제어권을 장치 드라이버에 반환합니다.

UR을 종료하고 최종 처리 루틴을 호출하는 상황은 3가지뿐입니다.
(1)urb가 장치에 성공적으로 전송되고 장치는 올바른 확인을 반환합니다. 그렇다면 urb의 상태 변수는 0으로 설정됩니다.
(2) 오류가 발생하고 오류 값이 urb 구조의 상태 변수에 기록됩니다.
(3)USB 코어에서 URB 연결 해제는 드라이버가 usb_unlink_urb 또는 usb_kill_urb를 호출하여 제출된 UB를 취소하도록 USB 코어에 지시하거나 urb가 제출되고 장치가 시스템에서 제거될 때 발생합니다.

9. 감지 및 연결 해제

struct usb_driver 구조에는 USB 코어가 적절한 시점에 호출하는 2가지 함수가 있습니다.
(1) 장치가 연결되었을 때 USB 코어가 드라이버가 이를 처리할 수 있다고 생각하는 경우(USB 코어는 목록(제조업체 ID와 장치 번호 ID가 포함된 구조)을 사용하여 장치에 사용할 드라이버를 결정합니다) , 프로브 기능이 호출됩니다. 프로브 기능은 전달된 장치 정보를 확인하고 드라이버가 실제로 이 장치에 적합한지 확인합니다.
(2) 어떤 이유로 장치가 제거되거나 드라이버가 더 이상 장치를 제어하지 않는 경우 연결 해제 기능을 호출하고 적절한 정리를 수행합니다.

감지 및 연결 해제 콜백 함수는 모두 USB 허브 커널 스레드 컨텍스트에서 호출되므로 USB 감지 시간을 단축하기 위해 대부분의 작업은 장치가 켜져 있을 때 수행됩니다. 이는 USB 장치의 추가 및 제거가 스레드에서 처리되므로 장치 드라이버가 느리면 USB 장치 감지 시간이 길어질 수 있습니다.

9.1 감지 기능 분석
프로브 콜백 기능에서 USB 장치 드라이버는 USB 장치를 관리하는 데 사용할 수 있는 모든 로컬 구조를 초기화하고 필요한 모든 장치 정보를 로컬 구조에 저장해야 합니다. 일반적으로 이 시점에서 통신하는 것이 더 쉽기 때문입니다. USB 드라이버는 일반적으로 장치의 엔드포인트 주소와 버퍼 크기를 조사합니다.

이 글에서는 커널 드라이버 프레임워크, 커널 모듈 작성, 장치 드라이버 등록 및 등록 취소 등 Linux 커널 드라이버의 구현 방법을 자세히 소개합니다. 우리는 이 기사를 연구함으로써 독자들이 Linux 커널 드라이버의 구현 원리를 더 깊이 이해하고 자신의 개발 작업에 더 많은 참조와 도움을 제공할 수 있다고 믿습니다.

위 내용은 Linux USB 드라이버 작업 흐름에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 lxlinux.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제