commit 99702eb036df0ebe9e83ef4f91f8e84f0b9fb0d8
parent 1d29753b1e32b940260e386a0c5d3c50ade416cc
Author: amin <dev@aminmesbah.com>
Date: Sat, 28 May 2022 22:51:45 +0000
Cleanup when error; don't try to handle SIGKILL
FossilOrigin-Name: 220ac21a183fe03f6efb2fe48c51c4a8edc7b3300e49fff0dd93a815e7a894c6
Diffstat:
M | main.c | | | 180 | +++++++++++++++++++++++++++++++++++++++++-------------------------------------- |
1 file changed, 93 insertions(+), 87 deletions(-)
diff --git a/main.c b/main.c
@@ -13,7 +13,6 @@
// TODO: Use syslog.h for logging
// TODO: Make a systemd unit for this
-// TODO: cleanup on error
// https://www.kernel.org/doc/Documentation/hid/hidraw.txt
#include <linux/hidraw.h>
@@ -31,33 +30,35 @@ static void stop_running(int signal)
int main(void)
{
{
- struct sigaction act = {
+ struct sigaction act =
+ {
.sa_handler = stop_running,
};
- sigaction(SIGINT, &act, NULL);
- sigaction(SIGKILL, &act, NULL);
- sigaction(SIGTERM, &act, NULL);
+ int failure = sigaction(SIGINT, &act, NULL);
+ failure |= sigaction(SIGTERM, &act, NULL);
+ if (failure)
+ {
+ printf("ERROR: Failed to register signal handler.\n");
+ return 1;
+ }
}
+
// NOTE: Included udev rules create this symlink to the appropriate hidraw
// entry.
const char *hid_file_path = "/dev/co2mini0";
const char *temperature_file_path = "/tmp/co2minimon_temp";
const char *co2_file_path = "/tmp/co2minimon_co2";
+ bool error_occurred = false;
int device_handle = -1;
+ bool need_send_feature_report = true;
+ fd_set read_fds;
while (running)
{
if (access(hid_file_path, F_OK) != 0)
{
- {
- fd_set read_fds;
- FD_ZERO(&read_fds);
- FD_SET(device_handle, &read_fds);
- int ready = select(device_handle + 1, &read_fds, NULL, NULL, &(struct timeval){ .tv_sec = 15 });
- assert(ready != -1);
- }
if (close(device_handle) == 0)
{
device_handle = -1;
@@ -66,7 +67,7 @@ int main(void)
unlink(co2_file_path);
unlink(temperature_file_path);
- sleep(5);
+ sleep(30);
continue;
}
@@ -76,110 +77,115 @@ int main(void)
if (device_handle < 0)
{
printf("ERROR: Failed to open HID.\n");
- return 1;
+ goto error;
}
- // TODO: Try with just a 0
+ FD_ZERO(&read_fds);
+ FD_SET(device_handle, &read_fds);
+ need_send_feature_report = true;
+ }
+
+ if (need_send_feature_report) {
uint8_t key[8] = {0};
int result = ioctl(device_handle, HIDIOCSFEATURE(sizeof(key)), key);
if (result < 0 || result != sizeof(key))
{
printf("ERROR: Failed to send feature report.\n");
- return 1;
+ goto error;
}
+ need_send_feature_report = false;
}
- fd_set read_fds;
- FD_ZERO(&read_fds);
- FD_SET(device_handle, &read_fds);
errno = 0;
int ready = select(device_handle + 1, &read_fds, NULL, NULL, &(struct timeval){ .tv_sec = 15 });
- int bytes_read = 0;
- uint8_t data[8] = {0};
if (ready == -1 && errno != EINTR)
{
- assert(false);
- break;
+ printf("ERROR: Failed to select() device handle.\n");
+ goto error;
}
else if (ready == 0)
{
- // If we go too long with an empty pipe, the device may
- // have stopped sending data. Resend the feature report to
- // get it to send data again. A situation where I've
- // observed this happening is when I hibernate and resume
- // the computer. Upon resumption, all calls to read() will
- // block until we resend the feature report.
+ // select() timed out
//
- // I'm not sure why this happens, but my guess would be
- // that the device stops sending new data if the data
- // hasn't been read in a while.
- uint8_t key[8] = {0};
- int result = ioctl(device_handle, HIDIOCSFEATURE(sizeof(key)), key);
- if (result < 0 || result != sizeof(key))
- {
- printf("ERROR: Failed to send feature report.\n");
- return 1;
- }
+ // If we go too long with an empty pipe, the device may have
+ // stopped sending data. One situation where I've observed this can
+ // happen is when the system resumes from hibernation. In this
+ // case, all calls to read() will block until we resend the feature
+ // report.
+ //
+ // I'm not sure why this happens, but my guess would be that the
+ // device stops sending new data if the data hasn't been read in a
+ // while.
+ need_send_feature_report = true;
}
else
{
- bytes_read = read(device_handle, &data, sizeof(data));
- }
-
- uint8_t item = data[0];
- uint8_t msb = data[1];
- uint8_t lsb = data[2];
- uint8_t checksum = data[3];
- uint8_t end = data[4];
-
- if (bytes_read == sizeof(data)
- && end == 0x0d
- && (item == 0x42 || item == 0x50)
- && ((item + msb + lsb) & 0xFF) == checksum)
- {
- printf("write\n");
- uint16_t value = (((uint16_t)msb) << 8) | lsb;
- char buf[1024] = {0};
- int str_len = 0;
- mode_t create_mode = S_IRUSR | S_IWUSR;
- int open_mode = O_WRONLY | O_CREAT | O_TRUNC;
-
- switch(item)
+ uint8_t data[8] = {0};
+ int bytes_read = read(device_handle, &data, sizeof(data));
+
+ uint8_t item = data[0];
+ uint8_t msb = data[1];
+ uint8_t lsb = data[2];
+ uint8_t checksum = data[3];
+ uint8_t end = data[4];
+
+ if (bytes_read == sizeof(data)
+ && end == 0x0d
+ && (item == 0x42 || item == 0x50)
+ && ((item + msb + lsb) & 0xFF) == checksum)
{
- case 0x42:
+ need_send_feature_report = false;
+ uint16_t value = (((uint16_t)msb) << 8) | lsb;
+ char buf[1024] = {0};
+ int str_len = 0;
+ mode_t create_mode = S_IRUSR | S_IWUSR;
+ int open_mode = O_WRONLY | O_CREAT | O_TRUNC;
+
+ switch(item)
{
- printf("bytes T\n");
- double t_celsius = value / 16.0 - 273.15;
- str_len = snprintf(buf, sizeof(buf), "%.2f", t_celsius);
- assert(str_len > 0);
- int f = open(temperature_file_path, open_mode, create_mode);
- if (f == -1)
+ case 0x42:
{
- return 1;
- }
- write(f, buf, str_len);
- close(f);
- } break;
-
- case 0x50:
- {
- printf("bytes C\n");
- str_len = snprintf(buf, sizeof(buf), "%d", value);
- assert(str_len > 0);
- int f = open(co2_file_path, open_mode, create_mode);
- if (f == -1)
+ printf("bytes T\n");
+ double t_celsius = value / 16.0 - 273.15;
+ str_len = snprintf(buf, sizeof(buf), "%.2f", t_celsius);
+ assert(str_len > 0);
+ int f = open(temperature_file_path, open_mode, create_mode);
+ if (f == -1)
+ {
+ printf("ERROR: Failed to open output file for temperature.\n");
+ goto error;
+ }
+ write(f, buf, str_len);
+ close(f);
+ } break;
+
+ case 0x50:
{
- return 1;
- }
- write(f, buf, str_len);
- close(f);
- } break;
+ printf("bytes C\n");
+ str_len = snprintf(buf, sizeof(buf), "%d", value);
+ assert(str_len > 0);
+ int f = open(co2_file_path, open_mode, create_mode);
+ if (f == -1)
+ {
+ printf("ERROR: Failed to open output file for CO2.\n");
+ goto error;
+ }
+ write(f, buf, str_len);
+ close(f);
+ } break;
+ }
}
}
}
+ goto cleanup;
+
+error:
+ error_occurred = true;
+cleanup:
unlink(co2_file_path);
unlink(temperature_file_path);
close(device_handle);
- return 0;
+
+ return error_occurred;
}