Skip to content

Commit

Permalink
Temporary fix for issues with thread safety
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthew Else committed Sep 11, 2015
1 parent b212138 commit cafcd0f
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 9 deletions.
74 changes: 65 additions & 9 deletions src/gattlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@

#include "gattlib.h"

#if 1
#define DEBUG(x) std::cout << "GATTRequester:" << x << std::endl;
#else
#define DEBUG(x)
#endif

#define DELAY 0.1

class PyThreadsGuard {
public:
PyThreadsGuard() : _save(NULL) {
Expand All @@ -30,6 +38,15 @@ class PyThreadsGuard {
PyThreadState* _save;
};

class PyGILGuard {
public:
PyGILGuard() { _state = PyGILState_Ensure(); }
~PyGILGuard() { PyGILState_Release(_state); }

private:
PyGILState_STATE _state;
};


IOService::IOService(bool run) {
if (run)
Expand Down Expand Up @@ -104,6 +121,8 @@ GATTRequester::GATTRequester(std::string address, bool do_connect,
_channel(NULL),
_attrib(NULL) {

//pthread_mutex_init(&_lock, NULL);

int dev_id = hci_devid(_device.c_str());
if (dev_id < 0)
throw std::runtime_error("Invalid device!");
Expand Down Expand Up @@ -131,6 +150,8 @@ GATTRequester::~GATTRequester() {
if (_attrib != NULL) {
g_attrib_unref(_attrib);
}

//pthread_mutex_destroy(&_lock);
}

void
Expand All @@ -155,6 +176,8 @@ GATTRequester::on_indication(const uint16_t handle, const std::string data) {

void
events_handler(const uint8_t* data, uint16_t size, gpointer userp) {
PyGILGuard guard;

GATTRequester* request = (GATTRequester*)userp;
uint16_t handle = htobs(bt_get_le16(&data[1]));

Expand Down Expand Up @@ -351,6 +374,8 @@ GATTRequester::read_by_handle_async(uint16_t handle, GATTResponse* response) {

boost::python::list
GATTRequester::read_by_handle(uint16_t handle) {
//pthread_mutex_lock(&_lock);

GATTResponse response;
read_by_handle_async(handle, &response);

Expand All @@ -359,6 +384,7 @@ GATTRequester::read_by_handle(uint16_t handle) {
// GLIB as callback!!
throw std::runtime_error("Device is not responding!");

//pthread_mutex_unlock(&_lock);
return response.received();
}

Expand Down Expand Up @@ -394,6 +420,8 @@ read_by_uuid_cb(guint8 status, const guint8* data,

void
GATTRequester::read_by_uuid_async(std::string uuid, GATTResponse* response) {
PyGILGuard guard;

uint16_t start = 0x0001;
uint16_t end = 0xffff;
bt_uuid_t btuuid;
Expand All @@ -409,7 +437,7 @@ GATTRequester::read_by_uuid_async(std::string uuid, GATTResponse* response) {

boost::python::list
GATTRequester::read_by_uuid(std::string uuid) {
PyThreadsGuard guard;
//pthread_mutex_lock(&_lock);
GATTResponse response;

read_by_uuid_async(uuid, &response);
Expand All @@ -419,12 +447,14 @@ GATTRequester::read_by_uuid(std::string uuid) {
// GLIB as callback!!
throw std::runtime_error("Device is not responding!");

//pthread_mutex_unlock(&_lock);
return response.received();
}

static void
write_by_handle_cb(guint8 status, const guint8* data,
guint16 size, gpointer userp) {
DEBUG("write successful");
GATTResponse* response = (GATTResponse*)userp;
if (!status && data) {
response->on_response(std::string((const char*)data, size));
Expand All @@ -435,14 +465,16 @@ write_by_handle_cb(guint8 status, const guint8* data,
void
GATTRequester::write_by_handle_async(uint16_t handle, std::string data,
GATTResponse* response) {
PyGILGuard guard;
check_channel();
gatt_write_char(_attrib, handle, (const uint8_t*)data.data(), data.size(),
write_by_handle_cb, (gpointer)response);
}

boost::python::list
GATTRequester::write_by_handle(uint16_t handle, std::string data) {
PyThreadsGuard guard;
//pthread_mutex_lock(&_lock);
usleep(DELAY * 1000000);
GATTResponse response;

write_by_handle_async(handle, data, &response);
Expand All @@ -452,16 +484,20 @@ GATTRequester::write_by_handle(uint16_t handle, std::string data) {
// GLIB as callback!!
throw std::runtime_error("Device is not responding!");

//pthread_mutex_unlock(&_lock);
return response.received();
}

void
GATTRequester::write_without_response_by_handle(uint16_t handle, std::string data) {
//PyThreadsGuard guard;
//pthread_mutex_lock(&_lock);
usleep(DELAY * 1000000);
PyGILGuard guard;

check_channel();
gatt_write_cmd(_attrib, handle, (const uint8_t*)data.data(), data.size(),
NULL, NULL);
//pthread_mutex_unlock(&_lock);
}


Expand Down Expand Up @@ -521,6 +557,7 @@ discover_primary_cb(guint8 status, GSList *services, void *userp) {

void
GATTRequester::discover_primary_async(GATTResponse* response) {
PyGILGuard guard;
check_connected();
if( not gatt_discover_primary(
_attrib, NULL, discover_primary_cb, (gpointer)response)) {
Expand All @@ -529,15 +566,18 @@ GATTRequester::discover_primary_async(GATTResponse* response) {
}

boost::python::list GATTRequester::discover_primary() {
PyThreadsGuard guard;
//pthread_mutex_lock(&_lock);
usleep(DELAY * 1000000);

GATTResponse response;
discover_primary_async(&response);
discover_primary_async(&response);

if (not response.wait(5*MAX_WAIT_FOR_PACKET))
// FIXME: now, response is deleted, but is still registered on
// GLIB as callback!!
throw std::runtime_error("Device is not responding!");

//pthread_mutex_unlock(&_lock);
return response.received();
}

Expand All @@ -554,6 +594,7 @@ static void discover_char_cb(guint8 status, GSList *characteristics,

for (GSList * l = characteristics; l; l = l->next) {
struct gatt_char *chars = (gatt_char*) l->data;
std::cout << "received something :)" << std::endl;
boost::python::dict adescr;
adescr["uuid"] = chars->uuid;
adescr["handle"] = chars->handle;
Expand All @@ -567,10 +608,16 @@ static void discover_char_cb(guint8 status, GSList *characteristics,

void GATTRequester::discover_characteristics_async(GATTResponse* response,
int start, int end, std::string uuid_str) {
PyGILGuard guard;

check_connected();

unsigned int err;

DEBUG("_attrib = " << _attrib << ", start = " << start << ", end = " << end);

DEBUG("_attrib = " << _attrib << ", start = " << start << ", end = " << end);

if (uuid_str.size() == 0) {
//TODO handle error
err = gatt_discover_char(_attrib, start, end, NULL, discover_char_cb,
Expand All @@ -585,21 +632,24 @@ void GATTRequester::discover_characteristics_async(GATTResponse* response,
(gpointer) response);
}

//std::cout << "error code: " << err << std::endl;
std::cout << "return code: " << err << std::endl;
}

boost::python::list GATTRequester::discover_characteristics(int start, int end,
std::string uuid_str) {
//PyThreadsGuard guard;
usleep(DELAY * 1000000);

GATTResponse response;

DEBUG("_attrib = " << _attrib << ", start = " << start << ", end = " << end);
discover_characteristics_async(&response, start, end, uuid_str);

if (not response.wait(5 * MAX_WAIT_FOR_PACKET))
// FIXME: now, response is deleted, but is still registered on
// GLIB as callback!!
throw std::runtime_error("Device is not responding!");
return response.received();

return response.received();
}

static void discover_desc_cb(guint8 status, GSList *characteristics,
Expand All @@ -622,6 +672,7 @@ static void discover_desc_cb(guint8 status, GSList *characteristics,
}

void GATTRequester::discover_descriptors_async(GATTResponse* response, int start, int end, std::string uuid_str) {
PyGILGuard guard;
check_connected();

if (uuid_str.size() == 0) {
Expand All @@ -640,14 +691,19 @@ void GATTRequester::discover_descriptors_async(GATTResponse* response, int start
}

boost::python::list GATTRequester::discover_descriptors(int start, int end, std::string uuid) {
PyThreadsGuard guard;
//pthread_mutex_lock(&_lock);
usleep(DELAY * 1000000);

GATTResponse response;

discover_descriptors_async(&response, start, end, uuid);

if (not response.wait(5 * MAX_WAIT_FOR_PACKET))
// FIXME: now, response is deleted, but is still registered on
// GLIB as callback!!
throw std::runtime_error("Device is not responding!");

//pthread_mutex_unlock(&_lock);
return response.received();
}

Expand Down
4 changes: 4 additions & 0 deletions src/gattlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ extern "C" {
#include "attrib/gattrib.h"
#include "attrib/gatt.h"
#include "attrib/utils.h"

#include <pthread.h>
}

#include "event.hpp"
Expand Down Expand Up @@ -106,6 +108,8 @@ class GATTRequester {
int _hci_socket;
GIOChannel* _channel;
GAttrib* _attrib;

pthread_mutex_t _lock;
};

#endif // _MIBANDA_GATTLIB_H_

0 comments on commit cafcd0f

Please sign in to comment.