Skip to content

Commit

Permalink
Detect suspend on linux using CLOCK_BOOTTIME
Browse files Browse the repository at this point in the history
  • Loading branch information
tatokis committed Jun 5, 2019
1 parent 85d0e48 commit 4354134
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 18 deletions.
19 changes: 19 additions & 0 deletions src/daemon/usb.c
Expand Up @@ -847,3 +847,22 @@ void print_urb_buffer(const char* prefix, const unsigned char* buffer, int actua
else
ckb_info("ckb%i %s (via %s:%d) %s %s\n", devnum, function, file, line, prefix, converted);
}

void reactivate_devices()
{
ckb_info("System has woken from sleep\n");
usbdevice *kb = NULL;
for(int i = 0; i < DEV_MAX; i++){
if(IS_CONNECTED(keyboard + i)){
kb = keyboard + i;
// If the device was active, mark it as disabled and re-enable it
pthread_mutex_lock(dmutex(kb));
if(kb->active){
kb->active = 0;
const devcmd* vt = kb->vtable;
vt->active(kb, 0, 0, 0, 0);
}
pthread_mutex_unlock(dmutex(kb));
}
}
}
3 changes: 2 additions & 1 deletion src/daemon/usb.h
Expand Up @@ -386,9 +386,10 @@ int _usbsend_control(usbdevice* kb, uchar* data, ushort len, uchar bRequest, ush
#define usbsend_control(kb, message, len, bRequest, wValue, wIndex) _usbsend_control(kb, message, len, bRequest, wValue, wIndex, __FILE_NOPATH__, __LINE__)
int os_usbsend_control(usbdevice* kb, uchar* data, ushort len, uchar bRequest, ushort wValue, ushort wIndex, const char* file, int line);


// receive message from initial sighandler socketpair communication
extern int sighandler_pipe[2];
extern void exithandler(int type);

void reactivate_devices();

#endif // USB_H
51 changes: 49 additions & 2 deletions src/daemon/usb_linux.c
Expand Up @@ -5,6 +5,7 @@
#include "usb.h"

#ifdef OS_LINUX
#include <time.h>

// usb.c
extern _Atomic int reset_stop;
Expand Down Expand Up @@ -783,6 +784,44 @@ static void udev_enum(){
udev_enumerate_unref(enumerator);
}

_Atomic int suspend_run = 1;

// While POSIX says we may need a runtime test, on Linux the clock
// was added immediately after the define was introduced, so a
// compile time check should be enough

// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=70a08cca1227dc31c784ec930099a4417a06e7d0
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7fdd7f89006dd5a4c702fa0ce0c272345fa44ae0

#ifndef CLOCK_BOOTTIME
#define CLOCK_BOOTTIME CLOCK_REALTIME
#endif

static time_t get_clock_monotonic_seconds() {
struct timespec timespec_var = {0};

if(clock_gettime(CLOCK_BOOTTIME, &timespec_var))
ckb_err("Error in clock_gettime()\n");

return timespec_var.tv_sec;
}

void* suspend_check() {
time_t prev_time = get_clock_monotonic_seconds();
if(!prev_time)
return NULL;
while(suspend_run){
clock_nanosleep(CLOCK_MONOTONIC, 0, &(struct timespec) {.tv_sec = 2}, NULL);
time_t current_time = get_clock_monotonic_seconds(NULL);

if(prev_time + 4 < current_time)
reactivate_devices();

prev_time = current_time;
}
return NULL;
}

/// \brief .
///
/// \brief usbmain is called by main() after setting up all other stuff.
Expand All @@ -796,7 +835,12 @@ int usbmain(){
ckb_fatal("Failed to initialize udev in usbmain(), usb_linux.c\n");
return -1;
}


// Create thread that detects system suspend
pthread_t suspend_thread;
pthread_create(&suspend_thread, NULL, suspend_check, NULL);
pthread_setname_np(suspend_thread, "suspend");

///
/// Enumerate all currently connected devices
udev_enum();
Expand All @@ -809,8 +853,8 @@ int usbmain(){
udev_monitor_enable_receiving(monitor);
// Get an fd for the monitor
int fd = udev_monitor_get_fd(monitor);

fd_set fds;

while(udev){
FD_ZERO(&fds);
FD_SET(fd, &fds);
Expand Down Expand Up @@ -855,6 +899,9 @@ int usbmain(){
}
}
udev_monitor_unref(monitor);
suspend_run = 0;
pthread_join(suspend_thread, NULL);

return 0;
}

Expand Down
16 changes: 1 addition & 15 deletions src/daemon/usb_mac.c
Expand Up @@ -951,21 +951,7 @@ static void iterate_devices_hid(void* context, io_iterator_t iterator){
void powerEventCallback(void *refcon, io_service_t service, uint32_t type, void *arg) {
if(type != kIOMessageSystemHasPoweredOn)
return;
ckb_info("System has woken from sleep\n");
usbdevice *kb = NULL;
for(int i = 0; i < DEV_MAX; i++){
if(IS_CONNECTED(keyboard + i)){
kb = keyboard + i;
// If the device was active, mark it as disabled and re-enable it
pthread_mutex_lock(dmutex(kb));
if(kb->active){
kb->active = 0;
const devcmd* vt = kb->vtable;
vt->active(kb, 0, 0, 0, 0);
}
pthread_mutex_unlock(dmutex(kb));
}
}
reactivate_devices();
}

///
Expand Down

0 comments on commit 4354134

Please sign in to comment.