dap_rs/usb/
dap_v1.rs

1use super::Request;
2use super::DAP1_PACKET_SIZE;
3use usb_device::class_prelude::*;
4use usb_device::control::{Recipient, RequestType};
5use usb_device::{device, Result};
6
7const INTERFACE_CLASS_HID: u8 = 0x03;
8
9#[derive(Debug, Clone, Copy)]
10#[repr(u8)]
11pub enum DescriptorType {
12    Hid = 0x21,
13    Report = 0x22,
14}
15
16const REPORT_DESCRIPTOR: &[u8] = &[
17    0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
18    0x09, 0x01, // Usage (0x01)
19    0xA1, 0x01, // Collection (Application)
20    0x15, 0x00, //   Logical Minimum (0)
21    0x25, 0xFF, //   Logical Maximum (255)
22    0x75, 0x08, //   Report Size (8)
23    0x95, 0x40, //   Report Count (64)
24    0x09, 0x01, //   Usage (0x01)
25    0x81, 0x02, //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
26    0x95, 0x40, //   Report Count (64)
27    0x09, 0x01, //   Usage (0x01)
28    0x91,
29    0x02, //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
30    0x95, 0x01, //   Report Count (1)
31    0x09, 0x01, //   Usage (0x01)
32    0xB1,
33    0x02, //   Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
34    0xC0, // End Collection
35
36          // 32 bytes
37];
38
39pub struct CmsisDapV1<'a, B: UsbBus> {
40    interface: InterfaceNumber,
41    name: StringIndex,
42    read_ep: EndpointOut<'a, B>,
43    write_ep: EndpointIn<'a, B>,
44}
45
46impl<B: UsbBus> CmsisDapV1<'_, B> {
47    pub fn new(max_packet_size: u16, alloc: &UsbBusAllocator<B>) -> CmsisDapV1<B> {
48        CmsisDapV1 {
49            interface: alloc.interface(),
50            name: alloc.string(),
51            read_ep: alloc.interrupt(max_packet_size, 1),
52            write_ep: alloc.interrupt(max_packet_size, 1),
53        }
54    }
55
56    pub fn process(&mut self) -> Option<Request> {
57        let mut buf = [0u8; DAP1_PACKET_SIZE as usize];
58        match self.read_ep.read(&mut buf) {
59            Ok(size) if size > 0 => Some(Request::DAP1Command((buf, size))),
60            _ => None,
61        }
62    }
63
64    pub fn write_packet(&mut self, data: &[u8]) -> Result<()> {
65        if data.len() > self.write_ep.max_packet_size() as usize {
66            return Err(UsbError::BufferOverflow);
67        }
68        self.write_ep.write(&data).map(|_| ())
69    }
70}
71
72impl<B: UsbBus> UsbClass<B> for CmsisDapV1<'_, B> {
73    fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> {
74        writer.interface_alt(
75            self.interface,
76            device::DEFAULT_ALTERNATE_SETTING,
77            INTERFACE_CLASS_HID,
78            0,
79            0,
80            Some(self.name),
81        )?;
82
83        let descriptor_len = REPORT_DESCRIPTOR.len();
84        if descriptor_len > u16::max_value() as usize {
85            return Err(UsbError::InvalidState);
86        }
87        let descriptor_len = (descriptor_len as u16).to_le_bytes();
88        writer.write(
89            DescriptorType::Hid as u8,
90            &[
91                0x11,                         // bcdHID.lower
92                0x01,                         // bcdHID.upper
93                0x00,                         // bCountryCode: 0 = not supported
94                0x01,                         // bNumDescriptors
95                DescriptorType::Report as u8, // bDescriptorType
96                descriptor_len[0],            // bDescriptorLength.lower
97                descriptor_len[1],            // bDescriptorLength.upper
98            ],
99        )?;
100
101        writer.endpoint(&self.read_ep)?;
102        writer.endpoint(&self.write_ep)?;
103
104        Ok(())
105    }
106
107    fn get_string(&self, index: StringIndex, _lang_id: LangID) -> Option<&str> {
108        if index == self.name {
109            Some("CMSIS-DAP v1 Interface")
110        } else {
111            None
112        }
113    }
114
115    fn control_in(&mut self, xfer: ControlIn<B>) {
116        let req = xfer.request();
117        if !(req.request_type == RequestType::Standard
118            && req.recipient == Recipient::Interface
119            && req.index == u8::from(self.interface) as u16)
120        {
121            return;
122        }
123
124        if req.request == control::Request::GET_DESCRIPTOR {
125            let (dtype, index) = req.descriptor_type_index();
126            if dtype == DescriptorType::Report as u8 && index == 0 {
127                xfer.accept_with(REPORT_DESCRIPTOR).ok();
128            }
129        }
130    }
131}