Maxim Integrated / Mbed OS MAXREFDES220_HR_SPO2_MONITOR

Dependencies:   max32630fthr USBDevice

Fork of MAXREFDES220_HEART_RATE_MONITOR 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     "page_erase",
00051     "flash",
00052     "set_cfg bl enter_mode",
00053     "set_cfg bl enter_pin",
00054     "set_cfg bl enter_pol",
00055     "set_cfg bl exit_mode",
00056     "set_cfg bl exit_to",
00057     "set_cfg bl save",
00058 };
00059 
00060 SSBootloaderComm::SSBootloaderComm(USBSerial *USB, SSInterface* ssInterface, DSInterface* dsInterface)
00061     :SensorComm("bl", false), m_USB(USB), ss_int(ssInterface), ds_int(dsInterface)
00062 {
00063 }
00064 
00065 int SSBootloaderComm::parse_auth(const char* cmd, uint8_t *auth_bytes)
00066 {
00067     char cmdStr[] = "set_auth ";
00068     int length = strlen(cmd);
00069     int expected_length = strlen(cmdStr) + 2*AES_AUTH_SIZE;
00070     if (length != expected_length) {
00071         pr_err("Couldn't parse Auth bytes, incorrect number of characters (len:%d, expected:%d)\n",
00072             length, expected_length);
00073         return COMM_INVALID_PARAM;
00074     }
00075 
00076     const char* macPtr = cmd + strlen(cmdStr);
00077 
00078     int num_found;
00079     int byteVal;
00080     for (int aidx = 0; aidx < AES_AUTH_SIZE; aidx++) {
00081         num_found = sscanf(macPtr, "%2X", &byteVal);
00082 
00083         if (num_found != 1 || byteVal > 0xFF) {
00084             pr_err("Couldn't parse byte %d of Auth\n", aidx);
00085             return COMM_INVALID_PARAM;
00086         }
00087 
00088         auth_bytes[aidx] = (uint8_t)byteVal;
00089         macPtr += 2;
00090     }
00091 
00092     return COMM_SUCCESS;
00093 }
00094 
00095 int SSBootloaderComm::parse_iv(const char* cmd, uint8_t* iv_bytes)
00096 {
00097     char cmdStr[] = "set_iv ";
00098     int length = strlen(cmd);
00099     int expected_length = strlen(cmdStr) + 2*AES_NONCE_SIZE;
00100     if (length != expected_length) {
00101         pr_err("Couldn't parse IV, incorrect number of characters (len:%d, expected:%d)\n",
00102                length, expected_length);
00103         return COMM_INVALID_PARAM;
00104     }
00105 
00106     const char* ivPtr = cmd + strlen(cmdStr);
00107 
00108     int num_found;
00109     int byteVal;
00110     for (int ividx = 0; ividx < AES_NONCE_SIZE; ividx++) {
00111         num_found = sscanf(ivPtr, "%2X", &byteVal);
00112 
00113         if (num_found != 1 || byteVal > 0xFF) {
00114             pr_err("Couldn't parse byte %d of IV\n", ividx);
00115             return COMM_INVALID_PARAM;
00116         }
00117         iv_bytes[ividx] = (uint8_t)byteVal;
00118         ivPtr += 2;
00119     }
00120 
00121     return COMM_SUCCESS;
00122 }
00123 
00124 bool SSBootloaderComm::parse_command(const char* cmd)
00125 {
00126     int ret = EXIT_SUCCESS;
00127     bool recognizedCmd = false;
00128 
00129     if (!ss_int) {
00130         pr_err("No SmartSensor Interface defined!");
00131         return false;
00132     }
00133     if (!ds_int) {
00134         pr_err("No DeviceStudio Interface defined!");
00135         return false;
00136     }
00137 
00138     for (int i = 0; i < NUM_CMDS; i++) {
00139         if (starts_with(cmd, cmd_tbl[i])) {
00140             cmd_state_t user_cmd = (cmd_state_t)i;
00141             recognizedCmd = true;
00142 
00143             switch (user_cmd) {
00144                 case cmd_enter_bootldr:
00145                 {
00146                     SS_STATUS status;
00147                     status = ss_int->reset_to_bootloader();
00148                     if (status == SS_SUCCESS)
00149                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00150                     else
00151                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00152 
00153                     ds_int->set_fw_platform(ss_int->get_ss_platform_name());
00154                     ds_int->set_fw_version(ss_int->get_ss_fw_version());
00155                     got_page_size = false;
00156                     sent_num_pages = false;
00157                 } break;
00158 
00159                 case cmd_exit_bootldr:
00160                 {
00161                     SS_STATUS status = ss_int->reset_to_main_app();
00162                     if (status == SS_SUCCESS)
00163                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00164                     else
00165                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00166 
00167                     ds_int->set_fw_platform(ss_int->get_ss_platform_name());
00168                     ds_int->set_fw_version(ss_int->get_ss_fw_version());
00169 
00170                 } break;
00171 
00172                 case cmd_reset:
00173                 {
00174                     SS_STATUS status = ss_int->reset();
00175                     if (status == SS_SUCCESS)
00176                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00177                     else
00178                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00179                     m_USB->printf("\r\n%s err=%d\r\n", cmd, ret);
00180 
00181                     ds_int->set_fw_platform(ss_int->get_ss_platform_name());
00182                     ds_int->set_fw_version(ss_int->get_ss_fw_version());
00183 
00184                 } break;
00185 
00186                 case cmd_page_size:
00187                 {
00188                     uint8_t cmd_bytes[] = { SS_FAM_R_BOOTLOADER, SS_CMDIDX_PAGESIZE };
00189                     uint8_t rxbuf[3];
00190 
00191                     SS_STATUS status = ss_int->read_cmd(
00192                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00193                             0, 0,
00194                             &rxbuf[0], ARRAY_SIZE(rxbuf));
00195 
00196                     if (status == SS_SUCCESS) {
00197                         //rxbuf holds page size in big-endian format
00198                         page_size = (256*(int)rxbuf[1]) + rxbuf[2];
00199                         assert_msg(page_size <= MAX_PAGE_SIZE, "Page size exceeds maximum allowed");
00200 
00201                         m_USB->printf("\r\n%s value=%d err=%d\r\n", cmd, page_size, COMM_SUCCESS);
00202                         got_page_size = true;
00203 
00204                     } else {
00205                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00206                     }
00207                 } break;
00208 
00209                 case cmd_num_pages:
00210                 {
00211                     int num_tok = sscanf(cmd, "num_pages %d", &num_pages);
00212                     if (num_tok != 1) {
00213                         m_USB->printf("\r\n%s value=%d err=%d\r\n", cmd, 0, COMM_INVALID_PARAM);
00214                         break;
00215                     }
00216 
00217                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETNUMPAGES };
00218                     //num pages = 256*MSB + LSB
00219                     uint8_t data[] = { (uint8_t)((num_pages >> 8) & 0xFF), (uint8_t)(num_pages & 0xFF) };
00220 
00221                     SS_STATUS status = ss_int->write_cmd(
00222                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00223                             &data[0], ARRAY_SIZE(data));
00224 
00225                     if (status == SS_SUCCESS) {
00226                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00227                         sent_num_pages = true;
00228 
00229                     } else {
00230                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00231                     }
00232                 } break;
00233 
00234                 case cmd_set_iv:
00235                 {
00236                     uint8_t iv_bytes[AES_NONCE_SIZE];
00237                     ret = parse_iv(cmd, &iv_bytes[0]);
00238                     if (ret != COMM_SUCCESS) {
00239                         m_USB->printf("\r\n%s err=%d\r\n", cmd, ret);
00240                     }
00241                     else
00242                     {
00243                         uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETIV };
00244 
00245                         SS_STATUS status = ss_int->write_cmd(
00246                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00247                             &iv_bytes[0], ARRAY_SIZE(iv_bytes));
00248 
00249                         if (status == SS_SUCCESS) {
00250                             m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00251 
00252                         } else {
00253                             m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00254                         }
00255                     }
00256                 } break;
00257 
00258                 case cmd_set_auth:
00259                 {
00260                     uint8_t auth_bytes[AES_AUTH_SIZE];
00261                     ret = parse_auth(cmd, &auth_bytes[0]);
00262                     if (ret != COMM_SUCCESS) {
00263                         m_USB->printf("\r\n%s err=%d\r\n", cmd, ret);
00264                     }
00265                     else
00266                     {
00267                         uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETAUTH };
00268 
00269                         SS_STATUS status = ss_int->write_cmd(
00270                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00271                             &auth_bytes[0], ARRAY_SIZE(auth_bytes));
00272 
00273                         if (status == SS_SUCCESS) {
00274                             m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00275 
00276                         } else {
00277                             m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00278                         }
00279                     }
00280                 } break;
00281 
00282                 case cmd_erase:
00283                 {
00284                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_ERASE };
00285 
00286                     SS_STATUS status = ss_int->write_cmd(
00287                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00288                             0, 0,
00289                             SS_BOOTLOADER_ERASE_DELAY);
00290                     if (status == SS_SUCCESS)
00291                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00292                     else
00293                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00294                 } break;
00295 
00296                 case cmd_page_erase:
00297                 {
00298                     int page_num_to_erase;
00299                     int num_tok = sscanf(cmd, "page_erase %d", &page_num_to_erase);
00300                     if (num_tok != 1) {
00301                         m_USB->printf("\r\n%s value=%d err=%d\r\n", cmd, 0, COMM_INVALID_PARAM);
00302                         break;
00303                     }
00304 
00305                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_ERASE_PAGE };
00306                     //num pages = 256*MSB + LSB
00307                     uint8_t data[] = { (uint8_t)((page_num_to_erase >> 8) & 0xFF), (uint8_t)(page_num_to_erase & 0xFF) };
00308 
00309                     SS_STATUS status = ss_int->write_cmd(
00310                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00311                             &data[0], ARRAY_SIZE(data), 50);
00312 
00313                     if (status == SS_SUCCESS) {
00314                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00315                         sent_num_pages = true;
00316                     } else {
00317                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00318                     }
00319                 } break;
00320 
00321                 case cmd_flash:
00322                 {
00323                     if (got_page_size && sent_num_pages) {
00324                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00325                         flash_page_data();
00326                     } else {
00327                         pr_err("Can't enter flash mode. Need number of pages, and size of page"
00328                                 "(num_pages, page_size, commands)\r\n");
00329                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00330                     }
00331                 } break;
00332 
00333                 case cmd_setcfg_bl_enter_mode:
00334                 {
00335                     uint8_t mode;
00336                     ret = parse_cmd_data(cmd, cmd_tbl[i], &mode, 1, false);
00337                     if (ret != 1) {
00338                         pr_err("parse_cmd_data=%d\r\n", ret);
00339                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00340                         break;
00341                     }
00342 
00343                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER_CFG, SS_CMDIDX_BL_ENTRY, SS_BL_CFG_ENTER_BL_MODE, mode };
00344                     SS_STATUS status = ss_int->write_cmd(
00345                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00346                             0, 0);
00347                     if (status == SS_SUCCESS)
00348                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00349                     else
00350                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00351 
00352                 } break;
00353 
00354                 case cmd_setcfg_bl_ebl_pin:
00355                 {
00356                     uint8_t pin[2];
00357                     ret = parse_cmd_data(cmd, cmd_tbl[i], &pin[0], 2, false);
00358                     if (ret != 2) {
00359                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00360                         break;
00361                     }
00362 
00363                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER_CFG, SS_CMDIDX_BL_ENTRY, SS_BL_CFG_EBL_PIN,
00364                                             pin[0], pin[1]};
00365                     SS_STATUS status = ss_int->write_cmd(
00366                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00367                             0, 0);
00368                     if (status == SS_SUCCESS)
00369                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00370                     else
00371                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00372 
00373                 } break;
00374 
00375                 case cmd_setcfg_bl_ebl_pol:
00376                 {
00377                     uint8_t mode;
00378                     ret = parse_cmd_data(cmd, cmd_tbl[i], &mode, 1, false);
00379                     if (ret != 1) {
00380                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00381                         break;
00382                     }
00383 
00384                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER_CFG, SS_CMDIDX_BL_ENTRY, SS_BL_CFG_EBL_POL, mode };
00385                     SS_STATUS status = ss_int->write_cmd(
00386                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00387                             0, 0);
00388                     if (status == SS_SUCCESS)
00389                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00390                     else
00391                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00392 
00393                 } break;
00394 
00395                 case cmd_setcfg_bl_exit_mode:
00396                 {
00397                     uint8_t mode;
00398                     ret = parse_cmd_data(cmd, cmd_tbl[i], &mode, 1, false);
00399                     if (ret != 1) {
00400                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00401                         break;
00402                     }
00403 
00404                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER_CFG, SS_CMDIDX_BL_EXIT, SS_BL_CFG_EXIT_BL_MODE, mode };
00405                     SS_STATUS status = ss_int->write_cmd(
00406                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00407                             0, 0);
00408                     if (status == SS_SUCCESS)
00409                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00410                     else
00411                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00412 
00413                 } break;
00414                 case cmd_setcfg_bl_timeout:
00415                 {
00416                     uint8_t to;
00417                     ret = parse_cmd_data(cmd, cmd_tbl[i], &to, 1, false);
00418                     if (ret != 1) {
00419                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00420                         break;
00421                     }
00422 
00423                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER_CFG, SS_CMDIDX_BL_EXIT, SS_BL_CFG_TIMEOUT, to };
00424                     SS_STATUS status = ss_int->write_cmd(
00425                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00426                             0, 0);
00427                     if (status == SS_SUCCESS)
00428                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00429                     else
00430                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00431 
00432                 } break;
00433                 case cmd_setcfg_bl_save:
00434                 {
00435                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER_CFG, SS_CMDIDX_BL_SAVE };
00436 
00437                     SS_STATUS status = ss_int->write_cmd(
00438                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00439                             0, 0, 50);
00440                     if (status == SS_SUCCESS)
00441                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00442                     else
00443                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00444 
00445                 } break;
00446 
00447                 default:
00448                 {
00449                     assert_msg(false, "Invalid switch case!");
00450                 }
00451             }
00452         }
00453     }
00454 
00455     return recognizedCmd;
00456 }
00457 
00458 void SSBootloaderComm::flash_page_data(void)
00459 {
00460     int totalBytes = 0;
00461     int currentPage = 1;
00462 
00463     static uint8_t tx_buf[MAX_PAGE_SIZE + CHECKBYTES_SIZE + 2] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SENDPAGE };
00464     uint8_t *data_buffer = &tx_buf[2];
00465 
00466     while (currentPage <= num_pages) {
00467         pr_info("Waiting for page %d/%d data (%d bytes)...", currentPage, num_pages, page_size);
00468 
00469         //Collect page data + checksum from PC/Android
00470 //      totalBytes = 100;
00471         while (totalBytes < (page_size + CHECKBYTES_SIZE)) {
00472             data_buffer[totalBytes++] = m_USB->_getc();
00473         }
00474 
00475         pr_info("Done\r\n");
00476 
00477         //Send data to SmartSensor
00478         SS_STATUS status = ss_int->write_cmd(tx_buf, page_size + CHECKBYTES_SIZE + 2, 2000);
00479         pr_err("status: %d\r\n", status);
00480 
00481         //Inform PC/Andoid of status
00482         if (status == SS_ERR_BTLDR_CHECKSUM) {
00483             pr_err("Verify checksum failed!\r\n");
00484             m_USB->printf("\r\npageFlashDone err=%d\r\n", FLASH_ERR_CHECKSUM);
00485         } else if (status != SS_SUCCESS) {
00486             pr_err("Page flash failed!\r\n");
00487             m_USB->printf("\r\npageFlashDone err=%d\r\n", FLASH_ERR_GENERAL);
00488         } else {
00489             currentPage++;
00490             pr_err("Page flash successful!\r\n");
00491             m_USB->printf("\r\npageFlashDone err=%d\r\n", COMM_SUCCESS);
00492         }
00493 
00494         totalBytes = 0;
00495     }
00496 }