From f10b94b6f000251c8b3428e38f8ae5607c4dcb63 Mon Sep 17 00:00:00 2001 From: Andrey Parfenov Date: Fri, 24 Apr 2026 20:09:05 +0700 Subject: [PATCH 1/5] codex: bug fixes and cleanup Signed-off-by: Andrey Parfenov --- cpp_package/src/board_shim.cpp | 12 +++-- .../brainflow/board_controller_library.cs | 40 +++++++------- .../brainflow/brainflow/board_shim.cs | 8 +-- .../src/main/java/brainflow/BoardShim.java | 19 +++---- matlab_package/brainflow/BoardShim.m | 16 ++++-- nodejs_package/brainflow/board_shim.ts | 15 +++--- nodejs_package/brainflow/functions.types.ts | 14 +++-- python_package/brainflow/board_shim.py | 23 +++++--- rust_package/brainflow/src/board_shim.rs | 27 ++++++++-- .../brainflow/src/ffi/board_controller.rs | 4 ++ src/board_controller/board_controller.cpp | 32 ++++++++++-- src/board_controller/board_info_getter.cpp | 52 ++++++++++++++----- src/board_controller/inc/board_controller.h | 3 +- src/board_controller/inc/board_info_getter.h | 6 +-- .../inc/playback_file_board.h | 1 + src/board_controller/playback_file_board.cpp | 36 +++++++++++++ src/board_controller/synthetic_board.cpp | 2 +- src/ml/onnx/onnx_classifier.cpp | 6 +-- 18 files changed, 225 insertions(+), 91 deletions(-) diff --git a/cpp_package/src/board_shim.cpp b/cpp_package/src/board_shim.cpp index 3ec1fc74c..1581195df 100644 --- a/cpp_package/src/board_shim.cpp +++ b/cpp_package/src/board_shim.cpp @@ -235,7 +235,8 @@ std::string BoardShim::config_board (std::string config) int response_len = 0; char response[8192]; int res = ::config_board ( - config.c_str (), response, &response_len, board_id, serialized_params.c_str ()); + config.c_str (), response, &response_len, sizeof (response), board_id, + serialized_params.c_str ()); if (res != (int)BrainFlowExitCodes::STATUS_OK) { throw BrainFlowException ("failed to config board", res); @@ -289,7 +290,8 @@ json BoardShim::get_board_descr (int board_id, int preset) { char board_descr_str[16000]; int string_len = 0; - int res = ::get_board_descr (board_id, preset, board_descr_str, &string_len); + int res = + ::get_board_descr (board_id, preset, board_descr_str, &string_len, sizeof (board_descr_str)); if (res != (int)BrainFlowExitCodes::STATUS_OK) { throw BrainFlowException ("failed to get board info", res); @@ -368,7 +370,7 @@ std::vector BoardShim::get_eeg_names (int board_id, int preset) { char eeg_names[4096]; int string_len = 0; - int res = ::get_eeg_names (board_id, preset, eeg_names, &string_len); + int res = ::get_eeg_names (board_id, preset, eeg_names, &string_len, sizeof (eeg_names)); if (res != (int)BrainFlowExitCodes::STATUS_OK) { throw BrainFlowException ("failed to get board info", res); @@ -401,7 +403,7 @@ std::string BoardShim::get_device_name (int board_id, int preset) { char name[4096]; int string_len = 0; - int res = ::get_device_name (board_id, preset, name, &string_len); + int res = ::get_device_name (board_id, preset, name, &string_len, sizeof (name)); if (res != (int)BrainFlowExitCodes::STATUS_OK) { throw BrainFlowException ("failed to get board info", res); @@ -602,4 +604,4 @@ std::string BoardShim::get_version () std::string verion_str (version, string_len); return verion_str; -} \ No newline at end of file +} diff --git a/csharp_package/brainflow/brainflow/board_controller_library.cs b/csharp_package/brainflow/brainflow/board_controller_library.cs index c363db037..9854e5c0e 100644 --- a/csharp_package/brainflow/brainflow/board_controller_library.cs +++ b/csharp_package/brainflow/brainflow/board_controller_library.cs @@ -151,7 +151,7 @@ public static class BoardControllerLibrary64 [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int log_message_board_controller (int log_level, string message); [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - public static extern int config_board (string config, byte[] response, int[] len, int board_id, string input_json); + public static extern int config_board (string config, byte[] response, int[] len, int max_len, int board_id, string input_json); [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int config_board_with_bytes (byte[] bytes, int len, int board_id, string input_json); [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] @@ -195,7 +195,7 @@ public static class BoardControllerLibrary64 [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int is_prepared (int[] prepared, int board_id, string input_json); [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - public static extern int get_eeg_names (int board_id, int preset, byte[] eeg_names, int[] len); + public static extern int get_eeg_names (int board_id, int preset, byte[] eeg_names, int[] len, int max_len); [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int get_resistance_channels (int board_id, int preset, int[] channels, int[] len); [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] @@ -203,11 +203,11 @@ public static class BoardControllerLibrary64 [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int get_exg_channels (int board_id, int preset, int[] channels, int[] len); [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - public static extern int get_device_name (int board_id, int preset, byte[] name, int[] len); + public static extern int get_device_name (int board_id, int preset, byte[] name, int[] len, int max_len); [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int insert_marker (double value, int preset, int board_id, string input_json); [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - public static extern int get_board_descr (int board_id, int preset, byte[] board_descr, int[] len); + public static extern int get_board_descr (int board_id, int preset, byte[] board_descr, int[] len, int max_len); [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int release_all_sessions (); [DllImport ("BoardController", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] @@ -241,7 +241,7 @@ public static class BoardControllerLibrary32 [DllImport ("BoardController32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int log_message_board_controller (int log_level, string message); [DllImport ("BoardController32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - public static extern int config_board (string config, byte[] response, int[] len, int board_id, string input_json); + public static extern int config_board (string config, byte[] response, int[] len, int max_len, int board_id, string input_json); [DllImport ("BoardController32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int config_board_with_bytes (byte[] bytes, int len, int board_id, string input_json); [DllImport ("BoardController32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] @@ -285,17 +285,17 @@ public static class BoardControllerLibrary32 [DllImport ("BoardController32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int is_prepared (int[] prepared, int board_id, string input_json); [DllImport ("BoardController32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - public static extern int get_eeg_names (int board_id, int preset, byte[] eeg_names, int[] len); + public static extern int get_eeg_names (int board_id, int preset, byte[] eeg_names, int[] len, int max_len); [DllImport ("BoardController32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int get_resistance_channels (int board_id, int preset, int[] channels, int[] len); [DllImport ("BoardController32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int get_exg_channels (int board_id, int preset, int[] channels, int[] len); [DllImport ("BoardController32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - public static extern int get_device_name (int board_id, int preset, byte[] name, int[] len); + public static extern int get_device_name (int board_id, int preset, byte[] name, int[] len, int max_len); [DllImport ("BoardController32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int insert_marker (double value, int preset, int board_id, string input_json); [DllImport ("BoardController32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - public static extern int get_board_descr (int board_id, int preset, byte[] board_descr, int[] len); + public static extern int get_board_descr (int board_id, int preset, byte[] board_descr, int[] len, int max_len); [DllImport ("BoardController32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int release_all_sessions (); [DllImport ("BoardController32", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] @@ -457,14 +457,14 @@ public static int insert_marker (double value, int preset, int board_id, string } - public static int config_board (string config, byte[] str, int[] len, int board_id, string input_json) + public static int config_board (string config, byte[] str, int[] len, int max_len, int board_id, string input_json) { switch (PlatformHelper.get_library_environment ()) { case LibraryEnvironment.x64: - return BoardControllerLibrary64.config_board (config, str, len, board_id, input_json); + return BoardControllerLibrary64.config_board (config, str, len, max_len, board_id, input_json); case LibraryEnvironment.x86: - return BoardControllerLibrary32.config_board (config, str, len, board_id, input_json); + return BoardControllerLibrary32.config_board (config, str, len, max_len, board_id, input_json); } return (int)BrainFlowExitCodes.GENERAL_ERROR; @@ -600,14 +600,14 @@ public static int get_marker_channel (int board_id, int preset, int[] marker_cha return (int)BrainFlowExitCodes.GENERAL_ERROR; } - public static int get_eeg_names (int board_id, int preset, byte[] names, int[] len) + public static int get_eeg_names (int board_id, int preset, byte[] names, int[] len, int max_len) { switch (PlatformHelper.get_library_environment ()) { case LibraryEnvironment.x64: - return BoardControllerLibrary64.get_eeg_names (board_id, preset, names, len); + return BoardControllerLibrary64.get_eeg_names (board_id, preset, names, len, max_len); case LibraryEnvironment.x86: - return BoardControllerLibrary32.get_eeg_names (board_id, preset, names, len); + return BoardControllerLibrary32.get_eeg_names (board_id, preset, names, len, max_len); } return (int)BrainFlowExitCodes.GENERAL_ERROR; @@ -626,27 +626,27 @@ public static int get_board_presets (int board_id, int[] names, int[] len) return (int)BrainFlowExitCodes.GENERAL_ERROR; } - public static int get_board_descr (int board_id, int preset, byte[] descr, int[] len) + public static int get_board_descr (int board_id, int preset, byte[] descr, int[] len, int max_len) { switch (PlatformHelper.get_library_environment ()) { case LibraryEnvironment.x64: - return BoardControllerLibrary64.get_board_descr (board_id, preset, descr, len); + return BoardControllerLibrary64.get_board_descr (board_id, preset, descr, len, max_len); case LibraryEnvironment.x86: - return BoardControllerLibrary32.get_board_descr (board_id, preset, descr, len); + return BoardControllerLibrary32.get_board_descr (board_id, preset, descr, len, max_len); } return (int)BrainFlowExitCodes.GENERAL_ERROR; } - public static int get_device_name (int board_id, int preset, byte[] name, int[] len) + public static int get_device_name (int board_id, int preset, byte[] name, int[] len, int max_len) { switch (PlatformHelper.get_library_environment ()) { case LibraryEnvironment.x64: - return BoardControllerLibrary64.get_device_name (board_id, preset, name, len); + return BoardControllerLibrary64.get_device_name (board_id, preset, name, len, max_len); case LibraryEnvironment.x86: - return BoardControllerLibrary32.get_device_name (board_id, preset, name, len); + return BoardControllerLibrary32.get_device_name (board_id, preset, name, len, max_len); } return (int)BrainFlowExitCodes.GENERAL_ERROR; diff --git a/csharp_package/brainflow/brainflow/board_shim.cs b/csharp_package/brainflow/brainflow/board_shim.cs index 24211f8f3..47191e7d7 100644 --- a/csharp_package/brainflow/brainflow/board_shim.cs +++ b/csharp_package/brainflow/brainflow/board_shim.cs @@ -179,7 +179,7 @@ public static string[] get_eeg_names (int board_id, int preset = (int)BrainFlowP { int[] len = new int[1]; byte[] str = new byte[4096]; - int res = BoardControllerLibrary.get_eeg_names (board_id, preset, str, len); + int res = BoardControllerLibrary.get_eeg_names (board_id, preset, str, len, str.Length); if (res != (int)BrainFlowExitCodes.STATUS_OK) { throw new BrainFlowError (res); @@ -222,7 +222,7 @@ public static T get_board_descr (int board_id, int preset = (int)BrainFlowPre { int[] len = new int[1]; byte[] str = new byte[16000]; - int res = BoardControllerLibrary.get_board_descr (board_id, preset, str, len); + int res = BoardControllerLibrary.get_board_descr (board_id, preset, str, len, str.Length); if (res != (int)BrainFlowExitCodes.STATUS_OK) { throw new BrainFlowError (res); @@ -246,7 +246,7 @@ public static string get_device_name (int board_id, int preset = (int)BrainFlowP { int[] len = new int[1]; byte[] str = new byte[4096]; - int res = BoardControllerLibrary.get_device_name (board_id, preset, str, len); + int res = BoardControllerLibrary.get_device_name (board_id, preset, str, len, str.Length); if (res != (int)BrainFlowExitCodes.STATUS_OK) { throw new BrainFlowError (res); @@ -717,7 +717,7 @@ public string config_board (string config) { int[] len = new int[1]; byte[] str = new byte[4096]; - int res = BoardControllerLibrary.config_board (config, str, len, board_id, input_json); + int res = BoardControllerLibrary.config_board (config, str, len, str.Length, board_id, input_json); if (res != (int)BrainFlowExitCodes.STATUS_OK) { throw new BrainFlowError (res); diff --git a/java_package/brainflow/src/main/java/brainflow/BoardShim.java b/java_package/brainflow/src/main/java/brainflow/BoardShim.java index 7603178ae..bc02522a5 100644 --- a/java_package/brainflow/src/main/java/brainflow/BoardShim.java +++ b/java_package/brainflow/src/main/java/brainflow/BoardShim.java @@ -23,7 +23,8 @@ private interface DllInterface extends Library { int prepare_session (int board_id, String params); - int config_board (String config, byte[] names, int[] len, int board_id, String params); + int config_board ( + String config, byte[] names, int[] len, int max_len, int board_id, String params); int config_board_with_bytes (byte[] bytes, int len, int board_id, String params); @@ -100,11 +101,11 @@ int get_current_board_data (int num_samples, int preset, double[] data_buf, int[ int is_prepared (int[] prepared, int board_id, String params); - int get_eeg_names (int board_id, int preset, byte[] names, int[] len); + int get_eeg_names (int board_id, int preset, byte[] names, int[] len, int max_len); - int get_board_descr (int board_id, int preset, byte[] names, int[] len); + int get_board_descr (int board_id, int preset, byte[] names, int[] len, int max_len); - int get_device_name (int board_id, int preset, byte[] name, int[] len); + int get_device_name (int board_id, int preset, byte[] name, int[] len, int max_len); int get_board_presets (int board_id, int[] presets, int[] len); @@ -509,7 +510,7 @@ public static String[] get_eeg_names (int board_id, BrainFlowPresets preset) thr { int[] len = new int[1]; byte[] str = new byte[4096]; - int ec = instance.get_eeg_names (board_id, preset.get_code (), str, len); + int ec = instance.get_eeg_names (board_id, preset.get_code (), str, len, str.length); if (ec != BrainFlowExitCode.STATUS_OK.get_code ()) { throw new BrainFlowError ("Error in board info getter", ec); @@ -574,7 +575,7 @@ public static T get_board_descr (Class type, int board_id, BrainFlowPrese { int[] len = new int[1]; byte[] str = new byte[16000]; - int ec = instance.get_board_descr (board_id, preset.get_code (), str, len); + int ec = instance.get_board_descr (board_id, preset.get_code (), str, len, str.length); if (ec != BrainFlowExitCode.STATUS_OK.get_code ()) { throw new BrainFlowError ("Error in board info getter", ec); @@ -617,7 +618,7 @@ public static String get_device_name (int board_id, BrainFlowPresets preset) thr { int[] len = new int[1]; byte[] str = new byte[4096]; - int ec = instance.get_device_name (board_id, preset.get_code (), str, len); + int ec = instance.get_device_name (board_id, preset.get_code (), str, len, str.length); if (ec != BrainFlowExitCode.STATUS_OK.get_code ()) { throw new BrainFlowError ("Error in board info getter", ec); @@ -1217,7 +1218,7 @@ public static int[] get_gyro_channels (int board_id, BrainFlowPresets preset) th */ public static int[] get_gyro_channels (int board_id) throws BrainFlowError { - return get_gyro_channels (board_id); + return get_gyro_channels (board_id, BrainFlowPresets.DEFAULT_PRESET); } /** @@ -1410,7 +1411,7 @@ public String config_board (String config) throws BrainFlowError { int[] len = new int[1]; byte[] str = new byte[4096]; - int ec = instance.config_board (config, str, len, board_id, input_json); + int ec = instance.config_board (config, str, len, str.length, board_id, input_json); if (ec != BrainFlowExitCode.STATUS_OK.get_code ()) { throw new BrainFlowError ("Error in config_board", ec); diff --git a/matlab_package/brainflow/BoardShim.m b/matlab_package/brainflow/BoardShim.m index 248e2aba3..629f878ec 100644 --- a/matlab_package/brainflow/BoardShim.m +++ b/matlab_package/brainflow/BoardShim.m @@ -147,10 +147,12 @@ function log_message(log_level, message) % get board descr for provided board id task_name = 'get_board_descr'; lib_name = BoardShim.load_lib(); + str_len = libpointer('int32Ptr', 0); % no way to understand how it works in matlab, used this link % https://nl.mathworks.com/matlabcentral/answers/131446-what-data-type-do-i-need-to-calllib-with-pointer-argument-char% - [exit_code, board_descr] = calllib(lib_name, task_name, board_id, preset, blanks(16000), 16000); + [exit_code, board_descr] = calllib(lib_name, task_name, board_id, preset, blanks(16000), str_len, 16000); BoardShim.check_ec(exit_code, task_name); + board_descr = extractBefore(board_descr, str_len.Value + 1); board_descr = jsondecode(board_descr); end @@ -158,10 +160,12 @@ function log_message(log_level, message) % get eeg names for provided board id task_name = 'get_eeg_names'; lib_name = BoardShim.load_lib(); + str_len = libpointer('int32Ptr', 0); % no way to understand how it works in matlab, used this link % https://nl.mathworks.com/matlabcentral/answers/131446-what-data-type-do-i-need-to-calllib-with-pointer-argument-char% - [exit_code, eeg_names] = calllib(lib_name, task_name, board_id, preset, blanks(4096), 4096); + [exit_code, eeg_names] = calllib(lib_name, task_name, board_id, preset, blanks(4096), str_len, 4096); BoardShim.check_ec(exit_code, task_name); + eeg_names = extractBefore(eeg_names, str_len.Value + 1); eeg_names = split(eeg_names, ','); end @@ -191,10 +195,12 @@ function log_message(log_level, message) % get device name for provided board id task_name = 'get_device_name'; lib_name = BoardShim.load_lib(); + str_len = libpointer('int32Ptr', 0); % no way to understand how it works in matlab used this link % https://nl.mathworks.com/matlabcentral/answers/131446-what-data-type-do-i-need-to-calllib-with-pointer-argument-char% - [exit_code, device_name] = calllib(lib_name, task_name, board_id, preset, blanks(4096), 4096); + [exit_code, device_name] = calllib(lib_name, task_name, board_id, preset, blanks(4096), str_len, 4096); BoardShim.check_ec(exit_code, task_name); + device_name = extractBefore(device_name, str_len.Value + 1); end function eeg_channels = get_eeg_channels(board_id, preset) @@ -380,10 +386,12 @@ function prepare_session(obj) % send string to the board task_name = 'config_board'; lib_name = BoardShim.load_lib(); + str_len = libpointer('int32Ptr', 0); % no way to understand how it works in matlab used this link % https://nl.mathworks.com/matlabcentral/answers/131446-what-data-type-do-i-need-to-calllib-with-pointer-argument-char% - [exit_code, tmp, response] = calllib(lib_name, task_name, config, blanks(4096), 4096, obj.board_id, obj.input_params_json); + [exit_code, tmp, response] = calllib(lib_name, task_name, config, blanks(4096), str_len, 4096, obj.board_id, obj.input_params_json); BoardShim.check_ec(exit_code, task_name); + response = extractBefore(response, str_len.Value + 1); end function config_board_with_bytes(obj, bytes) diff --git a/nodejs_package/brainflow/board_shim.ts b/nodejs_package/brainflow/board_shim.ts index 2a94e924e..1ac7ba63c 100644 --- a/nodejs_package/brainflow/board_shim.ts +++ b/nodejs_package/brainflow/board_shim.ts @@ -279,7 +279,7 @@ export class BoardShim const len = [0]; let out = ['\0'.repeat(4096)]; const res = BoardControllerDLL.getInstance().configBoard( - config, out, len, this.boardId, this.inputJson); + config, out, len, out[0].length, this.boardId, this.inputJson); if (res !== BrainFlowExitCodes.STATUS_OK) { throw new BrainFlowError (res, 'Could not config board'); @@ -674,8 +674,9 @@ export class BoardShim public static getDeviceName(boardId: BoardIds, preset = BrainFlowPresets.DEFAULT_PRESET): string { const len = [0]; - let out = ['\0'.repeat(512)]; - const res = BoardControllerDLL.getInstance().getDeviceName(boardId, preset, out, len); + let out = ['\0'.repeat(4096)]; + const res = + BoardControllerDLL.getInstance().getDeviceName(boardId, preset, out, len, out[0].length); if (res !== BrainFlowExitCodes.STATUS_OK) { throw new BrainFlowError (res, 'Could not get device info'); @@ -687,7 +688,8 @@ export class BoardShim { const len = [0]; let out = ['\0'.repeat(4096)]; - const res = BoardControllerDLL.getInstance().getEegNames(boardId, preset, out, len); + const res = + BoardControllerDLL.getInstance().getEegNames(boardId, preset, out, len, out[0].length); if (res !== BrainFlowExitCodes.STATUS_OK) { throw new BrainFlowError (res, 'Could not get device info'); @@ -698,8 +700,9 @@ export class BoardShim public static getBoardDescr(boardId: BoardIds, preset = BrainFlowPresets.DEFAULT_PRESET): Object { const len = [0]; - let out = ['\0'.repeat(4096)]; - const res = BoardControllerDLL.getInstance().getBoardDescr(boardId, preset, out, len); + let out = ['\0'.repeat(16000)]; + const res = + BoardControllerDLL.getInstance().getBoardDescr(boardId, preset, out, len, out[0].length); if (res !== BrainFlowExitCodes.STATUS_OK) { throw new BrainFlowError (res, 'Could not get device info'); diff --git a/nodejs_package/brainflow/functions.types.ts b/nodejs_package/brainflow/functions.types.ts index 7d171cc1d..7c60ead29 100644 --- a/nodejs_package/brainflow/functions.types.ts +++ b/nodejs_package/brainflow/functions.types.ts @@ -32,7 +32,7 @@ export enum BoardControllerCLikeFunctions { add_streamer = 'int add_streamer (const char *streamer, int preset, int board_id, const char *json_brainflow_input_params)', config_board = - 'int config_board (const char *config, _Inout_ char *response, _Inout_ int *resp_len, int board_id, const char *json_brainflow_input_params)', + 'int config_board (const char *config, _Inout_ char *response, _Inout_ int *resp_len, int response_max_len, int board_id, const char *json_brainflow_input_params)', config_board_with_bytes = 'int config_board_with_bytes (const char *bytes, int len, int board_id, const char *json_brainflow_input_params)', delete_streamer = @@ -88,11 +88,11 @@ export enum BoardControllerCLikeFunctions { get_rotation_channels = 'int get_rotation_channels (int board_id, int preset, _Inout_ int *channels, _Inout_ int *len)', get_eeg_names = - 'int get_eeg_names (int board_id, int preset, _Inout_ char *eeg_names, _Inout_ int *len)', + 'int get_eeg_names (int board_id, int preset, _Inout_ char *eeg_names, _Inout_ int *len, int max_len)', get_device_name = - 'int get_device_name (int board_id, int preset, _Inout_ char *device_name, _Inout_ int *len)', + 'int get_device_name (int board_id, int preset, _Inout_ char *device_name, _Inout_ int *len, int max_len)', get_board_descr = - 'int get_board_descr (int board_id, int preset, _Inout_ char *descr, _Inout_ int *len)', + 'int get_board_descr (int board_id, int preset, _Inout_ char *descr, _Inout_ int *len, int max_len)', get_board_presets = 'int get_board_presets (int board_id, _Inout_ int *presets, _Inout_ int *len)', } @@ -138,6 +138,7 @@ export class BoardControllerFunctions config: string, response: string[], responseLen: number[], + responseMaxLen: number, boardId: BoardIds, inputJson: string, ) => BrainFlowExitCodes; @@ -276,12 +277,14 @@ export class BoardControllerFunctions preset: BrainFlowPresets, names: string[], len: number[], + maxLen: number, ) => BrainFlowExitCodes; getDeviceName!: ( boardId: BoardIds, preset: BrainFlowPresets, name: string[], len: number[], + maxLen: number, ) => BrainFlowExitCodes; getBoardPresets!: ( boardId: BoardIds, @@ -293,6 +296,7 @@ export class BoardControllerFunctions preset: BrainFlowPresets, descr: string[], len: number[], + maxLen: number, ) => BrainFlowExitCodes; } @@ -471,4 +475,4 @@ export class MLModuleFunctions inputJson: string) => BrainFlowExitCodes; releaseAll!: () => BrainFlowExitCodes; release!: (inputJson: string) => BrainFlowExitCodes; -} \ No newline at end of file +} diff --git a/python_package/brainflow/board_shim.py b/python_package/brainflow/board_shim.py index faf57da7e..0bcdbf110 100644 --- a/python_package/brainflow/board_shim.py +++ b/python_package/brainflow/board_shim.py @@ -327,6 +327,7 @@ def __init__(self): ndpointer(ctypes.c_ubyte), ndpointer(ctypes.c_int32), ctypes.c_int, + ctypes.c_int, ctypes.c_char_p ] @@ -393,7 +394,8 @@ def __init__(self): ctypes.c_int, ctypes.c_int, ndpointer(ctypes.c_ubyte), - ndpointer(ctypes.c_int32) + ndpointer(ctypes.c_int32), + ctypes.c_int ] self.get_board_presets = self.lib.get_board_presets @@ -418,7 +420,8 @@ def __init__(self): ctypes.c_int, ctypes.c_int, ndpointer(ctypes.c_ubyte), - ndpointer(ctypes.c_int32) + ndpointer(ctypes.c_int32), + ctypes.c_int ] self.get_device_name = self.lib.get_device_name @@ -427,7 +430,8 @@ def __init__(self): ctypes.c_int, ctypes.c_int, ndpointer(ctypes.c_ubyte), - ndpointer(ctypes.c_int32) + ndpointer(ctypes.c_int32), + ctypes.c_int ] self.get_eeg_channels = self.lib.get_eeg_channels @@ -783,7 +787,8 @@ def get_eeg_names(cls, board_id: int, preset: int = BrainFlowPresets.DEFAULT_PRE string = numpy.zeros(4096).astype(numpy.ubyte) string_len = numpy.zeros(1).astype(numpy.int32) - res = BoardControllerDLL.get_instance().get_eeg_names(board_id, preset, string, string_len) + res = BoardControllerDLL.get_instance().get_eeg_names( + board_id, preset, string, string_len, string.size) if res != BrainFlowExitCodes.STATUS_OK.value: raise BrainFlowError('unable to request info about this board', res) return string.tobytes().decode('utf-8')[0:string_len[0]].split(',') @@ -838,7 +843,8 @@ def get_board_descr(cls, board_id: int, preset: int = BrainFlowPresets.DEFAULT_P string = numpy.zeros(16000).astype(numpy.ubyte) string_len = numpy.zeros(1).astype(numpy.int32) - res = BoardControllerDLL.get_instance().get_board_descr(board_id, preset, string, string_len) + res = BoardControllerDLL.get_instance().get_board_descr( + board_id, preset, string, string_len, string.size) if res != BrainFlowExitCodes.STATUS_OK.value: raise BrainFlowError('unable to request info about this board', res) return json.loads(string.tobytes().decode('utf-8')[0:string_len[0]]) @@ -858,7 +864,8 @@ def get_device_name(cls, board_id: int, preset: int = BrainFlowPresets.DEFAULT_P string = numpy.zeros(4096).astype(numpy.ubyte) string_len = numpy.zeros(1).astype(numpy.int32) - res = BoardControllerDLL.get_instance().get_device_name(board_id, preset, string, string_len) + res = BoardControllerDLL.get_instance().get_device_name( + board_id, preset, string, string_len, string.size) if res != BrainFlowExitCodes.STATUS_OK.value: raise BrainFlowError('unable to request info about this board', res) return string.tobytes().decode('utf-8')[0:string_len[0]] @@ -1405,8 +1412,8 @@ def config_board(self, config) -> str: string = numpy.zeros(4096).astype(numpy.ubyte) string_len = numpy.zeros(1).astype(numpy.int32) - res = BoardControllerDLL.get_instance().config_board(config_string, string, string_len, self.board_id, - self.input_json) + res = BoardControllerDLL.get_instance().config_board( + config_string, string, string_len, string.size, self.board_id, self.input_json) if res != BrainFlowExitCodes.STATUS_OK.value: raise BrainFlowError('unable to config board', res) return string.tobytes().decode('utf-8')[0:string_len[0]] diff --git a/rust_package/brainflow/src/board_shim.rs b/rust_package/brainflow/src/board_shim.rs index 9abf1dec3..87859441b 100644 --- a/rust_package/brainflow/src/board_shim.rs +++ b/rust_package/brainflow/src/board_shim.rs @@ -226,6 +226,7 @@ impl BoardShim { config, result_char_buffer.as_mut_ptr(), &mut response_len, + result_char_buffer.len() as c_int, self.board_id as c_int, self.json_brainflow_input_params.as_ptr(), ); @@ -374,7 +375,13 @@ pub fn get_board_descr(board_id: BoardIds, preset: BrainFlowPresets) -> Result Result Result ::std::os::raw::c_int; } extern "C" { @@ -59,6 +60,7 @@ extern "C" { preset: ::std::os::raw::c_int, eeg_names: *mut ::std::os::raw::c_char, len: *mut ::std::os::raw::c_int, + max_len: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } extern "C" { @@ -187,6 +189,7 @@ extern "C" { preset: ::std::os::raw::c_int, name: *mut ::std::os::raw::c_char, len: *mut ::std::os::raw::c_int, + max_len: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } extern "C" { @@ -254,6 +257,7 @@ extern "C" { config: *const ::std::os::raw::c_char, response: *mut ::std::os::raw::c_char, response_len: *mut ::std::os::raw::c_int, + response_max_len: ::std::os::raw::c_int, board_id: ::std::os::raw::c_int, json_brainflow_input_params: *const ::std::os::raw::c_char, ) -> ::std::os::raw::c_int; diff --git a/src/board_controller/board_controller.cpp b/src/board_controller/board_controller.cpp index 3e52792af..9b27ef4b6 100644 --- a/src/board_controller/board_controller.cpp +++ b/src/board_controller/board_controller.cpp @@ -69,6 +69,8 @@ static int check_board_session (int board_id, const char *json_brainflow_input_p std::pair &key, bool log_error = true); static int string_to_brainflow_input_params ( const char *json_brainflow_input_params, struct BrainFlowInputParams *params); +static int copy_string_to_buffer ( + const std::string &source, char *destination, int *destination_len, int max_len); int prepare_session (int board_id, const char *json_brainflow_input_params) @@ -482,11 +484,12 @@ int java_set_jnienv (JNIEnv *java_jnienv) return (int)BrainFlowExitCodes::STATUS_OK; } -int config_board (const char *config, char *response, int *response_len, int board_id, +int config_board (const char *config, char *response, int *response_len, int response_max_len, + int board_id, const char *json_brainflow_input_params) { std::lock_guard lock (mutex); - if ((config == NULL) || (response == NULL) || (response_len == NULL)) + if ((config == NULL) || (response == NULL) || (response_len == NULL) || (response_max_len < 1)) { return (int)BrainFlowExitCodes::INVALID_ARGUMENTS_ERROR; } @@ -503,8 +506,7 @@ int config_board (const char *config, char *response, int *response_len, int boa res = board_it->second->config_board (conf, resp); if (res == (int)BrainFlowExitCodes::STATUS_OK) { - *response_len = (int)resp.length (); - strcpy (response, resp.c_str ()); + res = copy_string_to_buffer (resp, response, response_len, response_max_len); } return res; } @@ -547,6 +549,28 @@ int add_streamer ( return board_it->second->add_streamer (streamer, preset); } +static int copy_string_to_buffer ( + const std::string &source, char *destination, int *destination_len, int max_len) +{ + if ((destination == NULL) || (destination_len == NULL) || (max_len < 1)) + { + return (int)BrainFlowExitCodes::INVALID_ARGUMENTS_ERROR; + } + + *destination_len = (int)source.size (); + if (((int)source.size () + 1) > max_len) + { + destination[0] = '\0'; + Board::board_logger->error ( + "provided output buffer is too small, required {}, got {}", source.size () + 1, + max_len); + return (int)BrainFlowExitCodes::INVALID_ARGUMENTS_ERROR; + } + + memcpy (destination, source.c_str (), source.size () + 1); + return (int)BrainFlowExitCodes::STATUS_OK; +} + int delete_streamer ( const char *streamer, int preset, int board_id, const char *json_brainflow_input_params) { diff --git a/src/board_controller/board_info_getter.cpp b/src/board_controller/board_info_getter.cpp index 4ddd5a1e9..679f6b678 100644 --- a/src/board_controller/board_info_getter.cpp +++ b/src/board_controller/board_info_getter.cpp @@ -13,10 +13,12 @@ static int get_single_value ( int board_id, int preset, const char *param_name, int *value, bool use_logger = true); static int get_string_value (int board_id, int preset, const char *param_name, char *string, - int *len, bool use_logger = true); + int *len, int max_len, bool use_logger = true); static int get_array_value (int board_id, int preset, const char *param_name, int *output_array, int *len, bool use_logger = true); static std::string get_preset_str (int preset); +static int copy_string_value ( + const std::string &value, char *destination, int *len, int max_len, bool use_logger); int get_board_presets (int board_id, int *presets, int *len) { @@ -63,7 +65,7 @@ int get_board_presets (int board_id, int *presets, int *len) } } -int get_board_descr (int board_id, int preset, char *board_descr, int *len) +int get_board_descr (int board_id, int preset, char *board_descr, int *len, int max_len) { std::string preset_str = get_preset_str (preset); try @@ -77,9 +79,7 @@ int get_board_descr (int board_id, int preset, char *board_descr, int *len) } else { - strcpy (board_descr, res.c_str ()); - *len = (int)strlen (res.c_str ()); - return (int)BrainFlowExitCodes::STATUS_OK; + return copy_string_value (res, board_descr, len, max_len, true); } } catch (json::exception &e) @@ -121,14 +121,14 @@ int get_timestamp_channel (int board_id, int preset, int *timestamp_channel) return get_single_value (board_id, preset, "timestamp_channel", timestamp_channel); } -int get_eeg_names (int board_id, int preset, char *eeg_names, int *len) +int get_eeg_names (int board_id, int preset, char *eeg_names, int *len, int max_len) { - return get_string_value (board_id, preset, "eeg_names", eeg_names, len); + return get_string_value (board_id, preset, "eeg_names", eeg_names, len, max_len); } -int get_device_name (int board_id, int preset, char *name, int *len) +int get_device_name (int board_id, int preset, char *name, int *len, int max_len) { - return get_string_value (board_id, preset, "name", name, len); + return get_string_value (board_id, preset, "name", name, len, max_len); } int get_eeg_channels (int board_id, int preset, int *eeg_channels, int *len) @@ -295,7 +295,8 @@ static int get_array_value ( } static int get_string_value ( - int board_id, int preset, const char *param_name, char *string, int *len, bool use_logger) + int board_id, int preset, const char *param_name, char *string, int *len, int max_len, + bool use_logger) { std::string preset_str = get_preset_str (preset); if (preset_str.empty ()) @@ -307,9 +308,7 @@ static int get_string_value ( std::string val = boards_struct .brainflow_boards_json["boards"][std::to_string (board_id)][preset_str][param_name]; - strcpy (string, val.c_str ()); - *len = (int)strlen (val.c_str ()); - return (int)BrainFlowExitCodes::STATUS_OK; + return copy_string_value (val, string, len, max_len, use_logger); } catch (json::exception &e) { @@ -344,4 +343,29 @@ static std::string get_preset_str (int preset) Board::board_logger->error ("unknown preset"); } return preset_str; -} \ No newline at end of file +} + +static int copy_string_value ( + const std::string &value, char *destination, int *len, int max_len, bool use_logger) +{ + if ((destination == NULL) || (len == NULL) || (max_len < 1)) + { + return (int)BrainFlowExitCodes::INVALID_ARGUMENTS_ERROR; + } + + *len = (int)value.size (); + if (((int)value.size () + 1) > max_len) + { + destination[0] = '\0'; + if (use_logger) + { + Board::board_logger->error ( + "provided output buffer is too small, required {}, got {}", value.size () + 1, + max_len); + } + return (int)BrainFlowExitCodes::INVALID_ARGUMENTS_ERROR; + } + + memcpy (destination, value.c_str (), value.size () + 1); + return (int)BrainFlowExitCodes::STATUS_OK; +} diff --git a/src/board_controller/inc/board_controller.h b/src/board_controller/inc/board_controller.h index d909a9df8..232a8a355 100644 --- a/src/board_controller/inc/board_controller.h +++ b/src/board_controller/inc/board_controller.h @@ -23,7 +23,8 @@ extern "C" SHARED_EXPORT int CALLING_CONVENTION get_board_data (int data_count, int preset, double *data_buf, int board_id, const char *json_brainflow_input_params); SHARED_EXPORT int CALLING_CONVENTION config_board (const char *config, char *response, - int *response_len, int board_id, const char *json_brainflow_input_params); + int *response_len, int response_max_len, int board_id, + const char *json_brainflow_input_params); SHARED_EXPORT int CALLING_CONVENTION config_board_with_bytes ( const char *bytes, int len, int board_id, const char *json_brainflow_input_params); SHARED_EXPORT int CALLING_CONVENTION is_prepared ( diff --git a/src/board_controller/inc/board_info_getter.h b/src/board_controller/inc/board_info_getter.h index 727040d3f..34ed7854a 100644 --- a/src/board_controller/inc/board_info_getter.h +++ b/src/board_controller/inc/board_info_getter.h @@ -8,7 +8,7 @@ extern "C" #endif // data and board desc methods SHARED_EXPORT int CALLING_CONVENTION get_board_descr ( - int board_id, int preset, char *board_descr, int *len); + int board_id, int preset, char *board_descr, int *len, int max_len); SHARED_EXPORT int CALLING_CONVENTION get_sampling_rate ( int board_id, int preset, int *sampling_rate); SHARED_EXPORT int CALLING_CONVENTION get_package_num_channel ( @@ -21,7 +21,7 @@ extern "C" int board_id, int preset, int *battery_channel); SHARED_EXPORT int CALLING_CONVENTION get_num_rows (int board_id, int preset, int *num_rows); SHARED_EXPORT int CALLING_CONVENTION get_eeg_names ( - int board_id, int preset, char *eeg_names, int *len); + int board_id, int preset, char *eeg_names, int *len, int max_len); SHARED_EXPORT int CALLING_CONVENTION get_exg_channels ( int board_id, int preset, int *exg_channels, int *len); SHARED_EXPORT int CALLING_CONVENTION get_eeg_channels ( @@ -53,7 +53,7 @@ extern "C" SHARED_EXPORT int CALLING_CONVENTION get_magnetometer_channels ( int board_id, int preset, int *magnetometer_channels, int *len); SHARED_EXPORT int CALLING_CONVENTION get_device_name ( - int board_id, int preset, char *name, int *len); + int board_id, int preset, char *name, int *len, int max_len); SHARED_EXPORT int CALLING_CONVENTION get_board_presets (int board_id, int *presets, int *len); #ifdef __cplusplus diff --git a/src/board_controller/inc/playback_file_board.h b/src/board_controller/inc/playback_file_board.h index cb59ba2d6..b3531b251 100644 --- a/src/board_controller/inc/playback_file_board.h +++ b/src/board_controller/inc/playback_file_board.h @@ -21,6 +21,7 @@ class PlaybackFileBoard : public Board bool initialized; std::vector> file_offsets; + int validate_file_access (const std::string &filename); void read_thread (int preset, std::string filename); int get_file_offsets (std::string filename, std::vector &offsets); diff --git a/src/board_controller/playback_file_board.cpp b/src/board_controller/playback_file_board.cpp index 847d9ad6f..38ea42067 100644 --- a/src/board_controller/playback_file_board.cpp +++ b/src/board_controller/playback_file_board.cpp @@ -132,6 +132,30 @@ int PlaybackFileBoard::start_stream (int buffer_size, const char *streamer_param { return res; } + if (!params.file.empty ()) + { + res = validate_file_access (params.file); + if (res != (int)BrainFlowExitCodes::STATUS_OK) + { + return res; + } + } + if (!params.file_aux.empty ()) + { + res = validate_file_access (params.file_aux); + if (res != (int)BrainFlowExitCodes::STATUS_OK) + { + return res; + } + } + if (!params.file_anc.empty ()) + { + res = validate_file_access (params.file_anc); + if (res != (int)BrainFlowExitCodes::STATUS_OK) + { + return res; + } + } keep_alive = true; if (!params.file.empty ()) @@ -153,6 +177,18 @@ int PlaybackFileBoard::start_stream (int buffer_size, const char *streamer_param return (int)BrainFlowExitCodes::STATUS_OK; } +int PlaybackFileBoard::validate_file_access (const std::string &filename) +{ + FILE *fp = fopen (filename.c_str (), "rb"); + if (fp == NULL) + { + safe_logger (spdlog::level::err, "failed to open file {}", filename); + return (int)BrainFlowExitCodes::INVALID_ARGUMENTS_ERROR; + } + fclose (fp); + return (int)BrainFlowExitCodes::STATUS_OK; +} + int PlaybackFileBoard::stop_stream () { if (keep_alive) diff --git a/src/board_controller/synthetic_board.cpp b/src/board_controller/synthetic_board.cpp index 09be30a02..9677ca130 100644 --- a/src/board_controller/synthetic_board.cpp +++ b/src/board_controller/synthetic_board.cpp @@ -61,8 +61,8 @@ int SyntheticBoard::start_stream (int buffer_size, const char *streamer_params) } keep_alive = true; - streaming_thread = std::thread ([this] { this->read_thread (); }); is_streaming = true; + streaming_thread = std::thread ([this] { this->read_thread (); }); return (int)BrainFlowExitCodes::STATUS_OK; } diff --git a/src/ml/onnx/onnx_classifier.cpp b/src/ml/onnx/onnx_classifier.cpp index c168ecce9..02d99724b 100644 --- a/src/ml/onnx/onnx_classifier.cpp +++ b/src/ml/onnx/onnx_classifier.cpp @@ -364,7 +364,7 @@ int OnnxClassifier::predict (double *data, int data_len, double *output, int *ou default: { safe_logger (spdlog::level::err, "unknown output type"); - res = (int)BrainFlowExitCodes::STATUS_OK; + res = (int)BrainFlowExitCodes::INVALID_ARGUMENTS_ERROR; } } } @@ -387,7 +387,7 @@ int OnnxClassifier::predict (double *data, int data_len, double *output, int *ou delete[] float_data; } - return (int)BrainFlowExitCodes::STATUS_OK; + return res; } int OnnxClassifier::release () @@ -887,4 +887,4 @@ int OnnxClassifier::get_output_info () } return res; -} \ No newline at end of file +} From 7f619fd38583e69c67ed0fea439613f63fc4dfb4 Mon Sep 17 00:00:00 2001 From: Andrey Parfenov Date: Mon, 27 Apr 2026 23:16:43 +0700 Subject: [PATCH 2/5] muse s anthena timestamp rework Signed-off-by: Andrey Parfenov --- src/board_controller/muse/inc/muse_anthena.h | 12 +-- .../muse/inc/muse_anthena_constants.h | 1 - src/board_controller/muse/muse_anthena.cpp | 74 ++++++++++++------- 3 files changed, 53 insertions(+), 34 deletions(-) diff --git a/src/board_controller/muse/inc/muse_anthena.h b/src/board_controller/muse/inc/muse_anthena.h index 64c049a5b..984d507c7 100644 --- a/src/board_controller/muse/inc/muse_anthena.h +++ b/src/board_controller/muse/inc/muse_anthena.h @@ -42,9 +42,9 @@ class MuseAnthena : public BLELibBoard std::condition_variable cv; std::vector> notified_characteristics; std::pair control_characteristics; - bool timestamp_initialized; - uint32_t first_device_tick; - double first_host_timestamp; + double last_eeg_timestamp; + double last_aux_timestamp; + double last_anc_timestamp; double last_battery; std::string muse_preset; bool enable_low_latency; @@ -57,10 +57,12 @@ class MuseAnthena : public BLELibBoard std::string bytes_to_string (const uint8_t *data, size_t size); void handle_data_notification (const uint8_t *data, size_t size); void parse_sensor_payload ( - uint8_t tag, uint8_t sequence_num, uint32_t device_tick, const uint8_t *data, size_t size); + uint8_t tag, uint8_t sequence_num, double host_timestamp, const uint8_t *data, size_t size); bool get_sensor_config (uint8_t tag, SensorConfig &config); int get_optics_canonical_index (uint8_t tag, int channel); - double get_sample_timestamp (uint32_t device_tick, int sample_index, double sampling_rate); + void reset_timestamps (); + static double get_sample_timestamp (double last_timestamp, double current_timestamp, + int sample_index, int n_samples, double sampling_rate); public: MuseAnthena (int board_id, struct BrainFlowInputParams params); diff --git a/src/board_controller/muse/inc/muse_anthena_constants.h b/src/board_controller/muse/inc/muse_anthena_constants.h index 9c98e4d5b..9c5c0692e 100644 --- a/src/board_controller/muse/inc/muse_anthena_constants.h +++ b/src/board_controller/muse/inc/muse_anthena_constants.h @@ -11,6 +11,5 @@ // info for equations #define MUSE_ANTHENA_ACCELEROMETER_SCALE_FACTOR 0.0000610352 #define MUSE_ANTHENA_GYRO_SCALE_FACTOR -0.0074768 -#define MUSE_ANTHENA_DEVICE_CLOCK_HZ 256000.0 #define MUSE_ANTHENA_EEG_SCALE_FACTOR (1450.0 / 16383.0) #define MUSE_ANTHENA_OPTICS_SCALE_FACTOR 1.0 diff --git a/src/board_controller/muse/muse_anthena.cpp b/src/board_controller/muse/muse_anthena.cpp index 9cce37423..dd1b29e8a 100644 --- a/src/board_controller/muse/muse_anthena.cpp +++ b/src/board_controller/muse/muse_anthena.cpp @@ -263,9 +263,7 @@ MuseAnthena::MuseAnthena (int board_id, struct BrainFlowInputParams params) muse_adapter = NULL; muse_peripheral = NULL; is_streaming = false; - timestamp_initialized = false; - first_device_tick = 0; - first_host_timestamp = 0.0; + reset_timestamps (); last_battery = 0.0; muse_preset = "p1041"; enable_low_latency = true; @@ -486,9 +484,7 @@ int MuseAnthena::start_stream (int buffer_size, const char *streamer_params) if (res == (int)BrainFlowExitCodes::STATUS_OK) { std::lock_guard callback_guard (callback_lock); - timestamp_initialized = false; - first_device_tick = 0; - first_host_timestamp = 0.0; + reset_timestamps (); last_battery = 0.0; } if (res == (int)BrainFlowExitCodes::STATUS_OK) @@ -555,7 +551,7 @@ int MuseAnthena::stop_stream () res = (int)BrainFlowExitCodes::STREAM_ALREADY_RUN_ERROR; } is_streaming = false; - timestamp_initialized = false; + reset_timestamps (); return res; } @@ -744,8 +740,7 @@ void MuseAnthena::handle_data_notification (const uint8_t *data, size_t size) const uint8_t *packet = data + offset; uint8_t packet_index = packet[1]; - uint32_t device_tick = - cast_32bit_to_uint32_little_endian ((const unsigned char *)(packet + 2)); + double packet_host_timestamp = get_timestamp (); uint8_t primary_tag = packet[9]; const uint8_t *packet_data = packet + PACKET_HEADER_SIZE; size_t packet_data_size = packet_len - PACKET_HEADER_SIZE; @@ -758,8 +753,8 @@ void MuseAnthena::handle_data_notification (const uint8_t *data, size_t size) primary_config.variable_length ? packet_data_size : primary_config.data_len; if ((primary_data_len > 0) && (primary_data_len <= packet_data_size)) { - parse_sensor_payload ( - primary_tag, packet_index, device_tick, packet_data, primary_data_len); + parse_sensor_payload (primary_tag, packet_index, packet_host_timestamp, packet_data, + primary_data_len); packet_data_offset = primary_data_len; } else @@ -799,7 +794,7 @@ void MuseAnthena::handle_data_notification (const uint8_t *data, size_t size) break; } - parse_sensor_payload (tag, subpacket_index, device_tick, + parse_sensor_payload (tag, subpacket_index, packet_host_timestamp, packet_data + packet_data_offset + SUBPACKET_HEADER_SIZE, sensor_data_len); packet_data_offset += SUBPACKET_HEADER_SIZE + sensor_data_len; } @@ -809,7 +804,7 @@ void MuseAnthena::handle_data_notification (const uint8_t *data, size_t size) } void MuseAnthena::parse_sensor_payload ( - uint8_t tag, uint8_t sequence_num, uint32_t device_tick, const uint8_t *data, size_t size) + uint8_t tag, uint8_t sequence_num, double host_timestamp, const uint8_t *data, size_t size) { SensorConfig config; if (!get_sensor_config (tag, config)) @@ -872,10 +867,11 @@ void MuseAnthena::parse_sensor_payload ( } } } - package[(size_t)timestamp_channel] = - get_sample_timestamp (device_tick, sample, config.sampling_rate); + package[(size_t)timestamp_channel] = get_sample_timestamp ( + last_eeg_timestamp, host_timestamp, sample, config.n_samples, config.sampling_rate); push_package (package.data (), (int)BrainFlowPresets::DEFAULT_PRESET); } + last_eeg_timestamp = host_timestamp; return; } @@ -911,10 +907,11 @@ void MuseAnthena::parse_sensor_payload ( (double)raw * MUSE_ANTHENA_GYRO_SCALE_FACTOR; } } - package[(size_t)timestamp_channel] = - get_sample_timestamp (device_tick, sample, config.sampling_rate); + package[(size_t)timestamp_channel] = get_sample_timestamp ( + last_aux_timestamp, host_timestamp, sample, config.n_samples, config.sampling_rate); push_package (package.data (), (int)BrainFlowPresets::AUXILIARY_PRESET); } + last_aux_timestamp = host_timestamp; return; } @@ -947,26 +944,47 @@ void MuseAnthena::parse_sensor_payload ( } } - package[(size_t)timestamp_channel] = - get_sample_timestamp (device_tick, sample, config.sampling_rate); + package[(size_t)timestamp_channel] = get_sample_timestamp ( + last_anc_timestamp, host_timestamp, sample, config.n_samples, config.sampling_rate); push_package (package.data (), (int)BrainFlowPresets::ANCILLARY_PRESET); } + last_anc_timestamp = host_timestamp; } } -double MuseAnthena::get_sample_timestamp ( - uint32_t device_tick, int sample_index, double sampling_rate) +void MuseAnthena::reset_timestamps () { - if (!timestamp_initialized) + last_eeg_timestamp = -1.0; + last_aux_timestamp = -1.0; + last_anc_timestamp = -1.0; +} + +double MuseAnthena::get_sample_timestamp (double last_timestamp, double current_timestamp, + int sample_index, int n_samples, double sampling_rate) +{ + if ((n_samples <= 0) || (sampling_rate <= 0.0)) + { + return current_timestamp; + } + + if (last_timestamp <= 0.0) + { + return current_timestamp - (double)(n_samples - sample_index - 1) / sampling_rate; + } + + if (current_timestamp <= last_timestamp) + { + return current_timestamp; + } + + double sample_timestamp = last_timestamp + (double)(sample_index + 1) / sampling_rate; + if (sample_timestamp <= current_timestamp) { - timestamp_initialized = true; - first_device_tick = device_tick; - first_host_timestamp = get_timestamp (); + return sample_timestamp; } - uint32_t elapsed_ticks = device_tick - first_device_tick; - return first_host_timestamp + (double)elapsed_ticks / MUSE_ANTHENA_DEVICE_CLOCK_HZ + - (double)sample_index / sampling_rate; + double step = (current_timestamp - last_timestamp) / (double)n_samples; + return last_timestamp + step * (double)(sample_index + 1); } std::string MuseAnthena::bytes_to_string (const uint8_t *data, size_t size) From c670770752a2c8e86d6578bd3c0244dfaa4eed53 Mon Sep 17 00:00:00 2001 From: Andrey Parfenov Date: Mon, 27 Apr 2026 23:58:23 +0700 Subject: [PATCH 3/5] Use newer CMake setup action in CI --- .github/workflows/deploy_cpp_libs.yml | 6 +++--- .github/workflows/run_android.yml | 6 +++--- .github/workflows/run_libftdi.yml | 6 +++--- .github/workflows/run_matlab.yml | 6 +++--- .github/workflows/run_unix.yml | 6 +++--- .github/workflows/valgrind.yml | 6 +++--- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/deploy_cpp_libs.yml b/.github/workflows/deploy_cpp_libs.yml index 13c0400c7..9b0c4cae6 100644 --- a/.github/workflows/deploy_cpp_libs.yml +++ b/.github/workflows/deploy_cpp_libs.yml @@ -64,10 +64,10 @@ jobs: steps: - name: Clone Repository uses: actions/checkout@v2 - - name: Setup Cmake - uses: jwlawson/actions-setup-cmake@v1.13 + - name: Setup CMake + uses: jwlawson/actions-setup-cmake@v2.2 with: - cmake-version: '3.21.x' + cmake-version: '3.31.x' - name: Install Ninja if: (matrix.os == 'macos-14') run: | diff --git a/.github/workflows/run_android.yml b/.github/workflows/run_android.yml index 5181196c0..a867a89db 100644 --- a/.github/workflows/run_android.yml +++ b/.github/workflows/run_android.yml @@ -24,10 +24,10 @@ jobs: sudo -H apt-get install -y ninja-build zip unzip python3-setuptools python3-pygments env: DEBIAN_FRONTEND: noninteractive - - name: Setup Cmake - uses: jwlawson/actions-setup-cmake@v1.4 + - name: Setup CMake + uses: jwlawson/actions-setup-cmake@v2.2 with: - cmake-version: '3.16.x' + cmake-version: '3.31.x' - name: Install NDK run: | echo "y" | sudo -H ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --install "ndk;${ANDROID_NDK_VERSION}" --sdk_root=${ANDROID_SDK_ROOT} diff --git a/.github/workflows/run_libftdi.yml b/.github/workflows/run_libftdi.yml index 7a27db389..e000a9006 100644 --- a/.github/workflows/run_libftdi.yml +++ b/.github/workflows/run_libftdi.yml @@ -27,10 +27,10 @@ jobs: sudo -H apt-get install -y python3-setuptools python3-pygments libftdi1-dev env: DEBIAN_FRONTEND: noninteractive - - name: Setup Cmake - uses: jwlawson/actions-setup-cmake@v1.4 + - name: Setup CMake + uses: jwlawson/actions-setup-cmake@v2.2 with: - cmake-version: '3.16.x' + cmake-version: '3.31.x' - name: Compile BrainFlow run: | mkdir $GITHUB_WORKSPACE/build diff --git a/.github/workflows/run_matlab.yml b/.github/workflows/run_matlab.yml index ece48d78b..2c0b8a941 100644 --- a/.github/workflows/run_matlab.yml +++ b/.github/workflows/run_matlab.yml @@ -10,10 +10,10 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v2 - - name: Setup Cmake - uses: jwlawson/actions-setup-cmake@v1.4 + - name: Setup CMake + uses: jwlawson/actions-setup-cmake@v2.2 with: - cmake-version: '3.16.x' + cmake-version: '3.31.x' - name: Compile BrainFlow run: | mkdir $GITHUB_WORKSPACE/build diff --git a/.github/workflows/run_unix.yml b/.github/workflows/run_unix.yml index 29f3f7746..614a0002b 100644 --- a/.github/workflows/run_unix.yml +++ b/.github/workflows/run_unix.yml @@ -55,10 +55,10 @@ jobs: with: version: '1' arch: 'default' - - name: Setup Cmake - uses: jwlawson/actions-setup-cmake@v1.13 + - name: Setup CMake + uses: jwlawson/actions-setup-cmake@v2.2 with: - cmake-version: '3.21.x' + cmake-version: '3.31.x' - name: Set up JDK 11 uses: actions/setup-java@v1 with: diff --git a/.github/workflows/valgrind.yml b/.github/workflows/valgrind.yml index b374d4c71..b44423897 100644 --- a/.github/workflows/valgrind.yml +++ b/.github/workflows/valgrind.yml @@ -16,10 +16,10 @@ jobs: # compile and prepare env - name: Clone Repository uses: actions/checkout@v2 - - name: Setup Cmake - uses: jwlawson/actions-setup-cmake@v1.4 + - name: Setup CMake + uses: jwlawson/actions-setup-cmake@v2.2 with: - cmake-version: '3.16.x' + cmake-version: '3.31.x' - name: Install Dependencies run: | sudo -H apt-get update -y From 27767aecf7619ce3d5761dc12a0b8796752710cd Mon Sep 17 00:00:00 2001 From: Andrey Parfenov Date: Tue, 28 Apr 2026 01:03:49 +0700 Subject: [PATCH 4/5] Pin CMake setup to project-compatible version --- .github/workflows/deploy_cpp_libs.yml | 2 +- .github/workflows/run_android.yml | 2 +- .github/workflows/run_libftdi.yml | 2 +- .github/workflows/run_matlab.yml | 2 +- .github/workflows/run_unix.yml | 2 +- .github/workflows/valgrind.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy_cpp_libs.yml b/.github/workflows/deploy_cpp_libs.yml index 9b0c4cae6..bba377831 100644 --- a/.github/workflows/deploy_cpp_libs.yml +++ b/.github/workflows/deploy_cpp_libs.yml @@ -67,7 +67,7 @@ jobs: - name: Setup CMake uses: jwlawson/actions-setup-cmake@v2.2 with: - cmake-version: '3.31.x' + cmake-version: '3.21.4' - name: Install Ninja if: (matrix.os == 'macos-14') run: | diff --git a/.github/workflows/run_android.yml b/.github/workflows/run_android.yml index a867a89db..86827f626 100644 --- a/.github/workflows/run_android.yml +++ b/.github/workflows/run_android.yml @@ -27,7 +27,7 @@ jobs: - name: Setup CMake uses: jwlawson/actions-setup-cmake@v2.2 with: - cmake-version: '3.31.x' + cmake-version: '3.21.4' - name: Install NDK run: | echo "y" | sudo -H ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --install "ndk;${ANDROID_NDK_VERSION}" --sdk_root=${ANDROID_SDK_ROOT} diff --git a/.github/workflows/run_libftdi.yml b/.github/workflows/run_libftdi.yml index e000a9006..98aa1d598 100644 --- a/.github/workflows/run_libftdi.yml +++ b/.github/workflows/run_libftdi.yml @@ -30,7 +30,7 @@ jobs: - name: Setup CMake uses: jwlawson/actions-setup-cmake@v2.2 with: - cmake-version: '3.31.x' + cmake-version: '3.21.4' - name: Compile BrainFlow run: | mkdir $GITHUB_WORKSPACE/build diff --git a/.github/workflows/run_matlab.yml b/.github/workflows/run_matlab.yml index 2c0b8a941..ec0404092 100644 --- a/.github/workflows/run_matlab.yml +++ b/.github/workflows/run_matlab.yml @@ -13,7 +13,7 @@ jobs: - name: Setup CMake uses: jwlawson/actions-setup-cmake@v2.2 with: - cmake-version: '3.31.x' + cmake-version: '3.21.4' - name: Compile BrainFlow run: | mkdir $GITHUB_WORKSPACE/build diff --git a/.github/workflows/run_unix.yml b/.github/workflows/run_unix.yml index 614a0002b..aebbb5b34 100644 --- a/.github/workflows/run_unix.yml +++ b/.github/workflows/run_unix.yml @@ -58,7 +58,7 @@ jobs: - name: Setup CMake uses: jwlawson/actions-setup-cmake@v2.2 with: - cmake-version: '3.31.x' + cmake-version: '3.21.4' - name: Set up JDK 11 uses: actions/setup-java@v1 with: diff --git a/.github/workflows/valgrind.yml b/.github/workflows/valgrind.yml index b44423897..21c567f52 100644 --- a/.github/workflows/valgrind.yml +++ b/.github/workflows/valgrind.yml @@ -19,7 +19,7 @@ jobs: - name: Setup CMake uses: jwlawson/actions-setup-cmake@v2.2 with: - cmake-version: '3.31.x' + cmake-version: '3.21.4' - name: Install Dependencies run: | sudo -H apt-get update -y From b40c5e8ff95bb807865b2993f58dc6457e267c60 Mon Sep 17 00:00:00 2001 From: Andrey Parfenov Date: Tue, 28 Apr 2026 01:08:24 +0700 Subject: [PATCH 5/5] Use maintained CMake setup action --- .github/workflows/deploy_cpp_libs.yml | 4 ++-- .github/workflows/run_android.yml | 4 ++-- .github/workflows/run_libftdi.yml | 4 ++-- .github/workflows/run_matlab.yml | 4 ++-- .github/workflows/run_unix.yml | 4 ++-- .github/workflows/valgrind.yml | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/deploy_cpp_libs.yml b/.github/workflows/deploy_cpp_libs.yml index bba377831..e2eab8f35 100644 --- a/.github/workflows/deploy_cpp_libs.yml +++ b/.github/workflows/deploy_cpp_libs.yml @@ -65,9 +65,9 @@ jobs: - name: Clone Repository uses: actions/checkout@v2 - name: Setup CMake - uses: jwlawson/actions-setup-cmake@v2.2 + uses: lukka/get-cmake@v4.3.2 with: - cmake-version: '3.21.4' + cmakeVersion: '3.21.4' - name: Install Ninja if: (matrix.os == 'macos-14') run: | diff --git a/.github/workflows/run_android.yml b/.github/workflows/run_android.yml index 86827f626..9945618ec 100644 --- a/.github/workflows/run_android.yml +++ b/.github/workflows/run_android.yml @@ -25,9 +25,9 @@ jobs: env: DEBIAN_FRONTEND: noninteractive - name: Setup CMake - uses: jwlawson/actions-setup-cmake@v2.2 + uses: lukka/get-cmake@v4.3.2 with: - cmake-version: '3.21.4' + cmakeVersion: '3.21.4' - name: Install NDK run: | echo "y" | sudo -H ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --install "ndk;${ANDROID_NDK_VERSION}" --sdk_root=${ANDROID_SDK_ROOT} diff --git a/.github/workflows/run_libftdi.yml b/.github/workflows/run_libftdi.yml index 98aa1d598..b76ff8e92 100644 --- a/.github/workflows/run_libftdi.yml +++ b/.github/workflows/run_libftdi.yml @@ -28,9 +28,9 @@ jobs: env: DEBIAN_FRONTEND: noninteractive - name: Setup CMake - uses: jwlawson/actions-setup-cmake@v2.2 + uses: lukka/get-cmake@v4.3.2 with: - cmake-version: '3.21.4' + cmakeVersion: '3.21.4' - name: Compile BrainFlow run: | mkdir $GITHUB_WORKSPACE/build diff --git a/.github/workflows/run_matlab.yml b/.github/workflows/run_matlab.yml index ec0404092..14042196f 100644 --- a/.github/workflows/run_matlab.yml +++ b/.github/workflows/run_matlab.yml @@ -11,9 +11,9 @@ jobs: - name: Check out repository uses: actions/checkout@v2 - name: Setup CMake - uses: jwlawson/actions-setup-cmake@v2.2 + uses: lukka/get-cmake@v4.3.2 with: - cmake-version: '3.21.4' + cmakeVersion: '3.21.4' - name: Compile BrainFlow run: | mkdir $GITHUB_WORKSPACE/build diff --git a/.github/workflows/run_unix.yml b/.github/workflows/run_unix.yml index aebbb5b34..fdb59cebc 100644 --- a/.github/workflows/run_unix.yml +++ b/.github/workflows/run_unix.yml @@ -56,9 +56,9 @@ jobs: version: '1' arch: 'default' - name: Setup CMake - uses: jwlawson/actions-setup-cmake@v2.2 + uses: lukka/get-cmake@v4.3.2 with: - cmake-version: '3.21.4' + cmakeVersion: '3.21.4' - name: Set up JDK 11 uses: actions/setup-java@v1 with: diff --git a/.github/workflows/valgrind.yml b/.github/workflows/valgrind.yml index 21c567f52..9dc098137 100644 --- a/.github/workflows/valgrind.yml +++ b/.github/workflows/valgrind.yml @@ -17,9 +17,9 @@ jobs: - name: Clone Repository uses: actions/checkout@v2 - name: Setup CMake - uses: jwlawson/actions-setup-cmake@v2.2 + uses: lukka/get-cmake@v4.3.2 with: - cmake-version: '3.21.4' + cmakeVersion: '3.21.4' - name: Install Dependencies run: | sudo -H apt-get update -y