From 757b0e853d54005db73b4725dd649e16b655b6eb Mon Sep 17 00:00:00 2001 From: Tasos Sahanidis Date: Tue, 26 Oct 2021 02:25:39 +0300 Subject: [PATCH] Fix data race when accessing dongle children --- src/daemon/device.c | 5 +++-- src/daemon/device.h | 4 ++++ src/daemon/device_bragi.c | 2 ++ src/daemon/keymap.c | 2 ++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/daemon/device.c b/src/daemon/device.c index ef314e60..554aac91 100644 --- a/src/daemon/device.c +++ b/src/daemon/device.c @@ -17,6 +17,7 @@ pthread_cond_t macrovar[DEV_MAX] = { [0 ... DEV_MAX-1] = PTHREAD_COND_INITIALIZE pthread_cond_t macroint[DEV_MAX]; ///< Should a macro thread's sleep be interrupted, due to repeated key press? pthread_mutex_t interruptmutex[DEV_MAX] = { [0 ... DEV_MAX-1] = PTHREAD_MUTEX_INITIALIZER };///< Used for interrupt transfers pthread_cond_t interruptcond[DEV_MAX]; ///< Same as above +pthread_mutex_t childrenmutex[DEV_MAX] = { [0 ... DEV_MAX-1] = PTHREAD_MUTEX_INITIALIZER }; /// /// \brief cond_nanosleep matches semantics of pthread_cond_timedwait, but with a relative wake time @@ -175,7 +176,7 @@ int _start_dev(usbdevice* kb, int makeactive){ /// if(IS_SINGLE_EP(kb)) kb->features &= ~FEAT_BIND; - + /// /// The Polaris doesn't support hardware profiles, so remove the FEAT_HWLOAD bit. /// @@ -187,7 +188,7 @@ int _start_dev(usbdevice* kb, int makeactive){ /// if(USES_FILE_HWSAVE(kb)) kb->features &= ~FEAT_HWLOAD; - + /// /// K66 has no backlight /// diff --git a/src/daemon/device.h b/src/daemon/device.h index c14ff49b..dd6e5cd3 100644 --- a/src/daemon/device.h +++ b/src/daemon/device.h @@ -60,6 +60,10 @@ extern pthread_mutex_t interruptmutex[DEV_MAX]; extern pthread_cond_t interruptcond[DEV_MAX]; #define intcond(kb) (interruptcond + INDEX_OF(kb, keyboard)) +// Mutex to access the children for each device +extern pthread_mutex_t childrenmutex[DEV_MAX]; +#define cmutex(kb) (childrenmutex + INDEX_OF(kb, keyboard)) + int init_cond_monotonic(void); // Sets up device hardware, after software initialization is finished. Also used during resets diff --git a/src/daemon/device_bragi.c b/src/daemon/device_bragi.c index 3811e6b8..623377ad 100644 --- a/src/daemon/device_bragi.c +++ b/src/daemon/device_bragi.c @@ -205,7 +205,9 @@ static inline int bragi_dongle_probe(usbdevice* kb){ subkb->bragi_child_id = i; // Add the device to our children array + pthread_mutex_lock(cmutex(kb)); kb->children[i-1] = subkb; + pthread_mutex_unlock(cmutex(kb)); // Fill dev information ushort vid = bragi_get_property(subkb, BRAGI_VID); diff --git a/src/daemon/keymap.c b/src/daemon/keymap.c index 9e484b14..76014206 100644 --- a/src/daemon/keymap.c +++ b/src/daemon/keymap.c @@ -590,6 +590,7 @@ void process_input_urb(void* context, unsigned char* buffer, int urblen, ushort // All device specific events have the max length of bytes usbdevice* targetkb = kb; if(kb->protocol == PROTO_BRAGI && IS_DONGLE(kb)){ + pthread_mutex_lock(cmutex(kb)); if(urblen == kb->out_ep_packet_size){ // Extract the device id int devid = firstbyte & 0x7; @@ -608,6 +609,7 @@ void process_input_urb(void* context, unsigned char* buffer, int urblen, ushort ckb_err("kb->children[0] is NULL"); #endif } + pthread_mutex_unlock(cmutex(kb)); } // If the response starts with CMD_GET (0x0e) for NXP, or it came from a bragi command EP, that means it needs to go to os_usbrecv()