1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//! Abstract Human Interface Device Interfaces
use frunk::{HCons, HNil, ToMut};
use packed_struct::prelude::*;
use usb_device::bus::{StringIndex, UsbBus, UsbBusAllocator};
use usb_device::class_prelude::DescriptorWriter;

use crate::hid_class::descriptor::DescriptorType;

use self::raw::RawInterface;

pub mod managed;
pub mod raw;

#[derive(Clone, Copy, Debug, PartialEq, Eq, PackedStruct)]
#[packed_struct(endian = "lsb", size_bytes = 7)]
pub struct HidDescriptorBody {
    bcd_hid: u16,
    country_code: u8,
    num_descriptors: u8,
    #[packed_field(ty = "enum", size_bytes = "1")]
    descriptor_type: DescriptorType,
    descriptor_length: u16,
}

pub trait UsbAllocatable<'a, B: UsbBus> {
    type Allocated;
    fn allocate(self, usb_alloc: &'a UsbBusAllocator<B>) -> Self::Allocated;
}

impl<'a, B: UsbBus + 'a> UsbAllocatable<'a, B> for HNil {
    type Allocated = Self;

    fn allocate(self, _: &'a UsbBusAllocator<B>) -> Self::Allocated {
        self
    }
}

impl<'a, B, C, Tail> UsbAllocatable<'a, B> for HCons<C, Tail>
where
    B: UsbBus + 'a,
    C: UsbAllocatable<'a, B>,
    Tail: UsbAllocatable<'a, B>,
{
    type Allocated = HCons<C::Allocated, Tail::Allocated>;

    fn allocate(self, usb_alloc: &'a UsbBusAllocator<B>) -> Self::Allocated {
        HCons {
            head: self.head.allocate(usb_alloc),
            tail: self.tail.allocate(usb_alloc),
        }
    }
}

pub trait InterfaceClass<'a, B: UsbBus> {
    fn interface(&mut self) -> &mut RawInterface<'a, B>;
    fn reset(&mut self);
}

pub trait InterfaceHList<'a, B>: ToMut<'a> {
    fn get(&mut self, id: u8) -> Option<&mut dyn InterfaceClass<'a, B>>;
    fn reset(&mut self);
    fn write_descriptors(&mut self, writer: &mut DescriptorWriter) -> usb_device::Result<()>;
    fn get_string(&mut self, index: StringIndex, lang_id: u16) -> Option<&'a str>;
}

impl<'a, B> InterfaceHList<'a, B> for HNil {
    fn get(&mut self, _: u8) -> Option<&mut dyn InterfaceClass<'a, B>> {
        None
    }

    fn reset(&mut self) {}

    fn write_descriptors(&mut self, _: &mut DescriptorWriter) -> usb_device::Result<()> {
        Ok(())
    }

    fn get_string(&mut self, _: StringIndex, _: u16) -> Option<&'a str> {
        None
    }
}

impl<'a, B: UsbBus + 'a, Head: InterfaceClass<'a, B> + 'a, Tail: InterfaceHList<'a, B>>
    InterfaceHList<'a, B> for HCons<Head, Tail>
{
    fn get(&mut self, id: u8) -> Option<&mut dyn InterfaceClass<'a, B>> {
        if id == u8::from(self.head.interface().id()) {
            Some(&mut self.head)
        } else {
            self.tail.get(id)
        }
    }

    fn reset(&mut self) {
        self.head.interface().reset();
        self.head.reset();
        self.tail.reset();
    }

    fn write_descriptors(&mut self, writer: &mut DescriptorWriter) -> usb_device::Result<()> {
        self.head.interface().write_descriptors(writer)?;
        self.tail.write_descriptors(writer)
    }

    fn get_string(&mut self, index: StringIndex, lang_id: u16) -> Option<&'a str> {
        let s = self.head.interface().get_string(index, lang_id);
        if s.is_some() {
            s
        } else {
            self.tail.get_string(index, lang_id)
        }
    }
}