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 <init.h>
42 #include <kernel.h>
43 #include <stdio.h>
44 #include <errno.h>
45 #include <drivers/flash.h>
46 #include <storage/flash_map.h>
47 #include <dfu/mcuboot.h>
48 #include <dfu/flash_img.h>
49 #include <sys/byteorder.h>
50 #include <usb/usb_device.h>
51 #include <usb/class/usb_dfu.h>
52 #include <usb_descriptor.h>
53 #include <usb_work_q.h>
54 
55 #define LOG_LEVEL CONFIG_USB_DEVICE_LOG_LEVEL
56 #include <logging/log.h>
57 LOG_MODULE_REGISTER(usb_dfu);
58 
59 #define USB_DFU_MAX_XFER_SIZE		CONFIG_USB_REQUEST_BUFFER_SIZE
60 
61 #define FIRMWARE_IMAGE_0_LABEL FLASH_AREA_LABEL_STR(image_0)
62 #if FLASH_AREA_LABEL_EXISTS(image_1)
63 #define FIRMWARE_IMAGE_1_LABEL FLASH_AREA_LABEL_STR(image_1)
64 #endif
65 
66 #define INTERMITTENT_CHECK_DELAY	50
67 
68 static struct k_poll_event dfu_event;
69 static struct k_poll_signal dfu_signal;
70 static struct k_timer dfu_timer;
71 
72 static struct k_work dfu_work;
73 
74 struct dfu_worker_data_t {
75 	uint8_t buf[USB_DFU_MAX_XFER_SIZE];
76 	enum dfu_state worker_state;
77 	uint16_t worker_len;
78 };
79 
80 static struct dfu_worker_data_t dfu_data_worker;
81 
82 struct usb_dfu_config {
83 	struct usb_if_descriptor if0;
84 	struct dfu_runtime_descriptor dfu_descr;
85 } __packed;
86 
87 USBD_CLASS_DESCR_DEFINE(primary, 0) struct usb_dfu_config dfu_cfg = {
88 	/* Interface descriptor */
89 	.if0 = {
90 		.bLength = sizeof(struct usb_if_descriptor),
91 		.bDescriptorType = USB_DESC_INTERFACE,
92 		.bInterfaceNumber = 0,
93 		.bAlternateSetting = 0,
94 		.bNumEndpoints = 0,
95 		.bInterfaceClass = USB_BCC_APPLICATION,
96 		.bInterfaceSubClass = DFU_SUBCLASS,
97 		.bInterfaceProtocol = DFU_RT_PROTOCOL,
98 		.iInterface = 0,
99 	},
100 	.dfu_descr = {
101 		.bLength = sizeof(struct dfu_runtime_descriptor),
102 		.bDescriptorType = DFU_FUNC_DESC,
103 		.bmAttributes = DFU_ATTR_CAN_DNLOAD |
104 				DFU_ATTR_CAN_UPLOAD |
105 				DFU_ATTR_MANIFESTATION_TOLERANT,
106 		.wDetachTimeOut =
107 			sys_cpu_to_le16(CONFIG_USB_DFU_DETACH_TIMEOUT),
108 		.wTransferSize =
109 			sys_cpu_to_le16(USB_DFU_MAX_XFER_SIZE),
110 		.bcdDFUVersion =
111 			sys_cpu_to_le16(DFU_VERSION),
112 	},
113 };
114 
115 /* dfu mode device descriptor */
116 
117 struct dev_dfu_mode_descriptor {
118 	struct usb_device_descriptor device_descriptor;
119 	struct usb_cfg_descriptor cfg_descr;
120 	struct usb_sec_dfu_config {
121 		struct usb_if_descriptor if0;
122 #if FLASH_AREA_LABEL_EXISTS(image_1)
123 		struct usb_if_descriptor if1;
124 #endif
125 		struct dfu_runtime_descriptor dfu_descr;
126 	} __packed sec_dfu_cfg;
127 } __packed;
128 
129 
130 USBD_DEVICE_DESCR_DEFINE(secondary)
131 struct dev_dfu_mode_descriptor dfu_mode_desc = {
132 	/* Device descriptor */
133 	.device_descriptor = {
134 		.bLength = sizeof(struct usb_device_descriptor),
135 		.bDescriptorType = USB_DESC_DEVICE,
136 		.bcdUSB = sys_cpu_to_le16(USB_SRN_2_0),
137 		.bDeviceClass = 0,
138 		.bDeviceSubClass = 0,
139 		.bDeviceProtocol = 0,
140 		.bMaxPacketSize0 = USB_MAX_CTRL_MPS,
141 		.idVendor = sys_cpu_to_le16((uint16_t)CONFIG_USB_DEVICE_VID),
142 		.idProduct =
143 			sys_cpu_to_le16((uint16_t)CONFIG_USB_DEVICE_DFU_PID),
144 		.bcdDevice = sys_cpu_to_le16(USB_BCD_DRN),
145 		.iManufacturer = 1,
146 		.iProduct = 2,
147 		.iSerialNumber = 3,
148 		.bNumConfigurations = 1,
149 	},
150 	/* Configuration descriptor */
151 	.cfg_descr = {
152 		.bLength = sizeof(struct usb_cfg_descriptor),
153 		.bDescriptorType = USB_DESC_CONFIGURATION,
154 		.wTotalLength = 0,
155 		.bNumInterfaces = 1,
156 		.bConfigurationValue = 1,
157 		.iConfiguration = 0,
158 		.bmAttributes = USB_SCD_ATTRIBUTES,
159 		.bMaxPower = CONFIG_USB_MAX_POWER,
160 	},
161 	.sec_dfu_cfg = {
162 		/* Interface descriptor */
163 		.if0 = {
164 			.bLength = sizeof(struct usb_if_descriptor),
165 			.bDescriptorType = USB_DESC_INTERFACE,
166 			.bInterfaceNumber = 0,
167 			.bAlternateSetting = 0,
168 			.bNumEndpoints = 0,
169 			.bInterfaceClass = USB_BCC_APPLICATION,
170 			.bInterfaceSubClass = DFU_SUBCLASS,
171 			.bInterfaceProtocol = DFU_MODE_PROTOCOL,
172 			.iInterface = 4,
173 		},
174 #if FLASH_AREA_LABEL_EXISTS(image_1)
175 		.if1 = {
176 			.bLength = sizeof(struct usb_if_descriptor),
177 			.bDescriptorType = USB_DESC_INTERFACE,
178 			.bInterfaceNumber = 0,
179 			.bAlternateSetting = 1,
180 			.bNumEndpoints = 0,
181 			.bInterfaceClass = USB_BCC_APPLICATION,
182 			.bInterfaceSubClass = DFU_SUBCLASS,
183 			.bInterfaceProtocol = DFU_MODE_PROTOCOL,
184 			.iInterface = 5,
185 		},
186 #endif
187 		.dfu_descr = {
188 			.bLength = sizeof(struct dfu_runtime_descriptor),
189 			.bDescriptorType = DFU_FUNC_DESC,
190 			.bmAttributes = DFU_ATTR_CAN_DNLOAD |
191 					DFU_ATTR_CAN_UPLOAD |
192 					DFU_ATTR_MANIFESTATION_TOLERANT,
193 			.wDetachTimeOut =
194 				sys_cpu_to_le16(CONFIG_USB_DFU_DETACH_TIMEOUT),
195 			.wTransferSize =
196 				sys_cpu_to_le16(USB_DFU_MAX_XFER_SIZE),
197 			.bcdDFUVersion =
198 				sys_cpu_to_le16(DFU_VERSION),
199 		},
200 	},
201 };
202 
203 struct usb_string_desription {
204 	struct usb_string_descriptor lang_descr;
205 	struct usb_mfr_descriptor {
206 		uint8_t bLength;
207 		uint8_t bDescriptorType;
208 		uint8_t bString[USB_BSTRING_LENGTH(
209 				CONFIG_USB_DEVICE_MANUFACTURER)];
210 	} __packed utf16le_mfr;
211 
212 	struct usb_product_descriptor {
213 		uint8_t bLength;
214 		uint8_t bDescriptorType;
215 		uint8_t bString[USB_BSTRING_LENGTH(CONFIG_USB_DEVICE_PRODUCT)];
216 	} __packed utf16le_product;
217 
218 	struct usb_sn_descriptor {
219 		uint8_t bLength;
220 		uint8_t bDescriptorType;
221 		uint8_t bString[USB_BSTRING_LENGTH(CONFIG_USB_DEVICE_SN)];
222 	} __packed utf16le_sn;
223 
224 	struct image_0_descriptor {
225 		uint8_t bLength;
226 		uint8_t bDescriptorType;
227 		uint8_t bString[USB_BSTRING_LENGTH(FIRMWARE_IMAGE_0_LABEL)];
228 	} __packed utf16le_image0;
229 
230 #if FLASH_AREA_LABEL_EXISTS(image_1)
231 	struct image_1_descriptor {
232 		uint8_t bLength;
233 		uint8_t bDescriptorType;
234 		uint8_t bString[USB_BSTRING_LENGTH(FIRMWARE_IMAGE_1_LABEL)];
235 	} __packed utf16le_image1;
236 #endif
237 } __packed;
238 
239 USBD_STRING_DESCR_DEFINE(secondary)
240 struct usb_string_desription string_descr = {
241 	.lang_descr = {
242 		.bLength = sizeof(struct usb_string_descriptor),
243 		.bDescriptorType = USB_DESC_STRING,
244 		.bString = sys_cpu_to_le16(0x0409),
245 	},
246 	/* Manufacturer String Descriptor */
247 	.utf16le_mfr = {
248 		.bLength = USB_STRING_DESCRIPTOR_LENGTH(
249 				CONFIG_USB_DEVICE_MANUFACTURER),
250 		.bDescriptorType = USB_DESC_STRING,
251 		.bString = CONFIG_USB_DEVICE_MANUFACTURER,
252 	},
253 	/* Product String Descriptor */
254 	.utf16le_product = {
255 		.bLength = USB_STRING_DESCRIPTOR_LENGTH(
256 				CONFIG_USB_DEVICE_PRODUCT),
257 		.bDescriptorType = USB_DESC_STRING,
258 		.bString = CONFIG_USB_DEVICE_PRODUCT,
259 	},
260 	/* Serial Number String Descriptor */
261 	.utf16le_sn = {
262 		.bLength = USB_STRING_DESCRIPTOR_LENGTH(CONFIG_USB_DEVICE_SN),
263 		.bDescriptorType = USB_DESC_STRING,
264 		.bString = CONFIG_USB_DEVICE_SN,
265 	},
266 	/* Image 0 String Descriptor */
267 	.utf16le_image0 = {
268 		.bLength = USB_STRING_DESCRIPTOR_LENGTH(
269 				FIRMWARE_IMAGE_0_LABEL),
270 		.bDescriptorType = USB_DESC_STRING,
271 		.bString = FIRMWARE_IMAGE_0_LABEL,
272 	},
273 #if FLASH_AREA_LABEL_EXISTS(image_1)
274 	/* Image 1 String Descriptor */
275 	.utf16le_image1 = {
276 		.bLength = USB_STRING_DESCRIPTOR_LENGTH(
277 				FIRMWARE_IMAGE_1_LABEL),
278 		.bDescriptorType = USB_DESC_STRING,
279 		.bString = FIRMWARE_IMAGE_1_LABEL,
280 	},
281 #endif
282 };
283 
284 /* This element marks the end of the entire descriptor. */
285 USBD_TERM_DESCR_DEFINE(secondary) struct usb_desc_header term_descr = {
286 	.bLength = 0,
287 	.bDescriptorType = 0,
288 };
289 
290 static struct usb_cfg_data dfu_config;
291 
292 /* Device data structure */
293 struct dfu_data_t {
294 	uint8_t flash_area_id;
295 	uint32_t flash_upload_size;
296 	/* Number of bytes sent during upload */
297 	uint32_t bytes_sent;
298 	uint32_t alt_setting;              /* DFU alternate setting */
299 	struct flash_img_context ctx;
300 	enum dfu_state state;              /* State of the DFU device */
301 	enum dfu_status status;            /* Status of the DFU device */
302 	uint16_t block_nr;                 /* DFU block number */
303 	uint16_t bwPollTimeout;
304 };
305 
306 #if FLASH_AREA_LABEL_EXISTS(image_1)
307 	#define UPLOAD_FLASH_AREA_ID FLASH_AREA_ID(image_1)
308 #else
309 	#define UPLOAD_FLASH_AREA_ID FLASH_AREA_ID(image_0)
310 #endif
311 
312 
313 static struct dfu_data_t dfu_data = {
314 	.state = appIDLE,
315 	.status = statusOK,
316 	.flash_area_id = UPLOAD_FLASH_AREA_ID,
317 	.alt_setting = 0,
318 	.bwPollTimeout = CONFIG_USB_DFU_DEFAULT_POLLTIMEOUT,
319 };
320 
321 /**
322  * @brief Helper function to check if in DFU app state.
323  *
324  * @return  true if app state, false otherwise.
325  */
dfu_check_app_state(void)326 static bool dfu_check_app_state(void)
327 {
328 	if (dfu_data.state == appIDLE ||
329 	    dfu_data.state == appDETACH) {
330 		dfu_data.state = appIDLE;
331 		return true;
332 	}
333 
334 	return false;
335 }
336 
337 /**
338  * @brief Helper function to reset DFU internal counters.
339  */
dfu_reset_counters(void)340 static void dfu_reset_counters(void)
341 {
342 	dfu_data.bytes_sent = 0U;
343 	dfu_data.block_nr = 0U;
344 	if (flash_img_init(&dfu_data.ctx)) {
345 		LOG_ERR("flash img init error");
346 		dfu_data.state = dfuERROR;
347 		dfu_data.status = errUNKNOWN;
348 	}
349 }
350 
dfu_flash_write(uint8_t * data,size_t len)351 static void dfu_flash_write(uint8_t *data, size_t len)
352 {
353 	bool flush = false;
354 
355 	if (!len) {
356 		/* Download completed */
357 		flush = true;
358 	}
359 
360 	if (flash_img_buffered_write(&dfu_data.ctx, data, len, flush)) {
361 		LOG_ERR("flash write error");
362 		dfu_data.state = dfuERROR;
363 		dfu_data.status = errWRITE;
364 	} else if (!len) {
365 		LOG_DBG("flash write done");
366 		dfu_data.state = dfuMANIFEST_SYNC;
367 		dfu_reset_counters();
368 		if (boot_request_upgrade(false)) {
369 			dfu_data.state = dfuERROR;
370 			dfu_data.status = errWRITE;
371 		}
372 
373 		k_poll_signal_raise(&dfu_signal, 0);
374 	} else {
375 		dfu_data.state = dfuDNLOAD_IDLE;
376 	}
377 
378 	LOG_DBG("bytes written 0x%x", flash_img_bytes_written(&dfu_data.ctx));
379 }
380 
dfu_timer_expired(struct k_timer * timer)381 static void dfu_timer_expired(struct k_timer *timer)
382 {
383 	if (dfu_data.state == appDETACH) {
384 		dfu_data.state = appIDLE;
385 	}
386 }
387 
dfu_class_handle_to_host(struct usb_setup_packet * setup,int32_t * data_len,uint8_t ** data)388 static int dfu_class_handle_to_host(struct usb_setup_packet *setup,
389 				    int32_t *data_len, uint8_t **data)
390 {
391 	uint32_t bytes_left;
392 	uint32_t len;
393 	int ret;
394 
395 	switch (setup->bRequest) {
396 	case DFU_GETSTATUS:
397 		LOG_DBG("DFU_GETSTATUS: status %d, state %d",
398 			dfu_data.status, dfu_data.state);
399 
400 		if (dfu_data.state == dfuMANIFEST_SYNC) {
401 			dfu_data.state = dfuIDLE;
402 		}
403 
404 		/* bStatus */
405 		(*data)[0] = dfu_data.status;
406 		/* bwPollTimeout */
407 		sys_put_le16(dfu_data.bwPollTimeout, &(*data)[1]);
408 		(*data)[3] = 0U;
409 		/* bState */
410 		(*data)[4] = dfu_data.state;
411 		/* iString */
412 		(*data)[5] = 0U;
413 		*data_len = 6;
414 		break;
415 
416 	case DFU_GETSTATE:
417 		LOG_DBG("DFU_GETSTATE");
418 		(*data)[0] = dfu_data.state;
419 		*data_len = 1;
420 		break;
421 
422 	case DFU_UPLOAD:
423 		LOG_DBG("DFU_UPLOAD block %d, len %d, state %d",
424 			setup->wValue, setup->wLength, dfu_data.state);
425 
426 		if (dfu_check_app_state()) {
427 			return -EINVAL;
428 		}
429 
430 		switch (dfu_data.state) {
431 		case dfuIDLE:
432 			dfu_reset_counters();
433 			LOG_DBG("DFU_UPLOAD start");
434 			__fallthrough;
435 		case dfuUPLOAD_IDLE:
436 			if (!setup->wLength ||
437 			    dfu_data.block_nr != setup->wValue) {
438 				LOG_ERR("DFU_UPLOAD block %d, expected %d, "
439 					"len %d", setup->wValue,
440 					dfu_data.block_nr, setup->wLength);
441 				dfu_data.state = dfuERROR;
442 				dfu_data.status = errUNKNOWN;
443 				return -EINVAL;
444 			}
445 
446 			/* Upload in progress */
447 			bytes_left = dfu_data.flash_upload_size -
448 				     dfu_data.bytes_sent;
449 			if (bytes_left < setup->wLength) {
450 				len = bytes_left;
451 			} else {
452 				len = setup->wLength;
453 			}
454 
455 			if (len > USB_DFU_MAX_XFER_SIZE) {
456 				/*
457 				 * The host could requests more data as stated
458 				 * in wTransferSize. Limit upload length to the
459 				 * size of the request-buffer.
460 				 */
461 				len = USB_DFU_MAX_XFER_SIZE;
462 			}
463 
464 			if (len) {
465 				const struct flash_area *fa;
466 
467 				ret = flash_area_open(dfu_data.flash_area_id,
468 						      &fa);
469 				if (ret) {
470 					dfu_data.state = dfuERROR;
471 					dfu_data.status = errFILE;
472 					return -EINVAL;
473 				}
474 				ret = flash_area_read(fa, dfu_data.bytes_sent,
475 						      *data, len);
476 				flash_area_close(fa);
477 				if (ret) {
478 					dfu_data.state = dfuERROR;
479 					dfu_data.status = errFILE;
480 					return -EINVAL;
481 				}
482 			}
483 			*data_len = len;
484 
485 			dfu_data.bytes_sent += len;
486 			dfu_data.block_nr++;
487 
488 			if (dfu_data.bytes_sent == dfu_data.flash_upload_size &&
489 			    len < setup->wLength) {
490 				/* Upload completed when a
491 				 * short packet is received
492 				 */
493 				*data_len = 0;
494 				dfu_data.state = dfuIDLE;
495 			} else {
496 				dfu_data.state = dfuUPLOAD_IDLE;
497 			}
498 
499 			break;
500 		default:
501 			LOG_ERR("DFU_UPLOAD wrong state %d", dfu_data.state);
502 			dfu_data.state = dfuERROR;
503 			dfu_data.status = errUNKNOWN;
504 			dfu_reset_counters();
505 			return -EINVAL;
506 		}
507 		break;
508 
509 	default:
510 		LOG_DBG("Unsupported bmRequestType 0x%02x bRequest 0x%02x",
511 			setup->bmRequestType, setup->bRequest);
512 		return -EINVAL;
513 	}
514 
515 	return 0;
516 }
517 
dfu_class_handle_to_device(struct usb_setup_packet * setup,int32_t * data_len,uint8_t ** data)518 static int dfu_class_handle_to_device(struct usb_setup_packet *setup,
519 				      int32_t *data_len, uint8_t **data)
520 {
521 	uint16_t timeout;
522 
523 	switch (setup->bRequest) {
524 	case DFU_ABORT:
525 		LOG_DBG("DFU_ABORT");
526 
527 		if (dfu_check_app_state()) {
528 			return -EINVAL;
529 		}
530 
531 		dfu_reset_counters();
532 		dfu_data.state = dfuIDLE;
533 		dfu_data.status = statusOK;
534 		break;
535 
536 	case DFU_CLRSTATUS:
537 		LOG_DBG("DFU_CLRSTATUS");
538 
539 		if (dfu_check_app_state()) {
540 			return -EINVAL;
541 		}
542 
543 		dfu_data.state = dfuIDLE;
544 		dfu_data.status = statusOK;
545 		break;
546 
547 	case DFU_DNLOAD:
548 		LOG_DBG("DFU_DNLOAD block %d, len %d, state %d",
549 			setup->wValue, setup->wLength, dfu_data.state);
550 
551 		if (dfu_check_app_state()) {
552 			return -EINVAL;
553 		}
554 
555 		switch (dfu_data.state) {
556 		case dfuIDLE:
557 			LOG_DBG("DFU_DNLOAD start");
558 			dfu_reset_counters();
559 			k_poll_signal_reset(&dfu_signal);
560 
561 			if (dfu_data.flash_area_id != UPLOAD_FLASH_AREA_ID) {
562 				dfu_data.status = errWRITE;
563 				dfu_data.state = dfuERROR;
564 				LOG_ERR("This area can not be overwritten");
565 				break;
566 			}
567 
568 			dfu_data.state = dfuDNBUSY;
569 			dfu_data_worker.worker_state = dfuIDLE;
570 			dfu_data_worker.worker_len  = setup->wLength;
571 			memcpy(dfu_data_worker.buf, *data, setup->wLength);
572 			k_work_submit_to_queue(&USB_WORK_Q, &dfu_work);
573 			break;
574 		case dfuDNLOAD_IDLE:
575 			dfu_data.state = dfuDNBUSY;
576 			dfu_data_worker.worker_state = dfuDNLOAD_IDLE;
577 			dfu_data_worker.worker_len  = setup->wLength;
578 
579 			memcpy(dfu_data_worker.buf, *data, setup->wLength);
580 			k_work_submit_to_queue(&USB_WORK_Q, &dfu_work);
581 			break;
582 		default:
583 			LOG_ERR("DFU_DNLOAD wrong state %d", dfu_data.state);
584 			dfu_data.state = dfuERROR;
585 			dfu_data.status = errUNKNOWN;
586 			dfu_reset_counters();
587 			return -EINVAL;
588 		}
589 		break;
590 	case DFU_DETACH:
591 		LOG_DBG("DFU_DETACH timeout %d, state %d",
592 			setup->wValue, dfu_data.state);
593 
594 		if (dfu_data.state != appIDLE) {
595 			dfu_data.state = appIDLE;
596 			return -EINVAL;
597 		}
598 
599 		/* Move to appDETACH state */
600 		dfu_data.state = appDETACH;
601 		/* Begin detach timeout timer */
602 		timeout = MIN(setup->wValue, CONFIG_USB_DFU_DETACH_TIMEOUT);
603 		k_timer_start(&dfu_timer, K_MSEC(timeout), K_FOREVER);
604 		break;
605 	default:
606 		LOG_DBG("Unsupported bmRequestType 0x%02x bRequest 0x%02x",
607 			setup->bmRequestType, setup->bRequest);
608 		return -EINVAL;
609 	}
610 
611 	return 0;
612 }
613 
614 /**
615  * @brief Handler called for DFU Class requests not handled by the USB stack.
616  *
617  * @param setup     Information about the request to execute.
618  * @param len       Size of the buffer.
619  * @param data      Buffer containing the request result.
620  *
621  * @return  0 on success, negative errno code on fail.
622  */
dfu_class_handle_req(struct usb_setup_packet * setup,int32_t * data_len,uint8_t ** data)623 static int dfu_class_handle_req(struct usb_setup_packet *setup,
624 				int32_t *data_len, uint8_t **data)
625 {
626 	if (usb_reqtype_is_to_host(setup)) {
627 		return dfu_class_handle_to_host(setup, data_len, data);
628 	} else {
629 		return dfu_class_handle_to_device(setup, data_len, data);
630 	}
631 }
632 
633 
634 /**
635  * @brief Callback used to know the USB connection status
636  *
637  * @param status USB device status code.
638  *
639  * @return  N/A.
640  */
dfu_status_cb(struct usb_cfg_data * cfg,enum usb_dc_status_code status,const uint8_t * param)641 static void dfu_status_cb(struct usb_cfg_data *cfg,
642 			  enum usb_dc_status_code status,
643 			  const uint8_t *param)
644 {
645 	ARG_UNUSED(param);
646 	ARG_UNUSED(cfg);
647 
648 	/* Check the USB status and do needed action if required */
649 	switch (status) {
650 	case USB_DC_ERROR:
651 		LOG_DBG("USB device error");
652 		break;
653 	case USB_DC_RESET:
654 		LOG_DBG("USB device reset detected, state %d", dfu_data.state);
655 		/* Stop the appDETACH timeout timer */
656 		k_timer_stop(&dfu_timer);
657 		if (dfu_data.state == appDETACH) {
658 			dfu_data.state = dfuIDLE;
659 
660 			/* Set the DFU mode descriptors to be used after
661 			 * reset
662 			 */
663 			dfu_config.usb_device_description =
664 				(uint8_t *) &dfu_mode_desc;
665 			if (usb_set_config(dfu_config.usb_device_description)) {
666 				LOG_ERR("usb_set_config failed during USB "
667 					"device reset");
668 			}
669 		}
670 		break;
671 	case USB_DC_CONNECTED:
672 		LOG_DBG("USB device connected");
673 		break;
674 	case USB_DC_CONFIGURED:
675 		LOG_DBG("USB device configured");
676 		break;
677 	case USB_DC_DISCONNECTED:
678 		LOG_DBG("USB device disconnected");
679 		break;
680 	case USB_DC_SUSPEND:
681 		LOG_DBG("USB device supended");
682 		break;
683 	case USB_DC_RESUME:
684 		LOG_DBG("USB device resumed");
685 		break;
686 	case USB_DC_SOF:
687 		break;
688 	case USB_DC_UNKNOWN:
689 	default:
690 		LOG_DBG("USB unknown state");
691 		break;
692 	}
693 }
694 
695 /**
696  * @brief Custom handler for standard ('chapter 9') requests
697  *        in order to catch the SET_INTERFACE request and
698  *        extract the interface alternate setting
699  *
700  * @param setup    Information about the request to execute.
701  * @param len       Size of the buffer.
702  * @param data      Buffer containing the request result.
703  *
704  * @return          -ENOTSUP so that the stack can process control request.
705  */
706 
dfu_custom_handle_req(struct usb_setup_packet * setup,int32_t * data_len,uint8_t ** data)707 static int dfu_custom_handle_req(struct usb_setup_packet *setup,
708 				 int32_t *data_len, uint8_t **data)
709 {
710 	ARG_UNUSED(data);
711 
712 	if (usb_reqtype_is_to_host(setup) ||
713 	    setup->RequestType.recipient != USB_REQTYPE_RECIPIENT_INTERFACE) {
714 		return -ENOTSUP;
715 	}
716 
717 	if (setup->bRequest == USB_SREQ_SET_INTERFACE) {
718 		LOG_DBG("DFU alternate setting %d", setup->wValue);
719 
720 		const struct flash_area *fa;
721 
722 		switch (setup->wValue) {
723 		case 0:
724 			dfu_data.flash_area_id =
725 			    FLASH_AREA_ID(image_0);
726 			break;
727 #if FLASH_AREA_LABEL_EXISTS(image_1)
728 		case 1:
729 			dfu_data.flash_area_id =
730 			    UPLOAD_FLASH_AREA_ID;
731 			break;
732 #endif
733 		default:
734 			LOG_WRN("Invalid DFU alternate setting");
735 			return -ENOTSUP;
736 		}
737 
738 		if (flash_area_open(dfu_data.flash_area_id, &fa)) {
739 			return -EIO;
740 		}
741 
742 		dfu_data.flash_upload_size = fa->fa_size;
743 		flash_area_close(fa);
744 		dfu_data.alt_setting = setup->wValue;
745 	}
746 
747 	/* Never handled by us */
748 	return -EINVAL;
749 }
750 
dfu_interface_config(struct usb_desc_header * head,uint8_t bInterfaceNumber)751 static void dfu_interface_config(struct usb_desc_header *head,
752 				 uint8_t bInterfaceNumber)
753 {
754 	ARG_UNUSED(head);
755 
756 	dfu_cfg.if0.bInterfaceNumber = bInterfaceNumber;
757 }
758 
759 /* Configuration of the DFU Device send to the USB Driver */
760 USBD_CFG_DATA_DEFINE(primary, dfu) struct usb_cfg_data dfu_config = {
761 	.usb_device_description = NULL,
762 	.interface_config = dfu_interface_config,
763 	.interface_descriptor = &dfu_cfg.if0,
764 	.cb_usb_status = dfu_status_cb,
765 	.interface = {
766 		.class_handler = dfu_class_handle_req,
767 		.custom_handler = dfu_custom_handle_req,
768 	},
769 	.num_endpoints = 0,
770 };
771 
772 /*
773  * Dummy configuration, this is necessary to configure DFU mode descriptor
774  * which is an alternative (secondary) device descriptor.
775  */
776 USBD_CFG_DATA_DEFINE(secondary, dfu) struct usb_cfg_data dfu_mode_config = {
777 	.usb_device_description = NULL,
778 	.interface_config = NULL,
779 	.interface_descriptor = &dfu_mode_desc.sec_dfu_cfg.if0,
780 	.cb_usb_status = dfu_status_cb,
781 	.interface = {
782 		.class_handler = dfu_class_handle_req,
783 		.custom_handler = dfu_custom_handle_req,
784 	},
785 	.num_endpoints = 0,
786 };
787 
dfu_work_handler(struct k_work * item)788 static void dfu_work_handler(struct k_work *item)
789 {
790 	ARG_UNUSED(item);
791 
792 	switch (dfu_data_worker.worker_state) {
793 	case dfuIDLE:
794 /*
795  * If progressive erase is enabled, then erase take place while
796  * image collection, so not erase whole bank at DFU beginning
797  */
798 #ifndef CONFIG_IMG_ERASE_PROGRESSIVELY
799 		if (boot_erase_img_bank(UPLOAD_FLASH_AREA_ID)) {
800 			dfu_data.state = dfuERROR;
801 			dfu_data.status = errERASE;
802 			break;
803 		}
804 #endif
805 	case dfuDNLOAD_IDLE:
806 		dfu_flash_write(dfu_data_worker.buf,
807 				dfu_data_worker.worker_len);
808 		break;
809 	default:
810 		LOG_ERR("OUT of state machine");
811 		break;
812 	}
813 }
814 
usb_dfu_init(const struct device * dev)815 static int usb_dfu_init(const struct device *dev)
816 {
817 	const struct flash_area *fa;
818 
819 	ARG_UNUSED(dev);
820 
821 	k_work_init(&dfu_work, dfu_work_handler);
822 	k_poll_signal_init(&dfu_signal);
823 	k_timer_init(&dfu_timer, dfu_timer_expired, NULL);
824 
825 	if (flash_area_open(dfu_data.flash_area_id, &fa)) {
826 		return -EIO;
827 	}
828 
829 	dfu_data.flash_upload_size = fa->fa_size;
830 	flash_area_close(fa);
831 
832 	return 0;
833 }
834 
835 /**
836  * @brief Function to check if DFU is started.
837  *
838  * @return  true if DNBUSY/DNLOAD_IDLE, false otherwise.
839  */
is_dfu_started(void)840 static bool is_dfu_started(void)
841 {
842 	if ((dfu_data.state == dfuDNBUSY) ||
843 	    (dfu_data.state == dfuDNLOAD_IDLE)) {
844 		return true;
845 	}
846 
847 	return false;
848 }
849 
850 /**
851  * @brief Function to check and wait while the USB DFU is in progress.
852  *
853  * @return  N/A
854  */
wait_for_usb_dfu(k_timeout_t delay)855 void wait_for_usb_dfu(k_timeout_t delay)
856 {
857 	uint64_t end = sys_clock_timeout_end_calc(delay);
858 
859 	/* Wait for a prescribed duration of time. If DFU hasn't started within
860 	 * that time, stop waiting and proceed further.
861 	 */
862 	while (end > k_uptime_ticks()) {
863 		if (is_dfu_started()) {
864 			k_poll_event_init(&dfu_event, K_POLL_TYPE_SIGNAL,
865 				K_POLL_MODE_NOTIFY_ONLY, &dfu_signal);
866 
867 			/* Wait till DFU is complete */
868 			if (k_poll(&dfu_event, 1, K_FOREVER) != 0) {
869 				LOG_DBG("USB DFU Error");
870 			}
871 
872 			LOG_INF("USB DFU Completed");
873 			break;
874 		}
875 
876 		k_msleep(INTERMITTENT_CHECK_DELAY);
877 	}
878 }
879 
880 SYS_INIT(usb_dfu_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
881