diff options
Diffstat (limited to 'usbh/src/pipe/addr.rs')
-rw-r--r-- | usbh/src/pipe/addr.rs | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/usbh/src/pipe/addr.rs b/usbh/src/pipe/addr.rs new file mode 100644 index 0000000..8b92177 --- /dev/null +++ b/usbh/src/pipe/addr.rs @@ -0,0 +1,87 @@ +/// ยง 32.8.7.2 +/// Address of the Data Buffer. +/// +/// Offset: 0x00 & 0x10 +/// Reset: 0xxxxxxxxx +/// Property: NA +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub(crate) struct Addr(u32); + +pub(crate) struct R { + bits: u32, +} + +pub(crate) struct W { + bits: u32, +} + +impl Addr { + pub fn read(&self) -> R { + R { bits: self.0 } + } + + pub fn write<F>(&mut self, f: F) + where + F: FnOnce(&mut W) -> &mut W, + { + let mut w = W { bits: self.0 }; + f(&mut w); + // Address must be 32-bit aligned. + assert!((w.bits & 0x3) == 0); + self.0 = w.bits; + } +} + +impl From<u32> for Addr { + fn from(v: u32) -> Self { + Self(v) + } +} + +impl R { + /// Value in raw bits. + pub fn bits(&self) -> u32 { + self.bits + } + + pub fn addr(&self) -> AddrR { + AddrR(self.bits) + } +} + +/// Data Pointer Address Value +/// +/// These bits define the data pointer address as an absolute double +/// word address in RAM. The two least significant bits must be zero +/// to ensure the descriptor is 32-bit aligned. +pub(crate) struct AddrR(u32); +impl AddrR { + pub fn bits(&self) -> u32 { + self.0 + } +} + +impl W { + /// Write raw bits. + pub unsafe fn bits(&mut self, v: u32) -> &mut Self { + self.bits = v; + self + } + + pub fn addr(&mut self) -> AddrW { + AddrW { w: self } + } +} + +pub(crate) struct AddrW<'a> { + w: &'a mut W, +} +impl<'a> AddrW<'a> { + pub unsafe fn bits(self, v: u32) -> &'a mut W { + self.w.bits = v; + self.w + } + + // TODO: "safe" method take a pointer instead of raw u32 +} |