Skip to content

Commit ff111bd

Browse files
ArcaneNibbledlech
authored andcommitted
pbio/drv/usb/usb_ch9.h: Add definitions for USB data types
These data types are defined in Chapter 9 of the USB standard and consistute the "USB Device Framework".
1 parent e9874f4 commit ff111bd

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-0
lines changed

lib/pbio/drv/usb/usb_ch9.h

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// SPDX-License-Identifier: MIT
2+
// Copyright (c) 2025 The Pybricks Authors
3+
4+
// Various bits of USB "Chapter 9" types
5+
6+
#ifndef _INTERNAL_PBDRV_USB_CH9_H_
7+
#define _INTERNAL_PBDRV_USB_CH9_H_
8+
9+
#include <stdint.h>
10+
#include <pbdrv/compiler.h>
11+
12+
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
13+
#error This file needs to be revisited for big-endian systems
14+
#endif
15+
16+
// A number of these types additionally define a union with uint32_t.
17+
// This serves two functions:
18+
// 1. Aligns the data to a 4-byte boundary
19+
// 2. Explicitly enables type punning without violating strict aliasing
20+
//
21+
// The latter is important for drivers which want to efficiently copy data
22+
// multiple bytes at a time. The C standard considers it undefined to access
23+
// data behind a struct pointer by casting it to a uint32_t pointer,
24+
// and doing so can cause miscompiles. In order to get what we actually want,
25+
// GCC explicitly allows type punning via unions. This is documented in the manual:
26+
// https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Type-punning
27+
//
28+
// The following macro helps construct these structs
29+
#define PBDRV_USB_TYPE_PUNNING_HELPER(type) \
30+
typedef union { \
31+
type##_t s; \
32+
uint32_t u[(sizeof(type##_t) + sizeof(uint32_t) - 1) / sizeof(uint32_t)]; \
33+
} type##_union_t;
34+
35+
// SETUP transaction packet structure
36+
typedef struct {
37+
uint8_t bmRequestType;
38+
uint8_t bRequest;
39+
uint16_t wValue;
40+
uint16_t wIndex;
41+
uint16_t wLength;
42+
} pbdrv_usb_setup_packet_t;
43+
PBDRV_USB_TYPE_PUNNING_HELPER(pbdrv_usb_setup_packet)
44+
45+
// Bitfields in bmRequestType
46+
#define BM_REQ_DIR_MASK 0x80
47+
#define BM_REQ_DIR_H2D 0x00
48+
#define BM_REQ_DIR_D2H 0x80
49+
50+
#define BM_REQ_TYPE_MASK 0x60
51+
#define BM_REQ_TYPE_STANDARD (0 << 5)
52+
#define BM_REQ_TYPE_CLASS (1 << 5)
53+
#define BM_REQ_TYPE_VENDOR (2 << 5)
54+
55+
#define BM_REQ_RECIP_MASK 0x1f
56+
#define BM_REQ_RECIP_DEV 0
57+
#define BM_REQ_RECIP_IF 1
58+
#define BM_REQ_RECIP_EP 2
59+
#define BM_REQ_RECIP_OTHER 3
60+
61+
// Standard USB requests
62+
#define GET_STATUS 0
63+
#define CLEAR_FEATURE 1
64+
#define SET_FEATURE 3
65+
#define SET_ADDRESS 5
66+
#define GET_DESCRIPTOR 6
67+
#define SET_DESCRIPTOR 7
68+
#define GET_CONFIGURATION 8
69+
#define SET_CONFIGURATION 9
70+
#define GET_INTERFACE 10
71+
#define SET_INTERFACE 11
72+
#define SYNCH_FRAME 12
73+
74+
// Standard descriptor types
75+
#define DESC_TYPE_DEVICE 1
76+
#define DESC_TYPE_CONFIGURATION 2
77+
#define DESC_TYPE_STRING 3
78+
#define DESC_TYPE_INTERFACE 4
79+
#define DESC_TYPE_ENDPOINT 5
80+
#define DESC_TYPE_DEVICE_QUALIFIER 6
81+
#define DESC_TYPE_OTHER_SPEED_CONFIGURATION 7
82+
#define DESC_TYPE_INTERFACE_POWER 8
83+
84+
// Device descriptor
85+
typedef struct PBDRV_PACKED {
86+
uint8_t bLength;
87+
uint8_t bDescriptorType;
88+
uint16_t bcdUSB;
89+
uint8_t bDeviceClass;
90+
uint8_t bDeviceSubClass;
91+
uint8_t bDeviceProtocol;
92+
uint8_t bMaxPacketSize0;
93+
uint16_t idVendor;
94+
uint16_t idProduct;
95+
uint16_t bcdDevice;
96+
uint8_t iManufacturer;
97+
uint8_t iProduct;
98+
uint8_t iSerialNumber;
99+
uint8_t bNumConfigurations;
100+
} pbdrv_usb_dev_desc_t;
101+
PBDRV_USB_TYPE_PUNNING_HELPER(pbdrv_usb_dev_desc);
102+
103+
// Configuration descriptor
104+
typedef struct PBDRV_PACKED {
105+
uint8_t bLength;
106+
uint8_t bDescriptorType;
107+
uint16_t wTotalLength;
108+
uint8_t bNumInterfaces;
109+
uint8_t bConfigurationValue;
110+
uint8_t iConfiguration;
111+
uint8_t bmAttributes;
112+
uint8_t bMaxPower;
113+
} pbdrv_usb_conf_desc_t;
114+
PBDRV_USB_TYPE_PUNNING_HELPER(pbdrv_usb_conf_desc);
115+
116+
#define USB_CONF_DESC_BM_ATTR_MUST_BE_SET 0x80
117+
#define USB_CONF_DESC_BM_ATTR_SELF_POWERED 0x40
118+
#define USB_CONF_DESC_BM_ATTR_REMOTE_WAKEUP 0x20
119+
120+
// Interface descriptor
121+
typedef struct PBDRV_PACKED {
122+
uint8_t bLength;
123+
uint8_t bDescriptorType;
124+
uint8_t bInterfaceNumber;
125+
uint8_t bAlternateSetting;
126+
uint8_t bNumEndpoints;
127+
uint8_t bInterfaceClass;
128+
uint8_t bInterfaceSubClass;
129+
uint8_t bInterfaceProtocol;
130+
uint8_t iInterface;
131+
} pbdrv_usb_iface_desc_t;
132+
133+
// Endpoint descriptor
134+
typedef struct PBDRV_PACKED {
135+
uint8_t bLength;
136+
uint8_t bDescriptorType;
137+
uint8_t bEndpointAddress;
138+
uint8_t bmAttributes;
139+
uint16_t wMaxPacketSize;
140+
uint8_t bInterval;
141+
} pbdrv_usb_ep_desc_t;
142+
143+
// Endpoint types for bmAttributes
144+
#define EP_TYPE_CTRL 0
145+
#define EP_TYPE_ISOC 1
146+
#define EP_TYPE_BULK 2
147+
#define EP_TYPE_INTR 3
148+
149+
// Device qualifier descriptor
150+
typedef struct PBDRV_PACKED {
151+
uint8_t bLength;
152+
uint8_t bDescriptorType;
153+
uint16_t bcdUSB;
154+
uint8_t bDeviceClass;
155+
uint8_t bDeviceSubClass;
156+
uint8_t bDeviceProtocol;
157+
uint8_t bMaxPacketSize0;
158+
uint8_t bNumConfigurations;
159+
uint8_t bReserved;
160+
} pbdrv_usb_dev_qualifier_desc_t;
161+
PBDRV_USB_TYPE_PUNNING_HELPER(pbdrv_usb_dev_qualifier_desc);
162+
163+
#endif // _INTERNAL_PBDRV_USB_CH9_H_

lib/pbio/drv/usb/usb_ev3.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
#include <pbdrv/clock.h>
2929

30+
#include "usb_ch9.h"
31+
3032
static void usb_device_intr(void) {
3133
IntSystemStatusClear(SYS_INT_USB0);
3234
}

lib/pbio/include/pbdrv/compiler.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,9 @@
99
// Forces the compiler to not reorder memory access around this line
1010
#define pbdrv_compiler_memory_barrier() __asm__ volatile ("" ::: "memory")
1111

12+
// Forces structure packing (forces the structure to contain data exactly as written,
13+
// so that it can match some externally-specified data layout, instead of allowing
14+
// the compiler to insert padding for more optimal code)
15+
#define PBDRV_PACKED __attribute__((packed))
16+
1217
#endif

0 commit comments

Comments
 (0)