MCPcopy Index your code
hub / github.com/faassen/rust-it8951

github.com/faassen/rust-it8951 @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
32 symbols 59 edges 3 files 10 documented · 31%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

USB IT8951 epaper driver Rust

Waveshare sells a range of epaper displays, some of which ship with a IT8951 display HAT. This IT8951 can be controlled via SPI (typically through a Raspberry Pi) but also through USB, which I was interested in so I could control it with my Linux desktop.

Thankfully, a large part of the problem had already been solved by Martijn Braam in C, and his solution inspired mine. One drawback of Martijn Braam's solution is that it requires root access as it uses a specific Linux ioctl command to send data to the epaper display.

Martijn Braam links to a IT8951 USB Programming Guide which gave me the clue that it should be possible to do this directly over USB without root access. After quite some digging I've implemented a working solution in Rust.

Preparation

In order to make this work you need to create a udev rule that gives users permission to talk to this device. To this end add a file 60-it8951.rules to the /etc/udev/rules.d/etc/udev/rules.d directory with the following contents:

SUBSYSTEM=="usb", ATTRS{idVendor}=="048d", MODE="0666"

This gives applications access to talk to devices by vendor "048d", which is the IT8951. You can then restart your system, or by write this to trigger without reboot:

udevadm control --reload-rules && udevadm trigger

Custom SCSI commands over SCSI over USB

The IT8951 implements custom SCSI commands to control the epaper display. Normally SCSI is a disk protocol, but with these custom commands it can be extended to arbitrary new commands. It's possible to send SCSI commands over USB: you need to wrap them in a Command Block Wrapper and Command Status Wrapper. Unlike the ioctl which can be used to talk to SCSI directly, USB may be controlled by users, which is how this code works without requiring root access.

Core symbols most depended-on inside this repo

get_command_block_wrapper
called by 5
src/usb.rs
get_system_info
called by 3
src/lib.rs
write_command_no_data
called by 3
src/usb.rs
send_status_block_wrapper
called by 3
src/usb.rs
read_command
called by 2
src/usb.rs
write_command
called by 2
src/usb.rs
open_it8951
called by 1
src/lib.rs
inquiry
called by 1
src/lib.rs

Shape

Method 17
Class 9
Function 4
Enum 2

Languages

Rust100%

Modules by API surface

src/lib.rs21 symbols
src/usb.rs10 symbols
examples/simple.rs1 symbols

For agents

$ claude mcp add rust-it8951 \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact