USB 장치에 원시 데이터를 쓰는 방법

USB 장치에 원시 데이터를 쓰는 방법

내 컴퓨터에 연결된 USB 장치에 원시 데이터를 쓰려고 합니다. 저는 Kali Linux를 사용하고 있으며 올바른 파일 경로를 찾았습니다: "/dev/usb/003/013" . 그런데 데이터를 쓰려고 하면 오류가 발생합니다.

root@kali:~/usb# printf "test" > /dev/bus/usb/003/013
bash: printf: write error: Invalid argument

나는 또한 cat을 사용해 보았습니다.

root@kali:~/usb# cat test > /dev/bus/usb/003/013 
cat: write error: Invalid argument

전자의 경우 "test" 파일이 존재하며 데이터를 포함합니다. 파일 설명자가 있는데도 시스템이 파일 설명자에 쓸 수 없는 것 같습니다.

연구 끝에 나는 다음과 같은 결론에 도달했습니다.

A. 장치에 연결하려면 USB 드라이버가 필요합니다.

B. SCSI 패스스루를 사용하여 장치의 엔드포인트에 직접 데이터를 씁니다.

저는 USB 프로그래밍이 처음이고 시도해 보고 싶지만 이전에 드라이버를 작성한 적이 없습니다. 어떤 조언이나 도움이라도 대단히 감사하겠습니다.

원래 시도했던 것처럼 원시 데이터를 장치에 쓰는 것이 가능합니까? 그렇지 않다면 제가 사용할 수 있는 몇 가지 옵션을 설명해 주실 수 있나요?

답변1

USB 장치는 단순한 읽기 및 쓰기 파이프보다 훨씬 더 복잡합니다. 이를 작동하려면 코드를 작성해야 합니다. (아마도) 커널 드라이버를 작성할 필요는 없습니다. 바라보다http://libusb.info(옛 libusb.org) 및http://libusb.sourceforge.net/api-1.0. Linux, OSX, Windows, Android, OpenBSD 등에서 작동한다고 주장합니다. Mac OS X에는 사용자 수준 기능이 있습니다.입력/출력 키트이렇게 하면 USB에 액세스할 수 있습니다. Windows에서는 WinUSB를 사용할 수 있지만 복잡합니다.

이것은 USB 아키텍처를 이해하는 데 도움을 주기 위해 제가 그린 작은 다이어그램입니다.

                 ╭────────────────────────────────────╮
    ┌──────┐     │   device     ┌─────┐  ┌─────────┐  │
    │ Port ├──┐  │            ┌─┤ EP0 ├──┤ control │  │
    └──────┘  │  │ ┌────────┐ │ └─────┘  ├─────────┤  │
              ├────┤addr = 2├─┤ ┌─────┐  │         │  │
              │  │ └────────┘ ├─┤ EP1 ├──┤interface│  │
              │  │            │ └─────┘  │   #0    │  │
              │  │            │ ┌─────┐  ├─────────┤  │
              │  │            ├─┤ EP2 ├──┤         │  │
              │  │            │ └─────┘  │interface│  │
              │  │            │ ┌─────┐  │   #1    │  │
              │  │            └─┤ EP3 ├──┤         │  │
              │  │              └─────┘  └─────────┘  │
              │  ╰────────────────────────────────────╯
              :

요약: 각 장치에는 주소(운영 체제에 의해 할당되고 변경될 수 있음)와 최대 32개의 엔드포인트가 있습니다.

장치에는 하나 이상의 "인터페이스"가 있습니다. 예를 들어 웹캠은 "카메라" 포트와 "마이크" 포트를 제공할 수 있습니다. 다기능 프린터는 여러 인터페이스를 제공합니다.

엔드포인트 0은 장치 제어 및 구성에 사용되며, 다른 엔드포인트는 다양한 인터페이스에 액세스하는 데 사용됩니다. 각 인터페이스에는 0개 이상의(보통 더 많은) 엔드포인트가 있습니다.

엔드포인트는 여러 전송 유형 중 하나일 수 있습니다.

  • 제어 전송은 장치를 쿼리하고 구성하는 데 사용됩니다. 각 장치는 최소한의 제어문 세트를 지원해야 합니다. 나는 제어 전송이 끝점 0에만 해당된다고 생각합니다.
  • 대량 전송은 전체 대역폭에서 데이터를 보내거나 받습니다.
  • 인터럽트 전송(대량 전송과 어떻게 다른지 잘 모르겠습니다. USB는 인터럽트를 수행하지 않습니다). 예로는 키보드와 마우스가 있습니다.
  • 등시성 전송은 전체 대역폭에서 데이터를 전송하거나 수신하므로 실시간 요구 사항이 있지만 신뢰성이 부족합니다. 오디오/비디오 애플리케이션용.

또한 주목할 만한 점은 USB 장치에는 사용 가능한 인터페이스 등을 제어하는 ​​여러 구성이 있을 수 있다는 것입니다. 장치 구성을 변경하는 것은 장치의 플러그를 뽑고 그 자리에 다른 장치를 연결하는 것과 거의 같습니다.

이 모든 정보는 장치 설명자, 구성 설명자, 인터페이스 설명자, 엔드포인트 설명자 등에 배치되며 엔드포인트 0을 통해 쿼리할 수 있습니다.

(내부적으로 데이터는 바이트 스트림이 아니며 패킷으로 패키지되어 있으며 정확한 형식은 USB 사양의 일부입니다. 대부분의 경우 컨트롤러와 드라이버가 이에 대해 걱정할 필요가 없습니다. 이 부분을 관리하세요.)

실제로는 API 라이브러리와 OS에 따라 장치를 감지하고, 다양한 설명자를 읽어 현재 다루고 있는 내용을 파악하고, 선택적으로 구성을 설정하고(OS에서 허용하는 경우) 인터페이스를 열어야 합니다. 끝점을 엽니다.

배치 엔드포인트의 경우 원시 데이터를 읽고 쓸 수 있습니다. 제어 전송을 위해 API 라이브러리는 함수 호출을 제공합니다. 나는 인터럽트나 동기 전송을 사용한 적이 없습니다. API 라이브러리에 이에 대한 문서가 있을 것이라고 확신합니다.


추가 정보: "함수"는 함께 작동하는 인터페이스 모음입니다. 이는 원래 USB 사양의 일부가 아니었기 때문에 어떤 인터페이스를 함께 그룹화해야 하는지 결정하는 것은 장치 드라이버에 맡겼습니다. USB 작업 그룹은 기능을 지원하는 장치 클래스를 정의합니다. 이는 IAD(인터페이스 연결 설명자)를 통해 수행됩니다.

관련 정보