1beacf11bSopenharmony_ci/* ----------------------------------------------------------------------------
2beacf11bSopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
3beacf11bSopenharmony_ci * Description: LiteOS USB Driver DFU Protocol
4beacf11bSopenharmony_ci * Author: huangjieliang
5beacf11bSopenharmony_ci * Create: 2017-12-25
6beacf11bSopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
7beacf11bSopenharmony_ci * are permitted provided that the following conditions are met:
8beacf11bSopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
9beacf11bSopenharmony_ci * conditions and the following disclaimer.
10beacf11bSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11beacf11bSopenharmony_ci * of conditions and the following disclaimer in the documentation and/or other materials
12beacf11bSopenharmony_ci * provided with the distribution.
13beacf11bSopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
14beacf11bSopenharmony_ci * to endorse or promote products derived from this software without specific prior written
15beacf11bSopenharmony_ci * permission.
16beacf11bSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17beacf11bSopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18beacf11bSopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19beacf11bSopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20beacf11bSopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21beacf11bSopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22beacf11bSopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23beacf11bSopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24beacf11bSopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25beacf11bSopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26beacf11bSopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27beacf11bSopenharmony_ci * --------------------------------------------------------------------------- */
28beacf11bSopenharmony_ci/* ----------------------------------------------------------------------------
29beacf11bSopenharmony_ci * Notice of Export Control Law
30beacf11bSopenharmony_ci * ===============================================
31beacf11bSopenharmony_ci * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
32beacf11bSopenharmony_ci * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
33beacf11bSopenharmony_ci * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
34beacf11bSopenharmony_ci * applicable export control laws and regulations.
35beacf11bSopenharmony_ci * --------------------------------------------------------------------------- */
36beacf11bSopenharmony_ci
37beacf11bSopenharmony_ci#include <hisoc/uart.h>
38beacf11bSopenharmony_ci#include "gadget/f_dfu.h"
39beacf11bSopenharmony_ci#include "gadget/composite.h"
40beacf11bSopenharmony_ci
41beacf11bSopenharmony_ci#ifdef __cplusplus
42beacf11bSopenharmony_ci#if __cplusplus
43beacf11bSopenharmony_ciextern "C" {
44beacf11bSopenharmony_ci#endif /* __cplusplus */
45beacf11bSopenharmony_ci#endif /* __cplusplus */
46beacf11bSopenharmony_ci
47beacf11bSopenharmony_ciint usbdev_dfu_initialize(struct module *mod, int n, void *arg);
48beacf11bSopenharmony_ci
49beacf11bSopenharmony_ci/* device driver structure definition */
50beacf11bSopenharmony_ci
51beacf11bSopenharmony_cistatic const driver_t g_dfu_driver =
52beacf11bSopenharmony_ci{
53beacf11bSopenharmony_ci  .name     = "fdfu",
54beacf11bSopenharmony_ci  .methods  = NULL,
55beacf11bSopenharmony_ci  .size     = 0
56beacf11bSopenharmony_ci};
57beacf11bSopenharmony_ci
58beacf11bSopenharmony_ci/* private device class information */
59beacf11bSopenharmony_ci
60beacf11bSopenharmony_cistatic devclass_t g_dfu_devclass;
61beacf11bSopenharmony_ciDRIVER_MODULE(fdfu, simple, g_dfu_driver, g_dfu_devclass, usbdev_dfu_initialize, 0);
62beacf11bSopenharmony_ci
63beacf11bSopenharmony_cistatic struct usb_dfu_dev *g_dfu_dev       = NULL;
64beacf11bSopenharmony_cistatic struct usb_dfu_entity *g_dfu_entity = NULL;
65beacf11bSopenharmony_cistatic struct pthread_mutex g_dfu_mtx      = PTHREAD_MUTEX_INITIALIZER;
66beacf11bSopenharmony_ci
67beacf11bSopenharmony_cistatic struct string_des g_manufacturer_str;
68beacf11bSopenharmony_cistatic struct string_des g_serial_number_str;
69beacf11bSopenharmony_cistatic struct string_des g_product_str;
70beacf11bSopenharmony_ci
71beacf11bSopenharmony_civolatile uint8_t g_flash_upgrade_state = DFU_FLASH_STATE_UPGRADING;
72beacf11bSopenharmony_ci
73beacf11bSopenharmony_ci/* define descriptor */
74beacf11bSopenharmony_ci
75beacf11bSopenharmony_ci#define DEVICE_VENDOR_ID        0x0955
76beacf11bSopenharmony_ci#define DEVICE_PRODUCT_ID       0x701A
77beacf11bSopenharmony_ci#define DEVICE_VERSION          0x0110
78beacf11bSopenharmony_ci
79beacf11bSopenharmony_ci#define DFU_STRING_LEN_BYTE     0
80beacf11bSopenharmony_ci#define DFU_STRING_DATA_BYTE    2
81beacf11bSopenharmony_ci#define DFU_STRING_HEAD_LEN     2
82beacf11bSopenharmony_ci#define DFU_MANU_STRING_LEN     28
83beacf11bSopenharmony_ci#define DFU_PRODUCT_STRING_LEN  48
84beacf11bSopenharmony_ci#define DFU_SERIAL_STRING_LEN   22
85beacf11bSopenharmony_ci#define DFU_STRING_ID_LEN       4
86beacf11bSopenharmony_ci
87beacf11bSopenharmony_cistatic const struct usb_device_descriptor g_dfu_device_desc =
88beacf11bSopenharmony_ci{
89beacf11bSopenharmony_ci  .bLength            = sizeof(struct usb_device_descriptor),
90beacf11bSopenharmony_ci  .bDescriptorType    = UDESC_DEVICE,
91beacf11bSopenharmony_ci  HSETW(.bcdUSB, 0x0200),
92beacf11bSopenharmony_ci  .bDeviceClass       = 0x02,
93beacf11bSopenharmony_ci  .bDeviceSubClass    = 0x02, /* CDC-modem */
94beacf11bSopenharmony_ci  .bDeviceProtocol    = 0x01, /* Interface Association Descriptor */
95beacf11bSopenharmony_ci  .bMaxPacketSize     = 64,   /* Control Endpoint packet size */
96beacf11bSopenharmony_ci  HSETW(.idVendor, DEVICE_VENDOR_ID),
97beacf11bSopenharmony_ci  HSETW(.idProduct, DEVICE_PRODUCT_ID),
98beacf11bSopenharmony_ci  HSETW(.bcdDevice, DEVICE_VERSION),
99beacf11bSopenharmony_ci  .iManufacturer      = 1,    /* Manufacturer name, string index */
100beacf11bSopenharmony_ci  .iProduct           = 2,
101beacf11bSopenharmony_ci  .iSerialNumber      = 3,
102beacf11bSopenharmony_ci  .bNumConfigurations = 1,
103beacf11bSopenharmony_ci};
104beacf11bSopenharmony_ci
105beacf11bSopenharmony_cistruct usb_config_descriptor g_dfu_config_desc =
106beacf11bSopenharmony_ci{
107beacf11bSopenharmony_ci  .bLength             = USB_CONFIG_DESC_SIZE,
108beacf11bSopenharmony_ci  .bDescriptorType     = UDESC_CONFIG,
109beacf11bSopenharmony_ci
110beacf11bSopenharmony_ci  /* HSETW(.wTotalLength, USB_CONFIG_DESC_SIZE + sizeof(usb_dfu_func) + sizeof(usb_dfu_intf_desc)), */
111beacf11bSopenharmony_ci
112beacf11bSopenharmony_ci  HSETW(.wTotalLength, 0),  /* Modify according to the actual length */
113beacf11bSopenharmony_ci  .bNumInterface       = 1,
114beacf11bSopenharmony_ci  .bConfigurationValue = 1,
115beacf11bSopenharmony_ci  .iConfiguration      = 0,
116beacf11bSopenharmony_ci  .bmAttributes        = UC_SELF_POWERED | UC_BUS_POWERED,   /* 0xc0 */
117beacf11bSopenharmony_ci  .bMaxPower           = 1                                   /* max power */
118beacf11bSopenharmony_ci};
119beacf11bSopenharmony_ci
120beacf11bSopenharmony_ci/* HUAWEI LiteOS */
121beacf11bSopenharmony_ci
122beacf11bSopenharmony_cistatic char g_dfu_manufacturer[DFU_MANU_STRING_LEN] =
123beacf11bSopenharmony_ci{
124beacf11bSopenharmony_ci  DFU_MANU_STRING_LEN,
125beacf11bSopenharmony_ci  UDESC_STRING,
126beacf11bSopenharmony_ci  'H', 0, 'U', 0, 'A', 0, 'W', 0, 'E', 0, 'I', 0, ' ', 0,
127beacf11bSopenharmony_ci  'L', 0, 'i', 0, 't', 0, 'e', 0, 'O', 0, 'S', 0
128beacf11bSopenharmony_ci};
129beacf11bSopenharmony_ci
130beacf11bSopenharmony_ci/* USB download gadget */
131beacf11bSopenharmony_ci
132beacf11bSopenharmony_cistatic char g_dfu_product[DFU_PRODUCT_STRING_LEN] =
133beacf11bSopenharmony_ci{
134beacf11bSopenharmony_ci  DFU_PRODUCT_STRING_LEN,
135beacf11bSopenharmony_ci  UDESC_STRING,
136beacf11bSopenharmony_ci  'U', 0, 'S', 0, 'B', 0, ' ', 0, 'd', 0, 'o', 0, 'w', 0, 'n', 0, 'l', 0, 'o', 0,
137beacf11bSopenharmony_ci  'w', 0, 'n', 0, 'l', 0, 'o', 0, 'a', 0, 'd', 0, ' ', 0, 'g', 0, 'a', 0, 'd', 0,
138beacf11bSopenharmony_ci  'g', 0, 'e', 0, 't', 0
139beacf11bSopenharmony_ci};
140beacf11bSopenharmony_ci
141beacf11bSopenharmony_cistatic char g_dfu_serial[DFU_SERIAL_STRING_LEN] =
142beacf11bSopenharmony_ci{
143beacf11bSopenharmony_ci  DFU_SERIAL_STRING_LEN,
144beacf11bSopenharmony_ci  UDESC_STRING,
145beacf11bSopenharmony_ci  '1', 0, '2', 0, '3', 0, '4', 0, '5', 0,
146beacf11bSopenharmony_ci  '6', 0, '7', 0, '8', 0, '9', 0, '0', 0
147beacf11bSopenharmony_ci};
148beacf11bSopenharmony_ci
149beacf11bSopenharmony_cistatic const char g_dfu_string_id[DFU_STRING_ID_LEN] =
150beacf11bSopenharmony_ci{
151beacf11bSopenharmony_ci  DFU_STRING_ID_LEN,
152beacf11bSopenharmony_ci  UDESC_STRING,
153beacf11bSopenharmony_ci  0x09, 0x04
154beacf11bSopenharmony_ci};
155beacf11bSopenharmony_ci
156beacf11bSopenharmony_cistatic struct usbd_string g_dfu_string_defs[] =
157beacf11bSopenharmony_ci{
158beacf11bSopenharmony_ci  { 0, g_dfu_string_id },
159beacf11bSopenharmony_ci  { 1, g_dfu_manufacturer },
160beacf11bSopenharmony_ci  { 2, g_dfu_product },
161beacf11bSopenharmony_ci  { 3, g_dfu_serial },
162beacf11bSopenharmony_ci  { 4, g_dfu_product },
163beacf11bSopenharmony_ci  USBD_DEVICE_STRINGS_END /* end of list */
164beacf11bSopenharmony_ci};
165beacf11bSopenharmony_ci
166beacf11bSopenharmony_civoid set_manufacturer_string(struct string_des *des)
167beacf11bSopenharmony_ci{
168beacf11bSopenharmony_ci  char *buf;
169beacf11bSopenharmony_ci  struct string_des *str_des;
170beacf11bSopenharmony_ci  int len;
171beacf11bSopenharmony_ci
172beacf11bSopenharmony_ci  if (des == NULL)
173beacf11bSopenharmony_ci    {
174beacf11bSopenharmony_ci      usb_err("%s failed\n", __FUNCTION__);
175beacf11bSopenharmony_ci      return;
176beacf11bSopenharmony_ci    }
177beacf11bSopenharmony_ci
178beacf11bSopenharmony_ci  if (des->str == NULL || des->len <= 0)
179beacf11bSopenharmony_ci    {
180beacf11bSopenharmony_ci      usb_err("%s failed, des->str is NULL or des->len is 0\n", __FUNCTION__);
181beacf11bSopenharmony_ci      return;
182beacf11bSopenharmony_ci    }
183beacf11bSopenharmony_ci
184beacf11bSopenharmony_ci  str_des = des;
185beacf11bSopenharmony_ci  len     = str_des->len + DFU_STRING_HEAD_LEN;
186beacf11bSopenharmony_ci
187beacf11bSopenharmony_ci  buf = (char *)malloc(len);
188beacf11bSopenharmony_ci  if (buf == NULL)
189beacf11bSopenharmony_ci    {
190beacf11bSopenharmony_ci      usb_err("%s malloc failed\n", __FUNCTION__);
191beacf11bSopenharmony_ci      return;
192beacf11bSopenharmony_ci    }
193beacf11bSopenharmony_ci
194beacf11bSopenharmony_ci  g_manufacturer_str.str = buf;
195beacf11bSopenharmony_ci  g_manufacturer_str.len = len;
196beacf11bSopenharmony_ci
197beacf11bSopenharmony_ci  *buf = len;
198beacf11bSopenharmony_ci  *(buf + 1) = UDESC_STRING;
199beacf11bSopenharmony_ci  (void)memcpy_s(buf + DFU_STRING_HEAD_LEN, (size_t)str_des->len, str_des->str, (size_t)str_des->len);
200beacf11bSopenharmony_ci}
201beacf11bSopenharmony_ci
202beacf11bSopenharmony_civoid set_serial_number_string(struct string_des *des)
203beacf11bSopenharmony_ci{
204beacf11bSopenharmony_ci  char *buf;
205beacf11bSopenharmony_ci  struct string_des *str_des;
206beacf11bSopenharmony_ci  int len;
207beacf11bSopenharmony_ci
208beacf11bSopenharmony_ci  if (des == NULL)
209beacf11bSopenharmony_ci    {
210beacf11bSopenharmony_ci      usb_err("%s failed\n", __FUNCTION__);
211beacf11bSopenharmony_ci      return;
212beacf11bSopenharmony_ci    }
213beacf11bSopenharmony_ci
214beacf11bSopenharmony_ci  if (des->str == NULL || des->len <= 0)
215beacf11bSopenharmony_ci    {
216beacf11bSopenharmony_ci      usb_err("%s failed, des->str is NULL or des->len is 0\n", __FUNCTION__);
217beacf11bSopenharmony_ci      return;
218beacf11bSopenharmony_ci    }
219beacf11bSopenharmony_ci
220beacf11bSopenharmony_ci  str_des = des;
221beacf11bSopenharmony_ci  len     = str_des->len + DFU_STRING_HEAD_LEN;
222beacf11bSopenharmony_ci
223beacf11bSopenharmony_ci  buf = (char *)malloc(len);
224beacf11bSopenharmony_ci  if (buf == NULL)
225beacf11bSopenharmony_ci    {
226beacf11bSopenharmony_ci      usb_err("%s malloc failed\n", __FUNCTION__);
227beacf11bSopenharmony_ci      return;
228beacf11bSopenharmony_ci    }
229beacf11bSopenharmony_ci
230beacf11bSopenharmony_ci  g_serial_number_str.str = buf;
231beacf11bSopenharmony_ci  g_serial_number_str.len = len;
232beacf11bSopenharmony_ci
233beacf11bSopenharmony_ci  *buf = len;
234beacf11bSopenharmony_ci  *(buf + 1) = UDESC_STRING;
235beacf11bSopenharmony_ci  (void)memcpy_s(buf + DFU_STRING_HEAD_LEN, (size_t)str_des->len, str_des->str, (size_t)str_des->len);
236beacf11bSopenharmony_ci}
237beacf11bSopenharmony_ci
238beacf11bSopenharmony_civoid set_product_string(struct string_des *des)
239beacf11bSopenharmony_ci{
240beacf11bSopenharmony_ci  char *buf;
241beacf11bSopenharmony_ci  struct string_des *str_des;
242beacf11bSopenharmony_ci  int len;
243beacf11bSopenharmony_ci
244beacf11bSopenharmony_ci  if (des == NULL)
245beacf11bSopenharmony_ci    {
246beacf11bSopenharmony_ci      usb_err("%s failed\n", __FUNCTION__);
247beacf11bSopenharmony_ci      return;
248beacf11bSopenharmony_ci    }
249beacf11bSopenharmony_ci
250beacf11bSopenharmony_ci  if (des->str == NULL || des->len <= 0)
251beacf11bSopenharmony_ci    {
252beacf11bSopenharmony_ci      usb_err("%s failed, des->str is NULL or des->len is 0\n", __FUNCTION__);
253beacf11bSopenharmony_ci      return;
254beacf11bSopenharmony_ci    }
255beacf11bSopenharmony_ci
256beacf11bSopenharmony_ci  str_des = des;
257beacf11bSopenharmony_ci  len     = str_des->len + DFU_STRING_HEAD_LEN;
258beacf11bSopenharmony_ci
259beacf11bSopenharmony_ci  buf = (char *)malloc(len);
260beacf11bSopenharmony_ci  if (buf == NULL)
261beacf11bSopenharmony_ci    {
262beacf11bSopenharmony_ci      usb_err("%s malloc failed\n", __FUNCTION__);
263beacf11bSopenharmony_ci      return;
264beacf11bSopenharmony_ci    }
265beacf11bSopenharmony_ci
266beacf11bSopenharmony_ci  g_product_str.str = buf;
267beacf11bSopenharmony_ci  g_product_str.len = len;
268beacf11bSopenharmony_ci
269beacf11bSopenharmony_ci  *buf = len;
270beacf11bSopenharmony_ci  *(buf + 1) = UDESC_STRING;
271beacf11bSopenharmony_ci  (void)memcpy_s(buf + DFU_STRING_HEAD_LEN, (size_t)str_des->len, str_des->str, (size_t)str_des->len);
272beacf11bSopenharmony_ci}
273beacf11bSopenharmony_ci
274beacf11bSopenharmony_civoid set_flash_state(volatile uint8_t flash_state)
275beacf11bSopenharmony_ci{
276beacf11bSopenharmony_ci  if (flash_state != DFU_FLASH_STATE_UPGRADING &&
277beacf11bSopenharmony_ci      flash_state != DFU_FLASH_STATE_UPGRADED &&
278beacf11bSopenharmony_ci      flash_state != DFU_FLASH_STATE_ERROR)
279beacf11bSopenharmony_ci    {
280beacf11bSopenharmony_ci      PRINT_ERR("The state of flash upgrade is set failed!\n");
281beacf11bSopenharmony_ci      return;
282beacf11bSopenharmony_ci    }
283beacf11bSopenharmony_ci
284beacf11bSopenharmony_ci  g_flash_upgrade_state = flash_state;
285beacf11bSopenharmony_ci}
286beacf11bSopenharmony_ci
287beacf11bSopenharmony_civoid get_flash_state(struct usbdev_req_s *req)
288beacf11bSopenharmony_ci{
289beacf11bSopenharmony_ci  uint8_t *buf = req->buf;
290beacf11bSopenharmony_ci
291beacf11bSopenharmony_ci  buf[0] = g_flash_upgrade_state; /* The 0 bit is valid */
292beacf11bSopenharmony_ci}
293beacf11bSopenharmony_ci
294beacf11bSopenharmony_cibool usb_dfu_running(void)
295beacf11bSopenharmony_ci{
296beacf11bSopenharmony_ci  struct usb_dfu_entity *entity = usb_dfu_get_entity(0);
297beacf11bSopenharmony_ci
298beacf11bSopenharmony_ci  if (entity == NULL)
299beacf11bSopenharmony_ci    {
300beacf11bSopenharmony_ci      return false;
301beacf11bSopenharmony_ci    }
302beacf11bSopenharmony_ci
303beacf11bSopenharmony_ci  return (entity->trans_complete || entity->trans_size) ? true: false;
304beacf11bSopenharmony_ci}
305beacf11bSopenharmony_ci
306beacf11bSopenharmony_ciuint32_t usb_dfu_update_status(void)
307beacf11bSopenharmony_ci{
308beacf11bSopenharmony_ci  struct usb_dfu_entity *entity = usb_dfu_get_entity(0);
309beacf11bSopenharmony_ci
310beacf11bSopenharmony_ci  if (entity == NULL)
311beacf11bSopenharmony_ci    {
312beacf11bSopenharmony_ci      return 0;
313beacf11bSopenharmony_ci    }
314beacf11bSopenharmony_ci
315beacf11bSopenharmony_ci  return entity->trans_complete;
316beacf11bSopenharmony_ci}
317beacf11bSopenharmony_ci
318beacf11bSopenharmony_ciuint64_t *usb_dfu_update_size_get(void)
319beacf11bSopenharmony_ci{
320beacf11bSopenharmony_ci  struct usb_dfu_entity *entity = usb_dfu_get_entity(0);
321beacf11bSopenharmony_ci
322beacf11bSopenharmony_ci  if (entity == NULL)
323beacf11bSopenharmony_ci    {
324beacf11bSopenharmony_ci      return NULL;
325beacf11bSopenharmony_ci    }
326beacf11bSopenharmony_ci
327beacf11bSopenharmony_ci  return &entity->trans_size;
328beacf11bSopenharmony_ci}
329beacf11bSopenharmony_ci
330beacf11bSopenharmony_cistatic int dfu_ram_read(uint8_t *buf, uint32_t len)
331beacf11bSopenharmony_ci{
332beacf11bSopenharmony_ci  struct usb_dfu_entity *entity = usb_dfu_get_entity(0);
333beacf11bSopenharmony_ci  uint32_t offset;
334beacf11bSopenharmony_ci  errno_t ret;
335beacf11bSopenharmony_ci
336beacf11bSopenharmony_ci  if (buf == NULL || entity == NULL)
337beacf11bSopenharmony_ci    {
338beacf11bSopenharmony_ci      return -1;
339beacf11bSopenharmony_ci    }
340beacf11bSopenharmony_ci
341beacf11bSopenharmony_ci  offset = entity->offset;
342beacf11bSopenharmony_ci  if (offset > entity->ram_size)
343beacf11bSopenharmony_ci    {
344beacf11bSopenharmony_ci      return -1;
345beacf11bSopenharmony_ci    }
346beacf11bSopenharmony_ci
347beacf11bSopenharmony_ci  len = min(len, (entity->ram_size - offset));
348beacf11bSopenharmony_ci
349beacf11bSopenharmony_ci  ret = memcpy_s(buf, len, (const void *)((uint8_t *)entity->ram_addr + offset), len);
350beacf11bSopenharmony_ci  if (ret != EOK)
351beacf11bSopenharmony_ci    {
352beacf11bSopenharmony_ci      usb_err("memcpy failed!\n");
353beacf11bSopenharmony_ci      return -1;
354beacf11bSopenharmony_ci    }
355beacf11bSopenharmony_ci  entity->offset += len;
356beacf11bSopenharmony_ci
357beacf11bSopenharmony_ci  (void)uart_putc('#');
358beacf11bSopenharmony_ci
359beacf11bSopenharmony_ci  return (int)len;
360beacf11bSopenharmony_ci}
361beacf11bSopenharmony_ci
362beacf11bSopenharmony_cistatic int dfu_ram_write(const uint8_t *buf, uint32_t len)
363beacf11bSopenharmony_ci{
364beacf11bSopenharmony_ci  struct usb_dfu_entity *entity = usb_dfu_get_entity(0);
365beacf11bSopenharmony_ci  uint32_t offset;
366beacf11bSopenharmony_ci  errno_t ret;
367beacf11bSopenharmony_ci
368beacf11bSopenharmony_ci  if (buf == NULL || entity == NULL)
369beacf11bSopenharmony_ci    {
370beacf11bSopenharmony_ci      return -1;
371beacf11bSopenharmony_ci    }
372beacf11bSopenharmony_ci
373beacf11bSopenharmony_ci  offset = entity->offset;
374beacf11bSopenharmony_ci  if (offset > entity->ram_size)
375beacf11bSopenharmony_ci    {
376beacf11bSopenharmony_ci      return -1;
377beacf11bSopenharmony_ci    }
378beacf11bSopenharmony_ci
379beacf11bSopenharmony_ci  len = min(len, (entity->ram_size - offset));
380beacf11bSopenharmony_ci
381beacf11bSopenharmony_ci  ret = memcpy_s((void *)((uint8_t *)entity->ram_addr + offset), entity->ram_size - offset, buf, len);
382beacf11bSopenharmony_ci  if (ret != EOK)
383beacf11bSopenharmony_ci    {
384beacf11bSopenharmony_ci      usb_err("memcpy failed!\n");
385beacf11bSopenharmony_ci      return -1;
386beacf11bSopenharmony_ci    }
387beacf11bSopenharmony_ci  entity->offset     += len;
388beacf11bSopenharmony_ci  entity->trans_size += len;
389beacf11bSopenharmony_ci
390beacf11bSopenharmony_ci  (void)uart_putc('#');
391beacf11bSopenharmony_ci
392beacf11bSopenharmony_ci  return 0;
393beacf11bSopenharmony_ci}
394beacf11bSopenharmony_ci
395beacf11bSopenharmony_civoid usbdev_dfu_dev_init(void)
396beacf11bSopenharmony_ci{
397beacf11bSopenharmony_ci  struct usb_dfu_dev *dev;
398beacf11bSopenharmony_ci  struct string_des str;
399beacf11bSopenharmony_ci
400beacf11bSopenharmony_ci  dev = malloc(sizeof(struct usb_dfu_dev));
401beacf11bSopenharmony_ci  if (dev == NULL)
402beacf11bSopenharmony_ci    {
403beacf11bSopenharmony_ci      return;
404beacf11bSopenharmony_ci    }
405beacf11bSopenharmony_ci  (void)memset_s(dev, sizeof(struct usb_dfu_dev), 0, sizeof(struct usb_dfu_dev));
406beacf11bSopenharmony_ci
407beacf11bSopenharmony_ci  g_dfu_dev = dev;
408beacf11bSopenharmony_ci
409beacf11bSopenharmony_ci  str.str = &g_dfu_manufacturer[DFU_STRING_DATA_BYTE];
410beacf11bSopenharmony_ci  str.len = g_dfu_manufacturer[DFU_STRING_LEN_BYTE] - DFU_STRING_HEAD_LEN;
411beacf11bSopenharmony_ci  set_manufacturer_string(&str);
412beacf11bSopenharmony_ci  str.str = &g_dfu_serial[DFU_STRING_DATA_BYTE];
413beacf11bSopenharmony_ci  str.len = g_dfu_serial[DFU_STRING_LEN_BYTE] - DFU_STRING_HEAD_LEN;
414beacf11bSopenharmony_ci  set_serial_number_string(&str);
415beacf11bSopenharmony_ci  str.str = &g_dfu_product[DFU_STRING_DATA_BYTE];
416beacf11bSopenharmony_ci  str.len = g_dfu_product[DFU_STRING_LEN_BYTE] - DFU_STRING_HEAD_LEN;
417beacf11bSopenharmony_ci  set_product_string(&str);
418beacf11bSopenharmony_ci}
419beacf11bSopenharmony_ci
420beacf11bSopenharmony_civoid usbdev_dfu_dev_deinit(void)
421beacf11bSopenharmony_ci{
422beacf11bSopenharmony_ci  if (g_dfu_dev != NULL)
423beacf11bSopenharmony_ci    {
424beacf11bSopenharmony_ci      free(g_dfu_dev);
425beacf11bSopenharmony_ci      g_dfu_dev = NULL;
426beacf11bSopenharmony_ci    }
427beacf11bSopenharmony_ci
428beacf11bSopenharmony_ci  if (g_manufacturer_str.str != NULL)
429beacf11bSopenharmony_ci    {
430beacf11bSopenharmony_ci      free((void *)g_manufacturer_str.str);
431beacf11bSopenharmony_ci      g_manufacturer_str.str = NULL;
432beacf11bSopenharmony_ci    }
433beacf11bSopenharmony_ci
434beacf11bSopenharmony_ci  if (g_product_str.str != NULL)
435beacf11bSopenharmony_ci    {
436beacf11bSopenharmony_ci      free((void *)g_product_str.str);
437beacf11bSopenharmony_ci      g_product_str.str = NULL;
438beacf11bSopenharmony_ci    }
439beacf11bSopenharmony_ci
440beacf11bSopenharmony_ci  if (g_serial_number_str.str != NULL)
441beacf11bSopenharmony_ci    {
442beacf11bSopenharmony_ci      free((void *)g_serial_number_str.str);
443beacf11bSopenharmony_ci      g_serial_number_str.str = NULL;
444beacf11bSopenharmony_ci    }
445beacf11bSopenharmony_ci}
446beacf11bSopenharmony_ci
447beacf11bSopenharmony_cistatic struct usb_dfu_dev *usb_dfu_get_dev(void)
448beacf11bSopenharmony_ci{
449beacf11bSopenharmony_ci  return g_dfu_dev;
450beacf11bSopenharmony_ci}
451beacf11bSopenharmony_ci
452beacf11bSopenharmony_cistatic inline void dfu_set_state(int new_state)
453beacf11bSopenharmony_ci{
454beacf11bSopenharmony_ci  struct usb_dfu_dev *dev = usb_dfu_get_dev();
455beacf11bSopenharmony_ci  dev->dfu_state = new_state;
456beacf11bSopenharmony_ci}
457beacf11bSopenharmony_ci
458beacf11bSopenharmony_cistatic inline int dfu_get_state(void)
459beacf11bSopenharmony_ci{
460beacf11bSopenharmony_ci  struct usb_dfu_dev *dev = usb_dfu_get_dev();
461beacf11bSopenharmony_ci  return dev->dfu_state;
462beacf11bSopenharmony_ci}
463beacf11bSopenharmony_ci
464beacf11bSopenharmony_cistatic void dfu_dnload_complete(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
465beacf11bSopenharmony_ci{
466beacf11bSopenharmony_ci  struct usb_dfu_dev *dev = usb_dfu_get_dev();
467beacf11bSopenharmony_ci  int ret;
468beacf11bSopenharmony_ci
469beacf11bSopenharmony_ci  (void)ep;
470beacf11bSopenharmony_ci
471beacf11bSopenharmony_ci  ret = usb_dfu_write(usb_dfu_get_entity(0), req->buf, (int)req->len, dev->seq_num);
472beacf11bSopenharmony_ci  if (ret < 0)
473beacf11bSopenharmony_ci    {
474beacf11bSopenharmony_ci      dev->dfu_status.status = USB_DFU_ERR_UNKNOWN;
475beacf11bSopenharmony_ci      dev->dfu_state = USB_DFU_ERROR;
476beacf11bSopenharmony_ci    }
477beacf11bSopenharmony_ci}
478beacf11bSopenharmony_ci
479beacf11bSopenharmony_civoid usbdev_dfu_set_config(void)
480beacf11bSopenharmony_ci{
481beacf11bSopenharmony_ci  struct usb_dfu_dev *dev = usb_dfu_get_dev();
482beacf11bSopenharmony_ci
483beacf11bSopenharmony_ci  if (dev->dfu_state == USB_DFU_APP_DETACH)
484beacf11bSopenharmony_ci    {
485beacf11bSopenharmony_ci      dev->dfu_state = USB_DFU_IDLE;
486beacf11bSopenharmony_ci    }
487beacf11bSopenharmony_ci
488beacf11bSopenharmony_ci  dev->dfu_status.status = USB_DFU_STATUS_OK;
489beacf11bSopenharmony_ci}
490beacf11bSopenharmony_ci
491beacf11bSopenharmony_civoid usbdev_dfu_transaction_cleanup(void)
492beacf11bSopenharmony_ci{
493beacf11bSopenharmony_ci  struct usb_dfu_entity *entity = usb_dfu_get_entity(0);
494beacf11bSopenharmony_ci
495beacf11bSopenharmony_ci  if (entity == NULL)
496beacf11bSopenharmony_ci    {
497beacf11bSopenharmony_ci      return;
498beacf11bSopenharmony_ci    }
499beacf11bSopenharmony_ci
500beacf11bSopenharmony_ci  entity->trans_size     = 0;
501beacf11bSopenharmony_ci  entity->trans_complete = 0;
502beacf11bSopenharmony_ci  entity->seq_num        = 0;
503beacf11bSopenharmony_ci  entity->offset         = 0;
504beacf11bSopenharmony_ci}
505beacf11bSopenharmony_ci
506beacf11bSopenharmony_civoid usbdev_dfu_init(void)
507beacf11bSopenharmony_ci{
508beacf11bSopenharmony_ci  struct usb_dfu_dev *dev = usb_dfu_get_dev();
509beacf11bSopenharmony_ci
510beacf11bSopenharmony_ci  if (dev == NULL)
511beacf11bSopenharmony_ci    {
512beacf11bSopenharmony_ci      return;
513beacf11bSopenharmony_ci    }
514beacf11bSopenharmony_ci
515beacf11bSopenharmony_ci  /* When the host confirm that the dfu "bInterfaceProtocol" is the "Runtime mode"
516beacf11bSopenharmony_ci   * it will send a "DFU_DETACH" request to the device. When unload device, the device
517beacf11bSopenharmony_ci   * mode should change from "DFU mode" to "Runtime mode", so that next upgrade action
518beacf11bSopenharmony_ci   * can be performed smoothly.
519beacf11bSopenharmony_ci   *
520beacf11bSopenharmony_ci   * bInterfaceProtocol value: 0x1 --- Runtime protocol.
521beacf11bSopenharmony_ci   * bInterfaceProtocol value: 0x2 --- DFU mode protocol.
522beacf11bSopenharmony_ci   *
523beacf11bSopenharmony_ci   * More information, please refer to DFU_1.1.pdf
524beacf11bSopenharmony_ci   */
525beacf11bSopenharmony_ci
526beacf11bSopenharmony_ci  to_runtime_mode();
527beacf11bSopenharmony_ci  dev->dfu_state = USB_DFU_APP_IDLE;
528beacf11bSopenharmony_ci  (void)memset_s(&dev->dfu_status, sizeof(struct dfu_getstatus_response_s),
529beacf11bSopenharmony_ci                 0, sizeof(struct dfu_getstatus_response_s));
530beacf11bSopenharmony_ci  dev->dfu_status.poll_timeout[0] = USB_DFU_POLLTIMEOUT;
531beacf11bSopenharmony_ci
532beacf11bSopenharmony_ci  usbdev_dfu_transaction_cleanup();
533beacf11bSopenharmony_ci}
534beacf11bSopenharmony_ci
535beacf11bSopenharmony_cistatic int dfu_get_status_for_req(struct usbdev_req_s *ctrlreq)
536beacf11bSopenharmony_ci{
537beacf11bSopenharmony_ci  struct dfu_getstatus_response_s *status = (struct dfu_getstatus_response_s *)ctrlreq->buf;
538beacf11bSopenharmony_ci  struct usb_dfu_dev *dev = usb_dfu_get_dev();
539beacf11bSopenharmony_ci  int dfu_state = dev->dfu_state;
540beacf11bSopenharmony_ci
541beacf11bSopenharmony_ci  if (dfu_state == USB_DFU_DNLOAD_SYNC)
542beacf11bSopenharmony_ci    {
543beacf11bSopenharmony_ci      dev->dfu_state = USB_DFU_DNLOAD_IDLE;
544beacf11bSopenharmony_ci    }
545beacf11bSopenharmony_ci  else if (dfu_state == USB_DFU_DNBUSY)
546beacf11bSopenharmony_ci    {
547beacf11bSopenharmony_ci      dev->dfu_state = USB_DFU_DNLOAD_SYNC;
548beacf11bSopenharmony_ci    }
549beacf11bSopenharmony_ci  else if (dfu_state == USB_DFU_MANIFEST_SYNC)
550beacf11bSopenharmony_ci    {
551beacf11bSopenharmony_ci      dev->dfu_state = USB_DFU_MANIFEST;
552beacf11bSopenharmony_ci    }
553beacf11bSopenharmony_ci  else if (dfu_state == USB_DFU_MANIFEST)
554beacf11bSopenharmony_ci    {
555beacf11bSopenharmony_ci      dev->dfu_state = USB_DFU_IDLE;
556beacf11bSopenharmony_ci    }
557beacf11bSopenharmony_ci
558beacf11bSopenharmony_ci  *status = dev->dfu_status;
559beacf11bSopenharmony_ci  status->state = (uint8_t)dev->dfu_state;
560beacf11bSopenharmony_ci
561beacf11bSopenharmony_ci  return USB_DFU_RET_STATUS_LEN;
562beacf11bSopenharmony_ci}
563beacf11bSopenharmony_ci
564beacf11bSopenharmony_cistatic int dfu_get_state_for_req(struct usbdev_req_s *ctrlreq)
565beacf11bSopenharmony_ci{
566beacf11bSopenharmony_ci  uint8_t *state = ctrlreq->buf;
567beacf11bSopenharmony_ci
568beacf11bSopenharmony_ci  *state = (uint8_t)dfu_get_state();
569beacf11bSopenharmony_ci
570beacf11bSopenharmony_ci  return USB_DFU_RET_STATE_LEN;
571beacf11bSopenharmony_ci}
572beacf11bSopenharmony_ci
573beacf11bSopenharmony_cistatic int dfu_dnload(const struct usb_device_request *ctrl, struct usbdev_req_s *ctrlreq)
574beacf11bSopenharmony_ci{
575beacf11bSopenharmony_ci  struct usb_dfu_dev *dev = usb_dfu_get_dev();
576beacf11bSopenharmony_ci  int len                 = UGETW(ctrl->wLength);
577beacf11bSopenharmony_ci  uint16_t value          = UGETW(ctrl->wValue);
578beacf11bSopenharmony_ci
579beacf11bSopenharmony_ci  dev->dfu_state = USB_DFU_DNLOAD_SYNC;
580beacf11bSopenharmony_ci  dev->seq_num   = value;
581beacf11bSopenharmony_ci
582beacf11bSopenharmony_ci  if (len == 0)
583beacf11bSopenharmony_ci    {
584beacf11bSopenharmony_ci      if (dev->dfu_state == USB_DFU_IDLE)
585beacf11bSopenharmony_ci        {
586beacf11bSopenharmony_ci          dev->dfu_state = USB_DFU_ERROR;
587beacf11bSopenharmony_ci          return USB_DFU_RET_ERR;
588beacf11bSopenharmony_ci        }
589beacf11bSopenharmony_ci      else
590beacf11bSopenharmony_ci        {
591beacf11bSopenharmony_ci          dev->dfu_state = USB_DFU_MANIFEST_SYNC;
592beacf11bSopenharmony_ci        }
593beacf11bSopenharmony_ci    }
594beacf11bSopenharmony_ci
595beacf11bSopenharmony_ci  ctrlreq->callback = dfu_dnload_complete;
596beacf11bSopenharmony_ci
597beacf11bSopenharmony_ci  return len;
598beacf11bSopenharmony_ci}
599beacf11bSopenharmony_ci
600beacf11bSopenharmony_cistatic int dfu_upload(const struct usb_device_request *ctrl, struct usbdev_req_s *ctrlreq)
601beacf11bSopenharmony_ci{
602beacf11bSopenharmony_ci  struct usb_dfu_dev *dev = usb_dfu_get_dev();
603beacf11bSopenharmony_ci  uint16_t value          = UGETW(ctrl->wValue);
604beacf11bSopenharmony_ci
605beacf11bSopenharmony_ci  if (dev->dfu_state == USB_DFU_IDLE)
606beacf11bSopenharmony_ci    {
607beacf11bSopenharmony_ci      dev->dfu_state = USB_DFU_UPLOAD_IDLE;
608beacf11bSopenharmony_ci      dev->seq_num   = 0;
609beacf11bSopenharmony_ci      usbdev_dfu_transaction_cleanup();
610beacf11bSopenharmony_ci    }
611beacf11bSopenharmony_ci  else if (dev->dfu_state == USB_DFU_UPLOAD_IDLE)
612beacf11bSopenharmony_ci    {
613beacf11bSopenharmony_ci      dev->seq_num = value;
614beacf11bSopenharmony_ci    }
615beacf11bSopenharmony_ci
616beacf11bSopenharmony_ci  return usb_dfu_read(usb_dfu_get_entity(0), ctrlreq->buf, (int)ctrlreq->len, dev->seq_num);
617beacf11bSopenharmony_ci}
618beacf11bSopenharmony_ci
619beacf11bSopenharmony_cistatic int dfu_app_idle_request(const struct usb_device_request *ctrl, struct usbdev_req_s *ctrlreq)
620beacf11bSopenharmony_ci{
621beacf11bSopenharmony_ci  int ret = USB_DFU_RET_OK;
622beacf11bSopenharmony_ci
623beacf11bSopenharmony_ci  switch (ctrl->bRequest)
624beacf11bSopenharmony_ci    {
625beacf11bSopenharmony_ci    case USB_DFU_DETACH:
626beacf11bSopenharmony_ci      {
627beacf11bSopenharmony_ci        to_dfu_mode();
628beacf11bSopenharmony_ci        dfu_set_state(USB_DFU_APP_DETACH);
629beacf11bSopenharmony_ci      }
630beacf11bSopenharmony_ci      break;
631beacf11bSopenharmony_ci
632beacf11bSopenharmony_ci    case USB_DFU_GET_STATUS:
633beacf11bSopenharmony_ci      ret = dfu_get_status_for_req(ctrlreq);
634beacf11bSopenharmony_ci      break;
635beacf11bSopenharmony_ci
636beacf11bSopenharmony_ci    case USB_DFU_GET_STATE:
637beacf11bSopenharmony_ci      ret = dfu_get_state_for_req(ctrlreq);
638beacf11bSopenharmony_ci      break;
639beacf11bSopenharmony_ci
640beacf11bSopenharmony_ci    default:
641beacf11bSopenharmony_ci      {
642beacf11bSopenharmony_ci        ret = USB_DFU_RET_ERR;
643beacf11bSopenharmony_ci        dfu_set_state(USB_DFU_APP_IDLE);
644beacf11bSopenharmony_ci      }
645beacf11bSopenharmony_ci      break;
646beacf11bSopenharmony_ci    }
647beacf11bSopenharmony_ci
648beacf11bSopenharmony_ci  return ret;
649beacf11bSopenharmony_ci}
650beacf11bSopenharmony_ci
651beacf11bSopenharmony_cistatic int dfu_app_detach_request(const struct usb_device_request *ctrl, struct usbdev_req_s *ctrlreq)
652beacf11bSopenharmony_ci{
653beacf11bSopenharmony_ci  int ret;
654beacf11bSopenharmony_ci
655beacf11bSopenharmony_ci  switch (ctrl->bRequest)
656beacf11bSopenharmony_ci    {
657beacf11bSopenharmony_ci    case USB_DFU_GET_STATUS:
658beacf11bSopenharmony_ci      ret = dfu_get_status_for_req(ctrlreq);
659beacf11bSopenharmony_ci      break;
660beacf11bSopenharmony_ci
661beacf11bSopenharmony_ci    case USB_DFU_GET_STATE:
662beacf11bSopenharmony_ci      ret = dfu_get_state_for_req(ctrlreq);
663beacf11bSopenharmony_ci      break;
664beacf11bSopenharmony_ci
665beacf11bSopenharmony_ci    default:
666beacf11bSopenharmony_ci      {
667beacf11bSopenharmony_ci        ret = USB_DFU_RET_ERR;
668beacf11bSopenharmony_ci        dfu_set_state(USB_DFU_APP_IDLE);
669beacf11bSopenharmony_ci      }
670beacf11bSopenharmony_ci      break;
671beacf11bSopenharmony_ci    }
672beacf11bSopenharmony_ci
673beacf11bSopenharmony_ci  return ret;
674beacf11bSopenharmony_ci}
675beacf11bSopenharmony_ci
676beacf11bSopenharmony_cistatic int dfu_idle_request(const struct usb_device_request *ctrl, struct usbdev_req_s *ctrlreq)
677beacf11bSopenharmony_ci{
678beacf11bSopenharmony_ci  int ret = USB_DFU_RET_OK;
679beacf11bSopenharmony_ci
680beacf11bSopenharmony_ci  switch (ctrl->bRequest)
681beacf11bSopenharmony_ci    {
682beacf11bSopenharmony_ci    case USB_DFU_GET_STATUS:
683beacf11bSopenharmony_ci      ret = dfu_get_status_for_req(ctrlreq);
684beacf11bSopenharmony_ci      break;
685beacf11bSopenharmony_ci
686beacf11bSopenharmony_ci    case USB_DFU_GET_STATE:
687beacf11bSopenharmony_ci      ret = dfu_get_state_for_req(ctrlreq);
688beacf11bSopenharmony_ci      break;
689beacf11bSopenharmony_ci
690beacf11bSopenharmony_ci    case USB_DFU_DNLOAD:
691beacf11bSopenharmony_ci      ret = dfu_dnload(ctrl, ctrlreq);
692beacf11bSopenharmony_ci      break;
693beacf11bSopenharmony_ci
694beacf11bSopenharmony_ci    case USB_DFU_UPLOAD:
695beacf11bSopenharmony_ci      ret = dfu_upload(ctrl, ctrlreq);
696beacf11bSopenharmony_ci      break;
697beacf11bSopenharmony_ci
698beacf11bSopenharmony_ci    case USB_DFU_ABORT:
699beacf11bSopenharmony_ci      dfu_set_state(USB_DFU_IDLE);
700beacf11bSopenharmony_ci      break;
701beacf11bSopenharmony_ci
702beacf11bSopenharmony_ci    case USB_DFU_FLASH_STATE:
703beacf11bSopenharmony_ci      {
704beacf11bSopenharmony_ci        get_flash_state(ctrlreq);
705beacf11bSopenharmony_ci        ret = 1;
706beacf11bSopenharmony_ci      }
707beacf11bSopenharmony_ci      break;
708beacf11bSopenharmony_ci
709beacf11bSopenharmony_ci    default:
710beacf11bSopenharmony_ci      {
711beacf11bSopenharmony_ci        ret = USB_DFU_RET_ERR;
712beacf11bSopenharmony_ci        dfu_set_state(USB_DFU_ERROR);
713beacf11bSopenharmony_ci      }
714beacf11bSopenharmony_ci      break;
715beacf11bSopenharmony_ci    }
716beacf11bSopenharmony_ci
717beacf11bSopenharmony_ci  return ret;
718beacf11bSopenharmony_ci}
719beacf11bSopenharmony_ci
720beacf11bSopenharmony_cistatic int dfu_dnload_sync_request(const struct usb_device_request *ctrl, struct usbdev_req_s *ctrlreq)
721beacf11bSopenharmony_ci{
722beacf11bSopenharmony_ci  int ret;
723beacf11bSopenharmony_ci
724beacf11bSopenharmony_ci  switch (ctrl->bRequest)
725beacf11bSopenharmony_ci    {
726beacf11bSopenharmony_ci    case USB_DFU_GET_STATUS:
727beacf11bSopenharmony_ci      ret = dfu_get_status_for_req(ctrlreq);
728beacf11bSopenharmony_ci      break;
729beacf11bSopenharmony_ci
730beacf11bSopenharmony_ci    case USB_DFU_GET_STATE:
731beacf11bSopenharmony_ci      ret = dfu_get_state_for_req(ctrlreq);
732beacf11bSopenharmony_ci      break;
733beacf11bSopenharmony_ci
734beacf11bSopenharmony_ci    default:
735beacf11bSopenharmony_ci      {
736beacf11bSopenharmony_ci        ret = USB_DFU_RET_ERR;
737beacf11bSopenharmony_ci        dfu_set_state(USB_DFU_ERROR);
738beacf11bSopenharmony_ci      }
739beacf11bSopenharmony_ci      break;
740beacf11bSopenharmony_ci    }
741beacf11bSopenharmony_ci
742beacf11bSopenharmony_ci  return ret;
743beacf11bSopenharmony_ci}
744beacf11bSopenharmony_ci
745beacf11bSopenharmony_cistatic int dfu_dnbusy_request(const struct usb_device_request *ctrl, struct usbdev_req_s *ctrlreq)
746beacf11bSopenharmony_ci{
747beacf11bSopenharmony_ci  int ret;
748beacf11bSopenharmony_ci
749beacf11bSopenharmony_ci  switch (ctrl->bRequest)
750beacf11bSopenharmony_ci    {
751beacf11bSopenharmony_ci    case USB_DFU_GET_STATUS:
752beacf11bSopenharmony_ci      ret = dfu_get_status_for_req(ctrlreq);
753beacf11bSopenharmony_ci      break;
754beacf11bSopenharmony_ci
755beacf11bSopenharmony_ci    default:
756beacf11bSopenharmony_ci      {
757beacf11bSopenharmony_ci        ret = USB_DFU_RET_ERR;
758beacf11bSopenharmony_ci        dfu_set_state(USB_DFU_ERROR);
759beacf11bSopenharmony_ci      }
760beacf11bSopenharmony_ci      break;
761beacf11bSopenharmony_ci    }
762beacf11bSopenharmony_ci
763beacf11bSopenharmony_ci  return ret;
764beacf11bSopenharmony_ci}
765beacf11bSopenharmony_ci
766beacf11bSopenharmony_cistatic int dfu_dnload_idle_request(const struct usb_device_request *ctrl, struct usbdev_req_s *ctrlreq)
767beacf11bSopenharmony_ci{
768beacf11bSopenharmony_ci  int ret = USB_DFU_RET_OK;
769beacf11bSopenharmony_ci
770beacf11bSopenharmony_ci  switch (ctrl->bRequest)
771beacf11bSopenharmony_ci    {
772beacf11bSopenharmony_ci    case USB_DFU_GET_STATUS:
773beacf11bSopenharmony_ci      ret = dfu_get_status_for_req(ctrlreq);
774beacf11bSopenharmony_ci      break;
775beacf11bSopenharmony_ci
776beacf11bSopenharmony_ci    case USB_DFU_GET_STATE:
777beacf11bSopenharmony_ci      ret = dfu_get_state_for_req(ctrlreq);
778beacf11bSopenharmony_ci      break;
779beacf11bSopenharmony_ci
780beacf11bSopenharmony_ci    case USB_DFU_DNLOAD:
781beacf11bSopenharmony_ci      ret = dfu_dnload(ctrl, ctrlreq);
782beacf11bSopenharmony_ci      break;
783beacf11bSopenharmony_ci
784beacf11bSopenharmony_ci    case USB_DFU_ABORT:
785beacf11bSopenharmony_ci      dfu_set_state(USB_DFU_IDLE);
786beacf11bSopenharmony_ci      break;
787beacf11bSopenharmony_ci
788beacf11bSopenharmony_ci    default:
789beacf11bSopenharmony_ci      {
790beacf11bSopenharmony_ci        ret = USB_DFU_RET_ERR;
791beacf11bSopenharmony_ci        dfu_set_state(USB_DFU_ERROR);
792beacf11bSopenharmony_ci      }
793beacf11bSopenharmony_ci      break;
794beacf11bSopenharmony_ci    }
795beacf11bSopenharmony_ci
796beacf11bSopenharmony_ci  return ret;
797beacf11bSopenharmony_ci}
798beacf11bSopenharmony_ci
799beacf11bSopenharmony_cistatic int dfu_manifest_sync_request(const struct usb_device_request *ctrl, struct usbdev_req_s *ctrlreq)
800beacf11bSopenharmony_ci{
801beacf11bSopenharmony_ci  struct usb_dfu_dev *dev = usb_dfu_get_dev();
802beacf11bSopenharmony_ci  struct usb_dfu_entity *entity = usb_dfu_get_entity(0);
803beacf11bSopenharmony_ci  int ret;
804beacf11bSopenharmony_ci
805beacf11bSopenharmony_ci  switch (ctrl->bRequest)
806beacf11bSopenharmony_ci    {
807beacf11bSopenharmony_ci    case USB_DFU_GET_STATUS:
808beacf11bSopenharmony_ci      {
809beacf11bSopenharmony_ci        dev->seq_num = 0;
810beacf11bSopenharmony_ci        ret          = dfu_get_status_for_req(ctrlreq);
811beacf11bSopenharmony_ci        if (entity != NULL)
812beacf11bSopenharmony_ci          {
813beacf11bSopenharmony_ci            entity->seq_num = 0;
814beacf11bSopenharmony_ci            entity->offset  = 0;
815beacf11bSopenharmony_ci          }
816beacf11bSopenharmony_ci      }
817beacf11bSopenharmony_ci      break;
818beacf11bSopenharmony_ci
819beacf11bSopenharmony_ci    case USB_DFU_GET_STATE:
820beacf11bSopenharmony_ci      ret = dfu_get_state_for_req(ctrlreq);
821beacf11bSopenharmony_ci      break;
822beacf11bSopenharmony_ci
823beacf11bSopenharmony_ci    default:
824beacf11bSopenharmony_ci      {
825beacf11bSopenharmony_ci        ret = USB_DFU_RET_ERR;
826beacf11bSopenharmony_ci        dfu_set_state(USB_DFU_ERROR);
827beacf11bSopenharmony_ci      }
828beacf11bSopenharmony_ci      break;
829beacf11bSopenharmony_ci    }
830beacf11bSopenharmony_ci
831beacf11bSopenharmony_ci  return ret;
832beacf11bSopenharmony_ci}
833beacf11bSopenharmony_ci
834beacf11bSopenharmony_cistatic int dfu_manifest_request(const struct usb_device_request *ctrl, struct usbdev_req_s *ctrlreq)
835beacf11bSopenharmony_ci{
836beacf11bSopenharmony_ci  struct usb_dfu_dev *dev = usb_dfu_get_dev();
837beacf11bSopenharmony_ci  struct usb_dfu_entity *entity = usb_dfu_get_entity(0);
838beacf11bSopenharmony_ci  int ret;
839beacf11bSopenharmony_ci
840beacf11bSopenharmony_ci  switch (ctrl->bRequest)
841beacf11bSopenharmony_ci    {
842beacf11bSopenharmony_ci    case USB_DFU_GET_STATUS:
843beacf11bSopenharmony_ci      {
844beacf11bSopenharmony_ci        ret = dfu_get_status_for_req(ctrlreq);
845beacf11bSopenharmony_ci        dev->seq_num = 0;
846beacf11bSopenharmony_ci        if (entity != NULL)
847beacf11bSopenharmony_ci          {
848beacf11bSopenharmony_ci            entity->trans_complete = 1;
849beacf11bSopenharmony_ci          }
850beacf11bSopenharmony_ci        dprintf("\nDOWNLOAD ... OK\n");
851beacf11bSopenharmony_ci      }
852beacf11bSopenharmony_ci      break;
853beacf11bSopenharmony_ci
854beacf11bSopenharmony_ci    case USB_DFU_GET_STATE:
855beacf11bSopenharmony_ci      ret = dfu_get_state_for_req(ctrlreq);
856beacf11bSopenharmony_ci      break;
857beacf11bSopenharmony_ci
858beacf11bSopenharmony_ci    default:
859beacf11bSopenharmony_ci      {
860beacf11bSopenharmony_ci        ret = USB_DFU_RET_ERR;
861beacf11bSopenharmony_ci        dfu_set_state(USB_DFU_ERROR);
862beacf11bSopenharmony_ci      }
863beacf11bSopenharmony_ci      break;
864beacf11bSopenharmony_ci    }
865beacf11bSopenharmony_ci
866beacf11bSopenharmony_ci  return ret;
867beacf11bSopenharmony_ci}
868beacf11bSopenharmony_ci
869beacf11bSopenharmony_cistatic int dfu_manifest_wait_reset(const struct usb_device_request *ctrl, const struct usbdev_req_s *ctrlreq)
870beacf11bSopenharmony_ci{
871beacf11bSopenharmony_ci  (void)ctrl;
872beacf11bSopenharmony_ci  (void)ctrlreq;
873beacf11bSopenharmony_ci  dprintf("Do nothing!\n");
874beacf11bSopenharmony_ci  return 0;
875beacf11bSopenharmony_ci}
876beacf11bSopenharmony_ci
877beacf11bSopenharmony_cistatic int dfu_upload_idle_request(const struct usb_device_request *ctrl, struct usbdev_req_s *ctrlreq)
878beacf11bSopenharmony_ci{
879beacf11bSopenharmony_ci  int ret = USB_DFU_RET_OK;
880beacf11bSopenharmony_ci  int len = UGETW(ctrl->wLength);
881beacf11bSopenharmony_ci
882beacf11bSopenharmony_ci  switch (ctrl->bRequest)
883beacf11bSopenharmony_ci    {
884beacf11bSopenharmony_ci    case USB_DFU_GET_STATUS:
885beacf11bSopenharmony_ci      ret = dfu_get_status_for_req(ctrlreq);
886beacf11bSopenharmony_ci      break;
887beacf11bSopenharmony_ci
888beacf11bSopenharmony_ci    case USB_DFU_GET_STATE:
889beacf11bSopenharmony_ci      ret = dfu_get_state_for_req(ctrlreq);
890beacf11bSopenharmony_ci      break;
891beacf11bSopenharmony_ci
892beacf11bSopenharmony_ci    case USB_DFU_UPLOAD:
893beacf11bSopenharmony_ci      {
894beacf11bSopenharmony_ci        ret = dfu_upload(ctrl, ctrlreq);
895beacf11bSopenharmony_ci        if (ret >= 0 && ret < len)
896beacf11bSopenharmony_ci          {
897beacf11bSopenharmony_ci            dfu_set_state(USB_DFU_IDLE);
898beacf11bSopenharmony_ci          }
899beacf11bSopenharmony_ci      }
900beacf11bSopenharmony_ci      break;
901beacf11bSopenharmony_ci
902beacf11bSopenharmony_ci    case USB_DFU_ABORT:
903beacf11bSopenharmony_ci      dfu_set_state(USB_DFU_IDLE);
904beacf11bSopenharmony_ci      break;
905beacf11bSopenharmony_ci
906beacf11bSopenharmony_ci    default:
907beacf11bSopenharmony_ci      {
908beacf11bSopenharmony_ci        ret = USB_DFU_RET_ERR;
909beacf11bSopenharmony_ci        dfu_set_state(USB_DFU_ERROR);
910beacf11bSopenharmony_ci      }
911beacf11bSopenharmony_ci      break;
912beacf11bSopenharmony_ci    }
913beacf11bSopenharmony_ci
914beacf11bSopenharmony_ci  return ret;
915beacf11bSopenharmony_ci}
916beacf11bSopenharmony_ci
917beacf11bSopenharmony_cistatic int dfu_error_request(const struct usb_device_request *ctrl, struct usbdev_req_s *ctrlreq)
918beacf11bSopenharmony_ci{
919beacf11bSopenharmony_ci  struct usb_dfu_dev *dev = usb_dfu_get_dev();
920beacf11bSopenharmony_ci  int ret                 = USB_DFU_RET_OK;
921beacf11bSopenharmony_ci
922beacf11bSopenharmony_ci  switch (ctrl->bRequest)
923beacf11bSopenharmony_ci    {
924beacf11bSopenharmony_ci    case USB_DFU_GET_STATUS:
925beacf11bSopenharmony_ci      ret = dfu_get_status_for_req(ctrlreq);
926beacf11bSopenharmony_ci      break;
927beacf11bSopenharmony_ci
928beacf11bSopenharmony_ci    case USB_DFU_GET_STATE:
929beacf11bSopenharmony_ci      ret = dfu_get_state_for_req(ctrlreq);
930beacf11bSopenharmony_ci      break;
931beacf11bSopenharmony_ci
932beacf11bSopenharmony_ci    case USB_DFU_CLR_STATUS:
933beacf11bSopenharmony_ci      {
934beacf11bSopenharmony_ci        dev->dfu_status.status = USB_DFU_STATUS_OK;
935beacf11bSopenharmony_ci        dfu_set_state(USB_DFU_IDLE);
936beacf11bSopenharmony_ci      }
937beacf11bSopenharmony_ci      break;
938beacf11bSopenharmony_ci
939beacf11bSopenharmony_ci    default:
940beacf11bSopenharmony_ci      {
941beacf11bSopenharmony_ci        ret = USB_DFU_RET_ERR;
942beacf11bSopenharmony_ci        dfu_set_state(USB_DFU_ERROR);
943beacf11bSopenharmony_ci      }
944beacf11bSopenharmony_ci      break;
945beacf11bSopenharmony_ci    }
946beacf11bSopenharmony_ci
947beacf11bSopenharmony_ci  return ret;
948beacf11bSopenharmony_ci}
949beacf11bSopenharmony_ci
950beacf11bSopenharmony_ciint usbdev_dfu_class_requests(const struct usbdev_s *dev,
951beacf11bSopenharmony_ci                              const struct usb_device_request *ctrl,
952beacf11bSopenharmony_ci                              struct usbdev_req_s *ctrlreq)
953beacf11bSopenharmony_ci{
954beacf11bSopenharmony_ci  int ret = -EOPNOTSUPP;
955beacf11bSopenharmony_ci
956beacf11bSopenharmony_ci  (void)dev;
957beacf11bSopenharmony_ci
958beacf11bSopenharmony_ci  switch (dfu_get_state())
959beacf11bSopenharmony_ci    {
960beacf11bSopenharmony_ci    case USB_DFU_APP_IDLE:
961beacf11bSopenharmony_ci      ret = dfu_app_idle_request(ctrl, ctrlreq);
962beacf11bSopenharmony_ci      break;
963beacf11bSopenharmony_ci
964beacf11bSopenharmony_ci    case USB_DFU_APP_DETACH:
965beacf11bSopenharmony_ci      ret = dfu_app_detach_request(ctrl, ctrlreq);
966beacf11bSopenharmony_ci      break;
967beacf11bSopenharmony_ci
968beacf11bSopenharmony_ci    case USB_DFU_IDLE:
969beacf11bSopenharmony_ci      ret = dfu_idle_request(ctrl, ctrlreq);
970beacf11bSopenharmony_ci      break;
971beacf11bSopenharmony_ci
972beacf11bSopenharmony_ci    case USB_DFU_DNLOAD_SYNC:
973beacf11bSopenharmony_ci      ret = dfu_dnload_sync_request(ctrl, ctrlreq);
974beacf11bSopenharmony_ci      break;
975beacf11bSopenharmony_ci
976beacf11bSopenharmony_ci    case USB_DFU_DNBUSY:
977beacf11bSopenharmony_ci      ret = dfu_dnbusy_request(ctrl, ctrlreq);
978beacf11bSopenharmony_ci      break;
979beacf11bSopenharmony_ci
980beacf11bSopenharmony_ci    case USB_DFU_DNLOAD_IDLE:
981beacf11bSopenharmony_ci      ret = dfu_dnload_idle_request(ctrl, ctrlreq);
982beacf11bSopenharmony_ci      break;
983beacf11bSopenharmony_ci
984beacf11bSopenharmony_ci    case USB_DFU_MANIFEST_SYNC:
985beacf11bSopenharmony_ci      ret = dfu_manifest_sync_request(ctrl, ctrlreq);
986beacf11bSopenharmony_ci      break;
987beacf11bSopenharmony_ci
988beacf11bSopenharmony_ci    case USB_DFU_MANIFEST:
989beacf11bSopenharmony_ci      ret = dfu_manifest_request(ctrl, ctrlreq);
990beacf11bSopenharmony_ci      break;
991beacf11bSopenharmony_ci
992beacf11bSopenharmony_ci    case USB_DFU_MANIFEST_WAIT_RESET:
993beacf11bSopenharmony_ci      ret = dfu_manifest_wait_reset(ctrl, ctrlreq);
994beacf11bSopenharmony_ci      break;
995beacf11bSopenharmony_ci
996beacf11bSopenharmony_ci    case USB_DFU_UPLOAD_IDLE:
997beacf11bSopenharmony_ci      ret = dfu_upload_idle_request(ctrl, ctrlreq);
998beacf11bSopenharmony_ci      break;
999beacf11bSopenharmony_ci
1000beacf11bSopenharmony_ci    case USB_DFU_ERROR:
1001beacf11bSopenharmony_ci      ret = dfu_error_request(ctrl, ctrlreq);
1002beacf11bSopenharmony_ci      break;
1003beacf11bSopenharmony_ci
1004beacf11bSopenharmony_ci    default:
1005beacf11bSopenharmony_ci      usb_err("The state = %d of dfu is not support!\n", dfu_get_state());
1006beacf11bSopenharmony_ci      break;
1007beacf11bSopenharmony_ci    }
1008beacf11bSopenharmony_ci
1009beacf11bSopenharmony_ci  return ret;
1010beacf11bSopenharmony_ci}
1011beacf11bSopenharmony_ci
1012beacf11bSopenharmony_cistatic int dfu_ram_init_env(struct usb_dfu_entity *entity, char *envstr)
1013beacf11bSopenharmony_ci{
1014beacf11bSopenharmony_ci  char *st;
1015beacf11bSopenharmony_ci  int ret;
1016beacf11bSopenharmony_ci
1017beacf11bSopenharmony_ci  st = strsep(&envstr, " ");
1018beacf11bSopenharmony_ci  if (st == NULL)
1019beacf11bSopenharmony_ci    {
1020beacf11bSopenharmony_ci      return -1;
1021beacf11bSopenharmony_ci    }
1022beacf11bSopenharmony_ci  ret = strncpy_s(entity->dfu_name, DFU_NAME_MAX_LEN, st, strlen(st) + 1);
1023beacf11bSopenharmony_ci  if (ret != EOK)
1024beacf11bSopenharmony_ci    {
1025beacf11bSopenharmony_ci      return -1;
1026beacf11bSopenharmony_ci    }
1027beacf11bSopenharmony_ci
1028beacf11bSopenharmony_ci  st = strsep(&envstr, " ");
1029beacf11bSopenharmony_ci  if (strcmp(st, "ram"))
1030beacf11bSopenharmony_ci    {
1031beacf11bSopenharmony_ci      return -1;
1032beacf11bSopenharmony_ci    }
1033beacf11bSopenharmony_ci
1034beacf11bSopenharmony_ci  st = strsep(&envstr, " ");
1035beacf11bSopenharmony_ci  if (st == NULL)
1036beacf11bSopenharmony_ci    {
1037beacf11bSopenharmony_ci      return -1;
1038beacf11bSopenharmony_ci    }
1039beacf11bSopenharmony_ci  entity->ram_addr = (void *)strtoul(st, &st, 16);
1040beacf11bSopenharmony_ci
1041beacf11bSopenharmony_ci  st = strsep(&envstr, " ");
1042beacf11bSopenharmony_ci  if (st == NULL)
1043beacf11bSopenharmony_ci    {
1044beacf11bSopenharmony_ci      return -1;
1045beacf11bSopenharmony_ci    }
1046beacf11bSopenharmony_ci  entity->ram_size = strtoul(st, &st, 16);
1047beacf11bSopenharmony_ci
1048beacf11bSopenharmony_ci  entity->dfu_write = dfu_ram_write;
1049beacf11bSopenharmony_ci  entity->dfu_read  = dfu_ram_read;
1050beacf11bSopenharmony_ci
1051beacf11bSopenharmony_ci  return 0;
1052beacf11bSopenharmony_ci}
1053beacf11bSopenharmony_ci
1054beacf11bSopenharmony_ciint usb_dfu_init_env_entities(char *type, char *envstr, char *devstr)
1055beacf11bSopenharmony_ci{
1056beacf11bSopenharmony_ci  struct usb_dfu_entity *entity;
1057beacf11bSopenharmony_ci  int ret;
1058beacf11bSopenharmony_ci
1059beacf11bSopenharmony_ci  (void)devstr;
1060beacf11bSopenharmony_ci
1061beacf11bSopenharmony_ci  if (type == NULL || envstr == NULL)
1062beacf11bSopenharmony_ci    {
1063beacf11bSopenharmony_ci      return -1;
1064beacf11bSopenharmony_ci    }
1065beacf11bSopenharmony_ci
1066beacf11bSopenharmony_ci  mtx_lock(&g_dfu_mtx);
1067beacf11bSopenharmony_ci  if (g_dfu_entity != NULL)
1068beacf11bSopenharmony_ci    {
1069beacf11bSopenharmony_ci      goto err;
1070beacf11bSopenharmony_ci    }
1071beacf11bSopenharmony_ci
1072beacf11bSopenharmony_ci  entity = malloc(sizeof(struct usb_dfu_entity));
1073beacf11bSopenharmony_ci  if (entity == NULL)
1074beacf11bSopenharmony_ci    {
1075beacf11bSopenharmony_ci      goto err;
1076beacf11bSopenharmony_ci    }
1077beacf11bSopenharmony_ci  (void)memset_s(entity, sizeof(struct usb_dfu_entity), 0, sizeof(struct usb_dfu_entity));
1078beacf11bSopenharmony_ci
1079beacf11bSopenharmony_ci  if (!strcmp(type, "ram"))
1080beacf11bSopenharmony_ci    {
1081beacf11bSopenharmony_ci      ret = dfu_ram_init_env(entity, envstr);
1082beacf11bSopenharmony_ci      if (ret < 0)
1083beacf11bSopenharmony_ci        {
1084beacf11bSopenharmony_ci          free(entity);
1085beacf11bSopenharmony_ci          goto err;
1086beacf11bSopenharmony_ci        }
1087beacf11bSopenharmony_ci    }
1088beacf11bSopenharmony_ci  else
1089beacf11bSopenharmony_ci    {
1090beacf11bSopenharmony_ci      free(entity);
1091beacf11bSopenharmony_ci      usb_err("Device %s not (yet) supported!\n", type);
1092beacf11bSopenharmony_ci      goto err;
1093beacf11bSopenharmony_ci    }
1094beacf11bSopenharmony_ci
1095beacf11bSopenharmony_ci  g_dfu_entity = entity;
1096beacf11bSopenharmony_ci  usbdev_dfu_transaction_cleanup();
1097beacf11bSopenharmony_ci  mtx_unlock(&g_dfu_mtx);
1098beacf11bSopenharmony_ci
1099beacf11bSopenharmony_ci  return 0;
1100beacf11bSopenharmony_cierr:
1101beacf11bSopenharmony_ci  mtx_unlock(&g_dfu_mtx);
1102beacf11bSopenharmony_ci  return -1;
1103beacf11bSopenharmony_ci}
1104beacf11bSopenharmony_ci
1105beacf11bSopenharmony_civoid usb_dfu_free_entities(void)
1106beacf11bSopenharmony_ci{
1107beacf11bSopenharmony_ci  mtx_lock(&g_dfu_mtx);
1108beacf11bSopenharmony_ci  if (g_dfu_entity == NULL)
1109beacf11bSopenharmony_ci    {
1110beacf11bSopenharmony_ci      mtx_unlock(&g_dfu_mtx);
1111beacf11bSopenharmony_ci      return;
1112beacf11bSopenharmony_ci    }
1113beacf11bSopenharmony_ci  free(g_dfu_entity);
1114beacf11bSopenharmony_ci  g_dfu_entity = NULL;
1115beacf11bSopenharmony_ci  mtx_unlock(&g_dfu_mtx);
1116beacf11bSopenharmony_ci}
1117beacf11bSopenharmony_ci
1118beacf11bSopenharmony_cistruct usb_dfu_entity *usb_dfu_get_entity(int alter)
1119beacf11bSopenharmony_ci{
1120beacf11bSopenharmony_ci  (void)alter;
1121beacf11bSopenharmony_ci  return g_dfu_entity;
1122beacf11bSopenharmony_ci}
1123beacf11bSopenharmony_ci
1124beacf11bSopenharmony_ciint usb_dfu_read(struct usb_dfu_entity *dfu, void *buf, int size, uint32_t blk_seq_num)
1125beacf11bSopenharmony_ci{
1126beacf11bSopenharmony_ci  int ret;
1127beacf11bSopenharmony_ci
1128beacf11bSopenharmony_ci  if (dfu == NULL || buf == NULL)
1129beacf11bSopenharmony_ci    {
1130beacf11bSopenharmony_ci      return -1;
1131beacf11bSopenharmony_ci    }
1132beacf11bSopenharmony_ci
1133beacf11bSopenharmony_ci  if (dfu->seq_num != blk_seq_num)
1134beacf11bSopenharmony_ci    {
1135beacf11bSopenharmony_ci      return -1;
1136beacf11bSopenharmony_ci    }
1137beacf11bSopenharmony_ci  dfu->seq_num++;
1138beacf11bSopenharmony_ci
1139beacf11bSopenharmony_ci  ret = dfu->dfu_read(buf, size);
1140beacf11bSopenharmony_ci  if (ret < 0)
1141beacf11bSopenharmony_ci    {
1142beacf11bSopenharmony_ci      return -1;
1143beacf11bSopenharmony_ci    }
1144beacf11bSopenharmony_ci
1145beacf11bSopenharmony_ci  if (dfu->offset >= dfu->trans_size)
1146beacf11bSopenharmony_ci    {
1147beacf11bSopenharmony_ci      dprintf("\nUPLOAD ... done\n");
1148beacf11bSopenharmony_ci      usbdev_dfu_transaction_cleanup();
1149beacf11bSopenharmony_ci    }
1150beacf11bSopenharmony_ci
1151beacf11bSopenharmony_ci  return ret;
1152beacf11bSopenharmony_ci}
1153beacf11bSopenharmony_ci
1154beacf11bSopenharmony_ciint usb_dfu_write(struct usb_dfu_entity *dfu, void *buf, int size, uint32_t blk_seq_num)
1155beacf11bSopenharmony_ci{
1156beacf11bSopenharmony_ci  int ret;
1157beacf11bSopenharmony_ci
1158beacf11bSopenharmony_ci  if (dfu == NULL || buf == NULL)
1159beacf11bSopenharmony_ci    {
1160beacf11bSopenharmony_ci      return -1;
1161beacf11bSopenharmony_ci    }
1162beacf11bSopenharmony_ci
1163beacf11bSopenharmony_ci  if (dfu->seq_num != blk_seq_num)
1164beacf11bSopenharmony_ci    {
1165beacf11bSopenharmony_ci      usbdev_dfu_transaction_cleanup();
1166beacf11bSopenharmony_ci      return -1;
1167beacf11bSopenharmony_ci    }
1168beacf11bSopenharmony_ci  dfu->seq_num++;
1169beacf11bSopenharmony_ci
1170beacf11bSopenharmony_ci  ret = dfu->dfu_write(buf, size);
1171beacf11bSopenharmony_ci  if (ret < 0)
1172beacf11bSopenharmony_ci    {
1173beacf11bSopenharmony_ci      usbdev_dfu_transaction_cleanup();
1174beacf11bSopenharmony_ci      return -1;
1175beacf11bSopenharmony_ci    }
1176beacf11bSopenharmony_ci
1177beacf11bSopenharmony_ci  return 0;
1178beacf11bSopenharmony_ci}
1179beacf11bSopenharmony_ci
1180beacf11bSopenharmony_civoid usbdev_dfu_mkdevdesc(uint8_t *buf)
1181beacf11bSopenharmony_ci{
1182beacf11bSopenharmony_ci  errno_t ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, &g_dfu_device_desc, sizeof(g_dfu_device_desc));
1183beacf11bSopenharmony_ci  if (ret != EOK)
1184beacf11bSopenharmony_ci    {
1185beacf11bSopenharmony_ci      usb_err("memcpy_s fail!, ret:%d\n", ret);
1186beacf11bSopenharmony_ci      return;
1187beacf11bSopenharmony_ci    }
1188beacf11bSopenharmony_ci}
1189beacf11bSopenharmony_ci
1190beacf11bSopenharmony_ciint usbdev_dfu_mkstrdesc(uint8_t id, uint8_t *buf)
1191beacf11bSopenharmony_ci{
1192beacf11bSopenharmony_ci  errno_t ret;
1193beacf11bSopenharmony_ci  const char *str;
1194beacf11bSopenharmony_ci  int i;
1195beacf11bSopenharmony_ci
1196beacf11bSopenharmony_ci  for (i = 0; g_dfu_string_defs[i].s != NULL; i++)
1197beacf11bSopenharmony_ci    {
1198beacf11bSopenharmony_ci      str = g_dfu_string_defs[i].s;
1199beacf11bSopenharmony_ci      if (g_dfu_string_defs[i].id == id)
1200beacf11bSopenharmony_ci        {
1201beacf11bSopenharmony_ci          ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, str, str[0]);
1202beacf11bSopenharmony_ci          if (ret != EOK)
1203beacf11bSopenharmony_ci            {
1204beacf11bSopenharmony_ci              usb_err("memcpy_s failed, ret = %d\n", ret);
1205beacf11bSopenharmony_ci              return -1;
1206beacf11bSopenharmony_ci            }
1207beacf11bSopenharmony_ci          return str[0];
1208beacf11bSopenharmony_ci        }
1209beacf11bSopenharmony_ci    }
1210beacf11bSopenharmony_ci  usb_err("Can not find the id = %u of string\n", id);
1211beacf11bSopenharmony_ci
1212beacf11bSopenharmony_ci  return -1;
1213beacf11bSopenharmony_ci}
1214beacf11bSopenharmony_ci
1215beacf11bSopenharmony_cistatic void usbdev_dfu_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor)
1216beacf11bSopenharmony_ci{
1217beacf11bSopenharmony_ci  usbdev_dfu_get_composite_devdesc(dev);
1218beacf11bSopenharmony_ci
1219beacf11bSopenharmony_ci  /* Interfaces */
1220beacf11bSopenharmony_ci
1221beacf11bSopenharmony_ci  dev->devinfo.ifnobase = ifnobase; /* Offset to Interface-IDs */
1222beacf11bSopenharmony_ci  dev->minor = minor;               /* The minor interface number */
1223beacf11bSopenharmony_ci
1224beacf11bSopenharmony_ci  /* Strings */
1225beacf11bSopenharmony_ci
1226beacf11bSopenharmony_ci  dev->devinfo.strbase = 0;         /* Offset to String Numbers */
1227beacf11bSopenharmony_ci}
1228beacf11bSopenharmony_ci
1229beacf11bSopenharmony_ciint usbdev_dfu_initialize(struct module *mod, int n, void *arg)
1230beacf11bSopenharmony_ci{
1231beacf11bSopenharmony_ci  struct composite_softc *com_s = (struct composite_softc *)arg;
1232beacf11bSopenharmony_ci  struct composite_devdesc_s dev;
1233beacf11bSopenharmony_ci  int ret;
1234beacf11bSopenharmony_ci
1235beacf11bSopenharmony_ci  /* ignore compilation warnings */
1236beacf11bSopenharmony_ci
1237beacf11bSopenharmony_ci  (void)mod;
1238beacf11bSopenharmony_ci  (void)n;
1239beacf11bSopenharmony_ci
1240beacf11bSopenharmony_ci  if (com_s == NULL)
1241beacf11bSopenharmony_ci    {
1242beacf11bSopenharmony_ci      return -1;
1243beacf11bSopenharmony_ci    }
1244beacf11bSopenharmony_ci
1245beacf11bSopenharmony_ci  usbdev_dfu_initialize_sub(&dev, 0, DEV_DFU);
1246beacf11bSopenharmony_ci
1247beacf11bSopenharmony_ci  ret = composite_initialize(com_s, 1, &dev);
1248beacf11bSopenharmony_ci  if (ret < 0)
1249beacf11bSopenharmony_ci    {
1250beacf11bSopenharmony_ci      return -1;
1251beacf11bSopenharmony_ci    }
1252beacf11bSopenharmony_ci
1253beacf11bSopenharmony_ci  PRINTK("** DFU device initialized successfully! **\n");
1254beacf11bSopenharmony_ci  return 0;
1255beacf11bSopenharmony_ci}
1256beacf11bSopenharmony_ci
1257beacf11bSopenharmony_ci#ifdef __cplusplus
1258beacf11bSopenharmony_ci#if __cplusplus
1259beacf11bSopenharmony_ci}
1260beacf11bSopenharmony_ci#endif /* __cplusplus */
1261beacf11bSopenharmony_ci#endif /* __cplusplus */