1 /*******************************************************************************
2  *
3  * Copyright(c) 2015,2016 Intel Corporation.
4  * Copyright(c) 2017 PHYTEC Messtechnik GmbH
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  * * Neither the name of Intel Corporation nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  ******************************************************************************/
33 
34 /**
35  * @brief DFU class driver
36  *
37  * USB DFU device class driver
38  *
39  */
40 
41 #include <zephyr/init.h>
42 #include <zephyr/kernel.h>
43 #include <stdio.h>
44 #include <errno.h>
45 #include <zephyr/drivers/flash.h>
46 #include <zephyr/storage/flash_map.h>
47 #include <zephyr/dfu/mcuboot.h>
48 #include <zephyr/dfu/flash_img.h>
49 #include <zephyr/sys/byteorder.h>
50 #include <zephyr/sys/reboot.h>
51 #include <zephyr/usb/usb_device.h>
52 #include <zephyr/usb/class/usb_dfu.h>
53 #include <usb_descriptor.h>
54 #include <usb_work_q.h>
55 
56 #include <zephyr/logging/log.h>
57 LOG_MODULE_REGISTER(usb_dfu, CONFIG_USB_DEVICE_LOG_LEVEL);
58 
59 #define SLOT0_PARTITION			slot0_partition
60 #define SLOT1_PARTITION			slot1_partition
61 
62 #define FIRMWARE_IMAGE_0_LABEL "image_0"
63 #define FIRMWARE_IMAGE_1_LABEL "image_1"
64 
65 #define USB_DFU_MAX_XFER_SIZE		CONFIG_USB_REQUEST_BUFFER_SIZE
66 
67 #define INTERMITTENT_CHECK_DELAY	50
68 
69 #if defined(CONFIG_USB_DFU_REBOOT)
70 #define DFU_DESC_ATTRIBUTES_MANIF_TOL 0
71 #else
72 #define DFU_DESC_ATTRIBUTES_MANIF_TOL DFU_ATTR_MANIFESTATION_TOLERANT
73 #endif
74 
75 #if defined(CONFIG_USB_DFU_ENABLE_UPLOAD)
76 #define DFU_DESC_ATTRIBUTES_CAN_UPLOAD	 DFU_ATTR_CAN_UPLOAD
77 #else
78 #define DFU_DESC_ATTRIBUTES_CAN_UPLOAD 0
79 #endif
80 
81 #if defined(CONFIG_USB_DFU_WILL_DETACH)
82 #define DFU_DESC_ATTRIBUTES_WILL_DETACH DFU_ATTR_WILL_DETACH
83 #else
84 #define DFU_DESC_ATTRIBUTES_WILL_DETACH 0
85 #endif
86 
87 #define DFU_DESC_ATTRIBUTES		(DFU_ATTR_CAN_DNLOAD | \
88 					 DFU_DESC_ATTRIBUTES_CAN_UPLOAD |\
89 					 DFU_DESC_ATTRIBUTES_MANIF_TOL |\
90 					 DFU_DESC_ATTRIBUTES_WILL_DETACH)
91 
92 static struct k_poll_event dfu_event;
93 static struct k_poll_signal dfu_signal;
94 static struct k_work_delayable dfu_timer_work;
95 
96 static struct k_work dfu_work;
97 
98 struct dfu_worker_data_t {
99 	uint8_t buf[USB_DFU_MAX_XFER_SIZE];
100 	enum dfu_state worker_state;
101 	uint16_t worker_len;
102 };
103 
104 static struct dfu_worker_data_t dfu_data_worker;
105 
106 struct usb_dfu_config {
107 	struct usb_if_descriptor if0;
108 	struct dfu_runtime_descriptor dfu_descr;
109 } __packed;
110 
111 USBD_CLASS_DESCR_DEFINE(primary, 0) struct usb_dfu_config dfu_cfg = {
112 	/* Interface descriptor */
113 	.if0 = {
114 		.bLength = sizeof(struct usb_if_descriptor),
115 		.bDescriptorType = USB_DESC_INTERFACE,
116 		.bInterfaceNumber = 0,
117 		.bAlternateSetting = 0,
118 		.bNumEndpoints = 0,
119 		.bInterfaceClass = USB_BCC_APPLICATION,
120 		.bInterfaceSubClass = DFU_SUBCLASS,
121 		.bInterfaceProtocol = DFU_RT_PROTOCOL,
122 		.iInterface = 0,
123 	},
124 	.dfu_descr = {
125 		.bLength = sizeof(struct dfu_runtime_descriptor),
126 		.bDescriptorType = DFU_FUNC_DESC,
127 		.bmAttributes = DFU_DESC_ATTRIBUTES,
128 		.wDetachTimeOut =
129 			sys_cpu_to_le16(CONFIG_USB_DFU_DETACH_TIMEOUT),
130 		.wTransferSize =
131 			sys_cpu_to_le16(USB_DFU_MAX_XFER_SIZE),
132 		.bcdDFUVersion =
133 			sys_cpu_to_le16(DFU_VERSION),
134 	},
135 };
136 
137 /* dfu mode device descriptor */
138 
139 struct dev_dfu_mode_descriptor {
140 	struct usb_device_descriptor device_descriptor;
141 	struct usb_cfg_descriptor cfg_descr;
142 	struct usb_sec_dfu_config {
143 		struct usb_if_descriptor if0;
144 #if FIXED_PARTITION_EXISTS(SLOT1_PARTITION)
145 		struct usb_if_descriptor if1;
146 #endif
147 		struct dfu_runtime_descriptor dfu_descr;
148 	} __packed sec_dfu_cfg;
149 } __packed;
150 
151 
152 USBD_DEVICE_DESCR_DEFINE(secondary)
153 struct dev_dfu_mode_descriptor dfu_mode_desc = {
154 	/* Device descriptor */
155 	.device_descriptor = {
156 		.bLength = sizeof(struct usb_device_descriptor),
157 		.bDescriptorType = USB_DESC_DEVICE,
158 		.bcdUSB = sys_cpu_to_le16(USB_SRN_2_0),
159 		.bDeviceClass = 0,
160 		.bDeviceSubClass = 0,
161 		.bDeviceProtocol = 0,
162 		.bMaxPacketSize0 = USB_MAX_CTRL_MPS,
163 		.idVendor = sys_cpu_to_le16((uint16_t)CONFIG_USB_DEVICE_VID),
164 		.idProduct =
165 			sys_cpu_to_le16((uint16_t)CONFIG_USB_DEVICE_DFU_PID),
166 		.bcdDevice = sys_cpu_to_le16(USB_BCD_DRN),
167 		.iManufacturer = 1,
168 		.iProduct = 2,
169 		.iSerialNumber = 3,
170 		.bNumConfigurations = 1,
171 	},
172 	/* Configuration descriptor */
173 	.cfg_descr = {
174 		.bLength = sizeof(struct usb_cfg_descriptor),
175 		.bDescriptorType = USB_DESC_CONFIGURATION,
176 		.wTotalLength = 0,
177 		.bNumInterfaces = 1,
178 		.bConfigurationValue = 1,
179 		.iConfiguration = 0,
180 		.bmAttributes = USB_SCD_RESERVED |
181 				COND_CODE_1(CONFIG_USB_SELF_POWERED,
182 					    (USB_SCD_SELF_POWERED), (0)) |
183 				COND_CODE_1(CONFIG_USB_DEVICE_REMOTE_WAKEUP,
184 					    (USB_SCD_REMOTE_WAKEUP), (0)),
185 		.bMaxPower = CONFIG_USB_MAX_POWER,
186 	},
187 	.sec_dfu_cfg = {
188 		/* Interface descriptor */
189 		.if0 = {
190 			.bLength = sizeof(struct usb_if_descriptor),
191 			.bDescriptorType = USB_DESC_INTERFACE,
192 			.bInterfaceNumber = 0,
193 			.bAlternateSetting = 0,
194 			.bNumEndpoints = 0,
195 			.bInterfaceClass = USB_BCC_APPLICATION,
196 			.bInterfaceSubClass = DFU_SUBCLASS,
197 			.bInterfaceProtocol = DFU_MODE_PROTOCOL,
198 			.iInterface = 4,
199 		},
200 #if FIXED_PARTITION_EXISTS(SLOT1_PARTITION)
201 		.if1 = {
202 			.bLength = sizeof(struct usb_if_descriptor),
203 			.bDescriptorType = USB_DESC_INTERFACE,
204 			.bInterfaceNumber = 0,
205 			.bAlternateSetting = 1,
206 			.bNumEndpoints = 0,
207 			.bInterfaceClass = USB_BCC_APPLICATION,
208 			.bInterfaceSubClass = DFU_SUBCLASS,
209 			.bInterfaceProtocol = DFU_MODE_PROTOCOL,
210 			.iInterface = 5,
211 		},
212 #endif
213 		.dfu_descr = {
214 			.bLength = sizeof(struct dfu_runtime_descriptor),
215 			.bDescriptorType = DFU_FUNC_DESC,
216 			.bmAttributes = DFU_DESC_ATTRIBUTES,
217 			.wDetachTimeOut =
218 				sys_cpu_to_le16(CONFIG_USB_DFU_DETACH_TIMEOUT),
219 			.wTransferSize =
220 				sys_cpu_to_le16(USB_DFU_MAX_XFER_SIZE),
221 			.bcdDFUVersion =
222 				sys_cpu_to_le16(DFU_VERSION),
223 		},
224 	},
225 };
226 
227 struct usb_string_desription {
228 	struct usb_string_descriptor lang_descr;
229 	struct usb_mfr_descriptor {
230 		uint8_t bLength;
231 		uint8_t bDescriptorType;
232 		uint8_t bString[USB_BSTRING_LENGTH(
233 				CONFIG_USB_DEVICE_MANUFACTURER)];
234 	} __packed utf16le_mfr;
235 
236 	struct usb_product_descriptor {
237 		uint8_t bLength;
238 		uint8_t bDescriptorType;
239 		uint8_t bString[USB_BSTRING_LENGTH(CONFIG_USB_DEVICE_PRODUCT)];
240 	} __packed utf16le_product;
241 
242 	struct usb_sn_descriptor {
243 		uint8_t bLength;
244 		uint8_t bDescriptorType;
245 		uint8_t bString[USB_BSTRING_LENGTH(CONFIG_USB_DEVICE_SN)];
246 	} __packed utf16le_sn;
247 
248 	struct image_0_descriptor {
249 		uint8_t bLength;
250 		uint8_t bDescriptorType;
251 		uint8_t bString[USB_BSTRING_LENGTH(FIRMWARE_IMAGE_0_LABEL)];
252 	} __packed utf16le_image0;
253 
254 #if FIXED_PARTITION_EXISTS(SLOT1_PARTITION)
255 	struct image_1_descriptor {
256 		uint8_t bLength;
257 		uint8_t bDescriptorType;
258 		uint8_t bString[USB_BSTRING_LENGTH(FIRMWARE_IMAGE_1_LABEL)];
259 	} __packed utf16le_image1;
260 #endif
261 } __packed;
262 
263 USBD_STRING_DESCR_DEFINE(secondary)
264 struct usb_string_desription string_descr = {
265 	.lang_descr = {
266 		.bLength = sizeof(struct usb_string_descriptor),
267 		.bDescriptorType = USB_DESC_STRING,
268 		.bString = sys_cpu_to_le16(0x0409),
269 	},
270 	/* Manufacturer String Descriptor */
271 	.utf16le_mfr = {
272 		.bLength = USB_STRING_DESCRIPTOR_LENGTH(
273 				CONFIG_USB_DEVICE_MANUFACTURER),
274 		.bDescriptorType = USB_DESC_STRING,
275 		.bString = CONFIG_USB_DEVICE_MANUFACTURER,
276 	},
277 	/* Product String Descriptor */
278 	.utf16le_product = {
279 		.bLength = USB_STRING_DESCRIPTOR_LENGTH(
280 				CONFIG_USB_DEVICE_PRODUCT),
281 		.bDescriptorType = USB_DESC_STRING,
282 		.bString = CONFIG_USB_DEVICE_PRODUCT,
283 	},
284 	/* Serial Number String Descriptor */
285 	.utf16le_sn = {
286 		.bLength = USB_STRING_DESCRIPTOR_LENGTH(CONFIG_USB_DEVICE_SN),
287 		.bDescriptorType = USB_DESC_STRING,
288 		.bString = CONFIG_USB_DEVICE_SN,
289 	},
290 	/* Image 0 String Descriptor */
291 	.utf16le_image0 = {
292 		.bLength = USB_STRING_DESCRIPTOR_LENGTH(
293 				FIRMWARE_IMAGE_0_LABEL),
294 		.bDescriptorType = USB_DESC_STRING,
295 		.bString = FIRMWARE_IMAGE_0_LABEL,
296 	},
297 #if FIXED_PARTITION_EXISTS(SLOT1_PARTITION)
298 	/* Image 1 String Descriptor */
299 	.utf16le_image1 = {
300 		.bLength = USB_STRING_DESCRIPTOR_LENGTH(
301 				FIRMWARE_IMAGE_1_LABEL),
302 		.bDescriptorType = USB_DESC_STRING,
303 		.bString = FIRMWARE_IMAGE_1_LABEL,
304 	},
305 #endif
306 };
307 
308 /* This element marks the end of the entire descriptor. */
309 USBD_TERM_DESCR_DEFINE(secondary) struct usb_desc_header term_descr = {
310 	.bLength = 0,
311 	.bDescriptorType = 0,
312 };
313 
314 static struct usb_cfg_data dfu_config;
315 
316 /* Device data structure */
317 struct dfu_data_t {
318 	uint8_t flash_area_id;
319 	uint32_t flash_upload_size;
320 	/* Number of bytes sent during upload */
321 	uint32_t bytes_sent;
322 	uint32_t alt_setting;              /* DFU alternate setting */
323 	struct flash_img_context ctx;
324 	enum dfu_state state;              /* State of the DFU device */
325 	enum dfu_status status;            /* Status of the DFU device */
326 	uint16_t block_nr;                 /* DFU block number */
327 	uint16_t bwPollTimeout;
328 };
329 
330 #if FIXED_PARTITION_EXISTS(SLOT1_PARTITION)
331 	#define DOWNLOAD_FLASH_AREA_ID FIXED_PARTITION_ID(SLOT1_PARTITION)
332 #else
333 	#define DOWNLOAD_FLASH_AREA_ID FIXED_PARTITION_ID(SLOT0_PARTITION)
334 #endif
335 
336 
337 static struct dfu_data_t dfu_data = {
338 	.state = appIDLE,
339 	.status = statusOK,
340 	.flash_area_id = DOWNLOAD_FLASH_AREA_ID,
341 	.alt_setting = 0,
342 	.bwPollTimeout = CONFIG_USB_DFU_DEFAULT_POLLTIMEOUT,
343 };
344 
345 /**
346  * @brief Helper function to check if in DFU app state.
347  *
348  * @return  true if app state, false otherwise.
349  */
dfu_check_app_state(void)350 static bool dfu_check_app_state(void)
351 {
352 	if (dfu_data.state == appIDLE ||
353 	    dfu_data.state == appDETACH) {
354 		dfu_data.state = appIDLE;
355 		return true;
356 	}
357 
358 	return false;
359 }
360 
361 /**
362  * @brief Helper function to reset DFU internal counters.
363  */
dfu_reset_counters(void)364 static void dfu_reset_counters(void)
365 {
366 	dfu_data.bytes_sent = 0U;
367 	dfu_data.block_nr = 0U;
368 	if (flash_img_init(&dfu_data.ctx)) {
369 		LOG_ERR("flash img init error");
370 		dfu_data.state = dfuERROR;
371 		dfu_data.status = errUNKNOWN;
372 	}
373 }
374 
dfu_flash_write(uint8_t * data,size_t len)375 static void dfu_flash_write(uint8_t *data, size_t len)
376 {
377 	bool flush = false;
378 
379 	if (!len) {
380 		/* Download completed */
381 		flush = true;
382 	}
383 
384 	if (flash_img_buffered_write(&dfu_data.ctx, data, len, flush)) {
385 		LOG_ERR("flash write error");
386 		dfu_data.state = dfuERROR;
387 		dfu_data.status = errWRITE;
388 	} else if (!len) {
389 		const bool should_confirm = IS_ENABLED(CONFIG_USB_DFU_PERMANENT_DOWNLOAD);
390 
391 		LOG_DBG("flash write done");
392 		dfu_data.state = dfuMANIFEST_SYNC;
393 		dfu_reset_counters();
394 
395 		LOG_DBG("Should confirm: %d", should_confirm);
396 		if (boot_request_upgrade(should_confirm)) {
397 			dfu_data.state = dfuERROR;
398 			dfu_data.status = errWRITE;
399 		}
400 
401 		k_poll_signal_raise(&dfu_signal, 0);
402 	} else {
403 		dfu_data.state = dfuDNLOAD_IDLE;
404 	}
405 
406 	LOG_DBG("bytes written 0x%x", flash_img_bytes_written(&dfu_data.ctx));
407 }
408 
dfu_enter_idle(void)409 static void dfu_enter_idle(void)
410 {
411 	dfu_data.state = dfuIDLE;
412 
413 	/* Set the DFU mode descriptors to be used after reset */
414 	dfu_config.usb_device_description = (uint8_t *) &dfu_mode_desc;
415 	if (usb_set_config(dfu_config.usb_device_description)) {
416 		LOG_ERR("usb_set_config failed during DFU idle entry");
417 	}
418 }
419 
dfu_timer_work_handler(struct k_work * item)420 static void dfu_timer_work_handler(struct k_work *item)
421 {
422 	ARG_UNUSED(item);
423 
424 	if (dfu_data.state == appDETACH) {
425 		if (IS_ENABLED(CONFIG_USB_DFU_WILL_DETACH)) {
426 			if (usb_dc_detach()) {
427 				LOG_ERR("usb_dc_detach failed");
428 			}
429 			dfu_enter_idle();
430 
431 			/* Wait 1 SOF period to ensure the host notices the deconnection. */
432 			k_sleep(K_MSEC(1));
433 
434 			if (usb_dc_attach()) {
435 				LOG_ERR("usb_dc_attach failed");
436 			}
437 		} else {
438 			dfu_data.state = appIDLE;
439 		}
440 	}
441 }
442 
443 #ifdef CONFIG_USB_DFU_REBOOT
444 static struct k_work_delayable reboot_work;
445 
reboot_work_handler(struct k_work * item)446 static void reboot_work_handler(struct k_work *item)
447 {
448 	ARG_UNUSED(item);
449 
450 	sys_reboot(SYS_REBOOT_WARM);
451 }
452 
reboot_schedule(void)453 static void reboot_schedule(void)
454 {
455 	LOG_DBG("Scheduling reboot in 500ms");
456 
457 	/*
458 	 * Reboot with a delay,
459 	 * so there is some time to send the status to the host
460 	 */
461 	k_work_schedule_for_queue(&USB_WORK_Q, &reboot_work, K_MSEC(500));
462 }
463 #endif
464 
dfu_class_handle_to_host(struct usb_setup_packet * setup,int32_t * data_len,uint8_t ** data)465 static int dfu_class_handle_to_host(struct usb_setup_packet *setup,
466 				    int32_t *data_len, uint8_t **data)
467 {
468 	uint32_t bytes_left;
469 	uint32_t len;
470 	int ret;
471 
472 	switch (setup->bRequest) {
473 	case DFU_GETSTATUS:
474 		LOG_DBG("DFU_GETSTATUS: status %d, state %d",
475 			dfu_data.status, dfu_data.state);
476 
477 		if (dfu_data.state == dfuMANIFEST_SYNC) {
478 
479 #if defined(CONFIG_USB_DFU_REBOOT)
480 			dfu_data.state = dfuMANIFEST_WAIT_RST;
481 			reboot_schedule();
482 #else
483 			dfu_data.state = dfuIDLE;
484 #endif
485 		}
486 
487 		/* bStatus */
488 		(*data)[0] = dfu_data.status;
489 		/* bwPollTimeout */
490 		sys_put_le16(dfu_data.bwPollTimeout, &(*data)[1]);
491 		(*data)[3] = 0U;
492 		/* bState */
493 		(*data)[4] = dfu_data.state;
494 		/* iString */
495 		(*data)[5] = 0U;
496 		*data_len = 6;
497 		break;
498 
499 	case DFU_GETSTATE:
500 		LOG_DBG("DFU_GETSTATE");
501 		(*data)[0] = dfu_data.state;
502 		*data_len = 1;
503 		break;
504 
505 	case DFU_UPLOAD:
506 		LOG_DBG("DFU_UPLOAD block %d, len %d, state %d",
507 			setup->wValue, setup->wLength, dfu_data.state);
508 
509 		if (!IS_ENABLED(CONFIG_USB_DFU_ENABLE_UPLOAD)) {
510 			LOG_WRN("Firmware uploading is not enabled");
511 			dfu_data.status = errSTALLEDPKT;
512 			dfu_data.state = dfuERROR;
513 			return -ENOTSUP;
514 		}
515 
516 		if (dfu_check_app_state()) {
517 			return -EINVAL;
518 		}
519 
520 		switch (dfu_data.state) {
521 		case dfuIDLE:
522 			dfu_reset_counters();
523 			LOG_DBG("DFU_UPLOAD start");
524 			__fallthrough;
525 		case dfuUPLOAD_IDLE:
526 			if (!setup->wLength ||
527 			    dfu_data.block_nr != setup->wValue) {
528 				LOG_ERR("DFU_UPLOAD block %d, expected %d, "
529 					"len %d", setup->wValue,
530 					dfu_data.block_nr, setup->wLength);
531 				dfu_data.state = dfuERROR;
532 				dfu_data.status = errUNKNOWN;
533 				return -EINVAL;
534 			}
535 
536 			/* Upload in progress */
537 			bytes_left = dfu_data.flash_upload_size -
538 				     dfu_data.bytes_sent;
539 			if (bytes_left < setup->wLength) {
540 				len = bytes_left;
541 			} else {
542 				len = setup->wLength;
543 			}
544 
545 			if (len > USB_DFU_MAX_XFER_SIZE) {
546 				/*
547 				 * The host could requests more data as stated
548 				 * in wTransferSize. Limit upload length to the
549 				 * size of the request-buffer.
550 				 */
551 				len = USB_DFU_MAX_XFER_SIZE;
552 			}
553 
554 			if (len) {
555 				const struct flash_area *fa;
556 
557 				ret = flash_area_open(dfu_data.flash_area_id,
558 						      &fa);
559 				if (ret) {
560 					dfu_data.state = dfuERROR;
561 					dfu_data.status = errFILE;
562 					return -EINVAL;
563 				}
564 				ret = flash_area_read(fa, dfu_data.bytes_sent,
565 						      *data, len);
566 				flash_area_close(fa);
567 				if (ret) {
568 					dfu_data.state = dfuERROR;
569 					dfu_data.status = errFILE;
570 					return -EINVAL;
571 				}
572 			}
573 			*data_len = len;
574 
575 			dfu_data.bytes_sent += len;
576 			dfu_data.block_nr++;
577 
578 			if (dfu_data.bytes_sent == dfu_data.flash_upload_size &&
579 			    len < setup->wLength) {
580 				/* Upload completed when a
581 				 * short packet is received
582 				 */
583 				*data_len = 0;
584 				dfu_data.state = dfuIDLE;
585 			} else {
586 				dfu_data.state = dfuUPLOAD_IDLE;
587 			}
588 
589 			break;
590 		default:
591 			LOG_ERR("DFU_UPLOAD wrong state %d", dfu_data.state);
592 			dfu_data.state = dfuERROR;
593 			dfu_data.status = errUNKNOWN;
594 			dfu_reset_counters();
595 			return -EINVAL;
596 		}
597 		break;
598 
599 	default:
600 		LOG_DBG("Unsupported bmRequestType 0x%02x bRequest 0x%02x",
601 			setup->bmRequestType, setup->bRequest);
602 		return -EINVAL;
603 	}
604 
605 	return 0;
606 }
607 
dfu_class_handle_to_device(struct usb_setup_packet * setup,int32_t * data_len,uint8_t ** data)608 static int dfu_class_handle_to_device(struct usb_setup_packet *setup,
609 				      int32_t *data_len, uint8_t **data)
610 {
611 	uint16_t timeout;
612 
613 	switch (setup->bRequest) {
614 	case DFU_ABORT:
615 		LOG_DBG("DFU_ABORT");
616 
617 		if (dfu_check_app_state()) {
618 			return -EINVAL;
619 		}
620 
621 		dfu_reset_counters();
622 		dfu_data.state = dfuIDLE;
623 		dfu_data.status = statusOK;
624 		break;
625 
626 	case DFU_CLRSTATUS:
627 		LOG_DBG("DFU_CLRSTATUS");
628 
629 		if (dfu_check_app_state()) {
630 			return -EINVAL;
631 		}
632 
633 		dfu_data.state = dfuIDLE;
634 		dfu_data.status = statusOK;
635 		break;
636 
637 	case DFU_DNLOAD:
638 		LOG_DBG("DFU_DNLOAD block %d, len %d, state %d",
639 			setup->wValue, setup->wLength, dfu_data.state);
640 
641 		if (dfu_check_app_state()) {
642 			return -EINVAL;
643 		}
644 
645 		switch (dfu_data.state) {
646 		case dfuIDLE:
647 			LOG_DBG("DFU_DNLOAD start");
648 			dfu_reset_counters();
649 			k_poll_signal_reset(&dfu_signal);
650 
651 			if (dfu_data.flash_area_id != DOWNLOAD_FLASH_AREA_ID) {
652 				dfu_data.status = errWRITE;
653 				dfu_data.state = dfuERROR;
654 				LOG_ERR("This area can not be overwritten");
655 				break;
656 			}
657 
658 			dfu_data.state = dfuDNBUSY;
659 			dfu_data_worker.worker_state = dfuIDLE;
660 			dfu_data_worker.worker_len  = setup->wLength;
661 			memcpy(dfu_data_worker.buf, *data, setup->wLength);
662 			k_work_submit_to_queue(&USB_WORK_Q, &dfu_work);
663 			break;
664 		case dfuDNLOAD_IDLE:
665 			dfu_data.state = dfuDNBUSY;
666 			dfu_data_worker.worker_state = dfuDNLOAD_IDLE;
667 			dfu_data_worker.worker_len  = setup->wLength;
668 
669 			memcpy(dfu_data_worker.buf, *data, setup->wLength);
670 			k_work_submit_to_queue(&USB_WORK_Q, &dfu_work);
671 			break;
672 		default:
673 			LOG_ERR("DFU_DNLOAD wrong state %d", dfu_data.state);
674 			dfu_data.state = dfuERROR;
675 			dfu_data.status = errUNKNOWN;
676 			dfu_reset_counters();
677 			return -EINVAL;
678 		}
679 		break;
680 	case DFU_DETACH:
681 		LOG_DBG("DFU_DETACH timeout %d, state %d",
682 			setup->wValue, dfu_data.state);
683 
684 		if (dfu_data.state != appIDLE) {
685 			dfu_data.state = appIDLE;
686 			return -EINVAL;
687 		}
688 
689 		/* Move to appDETACH state */
690 		dfu_data.state = appDETACH;
691 		if (IS_ENABLED(CONFIG_USB_DFU_WILL_DETACH)) {
692 			/* Note: Detach should happen once the status stage
693 			 * finishes but the USB device stack does not expose
694 			 * such callback. Wait fixed time (ignore wValue) to
695 			 * let device finish control transfer status stage.
696 			 */
697 			timeout = CONFIG_USB_DFU_DETACH_TIMEOUT;
698 		} else {
699 			/* Begin detach timeout timer */
700 			timeout = MIN(setup->wValue, CONFIG_USB_DFU_DETACH_TIMEOUT);
701 		}
702 		k_work_reschedule_for_queue(&USB_WORK_Q, &dfu_timer_work, K_MSEC(timeout));
703 		break;
704 	default:
705 		LOG_DBG("Unsupported bmRequestType 0x%02x bRequest 0x%02x",
706 			setup->bmRequestType, setup->bRequest);
707 		return -EINVAL;
708 	}
709 
710 	return 0;
711 }
712 
713 /**
714  * @brief Handler called for DFU Class requests not handled by the USB stack.
715  *
716  * @param setup     Information about the request to execute.
717  * @param len       Size of the buffer.
718  * @param data      Buffer containing the request result.
719  *
720  * @return  0 on success, negative errno code on fail.
721  */
dfu_class_handle_req(struct usb_setup_packet * setup,int32_t * data_len,uint8_t ** data)722 static int dfu_class_handle_req(struct usb_setup_packet *setup,
723 				int32_t *data_len, uint8_t **data)
724 {
725 	if (usb_reqtype_is_to_host(setup)) {
726 		return dfu_class_handle_to_host(setup, data_len, data);
727 	} else {
728 		return dfu_class_handle_to_device(setup, data_len, data);
729 	}
730 }
731 
732 
733 /**
734  * @brief Callback used to know the USB connection status
735  *
736  * @param status USB device status code.
737  *
738  * @return  N/A.
739  */
dfu_status_cb(struct usb_cfg_data * cfg,enum usb_dc_status_code status,const uint8_t * param)740 static void dfu_status_cb(struct usb_cfg_data *cfg,
741 			  enum usb_dc_status_code status,
742 			  const uint8_t *param)
743 {
744 	ARG_UNUSED(param);
745 	ARG_UNUSED(cfg);
746 
747 	/* Check the USB status and do needed action if required */
748 	switch (status) {
749 	case USB_DC_ERROR:
750 		LOG_DBG("USB device error");
751 		break;
752 	case USB_DC_RESET:
753 		LOG_DBG("USB device reset detected, state %d", dfu_data.state);
754 		if (!IS_ENABLED(CONFIG_USB_DFU_WILL_DETACH)) {
755 			/* Stop the appDETACH timeout timer */
756 			k_work_cancel_delayable(&dfu_timer_work);
757 			if (dfu_data.state == appDETACH) {
758 				dfu_enter_idle();
759 			}
760 		}
761 		break;
762 	case USB_DC_CONNECTED:
763 		LOG_DBG("USB device connected");
764 		break;
765 	case USB_DC_CONFIGURED:
766 		LOG_DBG("USB device configured");
767 		break;
768 	case USB_DC_DISCONNECTED:
769 		LOG_DBG("USB device disconnected");
770 		break;
771 	case USB_DC_SUSPEND:
772 		LOG_DBG("USB device suspended");
773 		break;
774 	case USB_DC_RESUME:
775 		LOG_DBG("USB device resumed");
776 		break;
777 	case USB_DC_SOF:
778 		break;
779 	case USB_DC_UNKNOWN:
780 	default:
781 		LOG_DBG("USB unknown state");
782 		break;
783 	}
784 }
785 
786 /**
787  * @brief Custom handler for standard ('chapter 9') requests
788  *        in order to catch the SET_INTERFACE request and
789  *        extract the interface alternate setting
790  *
791  * @param setup    Information about the request to execute.
792  * @param len       Size of the buffer.
793  * @param data      Buffer containing the request result.
794  *
795  * @return          -ENOTSUP so that the stack can process control request.
796  */
797 
dfu_custom_handle_req(struct usb_setup_packet * setup,int32_t * data_len,uint8_t ** data)798 static int dfu_custom_handle_req(struct usb_setup_packet *setup,
799 				 int32_t *data_len, uint8_t **data)
800 {
801 	ARG_UNUSED(data);
802 
803 	if (usb_reqtype_is_to_host(setup) ||
804 	    setup->RequestType.recipient != USB_REQTYPE_RECIPIENT_INTERFACE) {
805 		return -ENOTSUP;
806 	}
807 
808 	if (setup->bRequest == USB_SREQ_SET_INTERFACE) {
809 		LOG_DBG("DFU alternate setting %d", setup->wValue);
810 
811 		const struct flash_area *fa;
812 
813 		switch (setup->wValue) {
814 		case 0:
815 			dfu_data.flash_area_id =
816 			    FIXED_PARTITION_ID(SLOT0_PARTITION);
817 			break;
818 #if FIXED_PARTITION_EXISTS(SLOT1_PARTITION)
819 		case 1:
820 			dfu_data.flash_area_id = DOWNLOAD_FLASH_AREA_ID;
821 			break;
822 #endif
823 		default:
824 			LOG_WRN("Invalid DFU alternate setting");
825 			return -ENOTSUP;
826 		}
827 
828 		if (flash_area_open(dfu_data.flash_area_id, &fa)) {
829 			return -EIO;
830 		}
831 
832 		dfu_data.flash_upload_size = fa->fa_size;
833 		flash_area_close(fa);
834 		dfu_data.alt_setting = setup->wValue;
835 	}
836 
837 	/* Never handled by us */
838 	return -EINVAL;
839 }
840 
dfu_interface_config(struct usb_desc_header * head,uint8_t bInterfaceNumber)841 static void dfu_interface_config(struct usb_desc_header *head,
842 				 uint8_t bInterfaceNumber)
843 {
844 	ARG_UNUSED(head);
845 
846 	dfu_cfg.if0.bInterfaceNumber = bInterfaceNumber;
847 }
848 
849 /* Configuration of the DFU Device send to the USB Driver */
850 USBD_DEFINE_CFG_DATA(dfu_config) = {
851 	.usb_device_description = NULL,
852 	.interface_config = dfu_interface_config,
853 	.interface_descriptor = &dfu_cfg.if0,
854 	.cb_usb_status = dfu_status_cb,
855 	.interface = {
856 		.class_handler = dfu_class_handle_req,
857 		.custom_handler = dfu_custom_handle_req,
858 	},
859 	.num_endpoints = 0,
860 };
861 
862 /*
863  * Dummy configuration, this is necessary to configure DFU mode descriptor
864  * which is an alternative (secondary) device descriptor.
865  */
866 USBD_DEFINE_CFG_DATA(dfu_mode_config) = {
867 	.usb_device_description = NULL,
868 	.interface_config = NULL,
869 	.interface_descriptor = &dfu_mode_desc.sec_dfu_cfg.if0,
870 	.cb_usb_status = dfu_status_cb,
871 	.interface = {
872 		.class_handler = dfu_class_handle_req,
873 		.custom_handler = dfu_custom_handle_req,
874 	},
875 	.num_endpoints = 0,
876 };
877 
dfu_work_handler(struct k_work * item)878 static void dfu_work_handler(struct k_work *item)
879 {
880 	ARG_UNUSED(item);
881 
882 	switch (dfu_data_worker.worker_state) {
883 	case dfuIDLE:
884 /*
885  * If progressive erase is enabled, then erase take place while
886  * image collection, so not erase whole bank at DFU beginning
887  */
888 #ifndef CONFIG_IMG_ERASE_PROGRESSIVELY
889 		if (boot_erase_img_bank(DOWNLOAD_FLASH_AREA_ID)) {
890 			dfu_data.state = dfuERROR;
891 			dfu_data.status = errERASE;
892 			break;
893 		}
894 #endif
895 	case dfuDNLOAD_IDLE:
896 		dfu_flash_write(dfu_data_worker.buf,
897 				dfu_data_worker.worker_len);
898 		break;
899 	default:
900 		LOG_ERR("OUT of state machine");
901 		break;
902 	}
903 }
904 
usb_dfu_init(void)905 static int usb_dfu_init(void)
906 {
907 	const struct flash_area *fa;
908 
909 
910 	k_work_init(&dfu_work, dfu_work_handler);
911 	k_poll_signal_init(&dfu_signal);
912 	k_work_init_delayable(&dfu_timer_work, dfu_timer_work_handler);
913 
914 #ifdef CONFIG_USB_DFU_REBOOT
915 	k_work_init_delayable(&reboot_work, reboot_work_handler);
916 #endif
917 
918 	if (flash_area_open(dfu_data.flash_area_id, &fa)) {
919 		return -EIO;
920 	}
921 
922 	dfu_data.flash_upload_size = fa->fa_size;
923 	flash_area_close(fa);
924 
925 	return 0;
926 }
927 
928 /**
929  * @brief Function to check if DFU is started.
930  *
931  * @return  true if DNBUSY/DNLOAD_IDLE, false otherwise.
932  */
is_dfu_started(void)933 static bool is_dfu_started(void)
934 {
935 	if ((dfu_data.state == dfuDNBUSY) ||
936 	    (dfu_data.state == dfuDNLOAD_IDLE)) {
937 		return true;
938 	}
939 
940 	return false;
941 }
942 
943 /**
944  * @brief Function to check and wait while the USB DFU is in progress.
945  *
946  * @return  N/A
947  */
wait_for_usb_dfu(k_timeout_t delay)948 void wait_for_usb_dfu(k_timeout_t delay)
949 {
950 	k_timepoint_t end = sys_timepoint_calc(delay);
951 
952 	/* Wait for a prescribed duration of time. If DFU hasn't started within
953 	 * that time, stop waiting and proceed further.
954 	 */
955 	while (!sys_timepoint_expired(end)) {
956 		if (is_dfu_started()) {
957 			k_poll_event_init(&dfu_event, K_POLL_TYPE_SIGNAL,
958 				K_POLL_MODE_NOTIFY_ONLY, &dfu_signal);
959 
960 			/* Wait till DFU is complete */
961 			if (k_poll(&dfu_event, 1, K_FOREVER) != 0) {
962 				LOG_DBG("USB DFU Error");
963 			}
964 
965 			LOG_INF("USB DFU Completed");
966 			break;
967 		}
968 
969 		k_msleep(INTERMITTENT_CHECK_DELAY);
970 	}
971 }
972 
973 SYS_INIT(usb_dfu_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
974