Skip to content

Commit

Permalink
feat: impl list_devices for windows driver
Browse files Browse the repository at this point in the history
  • Loading branch information
andelf committed Jan 7, 2024
1 parent 2239eec commit d30e946
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 18 deletions.
20 changes: 7 additions & 13 deletions src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
use std::time::Duration;

use log::info;
use rusb::{DeviceHandle, UsbContext};

use crate::{
commands::{control::ProbeInfo, ChipUID, RawCommand, Response},
Expand Down Expand Up @@ -146,7 +145,7 @@ impl WchLink {
/// Switch from DAP mode to RV mode
// ref: https://github.com/cjacker/wchlinke-mode-switch/blob/main/main.c
pub fn try_switch_from_rv_to_dap<USB: USBDeviceBackend>(nth: usize) -> Result<()> {
let mut dev = USB::open_nth(VENDOR_ID, PRODUCT_ID, nth)?;
let dev = USB::open_nth(VENDOR_ID, PRODUCT_ID, nth)?;
info!("Switch mode for WCH-LinkRV");

let mut dev = WchLink {
Expand Down Expand Up @@ -182,17 +181,12 @@ pub fn try_switch_from_dap_to_rv<USB: USBDeviceBackend>(nth: usize) -> Result<()
}

/// Check connected USB device
pub fn check_usb_device() -> Result<()> {
let context = rusb::Context::new()?;
log::trace!("Acquired libusb context.");

for device in context.devices()?.iter() {
let desc = device.device_descriptor()?;
if desc.vendor_id() == VENDOR_ID && desc.product_id() == PRODUCT_ID {
log::info!("Found WCH-LinkRV, {:?}", device);
} else if desc.vendor_id() == VENDOR_ID_DAP && desc.product_id() == PRODUCT_ID_DAP {
log::info!("Found WCH-LinkDAP, {:?}", device);
}
pub fn check_all_devices() -> Result<()> {
for dev in usb_device::list_devices(VENDOR_ID, PRODUCT_ID)? {
log::info!("Found WCH-LinkRV, {:?}", dev);
}
for dev in usb_device::list_devices(VENDOR_ID_DAP, PRODUCT_ID_DAP)? {
log::info!("Found WCH-LinkDAP, {:?}", dev);
}

Ok(())
Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,12 @@ fn main() -> Result<()> {

match cli.command {
None => {
wlink::device::check_usb_device()?;
wlink::device::check_all_devices()?;
println!("No command given, use --help for help.");
println!("hint: use `wlink status` to get started.");
}
Some(ModeSwitch { rv, dap }) => {
wlink::device::check_usb_device()?; // list all connected devices
wlink::device::check_all_devices()?; // list all connected devices
log::warn!("This is an experimental feature, better use the WCH-LinkUtility!");
if !(rv ^ dap) {
println!("Please choose one mode to switch, either --rv or --dap");
Expand Down
59 changes: 56 additions & 3 deletions src/usb_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ pub trait USBDeviceBackend {
fn write_endpoint(&mut self, ep: u8, buf: &[u8]) -> Result<()>;
}

pub fn open_nth(vid: u16, pid: u16, nth: usize) -> Result<Box<dyn USBDeviceBackend>> {
#[cfg(all(target_os = "windows", target_arch = "x86"))]
{
ch375_driver::USBDevice::open_nth(vid, pid, nth)
.or_else(|_| libusb::USBDevice::open_nth(vid, pid, nth))
}
#[cfg(not(all(target_os = "windows", target_arch = "x86")))]
{
libusb::USBDevice::open_nth(vid, pid, nth)
}
}

pub fn list_devices(vid: u16, pid: u16) -> Result<Vec<String>> {
let mut ret = vec![];
ret.extend(
Expand All @@ -23,12 +35,20 @@ pub fn list_devices(vid: u16, pid: u16) -> Result<Vec<String>> {
.map(|s| s.to_string()),
);

#[cfg(all(target_os = "windows", target_arch = "x86"))]
{
ret.extend(
ch375_driver::list_devices(vid, pid)?
.into_iter()
.map(|s| s.to_string()),
);
}

Ok(ret)
}

// pub use libusb::USBDevice;

pub use ch375_driver::USBDevice;
pub use libusb::USBDevice;
// pub use ch375_driver::USBDevice;

mod libusb {
use super::*;
Expand Down Expand Up @@ -126,6 +146,7 @@ mod libusb {
}
}

#[cfg(all(target_os = "windows", target_arch = "x86"))]
mod ch375_driver {
use libloading::os::windows::*;

Expand Down Expand Up @@ -179,6 +200,38 @@ mod ch375_driver {
bNumConfigurations: u8,
}

pub fn list_devices(vid: u16, pid: u16) -> Result<Vec<impl Display>> {
let lib = ensure_library_load()?;
let mut ret: Vec<String> = vec![];

let open_device: Symbol<unsafe extern "stdcall" fn(u32) -> u32> =
unsafe { lib.get(b"CH375OpenDevice").unwrap() };
let close_device: Symbol<unsafe extern "stdcall" fn(u32)> =
unsafe { lib.get(b"CH375CloseDevice").unwrap() };
let get_device_descriptor: Symbol<
unsafe extern "stdcall" fn(u32, *mut UsbDeviceDescriptor, *mut u32) -> bool,
> = unsafe { lib.get(b"CH375GetDeviceDescr").unwrap() };

const INVALID_HANDLE: u32 = 0xffffffff;

for i in 0..8 {
let h = unsafe { open_device(i) };
if h != INVALID_HANDLE {
let mut descr = unsafe { core::mem::zeroed() };
let mut len = core::mem::size_of::<UsbDeviceDescriptor>() as u32;
let _ = unsafe { get_device_descriptor(i, &mut descr, &mut len) };
let vid = descr.idVendor;
let pid = descr.idProduct;

log::debug!("Device #{}: {:04x}:{:04x}", i, vid, pid);
if vid == vid && pid == pid {
ret.push(format!("<WCH-Link#{}> {:04x}:{:04x}", i, vid, pid));
}
unsafe { close_device(i) };
}
}
}

pub struct USBDevice {
index: u32,
}
Expand Down

0 comments on commit d30e946

Please sign in to comment.