Files
OpenSK/patches/tock/04-vendor-hid.patch
Jean-Michel Picod e3d2e7d778 Fix USB enumeration on OS X (#640)
Hopefully without breaking the others.

Summary of the changes:
- Device descriptor reports the device is bus powered and requires
  100mA max.
- HID descriptor version bumped to 1.11 (was 1.10)
- Added string index for Interface and HID descriptors (which seems to
  make OS X happy)
2023-07-26 14:21:55 +02:00

156 lines
7.2 KiB
Diff

diff --git a/capsules/Cargo.toml b/capsules/Cargo.toml
index 65301bcf1..dc70e98b1 100644
--- a/capsules/Cargo.toml
+++ b/capsules/Cargo.toml
@@ -8,3 +8,6 @@ edition = "2021"
kernel = { path = "../kernel" }
enum_primitive = { path = "../libraries/enum_primitive" }
tickv = { path = "../libraries/tickv" }
+
+[features]
+vendor_hid = []
diff --git a/capsules/src/usb/descriptors.rs b/capsules/src/usb/descriptors.rs
index 9c5bc9cd1..c3ed71c44 100644
--- a/capsules/src/usb/descriptors.rs
+++ b/capsules/src/usb/descriptors.rs
@@ -415,13 +415,14 @@ impl DescriptorBuffer {
/// example, if the interface descriptor list contains `[ID1, ID2, ID3]`,
/// and the endpoint descriptors list is `[[ED1, ED2], [ED3, ED4, ED5],
/// [ED6]]`, then the third interface descriptor (`ID3`) has one
-/// corresponding endpoint descriptor (`ED6`).
+/// corresponding endpoint descriptor (`ED6`). If supplied, each HID descriptor
+/// corresponds to the matching index in the interface descriptor list.
pub fn create_descriptor_buffers(
device_descriptor: DeviceDescriptor,
mut configuration_descriptor: ConfigurationDescriptor,
interface_descriptor: &mut [InterfaceDescriptor],
endpoint_descriptors: &[&[EndpointDescriptor]],
- hid_descriptor: Option<&HIDDescriptor>,
+ hid_descriptor: Option<&[&HIDDescriptor<'static>]>,
cdc_descriptor: Option<&[CdcInterfaceDescriptor]>,
) -> (DeviceBuffer, DescriptorBuffer) {
// Create device descriptor buffer and fill.
@@ -505,7 +506,7 @@ pub fn create_descriptor_buffers(
.iter()
.map(|descs| descs.iter().map(|d| d.size()).sum::<usize>())
.sum::<usize>()
- + hid_descriptor.map_or(0, |d| d.size())
+ + hid_descriptor.map_or(0, |ds| ds.iter().map(|d| d.size()).sum::<usize>())
+ cdc_descriptor.map_or(0, |ds| ds.iter().map(|d| d.size()).sum::<usize>());
// Set the number of endpoints for each interface descriptor.
@@ -522,12 +523,10 @@ pub fn create_descriptor_buffers(
// Add the interface descriptor.
len += d.write_to(&other_buf.buf[len..]);
- // If there is a HID descriptor, we include
- // it with the first interface descriptor.
- if i == 0 {
- // HID descriptor, if any.
- if let Some(dh) = hid_descriptor {
- len += dh.write_to(&other_buf.buf[len..]);
+ // HID descriptor, if present, for this interface.
+ if let Some(dh) = hid_descriptor {
+ if let Some(d) = dh.get(i) {
+ len += d.write_to(&other_buf.buf[len..]);
}
}
diff --git a/capsules/src/usb/usbc_client_ctrl.rs b/capsules/src/usb/usbc_client_ctrl.rs
index c8e55a8a8..54c7c3bbb 100644
--- a/capsules/src/usb/usbc_client_ctrl.rs
+++ b/capsules/src/usb/usbc_client_ctrl.rs
@@ -40,6 +40,12 @@ const DESCRIPTOR_BUFLEN: usize = 128;
const N_ENDPOINTS: usize = 3;
+#[cfg(feature = "vendor_hid")]
+const N_HID_INTERFACES: usize = 2;
+
+#[cfg(not(feature = "vendor_hid"))]
+const N_HID_INTERFACES: usize = 1;
+
/// Handler for USB control endpoint requests.
pub struct ClientCtrl<'a, 'b, U: 'a> {
/// The USB hardware controller.
@@ -66,12 +72,12 @@ pub struct ClientCtrl<'a, 'b, U: 'a> {
/// An optional HID descriptor for the configuration. This can be requested
/// separately. It must also be included in `other_descriptor_buffer` if it exists.
- hid_descriptor: Option<&'b HIDDescriptor<'b>>,
+ hid_descriptor: Option<[&'b HIDDescriptor<'b>; N_HID_INTERFACES]>,
/// An optional report descriptor for the configuration. This can be
/// requested separately. It must also be included in
/// `other_descriptor_buffer` if it exists.
- report_descriptor: Option<&'b ReportDescriptor<'b>>,
+ report_descriptor: Option<[&'b ReportDescriptor<'b>; N_HID_INTERFACES]>,
/// Supported language (only one for now).
language: &'b [u16; 1],
@@ -106,8 +112,8 @@ impl<'a, 'b, U: hil::usb::UsbController<'a>> ClientCtrl<'a, 'b, U> {
controller: &'a U,
device_descriptor_buffer: DeviceBuffer,
other_descriptor_buffer: DescriptorBuffer,
- hid_descriptor: Option<&'b HIDDescriptor<'b>>,
- report_descriptor: Option<&'b ReportDescriptor<'b>>,
+ hid_descriptor: Option<[&'b HIDDescriptor<'b>; N_HID_INTERFACES]>,
+ report_descriptor: Option<[&'b ReportDescriptor<'b>; N_HID_INTERFACES]>,
language: &'b [u16; 1],
strings: &'b [&'b str],
) -> Self {
@@ -333,28 +339,39 @@ impl<'a, 'b, U: hil::usb::UsbController<'a>> ClientCtrl<'a, 'b, U> {
descriptor_type,
// TODO: use the descriptor index
descriptor_index: _,
- // TODO: use the language ID?
- lang_id: _,
+ lang_id,
requested_length,
} => match descriptor_type {
DescriptorType::HID => {
- if let Some(desc) = self.hid_descriptor {
- let buf = self.descriptor_buf();
- let len = desc.write_to(buf);
- let end = min(len, requested_length as usize);
- self.state[endpoint].set(State::CtrlIn(0, end));
- hil::usb::CtrlSetupResult::Ok
+ if let Some(dh) = self.hid_descriptor {
+ let interface = lang_id as usize;
+ if interface < dh.len() {
+ let d = dh[interface];
+ let buf = self.descriptor_buf();
+ let len = d.write_to(buf);
+ let end = min(len, requested_length as usize);
+ self.state[endpoint].set(State::CtrlIn(0, end));
+ hil::usb::CtrlSetupResult::Ok
+ } else {
+ hil::usb::CtrlSetupResult::ErrGeneric
+ }
} else {
hil::usb::CtrlSetupResult::ErrGeneric
}
}
DescriptorType::Report => {
- if let Some(desc) = self.report_descriptor {
- let buf = self.descriptor_buf();
- let len = desc.write_to(buf);
- let end = min(len, requested_length as usize);
- self.state[endpoint].set(State::CtrlIn(0, end));
- hil::usb::CtrlSetupResult::Ok
+ if let Some(desc_array) = self.report_descriptor {
+ let interface = lang_id as usize;
+ if interface < desc_array.len() {
+ let desc = desc_array[interface];
+ let buf = self.descriptor_buf();
+ let len = desc.write_to(buf);
+ let end = min(len, requested_length as usize);
+ self.state[endpoint].set(State::CtrlIn(0, end));
+ hil::usb::CtrlSetupResult::Ok
+ } else {
+ hil::usb::CtrlSetupResult::ErrGeneric
+ }
} else {
hil::usb::CtrlSetupResult::ErrGeneric
}