diff --git a/Cargo.toml b/Cargo.toml index d2927f6..a5ceff2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ categories = ["hardware-support"] include = ["src/**/*", "Cargo.toml", "README.md", "LICENSE"] [dependencies] -hid = "^0.4.1" +hidapi = "^2.4.1" error-chain = "^0.11.0" [badges] diff --git a/examples/simple.rs b/examples/simple.rs index 71d3297..e1f24b9 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -1,13 +1,15 @@ -extern crate hid; extern crate cp211x_uart; +extern crate hidapi; +use cp211x_uart::{DataBits, FlowControl, HidUart, Parity, StopBits, UartConfig}; use std::time::Duration; -use cp211x_uart::{HidUart, UartConfig, DataBits, StopBits, Parity, FlowControl}; fn run() -> Result<(), cp211x_uart::Error> { - let manager = hid::init()?; - for device in manager.find(Some(0x10C4), Some(0xEA80)) { - let handle = device.open()?; + let manager = hidapi::HidApi::new()?; + for device_info in manager.device_list().filter(|device_info| { + device_info.vendor_id() == 0x10C4 && device_info.product_id() == 0xEA80 + }) { + let handle = device_info.open_device(&manager)?; let mut uart = HidUart::new(handle)?; let config = UartConfig { @@ -37,4 +39,4 @@ fn main() { } _ => {} } -} \ No newline at end of file +} diff --git a/src/error.rs b/src/error.rs index a15f6fa..a937204 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,6 @@ error_chain! { foreign_links { - HidError(::hid::Error); + HidError(::hidapi::HidError); } errors { @@ -9,4 +9,4 @@ error_chain! { display("write operation is time out") } } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index 97e2f5e..fa0a2f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,26 +3,27 @@ //! See more information [here][1]. //! [1]: https://www.silabs.com/products/interface/usb-bridges/classic-usb-bridges/device.cp2110-f01-gm -extern crate hid; -#[macro_use] extern crate error_chain; +extern crate hidapi; +#[macro_use] +extern crate error_chain; use std::cmp::min; use std::default::Default; use std::time::{Duration, Instant}; mod error; -use error::*; pub use error::Error; +use error::*; const FEATURE_REPORT_LENGTH: usize = 64; const INTERRUPT_REPORT_LENGTH: usize = 64; const GETSET_UART_ENABLE: u8 = 0x41; // Get Set Receive Status -const PURGE_FIFOS: u8 = 0x43; // Purge FIFOs +const PURGE_FIFOS: u8 = 0x43; // Purge FIFOs const GETSET_UART_CONFIG: u8 = 0x50; // Get Set UART Config const PURGE_TRANSMIT_MASK: u8 = 0x01; -const PURGE_RECEIVE_MASK: u8 = 0x02; +const PURGE_RECEIVE_MASK: u8 = 0x02; /// The number of data bits in [UART configuration](struct.UartConfig.html). #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -116,14 +117,15 @@ impl Default for UartConfig { } } -/// Wrapper around `hid::Handle` to provide UART control. +/// Wrapper around `hidapi::HidDevice` to provide UART control. pub struct HidUart { - handle: hid::Handle, + handle: hidapi::HidDevice, read_timeout: Duration, write_timeout: Duration, + rx_buffer: RxBuffer, } -fn set_uart_enable(handle: &mut hid::Handle, enable: bool) -> Result<()> { +fn set_uart_enable(handle: &mut hidapi::HidDevice, enable: bool) -> Result<()> { let mut buf: [u8; FEATURE_REPORT_LENGTH] = [0; FEATURE_REPORT_LENGTH]; buf[0] = GETSET_UART_ENABLE; @@ -132,19 +134,20 @@ fn set_uart_enable(handle: &mut hid::Handle, enable: bool) -> Result<()> { } else { buf[1] = 0x00; } - handle.feature().send(&buf[..])?; + handle.send_feature_report(&buf[..])?; Ok(()) } impl HidUart { - /// Returns a new instance of `HidUart` from `hid::Handle`. + /// Returns a new instance of `HidUart` from `hidapi::HidDevice`. /// /// The instance enables UART automatically. - pub fn new(handle: hid::Handle) -> Result { + pub fn new(handle: hidapi::HidDevice) -> Result { let mut instance = HidUart { handle, read_timeout: Duration::from_millis(1000), write_timeout: Duration::from_millis(1000), + rx_buffer: RxBuffer::new(), }; instance.enable()?; Ok(instance) @@ -185,7 +188,7 @@ impl HidUart { let mut buf: [u8; FEATURE_REPORT_LENGTH] = [0; FEATURE_REPORT_LENGTH]; buf[0] = GETSET_UART_ENABLE; - self.handle.feature().get(&mut buf[..])?; + self.handle.get_feature_report(&mut buf[..])?; if buf[1] == 0x00 { Ok(false) } else { @@ -202,33 +205,29 @@ impl HidUart { buf[2] = ((config.baud_rate >> 16) & 0xFF) as u8; buf[3] = ((config.baud_rate >> 8) & 0xFF) as u8; buf[4] = (config.baud_rate & 0xFF) as u8; - buf[5] = - match config.parity { - Parity::None => 0x00, - Parity::Odd => 0x01, - Parity::Even => 0x02, - Parity::Mark => 0x03, - Parity::Space => 0x04, - }; - buf[6] = - match config.flow_control { - FlowControl::None => 0x00, - FlowControl::RtsCts => 0x01, - }; - buf[7] = - match config.data_bits { - DataBits::Bits5 => 0x00, - DataBits::Bits6 => 0x01, - DataBits::Bits7 => 0x02, - DataBits::Bits8 => 0x03, - }; - buf[8] = - match config.stop_bits { - StopBits::Short => 0x00, - StopBits::Long => 0x01, - }; - - self.handle.feature().send(&buf[..])?; + buf[5] = match config.parity { + Parity::None => 0x00, + Parity::Odd => 0x01, + Parity::Even => 0x02, + Parity::Mark => 0x03, + Parity::Space => 0x04, + }; + buf[6] = match config.flow_control { + FlowControl::None => 0x00, + FlowControl::RtsCts => 0x01, + }; + buf[7] = match config.data_bits { + DataBits::Bits5 => 0x00, + DataBits::Bits6 => 0x01, + DataBits::Bits7 => 0x02, + DataBits::Bits8 => 0x03, + }; + buf[8] = match config.stop_bits { + StopBits::Short => 0x00, + StopBits::Long => 0x01, + }; + + self.handle.send_feature_report(&buf[..])?; Ok(()) } @@ -237,38 +236,37 @@ impl HidUart { let mut buf: [u8; FEATURE_REPORT_LENGTH] = [0; FEATURE_REPORT_LENGTH]; buf[0] = GETSET_UART_CONFIG; - self.handle.feature().get(&mut buf[..])?; - - let baud_rate: u32 = u32::from(buf[1]) << 24 | u32::from(buf[2]) << 16 | u32::from(buf[3]) << 8 | u32::from(buf[4]); - let parity = - match buf[5] { - 0x00 => Ok(Parity::None), - 0x01 => Ok(Parity::Odd), - 0x02 => Ok(Parity::Even), - 0x03 => Ok(Parity::Mark), - 0x04 => Ok(Parity::Space), - _ => Err("Unknown parity mode"), - }?; - let flow_control = - match buf[6] { - 0x00 => Ok(FlowControl::None), - 0x01 => Ok(FlowControl::RtsCts), - _ => Err("Unknown flow control mode"), - }?; - let data_bits = - match buf[7] { - 0x00 => Ok(DataBits::Bits5), - 0x01 => Ok(DataBits::Bits6), - 0x02 => Ok(DataBits::Bits7), - 0x03 => Ok(DataBits::Bits8), - _ => Err("Unknown data bits mode"), - }?; - let stop_bits = - match buf[8] { - 0x00 => Ok(StopBits::Short), - 0x01 => Ok(StopBits::Long), - _ => Err("Unknown stop bits mode"), - }?; + self.handle.get_feature_report(&mut buf[..])?; + + let baud_rate: u32 = u32::from(buf[1]) << 24 + | u32::from(buf[2]) << 16 + | u32::from(buf[3]) << 8 + | u32::from(buf[4]); + let parity = match buf[5] { + 0x00 => Ok(Parity::None), + 0x01 => Ok(Parity::Odd), + 0x02 => Ok(Parity::Even), + 0x03 => Ok(Parity::Mark), + 0x04 => Ok(Parity::Space), + _ => Err("Unknown parity mode"), + }?; + let flow_control = match buf[6] { + 0x00 => Ok(FlowControl::None), + 0x01 => Ok(FlowControl::RtsCts), + _ => Err("Unknown flow control mode"), + }?; + let data_bits = match buf[7] { + 0x00 => Ok(DataBits::Bits5), + 0x01 => Ok(DataBits::Bits6), + 0x02 => Ok(DataBits::Bits7), + 0x03 => Ok(DataBits::Bits8), + _ => Err("Unknown data bits mode"), + }?; + let stop_bits = match buf[8] { + 0x00 => Ok(StopBits::Short), + 0x01 => Ok(StopBits::Long), + _ => Err("Unknown stop bits mode"), + }?; let config = UartConfig { baud_rate, parity, @@ -291,11 +289,14 @@ impl HidUart { buf[0] = PURGE_FIFOS; if rx { buf[1] |= PURGE_RECEIVE_MASK; + + // also dump any buffered data + self.rx_buffer.clear(); } if tx { buf[1] |= PURGE_TRANSMIT_MASK; } - self.handle.feature().send(&buf[..])?; + self.handle.send_feature_report(&buf[..])?; Ok(()) } @@ -304,17 +305,15 @@ impl HidUart { pub fn write(&mut self, data: &[u8]) -> Result<()> { let mut buf: [u8; INTERRUPT_REPORT_LENGTH]; - let mut data_handle = self.handle.data(); - let start_time = Instant::now(); for chunk in data.chunks(INTERRUPT_REPORT_LENGTH - 1) { + buf = [0; INTERRUPT_REPORT_LENGTH]; + buf[0] = chunk.len() as u8; + buf[1..chunk.len() + 1].copy_from_slice(chunk); + self.handle.write(&buf[..])?; if start_time.elapsed() > self.write_timeout { return Err(ErrorKind::WriteTimeout.into()); } - buf = [0; INTERRUPT_REPORT_LENGTH]; - buf[0] = chunk.len() as u8; - buf[1..chunk.len()+1].copy_from_slice(chunk); - data_handle.write(&buf[..])?; } Ok(()) @@ -322,26 +321,94 @@ impl HidUart { /// Receive `data` and returns a number of read bytes. pub fn read(&mut self, data: &mut [u8]) -> Result { + // drain any buffered data + let mut num_bytes_read = self.rx_buffer.read(data); + + // read from usb let mut buf: [u8; INTERRUPT_REPORT_LENGTH]; let start_time = Instant::now(); - let mut num_bytes_read = 0; - let mut data_handle = self.handle.data(); - while start_time.elapsed() < self.read_timeout { + loop { let data_free = data.len() - num_bytes_read; if data_free > 0 { buf = [0; INTERRUPT_REPORT_LENGTH]; - let buf_size = min(data_free, INTERRUPT_REPORT_LENGTH - 1) + 1; - if let Some(_) = data_handle.read(&mut buf[0..buf_size], Duration::from_millis(1))? { + let total_read = self.handle.read_timeout(&mut buf, 1)?; + if total_read != 0 { let report_len: usize = buf[0] as usize; - data[num_bytes_read..(num_bytes_read + report_len)].copy_from_slice(&buf[1..(report_len + 1)]); - num_bytes_read += report_len; - } else { - break; + let copy_len = min(report_len, data_free); + data[num_bytes_read..(num_bytes_read + copy_len)] + .copy_from_slice(&buf[1..(copy_len + 1)]); + num_bytes_read += copy_len; + + // buffer the left overs + if copy_len < report_len { + let left = report_len - copy_len; + let start = 1 + copy_len; + let end = start + left; + + self.rx_buffer.write(&buf[start..end]); + + return Ok(num_bytes_read); + } } } else { break; } + if start_time.elapsed() > self.read_timeout { + break; + } } + Ok(num_bytes_read) } } + +struct RxBuffer { + start: u8, + len: u8, + data: [u8; INTERRUPT_REPORT_LENGTH], +} + +impl RxBuffer { + fn new() -> Self { + Self { + start: 0, + len: 0, + data: [0; INTERRUPT_REPORT_LENGTH], + } + } + + fn read(&mut self, dest: &mut [u8]) -> usize { + if self.len == 0 { + return 0; + } + + let num_bytes_read = min(dest.len(), self.len as usize); + let start = self.start as usize; + let end = start + num_bytes_read; + let source_buf = &self.data[start..end]; + dest[0..num_bytes_read].copy_from_slice(&source_buf); + self.len -= num_bytes_read as u8; + if self.len == 0 { + self.start = 0; + } else { + self.start += num_bytes_read as u8; + } + + return num_bytes_read; + } + + fn write(&mut self, source: &[u8]) { + if source.len() == 0 { + return; + } + + self.data[0..source.len()].copy_from_slice(&source); + self.start = 0; + self.len = source.len() as u8; + } + + fn clear(&mut self) { + self.start = 0; + self.len = 0; + } +}