From 096fda843a2ddb5db006b573afe946819a8bdce8 Mon Sep 17 00:00:00 2001 From: Tobias Kohlbau Date: Thu, 29 Feb 2024 14:39:09 +0100 Subject: [PATCH] usb: unify handling of length parameters (#177) * usb: unify handling of length parameters The length parameters in USB packets are strict and the existing implementation does already hardcode the length within the serialize functions. Therefore the user should not provide these lengths during creation time. In order to make this more verbose use defaults values within the structs and reference these defaults values within the serialization functions. It's not possible to remove these fields completly as this fields are used within deserialization from the hardware itself. Signed-off-by: Tobias Kohlbau * Remove length fields as they are obsolete. The lengths is only required during the serialization and therefore is already hardcoded. The only other convinience is the calculation of the descriptor size, but this is already wrong. extern structs are padded and therefore do not have the right sizes. Signed-off-by: Tobias Kohlbau * cleanup some accidentially added changes Signed-off-by: Tobias Kohlbau --------- Signed-off-by: Tobias Kohlbau --- .../raspberrypi-rp2040/src/hal/usb.zig | 2 -- core/src/core/usb.zig | 32 ++++++------------- core/src/core/usb/hid.zig | 5 ++- .../raspberrypi-rp2040/src/usb_device.zig | 9 ++---- examples/raspberrypi-rp2040/src/usb_hid.zig | 9 ++---- 5 files changed, 18 insertions(+), 39 deletions(-) diff --git a/board-support/raspberrypi-rp2040/src/hal/usb.zig b/board-support/raspberrypi-rp2040/src/hal/usb.zig index 3177047..575a4d3 100644 --- a/board-support/raspberrypi-rp2040/src/hal/usb.zig +++ b/board-support/raspberrypi-rp2040/src/hal/usb.zig @@ -42,7 +42,6 @@ pub const utf8ToUtf16Le = usb.utf8Toutf16Le; pub var EP0_OUT_CFG: usb.EndpointConfiguration = .{ .descriptor = &usb.EndpointDescriptor{ - .length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.EP0_OUT_ADDR, .attributes = @intFromEnum(usb.TransferType.Control), @@ -57,7 +56,6 @@ pub var EP0_OUT_CFG: usb.EndpointConfiguration = .{ pub var EP0_IN_CFG: usb.EndpointConfiguration = .{ .descriptor = &usb.EndpointDescriptor{ - .length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.EP0_IN_ADDR, .attributes = @intFromEnum(usb.TransferType.Control), diff --git a/core/src/core/usb.zig b/core/src/core/usb.zig index a7b4e56..9f38ed9 100644 --- a/core/src/core/usb.zig +++ b/core/src/core/usb.zig @@ -511,9 +511,7 @@ pub const Dir = enum(u8) { }; /// Describes an endpoint within an interface -pub const EndpointDescriptor = extern struct { - /// Length of this struct, must be 7. - length: u8, +pub const EndpointDescriptor = struct { /// Type of this descriptor, must be `Endpoint`. descriptor_type: DescType, /// Address of this endpoint, where the bottom 4 bits give the endpoint @@ -530,7 +528,7 @@ pub const EndpointDescriptor = extern struct { pub fn serialize(self: *const @This()) [7]u8 { var out: [7]u8 = undefined; - out[0] = 7; // length + out[0] = out.len; out[1] = @intFromEnum(self.descriptor_type); out[2] = self.endpoint_address; out[3] = self.attributes; @@ -542,9 +540,7 @@ pub const EndpointDescriptor = extern struct { }; /// Description of an interface within a configuration. -pub const InterfaceDescriptor = extern struct { - /// Length of this structure, must be 9. - length: u8, +pub const InterfaceDescriptor = struct { /// Type of this descriptor, must be `Interface`. descriptor_type: DescType, /// ID of this interface. @@ -566,7 +562,7 @@ pub const InterfaceDescriptor = extern struct { pub fn serialize(self: *const @This()) [9]u8 { var out: [9]u8 = undefined; - out[0] = 9; // length + out[0] = out.len; out[1] = @intFromEnum(self.descriptor_type); out[2] = self.interface_number; out[3] = self.alternate_setting; @@ -580,9 +576,7 @@ pub const InterfaceDescriptor = extern struct { }; /// Description of a single available device configuration. -pub const ConfigurationDescriptor = extern struct { - /// Length of this structure, must be 9. - length: u8, +pub const ConfigurationDescriptor = struct { /// Type of this descriptor, must be `Config`. descriptor_type: DescType, /// Total length of all descriptors in this configuration, concatenated. @@ -610,7 +604,7 @@ pub const ConfigurationDescriptor = extern struct { pub fn serialize(self: *const @This()) [9]u8 { var out: [9]u8 = undefined; - out[0] = 9; // length + out[0] = out.len; out[1] = @intFromEnum(self.descriptor_type); out[2] = @intCast(self.total_length & 0xff); out[3] = @intCast((self.total_length >> 8) & 0xff); @@ -625,9 +619,7 @@ pub const ConfigurationDescriptor = extern struct { /// Describes a device. This is the most broad description in USB and is /// typically the first thing the host asks for. -pub const DeviceDescriptor = extern struct { - /// Length of this structure, must be 18. - length: u8, +pub const DeviceDescriptor = struct { /// Type of this descriptor, must be `Device`. descriptor_type: DescType, /// Version of the device descriptor / USB protocol, in binary-coded @@ -658,7 +650,7 @@ pub const DeviceDescriptor = extern struct { pub fn serialize(self: *const @This()) [18]u8 { var out: [18]u8 = undefined; - out[0] = 18; // length + out[0] = out.len; out[1] = @intFromEnum(self.descriptor_type); out[2] = @intCast(self.bcd_usb & 0xff); out[3] = @intCast((self.bcd_usb >> 8) & 0xff); @@ -682,9 +674,7 @@ pub const DeviceDescriptor = extern struct { /// USB Device Qualifier Descriptor /// This descriptor is mostly the same as the DeviceDescriptor -pub const DeviceQualifierDescriptor = extern struct { - /// Length of this structure, must be 18. - length: u8 = 10, +pub const DeviceQualifierDescriptor = struct { /// Type of this descriptor, must be `Device`. descriptor_type: DescType = DescType.DeviceQualifier, /// Version of the device descriptor / USB protocol, in binary-coded @@ -705,7 +695,7 @@ pub const DeviceQualifierDescriptor = extern struct { pub fn serialize(self: *const @This()) [10]u8 { var out: [10]u8 = undefined; - out[0] = 10; // length + out[0] = out.len; out[1] = @intFromEnum(self.descriptor_type); out[2] = @intCast(self.bcd_usb & 0xff); out[3] = @intCast((self.bcd_usb >> 8) & 0xff); @@ -721,8 +711,6 @@ pub const DeviceQualifierDescriptor = extern struct { /// Layout of an 8-byte USB SETUP packet. pub const SetupPacket = extern struct { - /// Request type; in practice, this is always either OUT (host-to-device) or - /// IN (device-to-host), whose values are given in the `Dir` enum. request_type: u8, /// Request. Standard setup requests are in the `SetupRequest` enum. /// Devices can extend this with additional types as long as they don't diff --git a/core/src/core/usb/hid.zig b/core/src/core/usb/hid.zig index c63e28a..79f87d7 100644 --- a/core/src/core/usb/hid.zig +++ b/core/src/core/usb/hid.zig @@ -87,8 +87,7 @@ pub const DescType = enum(u8) { }; /// USB HID descriptor -pub const HidDescriptor = extern struct { - length: u8 = 9, +pub const HidDescriptor = struct { descriptor_type: DescType = DescType.Hid, /// Numeric expression identifying the HID Class Specification release bcd_hid: u16, @@ -103,7 +102,7 @@ pub const HidDescriptor = extern struct { pub fn serialize(self: *const @This()) [9]u8 { var out: [9]u8 = undefined; - out[0] = 9; // length + out[0] = out.len; out[1] = @intFromEnum(self.descriptor_type); out[2] = @intCast(self.bcd_hid & 0xff); out[3] = @intCast((self.bcd_hid >> 8) & 0xff); diff --git a/examples/raspberrypi-rp2040/src/usb_device.zig b/examples/raspberrypi-rp2040/src/usb_device.zig index 8f2d74e..4c25c48 100644 --- a/examples/raspberrypi-rp2040/src/usb_device.zig +++ b/examples/raspberrypi-rp2040/src/usb_device.zig @@ -38,7 +38,6 @@ fn ep1_out_callback(dc: *usb.DeviceConfiguration, data: []const u8) void { // add your own endpoints to... pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{ .descriptor = &usb.EndpointDescriptor{ - .length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.Dir.Out.endpoint(1), .attributes = @intFromEnum(usb.TransferType.Bulk), @@ -55,7 +54,6 @@ pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{ pub var EP1_IN_CFG: usb.EndpointConfiguration = .{ .descriptor = &usb.EndpointDescriptor{ - .length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.Dir.In.endpoint(1), .attributes = @intFromEnum(usb.TransferType.Bulk), @@ -73,7 +71,6 @@ pub var EP1_IN_CFG: usb.EndpointConfiguration = .{ // This is our device configuration pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ .device_descriptor = &.{ - .length = @as(u8, @intCast(@sizeOf(usb.DeviceDescriptor))), .descriptor_type = usb.DescType.Device, .bcd_usb = 0x0110, .device_class = 0, @@ -89,7 +86,6 @@ pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ .num_configurations = 1, }, .interface_descriptor = &.{ - .length = @as(u8, @intCast(@sizeOf(usb.InterfaceDescriptor))), .descriptor_type = usb.DescType.Interface, .interface_number = 0, .alternate_setting = 0, @@ -101,9 +97,10 @@ pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ .interface_s = 0, }, .config_descriptor = &.{ - .length = @as(u8, @intCast(@sizeOf(usb.ConfigurationDescriptor))), .descriptor_type = usb.DescType.Config, - .total_length = @as(u8, @intCast(@sizeOf(usb.ConfigurationDescriptor) + @sizeOf(usb.InterfaceDescriptor) + @sizeOf(usb.EndpointDescriptor) + @sizeOf(usb.EndpointDescriptor))), + // This is calculated via the sizes of underlying descriptors contained in this configuration. + // ConfigurationDescriptor(9) + InterfaceDescriptor(9) * 1 + EndpointDescriptor(8) * 2 + .total_length = 34, .num_interfaces = 1, .configuration_value = 1, .configuration_s = 0, diff --git a/examples/raspberrypi-rp2040/src/usb_hid.zig b/examples/raspberrypi-rp2040/src/usb_hid.zig index 752111a..6705054 100644 --- a/examples/raspberrypi-rp2040/src/usb_hid.zig +++ b/examples/raspberrypi-rp2040/src/usb_hid.zig @@ -38,7 +38,6 @@ fn ep1_out_callback(dc: *usb.DeviceConfiguration, data: []const u8) void { // add your own endpoints to... pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{ .descriptor = &usb.EndpointDescriptor{ - .length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.Dir.Out.endpoint(1), .attributes = @intFromEnum(usb.TransferType.Interrupt), @@ -55,7 +54,6 @@ pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{ pub var EP1_IN_CFG: usb.EndpointConfiguration = .{ .descriptor = &usb.EndpointDescriptor{ - .length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.Dir.In.endpoint(1), .attributes = @intFromEnum(usb.TransferType.Interrupt), @@ -73,7 +71,6 @@ pub var EP1_IN_CFG: usb.EndpointConfiguration = .{ // This is our device configuration pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ .device_descriptor = &.{ - .length = @as(u8, @intCast(@sizeOf(usb.DeviceDescriptor))), .descriptor_type = usb.DescType.Device, .bcd_usb = 0x0200, .device_class = 0, @@ -91,7 +88,6 @@ pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ .num_configurations = 1, }, .interface_descriptor = &.{ - .length = @as(u8, @intCast(@sizeOf(usb.InterfaceDescriptor))), .descriptor_type = usb.DescType.Interface, .interface_number = 0, .alternate_setting = 0, @@ -103,9 +99,10 @@ pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ .interface_s = 0, }, .config_descriptor = &.{ - .length = @as(u8, @intCast(@sizeOf(usb.ConfigurationDescriptor))), .descriptor_type = usb.DescType.Config, - .total_length = @as(u8, @intCast(@sizeOf(usb.ConfigurationDescriptor) + @sizeOf(usb.InterfaceDescriptor) + @sizeOf(usb.EndpointDescriptor) + @sizeOf(usb.EndpointDescriptor))), + // This is calculated via the sizes of underlying descriptors contained in this configuration. + // ConfigurationDescriptor(9) + InterfaceDescriptor(9) * 1 + EndpointDescriptor(8) * 2 + .total_length = 34, .num_interfaces = 1, .configuration_value = 1, .configuration_s = 0,