1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-21 11:54:15 +01:00

OSX USB: Add write and read mutexs to avoid closing mid write.

This commit is contained in:
James Cotton 2012-09-10 00:32:40 -05:00
parent f8e5654ff4
commit e027c25071
3 changed files with 49 additions and 6 deletions

View File

@ -32,6 +32,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <QDebug> #include <QDebug>
#include <QMutex>
#include <QString> #include <QString>
#include "rawhid_global.h" #include "rawhid_global.h"
@ -132,6 +133,8 @@ private:
bool device_open; bool device_open;
bool unplugged; bool unplugged;
QMutex *m_writeMutex;
QMutex *m_readMutex;
#elif defined(Q_OS_UNIX) #elif defined(Q_OS_UNIX)
hid_t *first_hid; hid_t *first_hid;

View File

@ -53,10 +53,25 @@ struct timeout_info {
pjrc_rawhid::pjrc_rawhid() : pjrc_rawhid::pjrc_rawhid() :
device_open(false), hid_manager(NULL), buffer_count(0), unplugged(false) device_open(false), hid_manager(NULL), buffer_count(0), unplugged(false)
{ {
m_writeMutex = new QMutex();
m_readMutex = new QMutex();
} }
pjrc_rawhid::~pjrc_rawhid() pjrc_rawhid::~pjrc_rawhid()
{ {
if (device_open) {
close(0);
}
if (m_writeMutex) {
delete m_writeMutex;
m_writeMutex = NULL;
}
if (m_readMutex) {
delete m_readMutex;
m_readMutex = NULL;
}
} }
/** /**
@ -73,9 +88,9 @@ int pjrc_rawhid::open(int max, int vid, int pid, int usage_page, int usage)
CFMutableDictionaryRef dict; CFMutableDictionaryRef dict;
CFNumberRef num; CFNumberRef num;
IOReturn ret; IOReturn ret;
int count=0;
Q_ASSERT(hid_manager == NULL); Q_ASSERT(hid_manager == NULL);
Q_ASSERT(device_open == false);
// Start the HID Manager // Start the HID Manager
hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
@ -148,8 +163,12 @@ int pjrc_rawhid::open(int max, int vid, int pid, int usage_page, int usage)
*/ */
int pjrc_rawhid::receive(int, void *buf, int len, int timeout) int pjrc_rawhid::receive(int, void *buf, int len, int timeout)
{ {
if (!device_open) m_readMutex->lock();
if (!device_open) {
m_readMutex->unlock();
return -1; return -1;
}
// Pass information to the callback to stop this run loop and signal if a timeout occurred // Pass information to the callback to stop this run loop and signal if a timeout occurred
struct timeout_info info; struct timeout_info info;
@ -181,6 +200,8 @@ int pjrc_rawhid::receive(int, void *buf, int len, int timeout)
CFRunLoopTimerInvalidate(timer); CFRunLoopTimerInvalidate(timer);
CFRelease(timer); CFRelease(timer);
m_readMutex->unlock();
return len; return len;
} }
@ -215,10 +236,16 @@ private:
* @param[in] timeout = time to wait, in milliseconds * @param[in] timeout = time to wait, in milliseconds
* @returns number of bytes sent, or -1 on error * @returns number of bytes sent, or -1 on error
*/ */
int pjrc_rawhid::send(int num, void *buf, int len, int timeout) int pjrc_rawhid::send(int, void *buf, int len, int timeout)
{ {
if(!device_open) // This lock ensures that when closing we don't do it until the
// write has terminated (and then the device_open flag is set to false)
m_writeMutex->lock();
if(!device_open || unplugged) {
return -1; return -1;
}
uint8_t *report_buf = (uint8_t *) malloc(len); uint8_t *report_buf = (uint8_t *) malloc(len);
memcpy(&report_buf[0], buf,len); memcpy(&report_buf[0], buf,len);
@ -229,6 +256,8 @@ int pjrc_rawhid::send(int num, void *buf, int len, int timeout)
QTimer::singleShot(timeout, &el, SLOT(quit())); QTimer::singleShot(timeout, &el, SLOT(quit()));
el.exec(); el.exec();
m_writeMutex->unlock();
return sender.result; return sender.result;
} }
@ -250,6 +279,10 @@ QString pjrc_rawhid::getserial(int num) {
//! Close the HID device //! Close the HID device
void pjrc_rawhid::close(int) void pjrc_rawhid::close(int)
{ {
// Make sure any pending locks are done
m_writeMutex->lock();
m_readMutex->lock();
if (device_open) { if (device_open) {
device_open = false; device_open = false;
CFRunLoopStop(the_correct_runloop); CFRunLoopStop(the_correct_runloop);
@ -266,6 +299,12 @@ void pjrc_rawhid::close(int)
dev = NULL; dev = NULL;
hid_manager = NULL; hid_manager = NULL;
} }
// Must unlock to prevent deadlock in any read/write threads which will then fail
// because device_open is false\
m_writeMutex->unlock();
m_readMutex->unlock();
} }
/** /**

View File

@ -330,6 +330,9 @@ bool RawHID::openDevice() {
dev.close(i); dev.close(i);
} }
// Now things are opened or not (from read thread) allow the constructor to complete
m_startedMutex->unlock();
//didn't find the device we are trying to open (shouldnt happen) //didn't find the device we are trying to open (shouldnt happen)
if (opened < 0) if (opened < 0)
{ {
@ -339,8 +342,6 @@ bool RawHID::openDevice() {
m_writeThread = new RawHIDWriteThread(this); m_writeThread = new RawHIDWriteThread(this);
m_writeThread->start(); m_writeThread->start();
m_startedMutex->unlock();
return true; return true;
} }