From f5b542e6113967285b270f48fb2bd9e02565928f Mon Sep 17 00:00:00 2001 From: Hasan Ibraheem Date: Thu, 5 May 2022 02:12:10 -0400 Subject: [PATCH] Relay works on latest switch firmware Mac address needs to be changed to start with 94:58:CB: ? maybe ? https://github.com/Poohl/joycontrol/issues/4 Probably will move back away from async. Not sure why I was doing it, but this is some old code --- Cargo.lock | 20 ++++ Cargo.toml | 2 + src/hci_utils.rs | 139 +++++++++++++++++++++ src/hcidev.rs | 84 +++++++++++++ src/l2cap.rs | 46 ++++++- src/libc_helpe.rs | 10 ++ src/main.rs | 298 +++++++++++++++++++++++++++++----------------- src/smol_fd.rs | 11 +- 8 files changed, 487 insertions(+), 123 deletions(-) create mode 100644 src/hci_utils.rs create mode 100644 src/hcidev.rs create mode 100644 src/libc_helpe.rs diff --git a/Cargo.lock b/Cargo.lock index bf21302..d5beb28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -131,6 +131,15 @@ dependencies = [ "libdbus-sys", ] +[[package]] +name = "fd" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "275ab28c5c4076abec490e95cd4d69eaad40b6c16a2e692debd0e53453d006d0" +dependencies = [ + "libc", +] + [[package]] name = "futures" version = "0.3.4" @@ -233,6 +242,16 @@ dependencies = [ "wasi", ] +[[package]] +name = "hciraw" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "510f5f58cd22e8f13d86901d71a981f944bd209762b4e31319bc5db0a00c5256" +dependencies = [ + "fd", + "libc", +] + [[package]] name = "hex" version = "0.3.2" @@ -246,6 +265,7 @@ dependencies = [ "blurz", "dbus 0.8.2", "futures", + "hciraw", "libbluetooth", "libc", "num-traits", diff --git a/Cargo.toml b/Cargo.toml index 6149a8a..cea3a38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,3 +18,5 @@ smol = "0.1" futures = "0.3.4" # For generic nums num-traits = { version = "0.2", default-features = false } +# For raw hci +hciraw = "1.0" diff --git a/src/hci_utils.rs b/src/hci_utils.rs new file mode 100644 index 0000000..56e8489 --- /dev/null +++ b/src/hci_utils.rs @@ -0,0 +1,139 @@ +use libc::EIO; +use std::ffi::c_void; +use std::io::{Result, Error}; +// use libbluetooth::hci::{ +// OGF_LINK_POLICY, +// sniff_mode_cp, OCF_SNIFF_MODE, SNIFF_MODE_CP_SIZE, +// exit_sniff_mode_cp, OCF_EXIT_SNIFF_MODE, EXIT_SNIFF_MODE_CP_SIZE, +// evt_mode_change, EVT_MODE_CHANGE, EVT_MODE_CHANGE_SIZE, +// }; + +use libbluetooth::hci_lib::hci_request; + +fn mut_void_ptr(t: &mut T) -> *mut c_void { + t as *mut T as *mut c_void +} + +fn void_ptr(t: &mut T) -> *const c_void { + t as *const T as *const c_void +} + +pub unsafe fn hci_send_req(dd: i32, req: &mut hci_request, timeout: i32) -> std::io::Result<()> { + let res = libbluetooth::hci_lib::hci_send_req(dd, req, timeout); + + if res < 0 { + Err(std::io::Error::last_os_error()) + } else { + Ok(()) + } +} + +pub fn hci_sniff_mode( + dd: i32, handle: u16, max_interval: u16, min_interval: u16, + sniff_attempt: u16, sniff_timeout: u16, timeout: i32 +) -> Result<()> { + use libbluetooth::hci::{ + OGF_LINK_POLICY, + sniff_mode_cp, OCF_SNIFF_MODE, SNIFF_MODE_CP_SIZE, + // evt_mode_change, EVT_MODE_CHANGE, EVT_MODE_CHANGE_SIZE, + evt_cmd_status, EVT_CMD_STATUS, EVT_CMD_STATUS_SIZE, + }; + + + let mut cp = sniff_mode_cp { + handle: handle, + max_interval: max_interval, + min_interval: min_interval, + attempt: sniff_attempt, + timeout: sniff_timeout + }; + + // let mut rp = evt_mode_change { + // status: 0, + // handle: 0, + // mode: 0, + // interval: 0 + // }; + + let mut rp = evt_cmd_status { + status: 0, + ncmd: 0, + opcode: 0 + }; + + let mut rq = hci_request { + ogf: OGF_LINK_POLICY as u16, + ocf: OCF_SNIFF_MODE as u16, + // event: EVT_MODE_CHANGE, + event: EVT_CMD_STATUS, + cparam: mut_void_ptr(&mut cp), + clen: SNIFF_MODE_CP_SIZE as i32, + rparam: mut_void_ptr(&mut rp), + // rlen: EVT_MODE_CHANGE_SIZE as i32 + rlen: EVT_CMD_STATUS_SIZE as i32 + }; + + unsafe { + if libbluetooth::hci_lib::hci_send_req(dd, &mut rq, timeout) < 0 { + return Err(Error::last_os_error()); + } + } + + if rp.status != 0 { + return Err(Error::from_raw_os_error(EIO)); + } + + Ok(()) +} + +pub fn hci_exit_sniff_mode(dd: i32, handle: u16, timeout: i32) -> Result<()> { + use libbluetooth::hci::{ + OGF_LINK_POLICY, + exit_sniff_mode_cp, OCF_EXIT_SNIFF_MODE, EXIT_SNIFF_MODE_CP_SIZE, + // evt_mode_change, EVT_MODE_CHANGE, EVT_MODE_CHANGE_SIZE, + evt_cmd_status, EVT_CMD_STATUS, EVT_CMD_STATUS_SIZE, + }; + + let mut cp = exit_sniff_mode_cp { + handle: handle, + }; + + // let mut rp = evt_mode_change { + // status: 0, + // handle: 0, + // mode: 0, + // interval: 0 + // }; + + let mut rp = evt_cmd_status { + status: 0, + ncmd: 0, + opcode: 0 + }; + + let mut rq = hci_request { + ogf: OGF_LINK_POLICY as u16, + ocf: OCF_EXIT_SNIFF_MODE as u16, + // event: EVT_MODE_CHANGE, + event: EVT_CMD_STATUS, + cparam: mut_void_ptr(&mut cp), + clen: EXIT_SNIFF_MODE_CP_SIZE as i32, + rparam: mut_void_ptr(&mut rp), + // rlen: EVT_MODE_CHANGE_SIZE as i32 + rlen: EVT_CMD_STATUS_SIZE as i32 + }; + + unsafe { + if libbluetooth::hci_lib::hci_send_req(dd, &mut rq, timeout) < 0 { + return Err(Error::last_os_error()); + } + } + + if rp.status != 0 { + return Err(Error::from_raw_os_error(EIO)); + } + + Ok(()) +} + + diff --git a/src/hcidev.rs b/src/hcidev.rs new file mode 100644 index 0000000..3ce38b8 --- /dev/null +++ b/src/hcidev.rs @@ -0,0 +1,84 @@ +use std::ffi::c_void; +use std::os::raw::{c_char, c_int}; +use std::io::Result; +use libbluetooth::bluetooth::SOL_HCI; +use libbluetooth::hci::{HCI_EVENT_PKT, hci_filter, HCI_FILTER}; +use crate::libc_helpe::libc_check_error; +use libbluetooth::hci_lib::{self, hci_open_dev, hci_close_dev, hci_read_class_of_dev, hci_write_class_of_dev, hci_filter_clear_opcode}; +use libc::setsockopt; + +pub struct HciDev { + hdev: c_int, + socket: c_int, +} + +impl HciDev { + pub unsafe fn new(hdev: c_int) -> Result { + let socket = hci_open_dev(hdev); + + Ok(HciDev { + hdev: hdev, + socket: libc_check_error(socket)?, + }) + } + + pub unsafe fn write_class(&mut self, cod: u32) -> Result<()> { + let write_res = hci_write_class_of_dev(self.socket, cod, 2000); + libc_check_error(write_res)?; + Ok(()) + } + + pub unsafe fn read_class(&mut self) -> Result { + let mut class = [0u8; 4]; + let read_res = hci_read_class_of_dev(self.socket, class[1..].as_mut_ptr() as *mut c_char, 2000); + libc_check_error(read_res)?; + + Ok(u32::from_be_bytes(class)) + } + + pub unsafe fn cmd_cmd(&mut self, ocf: u16, ogf: u16, cmd: &mut [u8]) -> std::io::Result> { + let mut flt = hci_filter { + type_mask: 0, + event_mask: [0, 0], + opcode: 0 + }; + + /* Setup filter */ + hci_lib::hci_filter_set_ptype(HCI_EVENT_PKT, &mut flt); + hci_lib::hci_filter_all_events(&mut flt); + + libc_check_error(setsockopt( + self.socket, + SOL_HCI, + HCI_FILTER, + &flt as *const hci_filter as *const c_void, + std::mem::size_of::() as libc::socklen_t + ))?; + + libc_check_error(hci_lib::hci_send_cmd( + self.socket, + ogf, + ocf, + cmd.len() as c_char, + cmd.as_mut_ptr() as *mut c_void + ))?; + + let mut buf = vec![0u8; libbluetooth::hci::HCI_MAX_EVENT_SIZE]; + let len = libc::read(self.socket, buf.as_mut_ptr() as *mut c_void, buf.len()); + libc_check_error(len)?; + + buf.resize(len as usize, 0); + Ok(buf) + } + // pub unsafe fn write_cmd(&mut self) -> Result<()> { + // hci_write_ + // } +} + +impl Drop for HciDev { + fn drop(&mut self) { + unsafe { + hci_close_dev(self.socket); + } + } +} diff --git a/src/l2cap.rs b/src/l2cap.rs index 4ad343d..78f9606 100644 --- a/src/l2cap.rs +++ b/src/l2cap.rs @@ -1,4 +1,6 @@ -use crate::smol_fd::{libc_check_error, SmolFd}; +use std::borrow::Borrow; +use crate::smol_fd::SmolFd; +use crate::libc_helpe::libc_check_error; use libbluetooth::bluetooth::bdaddr_t; use std::io::{Read, Result, Write}; use std::mem::{size_of, MaybeUninit}; @@ -22,6 +24,27 @@ impl L2CAPListener { ) })?; + unsafe { + let opt: libc::c_int = 0; + + libc_check_error(libc::setsockopt( + socket, + libc::SOL_SOCKET, + libc::SO_SNDBUF, + &opt as *const i32 as *const libc::c_void, + std::mem::size_of::() as libc::socklen_t + ))?; + + const BT_POWER: libc::c_int = 9; + libc_check_error(libc::setsockopt( + socket, + libc::SOL_BLUETOOTH, + BT_POWER, + &opt as *const i32 as *const libc::c_void, + std::mem::size_of::() as libc::socklen_t + ))?; + } + Ok(L2CAPListener { fd: SmolFd::new(socket), }) @@ -124,6 +147,27 @@ impl L2CAPStream { ) })?; + unsafe { + let opt: libc::c_int = 0; + + libc_check_error(libc::setsockopt( + socket, + libc::SOL_SOCKET, + libc::SO_SNDBUF, + &opt as *const i32 as *const libc::c_void, + std::mem::size_of::() as libc::socklen_t + ))?; + + const BT_POWER: libc::c_int = 9; + libc_check_error(libc::setsockopt( + socket, + libc::SOL_BLUETOOTH, + BT_POWER, + &opt as *const i32 as *const libc::c_void, + std::mem::size_of::() as libc::socklen_t + ))?; + } + Ok(L2CAPStream { fd: SmolFd::new(socket), }) diff --git a/src/libc_helpe.rs b/src/libc_helpe.rs new file mode 100644 index 0000000..7b71582 --- /dev/null +++ b/src/libc_helpe.rs @@ -0,0 +1,10 @@ +use std::io::{Error, Result}; +use num_traits::{PrimInt, Signed, Zero}; + +pub fn libc_check_error(val: T) -> Result { + if val < T::zero() { + Err(Error::last_os_error()) + } else { + Ok(val) + } +} diff --git a/src/main.rs b/src/main.rs index 8a75c74..2910065 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,9 @@ use std::time::Duration; mod dbus_profile_manager; mod l2cap; mod smol_fd; +mod libc_helpe; +mod hci_utils; +mod hcidev; use l2cap::{L2CAPListener, L2CAPStream}; @@ -15,7 +18,9 @@ use dbus::arg::{RefArg, Variant}; use dbus::blocking::Connection; use dbus_profile_manager::OrgBluezProfileManager1; use std::num::ParseIntError; +use std::io::Read; +use smol::Async; use futures::prelude::*; const CONTROLLERS: [&str; 3] = ["Pro Controller", "Joy-Con (L)", "Joy-Con (R)"]; @@ -114,9 +119,12 @@ impl std::fmt::Display for BtAddr { } fn main() -> Result<(), Box> { + let id = 2; + let session = BluetoothSession::create_session(None).unwrap(); - let adapter = BluetoothAdapter::init(&session)?; - let adapter_addr = BtAddr::from_str(&adapter.get_address().unwrap()).unwrap(); + let adapter = BluetoothAdapter::create_adapter(&session, format!("/org/bluez/hci{id}")).unwrap(); + let adapter_addr_str = adapter.get_address().unwrap(); + let adapter_addr = BtAddr::from_str(&adapter_addr_str).unwrap(); let controller = scan_for_bluetooth_controller(&session, &adapter); let controller_addr = controller.get_address().unwrap(); @@ -153,6 +161,27 @@ fn main() -> Result<(), Box> { return Err(e)?; } + println!("Now we flush out all the data we're receiving from the controller until we're ready to use it."); + + let (mut stop_tx, mut stop_rx) = futures::channel::oneshot::channel::<()>(); + + let flush_thread = std::thread::spawn(move || { + let mut itr = controller_itr_l2cap; + let mut buf = [0u8; 64]; + + loop { + // I'm not using async here because when I did it just refused to read even though + // it works completely fine in the actual forwarding down below, which is very weird. + let res = itr.read(&mut buf); + + match stop_rx.try_recv() { + Ok(Some(())) => return Ok(itr), + Ok(None) => continue, + Err(e) => return Err(e), + } + } + }); + println!("Binding server to necessary ports. This will fail if we aren't root."); ctl_server_l2cap.bind(17)?; @@ -164,15 +193,14 @@ fn main() -> Result<(), Box> { println!("Changing name and class"); let session = BluetoothSession::create_session(None)?; - let adapter = BluetoothAdapter::init(&session)?; + let adapter = BluetoothAdapter::create_adapter(&session, format!("/org/bluez/hci{id}")).unwrap(); adapter.set_alias(controller_name)?; - let mut cmd = Command::new("hciconfig"); - cmd.arg("hci0"); - cmd.arg("class"); - cmd.arg("0x002508"); - cmd.spawn().unwrap().wait().unwrap(); + // TODO: Make this not hci0, but any hci you want + let mut hci_device = unsafe { + hcidev::HciDev::new(id) + }.unwrap(); println!("Advertising the Bluetooth SDP record..."); println!("Please open the \"Change Grip/Order\" menu."); @@ -197,6 +225,11 @@ fn main() -> Result<(), Box> { adapter.set_pairable(true)?; adapter.set_discoverable(true)?; + std::thread::sleep(Duration::from_secs(1)); + unsafe { + hci_device.write_class(0x002508); + } + println!("Connecting with the Switch... Please open the \"Change Grip/Order\" menu."); let (switch_ctl_l2cap, ctl_addr) = ctl_server_l2cap.accept()?; @@ -212,10 +245,51 @@ fn main() -> Result<(), Box> { let switch_ctl = smol::Async::new(switch_ctl_l2cap).unwrap(); let switch_itr = smol::Async::new(switch_itr_l2cap).unwrap(); + + println!("Stopping flush"); + + stop_tx.send(()).unwrap(); + + controller_itr_l2cap = flush_thread.join().unwrap().unwrap(); + let controller_ctl = smol::Async::new(controller_ctl_l2cap).unwrap(); let controller_itr = smol::Async::new(controller_itr_l2cap).unwrap(); - + println!("Stopped flush"); + + + // println!("This little maneuver is about to cost us 15ms"); + + // let adapter_devid = libc_check_error(unsafe { + // libbluetooth::hci_lib::hci_devid(adapter_addr_str.as_ptr() as *const i8) + // }).unwrap(); + + // let adapter_devid = 0; + + // println!("Adapter device id: {:?}", adapter_devid); + + // let adapter_dd = libc_check_error(unsafe { + // libbluetooth::hci_lib::hci_open_dev(adapter_devid as i32) + // }).unwrap(); + + // let controller_dd = libc_check_error(unsafe { + // libbluetooth::hci_lib::hci_open_dev(controller_devid as i32) + // }).unwrap(); + + // let n_15ms = 24; // 24 * 0.625 = 15 + + // 1 = 0.625ms + // 24 = 15.000ms + // hci_utils::hci_sniff_mode( + // adapter_dd, 0x1, 100, 4, + // 40, 40, 1000 + // ).unwrap(); + + // std::thread::sleep(Duration::from_secs(10)); + // std::process::exit(0); + + + // let ctl_relay = std::thread::spawn(move || { // let (mut sw_ctl_r, mut sw_ctl_w) = switch_ctl.split(); // let (mut cn_ctl_r, mut cn_ctl_w) = controller_ctl.split(); @@ -223,13 +297,13 @@ fn main() -> Result<(), Box> { // smol::run(async { // let mut controller_incoming = [0u8; 512]; // let mut switch_incoming = [0u8; 512]; - + // let mut sw_r = sw_ctl_r.read(&mut switch_incoming); // let mut cn_r = cn_ctl_r.read(&mut controller_incoming); - + // let mut total_read_from_cn = 0; // let mut total_read_from_sw = 0; - + // loop { // let both_r = futures::future::select(sw_r, cn_r); @@ -244,11 +318,11 @@ fn main() -> Result<(), Box> { // } // cn_ctl_w.write_all(&switch_incoming[0..n]).await.unwrap(); - + // cn_r = old_cn_r; // sw_r = sw_ctl_r.read(&mut switch_incoming); // }, - + // // Read successfully from controller // future::Either::Right((Ok(n), old_sw_r)) => { // total_read_from_cn += n; @@ -261,11 +335,11 @@ fn main() -> Result<(), Box> { // // dbg!(n); // sw_ctl_w.write_all(&controller_incoming[0..n]).await.unwrap(); - + // sw_r = old_sw_r; // cn_r = cn_ctl_r.read(&mut controller_incoming); // }, - + // // Read failed from switch // future::Either::Left((Err(e), _old_cn_r)) => { // println!("Read from switch failed: {}", e); @@ -279,7 +353,7 @@ fn main() -> Result<(), Box> { // }, // }; // } - + // println!("CTL finished."); // println!("Total bytes from from controller: {}", total_read_from_cn); // println!("Total bytes from from switch : {}", total_read_from_sw); @@ -288,99 +362,99 @@ fn main() -> Result<(), Box> { // let itr_relay = std::thread::spawn(move || { - let (mut sw_itr_r, mut sw_itr_w) = switch_itr.split(); - let (mut cn_itr_r, mut cn_itr_w) = controller_itr.split(); - - smol::run(async { - let mut controller_incoming = [0u8; 128]; - let mut switch_incoming = [0u8; 128]; - - let mut last_cn_len = 0; - let mut last_sw_len = 0; - - let mut sw_r = sw_itr_r.read(&mut switch_incoming); - let mut cn_r = cn_itr_r.read(&mut controller_incoming); - - let mut total_read_from_cn = 0; - let mut total_read_from_sw = 0; - - loop { - let both_r = futures::future::select(sw_r, cn_r); - - match both_r.await { - // Read successfully from switch - future::Either::Left((Ok(n), old_cn_r)) => { - total_read_from_sw += n; - last_sw_len = n; - - if n == 0 { - println!("Read 0 bytes from switch itr. Closing"); - break; - } - - cn_itr_w.write_all(&switch_incoming[0..n]).await.unwrap(); - - cn_r = old_cn_r; - sw_r = sw_itr_r.read(&mut switch_incoming); - }, - - // Read successfully from controller - future::Either::Right((Ok(n), old_sw_r)) => { - total_read_from_cn += n; - last_cn_len = n; - - if n == 0 { - println!("Read 0 bytes from controller itr. Closing"); - break; - } - - // dbg!(n); - - let hid_packet = &mut controller_incoming[1..n]; - - if n == 50 && (hid_packet[0], hid_packet[14]) == (0x21, 0x02) { - println!("Got a device info packet."); - - let mut old_addr = BtAddr([0; 6]); - old_addr.0.copy_from_slice(&hid_packet[19..25]); - - println!("Old address: {}", old_addr); - - hid_packet[19..25].copy_from_slice(&adapter_addr.0[..]); - - println!("New address: {}", adapter_addr); - } - - sw_itr_w.write_all(&controller_incoming[0..n]).await.unwrap(); - - sw_r = old_sw_r; - cn_r = cn_itr_r.read(&mut controller_incoming); - }, - - // Read failed from switch - future::Either::Left((Err(e), _old_cn_r)) => { - println!("Read from switch failed: {}", e); + let (mut sw_itr_r, mut sw_itr_w) = switch_itr.split(); + let (mut cn_itr_r, mut cn_itr_w) = controller_itr.split(); + + smol::run(async { + let mut controller_incoming = [0u8; 128]; + let mut switch_incoming = [0u8; 128]; + + let mut last_cn_len = 0; + let mut last_sw_len = 0; + + let mut sw_r = sw_itr_r.read(&mut switch_incoming); + let mut cn_r = cn_itr_r.read(&mut controller_incoming); + + let mut total_read_from_cn = 0; + let mut total_read_from_sw = 0; + + loop { + let both_r = futures::future::select(sw_r, cn_r); + + match both_r.await { + // Read successfully from switch + future::Either::Left((Ok(n), old_cn_r)) => { + total_read_from_sw += n; + last_sw_len = n; + + if n == 0 { + println!("Read 0 bytes from switch itr. Closing"); break; - }, + } + + cn_itr_w.write_all(&switch_incoming[0..n]).await.unwrap(); + + cn_r = old_cn_r; + sw_r = sw_itr_r.read(&mut switch_incoming); + } + + // Read successfully from controller + future::Either::Right((Ok(mut n), old_sw_r)) => { + total_read_from_cn += n; + last_cn_len = n; - // Read failed from controller - future::Either::Right((Err(e), _old_sw_r)) => { - println!("Read from controller failed: {}", e); + if n == 0 { + println!("Read 0 bytes from controller itr. Closing"); break; - }, - }; - } + } + + // dbg!(n); + + let hid_packet = &mut controller_incoming[1..n]; + + if n == 50 && (hid_packet[0], hid_packet[14]) == (0x21, 0x02) { + println!("Got a device info packet."); - println!("ITR finished."); - println!("Dumping last read from controller"); - println!("{}", hexdump(&controller_incoming[..last_cn_len])); - - println!("Dumping last read from switch"); - println!("{}", hexdump(&switch_incoming[..last_sw_len])); + let mut old_addr = BtAddr([0; 6]); + old_addr.0.copy_from_slice(&hid_packet[19..25]); - println!("Total bytes from from controller: {}", total_read_from_cn); - println!("Total bytes from from switch : {}", total_read_from_sw); - }); + println!("Old address: {}", old_addr); + + hid_packet[19..25].copy_from_slice(&adapter_addr.0[..]); + + println!("New address: {}", adapter_addr); + } + + sw_itr_w.write_all(&controller_incoming[0..n]).await.unwrap(); + + sw_r = old_sw_r; + cn_r = cn_itr_r.read(&mut controller_incoming); + } + + // Read failed from switch + future::Either::Left((Err(e), _old_cn_r)) => { + println!("Read from switch failed: {}", e); + break; + } + + // Read failed from controller + future::Either::Right((Err(e), _old_sw_r)) => { + println!("Read from controller failed: {}", e); + break; + } + }; + } + + println!("ITR finished."); + println!("Dumping last read from controller"); + println!("{}", hexdump(&controller_incoming[..last_cn_len])); + + println!("Dumping last read from switch"); + println!("{}", hexdump(&switch_incoming[..last_sw_len])); + + println!("Total bytes from from controller: {}", total_read_from_cn); + println!("Total bytes from from switch : {}", total_read_from_sw); + }); // }); // ctl_relay.join().unwrap(); @@ -391,9 +465,9 @@ fn main() -> Result<(), Box> { Ok(()) } - - use std::fmt::Write as FmtWrite; +use std::borrow::BorrowMut; +use crate::libc_helpe::libc_check_error; fn hexdump(buf: &[u8]) -> String { let mut out = String::with_capacity(buf.len() * 4); @@ -402,13 +476,13 @@ fn hexdump(buf: &[u8]) -> String { for byte in chunk { write!(out, "{:02x} ", byte); } - + for _ in 0..16 - chunk.len() { out.push_str(" "); } - + out.push(' '); - + for byte in chunk { let c = *byte as char; @@ -421,6 +495,6 @@ fn hexdump(buf: &[u8]) -> String { out.push('\n'); } - + out -} \ No newline at end of file +} diff --git a/src/smol_fd.rs b/src/smol_fd.rs index ca4e311..85b15f6 100644 --- a/src/smol_fd.rs +++ b/src/smol_fd.rs @@ -1,16 +1,7 @@ use std::ffi::c_void; use std::io::{Error, Read, Result, Write}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; - -use num_traits::{PrimInt, Signed, Zero}; - -pub fn libc_check_error(val: T) -> Result { - if val < T::zero() { - Err(Error::last_os_error()) - } else { - Ok(val) - } -} +use crate::libc_helpe::libc_check_error; #[derive(Debug)] pub struct SmolFd {