use std::str; use std::thread::sleep; use std::time::Duration; use rusb::{ Context, DeviceHandle, UsbContext, }; fn main() { let args: Vec = std::env::args().collect(); if args.len() < 2 { println!("usage: {0} ", args[0]); return; } match Context::new() { Ok(mut context) => match open_orbic(&mut context) { Some(mut handle) => { send_command(&mut handle, &args[1]) }, None => panic!("No Orbic device found"), }, Err(e) => panic!("Failed to initialize libusb: {0}", e), } } fn send_command( handle: &mut DeviceHandle, command: &str, ) { let mut data = String::new(); data.push_str("\r\n"); data.push_str(command); data.push_str("\r\n"); let timeout = Duration::from_secs(1); let mut response = [0; 256]; // Set up the serial port appropriately handle.write_control(0x21, 0x22, 3, 1, &[], timeout).expect("Failed to send control request"); // Send the command handle.write_bulk(0x2, data.as_bytes(), timeout).expect("Failed to write command"); // Consume the echoed command handle.read_bulk(0x82, &mut response, timeout).expect("Failed to read submitted command"); // Read the actual response handle.read_bulk(0x82, &mut response, timeout).expect("Failed to read response"); let responsestr = str::from_utf8(&response).expect("Failed to parse response"); if !responsestr.starts_with("\r\nOK\r\n") { println!("Received unexpected response{0}", responsestr) } } fn switch_device( handle: &mut DeviceHandle, ) { // Send a command to switch the device into generic mode, exposing serial let timeout = Duration::from_secs(1); if let Err(e) = handle.write_control(0x40, 0xa0, 0, 0, &[], timeout) { // If the device reboots while the command is still executing we // may get a pipe error here if e == rusb::Error::Pipe { return } panic!("Failed to send device switch control request: {0}", e) } } fn open_orbic( context: &mut T, ) -> Option> { // Device after initial mode switch if let Some(handle) = open_device(context, 0x05c6, 0xf601) { return Some(handle) } // Device with rndis enabled as well if let Some(handle) = open_device(context, 0x05c6, 0xf622) { return Some(handle) } // Device in out-of-the-box state, need to switch to diag mode match open_device(context, 0x05c6, 0xf626) { Some(mut handle) => switch_device(&mut handle), None => panic!("No Orbic device detected") } for _ in 1..10 { if let Some(handle) = open_device(context, 0x05c6, 0xf601) { return Some(handle) } sleep(Duration::from_secs(10)) } panic!("No Orbic device detected") } fn open_device( context: &mut T, vid: u16, pid: u16, ) -> Option> { let devices = match context.devices() { Ok(d) => d, Err(_) => return None, }; for device in devices.iter() { let device_desc = match device.device_descriptor() { Ok(d) => d, Err(_) => continue, }; if device_desc.vendor_id() == vid && device_desc.product_id() == pid { match device.open() { Ok(handle) => return Some(handle), Err(e) => panic!("device found but failed to open: {}", e), } } } None }