diff options
author | Volodymyr Vorobiov <volodymyr.vorobiov@globallogic.com> | 2022-09-15 16:03:20 +0300 |
---|---|---|
committer | Volodymyr Vorobiov <volodymyr.vorobiov@globallogic.com> | 2022-09-15 16:03:20 +0300 |
commit | f3e37d4f13d2d089835cee94099eca6410e53893 (patch) | |
tree | 0c91fc93276db213252a36435c30c3c9ff215989 | |
parent | c20e979fb0e13f0360496f6f0a2269c212dd1e9b (diff) | |
parent | 4bbd03047c616a4d2b838e57fb73c7413d2f461a (diff) | |
download | mts-id-eeprom-f3e37d4f13d2d089835cee94099eca6410e53893.tar.gz mts-id-eeprom-f3e37d4f13d2d089835cee94099eca6410e53893.tar.bz2 mts-id-eeprom-f3e37d4f13d2d089835cee94099eca6410e53893.zip |
Merge branch 'master' into dc_board
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/eeprom_main.c | 102 | ||||
-rw-r--r-- | src/mts_wait_for_cell_reset.c | 108 | ||||
-rw-r--r-- | src/x | 108 |
5 files changed, 303 insertions, 20 deletions
diff --git a/configure.in b/configure.in index df4c0b1..6aca9d6 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ AC_INIT([src/eeprom_main.c]) -AM_INIT_AUTOMAKE([mts-id-eeprom], [0.6.0]) +AM_INIT_AUTOMAKE([mts-id-eeprom], [0.6.3]) AM_CONFIG_HEADER([config.h]) AC_PROG_CC diff --git a/src/Makefile.am b/src/Makefile.am index 99145a4..7dadb83 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,10 +2,11 @@ AUTOMAKE_OPTIONS = gnu AM_CFLAGS = -Wall -bin_PROGRAMS = mts-id-eeprom +bin_PROGRAMS = mts-id-eeprom mts-wait-for-cell-reset sbin_PROGRAMS = mts-hashpwd mts-fpga-loader mts_hashpwd_SOURCES = hashpwd.cpp mts_id_eeprom_SOURCES = eeprom_main.c +mts_wait_for_cell_reset_SOURCES = mts_wait_for_cell_reset.c noinst_HEADERS = eeprom.h log.h mts_error_codes.h mts_fpga_hash.h mts_fpga_reg.h mts_fpga_spi.h mts_hashpwd_LDADD = -lcrypto diff --git a/src/eeprom_main.c b/src/eeprom_main.c index a4bf4f1..04887c8 100644 --- a/src/eeprom_main.c +++ b/src/eeprom_main.c @@ -45,6 +45,7 @@ static int eeprom_size = 512; static void mts_id_eeprom_inspect(struct mts_id_eeprom_layout *id_eeprom); static void mts_ap_eeprom_inspect(struct mts_ap_eeprom_layout *ap_eeprom); + #ifdef MTCDT3B static void mtcdt3b_eeprom_inspect(struct mtcdt3b_eeprom_layout *mtcdt3b_eeprom); static void mtcdt3dc_eeprom_inspect(struct mtcdt3dc_eeprom_layout *mtcdt3dc_eeprom); @@ -170,9 +171,11 @@ static int id_yaml_out(const char *name, struct mts_id_eeprom_layout *id_eeprom) fprintf(file, "capa-wifi: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_WIFI) ? "true" : "false"); fprintf(file, "capa-bluetooth: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_BLUETOOTH) ? "true" : "false"); fprintf(file, "capa-lora: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_LORA) ? "true" : "false"); + fprintf(file, "capa-lora-lbt: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_LORA_LBT) ? "true" : "false"); fprintf(file, "capa-battery: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_BATTERY) ? "true" : "false"); fprintf(file, "capa-supercap: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_SUPERCAP) ? "true" : "false"); fprintf(file, "capa-cellular: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_CELLULAR) ? "true" : "false"); + fprintf(file, "capa-user-data-encryption: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_USER_DATA_ENCRYPTION) ? "true" : "false"); fprintf(file, "capa: \""); for (i = 0; i < sizeof(id_eeprom->capa); i++) { @@ -212,6 +215,10 @@ static int id_yaml_out(const char *name, struct mts_id_eeprom_layout *id_eeprom) fprintf(file, "lora-product-id: \"%.32s\"\n", id_eeprom->lora_product_id); fprintf(file, "lora-hw-version: \"%.32s\"\n", id_eeprom->lora_hw_version); +#ifdef MTRE + fprintf(file, "oem-string1: %.32s\n", id_eeprom->oem_string1); + fprintf(file, "oem-string2: %.32s\n", id_eeprom->oem_string2); +#endif fprintf(file, "...\n"); @@ -423,8 +430,10 @@ static void mts_id_eeprom_inspect(struct mts_id_eeprom_layout *id_eeprom) log_info("capa-wifi: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_WIFI) ? "yes" : "no"); log_info("capa-bluetooth: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_BLUETOOTH) ? "yes" : "no"); log_info("capa-lora: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_LORA) ? "yes" : "no"); + log_info("capa-lora-lbt: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_LORA_LBT) ? "yes" : "no"); log_info("capa-supercap: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_SUPERCAP) ? "yes" : "no"); log_info("capa-cellular: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_CELLULAR) ? "yes" : "no"); + log_info("capa-user-data-encryption: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_USER_DATA_ENCRYPTION) ? "yes" : "no"); log_info("mac-bluetooth: %02X:%02X:%02X:%02X:%02X:%02X", id_eeprom->mac_bluetooth[0], @@ -459,6 +468,10 @@ static void mts_id_eeprom_inspect(struct mts_id_eeprom_layout *id_eeprom) log_info("lora-product-id: %.32s", id_eeprom->lora_product_id); log_info("lora-hw-version: %.32s", id_eeprom->lora_hw_version); +#ifdef MTRE + log_info("oem-string1: %.32s", id_eeprom->oem_string1); + log_info("oem-string2: %.32s", id_eeprom->oem_string2); +#endif } static void mts_ap_eeprom_inspect(struct mts_ap_eeprom_layout *ap_eeprom) @@ -578,6 +591,10 @@ static void usage(FILE *out) { fprintf(out, " --lora-eui <EUI-64> |\n"); fprintf(out, " --lora-hw-version <hw-version> |\n"); fprintf(out, " --lora-product-id <product-id> |\n"); +#ifdef MTRE + fprintf(out, " --oem-string1 <string> |\n"); + fprintf(out, " --oem-string2 <string> |\n"); +#endif fprintf(out, " --imei <imei> |\n"); fprintf(out, " --capa-gps |\n"); fprintf(out, " --capa-din |\n"); @@ -586,9 +603,11 @@ static void usage(FILE *out) { fprintf(out, " --capa-wifi |\n"); fprintf(out, " --capa-bluetooth |\n"); fprintf(out, " --capa-lora |\n"); + fprintf(out, " --capa-lora-lbt |\n"); fprintf(out, " --capa-battery |\n"); fprintf(out, " --capa-supercap |\n"); fprintf(out, " --capa-cellular |\n"); + fprintf(out, " --capa-user-data-encryption |\n"); fprintf(out, " --capa-clear (clears all flags) |\n"); fprintf(out, " --hex-to-bin | \n"); fprintf(out, " --out-format { bin | yaml (default) } |\n"); @@ -632,13 +651,19 @@ enum { CMD_OPT_CAPA_WIFI, CMD_OPT_CAPA_BLUETOOTH, CMD_OPT_CAPA_LORA, + CMD_OPT_CAPA_LORA_LBT, CMD_OPT_CAPA_BATTERY, CMD_OPT_CAPA_SUPERCAP, CMD_OPT_CAPA_CELLULAR, + CMD_OPT_CAPA_USER_DATA_ENCRYPTION, CMD_OPT_CAPA_CLEAR, CMD_OPT_OUT_FORMAT, CMD_OPT_UPDATE, CMD_OPT_ACCESSORY_CARD, +#ifdef MTRE + CMD_OPT_OEM_STRING1, + CMD_OPT_OEM_STRING2, +#endif #ifdef MTCDT3B CMD_OPT_BASE_BOARD, CMD_OPT_DC_BOARD, @@ -667,6 +692,10 @@ static struct option long_options[] = { {"hw-version", 1, NULL, CMD_OPT_HW_VERSION}, {"lora-product-id", 1, NULL, CMD_OPT_LORA_PRODUCT_ID}, {"lora-hw-version", 1, NULL, CMD_OPT_LORA_HW_VERSION}, +#ifdef MTRE + {"oem-string1", 1, NULL, CMD_OPT_OEM_STRING1}, + {"oem-string2", 1, NULL, CMD_OPT_OEM_STRING2}, +#endif {"mac-addr", 1, NULL, CMD_OPT_MAC_ADDR}, {"mac-bluetooth", 1, NULL, CMD_OPT_MAC_BLUETOOTH}, {"mac-wifi", 1, NULL, CMD_OPT_MAC_WIFI}, @@ -679,9 +708,11 @@ static struct option long_options[] = { {"capa-wifi", 0, NULL, CMD_OPT_CAPA_WIFI}, {"capa-bluetooth", 0, NULL, CMD_OPT_CAPA_BLUETOOTH}, {"capa-lora", 0, NULL, CMD_OPT_CAPA_LORA}, + {"capa-lora-lbt", 0, NULL, CMD_OPT_CAPA_LORA_LBT}, {"capa-battery", 0, NULL, CMD_OPT_CAPA_BATTERY}, {"capa-supercap", 0, NULL, CMD_OPT_CAPA_SUPERCAP}, {"capa-cellular", 0, NULL, CMD_OPT_CAPA_CELLULAR}, + {"capa-user-data-encryption", 0, NULL, CMD_OPT_CAPA_USER_DATA_ENCRYPTION}, {"capa-clear", 0, NULL, CMD_OPT_CAPA_CLEAR}, {"hex-to-bin", 0, NULL, CMD_OPT_HEX_TO_BIN}, {"out-format", 1, NULL, CMD_OPT_OUT_FORMAT}, @@ -741,6 +772,10 @@ int main(int argc, char *argv[]) { char *lora_eui = NULL; char *lora_product_id = NULL; char *lora_hw_version = NULL; +#ifdef MTRE + char *oem_string1 = NULL; + char *oem_string2 = NULL; +#endif struct mts_id_eeprom_layout id_eeprom; struct mts_ap_eeprom_layout ap_eeprom; @@ -817,9 +852,9 @@ int main(int argc, char *argv[]) { tmp = read(fd, (char *) &mtcdt3b_eeprom, eeprom_size); } else if (dc_board) { - tmp = read(fd, (char *) &mtcdt3dc_eeprom, eeprom_size); + tmp = read(fd, (char *) &mtcdt3dc_eeprom, eeprom_size); #endif - } else { + } else { tmp = read(fd, (char *) &id_eeprom, eeprom_size); } @@ -835,13 +870,13 @@ int main(int argc, char *argv[]) { log_info("loaded ap eeprom from %s successfully", in_file); mts_ap_eeprom_inspect(&ap_eeprom); #ifdef MTCDT3B - } else if (base_board) { + } else if (base_board) { log_info("loaded ap eeprom from %s successfully", in_file); mtcdt3b_eeprom_inspect(&mtcdt3b_eeprom); } else if (dc_board) { mtcdt3dc_eeprom_inspect(&mtcdt3dc_eeprom); #endif - } else { + } else { log_info("loaded id eeprom from %s successfully", in_file); mts_id_eeprom_inspect(&id_eeprom); } @@ -921,6 +956,16 @@ int main(int argc, char *argv[]) { lora_product_id = optarg; break; +#ifdef MTRE + case CMD_OPT_OEM_STRING1: + oem_string1 = optarg; + break; + + case CMD_OPT_OEM_STRING2: + oem_string2 = optarg; + break; +#endif + case CMD_OPT_DEVICE_ID: device_id = optarg; break; @@ -1012,8 +1057,8 @@ int main(int argc, char *argv[]) { #ifdef MTCDT3B if (base_board) { DEVICE_CAPA_SET(mtcdt3b_eeprom.capa, MTCDT3B_CAPA_LORA); + break; } - break; #endif DEVICE_CAPA_SET(id_eeprom.capa, CAPA_LORA); break; @@ -1030,6 +1075,10 @@ int main(int argc, char *argv[]) { } break; #endif + case CMD_OPT_CAPA_LORA_LBT: + DEVICE_CAPA_SET(id_eeprom.capa, CAPA_LORA_LBT); + break; + case CMD_OPT_CAPA_BATTERY: DEVICE_CAPA_SET(id_eeprom.capa, CAPA_BATTERY); break; @@ -1042,6 +1091,10 @@ int main(int argc, char *argv[]) { DEVICE_CAPA_SET(id_eeprom.capa, CAPA_CELLULAR); break; + case CMD_OPT_CAPA_USER_DATA_ENCRYPTION: + DEVICE_CAPA_SET(id_eeprom.capa, CAPA_USER_DATA_ENCRYPTION); + break; + case CMD_OPT_CAPA_CLEAR: capa_clear = 1; break; @@ -1077,7 +1130,6 @@ int main(int argc, char *argv[]) { DEVICE_CAPA_SET(mtcdt3b_eeprom.capa, MTCDT3B_CAPA_ETH_SWITCH); } break; - case CMD_OPT_ETH_SWITCH_VERSION: if (base_board) { uint16_t u16; @@ -1094,7 +1146,6 @@ int main(int argc, char *argv[]) { mtcdt3b_eeprom.hw_version_eth_switch = u16; } break; - case CMD_OPT_ETH_SWITCH_MAC_ADDR: if (base_board) { tmp = hwaddr_aton(optarg, mtcdt3b_eeprom.mac_eth_switch, sizeof(mtcdt3b_eeprom.mac_eth_switch)); @@ -1226,7 +1277,6 @@ int main(int argc, char *argv[]) { #ifdef MTCDT3B else if(base_board) tmp = hwaddr_aton(mac_addr, mtcdt3b_eeprom.mac_addr, sizeof(mtcdt3b_eeprom.mac_addr)); - #endif else tmp = hwaddr_aton(mac_addr, id_eeprom.mac_addr, sizeof(id_eeprom.mac_addr)); @@ -1247,7 +1297,6 @@ int main(int argc, char *argv[]) { #ifdef MTCDT3B else if (base_board) EEPROM_SET(mtcdt3b_eeprom,lora_product_id) - #endif else EEPROM_SET(id_eeprom,lora_product_id) @@ -1263,11 +1312,30 @@ int main(int argc, char *argv[]) { #ifdef MTCDT3B else if (base_board) EEPROM_SET(mtcdt3b_eeprom,lora_hw_version) - #endif else EEPROM_SET(id_eeprom,lora_hw_version) } +#ifdef MTRE + if (oem_string1) { + if (! accessory_card) { + strncpy(id_eeprom.oem_string1, oem_string1, sizeof(id_eeprom.oem_string1) - 1); + } else { + log_error("--oem-string1 option is not supported on accessory card eeprom"); + usage(stderr); + exit(1); + } + } + if (oem_string2) { + if (! accessory_card) { + strncpy(id_eeprom.oem_string2, oem_string2, sizeof(id_eeprom.oem_string2) - 1); + } else { + log_error("--oem-string2 option is not supported on accessory card eeprom"); + usage(stderr); + exit(1); + } + } +#endif if (lora_eui) { if (accessory_card) tmp = hwaddr_aton(lora_eui, ap_eeprom.eui, sizeof(ap_eeprom.eui)); @@ -1277,7 +1345,6 @@ int main(int argc, char *argv[]) { usage(stderr); exit(1); } - #endif else tmp = hwaddr_aton(lora_eui, id_eeprom.lora_eui, sizeof(id_eeprom.lora_eui)); @@ -1388,8 +1455,8 @@ int main(int argc, char *argv[]) { else if (base_board) bin_out(out_file, (char*) &mtcdt3b_eeprom); - else if (dc_board) - bin_out(out_file, (char*) &mtcdt3dc_eeprom); + else if (dc_board) + bin_out(out_file, (char*) &mtcdt3dc_eeprom); #endif else { id_eeprom.eeprom_layout_version = EEPROM_LAYOUT_VERSION; @@ -1402,8 +1469,8 @@ int main(int argc, char *argv[]) { else if (base_board) mtcdt3b_yaml_out(out_file, &mtcdt3b_eeprom); - else if (dc_board) - mtcdt3dc_yaml_out(out_file, &mtcdt3dc_eeprom); + else if (dc_board) + mtcdt3dc_yaml_out(out_file, &mtcdt3dc_eeprom); #endif else id_yaml_out(out_file, &id_eeprom); @@ -1421,8 +1488,8 @@ int main(int argc, char *argv[]) { else if (base_board) mtcdt3b_eeprom_inspect(&mtcdt3b_eeprom); - else if (dc_board) - mtcdt3dc_eeprom_inspect(&mtcdt3dc_eeprom); + else if (dc_board) + mtcdt3dc_eeprom_inspect(&mtcdt3dc_eeprom); #endif else mts_id_eeprom_inspect(&id_eeprom); @@ -1432,4 +1499,3 @@ int main(int argc, char *argv[]) { return 0; } - diff --git a/src/mts_wait_for_cell_reset.c b/src/mts_wait_for_cell_reset.c new file mode 100644 index 0000000..9f7de31 --- /dev/null +++ b/src/mts_wait_for_cell_reset.c @@ -0,0 +1,108 @@ +/* + * mts-wait-for-cell-reset + * + * Block signal + * If not in reset, exit + * Register with mts-io for reset + * If not in reset, exit + * Suspend process for signal + * If signal occurs, exit + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> + +const char *name = "mts-wait-for-cell-reset"; +const int RST_SIG=SIGUSR2; // Wait for this signal +const char *MONITOR="/sys/devices/platform/mts-io/radio-reset-monitor"; +const char *RADIO_DISCOVERY="/sys/devices/platform/mts-io/radio-udev-discovery"; + +/* Return 0 if Cellular modem is being reset + * Return 1 if Cellular modem is not being reset + */ +int +not_reset(const char *attr_name) +{ + int not_in_reset, result; + char buf[256]; + int discovery; + + discovery = open(attr_name,O_RDONLY); + if (discovery == -1) { + fprintf(stderr,"FAILED: %s cannot open attribute %s: %s\n",name,attr_name,strerror(errno)); + exit(1); + } + result = read(discovery,buf,sizeof buf); + if (result > 0) + not_in_reset = atoi(buf); + else if (result == 0) { + fprintf(stderr,"FAILED: %s attribute %s has no state\n",name,attr_name); + exit(1); + } else { + fprintf(stderr,"FAILED: %s attribute %s error: %s\n",name,attr_name,strerror(errno)); + exit(1); + } + close(discovery); + return not_in_reset; +} + +void +handler(int sig) +{ + /* Normal way out of this program + * exit not safe from signal handler so + * use _exit() + */ + _exit(0); +} + +int +main(int argc, char *argv[]) +{ + sigset_t blockedset,nullset; + int monitor; + int result; + char buf[128]; + struct sigaction action; + + memset(&action,0,sizeof action); + action.sa_handler = handler; + memset(&blockedset,0,sizeof blockedset); + sigaddset(&blockedset,RST_SIG); + memset(&nullset,0,sizeof nullset); + + sigprocmask(SIG_BLOCK,&blockedset,NULL); // Blocked RST_SIG + + sigaction(RST_SIG,&action,NULL); + + if (not_reset(RADIO_DISCOVERY)) + exit(0); // Not in reset + sprintf(buf,"%d %d",getpid(),RST_SIG); + + monitor = open(MONITOR,O_WRONLY); + if (monitor == -1) { + fprintf(stderr,"FAILED: %s cannot open attribute %s: %s\n",name,MONITOR,strerror(errno)); + exit(2); + } + result = write(monitor,buf,strlen(buf)); + if(result != strlen(buf)) { + if (result == -1) { + fprintf(stderr,"FAILED: %s attribute %s write error: %s\n",name,MONITOR,strerror(errno)); + exit(3); + } + fprintf(stderr,"FAILED: %s attribute %s incomplete write error: %d/%d\n",name,MONITOR,result,(int)strlen(buf)); + exit(4); + } + close(monitor); + if (not_reset(RADIO_DISCOVERY)) + exit(0); + + sigsuspend(&nullset); // Allow all signals + /* NOTREACHED */ +} @@ -0,0 +1,108 @@ +/* + * mts-wait-for-cell-reset + * + * Block signal + * If not in reset, exit + * Register with mts-io for reset + * If not in reset, exit + * Suspend process for signal + * If signal occurs, exit + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> + +const char *name = "mts-wait-for-cell-reset"; +const int RST_SIG=SIGUSR2; // Wait for this signal +const char *MONITOR="/sys/devices/platform/mts-io/radio-reset-monitor"; +const char *RADIO_DISCOVERY="/sys/devices/platform/mts-io/radio-udev-discovery"; + +/* Return 0 if Cellular modem is being reset + * Return 1 if Cellular modem is not being reset + */ +int +not_reset(const char *attr_name) +{ + int not_in_reset, result; + char buf[256]; + int discovery; + + discovery = open(attr_name,O_RDONLY); + if (discovery == -1) { + fprintf(stderr,"FAILED: %s cannot open attribute %s: %s\n",name,attr_name,strerror(errno)); + exit(1); + } + result = read(discovery,buf,sizeof buf); + if (result > 0) + not_in_reset = atoi(buf); + else if (result == 0) { + fprintf(stderr,"FAILED: %s attribute %s has no state\n",name,attr_name); + exit(1); + } else { + fprintf(stderr,"FAILED: %s attribute %s error: %s\n",name,attr_name,strerror(errno)); + exit(1); + } + close(discovery); + return not_in_reset; +} + +void +handler(int sig) +{ + /* Normal way out of this program + * exit not safe from signal handler so + * use _exit() + */ + _exit(0); +} + +int +main(int argc, char *argv[]) +{ + sigset_t blockedset,nullset; + int monitor; + int result; + char buf[128]; + struct sigaction action; + + memset(&action,0,sizeof action); + action.sa_handler = handler; + memset(&blockedset,0,sizeof blockedset); + sigaddset(&blockedset,RST_SIG); + memset(&nullset,0,sizeof nullset); + + sigprocmask(SIG_BLOCK,&blockedset,NULL); // Blocked RST_SIG + + sigaction(RST_SIG,&action,NULL); + + if (not_reset(RADIO_DISCOVERY)) + exit(0); // Not in reset + sprintf(buf,"%d %d",getpid(),RST_SIG); + + monitor = open(MONITOR,O_WRONLY); + if (monitor == -1) { + fprintf(stderr,"FAILED: %s cannot open attribute %s: %s\n",name,MONITOR,strerror(errno)); + exit(2); + } + result = write(monitor,buf,strlen(buf)); + if(result != strlen(buf)) { + if (result == -1) { + fprintf(stderr,"FAILED: %s attribute %s write error: %s\n",name,MONITOR,strerror(errno)); + exit(3); + } + fprintf(stderr,"FAILED: %s attribute %s incomplete write error: %d/%d\n",name,MONITOR,result,(int)strlen(buf)); + exit(4); + } + close(monitor); + if (not_reset(RADIO_DISCOVERY)) + exit(0); + + sigsuspend(&nullset); // Allow all signals + /* NOTREACHED */ +} |