Skip to content

Commit 264959d

Browse files
committed
pbio/drv/usb/usb_ch9.h: Add definitions for USB data types
1 parent 31ee9b2 commit 264959d

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

lib/pbio/drv/usb/usb_ch9.h

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

0 commit comments

Comments
 (0)