Sci-SDK Library
SDK for Sci-Compiler projects
Loading...
Searching...
No Matches
Board discovery and board catalog

This page documents the SciSDK functions that let an application know which boards SciSDK can talk to, how a connection string is built for each of them and which boards are physically connected to the machine right now, plus the function that returns the RegisterFile JSON actually in use by a connected device.

These functions are meant to be used before SCISDK_AddNewDevice(): an application (or a tool such as Sci-Compiler Lab) can build a connection dialog automatically instead of hard-coding the list of models and the format of the connection paths.

Function Purpose
SCISDK_GetSupportedBoardList Plain ;-separated list of the accepted model strings
SCISDK_GetSupportedBoardsInfo Full JSON description of every supported board
SCISDK_Enumerate Discovers the boards currently connected to the machine
SCISDK_GetFirmwareJSON RegisterFile JSON in use by an already connected device

All of them return a string allocated by SciSDK: the caller must release it with SCISDK_free_string().


1. SCISDK_GetSupportedBoardList

SCISDK_DLL_API int SCISDK_GetSupportedBoardList(char** ret, void* handle);
SCISDK_DLL_API int SCISDK_GetSupportedBoardList(char **ret, void *handle)
Return the list of board models supported by this version of SciSDK.
#define SCISDK_DLL_API
Definition SciSDK_DLL.h:19

Returns every model string accepted by SCISDK_AddNewDevice() as a single ;-separated string. Aliases are listed as separate entries, right after the canonical model they belong to:

DT1260;SCIDK;V2495;DT2495;DT5771;DT5571;ULTRASPECTRA;DT4810;R5560;R5560SE;DT5560;
DAQ1X1;DAQ121;DAQ141;DAQ1416;NIDAQ1X1;NIDAQ121;NIDAQ141;NIDAQ1216;
V2740;DT2740;V2745;DT2745;V2730;DT2730;V2751;DT2751;
BoardEmulator;NiSciFakeBoard;FakeBoard;DT5550;DT5550W

(the exact content depends on the SciSDK version; the string above is shown split on several lines for readability only — the real return value has no newlines).

Model strings are case-insensitive when passed back to SCISDK_AddNewDevice().

‍NiSciFakeBoard is the former name of BoardEmulator and is kept as an alias, so code written before the rename keeps working unchanged.

char *models = NULL;
if (SCISDK_GetSupportedBoardList(&models, sdk) == NI_OK) {
printf("supported: %s\n", models);
}
#define NI_OK
Definition NIErrorCode.h:8
SCISDK_DLL_API int SCISDK_free_string(char *_str)
Free a SciSDK allocated string.

2. SCISDK_GetSupportedBoardsInfo

SCISDK_DLL_API int SCISDK_GetSupportedBoardsInfo(char** ret, void* handle);
SCISDK_DLL_API int SCISDK_GetSupportedBoardsInfo(char **ret, void *handle)

Returns a JSON array with everything needed to build a connection dialog without knowing anything about the individual boards. One element per board family:

{
"model": "R5560",
"aliases": ["R5560SE", "DT5560"],
"family": "X5560",
"connection_methods": [
{
"type": "eth",
"path_format": "IP",
"example": "192.168.50.10",
"default_port": 8888,
"notes": "A port written in the path is currently ignored: the default port is always used"
}
],
"registerfile_json": "required",
"supports_enumeration": false,
"external_library": "R5560_SDKLib.dll / libr5560.so"
}

Schema

Field Type Meaning
model string Canonical model string to pass as DeviceModel to SCISDK_AddNewDevice()
aliases string[] Other accepted spellings that map to the same board (may be empty)
family string Internal BOARD_MODEL the board maps to. Two entries with the same family share the same transport code
connection_methods object[] One entry per supported transport (see below). May be empty when the model is accepted but the transport is not implemented
registerfile_json string "required" = a local JSON file must be passed to SCISDK_AddNewDevice(). "from_device" = the board can serve its own RegisterFile, so JSONFwFilePath may be an empty string
supports_enumeration bool true when SCISDK_Enumerate() can discover this board
external_library string Runtime dependency that must be installed/reachable, "none" when SciSDK talks the protocol itself. Written as "<windows dll> / <linux so>"
notes string Optional free text at board level

connection_methods entries:

Field Type Meaning
type string "usb", "eth", "vme-v1718", "vme-v2718", "vme-v4718-eth", "vme-v4718-usb", "vme-a4818", "none"
path_format string Shape of the DevicePath string. [...] marks an optional part
example string A concrete, valid DevicePath
default_port int *(optional)* TCP port used when the path carries none
notes string *(optional)* free text, e.g. quirks of the path parsing

‍Note on the TCP port. For all the Ethernet boards except BoardEmulator the path is split on : before being parsed, so an explicit IP:port is silently ignored and the default port (8888) is always used. This is stated in the notes of the relevant connection methods so that a connection dialog can grey out the port field.

</blockquote>

3. SCISDK_Enumerate

