Maxim Integrated / Mbed OS MAXREFDES220_HEART_RATE_MONITOR

Dependencies:   USBDevice max32630fthr

Fork of MAXREFDES220# by Maxim Integrated

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SSBootloaderComm.cpp Source File

SSBootloaderComm.cpp

00001 /*******************************************************************************
00002  * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008  * and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included
00012  * in all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017  * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00018  * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020  * OTHER DEALINGS IN THE SOFTWARE.
00021  *
00022  * Except as contained in this notice, the name of Maxim Integrated
00023  * Products, Inc. shall not be used except as stated in the Maxim Integrated
00024  * Products, Inc. Branding Policy.
00025  *
00026  * The mere transfer of this software does not imply any licenses
00027  * of trade secrets, proprietary technology, copyrights, patents,
00028  * trademarks, maskwork rights, or any other form of intellectual
00029  * property whatsoever. Maxim Integrated Products, Inc. retains all
00030  * ownership rights.
00031  *******************************************************************************
00032  */
00033 
00034 #include "DSInterface.h"
00035 #include "SSBootloaderComm.h"
00036 #include "SSInterface.h"
00037 #include "Peripherals.h"
00038 #include "assert.h"
00039 #include "utils.h"
00040 
00041 static const char* const cmd_tbl[] = {
00042     "bootldr",
00043     "exit",
00044     "reset",
00045     "page_size",
00046     "num_pages",
00047     "set_iv",
00048     "set_auth",
00049     "erase",
00050     "flash",
00051 };
00052 
00053 SSBootloaderComm::SSBootloaderComm(USBSerial *USB, SSInterface* ssInterface, DSInterface* dsInterface)
00054     :SensorComm("bootldr", false), m_USB(USB), ss_int(ssInterface), ds_int(dsInterface)
00055 {
00056 }
00057 
00058 int SSBootloaderComm::parse_auth(const char* cmd, uint8_t *auth_bytes)
00059 {
00060     char cmdStr[] = "set_auth ";
00061     int length = strlen(cmd);
00062     int expected_length = strlen(cmdStr) + 2*AES_AUTH_SIZE;
00063     if (length != expected_length) {
00064         pr_err("Couldn't parse Auth bytes, incorrect number of characters (len:%d, expected:%d)\n",
00065             length, expected_length);
00066         return COMM_INVALID_PARAM;
00067     }
00068 
00069     const char* macPtr = cmd + strlen(cmdStr);
00070 
00071     int num_found;
00072     int byteVal;
00073     for (int aidx = 0; aidx < AES_AUTH_SIZE; aidx++) {
00074         num_found = sscanf(macPtr, "%2X", &byteVal);
00075 
00076         if (num_found != 1 || byteVal > 0xFF) {
00077             pr_err("Couldn't parse byte %d of Auth\n", aidx);
00078             return COMM_INVALID_PARAM;
00079         }
00080 
00081         auth_bytes[aidx] = (uint8_t)byteVal;
00082         macPtr += 2;
00083     }
00084 
00085     return COMM_SUCCESS;
00086 }
00087 
00088 int SSBootloaderComm::parse_iv(const char* cmd, uint8_t* iv_bytes)
00089 {
00090     char cmdStr[] = "set_iv ";
00091     int length = strlen(cmd);
00092     int expected_length = strlen(cmdStr) + 2*AES_NONCE_SIZE;
00093     if (length != expected_length) {
00094         pr_err("Couldn't parse IV, incorrect number of characters (len:%d, expected:%d)\n",
00095                length, expected_length);
00096         return COMM_INVALID_PARAM;
00097     }
00098 
00099     const char* ivPtr = cmd + strlen(cmdStr);
00100 
00101     int num_found;
00102     int byteVal;
00103     for (int ividx = 0; ividx < AES_NONCE_SIZE; ividx++) {
00104         num_found = sscanf(ivPtr, "%2X", &byteVal);
00105 
00106         if (num_found != 1 || byteVal > 0xFF) {
00107             pr_err("Couldn't parse byte %d of IV\n", ividx);
00108             return COMM_INVALID_PARAM;
00109         }
00110         iv_bytes[ividx] = (uint8_t)byteVal;
00111         ivPtr += 2;
00112     }
00113 
00114     return COMM_SUCCESS;
00115 }
00116 
00117 bool SSBootloaderComm::parse_command(const char* cmd)
00118 {
00119     const char *ptr_ch = NULL;
00120     int ret = EXIT_SUCCESS;
00121     bool recognizedCmd = false;
00122 
00123     if (!ss_int) {
00124         pr_err("No SmartSensor Interface defined!");
00125         return false;
00126     }
00127     if (!ds_int) {
00128         pr_err("No DeviceStudio Interface defined!");
00129         return false;
00130     }
00131 
00132     for (int i = 0; i < NUM_CMDS; i++) {
00133         ptr_ch = strstr(cmd, cmd_tbl[i]);
00134 
00135         if (*ptr_ch) {
00136             cmd_state_t user_cmd = (cmd_state_t)i;
00137             recognizedCmd = true;
00138 
00139             switch (user_cmd) {
00140                 case cmd_enter_bootldr:
00141                 {
00142                     SS_STATUS status;
00143                     status = ss_int->reset_to_bootloader();
00144                     if (status == SS_SUCCESS)
00145                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_SUCCESS);
00146                     else
00147                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_GENERAL_ERROR);
00148 
00149                     ds_int->set_fw_platform(ss_int->get_ss_platform_name());
00150                     ds_int->set_fw_version(ss_int->get_ss_fw_version());
00151 
00152                     got_page_size = false;
00153                     sent_num_pages = false;
00154                 } break;
00155 
00156                 case cmd_exit_bootldr:
00157                 {
00158                     SS_STATUS status = ss_int->reset_to_main_app();
00159                     if (status == SS_SUCCESS)
00160                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_SUCCESS);
00161                     else
00162                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_GENERAL_ERROR);
00163 
00164                     ds_int->set_fw_platform(ss_int->get_ss_platform_name());
00165                     ds_int->set_fw_version(ss_int->get_ss_fw_version());
00166 
00167                 } break;
00168 
00169                 case cmd_reset:
00170                 {
00171                     SS_STATUS status = ss_int->reset();
00172                     if (status == SS_SUCCESS)
00173                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_SUCCESS);
00174                     else
00175                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_GENERAL_ERROR);
00176                     m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, ret);
00177 
00178                     ds_int->set_fw_platform(ss_int->get_ss_platform_name());
00179                     ds_int->set_fw_version(ss_int->get_ss_fw_version());
00180 
00181                 } break;
00182 
00183                 case cmd_page_size:
00184                 {
00185                     uint8_t cmd_bytes[] = { SS_FAM_R_BOOTLOADER, SS_CMDIDX_PAGESIZE };
00186                     uint8_t rxbuf[3];
00187 
00188                     SS_STATUS status = ss_int->read_cmd(
00189                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00190                             0, 0,
00191                             &rxbuf[0], ARRAY_SIZE(rxbuf));
00192 
00193                     if (status == SS_SUCCESS) {
00194                         //rxbuf holds page size in big-endian format
00195                         page_size = (256*(int)rxbuf[1]) + rxbuf[2];
00196                         assert_msg(page_size <= MAX_PAGE_SIZE, "Page size exceeds maximum allowed");
00197 
00198                         m_USB->printf("\r\n%s value=%d err=%d\r\n", ptr_ch, page_size, COMM_SUCCESS);
00199                         got_page_size = true;
00200 
00201                     } else {
00202                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_GENERAL_ERROR);
00203                     }
00204                 } break;
00205 
00206                 case cmd_num_pages:
00207                 {
00208                     int num_tok = sscanf(ptr_ch, "num_pages %d", &num_pages);
00209                     if (num_tok != 1) {
00210                         m_USB->printf("\r\n%s value=%d err=%d\r\n", ptr_ch, 0, COMM_INVALID_PARAM);
00211                     }
00212 
00213                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETNUMPAGES };
00214                     //num pages = 256*MSB + LSB
00215                     uint8_t data[] = { (uint8_t)((num_pages >> 8) & 0xFF), (uint8_t)(num_pages & 0xFF) };
00216 
00217                     SS_STATUS status = ss_int->write_cmd(
00218                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00219                             &data[0], ARRAY_SIZE(data));
00220 
00221                     if (status == SS_SUCCESS) {
00222                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_SUCCESS);
00223                         sent_num_pages = true;
00224 
00225                     } else {
00226                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_GENERAL_ERROR);
00227                     }
00228                 } break;
00229 
00230                 case cmd_set_iv:
00231                 {
00232                     uint8_t iv_bytes[AES_NONCE_SIZE];
00233                     ret = parse_iv(ptr_ch, &iv_bytes[0]);
00234                     if (ret != COMM_SUCCESS) {
00235                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, ret);
00236                     }
00237                     else
00238                     {
00239                         uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETIV };
00240 
00241                         SS_STATUS status = ss_int->write_cmd(
00242                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00243                             &iv_bytes[0], ARRAY_SIZE(iv_bytes));
00244 
00245                         if (status == SS_SUCCESS) {
00246                             m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_SUCCESS);
00247 
00248                         } else {
00249                             m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_GENERAL_ERROR);
00250                         }
00251                     }
00252                 } break;
00253 
00254                 case cmd_set_auth:
00255                 {
00256                     uint8_t auth_bytes[AES_AUTH_SIZE];
00257                     ret = parse_auth(ptr_ch, &auth_bytes[0]);
00258                     if (ret != COMM_SUCCESS) {
00259                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, ret);
00260                     }
00261                     else
00262                     {
00263                         uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETAUTH };
00264 
00265                         SS_STATUS status = ss_int->write_cmd(
00266                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00267                             &auth_bytes[0], ARRAY_SIZE(auth_bytes));
00268 
00269                         if (status == SS_SUCCESS) {
00270                             m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_SUCCESS);
00271 
00272                         } else {
00273                             m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_GENERAL_ERROR);
00274                         }
00275                     }
00276                 } break;
00277 
00278                 case cmd_erase:
00279                 {
00280                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_ERASE };
00281 
00282                     SS_STATUS status = ss_int->write_cmd(
00283                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00284                             0, 0,
00285                             SS_BOOTLOADER_ERASE_DELAY);
00286                     if (status == SS_SUCCESS)
00287                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_SUCCESS);
00288                     else
00289                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_GENERAL_ERROR);
00290                 } break;
00291 
00292                 case cmd_flash:
00293                 {
00294                     if (got_page_size && sent_num_pages) {
00295                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_SUCCESS);
00296                         flash_page_data();
00297                     } else {
00298                         pr_err("Can't enter flash mode. Need number of pages, and size of page"
00299                                 "(num_pages, page_size, commands)\r\n");
00300                         m_USB->printf("\r\n%s err=%d\r\n", ptr_ch, COMM_GENERAL_ERROR);
00301                     }
00302                 } break;
00303 
00304                 default:
00305                 {
00306                     assert_msg(false, "Invalid switch case!");
00307                 }
00308             }
00309         }
00310     }
00311 
00312     return recognizedCmd;
00313 }
00314 
00315 void SSBootloaderComm::flash_page_data(void)
00316 {
00317     int totalBytes = 0;
00318     int currentPage = 1;
00319 
00320     static uint8_t tx_buf[MAX_PAGE_SIZE + CHECKBYTES_SIZE + 2] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SENDPAGE };
00321     uint8_t *data_buffer = &tx_buf[2];
00322 
00323     while (currentPage <= num_pages) {
00324         pr_info("Waiting for page %d/%d data (%d bytes)...", currentPage, num_pages, page_size);
00325 
00326         //Collect page data + checksum from PC/Android
00327 //      totalBytes = 100;
00328         while (totalBytes < (page_size + CHECKBYTES_SIZE)) {
00329             data_buffer[totalBytes++] = m_USB->_getc();
00330         }
00331 
00332         pr_info("Done\r\n");
00333 
00334         //Send data to SmartSensor
00335         SS_STATUS status = ss_int->write_cmd(tx_buf, page_size + CHECKBYTES_SIZE + 2, 2000);
00336         pr_err("status: %d\r\n", status);
00337 
00338         //Inform PC/Andoid of status
00339         if (status == SS_ERR_BTLDR_CHECKSUM) {
00340             pr_err("Verify checksum failed!\r\n");
00341             m_USB->printf("\r\npageFlashDone err=%d\r\n", FLASH_ERR_CHECKSUM);
00342         } else if (status != SS_SUCCESS) {
00343             pr_err("Page flash failed!\r\n");
00344             m_USB->printf("\r\npageFlashDone err=%d\r\n", FLASH_ERR_GENERAL);
00345         } else {
00346             currentPage++;
00347             pr_err("Page flash successful!\r\n");
00348             m_USB->printf("\r\npageFlashDone err=%d\r\n", COMM_SUCCESS);
00349         }
00350 
00351         totalBytes = 0;
00352     }
00353 }