#![no_std] mod types; fn poll(&self) -> PollResult { free(|cs| { let usb = self.usb.borrow(cs); let (usbint, udint, udien) = (usb.usbint.read(), usb.udint.read(), usb.udien.read()); if usbint.vbusti().bit_is_set() { usb.usbint.write(|w| w.vbusti().clear_bit()); if usb.usbsta.read().vbus().bit_is_set() { return PollResult::Resume; } else { return PollResult::Suspend; } } if udint.suspi().bit_is_set() && udien.suspe().bit_is_set() { return PollResult::Suspend; } if udint.wakeupi().bit_is_set() && udien.wakeupe().bit_is_set() { return PollResult::Resume; } if udint.eorsti().bit_is_set() { return PollResult::Reset; } if udint.sofi().bit_is_set() { usb.udint.write(|w| w.sofi().clear_bit()); } // Can only query endpoints while clock is running // (e.g. not in suspend state) if usb.usbcon.read().frzclk().bit_is_clear() { let (mut ep_out, mut ep_setup, mut ep_in_complete) = (0u8, 0u8, 0u8); for (index, _ep) in self .ep_table .iter() .enumerate() .filter(|(_i, e)| e.is_allocated) { if self.select_endpoint(cs, index).is_err() { // Endpoint selection has stopped working... break; } let ueintx = usb.ueintx.read(); if ueintx.rxouti().bit_is_set() { ep_out |= 1 << index; } if ueintx.rxstpi().bit_is_set() { ep_setup |= 1 << index; } if ueintx.txini().bit_is_set() { ep_in_complete |= 1 << index; } } if ep_out | ep_setup | ep_in_complete != 0 { return PollResult::Data { ep_out: ep_out as u16, ep_in_complete: ep_in_complete as u16, ep_setup: ep_setup as u16, }; } } PollResult::None }) } fn read(&self, ep_addr: EndpointAddress, buf: &mut [u8]) -> UsbResult { free(|cs| { let usb = self.usb.borrow(cs); match self.select_endpoint(cs, ep_addr.index()) { Ok(()) => { let target_endpoint = self.ep_table[ep_addr.index()]; let ueintx = usb.ueintx.read(); if ueintx.rxouti().bit_is_clear() { return Err(UsbError::WouldBlock); } if target_endpoint.ep_type == 0 { let bytes_count_to_read: usize = (usb.uebchx.read().bits() as usize) << 8 | (usb.uebclx.read().bits() as usize); if bytes_count_to_read > buf.len() { return Err(UsbError::BufferOverflow); } for slot in &mut buf[..bytes_count_to_read] { *slot = usb.uedatx.read().bits(); } usb.ueintx .write(|w| w.rxouti().clear_bit().rxstpi().clear_bit()); Ok(bytes_count_to_read) } else { usb.ueintx.write(|w| w.rxouti().clear_bit()); let mut bytes_read = 0; for slot in buf { if usb.ueintx.read().rwal().bit_is_clear() { break; } *slot = usb.uedatx.read().bits(); bytes_read += 1; } if usb.ueintx.read().rwal().bit_is_set() { return Err(UsbError::BufferOverflow); } usb.ueintx.write(|w| w.fifocon().clear_bit()); Ok(bytes_read) } } Err(err) => Err(err), } }) } fn write(&self, ep_addr: EndpointAddress, buf: &[u8]) -> UsbResult { free(|cs| { let usb = self.usb.borrow(cs); match self.select_endpoint(cs, ep_addr.index()) { Ok(()) => { let target_endpoint = self.ep_table[ep_addr.index()]; let ueintx = usb.ueintx.read(); if ueintx.rxouti().bit_is_clear() { return Err(UsbError::WouldBlock); } if target_endpoint.ep_type == 0 { let bytes_count_to_read: usize = (usb.uebchx.read().bits() as usize) << 8 | (usb.uebclx.read().bits() as usize); if bytes_count_to_read > buf.len() { return Err(UsbError::BufferOverflow); } buf.iter() .for_each(|&byte| usb.uedatx.write(|w| w.bits(byte))); usb.ueintx .write(|w| w.rxouti().clear_bit().rxstpi().clear_bit()); Ok(bytes_count_to_read) } else { usb.ueintx .write(|w| w.txini().clear_bit().rxouti().clear_bit()); for &byte in buf { if usb.ueintx.read().rwal().bit_is_set() { return Err(UsbError::BufferOverflow); } else { usb.uedatx.write(|w| w.bits(byte)); } } usb.ueintx .write(|w| w.fifocon().clear_bit().rxouti().clear_bit()); Ok(buf.len()) } } Err(err) => Err(err), } }) }