SCISDK_DLL_API int SCISDK_Enumerate(char* board_models, char** ret, void* handle);
SCISDK_DLL_API int SCISDK_Enumerate(char *board_models, char **ret, void *handle)
Discover the boards currently connected to the machine.

Discovers the boards currently connected to the machine.

Input — board_models is a ;-separated list of the models to look for, e.g. "DT1260;V2495". Whitespace around each name is trimmed and matching is case-insensitive. Models that are unknown or that do not support discovery are silently ignored: no error is returned, they simply contribute nothing to the result. Passing a family alias (e.g. "SCIDK" instead of "DT1260") is fine; when several aliases of the same board are requested the discovery runs only once.

Output — ret is a single ;-separated string; each entry has the form:

<model>:<connection path>

where <model> is the model string as the caller spelled it and <connection path> is everything after the first colon — i.e. exactly the two strings to pass to SCISDK_AddNewDevice():

DT1260:usb:10500;DT1260:usb:10501;V2495:usb:1234

Parse an entry by splitting on the first : only (the connection path itself contains colons).

The result is an empty string when nothing is found. This is not an error.

Which boards can be discovered

Board How
DT1260 / SCIDK NI_USBEnumerate() in SCIDK_Lib.dll / libSCIDK.so (FTDI devices whose product description is SCIDK)
V2495 / DT2495 CAEN_PLU_USBEnumerateSerialNumber() in CAEN_PLULib.dll / libCAEN_PLU.so (direct USB link only)

Every other board is Ethernet-based and has no discovery protocol: ask the user for the IP address (see connection_methods in SCISDK_GetSupportedBoardsInfo).

Connecting without knowing the serial number

The same enumeration is available straight from the connection path, so a program does not have to call SCISDK_Enumerate() and pick an entry just to open the only board on the bench. For the two discoverable families (DT1260/SCIDK and V2495/DT2495) AddNewDevice() accepts, besides the explicit usb:<serial>:

Path Opens
usb:<serial> the board with that vendor serial number (no enumeration: the fast path, and the only form that works if the board library has no enumeration entry point)
usb:* the first board found on the bus
usb:id:<n> the n-th board found on the bus, 0 based, so a bench with two identical boards can be addressed positionally
// no serial number anywhere in the program
SCISDK_AddNewDevice("usb:*", "DT1260", "RegisterFile.json", "board0", sdk);
// two identical boards, whichever serials they happen to have
SCISDK_AddNewDevice("usb:id:0", "DT1260", "RegisterFile.json", "board0", sdk);
SCISDK_AddNewDevice("usb:id:1", "DT1260", "RegisterFile.json", "board1", sdk);
SCISDK_DLL_API int SCISDK_AddNewDevice(char *DevicePath, char *DeviceModel, char *JSONFwFilePath, char *Name, void *handle)
Connect to and hardware device. The function tries to connect to the device, decode the Sci-Compiler ...

The resolved serial number is printed, so a log always records which physical board was opened. When the selector cannot be satisfied the error says what was on the bus instead:

device not found -- usb:id:1 does not exist: 1 board(s) on the bus (usb:id:0 = 28684)

The order of usb:id:<n> is the order the vendor library reports, which is stable while nothing is replugged but is not guaranteed across reboots or across USB ports: use it for "any board" and "the other board", not as a persistent identifier. For that, read the serial from the log or from SCISDK_Enumerate() and use usb:<serial>.

This is deliberately a shape that generalises: the day a board announces itself over the network, tcp:* and tcp:<id> can resolve the same way, and only the enumeration back end has to learn about it.

Error handling

SCISDK_Enumerate() returns NI_OK and an empty list when:

  • no board is found;
  • none of the requested models supports discovery;
  • the board specific library (SCIDK_Lib.dll, CAEN_PLULib.dll, ...) is not installed on the machine — the failure is reported on the console only, so that asking for a board whose SDK is missing never breaks an application that scans for everything.

A non-NI_OK code is only returned for a programming error (null pointers).

Example

char *found = NULL;
if (SCISDK_Enumerate((char *)"DT1260;V2495", &found, sdk) == NI_OK) {
/* found == "DT1260:usb:10500;V2495:usb:1234" */
}

Python:

err, devices = sdk.Enumerate("DT1260;V2495")
for entry in filter(None, devices.split(";")):
model, path = entry.split(":", 1)
sdk.AddNewDevice(path, model, "RegisterFile.json", "board0")

4. SCISDK_GetFirmwareJSON

SCISDK_DLL_API int SCISDK_GetFirmwareJSON(char* name, char** ret, void* handle);
SCISDK_DLL_API int SCISDK_GetFirmwareJSON(char *name, char **ret, void *handle)
Return the full firmware JSON configuration for the specified device.

Returns the RegisterFile JSON actually in use by the device called name. It is:

  • the content of the local JSON file, when a JSONFwFilePath was given to SCISDK_AddNewDevice();
  • the JSON downloaded from the board, when SCISDK_AddNewDevice() was called with an empty JSONFwFilePath and the board reports "registerfile_json": "from_device" (DT5771, BoardEmulator).

