linux_usb_functionfs_sys/
lib.rs

1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4
5include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
6
7#[repr(C, packed)]
8struct usb_functionfs_ep_descs {
9    intf: usb_interface_descriptor,
10    sink: usb_endpoint_descriptor_no_audio,
11    source: usb_endpoint_descriptor_no_audio,
12}
13
14// Per example this is not packed.
15struct usb_functionfs_ss_ep_descs {
16    intf: usb_interface_descriptor,
17    sink: usb_endpoint_descriptor_no_audio,
18    sink_comp: usb_ss_ep_comp_descriptor,
19    source: usb_endpoint_descriptor_no_audio,
20    source_comp: usb_ss_ep_comp_descriptor,
21}
22
23#[repr(C, packed)]
24struct usb_functionfs_descriptors {
25    header: usb_functionfs_descs_head_v2,
26    fs_count: u32,
27    hs_count: u32,
28    ss_count: u32,
29    fs_descs: usb_functionfs_ep_descs,
30    hs_descs: usb_functionfs_ep_descs,
31    ss_descs: usb_functionfs_ss_ep_descs,
32}
33
34#[cfg(test)]
35mod linux_usb_functionfs_sys {
36    use std::mem;
37    use crate::*;
38
39    #[test]
40    fn test_struct_contents() {
41        let descriptors = usb_functionfs_descriptors {
42            header: usb_functionfs_descs_head_v2 {
43                magic: FUNCTIONFS_DESCRIPTORS_MAGIC_V2.to_le(),
44                flags: (functionfs_flags_FUNCTIONFS_HAS_FS_DESC |
45                        functionfs_flags_FUNCTIONFS_HAS_HS_DESC |
46                        functionfs_flags_FUNCTIONFS_HAS_SS_DESC).to_le(),
47                length: (mem::size_of::<usb_functionfs_descriptors>() as u32).to_le(),
48            },
49            fs_count: 3u32.to_le(),
50            hs_count: 3u32.to_le(),
51            ss_count: 5u32.to_le(),
52            fs_descs: usb_functionfs_ep_descs {
53                intf: usb_interface_descriptor {
54                    bLength: mem::size_of::<usb_interface_descriptor>() as u8,
55                    bDescriptorType: USB_DT_INTERFACE as u8,
56                    bInterfaceNumber: 0,
57                    bAlternateSetting: 0,
58                    bNumEndpoints: 2,
59                    bInterfaceClass: USB_CLASS_VENDOR_SPEC as u8,
60                    bInterfaceSubClass: 0,
61                    bInterfaceProtocol: 0,
62                    iInterface: 1,
63                },
64                sink: usb_endpoint_descriptor_no_audio {
65                    bLength: mem::size_of::<usb_endpoint_descriptor_no_audio>() as u8,
66                    bDescriptorType: USB_DT_ENDPOINT as u8,
67                    bEndpointAddress: 1 | USB_DIR_IN as u8,
68                    bmAttributes: USB_ENDPOINT_XFER_BULK as u8,
69                    wMaxPacketSize: 0,
70                    bInterval: 0,
71                },
72                source: usb_endpoint_descriptor_no_audio {
73                    bLength: mem::size_of::<usb_endpoint_descriptor_no_audio>() as u8,
74                    bDescriptorType: USB_DT_ENDPOINT as u8,
75                    bEndpointAddress: 2 | USB_DIR_OUT as u8,
76                    bmAttributes: USB_ENDPOINT_XFER_BULK as u8,
77                    wMaxPacketSize: 0,
78                    bInterval: 0,
79                },
80            },
81            hs_descs: usb_functionfs_ep_descs {
82                intf: usb_interface_descriptor {
83                    bLength: mem::size_of::<usb_interface_descriptor>() as u8,
84                    bDescriptorType: USB_DT_INTERFACE as u8,
85                    bInterfaceNumber: 0,
86                    bAlternateSetting: 0,
87                    bNumEndpoints: 2,
88                    bInterfaceClass: USB_CLASS_VENDOR_SPEC as u8,
89                    bInterfaceSubClass: 0,
90                    bInterfaceProtocol: 0,
91                    iInterface: 1,
92                },
93                sink: usb_endpoint_descriptor_no_audio {
94                    bLength: mem::size_of::<usb_endpoint_descriptor_no_audio>() as u8,
95                    bDescriptorType: USB_DT_ENDPOINT as u8,
96                    bEndpointAddress: 1 | USB_DIR_IN as u8,
97                    bmAttributes: USB_ENDPOINT_XFER_BULK as u8,
98                    wMaxPacketSize: 512u16.to_le(),
99                    bInterval: 0,
100                },
101                source: usb_endpoint_descriptor_no_audio {
102                    bLength: mem::size_of::<usb_endpoint_descriptor_no_audio>() as u8,
103                    bDescriptorType: USB_DT_ENDPOINT as u8,
104                    bEndpointAddress: 2 | USB_DIR_OUT as u8,
105                    bmAttributes: USB_ENDPOINT_XFER_BULK as u8,
106                    wMaxPacketSize: 512u16.to_le(),
107                    bInterval: 1,
108                },
109            },
110            ss_descs: usb_functionfs_ss_ep_descs {
111                intf: usb_interface_descriptor {
112                    bLength: mem::size_of::<usb_interface_descriptor>() as u8,
113                    bDescriptorType: USB_DT_INTERFACE as u8,
114                    bInterfaceNumber: 0,
115                    bAlternateSetting: 0,
116                    bNumEndpoints: 2,
117                    bInterfaceClass: USB_CLASS_VENDOR_SPEC as u8,
118                    bInterfaceSubClass: 0,
119                    bInterfaceProtocol: 0,
120                    iInterface: 1,
121                },
122                sink: usb_endpoint_descriptor_no_audio {
123                    bLength: mem::size_of::<usb_endpoint_descriptor_no_audio>() as u8,
124                    bDescriptorType: USB_DT_ENDPOINT as u8,
125                    bEndpointAddress: 1 | USB_DIR_IN as u8,
126                    bmAttributes: USB_ENDPOINT_XFER_BULK as u8,
127                    wMaxPacketSize: 1024u16.to_le(),
128                    bInterval: 0,
129                },
130                sink_comp: usb_ss_ep_comp_descriptor {
131                    bLength: USB_DT_SS_EP_COMP_SIZE as u8,
132                    bDescriptorType: USB_DT_SS_ENDPOINT_COMP as u8,
133                    bMaxBurst: 0,
134                    bmAttributes: 0,
135                    wBytesPerInterval: 0,
136                },
137                source: usb_endpoint_descriptor_no_audio {
138                    bLength: mem::size_of::<usb_endpoint_descriptor_no_audio>() as u8,
139                    bDescriptorType: USB_DT_ENDPOINT as u8,
140                    bEndpointAddress: 2 | USB_DIR_OUT as u8,
141                    bmAttributes: USB_ENDPOINT_XFER_BULK as u8,
142                    wMaxPacketSize: 1024u16.to_le(),
143                    bInterval: 1,
144                },
145                source_comp: usb_ss_ep_comp_descriptor {
146                    bLength: USB_DT_SS_EP_COMP_SIZE as u8,
147                    bDescriptorType: USB_DT_SS_ENDPOINT_COMP as u8,
148                    bMaxBurst: 0,
149                    bmAttributes: 0,
150                    wBytesPerInterval: 0,
151                },
152            },
153        };
154
155        // This should catch most potential errors -- rust is very lenient about packing
156        // and byte order.
157        let size = mem::size_of::<usb_functionfs_descriptors>();
158        assert_eq!(size, 105, "Descriptor size does not match reference implementation size");
159
160        // But just to be sure, check the entire contents.
161        let pointer: *const usb_functionfs_descriptors = &descriptors;
162        let slice = unsafe { std::slice::from_raw_parts(&descriptors as *const _ as *const u8, size) };
163
164        // TODO: Include this from output of program compiled against Linux headers.
165        let real = vec![0x03, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02, 0xff, 0x00, 0x00, 0x01, 0x07, 0x05, 0x81, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02, 0xff, 0x00, 0x00, 0x01, 0x07, 0x05, 0x81, 0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x02, 0x02, 0x00, 0x02, 0x01, 0x09, 0x04, 0x00, 0x00, 0x02, 0xff, 0x00, 0x00, 0x01, 0x07, 0x05, 0x81, 0x02, 0x00, 0x04, 0x00, 0x06, 0x30, 0x00, 0x00, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x00, 0x04, 0x01, 0x06, 0x30, 0x00, 0x00, 0x00, 0x00, ];
166          
167        // Shown to user if test fails.
168        for i in 0..size {
169            if slice[i] != real[i] {
170                println!("{}", i);
171            }
172        }
173
174        assert_eq!(slice.to_vec(), real);
175    }
176}