Esempio n. 1
0
void fm_entry_uart(void)
{
	qm_gpio_state_t state;

	/*
	 * qda_init() implicitly initializes the HW required by XMODEM (i.e.,
	 * UART and PIC timer) and the DFU state machine.
	 */
	qda_init();
	do {
		/*
		 * The following function returns only when no data is received
		 * for 10 seconds.
		 */
		qda_receive_loop();
		fm_gpio_get_state(&state);
	} while (state == QM_GPIO_LOW);
	/*
	 * Cold reboot in order to restore the default system configuration
	 * (thus getting rid of all the changes done by the FM mode, like the
	 * UART configuration).
	 */
	qm_soc_reset(QM_COLD_RESET);
}
Esempio n. 2
0
/**
 * Process QDA packet.
 *
 * Parse, process, and reply to an incoming QDA packet.
 *
 * @param[in] data The buffer containing the packet.
 * @param[in] len  The length of packet or its upper bound (since XMODEM may
 * 		   add some padding bytes).
 */
static void qda_process_pkt(uint8_t *data, size_t len)
{
	qda_pkt_t *pkt;
	qda_dnl_req_payload_t *dnload_req;
	qda_upl_req_payload_t *upload_req;
	qda_set_alt_setting_payload_t *altset_req;
	size_t expected_len;

	dfu_dev_state_t state;
	dfu_dev_status_t status;
	uint32_t poll_timeout;

	pkt = (qda_pkt_t *)data;
	expected_len = sizeof(*pkt);

	switch (pkt->type) {
	case QDA_PKT_DEV_DESC_REQ:
		qda_dev_dsc_rsp();
		break;
	case QDA_PKT_DFU_DESC_REQ:
		qda_dfu_dsc_rsp();
		break;
	case QDA_PKT_DFU_SET_ALT_SETTING:
		altset_req = (qda_set_alt_setting_payload_t *)pkt->payload;
		STALL_AND_BREAK_ON_ERR(
		    dfu_set_alt_setting(altset_req->alt_setting));
		qda_ack();
		break;
	case QDA_PKT_DFU_DNLOAD_REQ:
		dnload_req = (qda_dnl_req_payload_t *)pkt->payload;
		expected_len += sizeof(*dnload_req) + dnload_req->data_len;
		if ((len < expected_len) ||
		    dfu_process_dnload(dnload_req->block_num, dnload_req->data,
				       dnload_req->data_len)) {
			qda_stall();
			break;
		}
		qda_ack();
		break;
	case QDA_PKT_DFU_UPLOAD_REQ:
		upload_req = (qda_upl_req_payload_t *)pkt->payload;
		/* UPLOAD requests are handled differently from the others in
		 * order to reuse qda_buf */
		handle_upload_req(upload_req);
		break;
	case QDA_PKT_DFU_GETSTATUS_REQ:
		STALL_AND_BREAK_ON_ERR(
		    dfu_get_status(&status, &state, &poll_timeout));
		qda_dfu_get_status_rsp(state, status, poll_timeout);
		break;
	case QDA_PKT_DFU_CLRSTATUS:
		STALL_AND_BREAK_ON_ERR(dfu_clr_status());
		qda_ack();
		break;
	case QDA_PKT_DFU_GETSTATE_REQ:
		STALL_AND_BREAK_ON_ERR(dfu_get_state(&state));
		qda_dfu_get_state_rsp(state);
		break;
	case QDA_PKT_DFU_ABORT:
		STALL_AND_BREAK_ON_ERR(dfu_abort());
		qda_ack();
		break;
	case QDA_PKT_RESET:
		qda_ack();
		qm_soc_reset(QM_COLD_RESET);
		break;
	/* QDA_PKT_DFU_DETACH should not be received */
	default:
		/* NOTE: how to handle bad QDA requests? Send a QDA_STALL
		 * message for now */
		qda_stall();
		break;
	}
}