/** * Initialize the DFU Core module. * * @return 0 if no error has occurred, an error code otherwise. */ int dfu_init() { /* Activate the default alt setting, i.e., alt setting 0 */ /* * NOTE: to be fixed: start in DFU_ERROR state if firmware is missing * or corrupted (dfu_set_alt_setting() makes the state machine start in * DFU_IDLE state and DFU_OK status). */ return dfu_set_alt_setting(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; } }