In both cases it is the exact tree SciSDK built its component list from, so it can be used to introspect the firmware without shipping the JSON file next to the application.


5. Connecting without a local JSON file

Boards whose descriptor says "registerfile_json": "from_device" serve their own RegisterFile, so the JSON path can simply be left empty:

SCISDK_AddNewDevice("127.0.0.1:8888", "BoardEmulator", "", "board0", sdk);

If a local path is given it always wins: the file takes priority over the copy stored in the board.

Board Mechanism
DT5771 / DT5571 NI_ReadFirmwareJson() exported by DT5771_SDKLib.dll / libdt5771.so
BoardEmulator opcode 10 READ_FW_JSON of the BoardEmulator wire protocol v1 (see BoardEmulator/docs/PROTOCOL.md)

When the board cannot provide a JSON and none was given, SCISDK_AddNewDevice() fails with NI_CFG_JSON_NOT_FOUND.


6. Wrapper equivalents

Language Supported board list Boards info (JSON) Enumerate Firmware JSON
C / C++ SCISDK_GetSupportedBoardList(char**, void*) SCISDK_GetSupportedBoardsInfo(char**, void*) SCISDK_Enumerate(char*, char**, void*) SCISDK_GetFirmwareJSON(char*, char**, void*)
C++ class NI_RESULT GetSupportedBoardList(string*) NI_RESULT GetSupportedBoardsInfo(string*) NI_RESULT Enumerate(string, string*) NI_RESULT GetFirmwareJSON(string, string*)
Python GetSupportedBoardList() -> (err, str) GetSupportedBoardsInfo() -> (err, str) Enumerate(board_models: str) -> (err, str) GetFirmwareJSON(name: str) -> (err, str)
C# int GetSupportedBoardList(out string) int GetSupportedBoardsInfo(out string) int Enumerate(string, out string) int GetFirmwareJSON(string, out string)
Java int GetSupportedBoardList(Ref<String>) int GetSupportedBoardsInfo(Ref<String>) int Enumerate(String, Ref<String>) int GetFirmwareJSON(String, Ref<String>)
TypeScript GetSupportedBoardList(): [number, string] GetSupportedBoardsInfo(): [number, string] Enumerate(boardModels: string): [number, string] GetFirmwareJSON(name: string): [number, string]
LabView LV_SCISDK_GetSupportedBoardList(char* ret, void* handle) LV_SCISDK_GetSupportedBoardsInfo(char* ret, void* handle) LV_SCISDK_Enumerate(char* board_models, char* ret, void* handle) LV_SCISDK_GetFirmwareJSON(char* name, char* ret, void* handle)

As for the other LabView entry points, the ret buffer must be pre-allocated by the VI.


7. Adding a new board to the catalog

The board catalog is not a centralized table: every board describes itself inside its own driver, and a tiny registry only collects the descriptors.

  1. Declare the descriptor in the board driver. In src/boards_driver/bd_<board>.cpp, include bd_boardinfo.h and add:

    const std::vector<SciSDK_BoardInfo>& bd_<board>_BoardInfoList() {
    static std::vector<SciSDK_BoardInfo> list;
    if (list.empty()) {
    SciSDK_BoardInfo b;
    b.model = "MYBOARD";
    b.aliases.push_back("MYBOARD_SE");
    b.family = "MYBOARD"; // the BOARD_MODEL it maps to
    b.connection_methods.push_back(SciSDK_MakeConnectionMethod(
    "eth", "IP[:port]", "192.168.50.10:8888", SCISDK_DEFAULT_ETHERNET_PORT));
    b.registerfile_json = "required"; // or "from_device"
    b.external_library = "MYBOARD_SDK.dll / libmyboard.so";
    b.enumerate = &bd_<board>_Enumerate; // omit if not discoverable
    list.push_back(b);
    }
    return list;
    }

    Boards that have no dedicated bd_* driver (FakeBoard, BoardEmulator, DT5550) are described in src/boards_driver/bd_nodriver.cpp.

  2. Implement discovery (optional). Write a static void bd_<board>_Enumerate(const std::string &alias, std::vector<std::string> &devices) in the same file; it appends one alias + ":" + <connection path> per board found, and must degrade gracefully (just log and return) when the board SDK is missing.
  3. Register it. Declare bd_<board>_BoardInfoList() in src/boards_driver/bd_boardinfo.h and add one line to the providers[] array in src/boards_driver/bd_boardinfo.cpp. This is the only central point.
  4. Handle the model in SciSDK_HAL::Connect() as usual (model string dispatch + the transport switch), and add the new sources to src/Makefile.am and to the SciSDK_VC++ projects.

SCISDK_GetSupportedBoardList(), SCISDK_GetSupportedBoardsInfo() and SCISDK_Enumerate() are all derived from the registry, so they pick the new board up automatically.