1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use libusb::{Context, Device, DeviceHandle, request_type, Direction, RequestType, Recipient};
use std::fmt;
use std::time::Duration;
pub use color::Color;
use constants::{HID_SET_REPORT, HID_FEATURE, PRODUCT_ID, VENDOR_ID};
pub use error::BlinkError;
pub use message::Message;
mod color;
mod constants;
mod error;
mod message;
fn is_blinker(device: &Device) -> bool {
if let Ok(desc) = device.device_descriptor() {
return desc.num_configurations() > 0 && desc.product_id() == PRODUCT_ID && desc.vendor_id() == VENDOR_ID;
}
false
}
fn send(device: &Device, message: &Message) -> Result<usize, BlinkError> {
let config = device.active_config_descriptor()?;
let mut handle: DeviceHandle = device.open()?;
let interface_num = config.interfaces().nth(0).ok_or(BlinkError::NotFound)?.number();
if let Ok(active) = handle.kernel_driver_active(interface_num) {
if active {
handle.detach_kernel_driver(interface_num)?;
}
}
handle.claim_interface(interface_num)?;
let buffer = message.buffer();
let time = Duration::new(0, 100);
let r_type = request_type(Direction::Out, RequestType::Class, Recipient::Interface);
let request_value: u16 = HID_FEATURE | (buffer[0] as u16);
let out = handle.write_control(r_type, HID_SET_REPORT, request_value, 0x00, &buffer, time);
handle.release_interface(interface_num)?;
out.map_err(|e| BlinkError::from(e))
}
pub struct Blinkers {
context: Context,
}
impl fmt::Debug for Blinkers {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Blinkers {{ }}")
}
}
impl Blinkers {
fn from_context(ctx: Context) -> Self {
Blinkers { context: ctx }
}
pub fn new() -> Result<Self, BlinkError> {
let context: Context = Context::new()?;
Ok(Blinkers::from_context(context))
}
pub fn send(&self, cmd: Message) -> Result<usize, BlinkError> {
let devices = self.context.devices()?;
devices
.iter()
.filter(is_blinker)
.map(|d| send(&d, &cmd))
.collect::<Result<Vec<usize>, BlinkError>>().map(|d| d.iter().sum())
}
pub fn device_count(&self) -> Result<usize, BlinkError> {
let devices = self.context.devices()?;
Ok(devices.iter().filter(is_blinker).count())
}
}