1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
/* Copyright 2022 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "dfu_bootmanager_shared.h"
#include "registers.h"
#include "usb_descriptor.h"
#include "usb_dfu_runtime.h"
#include "usb_hw.h"
/* DFU Run-Time Descriptor Set. */
const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_DFU) = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = USB_IFACE_DFU,
.bAlternateSetting = 0,
.bNumEndpoints = 0,
.bInterfaceClass = USB_CLASS_APP_SPEC,
.bInterfaceSubClass = USB_DFU_RUNTIME_SUBCLASS,
.bInterfaceProtocol = USB_DFU_RUNTIME_PROTOCOL,
.iInterface = USB_STR_DFU_NAME,
};
/* DFU Functional Descriptor. */
const struct usb_runtime_dfu_functional_desc USB_CUSTOM_DESC_VAR(USB_IFACE_DFU,
dfu, dfu_func_desc) = {
.bLength = USB_DFU_RUNTIME_DESC_SIZE,
.bDescriptorType = USB_DFU_RUNTIME_DESC_FUNCTIONAL,
.bmAttributes = USB_DFU_RUNTIME_DESC_ATTRS,
.wDetachTimeOut = USB_DFU_RUNTIME_DESC_DETACH_TIMEOUT,
.wTransferSize = USB_DFU_RUNTIME_DESC_TRANSFER_SIZE,
.bcdDFUVersion = USB_DFU_RUNTIME_DESC_DFU_VERSION,
};
static int dfu_runtime_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx)
{
struct usb_setup_packet packet;
usb_read_setup_packet(ep0_buf_rx, &packet);
btable_ep[0].tx_count = 0;
if ((packet.bmRequestType ==
(USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE)) &&
(packet.bRequest == USB_REQ_SET_INTERFACE)) {
/* ACK the change alternative mode request. */
STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0);
return 0;
} else if ((packet.bmRequestType ==
(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) &&
(packet.bRequest == USB_DFU_RUNTIME_REQ_DETACH)) {
/* Host is requesting a jump from application to DFU mode. */
STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0);
return dfu_bootmanager_enter_dfu();
} else if (packet.bmRequestType ==
(USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) {
if (packet.bRequest == USB_DFU_RUNTIME_REQ_GET_STATUS) {
/* Return the Get Status response. */
struct usb_runtime_dfu_get_status_resp response = {
.bStatus = USB_DFU_RUNTIME_STATUS_OK,
.bState = USB_DFU_RUNTIME_STATE_APP_IDLE,
};
memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx),
&response, sizeof(response));
btable_ep[0].tx_count = sizeof(response);
STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0);
return 0;
}
if (packet.bRequest == USB_DFU_RUNTIME_REQ_GET_STATE) {
/* Return the Get State response. */
struct usb_runtime_dfu_get_state_resp response = {
.bState = USB_DFU_RUNTIME_STATE_APP_IDLE,
};
memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx),
&response, sizeof(response));
btable_ep[0].tx_count = sizeof(response);
STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0);
return 0;
}
}
/* Return a stall response for any unhandled packets. */
STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_RX_VALID | EP_TX_STALL, 0);
return 0;
}
USB_DECLARE_IFACE(USB_IFACE_DFU, dfu_runtime_request)
|