Skip to content

Commit ebcb76d

Browse files
committed
Configure USB device and process pybricks commands
Configures the USB device and processes pybricks commands.
1 parent 994c3dd commit ebcb76d

File tree

1 file changed

+100
-1
lines changed

1 file changed

+100
-1
lines changed

lib/pbio/drv/usb/usb_stm32.c

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,33 @@
88
#if PBDRV_CONFIG_USB_STM32F4
99

1010
#include <stdbool.h>
11+
#include <string.h>
1112

1213
#include <contiki.h>
1314
#include <stm32f4xx_hal.h>
1415
#include <stm32f4xx_hal_pcd_ex.h>
1516
#include <usbd_core.h>
17+
#include <usbd_pybricks.h>
1618

1719
#include <pbdrv/usb.h>
1820
#include <pbio/util.h>
21+
#include <pbsys/command.h>
1922

2023
#include "../charger/charger.h"
2124
#include "./usb_stm32.h"
2225

26+
#define UUID_SZ (128 / 8)
27+
2328
PROCESS(pbdrv_usb_process, "USB");
2429

30+
static uint8_t usb_in_buf[USBD_PYBRICKS_MAX_PACKET_SIZE];
31+
static uint8_t usb_out_buf[USBD_PYBRICKS_MAX_PACKET_SIZE];
32+
static volatile uint32_t usb_in_sz;
33+
static volatile uint32_t usb_out_sz;
34+
2535
static USBD_HandleTypeDef husbd;
2636
static PCD_HandleTypeDef hpcd;
37+
2738
static volatile bool vbus_active;
2839
static pbdrv_usb_bcd_t pbdrv_usb_bcd;
2940

@@ -121,14 +132,87 @@ void pbdrv_usb_stm32_handle_vbus_irq(bool active) {
121132
process_poll(&pbdrv_usb_process);
122133
}
123134

135+
/**
136+
* @brief Pybricks_Itf_Init
137+
* Initializes the Pybricks media low layer
138+
* @param None
139+
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
140+
*/
141+
static int8_t Pybricks_Itf_Init(void) {
142+
USBD_Pybricks_SetTxBuffer(&husbd, usb_out_buf, sizeof(usb_out_buf));
143+
USBD_Pybricks_SetRxBuffer(&husbd, usb_in_buf);
144+
usb_in_sz = 0;
145+
usb_out_sz = 0;
146+
147+
return USBD_OK;
148+
}
149+
150+
/**
151+
* @brief Pybricks_Itf_DeInit
152+
* DeInitializes the Pybricks media low layer
153+
* @param None
154+
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
155+
*/
156+
static int8_t Pybricks_Itf_DeInit(void) {
157+
return USBD_OK;
158+
}
159+
160+
/**
161+
* @brief Pybricks_Itf_DataRx
162+
* Data received over USB OUT endpoint are sent over CDC interface
163+
* through this function.
164+
* @param Buf: Buffer of data to be transmitted
165+
* @param Len: Number of data received (in bytes)
166+
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
167+
*/
168+
static int8_t Pybricks_Itf_Receive(uint8_t *Buf, uint32_t *Len) {
169+
if (*Len > sizeof(usb_in_buf)) {
170+
return USBD_FAIL;
171+
}
172+
173+
memcpy(usb_in_buf, Buf, *Len);
174+
usb_in_sz = *Len;
175+
process_poll(&pbdrv_usb_process);
176+
return USBD_OK;
177+
}
178+
179+
/**
180+
* @brief Pybricks_Itf_TransmitCplt
181+
* Data transmitted callback
182+
*
183+
* @note
184+
* This function is IN transfer complete callback used to inform user that
185+
* the submitted Data is successfully sent over USB.
186+
*
187+
* @param Buf: Buffer of data to be received
188+
* @param Len: Number of data received (in bytes)
189+
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
190+
*/
191+
static int8_t Pybricks_Itf_TransmitCplt(uint8_t *Buf, uint32_t *Len, uint8_t epnum) {
192+
usb_out_sz = 0;
193+
process_poll(&pbdrv_usb_process);
194+
return USBD_OK;
195+
}
196+
197+
static USBD_Pybricks_ItfTypeDef USBD_Pybricks_fops = {
198+
.Init = Pybricks_Itf_Init,
199+
.DeInit = Pybricks_Itf_DeInit,
200+
.Receive = Pybricks_Itf_Receive,
201+
.TransmitCplt = Pybricks_Itf_TransmitCplt,
202+
};
203+
124204
// Common USB driver implementation.
125205

126206
void pbdrv_usb_init(void) {
127207
// Link the driver data structures
128208
husbd.pData = &hpcd;
129209
hpcd.pData = &husbd;
130210

131-
USBD_Init(&husbd, NULL, 0);
211+
USBD_Init(&husbd, &Pybricks_Desc, 0);
212+
USBD_RegisterClass(&husbd, &USBD_Pybricks_ClassDriver);
213+
USBD_Pybricks_RegisterInterface(&husbd, &USBD_Pybricks_fops);
214+
USBD_Start(&husbd);
215+
132216
process_start(&pbdrv_usb_process);
133217

134218
// VBUS may already be active
@@ -164,12 +248,27 @@ PROCESS_THREAD(pbdrv_usb_process, ev, data) {
164248

165249
PROCESS_BEGIN();
166250

251+
// Prepare to receive the first packet
252+
USBD_Pybricks_ReceivePacket(&husbd);
253+
167254
for (;;) {
168255
PROCESS_WAIT_EVENT();
169256

170257
if (bcd_busy) {
171258
bcd_busy = PT_SCHEDULE(pbdrv_usb_stm32_bcd_detect(&bcd_pt));
172259
}
260+
261+
if (usb_in_sz) {
262+
if ((usb_in_sz >= UUID_SZ) &&
263+
pbio_uuid128_le_compare(usb_in_buf, pbio_pybricks_command_event_char_uuid)) {
264+
pbsys_command(usb_in_buf + UUID_SZ, usb_in_sz - UUID_SZ);
265+
}
266+
267+
usb_in_sz = 0;
268+
269+
// Prepare to receive the next packet
270+
USBD_Pybricks_ReceivePacket(&husbd);
271+
}
173272
}
174273

175274
PROCESS_END();

0 commit comments

Comments
 (0)