blob: afee2aa1fd31ab8537541cd46e12008d5888592c [file] [log] [blame]
Austin Schuh41baf202022-01-01 14:33:40 -08001/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2019 Sylvain Munaut <tnt@246tNt.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 * This file is part of the TinyUSB stack.
25 */
26
27#include "tusb_option.h"
28
29#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME)
30
31#include "device/usbd.h"
32#include "device/usbd_pvt.h"
33
34#include "dfu_rt_device.h"
35
36//--------------------------------------------------------------------+
37// MACRO CONSTANT TYPEDEF
38//--------------------------------------------------------------------+
39
40//--------------------------------------------------------------------+
41// INTERNAL OBJECT & FUNCTION DECLARATION
42//--------------------------------------------------------------------+
43
44//--------------------------------------------------------------------+
45// USBD Driver API
46//--------------------------------------------------------------------+
47void dfu_rtd_init(void)
48{
49}
50
51void dfu_rtd_reset(uint8_t rhport)
52{
53 (void) rhport;
54}
55
56uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
57{
58 (void) rhport;
59 (void) max_len;
60
61 // Ensure this is DFU Runtime
62 TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) &&
63 (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT), 0);
64
65 uint8_t const * p_desc = tu_desc_next( itf_desc );
66 uint16_t drv_len = sizeof(tusb_desc_interface_t);
67
68 if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) )
69 {
70 drv_len += tu_desc_len(p_desc);
71 p_desc = tu_desc_next(p_desc);
72 }
73
74 return drv_len;
75}
76
77// Invoked when a control transfer occurred on an interface of this class
78// Driver response accordingly to the request and the transfer stage (setup/data/ack)
79// return false to stall control endpoint (e.g unsupported request)
80bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
81{
82 // nothing to do with DATA or ACK stage
83 if ( stage != CONTROL_STAGE_SETUP ) return true;
84
85 TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
86
87 // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request
88 if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type &&
89 TUSB_REQ_SET_INTERFACE == request->bRequest )
90 {
91 tud_control_status(rhport, request);
92 return true;
93 }
94
95 // Handle class request only from here
96 TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
97
98 switch (request->bRequest)
99 {
100 case DFU_REQUEST_DETACH:
101 {
102 TU_LOG2(" DFU RT Request: DETACH\r\n");
103 tud_control_status(rhport, request);
104 tud_dfu_runtime_reboot_to_dfu_cb();
105 }
106 break;
107
108 case DFU_REQUEST_GETSTATUS:
109 {
110 TU_LOG2(" DFU RT Request: GETSTATUS\r\n");
111 dfu_status_response_t resp;
112 // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0
113 memset(&resp, 0x00, sizeof(dfu_status_response_t));
114 tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t));
115 }
116 break;
117
118 default:
119 {
120 TU_LOG2(" DFU RT Unexpected Request: %d\r\n", request->bRequest);
121 return false; // stall unsupported request
122 }
123 }
124
125 return true;
126}
127
128#endif