crab-usb 0.9.10

A usb host for embedded systems, written in Rust.
Documentation
use std::sync::Arc;

use libusb1_sys::*;

use crate::err::*;

pub struct Context(*mut libusb1_sys::libusb_context);

unsafe impl Send for Context {}
unsafe impl Sync for Context {}

impl Context {
    pub fn new() -> Result<Arc<Self>> {
        let mut ctx = std::ptr::null_mut();
        usb!(libusb1_sys::libusb_init(&mut ctx))?;
        Ok(Arc::new(Self(ctx)))
    }

    pub fn device_list(&self) -> crate::err::Result<DeviceList> {
        let mut list: *const *mut libusb_device = std::ptr::null_mut();
        let count = unsafe { libusb1_sys::libusb_get_device_list(self.0, &mut list) };
        Ok(DeviceList {
            list,
            len: count as usize,
        })
    }

    pub fn handle_events(&self) -> Result<()> {
        usb!(libusb1_sys::libusb_handle_events(self.0))?;
        Ok(())
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            libusb1_sys::libusb_exit(self.0);
        }
    }
}

pub struct DeviceList {
    list: *const *mut libusb_device,
    len: usize,
}

impl Iterator for DeviceList {
    type Item = *mut libusb_device;

    fn next(&mut self) -> Option<Self::Item> {
        if self.len == 0 {
            return None;
        }
        unsafe {
            let device = *self.list;
            self.list = self.list.add(1);
            self.len -= 1;
            Some(device)
        }
    }
}

impl Drop for DeviceList {
    fn drop(&mut self) {
        if self.len == 0 {
            return;
        }
        unsafe {
            libusb1_sys::libusb_free_device_list(self.list, 1);
        }
    }
}