pyreworks_g560_driver/
raw.rs

1use nusb::Interface;
2use nusb::transfer::{ControlOut, ControlType, Recipient};
3use thiserror::Error;
4
5pub const VENDOR_ID: u16 = 0x046d;
6pub const PRODUCT_ID: u16 = 0x0a78;
7
8pub fn detach_and_claim_interface() -> Result<Interface, ClaimInterfaceError> {
9    let device = nusb::list_devices()?
10        .find(|dev| dev.vendor_id() == VENDOR_ID && dev.product_id() == PRODUCT_ID)
11            .ok_or(ClaimInterfaceError::InterfaceNotFound)?
12        .open()?;
13
14    Ok(device.detach_and_claim_interface(0x02)?)
15}
16
17#[derive(Error, Debug)]
18pub enum ClaimInterfaceError {
19    #[error("could not find \"g560\" device with vendor_id {0} and product_id {1}", VENDOR_ID, PRODUCT_ID)]
20    InterfaceNotFound,
21    #[error("could not open \"g560\" device")]
22    InterfaceClaimFailed(#[from] nusb::Error),
23}
24
25pub async fn send_raw_command(
26    interface: &Interface,
27    value: &[u8; 10]
28)
29-> Result<(), SendCommandError>
30{
31    let prefix = [0x11, 0xff, 0x04, 0x3a];
32    let suffix = [0x00; 6];
33
34    let mut data = Vec::with_capacity(20);
35    data.extend_from_slice(&prefix);
36    data.extend_from_slice(value);
37    data.extend_from_slice(&suffix);
38    
39    let control_out = ControlOut {
40        recipient: Recipient::Interface,
41        control_type: ControlType::Class,
42        request: 0x09,
43        value: 0x0211,
44        index: 0x02,
45        data: &data,
46    };
47
48    interface.control_out(control_out).await.into_result()?;
49
50    Ok(())
51}
52
53#[derive(Error, Debug)]
54pub enum SendCommandError {
55    #[error("control out failed")]
56    ControlOutFailed(#[from] nusb::transfer::TransferError),
57}