LCOV - code coverage report
Current view: top level - AP_Scripting - AP_Scripting.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 103 168 61.3 %
Date: 2026-09-09 11:02:08 Functions: 11 13 84.6 %

          Line data    Source code
       1             : /*
       2             :    This program is free software: you can redistribute it and/or modify
       3             :    it under the terms of the GNU General Public License as published by
       4             :    the Free Software Foundation, either version 3 of the License, or
       5             :    (at your option) any later version.
       6             : 
       7             :    This program is distributed in the hope that it will be useful,
       8             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10             :    GNU General Public License for more details.
      11             : 
      12             :    You should have received a copy of the GNU General Public License
      13             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      14             :  */
      15             : 
      16             : #include "AP_Scripting_config.h"
      17             : 
      18             : #if AP_SCRIPTING_ENABLED
      19             : 
      20             : #include <AP_Scripting/AP_Scripting.h>
      21             : #include <AP_RCTelemetry/AP_CRSF_Telem.h>
      22             : #include <AP_HAL/AP_HAL.h>
      23             : #include <GCS_MAVLink/GCS.h>
      24             : #include <AP_Arming/AP_Arming.h>
      25             : 
      26             : #include "lua_scripts.h"
      27             : #include "AP_Scripting_helpers.h"
      28             : 
      29             : // ensure that we have a set of stack sizes, and enforce constraints around it
      30             : // except for the minimum size, these are allowed to be defined by the build system
      31             : #undef SCRIPTING_STACK_MIN_SIZE
      32             : #define SCRIPTING_STACK_MIN_SIZE (8 * 1024)
      33             : 
      34             : #if !defined(SCRIPTING_STACK_SIZE)
      35             :   #define SCRIPTING_STACK_SIZE (17 * 1024) // Linux experiences stack corruption at ~16.25KB when handed bad scripts
      36             : #endif // !defined(SCRIPTING_STACK_SIZE)
      37             : 
      38             : #if !defined(SCRIPTING_STACK_MAX_SIZE)
      39             :   #define SCRIPTING_STACK_MAX_SIZE (64 * 1024)
      40             : #endif // !defined(SCRIPTING_STACK_MAX_SIZE)
      41             : 
      42             : #if !defined(SCRIPTING_HEAP_SIZE)
      43             :   #if CONFIG_HAL_BOARD == HAL_BOARD_SITL || CONFIG_HAL_BOARD == HAL_BOARD_LINUX || HAL_MEM_CLASS >= HAL_MEM_CLASS_1000
      44             :     #define SCRIPTING_HEAP_SIZE (200 * 1024)
      45             :   #elif HAL_MEM_CLASS >= HAL_MEM_CLASS_500
      46             :     #define SCRIPTING_HEAP_SIZE (100 * 1024)
      47             :   #else
      48             :     #define SCRIPTING_HEAP_SIZE (43 * 1024)
      49             :   #endif
      50             : #endif // !defined(SCRIPTING_HEAP_SIZE)
      51             : 
      52             : static_assert(SCRIPTING_STACK_SIZE >= SCRIPTING_STACK_MIN_SIZE, "Scripting requires a larger minimum stack size");
      53             : static_assert(SCRIPTING_STACK_SIZE <= SCRIPTING_STACK_MAX_SIZE, "Scripting requires a smaller stack size");
      54             : 
      55             : #ifndef SCRIPTING_ENABLE_DEFAULT
      56             : #define SCRIPTING_ENABLE_DEFAULT 0
      57             : #endif
      58             : 
      59             : #if AP_NETWORKING_ENABLED
      60             : #include <AP_HAL/utility/Socket.h>
      61             : #endif
      62             : 
      63             : extern const AP_HAL::HAL& hal;
      64             : 
      65             : const AP_Param::GroupInfo AP_Scripting::var_info[] = {
      66             :     // @Param: ENABLE
      67             :     // @DisplayName: Enable Scripting
      68             :     // @Description: Controls if scripting is enabled
      69             :     // @Values: 0:None,1:Lua Scripts
      70             :     // @RebootRequired: True
      71             :     // @User: Advanced
      72             :     AP_GROUPINFO_FLAGS("ENABLE", 1, AP_Scripting, _enable, SCRIPTING_ENABLE_DEFAULT, AP_PARAM_FLAG_ENABLE),
      73             : 
      74             :     // @Param: VM_I_COUNT
      75             :     // @DisplayName: Scripting Virtual Machine Instruction Count
      76             :     // @Description: The number virtual machine instructions that can be run before considering a script to have taken an excessive amount of time
      77             :     // @Range: 1000 1000000
      78             :     // @Increment: 10000
      79             :     // @User: Advanced
      80             :     AP_GROUPINFO("VM_I_COUNT", 2, AP_Scripting, _script_vm_exec_count, 10000),
      81             : 
      82             :     // @Param: HEAP_SIZE
      83             :     // @DisplayName: Scripting Heap Size
      84             :     // @Description: Amount of memory available for scripting
      85             :     // @Range: 1024 1048576
      86             :     // @Increment: 1024
      87             :     // @User: Advanced
      88             :     // @RebootRequired: True
      89             :     AP_GROUPINFO("HEAP_SIZE", 3, AP_Scripting, _script_heap_size, SCRIPTING_HEAP_SIZE),
      90             : 
      91             :     // @Param: DEBUG_OPTS
      92             :     // @DisplayName: Scripting Debug Level
      93             :     // @Description: Debugging options
      94             :     // @Bitmask: 0: No Scripts to run message if all scripts have stopped
      95             :     // @Bitmask: 1: Runtime messages for memory usage and execution time
      96             :     // @Bitmask: 2: Suppress logging scripts to dataflash
      97             :     // @Bitmask: 3: log runtime memory usage and execution time
      98             :     // @Bitmask: 4: Disable pre-arm check
      99             :     // @Bitmask: 5: Save CRC of current scripts to loaded and running checksum parameters enabling pre-arm
     100             :     // @Bitmask: 6: Disable heap expansion on allocation failure
     101             :     // @User: Advanced
     102             :     AP_GROUPINFO("DEBUG_OPTS", 4, AP_Scripting, _debug_options, 0),
     103             : 
     104             :     // @Param: USER1
     105             :     // @DisplayName: Scripting User Parameter1
     106             :     // @Description: General purpose user variable input for scripts
     107             :     // @User: Standard
     108             :     AP_GROUPINFO("USER1", 5, AP_Scripting, _user[0], 0.0),
     109             : 
     110             :     // @Param: USER2
     111             :     // @DisplayName: Scripting User Parameter2
     112             :     // @Description: General purpose user variable input for scripts
     113             :     // @User: Standard
     114             :     AP_GROUPINFO("USER2", 6, AP_Scripting, _user[1], 0.0),
     115             : 
     116             :     // @Param: USER3
     117             :     // @DisplayName: Scripting User Parameter3
     118             :     // @Description: General purpose user variable input for scripts
     119             :     // @User: Standard
     120             :     AP_GROUPINFO("USER3", 7, AP_Scripting, _user[2], 0.0),
     121             : 
     122             :     // @Param: USER4
     123             :     // @DisplayName: Scripting User Parameter4
     124             :     // @Description: General purpose user variable input for scripts
     125             :     // @User: Standard
     126             :     AP_GROUPINFO("USER4", 8, AP_Scripting, _user[3], 0.0),
     127             : 
     128             :     // @Param: USER5
     129             :     // @DisplayName: Scripting User Parameter5
     130             :     // @Description: General purpose user variable input for scripts
     131             :     // @User: Standard
     132             :     AP_GROUPINFO("USER5", 10, AP_Scripting, _user[4], 0.0),
     133             : 
     134             :     // @Param: USER6
     135             :     // @DisplayName: Scripting User Parameter6
     136             :     // @Description: General purpose user variable input for scripts
     137             :     // @User: Standard
     138             :     AP_GROUPINFO("USER6", 11, AP_Scripting, _user[5], 0.0),
     139             :     
     140             :     // @Param: DIR_DISABLE
     141             :     // @DisplayName: Directory disable
     142             :     // @Description: This will stop scripts being loaded from the given locations
     143             :     // @Bitmask: 0:ROMFS, 1:APM/scripts
     144             :     // @RebootRequired: True
     145             :     // @User: Advanced
     146             :     AP_GROUPINFO("DIR_DISABLE", 9, AP_Scripting, _dir_disable, 0),
     147             : 
     148             :     // @Param: LD_CHECKSUM
     149             :     // @DisplayName: Loaded script checksum
     150             :     // @Description: Required XOR of CRC32 checksum of loaded scripts, vehicle will not arm with incorrect scripts loaded, -1 disables
     151             :     // @User: Advanced
     152             :     AP_GROUPINFO("LD_CHECKSUM", 12, AP_Scripting, _required_loaded_checksum, -1),
     153             : 
     154             :     // @Param: RUN_CHECKSUM
     155             :     // @DisplayName: Running script checksum
     156             :     // @Description: Required XOR of CRC32 checksum of running scripts, vehicle will not arm with incorrect scripts running, -1 disables
     157             :     // @User: Advanced
     158             :     AP_GROUPINFO("RUN_CHECKSUM", 13, AP_Scripting, _required_running_checksum, -1),
     159             : 
     160             :     // @Param: THD_PRIORITY
     161             :     // @DisplayName: Scripting thread priority
     162             :     // @Description: This sets the priority of the scripting thread. This is normally set to a low priority to prevent scripts from interfering with other parts of the system. Advanced users can change this priority if scripting needs to be prioritised for realtime applications. WARNING: changing this parameter can impact the stability of your flight controller. The scipting thread priority in this parameter is chosen based on a set of system level priorities for other subsystems. It is strongly recommended that you use the lowest priority that is sufficient for your application. Note that all scripts run at the same priority, so if you raise this priority you must carefully audit all lua scripts for behaviour that does not interfere with the operation of the system.
     163             :     // @Values: 0:Normal, 1:IO Priority, 2:Storage Priority, 3:UART Priority, 4:I2C Priority, 5:SPI Priority, 6:Timer Priority, 7:Main Priority, 8:Boost Priority
     164             :     // @RebootRequired: True
     165             :     // @User: Advanced
     166             :     AP_GROUPINFO("THD_PRIORITY", 14, AP_Scripting, _thd_priority, uint8_t(ThreadPriority::NORMAL)),
     167             : 
     168             : #if AP_SCRIPTING_SERIALDEVICE_ENABLED
     169             :     // @Param: SDEV_EN
     170             :     // @DisplayName: Scripting serial device enable
     171             :     // @Description: Enable scripting serial devices
     172             :     // @Values: 0:Disabled, 1:Enabled
     173             :     // @RebootRequired: True
     174             :     // @User: Advanced
     175             :     AP_GROUPINFO_FLAGS("SDEV_EN", 15,  AP_Scripting, _serialdevice.enable, 0, AP_PARAM_FLAG_ENABLE),
     176             : 
     177             :     // @Param: SDEV1_PROTO
     178             :     // @DisplayName: Serial protocol of scripting serial device
     179             :     // @Description: Serial protocol of scripting serial device
     180             :     // @CopyFieldsFrom: SERIAL1_PROTOCOL
     181             :     // @RebootRequired: True
     182             :     // @User: Advanced
     183             :     AP_GROUPINFO("SDEV1_PROTO", 16,  AP_Scripting, _serialdevice.ports[0].state.protocol, -1),
     184             : 
     185             : #if AP_SCRIPTING_SERIALDEVICE_NUM_PORTS > 1
     186             :     // @Param: SDEV2_PROTO
     187             :     // @DisplayName: Serial protocol of scripting serial device
     188             :     // @Description: Serial protocol of scripting serial device
     189             :     // @CopyFieldsFrom: SCR_SDEV1_PROTO
     190             :     AP_GROUPINFO("SDEV2_PROTO", 17,  AP_Scripting, _serialdevice.ports[1].state.protocol, -1),
     191             : #endif
     192             : 
     193             : #if AP_SCRIPTING_SERIALDEVICE_NUM_PORTS > 2
     194             :     // @Param: SDEV3_PROTO
     195             :     // @DisplayName: Serial protocol of scripting serial device
     196             :     // @Description: Serial protocol of scripting serial device
     197             :     // @CopyFieldsFrom: SCR_SDEV1_PROTO
     198             :     AP_GROUPINFO("SDEV3_PROTO", 18,  AP_Scripting, _serialdevice.ports[2].state.protocol, -1),
     199             : #endif
     200             : #endif // AP_SCRIPTING_SERIALDEVICE_ENABLED
     201             : 
     202             :     // WARNING: additional parameters must be listed before SDEV_EN (but have an
     203             :     // index after SDEV3_PROTO) so they are not disabled by it!
     204             :     
     205             :     AP_GROUPEND
     206             : };
     207             : 
     208       14686 : AP_Scripting::AP_Scripting() {
     209        2098 :     AP_Param::setup_object_defaults(this, var_info);
     210             : 
     211             : #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
     212        2096 :     if (_singleton != nullptr) {
     213           0 :         AP_HAL::panic("Scripting must be a singleton");
     214             :     }
     215             : #endif // CONFIG_HAL_BOARD == HAL_BOARD_SITL
     216        2098 :     _singleton = this;
     217        2098 : }
     218             : 
     219        2086 : void AP_Scripting::init(void) {
     220        2086 :     if (!_enable) {
     221        1999 :         return;
     222             :     }
     223             : 
     224             : #if AP_FILESYSTEM_FILE_WRITING_ENABLED
     225          87 :     if ((_dir_disable & uint16_t(AP_Scripting::SCR_DIR::SCRIPTS)) == 0) {
     226             :         // Only try creating scripts directory if loading from it is enabled
     227          87 :         const char *dir_name = SCRIPTING_DIRECTORY;
     228          87 :         if (AP::FS().mkdir(dir_name)) {
     229          87 :             if (errno != EEXIST) {
     230           0 :                 GCS_SEND_TEXT(MAV_SEVERITY_INFO, "Scripting: failed to create (%s)", dir_name);
     231             :             }
     232             :         }
     233             :     }
     234             : #endif
     235             : 
     236          87 :     AP_HAL::Scheduler::priority_base priority = AP_HAL::Scheduler::PRIORITY_SCRIPTING;
     237             :     static const struct {
     238             :         ThreadPriority scr_priority;
     239             :         AP_HAL::Scheduler::priority_base hal_priority;
     240             :     } priority_map[] = {
     241             :         { ThreadPriority::NORMAL, AP_HAL::Scheduler::PRIORITY_SCRIPTING },
     242             :         { ThreadPriority::IO, AP_HAL::Scheduler::PRIORITY_IO },
     243             :         { ThreadPriority::STORAGE, AP_HAL::Scheduler::PRIORITY_STORAGE },
     244             :         { ThreadPriority::UART, AP_HAL::Scheduler::PRIORITY_UART },
     245             :         { ThreadPriority::I2C, AP_HAL::Scheduler::PRIORITY_I2C },
     246             :         { ThreadPriority::SPI, AP_HAL::Scheduler::PRIORITY_SPI },
     247             :         { ThreadPriority::TIMER, AP_HAL::Scheduler::PRIORITY_TIMER },
     248             :         { ThreadPriority::MAIN, AP_HAL::Scheduler::PRIORITY_MAIN },
     249             :         { ThreadPriority::BOOST, AP_HAL::Scheduler::PRIORITY_BOOST },
     250             :     };
     251         870 :     for (const auto &p : priority_map) {
     252         783 :         if (p.scr_priority == _thd_priority) {
     253          87 :             priority = p.hal_priority;
     254             :         }
     255             :     }
     256             : 
     257          87 :     if (!hal.scheduler->thread_create(FUNCTOR_BIND_MEMBER(&AP_Scripting::thread, void),
     258             :                                       "Scripting", SCRIPTING_STACK_SIZE, priority, 0)) {
     259           0 :         GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "Scripting: %s", "failed to start");
     260           0 :         _thread_failed = true;
     261             :     }
     262             : }
     263             : 
     264             : #if AP_SCRIPTING_SERIALDEVICE_ENABLED
     265        2094 : void AP_Scripting::init_serialdevice_ports(void) {
     266        2094 :     if (!_enable) {
     267        2007 :         return;
     268             :     }
     269             : 
     270          87 :     _serialdevice.init();
     271             : }
     272             : #endif
     273             : 
     274             : #if HAL_GCS_ENABLED
     275          10 : MAV_RESULT AP_Scripting::handle_command_int_packet(const mavlink_command_int_t &packet) {
     276          10 :     switch ((SCRIPTING_CMD)packet.param1) {
     277           0 :         case SCRIPTING_CMD_REPL_START:
     278             :         case SCRIPTING_CMD_REPL_STOP:
     279           0 :             return MAV_RESULT_DENIED;
     280             : 
     281           0 :         case SCRIPTING_CMD_STOP:
     282           0 :             _restart = false;
     283           0 :             _stop = true;
     284           0 :             return MAV_RESULT_ACCEPTED;
     285          10 :         case SCRIPTING_CMD_STOP_AND_RESTART:
     286          10 :             _restart = true;
     287          10 :             _stop = true;
     288          10 :             return MAV_RESULT_ACCEPTED;
     289           0 :         case SCRIPTING_CMD_ENUM_END: // cope with MAVLink generator appending to our enum
     290           0 :             break;
     291             :     }
     292             : 
     293           0 :     return MAV_RESULT_UNSUPPORTED;
     294             : }
     295             : #endif
     296             : 
     297          97 : void AP_Scripting::thread(void) {
     298             :     while (true) {
     299             :         // reset flags
     300          97 :         _stop = false;
     301          97 :         _restart = false;
     302          97 :         _init_failed = false;
     303             : 
     304          97 :         lua_scripts *lua = NEW_NOTHROW lua_scripts(_script_vm_exec_count, _script_heap_size, _debug_options);
     305          97 :         if (lua == nullptr || !lua->heap_allocated()) {
     306           0 :             GCS_SEND_TEXT(MAV_SEVERITY_CRITICAL, "Scripting: %s", "Unable to allocate memory");
     307           0 :             _init_failed = true;
     308             :         } else {
     309             : #if AP_SCRIPTING_SERIALDEVICE_ENABLED
     310             :             // clear data in serial buffers that the script wasn't ready to
     311             :             // receive
     312          97 :             _serialdevice.clear();
     313             : #endif
     314             : #if AP_ARMING_ENABLED && AP_ARMING_AUX_AUTH_ENABLED
     315             :             // Clear any dangling pre-arms from previous script loads
     316          97 :             AP_Arming::get_singleton()->reset_all_aux_auths();
     317             : #endif
     318             :             // run won't return while scripting is still active
     319          97 :             lua->run();
     320             : 
     321             :             // only reachable if the lua backend has died for any reason
     322          56 :             GCS_SEND_TEXT(MAV_SEVERITY_CRITICAL, "Scripting: %s", "stopped");
     323             :         }
     324          56 :         delete lua;
     325          56 :         lua = nullptr;
     326             : 
     327             :         // clear allocated i2c devices
     328         280 :         for (uint8_t i=0; i<SCRIPTING_MAX_NUM_I2C_DEVICE; i++) {
     329         224 :             delete _i2c_dev[i];
     330         224 :             _i2c_dev[i] = nullptr;
     331             :         }
     332          56 :         num_i2c_devices = 0;
     333             : 
     334             :         // clear allocated PWM sources
     335         280 :         for (uint8_t i=0; i<SCRIPTING_MAX_NUM_PWM_SOURCE; i++) {
     336         224 :             if (_pwm_source[i] != nullptr) {
     337           0 :                 delete _pwm_source[i];
     338           0 :                 _pwm_source[i] = nullptr;
     339             :             }
     340             :         }
     341          56 :         num_pwm_source = 0;
     342             : 
     343             : #if AP_NETWORKING_ENABLED
     344             :         // clear allocated sockets
     345        2856 :         for (uint8_t i=0; i<SCRIPTING_MAX_NUM_NET_SOCKET; i++) {
     346        2800 :             if (_net_sockets[i] != nullptr) {
     347           2 :                 delete _net_sockets[i];
     348           2 :                 _net_sockets[i] = nullptr;
     349             :             }
     350             :         }
     351             : #endif // AP_NETWORKING_ENABLED
     352             : 
     353             : #if AP_SCRIPTING_SERIALDEVICE_ENABLED
     354             :         // clear data in serial buffers that hasn't been transmitted
     355          56 :         _serialdevice.clear();
     356             : #endif
     357             : 
     358             : #if AP_CRSF_SCRIPTING_ENABLED
     359          56 :         AP::crsf_telem()->clear_menus();
     360             : #endif // AP_CRSF_SCRIPTING_ENABLED
     361             :         
     362             :         // Clear blocked commands
     363             :         {
     364          56 :             WITH_SEMAPHORE(mavlink_command_block_list_sem);
     365          56 :             while (mavlink_command_block_list != nullptr) {
     366           0 :                 command_block_list *next_item = mavlink_command_block_list->next;
     367           0 :                 delete mavlink_command_block_list;
     368           0 :                 mavlink_command_block_list = next_item;
     369             :             }
     370          56 :         }
     371             : 
     372          56 :         bool cleared = false;
     373             :         while(true) {
     374             :             // 1hz check if we should restart
     375         251 :             hal.scheduler->delay(1000);
     376         205 :             if (!enabled()) {
     377             :                 // enable must be put to 0 and back to 1 to restart from params
     378         195 :                 cleared = true;
     379         195 :                 continue;
     380             :             }
     381             :             // must be enabled to get this far
     382          10 :             if (cleared || _restart) {
     383          10 :                 GCS_SEND_TEXT(MAV_SEVERITY_CRITICAL, "Scripting: %s", "restarted");
     384          10 :                 break;
     385             :             }
     386           0 :             if (option_is_set(DebugOption::NO_SCRIPTS_TO_RUN)) {
     387           0 :                 GCS_SEND_TEXT(MAV_SEVERITY_DEBUG, "Scripting: %s", "stopped");
     388             :             }
     389             :         }
     390          10 :     }
     391             : }
     392             : 
     393           0 : void AP_Scripting::handle_mission_command(const AP_Mission::Mission_Command& cmd_in)
     394             : {
     395             : #if AP_MISSION_ENABLED
     396           0 :     if (!_enable) {
     397           0 :         return;
     398             :     }
     399             : 
     400           0 :     if (mission_data == nullptr) {
     401             :         // load buffer
     402           0 :         mission_data = NEW_NOTHROW ObjectBuffer<struct AP_Scripting::scripting_mission_cmd>(mission_cmd_queue_size);
     403           0 :         if (mission_data != nullptr && mission_data->get_size() == 0) {
     404           0 :             delete mission_data;
     405           0 :             mission_data = nullptr;
     406             :         }
     407           0 :         if (mission_data == nullptr) {
     408           0 :             GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "Scripting: %s", "unable to receive mission command");
     409           0 :             return;
     410             :         }
     411             :     }
     412             : 
     413           0 :     struct scripting_mission_cmd cmd {cmd_in.p1,
     414           0 :                                       cmd_in.content.scripting.p1,
     415           0 :                                       cmd_in.content.scripting.p2,
     416           0 :                                       cmd_in.content.scripting.p3,
     417           0 :                                       AP_HAL::millis()};
     418             : 
     419           0 :     mission_data->push(cmd);
     420             : #endif
     421             : }
     422             : 
     423       66607 : bool AP_Scripting::arming_checks(size_t buflen, char *buffer) const
     424             : {
     425       66607 :     if (!enabled() || option_is_set(DebugOption::DISABLE_PRE_ARM)) {
     426       62538 :         return true;
     427             :     }
     428             : 
     429        4069 :     if (_thread_failed) {
     430           0 :         hal.util->snprintf(buffer, buflen, "Scripting: %s", "failed to start");
     431           0 :         return false;
     432             :     }
     433             : 
     434        4069 :     if (_init_failed) {
     435           0 :         hal.util->snprintf(buffer, buflen, "Scripting: %s", "out of memory");
     436           0 :         return false;
     437             :     }
     438             : 
     439        4069 :     lua_scripts::get_last_error_semaphore()->take_blocking();
     440        4069 :     const char *error_buf = lua_scripts::get_last_error_message();
     441        4069 :     if (error_buf != nullptr) {
     442          48 :         hal.util->snprintf(buffer, buflen, "Scripting: %s", error_buf);
     443          48 :         lua_scripts::get_last_error_semaphore()->give();
     444          48 :         return false;
     445             :     }
     446        4021 :     lua_scripts::get_last_error_semaphore()->give();
     447             : 
     448             :     // Use -1 for disabled, this means we don't have to avoid 0 in the CRC, the sign bit is masked off anyway
     449        4021 :     if (_required_loaded_checksum != -1) {
     450           0 :         const uint32_t expected_loaded = (uint32_t)_required_loaded_checksum.get() & checksum_param_mask;
     451           0 :         const uint32_t loaded = lua_scripts::get_loaded_checksum() & checksum_param_mask;
     452           0 :         if (expected_loaded != loaded) {
     453           0 :             hal.util->snprintf(buffer, buflen, "Scripting: loaded CRC incorrect want: 0x%x", (unsigned int)loaded);
     454           0 :             return false;
     455             :         }
     456             :     }
     457             : 
     458        4021 :     if (_required_running_checksum != -1) {
     459           0 :         const uint32_t expected_running = (uint32_t)_required_running_checksum.get() & checksum_param_mask;
     460           0 :         const uint32_t running = lua_scripts::get_running_checksum() & checksum_param_mask;
     461           0 :         if (expected_running != running) {
     462           0 :             hal.util->snprintf(buffer, buflen, "Scripting: running CRC incorrect want: 0x%x", (unsigned int)running);
     463           0 :             return false;
     464             :         }
     465             :     }
     466             : 
     467        4021 :     return true;
     468             : }
     469             : 
     470           0 : void AP_Scripting::restart_all()
     471             : {
     472           0 :     _restart = true;
     473           0 :     _stop = true;
     474           0 : }
     475             : 
     476             : #if HAL_GCS_ENABLED
     477     2784435 : void AP_Scripting::handle_message(const mavlink_message_t &msg, const mavlink_channel_t chan) {
     478     2784435 :     if (mavlink_data.rx_buffer == nullptr) {
     479     2780636 :         return;
     480             :     }
     481             : 
     482        3841 :     struct mavlink_msg data {msg, chan, AP_HAL::millis()};
     483             : 
     484        3841 :     WITH_SEMAPHORE(mavlink_data.sem);
     485        7640 :     for (uint16_t i = 0; i < mavlink_data.accept_msg_ids_size; i++) {
     486        3841 :         if (mavlink_data.accept_msg_ids[i] == UINT32_MAX) {
     487           0 :             return;
     488             :         }
     489        3841 :         if (mavlink_data.accept_msg_ids[i] == msg.msgid) {
     490          42 :             mavlink_data.rx_buffer->push(data);
     491          42 :             return;
     492             :         }
     493             :     }
     494        3841 : }
     495             : 
     496      531154 : bool AP_Scripting::is_handling_command(uint16_t cmd_id)
     497             : {
     498      531154 :     WITH_SEMAPHORE(mavlink_command_block_list_sem);
     499             : 
     500             :     // Look in linked list to see if id is registered
     501      531154 :     if (mavlink_command_block_list != nullptr) {
     502           0 :         for (command_block_list *item = mavlink_command_block_list; item; item = item->next) {
     503           0 :             if (item->id == cmd_id) {
     504           0 :                 return true;
     505             :             }
     506             :         }
     507             :     }
     508             : 
     509      531154 :     return false;
     510      531154 : }
     511             : #endif // HAL_GCS_ENABLED
     512             : 
     513             : // Update called at 1Hz from AP_Vehicle
     514      149217 : void AP_Scripting::update() {
     515             : 
     516      149217 :     save_checksum();
     517             : 
     518      149217 : }
     519             : 
     520             : // Check if DEBUG_OPTS bit has been set to save current checksum values to params
     521      149217 : void AP_Scripting::save_checksum() {
     522             : 
     523      149217 :     if (!option_is_set(DebugOption::SAVE_CHECKSUM)) {
     524             :         // Bit not set, nothing to do
     525      149217 :         return;
     526             :     }
     527             : 
     528             :     // Save two checksum parameters to there current values
     529           0 :     _required_loaded_checksum.set_and_save(lua_scripts::get_loaded_checksum() & checksum_param_mask);
     530           0 :     _required_running_checksum.set_and_save(lua_scripts::get_running_checksum() & checksum_param_mask);
     531             : 
     532             :     // Un-set debug option bit
     533           0 :     option_clear(DebugOption::SAVE_CHECKSUM);
     534             : 
     535           0 :     GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "Scripting: %s", "saved checksums");
     536             : 
     537             : }
     538             : 
     539             : AP_Scripting *AP_Scripting::_singleton = nullptr;
     540             : 
     541             : namespace AP {
     542       95360 :     AP_Scripting *scripting() {
     543       95360 :         return AP_Scripting::get_singleton();
     544             :     }
     545             : }
     546             : 
     547             : #endif  // AP_SCRIPTING_ENABLED

Generated by: LCOV version 1.14