use core::convert::TryInto; const MAX_DEVICES: usize = 16; const MAX_ENDPOINTS: usize = 8; pub struct DeviceTable { devices: [Option; MAX_DEVICES], } impl DeviceTable { pub fn new() -> Self { Self { devices: Default::default(), } } /// Return the device at address `addr`. pub fn device_for(&mut self, addr: u8) -> Option<&mut Device> { if let Some(ref mut d) = self.devices[addr as usize] { Some(d) } else { None } } /// Allocate a device with the next available address. pub fn next(&mut self) -> Option<&mut Device> { for i in 0..self.devices.len() { if self.devices[i].is_none() { let a = i.try_into().unwrap(); let mut d: Device = Default::default(); d.addr = a; self.devices[i] = Some(d); return self.device_for(a); } } None } /// Remove the device at address `addr`. pub fn remove(&mut self, addr: u8) -> Option { let v = core::mem::replace(&mut self.devices[addr as usize], None); v } } pub struct Device { addr: u8, max_packet_size: u8, endpoints: [Endpoint; MAX_ENDPOINTS], } impl Default for Device { fn default() -> Self { Self { addr: 0, max_packet_size: 8, endpoints: Default::default(), } } } pub struct Endpoint { num: u8, typ: EndpointType, } impl Default for Endpoint { fn default() -> Self { Self { num: 0, typ: EndpointType::Control, } } } enum EndpointType { Control, In, Out, }