dfu: Provide means to find difference between dfu-util -e and -R
This commit provides distinction between DFU device detach and reset. The -R behavior is preserved with proper handling of the dfu-util's -e switch, which detach the DFU device. By running dfu-util -e; one can force device to finish the execution of dfu command on target and execute some other scripted commands. Moreover, some naming has been changed - the dfu_reset() method now is known as dfu_detach(). New name better reflects the purpose of the code. It was also necessary to increase the number of usb_gadget_handle_interrupts() calls since we also must wait for detection of the USB reset event. Example usage: 1. -e (detach) switch dfu-util -a0 -D file1.bin;dfu-util -a3 -D uImage;dfu-util -e access to u-boot prompt. 2. -R (reset) switch dfu-util -a0 -D file1.bin;dfu-util -R -a3 -D uImage target board reset Signed-off-by: Lukasz Majewski <l.majewski@samsung.com> Reviewed-by: Stephen Warren <swarren@nvidia.com> Tested-by: Stephen Warren <swarren@nvidia.com>
This commit is contained in:
		
							parent
							
								
									a1263632bb
								
							
						
					
					
						commit
						1cc03c5c53
					
				|  | @ -15,6 +15,8 @@ | ||||||
| 
 | 
 | ||||||
| static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | ||||||
| { | { | ||||||
|  | 	bool dfu_reset = false; | ||||||
|  | 
 | ||||||
| 	if (argc < 4) | 	if (argc < 4) | ||||||
| 		return CMD_RET_USAGE; | 		return CMD_RET_USAGE; | ||||||
| 
 | 
 | ||||||
|  | @ -36,17 +38,28 @@ static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | ||||||
| 
 | 
 | ||||||
| 	int controller_index = simple_strtoul(usb_controller, NULL, 0); | 	int controller_index = simple_strtoul(usb_controller, NULL, 0); | ||||||
| 	board_usb_init(controller_index, USB_INIT_DEVICE); | 	board_usb_init(controller_index, USB_INIT_DEVICE); | ||||||
| 
 | 	dfu_clear_detach(); | ||||||
| 	g_dnl_register("usb_dnl_dfu"); | 	g_dnl_register("usb_dnl_dfu"); | ||||||
| 	while (1) { | 	while (1) { | ||||||
| 		if (dfu_reset()) | 		if (dfu_detach()) { | ||||||
|  | 			/*
 | ||||||
|  | 			 * Check if USB bus reset is performed after detach, | ||||||
|  | 			 * which indicates that -R switch has been passed to | ||||||
|  | 			 * dfu-util. In this case reboot the device | ||||||
|  | 			 */ | ||||||
|  | 			if (dfu_usb_get_reset()) { | ||||||
|  | 				dfu_reset = true; | ||||||
|  | 				goto exit; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			/*
 | 			/*
 | ||||||
| 			 * This extra number of usb_gadget_handle_interrupts() | 			 * This extra number of usb_gadget_handle_interrupts() | ||||||
| 			 * calls is necessary to assure correct transmission | 			 * calls is necessary to assure correct transmission | ||||||
| 			 * completion with dfu-util | 			 * completion with dfu-util | ||||||
| 			 */ | 			 */ | ||||||
| 			if (++i == 10) | 			if (++i == 10000) | ||||||
| 				goto exit; | 				goto exit; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		if (ctrlc()) | 		if (ctrlc()) | ||||||
| 			goto exit; | 			goto exit; | ||||||
|  | @ -58,9 +71,11 @@ exit: | ||||||
| done: | done: | ||||||
| 	dfu_free_entities(); | 	dfu_free_entities(); | ||||||
| 
 | 
 | ||||||
| 	if (dfu_reset()) | 	if (dfu_reset) | ||||||
| 		run_command("reset", 0); | 		run_command("reset", 0); | ||||||
| 
 | 
 | ||||||
|  | 	dfu_clear_detach(); | ||||||
|  | 
 | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -17,20 +17,41 @@ | ||||||
| #include <linux/list.h> | #include <linux/list.h> | ||||||
| #include <linux/compiler.h> | #include <linux/compiler.h> | ||||||
| 
 | 
 | ||||||
| static bool dfu_reset_request; | static bool dfu_detach_request; | ||||||
| static LIST_HEAD(dfu_list); | static LIST_HEAD(dfu_list); | ||||||
| static int dfu_alt_num; | static int dfu_alt_num; | ||||||
| static int alt_num_cnt; | static int alt_num_cnt; | ||||||
| static struct hash_algo *dfu_hash_algo; | static struct hash_algo *dfu_hash_algo; | ||||||
| 
 | 
 | ||||||
| bool dfu_reset(void) | /*
 | ||||||
|  |  * The purpose of the dfu_usb_get_reset() function is to | ||||||
|  |  * provide information if after USB_DETACH request | ||||||
|  |  * being sent the dfu-util performed reset of USB | ||||||
|  |  * bus. | ||||||
|  |  * | ||||||
|  |  * Described behaviour is the only way to distinct if | ||||||
|  |  * user has typed -e (detach) or -R (reset) when invoking | ||||||
|  |  * dfu-util command. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | __weak bool dfu_usb_get_reset(void) | ||||||
| { | { | ||||||
| 	return dfu_reset_request; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void dfu_trigger_reset() | bool dfu_detach(void) | ||||||
| { | { | ||||||
| 	dfu_reset_request = true; | 	return dfu_detach_request; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dfu_trigger_detach(void) | ||||||
|  | { | ||||||
|  | 	dfu_detach_request = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dfu_clear_detach(void) | ||||||
|  | { | ||||||
|  | 	dfu_detach_request = false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int dfu_find_alt_num(const char *s) | static int dfu_find_alt_num(const char *s) | ||||||
|  |  | ||||||
|  | @ -372,7 +372,7 @@ static int state_dfu_idle(struct f_dfu *f_dfu, | ||||||
| 		to_runtime_mode(f_dfu); | 		to_runtime_mode(f_dfu); | ||||||
| 		f_dfu->dfu_state = DFU_STATE_appIDLE; | 		f_dfu->dfu_state = DFU_STATE_appIDLE; | ||||||
| 
 | 
 | ||||||
| 		dfu_trigger_reset(); | 		dfu_trigger_detach(); | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		f_dfu->dfu_state = DFU_STATE_dfuERROR; | 		f_dfu->dfu_state = DFU_STATE_dfuERROR; | ||||||
|  |  | ||||||
|  | @ -150,11 +150,14 @@ struct dfu_entity *dfu_get_entity(int alt); | ||||||
| char *dfu_extract_token(char** e, int *n); | char *dfu_extract_token(char** e, int *n); | ||||||
| void dfu_trigger_reset(void); | void dfu_trigger_reset(void); | ||||||
| int dfu_get_alt(char *name); | int dfu_get_alt(char *name); | ||||||
| bool dfu_reset(void); | bool dfu_detach(void); | ||||||
|  | void dfu_trigger_detach(void); | ||||||
|  | void dfu_clear_detach(void); | ||||||
| int dfu_init_env_entities(char *interface, char *devstr); | int dfu_init_env_entities(char *interface, char *devstr); | ||||||
| unsigned char *dfu_get_buf(struct dfu_entity *dfu); | unsigned char *dfu_get_buf(struct dfu_entity *dfu); | ||||||
| unsigned char *dfu_free_buf(void); | unsigned char *dfu_free_buf(void); | ||||||
| unsigned long dfu_get_buf_size(void); | unsigned long dfu_get_buf_size(void); | ||||||
|  | bool dfu_usb_get_reset(void); | ||||||
| 
 | 
 | ||||||
| int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num); | int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num); | ||||||
| int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num); | int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue