Added HID documentation and added cfg(windows) to the relevant patterns.
This commit is contained in:
parent
7b4ebd5432
commit
0e4105b669
27
src/lib.rs
27
src/lib.rs
@ -147,19 +147,23 @@ pub enum SolidColor {
|
||||
/// A pattern the light can be set to show.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Pattern {
|
||||
/// A preset pattern
|
||||
/// A preset pattern that cycles between red and blue.
|
||||
Police,
|
||||
/// A preset pattern
|
||||
/// A preset pattern that cycles between green,. yellow, and red.
|
||||
TrafficLights,
|
||||
/// A preset pattern
|
||||
/// Preset random patterns
|
||||
Random(u8),
|
||||
/// A preset pattern (accepted on Windows only)
|
||||
/// A preset pattern
|
||||
#[cfg(target_os = "windows")]
|
||||
Rainbow,
|
||||
/// A preset pattern (accepted on Windows only)
|
||||
/// A preset pattern
|
||||
#[cfg(target_os = "windows")]
|
||||
Sea,
|
||||
/// A preset pattern (accepted on Windows only)
|
||||
/// A preset pattern
|
||||
#[cfg(target_os = "windows")]
|
||||
WhiteWave,
|
||||
/// A preset pattern (accepted on Windows only)
|
||||
/// A preset pattern
|
||||
#[cfg(target_os = "windows")]
|
||||
Synthetic,
|
||||
}
|
||||
|
||||
@ -254,9 +258,13 @@ impl Display for Pattern {
|
||||
Pattern::Police => "police".to_string(),
|
||||
Pattern::TrafficLights => "traffic lights".to_string(),
|
||||
Pattern::Random(n) => format!("random {}", n),
|
||||
#[cfg(target_os = "windows")]
|
||||
Pattern::Rainbow => "rainbow".to_string(),
|
||||
#[cfg(target_os = "windows")]
|
||||
Pattern::Sea => "sea".to_string(),
|
||||
#[cfg(target_os = "windows")]
|
||||
Pattern::WhiteWave => "white wave".to_string(),
|
||||
#[cfg(target_os = "windows")]
|
||||
Pattern::Synthetic => "synthetic".to_string(),
|
||||
}
|
||||
)
|
||||
@ -276,8 +284,13 @@ impl FromStr for Pattern {
|
||||
"random 3" => Ok(Pattern::Random(3)),
|
||||
"random 4" => Ok(Pattern::Random(4)),
|
||||
"random 5" => Ok(Pattern::Random(5)),
|
||||
#[cfg(target_os = "windows")]
|
||||
"rainbow" => Ok(Pattern::Rainbow),
|
||||
#[cfg(target_os = "windows")]
|
||||
"sea" => Ok(Pattern::Sea),
|
||||
#[cfg(target_os = "windows")]
|
||||
"white wave" => Ok(Pattern::WhiteWave),
|
||||
#[cfg(target_os = "windows")]
|
||||
"synthetic" => Ok(Pattern::Synthetic),
|
||||
_ => Err(error::ErrorKind::InvalidPattern.into()),
|
||||
}
|
||||
|
151
src/usb_hid.rs
151
src/usb_hid.rs
@ -1,5 +1,107 @@
|
||||
/*!
|
||||
Implementation of the Device trait for USB connected lights.
|
||||
|
||||
# Specification
|
||||
|
||||
The identifiers used to discover the device using the HID API are as follows:
|
||||
|
||||
1. The vendor identifier (VID) is `0x04D8`.
|
||||
1. The product identifier (PID) is `0xF372`.
|
||||
|
||||
The following command groups exist for controlling the lights. Note that byte 0, the USB HID _report
|
||||
identifier_, must always be set to `0x00`. Also, trailing `0x00` values need not be written.
|
||||
|
||||
| Command Group | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||
|----------------|--------|--------|--------|--------|--------|--------|--------|--------|--------|
|
||||
| Simple | `0x00` | `0x00` | COLOR* | `0x00` | `0x00` | `0x00` | `0x00` | `0x00` | `0x00` |
|
||||
| Solid | `0x00` | `0x01` | LED | RED | GREEN | BLUE | `0x00` | `0x00` | `0x00` |
|
||||
| Fade | `0x00` | `0x02` | LED | RED | GREEN | BLUE | TIME | `0x00` | `0x00` |
|
||||
| Strobe | `0x00` | `0x03` | LED | RED | GREEN | BLUE | SPEED | `0x00` | REPEAT |
|
||||
| Wave | `0x00` | `0x04` | WTYPE | RED | GREEN | BLUE | `0x00` | REPEAT | SPEED |
|
||||
| Pattern | `0x00` | `0x06` | PTYPE | REPEAT | `0x00` | `0x00` | `0x00` | `0x00` | `0x00` |
|
||||
| Productivity | `0x00` | `0x0A` | COLOR | `0x00` | `0x00` | `0x00` | `0x00` | `0x00` | `0x00` |
|
||||
| Get Ver/Serial | `0x00` | `0x80` | `0x00` | `0x00` | `0x00` | `0x00` | `0x00` | `0x00` | `0x00` |
|
||||
|
||||
## Notes
|
||||
|
||||
1. The values for LED, COLOR, WTYPE, and PTYPE, are shown in the corresponding tables below.
|
||||
1. The values for RED, GREEN, BLUE, are `0..255` and correspond to standard RGB color.
|
||||
1. The value for TIME is the number of seconds to fade from the current color to the new color specified.
|
||||
1. The value for SPEED is the time to cycle through the change.
|
||||
1. The value of REPEAT is the number of times to repeat the wave or pattern.
|
||||
1. The response data for the get version and serial number command group is described below.
|
||||
|
||||
## LED values
|
||||
|
||||
| Value | Addressed LED |
|
||||
|--------------|--------------------|
|
||||
| `0x01..0x06` | Specific LED |
|
||||
| `0x41` | all back LEDs |
|
||||
| `0x42` | all front LEDs |
|
||||
| `0xFF` | all LEDs one color |
|
||||
|
||||
The addressable LEDs on the _Flag_ USB product are as follows, shown in vertical orientation:
|
||||
|
||||
| Back | Front |
|
||||
|------|-------|
|
||||
| 6 | 3 |
|
||||
| 5 | 2 |
|
||||
| 4 | 1 |
|
||||
|
||||
## COLOR values
|
||||
|
||||
1. For the command group _Productivity_ all the values below are valid.
|
||||
1. For the command group _Simple_ the values 'E' and 'D' are not valid.
|
||||
|
||||
| Letter | Value | Color |
|
||||
|--------|--------|-----------|
|
||||
| 'E' | `0x45` | _Enable_ |
|
||||
| 'D' | `0x44` | _Disable_ |
|
||||
| 'R' | `0x52` | Red |
|
||||
| 'G' | `0x47` | Green |
|
||||
| 'B' | `0x42` | Blue |
|
||||
| 'C' | `0x43` | Cyan |
|
||||
| 'M' | `0x4D` | Magenta |
|
||||
| 'Y' | `0x59` | Yellow |
|
||||
| 'W' | `0x57` | White |
|
||||
| 'O' | `0x4F` | Off |
|
||||
|
||||
## WTYPE values
|
||||
|
||||
| Value | Pattern |
|
||||
|--------|--------------------|
|
||||
| `0x01` | Short |
|
||||
| `0x02` | Long |
|
||||
| `0x03` | Overlapping Short |
|
||||
| `0x04` | Overlapping Long |
|
||||
| `0x05` | ? |
|
||||
|
||||
1. Luxafor describe wave type as a value `0x01..0x05` and yet there seems to be no description of `0x05` anywhere.
|
||||
|
||||
## PTYPE values
|
||||
|
||||
| Value | Pattern | Windows Only |
|
||||
|--------|--------------|--------------|
|
||||
| `0x00` | ? | Unknown |
|
||||
| `0x01` | Luxafor/Traffic Lights | No |
|
||||
| `0x02` | Random 1 | No |
|
||||
| `0x03` | Random 2 | No |
|
||||
| `0x04` | Random 3 | No |
|
||||
| `0x05` | Police | No |
|
||||
| `0x06` | Random 4 | No |
|
||||
| `0x07` | Random 5 | No |
|
||||
| `0x08` | Rainbow Wave | Yes |
|
||||
|
||||
1. Luxafor describe pattern type as a value `0x00..0x08` and yet there seems to be no description of `0x00` anywhere.
|
||||
|
||||
## Version/Serial response
|
||||
|
||||
| 0 | 1 | 2 | 3 |
|
||||
|--------|------------|-------------|------------|
|
||||
| `0x80` | FW Version | Serial High | Serial Low |
|
||||
|
||||
The serial number is returned as a pair, (high,low) bytes.
|
||||
|
||||
*/
|
||||
|
||||
use crate::{Device, Pattern, SolidColor};
|
||||
@ -33,6 +135,8 @@ pub struct USBDevice<'a> {
|
||||
const LUXAFOR_VENDOR_ID: u16 = 0x04d8;
|
||||
const LUXAFOR_PRODUCT_ID: u16 = 0xf372;
|
||||
|
||||
const HID_REPORT_ID: u8 = 0;
|
||||
|
||||
const MODE_SOLID: u8 = 1;
|
||||
#[allow(dead_code)]
|
||||
const MODE_FADE: u8 = 2;
|
||||
@ -66,6 +170,7 @@ const PATTERN_RANDOM_3: u8 = 4;
|
||||
const PATTERN_RANDOM_4: u8 = 6;
|
||||
const PATTERN_RANDOM_5: u8 = 7;
|
||||
const PATTERN_POLICE: u8 = 5;
|
||||
#[cfg(target_os = "windows")]
|
||||
const PATTERN_RAINBOW_WAVE: u8 = 8;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -132,14 +237,7 @@ impl<'a> Device for USBDevice<'a> {
|
||||
};
|
||||
let mode = if blink { MODE_STROBE } else { MODE_SOLID };
|
||||
trace!("{} ({:#04x},{:#04x},{:#04x})", mode, r, g, b);
|
||||
let result = self.hid_device.write(&[mode, LED_ALL, r, g, b]);
|
||||
match result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(err) => {
|
||||
error!("Could not write to HID device: {:?}", err);
|
||||
Err(crate::error::ErrorKind::InvalidRequest.into())
|
||||
}
|
||||
}
|
||||
self.write(&[HID_REPORT_ID, mode, LED_ALL, r, g, b])
|
||||
}
|
||||
|
||||
fn set_pattern(&self, pattern: Pattern) -> crate::error::Result<()> {
|
||||
@ -154,19 +252,16 @@ impl<'a> Device for USBDevice<'a> {
|
||||
4 => PATTERN_RANDOM_4,
|
||||
_ => PATTERN_RANDOM_5,
|
||||
},
|
||||
#[cfg(target_os = "windows")]
|
||||
Pattern::Rainbow => PATTERN_RAINBOW_WAVE,
|
||||
#[cfg(target_os = "windows")]
|
||||
Pattern::Sea => 9,
|
||||
#[cfg(target_os = "windows")]
|
||||
Pattern::WhiteWave => 10,
|
||||
#[cfg(target_os = "windows")]
|
||||
Pattern::Synthetic => 11,
|
||||
};
|
||||
let result = self.hid_device.write(&[MODE_PATTERN, LED_ALL, pattern]);
|
||||
match result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(err) => {
|
||||
error!("Could not write to HID device: {:?}", err);
|
||||
Err(crate::error::ErrorKind::InvalidRequest.into())
|
||||
}
|
||||
}
|
||||
self.write(&[HID_REPORT_ID, MODE_PATTERN, pattern, 255])
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,6 +281,30 @@ impl<'a> USBDevice<'a> {
|
||||
);
|
||||
Ok(Self { hid_device, id })
|
||||
}
|
||||
|
||||
fn write(&self, buffer: &[u8]) -> crate::error::Result<()> {
|
||||
trace!(
|
||||
"writing [{:?}]",
|
||||
buffer
|
||||
.iter()
|
||||
.map(|b| format!("{:#04x}", b))
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ")
|
||||
);
|
||||
let result = self.hid_device.write(buffer);
|
||||
match result {
|
||||
Ok(bytes_written) => if bytes_written == buffer.len() {
|
||||
Ok(())
|
||||
} else {
|
||||
error!("Bytes written, {}, did not match buffer length {}", bytes_written, buffer.len());
|
||||
Err(crate::error::ErrorKind::InvalidRequest.into())
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Could not write to HID device: {:?}", err);
|
||||
Err(crate::error::ErrorKind::InvalidRequest.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user