diff --git a/api/icsneoc2/icsneoc2.cpp b/api/icsneoc2/icsneoc2.cpp index 90642eb..81e190d 100644 --- a/api/icsneoc2/icsneoc2.cpp +++ b/api/icsneoc2/icsneoc2.cpp @@ -640,6 +640,46 @@ icsneoc2_error_t icsneoc2_device_supports_tc10(const icsneoc2_device_t* device, return icsneoc2_error_success; } +icsneoc2_error_t icsneoc2_device_tc10_wake_request(const icsneoc2_device_t* device, icsneoc2_netid_t netid) { + auto res = icsneoc2_device_is_valid(device); + if(res != icsneoc2_error_success) { + return res; + } + if(!device->device->requestTC10Wake(static_cast(netid))) { + return icsneoc2_error_transmit_message_failed; + } + return icsneoc2_error_success; +} + +icsneoc2_error_t icsneoc2_device_tc10_sleep_request(const icsneoc2_device_t* device, icsneoc2_netid_t netid) { + auto res = icsneoc2_device_is_valid(device); + if(res != icsneoc2_error_success) { + return res; + } + if(!device->device->requestTC10Sleep(static_cast(netid))) { + return icsneoc2_error_transmit_message_failed; + } + return icsneoc2_error_success; +} + +icsneoc2_error_t icsneoc2_device_tc10_status_get(const icsneoc2_device_t* device, icsneoc2_netid_t netid, icsneoc2_tc10_sleep_status_t* sleep_status, icsneoc2_tc10_wake_status_t* wake_status) { + auto res = icsneoc2_device_is_valid(device); + if(res != icsneoc2_error_success) { + return res; + } + auto cpp_status = device->device->getTC10Status(static_cast(netid)); + if(!cpp_status.has_value()) { + return icsneoc2_error_invalid_type; + } + if (sleep_status) { + *sleep_status = static_cast(cpp_status->sleepStatus); + } + if (wake_status) { + *wake_status = static_cast(cpp_status->wakeStatus); + } + return icsneoc2_error_success; +} + icsneoc2_error_t icsneoc2_device_digital_io_get(const icsneoc2_device_t* device, icsneoc2_io_type_t type, uint32_t number, bool* value) { auto res = icsneoc2_device_is_valid(device); if(res != icsneoc2_error_success) { diff --git a/api/icsneoc2/icsneoc2messages.cpp b/api/icsneoc2/icsneoc2messages.cpp index fac9ce4..fed73a8 100644 --- a/api/icsneoc2/icsneoc2messages.cpp +++ b/api/icsneoc2/icsneoc2messages.cpp @@ -69,6 +69,14 @@ icsneoc2_error_t icsneoc2_netid_name_get(icsneoc2_netid_t netid, char* value, si return safe_str_copy(value, value_length, netid_str) ? icsneoc2_error_success : icsneoc2_error_string_copy_failed; } +icsneoc2_error_t icsneoc2_netid_network_type_get(icsneoc2_netid_t netid, icsneoc2_network_type_t* network_type) { + if(!network_type) { + return icsneoc2_error_invalid_parameters; + } + *network_type = static_cast(Network::GetTypeOfNetID(static_cast(netid), true)); + return icsneoc2_error_success; +} + icsneoc2_error_t icsneoc2_message_netid_set(icsneoc2_message_t* message, icsneoc2_netid_t netid) { if(!message) { return icsneoc2_error_invalid_parameters; diff --git a/docs/icsneoc2/examples.rst b/docs/icsneoc2/examples.rst index e547a3a..5cac86f 100644 --- a/docs/icsneoc2/examples.rst +++ b/docs/icsneoc2/examples.rst @@ -73,3 +73,12 @@ T1S Loopback .. literalinclude:: ../../examples/c2/t1s_loopback/src/main.c :language: c + +TC10 +==== + +:download:`Download example <../../examples/c2/tc10/src/main.c>` + +.. literalinclude:: ../../examples/c2/tc10/src/main.c + :language: c + diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index dcf0ed8..e7582f1 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -11,6 +11,7 @@ option(LIBICSNEO_BUILD_C2_LIN_TRANSMIT_EXAMPLE "Build the C2 LIN transmit exampl option(LIBICSNEO_BUILD_C2_ETHERNET_TRANSMIT_EXAMPLE "Build the C2 ethernet transmit example." ON) option(LIBICSNEO_BUILD_C2_ETHERNET_RECEIVE_EXAMPLE "Build the C2 ethernet receive example." ON) option(LIBICSNEO_BUILD_C2_T1S_LOOPBACK_EXAMPLE "Build the C2 RAD-Comet3 T1S loopback example." ON) +option(LIBICSNEO_BUILD_C2_TC10_EXAMPLE "Build the C2 TC10 example." ON) option(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE "Build the simple C++ example." ON) option(LIBICSNEO_BUILD_CPP_INTERACTIVE_EXAMPLE "Build the command-line interactive C++ example." ON) option(LIBICSNEO_BUILD_CPP_A2B_EXAMPLE "Build the A2B example." ON) @@ -82,6 +83,10 @@ if(LIBICSNEO_BUILD_C2_T1S_LOOPBACK_EXAMPLE) add_subdirectory(c2/t1s_loopback) endif() +if(LIBICSNEO_BUILD_C2_TC10_EXAMPLE) + add_subdirectory(c2/tc10) +endif() + if(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE) add_subdirectory(cpp/simple) endif() diff --git a/examples/c2/tc10/CMakeLists.txt b/examples/c2/tc10/CMakeLists.txt new file mode 100644 index 0000000..81743ae --- /dev/null +++ b/examples/c2/tc10/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(libicsneoc2-tc10-example src/main.c) +target_link_libraries(libicsneoc2-tc10-example icsneoc2-static) + +if(WIN32) + target_compile_definitions(libicsneoc2-tc10-example PRIVATE _CRT_SECURE_NO_WARNINGS) +endif() diff --git a/examples/c2/tc10/src/main.c b/examples/c2/tc10/src/main.c new file mode 100644 index 0000000..358c1b0 --- /dev/null +++ b/examples/c2/tc10/src/main.c @@ -0,0 +1,393 @@ +/* + * TC10 example. + * + * Sends TC10 wake/sleep requests, queries TC10 status, or lists connected + * devices and the Automotive Ethernet networks they support. Loosely based + * on examples/python/tc10/tc10.py. If --serial is omitted, the first + * available device is used. + */ + +#include +#include + +#include +#include +#include +#include +#include + +typedef struct { + const char* serial; /* may be NULL */ + const char** networks; /* points into argv */ + size_t networks_count; + bool send_wake; + bool send_sleep; + bool status; + bool list; +} args_t; + +static int print_error_code(const char* message, icsneoc2_error_t error); +static void str_tolower(char* s); +static bool resolve_netid(const char* name, icsneoc2_netid_t* out); +static void print_usage(const char* prog); +static int parse_args(int argc, char** argv, args_t* out); +static icsneoc2_device_info_t* find_device(icsneoc2_device_info_t* list, const char* serial); +static int list_devices(icsneoc2_device_info_t* list); +static const char* tc10_wake_status_str(icsneoc2_tc10_wake_status_t s); +static const char* tc10_sleep_status_str(icsneoc2_tc10_sleep_status_t s); + +int main(int argc, char** argv) { + args_t args; + if(parse_args(argc, argv, &args) != 0) { + return 1; + } + + icsneoc2_device_info_t* found_devices = NULL; + icsneoc2_error_t res = icsneoc2_device_enumerate(0, &found_devices); + if(res != icsneoc2_error_success) { + return print_error_code("Failed to enumerate devices", res); + } + if(found_devices == NULL) { + fprintf(stderr, "error: no devices found\n"); + return 1; + } + + if(args.list) { + int rc = list_devices(found_devices); + icsneoc2_enumeration_free(found_devices); + return rc; + } + + icsneoc2_device_info_t* info = find_device(found_devices, args.serial); + if(info == NULL) { + fprintf(stderr, "error: unable to find device %s\n", args.serial ? args.serial : "(any)"); + icsneoc2_enumeration_free(found_devices); + return 1; + } + + char description[256] = {0}; + size_t description_len = sizeof(description); + res = icsneoc2_device_info_description_get(info, description, &description_len); + if(res != icsneoc2_error_success) { + icsneoc2_enumeration_free(found_devices); + return print_error_code("Failed to get device description", res); + } + + icsneoc2_device_t* device = NULL; + res = icsneoc2_device_create(info, &device); + if(res != icsneoc2_error_success) { + icsneoc2_enumeration_free(found_devices); + return print_error_code("Failed to create device", res); + } + + printf("Opening device %s\n", description); + res = icsneoc2_device_open(device, icsneoc2_open_options_default); + if(res != icsneoc2_error_success) { + icsneoc2_device_free(device); + icsneoc2_enumeration_free(found_devices); + return print_error_code("Failed to open device", res); + } + + bool supports_tc10 = false; + res = icsneoc2_device_supports_tc10(device, &supports_tc10); + if(res != icsneoc2_error_success || !supports_tc10) { + fprintf(stderr, "error: device does not support TC10 (%s)\n", description); + icsneoc2_device_close(device); + icsneoc2_device_free(device); + icsneoc2_enumeration_free(found_devices); + return 1; + } + + int rc = 0; + for(size_t i = 0; i < args.networks_count; ++i) { + const char* name = args.networks[i]; + icsneoc2_netid_t netid = icsneoc2_netid_invalid; + if(!resolve_netid(name, &netid)) { + fprintf(stderr, "error: unknown network '%s'\n", name); + rc = 1; + break; + } + + if(args.send_wake) { + printf("requesting TC10 wake on network %s\n", name); + res = icsneoc2_device_tc10_wake_request(device, netid); + if(res != icsneoc2_error_success) { + rc = print_error_code("Failed to send TC10 wake", res); + break; + } + } else if(args.send_sleep) { + printf("requesting TC10 sleep on network %s\n", name); + res = icsneoc2_device_tc10_sleep_request(device, netid); + if(res != icsneoc2_error_success) { + rc = print_error_code("Failed to send TC10 sleep", res); + break; + } + } else { /* args.status */ + icsneoc2_tc10_sleep_status_t sleep_s = icsneoc2_tc10_sleep_status_no_sleep_received; + icsneoc2_tc10_wake_status_t wake_s = icsneoc2_tc10_wake_status_no_wake_received; + res = icsneoc2_device_tc10_status_get(device, netid, &sleep_s, &wake_s); + if(res != icsneoc2_error_success) { + rc = print_error_code("Failed to get TC10 status", res); + break; + } + printf("TC10 status on network %s: wake=%s sleep=%s\n", name, + tc10_wake_status_str(wake_s), tc10_sleep_status_str(sleep_s)); + } + } + + printf("Closing device %s\n", description); + icsneoc2_device_close(device); + icsneoc2_device_free(device); + icsneoc2_enumeration_free(found_devices); + return rc; +} + +static int print_error_code(const char* message, icsneoc2_error_t error) { + char error_str[64]; + size_t error_str_len = sizeof(error_str); + icsneoc2_error_t res = icsneoc2_error_code_get(error, error_str, &error_str_len); + if(res != icsneoc2_error_success) { + printf("%s: Failed to get string for error code %d with error code %d\n", message, error, res); + return res; + } + printf("%s: \"%s\" (%u)\n", message, error_str, error); + return (int)error; +} + +static void str_tolower(char* s) { + for(; *s; ++s) { + *s = (char)tolower((unsigned char)*s); + } +} + +/* + * Resolve a network name (e.g. "ETHERNET_01", "ae_01") to its icsneoc2_netid_t + * by iterating over all known netids and comparing names case-insensitively. + */ +static bool resolve_netid(const char* name, icsneoc2_netid_t* out) { + char want[64]; + strncpy(want, name, sizeof(want) - 1); + want[sizeof(want) - 1] = '\0'; + str_tolower(want); + + for(uint16_t i = 0; i < icsneoc2_netid_maxsize; ++i) { + char buf[64]; + size_t buf_len = sizeof(buf); + if(icsneoc2_netid_name_get((icsneoc2_netid_t)i, buf, &buf_len) != icsneoc2_error_success) { + continue; + } + str_tolower(buf); + if(strcmp(buf, want) == 0) { + *out = (icsneoc2_netid_t)i; + return true; + } + } + return false; +} + +static void print_usage(const char* prog) { + printf("Usage:\n"); + printf(" %s --list\n", prog); + printf(" %s [--serial SERIAL] --networks NET1 [NET2 ...] (--send-wake | --send-sleep | --status)\n", prog); + printf("\n"); + printf(" --list List connected devices and the Automotive Ethernet networks they support.\n"); + printf(" --serial SERIAL Serial number of the device. If omitted, the first available device is used.\n"); + printf(" --networks NET ... One or more network names (e.g. ETHERNET_01 AE_01). Consumes args until the next flag.\n"); + printf(" --send-wake Trigger TC10 wake on the selected networks.\n"); + printf(" --send-sleep Trigger TC10 sleep on the selected networks.\n"); + printf(" --status Query TC10 wake/sleep status on the selected networks.\n"); + printf(" -h, --help Show this message.\n"); +} + +static int parse_args(int argc, char** argv, args_t* out) { + memset(out, 0, sizeof(*out)); + for(int i = 1; i < argc; ++i) { + const char* a = argv[i]; + if(strcmp(a, "-h") == 0 || strcmp(a, "--help") == 0) { + print_usage(argv[0]); + exit(0); + } else if(strcmp(a, "--serial") == 0) { + if(i + 1 >= argc) { + fprintf(stderr, "error: --serial requires a value\n"); + return 1; + } + out->serial = argv[++i]; + } else if(strcmp(a, "--send-wake") == 0) { + out->send_wake = true; + } else if(strcmp(a, "--send-sleep") == 0) { + out->send_sleep = true; + } else if(strcmp(a, "--status") == 0) { + out->status = true; + } else if(strcmp(a, "--list") == 0) { + out->list = true; + } else if(strcmp(a, "--networks") == 0) { + if(i + 1 >= argc || argv[i + 1][0] == '-') { + fprintf(stderr, "error: --networks requires at least one network name\n"); + return 1; + } + out->networks = (const char**)&argv[i + 1]; + size_t count = 0; + while(i + 1 < argc && argv[i + 1][0] != '-') { + ++count; + ++i; + } + out->networks_count = count; + } else { + fprintf(stderr, "error: unknown argument '%s'\n", a); + print_usage(argv[0]); + return 1; + } + } + + if(out->list) { + if(out->send_wake || out->send_sleep || out->status || out->networks_count > 0 || out->serial) { + fprintf(stderr, "error: --list cannot be combined with other options\n"); + print_usage(argv[0]); + return 1; + } + return 0; + } + + if(out->networks_count == 0) { + fprintf(stderr, "error: --networks is required\n"); + print_usage(argv[0]); + return 1; + } + int action_count = (out->send_wake ? 1 : 0) + (out->send_sleep ? 1 : 0) + (out->status ? 1 : 0); + if(action_count != 1) { + fprintf(stderr, "error: exactly one of --send-wake, --send-sleep, or --status is required\n"); + print_usage(argv[0]); + return 1; + } + return 0; +} + +static const char* tc10_wake_status_str(icsneoc2_tc10_wake_status_t s) { + switch(s) { + case icsneoc2_tc10_wake_status_no_wake_received: return "no_wake_received"; + case icsneoc2_tc10_wake_status_wake_received: return "wake_received"; + default: return "unknown"; + } +} + +static const char* tc10_sleep_status_str(icsneoc2_tc10_sleep_status_t s) { + switch(s) { + case icsneoc2_tc10_sleep_status_no_sleep_received: return "no_sleep_received"; + case icsneoc2_tc10_sleep_status_sleep_received: return "sleep_received"; + case icsneoc2_tc10_sleep_status_sleep_failed: return "sleep_failed"; + case icsneoc2_tc10_sleep_status_sleep_aborted: return "sleep_aborted"; + default: return "unknown"; + } +} + +/* + * Find a device matching the provided serial, or the first available device if serial is NULL. + * Returns NULL on failure (caller is responsible for the enumeration list). + */ +static icsneoc2_device_info_t* find_device(icsneoc2_device_info_t* list, const char* serial) { + if(serial == NULL) { + return list; + } + for(icsneoc2_device_info_t* cur = list; cur != NULL; cur = icsneoc2_device_info_next(cur)) { + char dev_serial[64] = {0}; + size_t dev_serial_len = sizeof(dev_serial); + if(icsneoc2_device_info_serial_get(cur, dev_serial, &dev_serial_len) != icsneoc2_error_success) { + continue; + } + if(strcmp(dev_serial, serial) == 0) { + return cur; + } + } + return NULL; +} + +/* + * List connected devices and the Automotive Ethernet networks each one supports. + */ +static int list_devices(icsneoc2_device_info_t* list) { + size_t index = 0; + for(icsneoc2_device_info_t* cur = list; cur != NULL; cur = icsneoc2_device_info_next(cur)) { + char serial[64] = {0}; + size_t serial_len = sizeof(serial); + (void)icsneoc2_device_info_serial_get(cur, serial, &serial_len); + + char description[256] = {0}; + size_t description_len = sizeof(description); + (void)icsneoc2_device_info_description_get(cur, description, &description_len); + + printf("[%zu] %s (%s)\n", index++, description, serial); + + icsneoc2_device_t* device = NULL; + icsneoc2_error_t res = icsneoc2_device_create(cur, &device); + if(res != icsneoc2_error_success) { + print_error_code(" Failed to create device", res); + continue; + } + + icsneoc2_open_options_t options = icsneoc2_open_options_default; + options &= ~ICSNEOC2_OPEN_OPTIONS_SYNC_RTC; + options &= ~ICSNEOC2_OPEN_OPTIONS_GO_ONLINE; + res = icsneoc2_device_open(device, options); + if(res != icsneoc2_error_success) { + print_error_code(" Failed to open device", res); + icsneoc2_device_free(device); + continue; + } + + bool supports_tc10 = false; + (void)icsneoc2_device_supports_tc10(device, &supports_tc10); + printf(" TC10 supported: %s\n", supports_tc10 ? "yes" : "no"); + + size_t count = 0; + res = icsneoc2_device_supported_tx_networks_get(device, NULL, &count); + if(res != icsneoc2_error_success || count == 0) { + icsneoc2_device_close(device); + icsneoc2_device_free(device); + continue; + } + + icsneoc2_netid_t* nets = (icsneoc2_netid_t*)calloc(count, sizeof(icsneoc2_netid_t)); + if(nets == NULL) { + fprintf(stderr, " error: out of memory\n"); + icsneoc2_device_close(device); + icsneoc2_device_free(device); + continue; + } + + res = icsneoc2_device_supported_tx_networks_get(device, nets, &count); + if(res != icsneoc2_error_success) { + print_error_code(" Failed to get supported networks", res); + free(nets); + icsneoc2_device_close(device); + icsneoc2_device_free(device); + continue; + } + + printf(" Automotive Ethernet networks:\n"); + bool any = false; + for(size_t i = 0; i < count; ++i) { + icsneoc2_network_type_t type = icsneoc2_network_type_invalid; + if(icsneoc2_netid_network_type_get(nets[i], &type) != icsneoc2_error_success) { + continue; + } + if(type != icsneoc2_network_type_automotive_ethernet) { + continue; + } + char name[64] = {0}; + size_t name_len = sizeof(name); + if(icsneoc2_netid_name_get(nets[i], name, &name_len) != icsneoc2_error_success) { + continue; + } + printf(" %s\n", name); + any = true; + } + if(!any) { + printf(" (none)\n"); + } + + free(nets); + icsneoc2_device_close(device); + icsneoc2_device_free(device); + } + return 0; +} diff --git a/include/icsneo/communication/tc10.h b/include/icsneo/communication/tc10.h index 64be44c..5241a82 100644 --- a/include/icsneo/communication/tc10.h +++ b/include/icsneo/communication/tc10.h @@ -4,19 +4,20 @@ #ifdef __cplusplus #include +#include "icsneo/icsneoc2types.h" namespace icsneo { -enum class TC10WakeStatus : uint8_t { - NoWakeReceived, - WakeReceived, +enum class TC10WakeStatus : icsneoc2_tc10_wake_status_t { + NoWakeReceived = icsneoc2_tc10_wake_status_no_wake_received, + WakeReceived = icsneoc2_tc10_wake_status_wake_received, }; -enum class TC10SleepStatus : uint8_t { - NoSleepReceived, - SleepReceived, - SleepFailed, - SleepAborted, +enum class TC10SleepStatus : icsneoc2_tc10_sleep_status_t { + NoSleepReceived = icsneoc2_tc10_sleep_status_no_sleep_received, + SleepReceived = icsneoc2_tc10_sleep_status_sleep_received, + SleepFailed = icsneoc2_tc10_sleep_status_sleep_failed, + SleepAborted = icsneoc2_tc10_sleep_status_sleep_aborted, }; } diff --git a/include/icsneo/icsneoc2.h b/include/icsneo/icsneoc2.h index a041a24..5d67622 100644 --- a/include/icsneo/icsneoc2.h +++ b/include/icsneo/icsneoc2.h @@ -473,6 +473,37 @@ icsneoc2_error_t icsneoc2_device_rtc_set(const icsneoc2_device_t* device, int64_ */ icsneoc2_error_t icsneoc2_device_supports_tc10(const icsneoc2_device_t* device, bool* supported); +/** + * Send a TC10 wake request to the device on a specific network. This is used to wake up ECUs that support TC10 wake on the specified network. + * + * @param[in] device The device to send the wake request from. + * @param[in] netid The network to send the wake request on. + * + * @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters or icsneoc2_error_transmit_message_failed otherwise. + */ +icsneoc2_error_t icsneoc2_device_tc10_wake_request(const icsneoc2_device_t* device, icsneoc2_netid_t netid); + +/** + * Send a TC10 sleep request to the device on a specific network. This is used to put ECUs that support TC10 sleep on the specified network to sleep. + * + * @param[in] device The device to send the sleep request from. + * @param[in] netid The network to send the sleep request on. + * + * @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters or icsneoc2_error_transmit_message_failed otherwise. + */ +icsneoc2_error_t icsneoc2_device_tc10_sleep_request(const icsneoc2_device_t* device, icsneoc2_netid_t netid); + +/** + * Get the current TC10 sleep/wake status of a specific network. + * + * @param[in] device The device to query. + * @param[in] netid The network to query the TC10 status of. + * @param[out] sleep_status Pointer to a icsneoc2_tc10_sleep_status_t to copy the sleep status into. May be NULL if sleep status is not needed. + * @param[out] wake_status Pointer to a icsneoc2_tc10_wake_status_t to copy the wake status into. May be NULL if wake status is not needed. + * + * @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise. + */ +icsneoc2_error_t icsneoc2_device_tc10_status_get(const icsneoc2_device_t* device, icsneoc2_netid_t netid, icsneoc2_tc10_sleep_status_t* sleep_status, icsneoc2_tc10_wake_status_t* wake_status); /** * Get the current state of a digital I/O pin. * diff --git a/include/icsneo/icsneoc2messages.h b/include/icsneo/icsneoc2messages.h index 04ff601..4db502b 100644 --- a/include/icsneo/icsneoc2messages.h +++ b/include/icsneo/icsneoc2messages.h @@ -75,6 +75,18 @@ icsneoc2_error_t icsneoc2_message_netid_get(icsneoc2_message_t* message, icsneoc */ icsneoc2_error_t icsneoc2_netid_name_get(icsneoc2_netid_t netid, char* value, size_t* value_length); +/** + * Get the network type for a icsneoc2_netid_t. + * + * @param[in] netid The network id to get the type of. + * @param[out] network_type Pointer to a icsneoc2_network_type_t to copy the network type into. + * + * @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise. + * + * @see icsneoc2_network_type_t, icsneoc2_network_type_name_get + */ +icsneoc2_error_t icsneoc2_netid_network_type_get(icsneoc2_netid_t netid, icsneoc2_network_type_t* network_type); + /** * Set the Network ID (netid) of a bus message * diff --git a/include/icsneo/icsneoc2types.h b/include/icsneo/icsneoc2types.h index 968201a..8509c15 100644 --- a/include/icsneo/icsneoc2types.h +++ b/include/icsneo/icsneoc2types.h @@ -422,6 +422,28 @@ typedef uint8_t icsneoc2_can_error_code_t; typedef uint64_t icsneoc2_message_can_error_flags_t; +typedef enum _icsneoc2_tc10_wake_status_t { + icsneoc2_tc10_wake_status_no_wake_received = 0, // No wake signal received + icsneoc2_tc10_wake_status_wake_received = 1, // Wake signal received + + // Must be last entry. Don't use as a TC10 wake status. + icsneoc2_tc10_wake_status_maxsize +} _icsneoc2_tc10_wake_status_t; + +typedef uint8_t icsneoc2_tc10_wake_status_t; + +typedef enum _icsneoc2_tc10_sleep_status_t { + icsneoc2_tc10_sleep_status_no_sleep_received = 0, // No sleep signal received + icsneoc2_tc10_sleep_status_sleep_received = 1, // Sleep signal received + icsneoc2_tc10_sleep_status_sleep_failed = 2, // Sleep attempt failed + icsneoc2_tc10_sleep_status_sleep_aborted = 3, // Sleep attempt aborted + + // Must be last entry. Don't use as a TC10 sleep status. + icsneoc2_tc10_sleep_status_maxsize +} _icsneoc2_tc10_sleep_status_t; + +typedef uint8_t icsneoc2_tc10_sleep_status_t; + #ifdef __cplusplus } #endif diff --git a/test/unit/icsneoc2.cpp b/test/unit/icsneoc2.cpp index 279d78b..61819fa 100644 --- a/test/unit/icsneoc2.cpp +++ b/test/unit/icsneoc2.cpp @@ -180,6 +180,15 @@ TEST(icsneoc2, test_icsneoc2_error_invalid_parameters_and_invalid_device) ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_pcb_serial_get(NULL, &placeholderInteger8, &placeholderSizeT)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_mac_address_get(NULL, &placeholderInteger8, &placeholderSizeT)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_supports_tc10(NULL, &placeholderBool)); + ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_tc10_wake_request(NULL, icsneoc2_netid_dwcan_01)); + ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_tc10_sleep_request(NULL, icsneoc2_netid_dwcan_01)); + { + icsneoc2_tc10_sleep_status_t sleep_s = icsneoc2_tc10_sleep_status_no_sleep_received; + icsneoc2_tc10_wake_status_t wake_s = icsneoc2_tc10_wake_status_no_wake_received; + ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_tc10_status_get(NULL, icsneoc2_netid_dwcan_01, &sleep_s, &wake_s)); + ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_tc10_status_get(NULL, icsneoc2_netid_dwcan_01, NULL, NULL)); + } + ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_netid_network_type_get(icsneoc2_netid_dwcan_01, NULL)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_timestamp_resolution_get(NULL, &placeholderInteger32)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_digital_io_get(NULL, 0, 0, &placeholderBool)); @@ -477,6 +486,60 @@ TEST(icsneoc2, icsneoc2_network_type_t) ASSERT_EQ(sizeof(icsneoc2_network_type_t), sizeof(uint8_t)); } +TEST(icsneoc2, test_icsneoc2_netid_network_type_get) +{ + icsneoc2_network_type_t type = icsneoc2_network_type_invalid; + + // CAN + ASSERT_EQ(icsneoc2_error_success, icsneoc2_netid_network_type_get(icsneoc2_netid_dwcan_01, &type)); + ASSERT_EQ(icsneoc2_network_type_can, type); + + // LIN + type = icsneoc2_network_type_invalid; + ASSERT_EQ(icsneoc2_error_success, icsneoc2_netid_network_type_get(icsneoc2_netid_lin_01, &type)); + ASSERT_EQ(icsneoc2_network_type_lin, type); + + // Ethernet + type = icsneoc2_network_type_invalid; + ASSERT_EQ(icsneoc2_error_success, icsneoc2_netid_network_type_get(icsneoc2_netid_ethernet_01, &type)); + ASSERT_EQ(icsneoc2_network_type_ethernet, type); + + // Automotive Ethernet + type = icsneoc2_network_type_invalid; + ASSERT_EQ(icsneoc2_error_success, icsneoc2_netid_network_type_get(icsneoc2_netid_ae_01, &type)); + ASSERT_EQ(icsneoc2_network_type_automotive_ethernet, type); + + // SWCAN + type = icsneoc2_network_type_invalid; + ASSERT_EQ(icsneoc2_error_success, icsneoc2_netid_network_type_get(icsneoc2_netid_swcan_01, &type)); + ASSERT_EQ(icsneoc2_network_type_swcan, type); + + // LSFTCAN + type = icsneoc2_network_type_invalid; + ASSERT_EQ(icsneoc2_error_success, icsneoc2_netid_network_type_get(icsneoc2_netid_lsftcan_01, &type)); + ASSERT_EQ(icsneoc2_network_type_lsftcan, type); +} + +TEST(icsneoc2, test_icsneoc2_tc10_wake_status_t) +{ + ASSERT_EQ(icsneoc2_tc10_wake_status_no_wake_received, 0); + ASSERT_EQ(icsneoc2_tc10_wake_status_wake_received, 1); + ASSERT_EQ(icsneoc2_tc10_wake_status_maxsize, 2); + + ASSERT_EQ(sizeof(icsneoc2_tc10_wake_status_t), sizeof(uint8_t)); +} + +TEST(icsneoc2, test_icsneoc2_tc10_sleep_status_t) +{ + ASSERT_EQ(icsneoc2_tc10_sleep_status_no_sleep_received, 0); + ASSERT_EQ(icsneoc2_tc10_sleep_status_sleep_received, 1); + ASSERT_EQ(icsneoc2_tc10_sleep_status_sleep_failed, 2); + ASSERT_EQ(icsneoc2_tc10_sleep_status_sleep_aborted, 3); + ASSERT_EQ(icsneoc2_tc10_sleep_status_maxsize, 4); + + ASSERT_EQ(sizeof(icsneoc2_tc10_sleep_status_t), sizeof(uint8_t)); +} + TEST(icsneoc2, test_icsneoc2_io_type_t) { ASSERT_EQ(icsneoc2_io_type_eth_activation, 0);