From a30c1a3af414f743c1ad40e66d6a3c7ada1064a1 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 14:59:04 -0800 Subject: added util to repo --- util/README.md | 72 ++++++++++++ util/util.c | 366 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util/util.h | 77 ++++++++++++ 3 files changed, 515 insertions(+) create mode 100644 util/README.md create mode 100644 util/util.c create mode 100644 util/util.h (limited to 'util') diff --git a/util/README.md b/util/README.md new file mode 100644 index 0000000..bda72c8 --- /dev/null +++ b/util/README.md @@ -0,0 +1,72 @@ +# brnkl-util + +Small collection of helper functions required by some of our open source code + +## File I/O + +Functions to handle boilerplate when reading and writing from files. + +```c +le_result_t ioutil_readIntFromFile(const char* path, int* value); +le_result_t ioutil_readDoubleFromFile(const char* filePath, double* value); +le_result_t ioutil_writeToFile(const char* path, + void* value, + size_t size, + size_t count); + +le_result_t ioutil_appendToFile(const char* path, + void* value, + size_t size, + size_t count); + +``` + +## General + +Collection of unsorted helper functions + +```c +uint64_t GetCurrentTimestamp(void); +time_t util_getMTime(char* path); +int util_getUnixDatetime(); +le_result_t util_flattenRes(le_result_t* res, int nRes); +bool util_fileExists(const char* path); +bool util_alreadyMounted(const char* devPath); +void* util_find(Functional* f); +void util_listDir(const char* dir, char* dest, size_t size); +``` + +## GPIO (Linux SysFS) + +Provides API calls for all functionality supported by the Linux SysFS GPIO interface + +```c +le_result_t gpio_exportPin(char* pin); +le_result_t gpio_unexportPin(char* pin); +void getGpioPath(char* outputStr, char* pin, char* subDir); +le_result_t gpio_setDirection(char* pin, char* direction); +le_result_t gpio_setInput(char* pin); +le_result_t gpio_setOutput(char* pin); +le_result_t gpio_setActiveState(char* pin, bool isActiveLow); +le_result_t gpio_isActive(char* pin, bool* isActive); +le_result_t gpio_setValue(char* pin, bool state); +le_result_t gpio_setLow(char* pin); +le_result_t gpio_setHigh(char* pin); +le_result_t gpio_setPull(char* pin, char* pull); +le_result_t gpio_pullDown(char* pin); +le_result_t gpio_pullUp(char* pin); +``` + +## Serial + +Handler boilerplate for reading and writing to a serial port + +```c +int fd_openSerial(const char* device, int baud); +speed_t fd_convertBaud(int baud); +int fd_puts(const int fd, const char* s); +int fd_getChar(const int fd); +void fd_flush(const int fd); +int fd_dataAvail(int fd, int* data); +void fd_flushInput(const int fd); +``` diff --git a/util/util.c b/util/util.c new file mode 100644 index 0000000..3042c22 --- /dev/null +++ b/util/util.c @@ -0,0 +1,366 @@ +#include "util.h" +#include "legato.h" +#include + +le_result_t readFromFile(const char* path, + void* value, + int (*scanCallback)(FILE* f, void* val)) { + FILE* f = fopen(path, "r"); + if (f == NULL) { + LE_WARN("Couldn't open '%s' - %m", path); + return LE_IO_ERROR; + } + int numScanned = scanCallback(f, value); + if (numScanned != 1) + return LE_FORMAT_ERROR; + fclose(f); + return LE_OK; +} + +int scanIntCallback(FILE* f, void* value) { + int* val = value; + return fscanf(f, "%d", val); +} + +int scanDoubleCallback(FILE* f, void* value) { + double* val = value; + return fscanf(f, "%lf", val); +} + +le_result_t ioutil_readIntFromFile(const char* path, int* value) { + return readFromFile(path, value, scanIntCallback); +} + +le_result_t ioutil_readDoubleFromFile(const char* path, double* value) { + return readFromFile(path, value, scanDoubleCallback); +} + +le_result_t writeToFile(const char* path, + void* value, + size_t size, + size_t count, + const char* openMode) { + FILE* f = fopen(path, openMode); + if (f == NULL) { + LE_WARN("Failed to open %s for writing", path); + return LE_IO_ERROR; + } + fwrite(value, size, count, f); + fflush(f); + fclose(f); + return LE_OK; +} + +le_result_t ioutil_writeToFile(const char* path, + void* value, + size_t size, + size_t count) { + return writeToFile(path, value, size, count, "w"); +} + +le_result_t ioutil_appendToFile(const char* path, + void* value, + size_t size, + size_t count) { + return writeToFile(path, value, size, count, "a"); +} + +le_result_t util_flattenRes(le_result_t* res, int nRes) { + for (int i = 0; i < nRes; i++) { + if (res[i] != LE_OK) + return res[i]; + } + return LE_OK; +} + +int util_getUnixDatetime() { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec; +} + +/** + * Get the last modified datetime + * of the file at path + */ +time_t util_getMTime(char* path) { + struct stat st; + if (stat(path, &st) != 0) + return -1; + else + return st.st_mtime; +} + +bool util_fileExists(const char* path) { + struct stat st; + return stat(path, &st) == 0; +} + +bool util_alreadyMounted(const char* devPath) { + char content[2048]; + FILE* f = fopen("/proc/mounts", "r"); + if (f == NULL) { + return false; + } + fread(content, sizeof(char), sizeof(content), f); + // if this ref is non-null, we found a match + return strstr(content, devPath) != NULL; +} + +uint64_t GetCurrentTimestamp(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + uint64_t utcMilliSec = + (uint64_t)(tv.tv_sec) * 1000 + (uint64_t)(tv.tv_usec) / 1000; + return utcMilliSec; +} + +// TODO verify this is working +le_result_t gpio_exportPin(char* pin) { + int len = strlen(pin); + return ioutil_writeToFile("/sys/class/gpio/export", &pin, sizeof(char), len); +} + +le_result_t gpio_unexportPin(char* pin) { + int len = strlen(pin); + return ioutil_writeToFile("/sys/class/gpio/unexport", &pin, sizeof(char), + len); +} + +void getGpioPath(char* outputStr, char* pin, char* subDir) { + sprintf(outputStr, "/sys/class/gpio/gpio%s/%s", pin, subDir); +} + +le_result_t gpio_setDirection(char* pin, char* direction) { + char path[100]; + getGpioPath(path, pin, "direction"); + return ioutil_writeToFile(path, direction, sizeof(char), strlen(direction)); +} + +le_result_t gpio_setPull(char* pin, char* pull) { + char path[100]; + getGpioPath(path, pin, "pull"); + return ioutil_writeToFile(path, pull, sizeof(char), strlen(pull)); +} + +le_result_t gpio_pullDown(char* pin) { + return gpio_setPull(pin, "down"); +} + +le_result_t gpio_pullUp(char* pin) { + return gpio_setPull(pin, "up"); +} + +le_result_t gpio_setInput(char* pin) { + return gpio_setDirection(pin, "in"); +} + +le_result_t gpio_setOutput(char* pin) { + return gpio_setDirection(pin, "out"); +} + +le_result_t gpio_setActiveState(char* pin, bool isActiveLow) { + // Any non zero value toggles the existing value + // so we must read the existing value first + char path[100]; + int isActiveLowSet; + getGpioPath(path, pin, "active_low"); + le_result_t readRes = ioutil_readIntFromFile(path, &isActiveLowSet); + le_result_t writeRes = LE_OK; + if (isActiveLow != isActiveLowSet) { + writeRes = ioutil_writeToFile(path, "1", sizeof(char), 1); + } + return readRes == LE_OK && writeRes == LE_OK ? LE_OK : LE_FAULT; +} + +le_result_t gpio_isActive(char* pin, bool* isActive) { + char path[50]; + getGpioPath(path, pin, "value"); + int val; + le_result_t readRes = ioutil_readIntFromFile(path, &val); + *isActive = val; + return readRes; +} + +le_result_t gpio_setValue(char* pin, bool state) { + char path[50]; + getGpioPath(path, pin, "value"); + char* strState = state ? "1" : "0"; + return ioutil_writeToFile(path, &strState, sizeof(char), strlen(strState)); +} + +le_result_t gpio_setLow(char* pin) { + return gpio_setValue(pin, LOW); +} + +le_result_t gpio_setHigh(char* pin) { + return gpio_setValue(pin, HIGH); +} + +void* util_find(Functional* f) { + f->args.i = 0; + while (f->args.i < f->n) { + if (f->callback(&f->args)) { + return f->derefCallback(f->args.i, f->args.arr); + } + f->args.i++; + } + return NULL; +} + +void util_listDir(const char* dir, char* dest, size_t size) { + struct dirent* de; + char toConcat[1024]; + DIR* dr = opendir(dir); + if (dr == NULL) + return; + while ((de = readdir(dr)) != NULL) { + if (de->d_name[0] != '.') { + snprintf(toConcat, size, "%s,", de->d_name); + strncat(dest, toConcat, size); + } + } + closedir(dr); +} + +/** + * Convert an integer baud rate to a speed_t + */ +speed_t fd_convertBaud(int baud) { + speed_t b; + switch (baud) { + case 50: + b = B50; + break; + case 75: + b = B75; + break; + case 110: + b = B110; + break; + case 134: + b = B134; + break; + case 150: + b = B150; + break; + case 200: + b = B200; + break; + case 300: + b = B300; + break; + case 600: + b = B600; + break; + case 1200: + b = B1200; + break; + case 1800: + b = B1800; + break; + case 2400: + b = B2400; + break; + case 9600: + b = B9600; + break; + case 19200: + b = B19200; + break; + case 38400: + b = B38400; + break; + case 57600: + b = B57600; + break; + case 115200: + b = B115200; + break; + case 230400: + b = B230400; + break; + case 921600: + b = B921600; + break; + default: + b = -2; + } + return b; +} + +/** + * Open a serial connection on device + * + * Lifted from here + * https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringSerial.c + */ +int fd_openSerial(const char* device, int baud) { + struct termios options; + speed_t binaryBaud = fd_convertBaud(baud); + int status, fd; + if ((fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1) + return -1; + fcntl(fd, F_SETFL, O_RDWR); + tcgetattr(fd, &options); + cfmakeraw(&options); + cfsetispeed(&options, binaryBaud); + cfsetospeed(&options, binaryBaud); + + options.c_cflag |= (CLOCAL | CREAD); + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + options.c_cflag &= ~CSIZE; + options.c_cflag |= CS8; + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_oflag &= ~OPOST; + + options.c_cc[VMIN] = 0; + options.c_cc[VTIME] = 10; // Ten seconds (100 deciseconds) + + tcsetattr(fd, TCSANOW | TCSAFLUSH, &options); + + ioctl(fd, TIOCMGET, &status); + + status |= TIOCM_DTR; + status |= TIOCM_RTS; + + ioctl(fd, TIOCMSET, &status); + usleep(10000); // 10mS + return fd; +} + +int fd_puts(const int fd, const char* s) { + return write(fd, s, strlen(s)); +} + +int fd_getChar(const int fd) { + uint8_t x; + + if (read(fd, &x, 1) != 1) + return -1; + + return ((int)x) & 0xFF; +} + +void fd_flush(const int fd) { + // tcflush(fd, TCIOFLUSH); + tcdrain(fd); +} + +void fd_flushInput(const int fd) { + tcflush(fd, TCIFLUSH); +} + +int fd_dataAvail(int fd, int* data) { + return ioctl(fd, FIONREAD, data); +} + +double util_avgDouble(double* readings, int nReadings) { + double sum = 0; + for (int i = 0; i < nReadings; i++) { + sum += readings[i]; + } + + return sum / nReadings; +} diff --git a/util/util.h b/util/util.h new file mode 100644 index 0000000..06ef2fb --- /dev/null +++ b/util/util.h @@ -0,0 +1,77 @@ +#ifndef UTIL_H +#define UTIL_H + +#include "legato.h" +#include + +#define HIGH 1 +#define LOW 0 + +typedef struct { + int i; + void* arr; + void* ctxp; +} FunctionalArgs; + +typedef struct { + int n; // number of elements in array + bool (*callback)(FunctionalArgs* args); // callback applied to arr[i] + void* (*derefCallback)(int i, void* j); // callback used to deference arr[i] + FunctionalArgs args; +} Functional; + +// ioutil +le_result_t readFromFile(const char* path, + void* value, + int (*scanCallback)(FILE* f, void* val)); +int scanDoubleCallback(FILE* f, void* value); +le_result_t ioutil_readIntFromFile(const char* path, int* value); +le_result_t ioutil_readDoubleFromFile(const char* filePath, double* value); +le_result_t ioutil_writeToFile(const char* path, + void* value, + size_t size, + size_t count); + +le_result_t ioutil_appendToFile(const char* path, + void* value, + size_t size, + size_t count); + +// TODO fix this name (no PascalCase) +uint64_t GetCurrentTimestamp(void); +time_t util_getMTime(char* path); +int util_getUnixDatetime(); +le_result_t util_flattenRes(le_result_t* res, int nRes); +bool util_fileExists(const char* path); +bool util_alreadyMounted(const char* devPath); +double util_avgDouble(double* readings, int nReadings); + +// TODO verify this is working +le_result_t gpio_exportPin(char* pin); +le_result_t gpio_unexportPin(char* pin); +void getGpioPath(char* outputStr, char* pin, char* subDir); +le_result_t gpio_setDirection(char* pin, char* direction); +le_result_t gpio_setInput(char* pin); +le_result_t gpio_setOutput(char* pin); +le_result_t gpio_setActiveState(char* pin, bool isActiveLow); +le_result_t gpio_isActive(char* pin, bool* isActive); +le_result_t gpio_setValue(char* pin, bool state); +le_result_t gpio_setLow(char* pin); +le_result_t gpio_setHigh(char* pin); +le_result_t gpio_setPull(char* pin, char* pull); +le_result_t gpio_pullDown(char* pin); +le_result_t gpio_pullUp(char* pin); + +void* util_find(Functional* f); + +void util_listDir(const char* dir, char* dest, size_t size); + +int fd_openSerial(const char* device, int baud); +speed_t fd_convertBaud(int baud); +int fd_puts(const int fd, const char* s); +int fd_getChar(const int fd); +void fd_flush(const int fd); +int fd_dataAvail(int fd, int* data); +void fd_flushInput(const int fd); + +#endif -- cgit v1.2.3 From 6d322af7d89bfaeca7d561280505e285e07c29a7 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 15:02:08 -0800 Subject: deleted util to resolve conflict when pushing --- util/README.md | 72 ------------ util/util.c | 366 --------------------------------------------------------- util/util.h | 77 ------------ 3 files changed, 515 deletions(-) delete mode 100644 util/README.md delete mode 100644 util/util.c delete mode 100644 util/util.h (limited to 'util') diff --git a/util/README.md b/util/README.md deleted file mode 100644 index bda72c8..0000000 --- a/util/README.md +++ /dev/null @@ -1,72 +0,0 @@ -# brnkl-util - -Small collection of helper functions required by some of our open source code - -## File I/O - -Functions to handle boilerplate when reading and writing from files. - -```c -le_result_t ioutil_readIntFromFile(const char* path, int* value); -le_result_t ioutil_readDoubleFromFile(const char* filePath, double* value); -le_result_t ioutil_writeToFile(const char* path, - void* value, - size_t size, - size_t count); - -le_result_t ioutil_appendToFile(const char* path, - void* value, - size_t size, - size_t count); - -``` - -## General - -Collection of unsorted helper functions - -```c -uint64_t GetCurrentTimestamp(void); -time_t util_getMTime(char* path); -int util_getUnixDatetime(); -le_result_t util_flattenRes(le_result_t* res, int nRes); -bool util_fileExists(const char* path); -bool util_alreadyMounted(const char* devPath); -void* util_find(Functional* f); -void util_listDir(const char* dir, char* dest, size_t size); -``` - -## GPIO (Linux SysFS) - -Provides API calls for all functionality supported by the Linux SysFS GPIO interface - -```c -le_result_t gpio_exportPin(char* pin); -le_result_t gpio_unexportPin(char* pin); -void getGpioPath(char* outputStr, char* pin, char* subDir); -le_result_t gpio_setDirection(char* pin, char* direction); -le_result_t gpio_setInput(char* pin); -le_result_t gpio_setOutput(char* pin); -le_result_t gpio_setActiveState(char* pin, bool isActiveLow); -le_result_t gpio_isActive(char* pin, bool* isActive); -le_result_t gpio_setValue(char* pin, bool state); -le_result_t gpio_setLow(char* pin); -le_result_t gpio_setHigh(char* pin); -le_result_t gpio_setPull(char* pin, char* pull); -le_result_t gpio_pullDown(char* pin); -le_result_t gpio_pullUp(char* pin); -``` - -## Serial - -Handler boilerplate for reading and writing to a serial port - -```c -int fd_openSerial(const char* device, int baud); -speed_t fd_convertBaud(int baud); -int fd_puts(const int fd, const char* s); -int fd_getChar(const int fd); -void fd_flush(const int fd); -int fd_dataAvail(int fd, int* data); -void fd_flushInput(const int fd); -``` diff --git a/util/util.c b/util/util.c deleted file mode 100644 index 3042c22..0000000 --- a/util/util.c +++ /dev/null @@ -1,366 +0,0 @@ -#include "util.h" -#include "legato.h" -#include - -le_result_t readFromFile(const char* path, - void* value, - int (*scanCallback)(FILE* f, void* val)) { - FILE* f = fopen(path, "r"); - if (f == NULL) { - LE_WARN("Couldn't open '%s' - %m", path); - return LE_IO_ERROR; - } - int numScanned = scanCallback(f, value); - if (numScanned != 1) - return LE_FORMAT_ERROR; - fclose(f); - return LE_OK; -} - -int scanIntCallback(FILE* f, void* value) { - int* val = value; - return fscanf(f, "%d", val); -} - -int scanDoubleCallback(FILE* f, void* value) { - double* val = value; - return fscanf(f, "%lf", val); -} - -le_result_t ioutil_readIntFromFile(const char* path, int* value) { - return readFromFile(path, value, scanIntCallback); -} - -le_result_t ioutil_readDoubleFromFile(const char* path, double* value) { - return readFromFile(path, value, scanDoubleCallback); -} - -le_result_t writeToFile(const char* path, - void* value, - size_t size, - size_t count, - const char* openMode) { - FILE* f = fopen(path, openMode); - if (f == NULL) { - LE_WARN("Failed to open %s for writing", path); - return LE_IO_ERROR; - } - fwrite(value, size, count, f); - fflush(f); - fclose(f); - return LE_OK; -} - -le_result_t ioutil_writeToFile(const char* path, - void* value, - size_t size, - size_t count) { - return writeToFile(path, value, size, count, "w"); -} - -le_result_t ioutil_appendToFile(const char* path, - void* value, - size_t size, - size_t count) { - return writeToFile(path, value, size, count, "a"); -} - -le_result_t util_flattenRes(le_result_t* res, int nRes) { - for (int i = 0; i < nRes; i++) { - if (res[i] != LE_OK) - return res[i]; - } - return LE_OK; -} - -int util_getUnixDatetime() { - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec; -} - -/** - * Get the last modified datetime - * of the file at path - */ -time_t util_getMTime(char* path) { - struct stat st; - if (stat(path, &st) != 0) - return -1; - else - return st.st_mtime; -} - -bool util_fileExists(const char* path) { - struct stat st; - return stat(path, &st) == 0; -} - -bool util_alreadyMounted(const char* devPath) { - char content[2048]; - FILE* f = fopen("/proc/mounts", "r"); - if (f == NULL) { - return false; - } - fread(content, sizeof(char), sizeof(content), f); - // if this ref is non-null, we found a match - return strstr(content, devPath) != NULL; -} - -uint64_t GetCurrentTimestamp(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - uint64_t utcMilliSec = - (uint64_t)(tv.tv_sec) * 1000 + (uint64_t)(tv.tv_usec) / 1000; - return utcMilliSec; -} - -// TODO verify this is working -le_result_t gpio_exportPin(char* pin) { - int len = strlen(pin); - return ioutil_writeToFile("/sys/class/gpio/export", &pin, sizeof(char), len); -} - -le_result_t gpio_unexportPin(char* pin) { - int len = strlen(pin); - return ioutil_writeToFile("/sys/class/gpio/unexport", &pin, sizeof(char), - len); -} - -void getGpioPath(char* outputStr, char* pin, char* subDir) { - sprintf(outputStr, "/sys/class/gpio/gpio%s/%s", pin, subDir); -} - -le_result_t gpio_setDirection(char* pin, char* direction) { - char path[100]; - getGpioPath(path, pin, "direction"); - return ioutil_writeToFile(path, direction, sizeof(char), strlen(direction)); -} - -le_result_t gpio_setPull(char* pin, char* pull) { - char path[100]; - getGpioPath(path, pin, "pull"); - return ioutil_writeToFile(path, pull, sizeof(char), strlen(pull)); -} - -le_result_t gpio_pullDown(char* pin) { - return gpio_setPull(pin, "down"); -} - -le_result_t gpio_pullUp(char* pin) { - return gpio_setPull(pin, "up"); -} - -le_result_t gpio_setInput(char* pin) { - return gpio_setDirection(pin, "in"); -} - -le_result_t gpio_setOutput(char* pin) { - return gpio_setDirection(pin, "out"); -} - -le_result_t gpio_setActiveState(char* pin, bool isActiveLow) { - // Any non zero value toggles the existing value - // so we must read the existing value first - char path[100]; - int isActiveLowSet; - getGpioPath(path, pin, "active_low"); - le_result_t readRes = ioutil_readIntFromFile(path, &isActiveLowSet); - le_result_t writeRes = LE_OK; - if (isActiveLow != isActiveLowSet) { - writeRes = ioutil_writeToFile(path, "1", sizeof(char), 1); - } - return readRes == LE_OK && writeRes == LE_OK ? LE_OK : LE_FAULT; -} - -le_result_t gpio_isActive(char* pin, bool* isActive) { - char path[50]; - getGpioPath(path, pin, "value"); - int val; - le_result_t readRes = ioutil_readIntFromFile(path, &val); - *isActive = val; - return readRes; -} - -le_result_t gpio_setValue(char* pin, bool state) { - char path[50]; - getGpioPath(path, pin, "value"); - char* strState = state ? "1" : "0"; - return ioutil_writeToFile(path, &strState, sizeof(char), strlen(strState)); -} - -le_result_t gpio_setLow(char* pin) { - return gpio_setValue(pin, LOW); -} - -le_result_t gpio_setHigh(char* pin) { - return gpio_setValue(pin, HIGH); -} - -void* util_find(Functional* f) { - f->args.i = 0; - while (f->args.i < f->n) { - if (f->callback(&f->args)) { - return f->derefCallback(f->args.i, f->args.arr); - } - f->args.i++; - } - return NULL; -} - -void util_listDir(const char* dir, char* dest, size_t size) { - struct dirent* de; - char toConcat[1024]; - DIR* dr = opendir(dir); - if (dr == NULL) - return; - while ((de = readdir(dr)) != NULL) { - if (de->d_name[0] != '.') { - snprintf(toConcat, size, "%s,", de->d_name); - strncat(dest, toConcat, size); - } - } - closedir(dr); -} - -/** - * Convert an integer baud rate to a speed_t - */ -speed_t fd_convertBaud(int baud) { - speed_t b; - switch (baud) { - case 50: - b = B50; - break; - case 75: - b = B75; - break; - case 110: - b = B110; - break; - case 134: - b = B134; - break; - case 150: - b = B150; - break; - case 200: - b = B200; - break; - case 300: - b = B300; - break; - case 600: - b = B600; - break; - case 1200: - b = B1200; - break; - case 1800: - b = B1800; - break; - case 2400: - b = B2400; - break; - case 9600: - b = B9600; - break; - case 19200: - b = B19200; - break; - case 38400: - b = B38400; - break; - case 57600: - b = B57600; - break; - case 115200: - b = B115200; - break; - case 230400: - b = B230400; - break; - case 921600: - b = B921600; - break; - default: - b = -2; - } - return b; -} - -/** - * Open a serial connection on device - * - * Lifted from here - * https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringSerial.c - */ -int fd_openSerial(const char* device, int baud) { - struct termios options; - speed_t binaryBaud = fd_convertBaud(baud); - int status, fd; - if ((fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1) - return -1; - fcntl(fd, F_SETFL, O_RDWR); - tcgetattr(fd, &options); - cfmakeraw(&options); - cfsetispeed(&options, binaryBaud); - cfsetospeed(&options, binaryBaud); - - options.c_cflag |= (CLOCAL | CREAD); - options.c_cflag &= ~PARENB; - options.c_cflag &= ~CSTOPB; - options.c_cflag &= ~CSIZE; - options.c_cflag |= CS8; - options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); - options.c_oflag &= ~OPOST; - - options.c_cc[VMIN] = 0; - options.c_cc[VTIME] = 10; // Ten seconds (100 deciseconds) - - tcsetattr(fd, TCSANOW | TCSAFLUSH, &options); - - ioctl(fd, TIOCMGET, &status); - - status |= TIOCM_DTR; - status |= TIOCM_RTS; - - ioctl(fd, TIOCMSET, &status); - usleep(10000); // 10mS - return fd; -} - -int fd_puts(const int fd, const char* s) { - return write(fd, s, strlen(s)); -} - -int fd_getChar(const int fd) { - uint8_t x; - - if (read(fd, &x, 1) != 1) - return -1; - - return ((int)x) & 0xFF; -} - -void fd_flush(const int fd) { - // tcflush(fd, TCIOFLUSH); - tcdrain(fd); -} - -void fd_flushInput(const int fd) { - tcflush(fd, TCIFLUSH); -} - -int fd_dataAvail(int fd, int* data) { - return ioctl(fd, FIONREAD, data); -} - -double util_avgDouble(double* readings, int nReadings) { - double sum = 0; - for (int i = 0; i < nReadings; i++) { - sum += readings[i]; - } - - return sum / nReadings; -} diff --git a/util/util.h b/util/util.h deleted file mode 100644 index 06ef2fb..0000000 --- a/util/util.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef UTIL_H -#define UTIL_H - -#include "legato.h" -#include - -#define HIGH 1 -#define LOW 0 - -typedef struct { - int i; - void* arr; - void* ctxp; -} FunctionalArgs; - -typedef struct { - int n; // number of elements in array - bool (*callback)(FunctionalArgs* args); // callback applied to arr[i] - void* (*derefCallback)(int i, void* j); // callback used to deference arr[i] - FunctionalArgs args; -} Functional; - -// ioutil -le_result_t readFromFile(const char* path, - void* value, - int (*scanCallback)(FILE* f, void* val)); -int scanDoubleCallback(FILE* f, void* value); -le_result_t ioutil_readIntFromFile(const char* path, int* value); -le_result_t ioutil_readDoubleFromFile(const char* filePath, double* value); -le_result_t ioutil_writeToFile(const char* path, - void* value, - size_t size, - size_t count); - -le_result_t ioutil_appendToFile(const char* path, - void* value, - size_t size, - size_t count); - -// TODO fix this name (no PascalCase) -uint64_t GetCurrentTimestamp(void); -time_t util_getMTime(char* path); -int util_getUnixDatetime(); -le_result_t util_flattenRes(le_result_t* res, int nRes); -bool util_fileExists(const char* path); -bool util_alreadyMounted(const char* devPath); -double util_avgDouble(double* readings, int nReadings); - -// TODO verify this is working -le_result_t gpio_exportPin(char* pin); -le_result_t gpio_unexportPin(char* pin); -void getGpioPath(char* outputStr, char* pin, char* subDir); -le_result_t gpio_setDirection(char* pin, char* direction); -le_result_t gpio_setInput(char* pin); -le_result_t gpio_setOutput(char* pin); -le_result_t gpio_setActiveState(char* pin, bool isActiveLow); -le_result_t gpio_isActive(char* pin, bool* isActive); -le_result_t gpio_setValue(char* pin, bool state); -le_result_t gpio_setLow(char* pin); -le_result_t gpio_setHigh(char* pin); -le_result_t gpio_setPull(char* pin, char* pull); -le_result_t gpio_pullDown(char* pin); -le_result_t gpio_pullUp(char* pin); - -void* util_find(Functional* f); - -void util_listDir(const char* dir, char* dest, size_t size); - -int fd_openSerial(const char* device, int baud); -speed_t fd_convertBaud(int baud); -int fd_puts(const int fd, const char* s); -int fd_getChar(const int fd); -void fd_flush(const int fd); -int fd_dataAvail(int fd, int* data); -void fd_flushInput(const int fd); - -#endif -- cgit v1.2.3 From 98d4719824f3cc2ed99f855bbdada129784245bf Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 16:06:47 -0800 Subject: added util to new folder --- util/util.c | 366 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util/util.h | 77 +++++++++++++ 2 files changed, 443 insertions(+) create mode 100644 util/util.c create mode 100644 util/util.h (limited to 'util') diff --git a/util/util.c b/util/util.c new file mode 100644 index 0000000..3042c22 --- /dev/null +++ b/util/util.c @@ -0,0 +1,366 @@ +#include "util.h" +#include "legato.h" +#include + +le_result_t readFromFile(const char* path, + void* value, + int (*scanCallback)(FILE* f, void* val)) { + FILE* f = fopen(path, "r"); + if (f == NULL) { + LE_WARN("Couldn't open '%s' - %m", path); + return LE_IO_ERROR; + } + int numScanned = scanCallback(f, value); + if (numScanned != 1) + return LE_FORMAT_ERROR; + fclose(f); + return LE_OK; +} + +int scanIntCallback(FILE* f, void* value) { + int* val = value; + return fscanf(f, "%d", val); +} + +int scanDoubleCallback(FILE* f, void* value) { + double* val = value; + return fscanf(f, "%lf", val); +} + +le_result_t ioutil_readIntFromFile(const char* path, int* value) { + return readFromFile(path, value, scanIntCallback); +} + +le_result_t ioutil_readDoubleFromFile(const char* path, double* value) { + return readFromFile(path, value, scanDoubleCallback); +} + +le_result_t writeToFile(const char* path, + void* value, + size_t size, + size_t count, + const char* openMode) { + FILE* f = fopen(path, openMode); + if (f == NULL) { + LE_WARN("Failed to open %s for writing", path); + return LE_IO_ERROR; + } + fwrite(value, size, count, f); + fflush(f); + fclose(f); + return LE_OK; +} + +le_result_t ioutil_writeToFile(const char* path, + void* value, + size_t size, + size_t count) { + return writeToFile(path, value, size, count, "w"); +} + +le_result_t ioutil_appendToFile(const char* path, + void* value, + size_t size, + size_t count) { + return writeToFile(path, value, size, count, "a"); +} + +le_result_t util_flattenRes(le_result_t* res, int nRes) { + for (int i = 0; i < nRes; i++) { + if (res[i] != LE_OK) + return res[i]; + } + return LE_OK; +} + +int util_getUnixDatetime() { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec; +} + +/** + * Get the last modified datetime + * of the file at path + */ +time_t util_getMTime(char* path) { + struct stat st; + if (stat(path, &st) != 0) + return -1; + else + return st.st_mtime; +} + +bool util_fileExists(const char* path) { + struct stat st; + return stat(path, &st) == 0; +} + +bool util_alreadyMounted(const char* devPath) { + char content[2048]; + FILE* f = fopen("/proc/mounts", "r"); + if (f == NULL) { + return false; + } + fread(content, sizeof(char), sizeof(content), f); + // if this ref is non-null, we found a match + return strstr(content, devPath) != NULL; +} + +uint64_t GetCurrentTimestamp(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + uint64_t utcMilliSec = + (uint64_t)(tv.tv_sec) * 1000 + (uint64_t)(tv.tv_usec) / 1000; + return utcMilliSec; +} + +// TODO verify this is working +le_result_t gpio_exportPin(char* pin) { + int len = strlen(pin); + return ioutil_writeToFile("/sys/class/gpio/export", &pin, sizeof(char), len); +} + +le_result_t gpio_unexportPin(char* pin) { + int len = strlen(pin); + return ioutil_writeToFile("/sys/class/gpio/unexport", &pin, sizeof(char), + len); +} + +void getGpioPath(char* outputStr, char* pin, char* subDir) { + sprintf(outputStr, "/sys/class/gpio/gpio%s/%s", pin, subDir); +} + +le_result_t gpio_setDirection(char* pin, char* direction) { + char path[100]; + getGpioPath(path, pin, "direction"); + return ioutil_writeToFile(path, direction, sizeof(char), strlen(direction)); +} + +le_result_t gpio_setPull(char* pin, char* pull) { + char path[100]; + getGpioPath(path, pin, "pull"); + return ioutil_writeToFile(path, pull, sizeof(char), strlen(pull)); +} + +le_result_t gpio_pullDown(char* pin) { + return gpio_setPull(pin, "down"); +} + +le_result_t gpio_pullUp(char* pin) { + return gpio_setPull(pin, "up"); +} + +le_result_t gpio_setInput(char* pin) { + return gpio_setDirection(pin, "in"); +} + +le_result_t gpio_setOutput(char* pin) { + return gpio_setDirection(pin, "out"); +} + +le_result_t gpio_setActiveState(char* pin, bool isActiveLow) { + // Any non zero value toggles the existing value + // so we must read the existing value first + char path[100]; + int isActiveLowSet; + getGpioPath(path, pin, "active_low"); + le_result_t readRes = ioutil_readIntFromFile(path, &isActiveLowSet); + le_result_t writeRes = LE_OK; + if (isActiveLow != isActiveLowSet) { + writeRes = ioutil_writeToFile(path, "1", sizeof(char), 1); + } + return readRes == LE_OK && writeRes == LE_OK ? LE_OK : LE_FAULT; +} + +le_result_t gpio_isActive(char* pin, bool* isActive) { + char path[50]; + getGpioPath(path, pin, "value"); + int val; + le_result_t readRes = ioutil_readIntFromFile(path, &val); + *isActive = val; + return readRes; +} + +le_result_t gpio_setValue(char* pin, bool state) { + char path[50]; + getGpioPath(path, pin, "value"); + char* strState = state ? "1" : "0"; + return ioutil_writeToFile(path, &strState, sizeof(char), strlen(strState)); +} + +le_result_t gpio_setLow(char* pin) { + return gpio_setValue(pin, LOW); +} + +le_result_t gpio_setHigh(char* pin) { + return gpio_setValue(pin, HIGH); +} + +void* util_find(Functional* f) { + f->args.i = 0; + while (f->args.i < f->n) { + if (f->callback(&f->args)) { + return f->derefCallback(f->args.i, f->args.arr); + } + f->args.i++; + } + return NULL; +} + +void util_listDir(const char* dir, char* dest, size_t size) { + struct dirent* de; + char toConcat[1024]; + DIR* dr = opendir(dir); + if (dr == NULL) + return; + while ((de = readdir(dr)) != NULL) { + if (de->d_name[0] != '.') { + snprintf(toConcat, size, "%s,", de->d_name); + strncat(dest, toConcat, size); + } + } + closedir(dr); +} + +/** + * Convert an integer baud rate to a speed_t + */ +speed_t fd_convertBaud(int baud) { + speed_t b; + switch (baud) { + case 50: + b = B50; + break; + case 75: + b = B75; + break; + case 110: + b = B110; + break; + case 134: + b = B134; + break; + case 150: + b = B150; + break; + case 200: + b = B200; + break; + case 300: + b = B300; + break; + case 600: + b = B600; + break; + case 1200: + b = B1200; + break; + case 1800: + b = B1800; + break; + case 2400: + b = B2400; + break; + case 9600: + b = B9600; + break; + case 19200: + b = B19200; + break; + case 38400: + b = B38400; + break; + case 57600: + b = B57600; + break; + case 115200: + b = B115200; + break; + case 230400: + b = B230400; + break; + case 921600: + b = B921600; + break; + default: + b = -2; + } + return b; +} + +/** + * Open a serial connection on device + * + * Lifted from here + * https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringSerial.c + */ +int fd_openSerial(const char* device, int baud) { + struct termios options; + speed_t binaryBaud = fd_convertBaud(baud); + int status, fd; + if ((fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1) + return -1; + fcntl(fd, F_SETFL, O_RDWR); + tcgetattr(fd, &options); + cfmakeraw(&options); + cfsetispeed(&options, binaryBaud); + cfsetospeed(&options, binaryBaud); + + options.c_cflag |= (CLOCAL | CREAD); + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + options.c_cflag &= ~CSIZE; + options.c_cflag |= CS8; + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_oflag &= ~OPOST; + + options.c_cc[VMIN] = 0; + options.c_cc[VTIME] = 10; // Ten seconds (100 deciseconds) + + tcsetattr(fd, TCSANOW | TCSAFLUSH, &options); + + ioctl(fd, TIOCMGET, &status); + + status |= TIOCM_DTR; + status |= TIOCM_RTS; + + ioctl(fd, TIOCMSET, &status); + usleep(10000); // 10mS + return fd; +} + +int fd_puts(const int fd, const char* s) { + return write(fd, s, strlen(s)); +} + +int fd_getChar(const int fd) { + uint8_t x; + + if (read(fd, &x, 1) != 1) + return -1; + + return ((int)x) & 0xFF; +} + +void fd_flush(const int fd) { + // tcflush(fd, TCIOFLUSH); + tcdrain(fd); +} + +void fd_flushInput(const int fd) { + tcflush(fd, TCIFLUSH); +} + +int fd_dataAvail(int fd, int* data) { + return ioctl(fd, FIONREAD, data); +} + +double util_avgDouble(double* readings, int nReadings) { + double sum = 0; + for (int i = 0; i < nReadings; i++) { + sum += readings[i]; + } + + return sum / nReadings; +} diff --git a/util/util.h b/util/util.h new file mode 100644 index 0000000..06ef2fb --- /dev/null +++ b/util/util.h @@ -0,0 +1,77 @@ +#ifndef UTIL_H +#define UTIL_H + +#include "legato.h" +#include + +#define HIGH 1 +#define LOW 0 + +typedef struct { + int i; + void* arr; + void* ctxp; +} FunctionalArgs; + +typedef struct { + int n; // number of elements in array + bool (*callback)(FunctionalArgs* args); // callback applied to arr[i] + void* (*derefCallback)(int i, void* j); // callback used to deference arr[i] + FunctionalArgs args; +} Functional; + +// ioutil +le_result_t readFromFile(const char* path, + void* value, + int (*scanCallback)(FILE* f, void* val)); +int scanDoubleCallback(FILE* f, void* value); +le_result_t ioutil_readIntFromFile(const char* path, int* value); +le_result_t ioutil_readDoubleFromFile(const char* filePath, double* value); +le_result_t ioutil_writeToFile(const char* path, + void* value, + size_t size, + size_t count); + +le_result_t ioutil_appendToFile(const char* path, + void* value, + size_t size, + size_t count); + +// TODO fix this name (no PascalCase) +uint64_t GetCurrentTimestamp(void); +time_t util_getMTime(char* path); +int util_getUnixDatetime(); +le_result_t util_flattenRes(le_result_t* res, int nRes); +bool util_fileExists(const char* path); +bool util_alreadyMounted(const char* devPath); +double util_avgDouble(double* readings, int nReadings); + +// TODO verify this is working +le_result_t gpio_exportPin(char* pin); +le_result_t gpio_unexportPin(char* pin); +void getGpioPath(char* outputStr, char* pin, char* subDir); +le_result_t gpio_setDirection(char* pin, char* direction); +le_result_t gpio_setInput(char* pin); +le_result_t gpio_setOutput(char* pin); +le_result_t gpio_setActiveState(char* pin, bool isActiveLow); +le_result_t gpio_isActive(char* pin, bool* isActive); +le_result_t gpio_setValue(char* pin, bool state); +le_result_t gpio_setLow(char* pin); +le_result_t gpio_setHigh(char* pin); +le_result_t gpio_setPull(char* pin, char* pull); +le_result_t gpio_pullDown(char* pin); +le_result_t gpio_pullUp(char* pin); + +void* util_find(Functional* f); + +void util_listDir(const char* dir, char* dest, size_t size); + +int fd_openSerial(const char* device, int baud); +speed_t fd_convertBaud(int baud); +int fd_puts(const int fd, const char* s); +int fd_getChar(const int fd); +void fd_flush(const int fd); +int fd_dataAvail(int fd, int* data); +void fd_flushInput(const int fd); + +#endif -- cgit v1.2.3