Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_control_center.c Source File

arm_uc_control_center.c

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2017 ARM Ltd.
00003 //
00004 // SPDX-License-Identifier: Apache-2.0
00005 //
00006 // Licensed under the Apache License, Version 2.0 (the "License");
00007 // you may not use this file except in compliance with the License.
00008 // You may obtain a copy of the License at
00009 //
00010 //     http://www.apache.org/licenses/LICENSE-2.0
00011 //
00012 // Unless required by applicable law or agreed to in writing, software
00013 // distributed under the License is distributed on an "AS IS" BASIS,
00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 // See the License for the specific language governing permissions and
00016 // limitations under the License.
00017 // ----------------------------------------------------------------------------
00018 
00019 #include "update-client-control-center/arm_uc_control_center.h"
00020 #include "update-client-common/arm_uc_trace.h"
00021 
00022 #include <stdbool.h>
00023 
00024 /* event handler */
00025 static void (*arm_uccc_event_handler)(uintptr_t) = NULL;
00026 static arm_uc_callback_t arm_uccc_authorize_callback = { 0 };
00027 static arm_uc_callback_t arm_uccc_monitor_callback = { 0 };
00028 
00029 /* authorization callback */
00030 static void (*arm_uc_authority_callback)(int32_t) = NULL;
00031 static bool arm_uc_download_token_armed = false;
00032 static bool arm_uc_install_token_armed = false;
00033 
00034 /* force authorization */
00035 static arm_uc_callback_t arm_uccc_override_callback = { 0 };
00036 
00037 static void arm_uccc_override_task(uintptr_t unused);
00038 
00039 /* progress callback */
00040 static void (*arm_uc_progress_callback)(uint32_t, uint32_t) = NULL;
00041 
00042 /* function pointer structs */
00043 static const ARM_UPDATE_MONITOR *arm_uc_monitor_struct = NULL;
00044 
00045 static void ARM_UC_ControlCenter_Notification_Handler(void)
00046 {
00047     if (arm_uccc_event_handler) {
00048         ARM_UC_PostCallback(&arm_uccc_monitor_callback,
00049                             arm_uccc_event_handler,
00050                             ARM_UCCC_EVENT_MONITOR_SEND_DONE);
00051     }
00052 }
00053 
00054 /**
00055  * @brief Initialize Control Center.
00056  *
00057  * @param callback Event handler to signal authorizations.
00058  * @return Error code.
00059  */
00060 arm_uc_error_t ARM_UC_ControlCenter_Initialize(void (*callback)(uintptr_t))
00061 {
00062     UC_CONT_TRACE("ARM_UC_ControlCenter_Initialize: %p", callback);
00063 
00064     arm_uccc_event_handler = callback;
00065 
00066     return (arm_uc_error_t) { ERR_NONE };
00067 }
00068 
00069 /**
00070  * @brief Add monitor struct for sending status and results remotely.
00071  *
00072  * @param monitor Pointer to an ARM_UPDATE_MONITOR struct.
00073  * @return Error code.
00074  */
00075 arm_uc_error_t ARM_UC_ControlCenter_AddMonitor(const ARM_UPDATE_MONITOR *monitor)
00076 {
00077     UC_CONT_TRACE("ARM_UC_ControlCenter_AddMonitor: %p", monitor);
00078 
00079     arm_uc_error_t result = (arm_uc_error_t) { ERR_INVALID_PARAMETER };
00080 
00081     arm_uc_monitor_struct = monitor;
00082 
00083     if (arm_uc_monitor_struct) {
00084         result = arm_uc_monitor_struct->Initialize(ARM_UC_ControlCenter_Notification_Handler);
00085     }
00086 
00087     return result;
00088 }
00089 
00090 /**
00091  * @brief Set callback for receiving download progress.
00092  * @details User application call for setting callback handler.
00093  *          The callback function takes the progreess in percent as argument.
00094  *
00095  * @param callback Function pointer to the progress function.
00096  * @return Error code.
00097  */
00098 arm_uc_error_t ARM_UC_ControlCenter_SetProgressHandler(void (*callback)(uint32_t progress, uint32_t total))
00099 {
00100     UC_CONT_TRACE("ARM_UC_ControlCenter_SetProgressHandler: %p", callback);
00101 
00102     arm_uc_progress_callback = callback;
00103 
00104     return (arm_uc_error_t) { ERR_NONE };
00105 }
00106 
00107 /**
00108  * @brief Set callback function for authorizing requests.
00109  * @details The callback function takes an enum request and an authorization
00110  *          function pointer. To authorize the given request, the caller
00111  *          invokes the authorization function.
00112  *
00113  * @param callback Function pointer to the authorization function.
00114  * @return Error code.
00115  */
00116 arm_uc_error_t ARM_UC_ControlCenter_SetAuthorityHandler(void (*callback)(int32_t))
00117 {
00118     UC_CONT_TRACE("ARM_UC_ControlCenter_SetAuthorityHandler: %p", callback);
00119 
00120     arm_uc_authority_callback = callback;
00121 
00122     return (arm_uc_error_t) { ERR_NONE };
00123 }
00124 
00125 /**
00126  * @brief Request authorization from Control Center.
00127  *
00128  * @param type Request type.
00129  * @return Error code.
00130  */
00131 arm_uc_error_t ARM_UC_ControlCenter_GetAuthorization(arm_uc_request_t request)
00132 {
00133     UC_CONT_TRACE("ARM_UC_ControlCenter_GetAuthorization: %d", (int) request);
00134 
00135     arm_uc_error_t result = (arm_uc_error_t) { ERR_INVALID_PARAMETER };
00136 
00137     switch (request) {
00138         case ARM_UCCC_REQUEST_DOWNLOAD:
00139             /* Arm callback token */
00140             arm_uc_download_token_armed = true;
00141 
00142             if (arm_uc_authority_callback) {
00143                 arm_uc_authority_callback(ARM_UCCC_REQUEST_DOWNLOAD);
00144             } else {
00145                 ARM_UC_ControlCenter_Authorize(ARM_UCCC_REQUEST_DOWNLOAD);
00146             }
00147             result.code = ERR_NONE;
00148             break;
00149 
00150         case ARM_UCCC_REQUEST_INSTALL:
00151             /* Arm callback token */
00152             arm_uc_install_token_armed = true;
00153 
00154             if (arm_uc_authority_callback) {
00155                 arm_uc_authority_callback(ARM_UCCC_REQUEST_INSTALL);
00156             } else {
00157                 ARM_UC_ControlCenter_Authorize(ARM_UCCC_REQUEST_INSTALL);
00158             }
00159             result.code = ERR_NONE;
00160             break;
00161         default:
00162             break;
00163     }
00164 
00165     return result;
00166 }
00167 
00168 /**
00169  * @brief Authorize request.
00170  *
00171  * @param request Request type. Must match the type in callback function.
00172  */
00173 arm_uc_error_t ARM_UC_ControlCenter_Authorize(arm_uc_request_t request)
00174 {
00175     UC_CONT_TRACE("ARM_UC_ControlCenter_Authorize: %d", (int) request);
00176 
00177     arm_uc_error_t result = (arm_uc_error_t) { ERR_INVALID_PARAMETER };
00178 
00179     switch (request) {
00180         case ARM_UCCC_REQUEST_DOWNLOAD:
00181             if (arm_uccc_event_handler && arm_uc_download_token_armed) {
00182                 arm_uc_download_token_armed = false;
00183 
00184                 ARM_UC_PostCallback(&arm_uccc_authorize_callback,
00185                                     arm_uccc_event_handler,
00186                                     ARM_UCCC_EVENT_AUTHORIZE_DOWNLOAD);
00187 
00188                 result.code = ERR_NONE;
00189             }
00190             break;
00191 
00192         case ARM_UCCC_REQUEST_INSTALL:
00193             if (arm_uccc_event_handler && arm_uc_install_token_armed) {
00194                 arm_uc_install_token_armed = false;
00195 
00196                 ARM_UC_PostCallback(&arm_uccc_authorize_callback,
00197                                     arm_uccc_event_handler,
00198                                     ARM_UCCC_EVENT_AUTHORIZE_INSTALL);
00199 
00200                 result.code = ERR_NONE;
00201             }
00202             break;
00203 
00204         default:
00205             break;
00206     }
00207 
00208     return result;
00209 }
00210 
00211 /**
00212  * @brief Override update authorization handler.
00213  * @details Force download and update to progress regardless of authorization
00214  *          handler. This function is used for unblocking an update in a buggy
00215  *          application.
00216  */
00217 void ARM_UC_ControlCenter_OverrideAuthorization(void)
00218 {
00219     ARM_UC_PostCallback(&arm_uccc_override_callback,
00220                         arm_uccc_override_task,
00221                         0);
00222 }
00223 
00224 static void arm_uccc_override_task(uintptr_t unused)
00225 {
00226     (void) unused;
00227 
00228     UC_CONT_TRACE("arm_uccc_override_task");
00229 
00230     if (arm_uc_download_token_armed) {
00231         arm_uc_download_token_armed = false;
00232 
00233         /* force authorization */
00234         if (arm_uccc_event_handler) {
00235             arm_uccc_event_handler(ARM_UCCC_EVENT_AUTHORIZE_DOWNLOAD);
00236         }
00237     } else if (arm_uc_install_token_armed) {
00238         arm_uc_install_token_armed = false;
00239 
00240         /* force authorization */
00241         if (arm_uccc_event_handler) {
00242             arm_uccc_event_handler(ARM_UCCC_EVENT_AUTHORIZE_INSTALL);
00243         }
00244     }
00245 
00246     /* disable authorization function */
00247     arm_uc_authority_callback = NULL;
00248 }
00249 
00250 /**
00251  * @brief Report download progress.
00252  * @details Update Client call for informing the Control Center about the
00253  *          current download progress. The Control Center will send this to the
00254  *          appication handler and the monitor if either/both are attached.
00255  *
00256  * @param progrss Bytes already downloaded.
00257  * @param total Total amount of bytes in download.
00258  * @return Error code.
00259  */
00260 arm_uc_error_t ARM_UC_ControlCenter_ReportProgress(uint32_t progress, uint32_t total)
00261 {
00262     UC_CONT_TRACE("ARM_UC_ControlCenter_ReportProgress: %" PRIu32 " / %" PRIu32, progress, total);
00263 
00264     /* only forward request if callback is set. */
00265     if (arm_uc_progress_callback) {
00266         arm_uc_progress_callback(progress, total);
00267     }
00268 
00269     return (arm_uc_error_t) { ERR_NONE };
00270 }
00271 
00272 /**
00273  * @brief Send Update Client state.
00274  * @param state Update Client state.
00275  *
00276  * @return Error code.
00277  */
00278 arm_uc_error_t ARM_UC_ControlCenter_ReportState(arm_uc_monitor_state_t state)
00279 {
00280     UC_CONT_TRACE("ARM_UC_ControlCenter_ReportState: %d", (int) state);
00281 
00282     arm_uc_error_t result = (arm_uc_error_t) { ERR_INVALID_PARAMETER };
00283 
00284     if (arm_uc_monitor_struct) {
00285         arm_uc_monitor_struct->SendState(state);
00286         result.code = ERR_NONE;
00287     }
00288 
00289     return result;
00290 }
00291 
00292 /**
00293  * @brief Set update result.
00294  * @param result Update result.
00295  *
00296  * @return Error code.
00297  */
00298 arm_uc_error_t ARM_UC_ControlCenter_ReportUpdateResult(arm_uc_monitor_result_t updateResult)
00299 {
00300     UC_CONT_TRACE("ARM_UC_ControlCenter_ReportUpdateResult: %d", (int) updateResult);
00301 
00302     arm_uc_error_t result = (arm_uc_error_t) { ERR_INVALID_PARAMETER };
00303 
00304     if (arm_uc_monitor_struct) {
00305         arm_uc_monitor_struct->SendUpdateResult(updateResult);
00306         result.code = ERR_NONE;
00307     }
00308 
00309     return result;
00310 }
00311 
00312 /**
00313  * @brief Set current firmware name.
00314  * @details Update Client call for informing the Control Center about the
00315  *          current firmware name. The Control Center will send this to the
00316  *          monitor. The firmware name is the SHA256 hash.
00317  *
00318  * @param name Pointer to buffer struct. Hash is stored as byte array.
00319  * @return Error code.
00320  */
00321 arm_uc_error_t ARM_UC_ControlCenter_ReportName(arm_uc_buffer_t *name)
00322 {
00323     UC_CONT_TRACE("ARM_UC_ControlCenter_ReportName: %p", name);
00324 
00325     arm_uc_error_t result = (arm_uc_error_t) { ERR_INVALID_PARAMETER };
00326 
00327     if (arm_uc_monitor_struct) {
00328         arm_uc_monitor_struct->SendName(name);
00329         result.code = ERR_NONE;
00330     }
00331 
00332     return result;
00333 }
00334 
00335 /**
00336  * @brief Set current firmware version.
00337  * @details The firmware version is the SHA256 hash.
00338  *
00339  * @param version Pointer to buffer struct. Hash is stored as byte array.
00340  * @return Error code.
00341  */
00342 arm_uc_error_t ARM_UC_ControlCenter_ReportVersion(uint64_t version)
00343 {
00344     UC_CONT_TRACE("ARM_UC_ControlCenter_ReportVersion: %" PRIu64, version);
00345 
00346     arm_uc_error_t result = (arm_uc_error_t) { ERR_INVALID_PARAMETER };
00347 
00348     if (arm_uc_monitor_struct) {
00349         arm_uc_monitor_struct->SendVersion(version);
00350         result.code = ERR_NONE;
00351     }
00352 
00353     return result;
00354 }
00355 
00356 /**
00357  * @brief Send bootloader hash to monitor.
00358  * @details The bootloader hash is a hash of the bootloader. This is
00359  *          used for tracking the version of the bootloader used.
00360  *
00361  * @param name Pointer to buffer struct. Hash is stored as byte array.
00362  * @return Error code.
00363  */
00364 arm_uc_error_t ARM_UC_ControlCenter_ReportBootloaderHash(arm_uc_buffer_t *hash)
00365 {
00366     UC_CONT_TRACE("ARM_UC_ControlCenter_ReportBootloaderHash");
00367 
00368     arm_uc_error_t result = (arm_uc_error_t) { ERR_INVALID_PARAMETER };
00369 
00370     if (arm_uc_monitor_struct && arm_uc_monitor_struct->SetBootloaderHash) {
00371         result = arm_uc_monitor_struct->SetBootloaderHash(hash);
00372     }
00373 
00374     return result;
00375 }
00376 
00377 /**
00378  * @brief Send the OEM bootloader hash to monitor.
00379  * @details If the end-user has modified the bootloader the hash of the
00380  *          modified bootloader can be set here.
00381  *
00382  * @param name Pointer to buffer struct. Hash is stored as byte array.
00383  * @return Error code.
00384  */
00385 arm_uc_error_t ARM_UC_ControlCenter_ReportOEMBootloaderHash(arm_uc_buffer_t *hash)
00386 {
00387     UC_CONT_TRACE("ARM_UC_ControlCenter_ReportOEMBootloaderHash");
00388 
00389     arm_uc_error_t result = (arm_uc_error_t) { ERR_INVALID_PARAMETER };
00390 
00391     if (arm_uc_monitor_struct && arm_uc_monitor_struct->SetOEMBootloaderHash) {
00392         result = arm_uc_monitor_struct->SetOEMBootloaderHash(hash);
00393     }
00394 
00395     return result;
00396 }