usbhidd: use rehid ReportHandler
This commit is contained in:
Generated
+2
-1
@@ -1140,9 +1140,10 @@ checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb"
|
||||
[[package]]
|
||||
name = "rehid"
|
||||
version = "0.1.0"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/rehid.git#9bf6c9ef7cc4f95932fcaabfa3141a24bfd39bbf"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/rehid.git#d3c74a8abbdb75d93260883e3378c46b3e875fa9"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"log",
|
||||
"ux",
|
||||
]
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ pub mod us {
|
||||
['\0', '\0'],
|
||||
['\0', '\0'],
|
||||
['\0', '\0'],
|
||||
[' ', ' ']
|
||||
[' ', ' '],
|
||||
];
|
||||
|
||||
pub fn get_char(scancode: u8, shift: bool) -> char {
|
||||
@@ -236,7 +236,7 @@ pub mod dvorak {
|
||||
['\0', '\0'],
|
||||
['\0', '\0'],
|
||||
['\0', '\0'],
|
||||
[' ', ' ']
|
||||
[' ', ' '],
|
||||
];
|
||||
|
||||
pub fn get_char(scancode: u8, shift: bool) -> char {
|
||||
@@ -311,7 +311,7 @@ pub mod azerty {
|
||||
['\0', '\0'],
|
||||
['\0', '\0'],
|
||||
['\0', '\0'],
|
||||
[' ', ' ']
|
||||
[' ', ' '],
|
||||
];
|
||||
|
||||
pub fn get_char(scancode: u8, shift: bool) -> char {
|
||||
@@ -386,7 +386,7 @@ pub mod bepo {
|
||||
['\0', '\0'],
|
||||
['\0', '\0'],
|
||||
['\0', '\0'],
|
||||
[' ', ' ']
|
||||
[' ', ' '],
|
||||
];
|
||||
|
||||
pub fn get_char(scancode: u8, shift: bool) -> char {
|
||||
@@ -461,7 +461,7 @@ pub mod it {
|
||||
['\0', '\0'],
|
||||
['\0', '\0'],
|
||||
['\0', '\0'],
|
||||
[' ', ' ']
|
||||
[' ', ' '],
|
||||
];
|
||||
|
||||
pub fn get_char(scancode: u8, shift: bool) -> char {
|
||||
|
||||
+168
-293
@@ -2,52 +2,51 @@ use std::collections::VecDeque;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use orbclient::KeyEvent as OrbKeyEvent;
|
||||
use redox_log::{OutputBuilder, RedoxLogger};
|
||||
use rehid::{binary_view::BinaryView, report_desc::{self, ReportTy}, usage_tables};
|
||||
use rehid::{
|
||||
report_desc::{self, ReportTy, REPORT_DESC_TY},
|
||||
report_handler::ReportHandler,
|
||||
usage_tables::{GenericDesktopUsage, UsagePage},
|
||||
};
|
||||
use xhcid_interface::{ConfigureEndpointsReq, DevDesc, PortReqRecipient, XhciClientHandle};
|
||||
|
||||
mod keymap;
|
||||
mod reqs;
|
||||
|
||||
use report_desc::{LocalItemsState, MainCollectionFlags, MainItem, MainItemFlags, GlobalItemsState, ReportFlatIter, ReportItem, ReportIter, ReportIterItem, REPORT_DESC_TY};
|
||||
|
||||
fn div_round_up(num: u32, denom: u32) -> u32 {
|
||||
if num % denom == 0 { num / denom } else { num / denom + 1 }
|
||||
}
|
||||
|
||||
fn setup_logging() -> Option<&'static RedoxLogger> {
|
||||
let mut logger = RedoxLogger::new()
|
||||
.with_output(
|
||||
OutputBuilder::stderr()
|
||||
.with_filter(log::LevelFilter::Info) // limit global output to important info
|
||||
.with_ansi_escape_codes()
|
||||
.flush_on_newline(true)
|
||||
.build()
|
||||
);
|
||||
let mut logger = RedoxLogger::new().with_output(
|
||||
OutputBuilder::stderr()
|
||||
.with_filter(log::LevelFilter::Info) // limit global output to important info
|
||||
.with_ansi_escape_codes()
|
||||
.flush_on_newline(true)
|
||||
.build(),
|
||||
);
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
match OutputBuilder::in_redox_logging_scheme("usb", "device", "hid.log") {
|
||||
Ok(b) => logger = logger.with_output(
|
||||
// TODO: Add a configuration file for this
|
||||
b.with_filter(log::LevelFilter::Info)
|
||||
.flush_on_newline(true)
|
||||
.build()
|
||||
),
|
||||
Ok(b) => {
|
||||
logger = logger.with_output(
|
||||
// TODO: Add a configuration file for this
|
||||
b.with_filter(log::LevelFilter::Info)
|
||||
.flush_on_newline(true)
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
Err(error) => eprintln!("Failed to create hid.log: {}", error),
|
||||
}
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
match OutputBuilder::in_redox_logging_scheme("usb", "device", "hid.ansi.log") {
|
||||
Ok(b) => logger = logger.with_output(
|
||||
b.with_filter(log::LevelFilter::Info)
|
||||
.with_ansi_escape_codes()
|
||||
.flush_on_newline(true)
|
||||
.build()
|
||||
),
|
||||
Ok(b) => {
|
||||
logger = logger.with_output(
|
||||
b.with_filter(log::LevelFilter::Info)
|
||||
.with_ansi_escape_codes()
|
||||
.flush_on_newline(true)
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
Err(error) => eprintln!("Failed to create hid.ansi.log: {}", error),
|
||||
}
|
||||
|
||||
@@ -63,7 +62,13 @@ fn setup_logging() -> Option<&'static RedoxLogger> {
|
||||
}
|
||||
}
|
||||
|
||||
fn send_key_event(display: &mut File, usage_page: u32, usage: u8, pressed: bool, shift_opt: Option<bool>) {
|
||||
fn send_key_event(
|
||||
display: &mut File,
|
||||
usage_page: u32,
|
||||
usage: u32,
|
||||
pressed: bool,
|
||||
shift_opt: Option<bool>,
|
||||
) {
|
||||
let scancode = match usage_page {
|
||||
0x07 => match usage {
|
||||
0x04 => orbclient::K_A,
|
||||
@@ -170,7 +175,7 @@ fn send_key_event(display: &mut File, usage_page: u32, usage: u8, pressed: bool,
|
||||
0xE0 => orbclient::K_CTRL, // TODO: left control
|
||||
0xE1 => orbclient::K_LEFT_SHIFT,
|
||||
0xE2 => orbclient::K_ALT,
|
||||
0xE3 => 0x5B, // left super
|
||||
0xE3 => 0x5B, // left super
|
||||
0xE4 => orbclient::K_CTRL, // TODO: right control
|
||||
0xE5 => orbclient::K_RIGHT_SHIFT,
|
||||
0xE6 => orbclient::K_ALT_GR,
|
||||
@@ -179,12 +184,12 @@ fn send_key_event(display: &mut File, usage_page: u32, usage: u8, pressed: bool,
|
||||
_ => {
|
||||
log::warn!("unknown usage_page {:#x} usage {:#x}", usage_page, usage);
|
||||
return;
|
||||
},
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
log::warn!("unknown usage_page {:#x}", usage_page);
|
||||
return;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
//TODO: other keymaps
|
||||
@@ -225,7 +230,9 @@ fn main() {
|
||||
|
||||
log::info!(
|
||||
"USB HID driver spawned with scheme `{}`, port {}, protocol {}",
|
||||
scheme, port, protocol
|
||||
scheme,
|
||||
port,
|
||||
protocol
|
||||
);
|
||||
|
||||
let handle = XhciClientHandle::new(scheme, port);
|
||||
@@ -251,292 +258,160 @@ fn main() {
|
||||
)
|
||||
.expect("Failed to retrieve report descriptor");
|
||||
|
||||
let report_desc = ReportIter::new(ReportFlatIter::new(&report_desc_bytes)).collect::<Vec<_>>();
|
||||
let mut handler =
|
||||
ReportHandler::new(&report_desc_bytes).expect("failed to parse report descriptor");
|
||||
|
||||
for item in &report_desc {
|
||||
log::debug!("{:?}", item);
|
||||
}
|
||||
|
||||
handle.configure_endpoints(&ConfigureEndpointsReq { config_desc: 0, interface_desc: None, alternate_setting: None }).expect("Failed to configure endpoints");
|
||||
|
||||
let (mut global_state, mut local_state, mut stack) = (GlobalItemsState::default(), LocalItemsState::default(), Vec::new());
|
||||
|
||||
let (_, application_collection, application_global_state, application_local_state) = report_desc.iter().filter_map(|item: &ReportIterItem| {
|
||||
log::trace!("1: {:?}", item);
|
||||
match item {
|
||||
&ReportIterItem::Item(ref item) => {
|
||||
report_desc::update_global_state(&mut global_state, &mut stack, item).unwrap();
|
||||
report_desc::update_local_state(&mut local_state, item);
|
||||
None
|
||||
}
|
||||
&ReportIterItem::Collection(n, ref collection) => {
|
||||
let lc_state = std::mem::replace(&mut local_state, LocalItemsState::default());
|
||||
Some((n, collection, global_state, lc_state))
|
||||
}
|
||||
}
|
||||
}).find(|&(n, _, _, _)| n == MainCollectionFlags::Application as u8).expect("Failed to find application collection");
|
||||
handle
|
||||
.configure_endpoints(&ConfigureEndpointsReq {
|
||||
config_desc: 0,
|
||||
interface_desc: None,
|
||||
alternate_setting: None,
|
||||
})
|
||||
.expect("Failed to configure endpoints");
|
||||
|
||||
// Get all main items, and their global item options.
|
||||
{
|
||||
let mut collections = VecDeque::new();
|
||||
collections.push_back(application_collection);
|
||||
let mut items = Vec::new();
|
||||
while let Some(collection) = collections.pop_front() {
|
||||
for item in collection {
|
||||
log::trace!("2: {:?}", item);
|
||||
match item {
|
||||
ReportIterItem::Item(item) => match item {
|
||||
ReportItem::Global(_) => {
|
||||
report_desc::update_global_state(&mut global_state, &mut stack, item).unwrap();
|
||||
}
|
||||
ReportItem::Main(m) => {
|
||||
let lc_state = std::mem::replace(&mut local_state, LocalItemsState::default());
|
||||
items.push((global_state, lc_state, m));
|
||||
}
|
||||
ReportItem::Local(_) => {
|
||||
report_desc::update_local_state(&mut local_state, item);
|
||||
},
|
||||
},
|
||||
//TODO: does local state need to be different for inner collections?
|
||||
ReportIterItem::Collection(_, collection) => {
|
||||
collections.push_back(collection);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut bit_offset = 0;
|
||||
let inputs = items.iter().filter_map(|(global_state, local_state, item)| {
|
||||
log::trace!("3: {:?}", item);
|
||||
|
||||
if let &MainItem::Input(flags) = item {
|
||||
let report_size = match global_state.report_size {
|
||||
Some(s) => s,
|
||||
None => return None,
|
||||
};
|
||||
let report_count = match global_state.report_count {
|
||||
Some(c) => c,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
let bit_length = report_size * report_count;
|
||||
let offset = bit_offset;
|
||||
bit_offset += bit_length;
|
||||
|
||||
Some((bit_length, offset, global_state, local_state, MainItemFlags::from_bits_truncate(*flags)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
let total_bit_length = inputs.iter().map(|(bit_length, _, _, _, _)| bit_length).sum();
|
||||
|
||||
let total_byte_length = div_round_up(total_bit_length, 8);
|
||||
|
||||
let mut report_buffer = vec! [0u8; total_byte_length as usize];
|
||||
let mut last_buffer = report_buffer.clone();
|
||||
let mut report_buffer = vec![0u8; handler.total_byte_length];
|
||||
let report_ty = ReportTy::Input;
|
||||
let report_id = 0;
|
||||
|
||||
let mut display = File::open("input:producer").expect("Failed to open orbital input socket");
|
||||
|
||||
let mut pressed_keys = Vec::<(u32, u8)>::new();
|
||||
let mut last_pressed_keys = pressed_keys.clone();
|
||||
let mut last_buttons = (false, false, false);
|
||||
|
||||
let mut display =
|
||||
File::open("input:producer").expect("Failed to open orbital input socket");
|
||||
let mut left_shift = false;
|
||||
let mut right_shift = false;
|
||||
let mut last_mouse_pos = (0, 0);
|
||||
let mut last_buttons = [false, false, false];
|
||||
loop {
|
||||
//TODO: get frequency from device
|
||||
std::thread::sleep(std::time::Duration::from_millis(10));
|
||||
|
||||
std::mem::swap(&mut report_buffer, &mut last_buffer);
|
||||
reqs::get_report(&handle, report_ty, report_id, interface_num, &mut report_buffer).expect("Failed to get report");
|
||||
reqs::get_report(
|
||||
&handle,
|
||||
report_ty,
|
||||
report_id,
|
||||
interface_num,
|
||||
&mut report_buffer,
|
||||
)
|
||||
.expect("Failed to get report");
|
||||
|
||||
if report_buffer == last_buffer {
|
||||
continue
|
||||
}
|
||||
|
||||
for &(bit_length, bit_offset, global_state, local_state, input) in &inputs {
|
||||
let report_size = global_state.report_size.unwrap();
|
||||
let report_count = global_state.report_count.unwrap();
|
||||
|
||||
log::trace!(
|
||||
"size {} count {} offset {} length {} usage page {:?}",
|
||||
report_size,
|
||||
report_count,
|
||||
bit_offset,
|
||||
bit_length,
|
||||
global_state.usage_page
|
||||
);
|
||||
|
||||
// TODO: For now, the dynamic value usages cannot overlap with selector usages...
|
||||
// for now.
|
||||
|
||||
if local_state.usage_min == Some(224) && local_state.usage_max == Some(231) {
|
||||
// The usages that this descriptor references are all dynamic values.
|
||||
} else {
|
||||
// The usages are selectors.
|
||||
}
|
||||
|
||||
if input.contains(MainItemFlags::VARIABLE) {
|
||||
// The item is a variable.
|
||||
|
||||
let binary_view = BinaryView::new(&report_buffer, bit_offset as usize, bit_length as usize);
|
||||
|
||||
if report_count == 8 && report_size == 1 && global_state.usage_page == Some(7) && local_state.usage_min == Some(224) && local_state.usage_max == Some(231) && global_state.logical_min == Some(0) && global_state.logical_max == Some(1) {
|
||||
let bits = binary_view.read_u8(0).expect("Failed to read array item");
|
||||
for bit in 0..8 {
|
||||
if bits & (1 << bit) > 0 {
|
||||
pressed_keys.push((0x07, 0xE0 + bit));
|
||||
}
|
||||
let mut mouse_pos = last_mouse_pos;
|
||||
let mut mouse_dx = 0i32;
|
||||
let mut mouse_dy = 0i32;
|
||||
let mut buttons = last_buttons;
|
||||
for event in handler
|
||||
.handle(&report_buffer)
|
||||
.expect("failed to parse report")
|
||||
{
|
||||
log::debug!("{:X?}", event);
|
||||
if event.usage_page == UsagePage::GenericDesktop as u32 {
|
||||
if event.usage == GenericDesktopUsage::X as u32 {
|
||||
if event.relative {
|
||||
mouse_dx += event.value;
|
||||
} else {
|
||||
mouse_pos.0 = event.value;
|
||||
}
|
||||
log::trace!("Report variable {:#x?}", bits);
|
||||
} else if report_count == 2 && report_size == 16 && global_state.usage_page == Some(1) {
|
||||
//TODO: Make this less hard-coded
|
||||
let raw_x =
|
||||
binary_view.read_u8(0).expect("Failed to read array item") as u16 |
|
||||
(binary_view.read_u8(8).expect("Failed to read array item") as u16) << 8;
|
||||
let raw_y =
|
||||
binary_view.read_u8(16).expect("Failed to read array item") as u16 |
|
||||
(binary_view.read_u8(24).expect("Failed to read array item") as u16) << 8;
|
||||
|
||||
// ps2d uses 0..=65535 as range, while usb uses 0..=32767. orbital
|
||||
// expects the former range, so multiply by two here to translate
|
||||
// the usb coordinates to what orbital expects.
|
||||
let x = raw_x * 2;
|
||||
let y = raw_y * 2;
|
||||
|
||||
log::trace!("Touchscreen {}, {} => {}, {}", raw_x, raw_y, x, y);
|
||||
if x != 0 || y != 0 {
|
||||
let mouse_event = orbclient::event::MouseEvent {
|
||||
x: x as i32,
|
||||
y: y as i32,
|
||||
};
|
||||
|
||||
match display.write(&mouse_event.to_event()) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
log::warn!("failed to send mouse event to orbital: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if report_count == 3 && report_size == 8 && global_state.usage_page == Some(1) {
|
||||
//TODO: Make this less hard-coded
|
||||
let dx = binary_view.read_u8(0).expect("Failed to read array item") as i8;
|
||||
let dy = binary_view.read_u8(8).expect("Failed to read array item") as i8;
|
||||
let dz = binary_view.read_u8(16).expect("Failed to read array item") as i8;
|
||||
log::trace!("Mouse {}, {}, {}", dx, dy, dz);
|
||||
if dx != 0 || dy != 0 {
|
||||
let mouse_event = orbclient::event::MouseRelativeEvent {
|
||||
dx: dx as i32,
|
||||
dy: dy as i32,
|
||||
};
|
||||
|
||||
match display.write(&mouse_event.to_event()) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
log::warn!("failed to send mouse event to orbital: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
if dz != 0 {
|
||||
let scroll_event = orbclient::event::ScrollEvent {
|
||||
x: dz as i32,
|
||||
y: 0,
|
||||
};
|
||||
|
||||
match display.write(&scroll_event.to_event()) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
log::warn!("failed to send scroll event to orbital: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if report_count == 3 && report_size == 1 && global_state.usage_page == Some(9) {
|
||||
//TODO: Make this less hard-coded
|
||||
let left = binary_view.get(0).expect("Failed to read array item");
|
||||
let right = binary_view.get(1).expect("Failed to read array item");
|
||||
let middle = binary_view.get(2).expect("Failed to read array item");
|
||||
log::trace!("Left {}, Right {}, Middle {}", left, right, middle);
|
||||
if last_buttons != (left, right, middle) {
|
||||
last_buttons = (left, right, middle);
|
||||
|
||||
let button_event = orbclient::event::ButtonEvent {
|
||||
left,
|
||||
right,
|
||||
middle,
|
||||
};
|
||||
|
||||
match display.write(&button_event.to_event()) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
log::warn!("failed to send button event to orbital: {}", err);
|
||||
}
|
||||
}
|
||||
} else if event.usage == GenericDesktopUsage::Y as u32 {
|
||||
if event.relative {
|
||||
mouse_dy += event.value;
|
||||
} else {
|
||||
mouse_pos.1 = event.value;
|
||||
}
|
||||
} else {
|
||||
log::trace!("Unknown report variable item: size {} count {} offset {} usage page {:?}", report_size, report_count, bit_offset, global_state.usage_page);
|
||||
log::info!(
|
||||
"unsupported generic desktop usage 0x{:X}:0x{:X} value {}",
|
||||
event.usage_page,
|
||||
event.usage,
|
||||
event.value
|
||||
);
|
||||
}
|
||||
} else if event.usage_page == UsagePage::KeyboardOrKeypad as u32 {
|
||||
let (pressed, shift_opt) = if event.value != 0 {
|
||||
(true, Some(left_shift | right_shift))
|
||||
} else {
|
||||
(false, None)
|
||||
};
|
||||
if event.usage == 0xE1 {
|
||||
left_shift = pressed;
|
||||
} else if event.usage == 0xE5 {
|
||||
right_shift = pressed;
|
||||
}
|
||||
send_key_event(
|
||||
&mut display,
|
||||
event.usage_page,
|
||||
event.usage,
|
||||
pressed,
|
||||
shift_opt,
|
||||
);
|
||||
} else if event.usage_page == UsagePage::Button as u32 {
|
||||
if event.usage > 0 && event.usage as usize <= buttons.len() {
|
||||
buttons[event.usage as usize - 1] = event.value != 0;
|
||||
} else {
|
||||
log::info!(
|
||||
"unsupported buttons usage 0x{:X}:0x{:X} value {}",
|
||||
event.usage_page,
|
||||
event.usage,
|
||||
event.value
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// The item is an array.
|
||||
log::info!(
|
||||
"unsupported usage 0x{:X}:0x{:X} value {}",
|
||||
event.usage_page,
|
||||
event.usage,
|
||||
event.value
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
log::trace!("INPUT FLAGS: {:?}", input);
|
||||
if report_size == 8 {
|
||||
for report_index in 0..report_count as usize {
|
||||
let binary_view = BinaryView::new(&report_buffer, bit_offset as usize + report_index * report_size as usize, report_size as usize);
|
||||
let usage = binary_view.read_u8(0).expect("Failed to read array item");
|
||||
if usage != 0 {
|
||||
pressed_keys.push((global_state.usage_page.unwrap_or(0), usage));
|
||||
}
|
||||
log::trace!("Report index array {}: {:#x}", report_index, usage);
|
||||
}
|
||||
} else {
|
||||
log::trace!("Unknown report array item: size {} count {} offset {} usage page {:?}", report_size, report_count, bit_offset, global_state.usage_page);
|
||||
if mouse_pos != last_mouse_pos {
|
||||
last_mouse_pos = mouse_pos;
|
||||
|
||||
// ps2d uses 0..=65535 as range, while usb uses 0..=32767. orbital
|
||||
// expects the former range, so multiply by two here to translate
|
||||
// the usb coordinates to what orbital expects.
|
||||
let mouse_event = orbclient::event::MouseEvent {
|
||||
x: mouse_pos.0 * 2,
|
||||
y: mouse_pos.1 * 2,
|
||||
};
|
||||
|
||||
match display.write(&mouse_event.to_event()) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
log::warn!("failed to send mouse event to orbital: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if mouse_dx != 0 || mouse_dy != 0 {
|
||||
let mouse_event = orbclient::event::MouseRelativeEvent {
|
||||
dx: mouse_dx,
|
||||
dy: mouse_dy,
|
||||
};
|
||||
|
||||
for &(usage_page, usage) in last_pressed_keys.iter() {
|
||||
if ! pressed_keys.contains(&(usage_page, usage)) {
|
||||
log::debug!("Released {:#x},{:#x}", usage_page, usage);
|
||||
send_key_event(&mut display, usage_page, usage, false, None);
|
||||
match display.write(&mouse_event.to_event()) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
log::warn!("failed to send mouse event to orbital: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for &(usage_page, usage) in pressed_keys.iter() {
|
||||
if ! last_pressed_keys.contains(&(usage_page, usage)) {
|
||||
log::debug!("Pressed {:#x},{:#x}", usage_page, usage);
|
||||
send_key_event(&mut display, usage_page, usage, true, Some(
|
||||
pressed_keys.contains(&(0x07, 0xE1)) || pressed_keys.contains(&(0x07, 0xE5))
|
||||
));
|
||||
if buttons != last_buttons {
|
||||
last_buttons = buttons;
|
||||
|
||||
let button_event = orbclient::event::ButtonEvent {
|
||||
left: buttons[0],
|
||||
right: buttons[1],
|
||||
middle: buttons[2],
|
||||
};
|
||||
|
||||
match display.write(&button_event.to_event()) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
log::warn!("failed to send button event to orbital: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::mem::swap(&mut pressed_keys, &mut last_pressed_keys);
|
||||
pressed_keys.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn binary_view() {
|
||||
// 0000 1000 1100 0111
|
||||
// E S
|
||||
let view = super::BinaryView::new(&[0xC7, 0x08], 3, 11);
|
||||
assert_eq!(view.get(0), Some(false));
|
||||
assert_eq!(view.get(2), Some(false));
|
||||
assert_eq!(view.get(3), Some(true));
|
||||
assert_eq!(view.get(7), Some(false));
|
||||
assert_eq!(view.get(17), None);
|
||||
|
||||
assert_eq!(view.read_u8(0), Some(0b0001_1000));
|
||||
assert_eq!(view.read_u8(1), Some(0b1000_1100));
|
||||
assert_eq!(view.read_u8(2), Some(0b0100_0110));
|
||||
assert_eq!(view.read_u8(3), Some(0b0010_0011));
|
||||
assert_eq!(view.read_u8(7), None);
|
||||
|
||||
// 0000 1000 1100 0111
|
||||
// E S
|
||||
let view = super::BinaryView::new(&[0xC7, 0x08], 8, 8);
|
||||
assert_eq!(view.read_u8(0), Some(0b0000_1000));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-4
@@ -80,10 +80,7 @@ pub fn set_idle(
|
||||
DeviceReqData::NoData,
|
||||
)
|
||||
}
|
||||
pub fn get_protocol(
|
||||
handle: &XhciClientHandle,
|
||||
if_num: u16,
|
||||
) -> Result<u8, XhciClientHandleError> {
|
||||
pub fn get_protocol(handle: &XhciClientHandle, if_num: u16) -> Result<u8, XhciClientHandleError> {
|
||||
let mut protocol = 0;
|
||||
let buffer = slice::from_mut(&mut protocol);
|
||||
handle.device_request(
|
||||
|
||||
Reference in New Issue
Block a user