diff --git a/src/BluetoothHciSocket.cpp b/src/BluetoothHciSocket.cpp index fd52a21..b951fe2 100644 --- a/src/BluetoothHciSocket.cpp +++ b/src/BluetoothHciSocket.cpp @@ -9,11 +9,11 @@ #include "BluetoothHciSocket.h" -#define BTPROTO_L2CAP 0 -#define BTPROTO_HCI 1 +#define BTPROTO_L2CAP 0 +#define BTPROTO_HCI 1 -#define SOL_HCI 0 -#define HCI_FILTER 2 +#define SOL_HCI 0 +#define HCI_FILTER 2 #define HCIGETDEVLIST _IOR('H', 210, int) #define HCIGETDEVINFO _IOR('H', 211, int) @@ -22,17 +22,18 @@ #define HCI_CHANNEL_USER 1 #define HCI_CHANNEL_CONTROL 3 -#define HCI_DEV_NONE 0xffff +#define HCI_DEV_NONE 0xffff #define HCI_MAX_DEV 16 #define ATT_CID 4 -#define HCI_BLE_NO_CON 0 -#define HCI_BLE_CON 1 -#define HCI_BLE_ENCH_CON 2 +#define HCI_BLE_NO_CON 0 +#define HCI_BLE_CON 1 +#define HCI_BLE_ENCH_CON 2 -enum { +enum +{ HCI_UP, HCI_INIT, HCI_RUNNING, @@ -46,32 +47,36 @@ enum { HCI_RAW, }; -struct sockaddr_hci { - sa_family_t hci_family; - unsigned short hci_dev; - unsigned short hci_channel; +struct sockaddr_hci +{ + sa_family_t hci_family; + unsigned short hci_dev; + unsigned short hci_channel; }; -struct hci_dev_req { +struct hci_dev_req +{ uint16_t dev_id; uint32_t dev_opt; }; -struct hci_dev_list_req { +struct hci_dev_list_req +{ uint16_t dev_num; struct hci_dev_req dev_req[0]; }; -struct hci_dev_info { +struct hci_dev_info +{ uint16_t dev_id; - char name[8]; + char name[8]; bdaddr_t bdaddr; uint32_t flags; - uint8_t type; + uint8_t type; - uint8_t features[8]; + uint8_t features[8]; uint32_t pkt_type; uint32_t link_policy; @@ -95,12 +100,12 @@ struct hci_dev_info { uint32_t byte_tx; }; - using namespace v8; Nan::Persistent BluetoothHciSocket::constructor_template; -NAN_MODULE_INIT(BluetoothHciSocket::Init) { +NAN_MODULE_INIT(BluetoothHciSocket::Init) +{ Nan::HandleScope scope; Local tmpl = Nan::New(New); @@ -123,24 +128,25 @@ NAN_MODULE_INIT(BluetoothHciSocket::Init) { Nan::Set(target, Nan::New("BluetoothHciSocket").ToLocalChecked(), Nan::GetFunction(tmpl).ToLocalChecked()); } -BluetoothHciSocket::BluetoothHciSocket() : - node::ObjectWrap(), - _mode(0), - _socket(-1), - _devId(0), - _pollHandle(), - _address(), - _addressType(0) - { +BluetoothHciSocket::BluetoothHciSocket() : node::ObjectWrap(), + _mode(0), + _socket(-1), + _devId(0), + _pollHandle(), + _address(), + _addressType(0) +{ int fd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI); - if (fd == -1) { + if (fd == -1) + { Nan::ThrowError(Nan::ErrnoException(errno, "socket")); return; } this->_socket = fd; - if (uv_poll_init(uv_default_loop(), &this->_pollHandle, this->_socket) < 0) { + if (uv_poll_init(uv_default_loop(), &this->_pollHandle, this->_socket) < 0) + { Nan::ThrowError("uv_poll_init failed"); return; } @@ -148,25 +154,31 @@ BluetoothHciSocket::BluetoothHciSocket() : this->_pollHandle.data = this; } -BluetoothHciSocket::~BluetoothHciSocket() { - uv_close((uv_handle_t*)&this->_pollHandle, (uv_close_cb)BluetoothHciSocket::PollCloseCallback); +BluetoothHciSocket::~BluetoothHciSocket() +{ + uv_close((uv_handle_t *)&this->_pollHandle, (uv_close_cb)BluetoothHciSocket::PollCloseCallback); close(this->_socket); } -void BluetoothHciL2Socket::connect(){ +void BluetoothHciL2Socket::connect() +{ _socket = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); - if(_socket < 0) return; + if (_socket < 0) + return; - if (bind(_socket, (struct sockaddr*)&l2_src, sizeof(l2_src)) < 0) { + if (bind(_socket, (struct sockaddr *)&l2_src, sizeof(l2_src)) < 0) + { close(_socket); _socket = -1; return; } // the kernel needs to flush the socket before we continue - while (::connect(_socket, (struct sockaddr *)&l2_dst, sizeof(l2_dst)) == -1 ) { - if(errno == EINTR) { + while (::connect(_socket, (struct sockaddr *)&l2_dst, sizeof(l2_dst)) == -1) + { + if (errno == EINTR) + { continue; } close(_socket); @@ -175,64 +187,75 @@ void BluetoothHciL2Socket::connect(){ } } -void BluetoothHciL2Socket::disconnect(){ - if(this->_socket != -1) close(this->_socket); +void BluetoothHciL2Socket::disconnect() +{ + if (this->_socket != -1) + close(this->_socket); this->_socket = -1; } -void BluetoothHciL2Socket::expires(uint64_t expires){ +void BluetoothHciL2Socket::expires(uint64_t expires) +{ _expires = expires; } -uint64_t BluetoothHciL2Socket::expires() const { +uint64_t BluetoothHciL2Socket::expires() const +{ return _expires; } -bool BluetoothHciL2Socket::connected() const { +bool BluetoothHciL2Socket::connected() const +{ return this->_socket != -1; } -BluetoothHciL2Socket::BluetoothHciL2Socket(BluetoothHciSocket* parent, unsigned char* srcaddr, char srcType, char* bdaddr, char bdaddrType, uint64_t expires): _parent(parent), _expires(expires), l2_src({}), l2_dst({}) { - unsigned short l2cid; +BluetoothHciL2Socket::BluetoothHciL2Socket(BluetoothHciSocket *parent, unsigned char *srcaddr, char srcType, char *bdaddr, char bdaddrType, uint64_t expires) : _parent(parent), _expires(expires), l2_src({}), l2_dst({}) +{ + unsigned short l2cid; #if __BYTE_ORDER == __LITTLE_ENDIAN - l2cid = ATT_CID; + l2cid = ATT_CID; #elif __BYTE_ORDER == __BIG_ENDIAN - l2cid = bswap_16(ATT_CID); + l2cid = bswap_16(ATT_CID); #else - #error "Unknown byte order" +#error "Unknown byte order" #endif - - memset(&l2_src, 0, sizeof(l2_src)); - l2_src.l2_family = AF_BLUETOOTH; - l2_src.l2_cid = l2cid; - memcpy(&l2_src.l2_bdaddr, srcaddr, sizeof(l2_src.l2_bdaddr)); - l2_src.l2_bdaddr_type = srcType; - - memset(&l2_dst, 0, sizeof(l2_dst)); - l2_dst.l2_family = AF_BLUETOOTH; - memcpy(&l2_dst.l2_bdaddr, bdaddr, sizeof(l2_dst.l2_bdaddr)); - l2_dst.l2_cid = l2cid; - l2_dst.l2_bdaddr_type = bdaddrType; // BDADDR_LE_PUBLIC (0x01), BDADDR_LE_RANDOM (0x02) - - connect(); -} - - -BluetoothHciL2Socket::~BluetoothHciL2Socket(){ - if(this->_socket != -1) disconnect(); - if(_expires == 0){ + + memset(&l2_src, 0, sizeof(l2_src)); + l2_src.l2_family = AF_BLUETOOTH; + l2_src.l2_cid = l2cid; + memcpy(&l2_src.l2_bdaddr, srcaddr, sizeof(l2_src.l2_bdaddr)); + l2_src.l2_bdaddr_type = srcType; + + memset(&l2_dst, 0, sizeof(l2_dst)); + l2_dst.l2_family = AF_BLUETOOTH; + memcpy(&l2_dst.l2_bdaddr, bdaddr, sizeof(l2_dst.l2_bdaddr)); + l2_dst.l2_cid = l2cid; + l2_dst.l2_bdaddr_type = bdaddrType; // BDADDR_LE_PUBLIC (0x01), BDADDR_LE_RANDOM (0x02) + + connect(); +} + +BluetoothHciL2Socket::~BluetoothHciL2Socket() +{ + if (this->_socket != -1) + disconnect(); + if (_expires == 0) + { this->_parent->_l2sockets_connected.erase(l2_dst.l2_bdaddr); } } -void BluetoothHciSocket::start() { - if (uv_poll_start(&this->_pollHandle, UV_READABLE, BluetoothHciSocket::PollCallback) < 0) { +void BluetoothHciSocket::start() +{ + if (uv_poll_start(&this->_pollHandle, UV_READABLE, BluetoothHciSocket::PollCallback) < 0) + { Nan::ThrowError("uv_poll_start failed"); } } -int BluetoothHciSocket::bindRaw(int* devId) { +int BluetoothHciSocket::bindRaw(int *devId) +{ struct sockaddr_hci a = {}; struct hci_dev_info di = {}; @@ -244,7 +267,8 @@ int BluetoothHciSocket::bindRaw(int* devId) { this->_devId = a.hci_dev; this->_mode = HCI_CHANNEL_RAW; - if (bind(this->_socket, (struct sockaddr *) &a, sizeof(a)) < 0) { + if (bind(this->_socket, (struct sockaddr *)&a, sizeof(a)) < 0) + { Nan::ThrowError(Nan::ErrnoException(errno, "bind")); return -1; } @@ -255,11 +279,13 @@ int BluetoothHciSocket::bindRaw(int* devId) { memset(_address, 0, sizeof(_address)); _addressType = 0; - if (ioctl(this->_socket, HCIGETDEVINFO, (void *)&di) > -1) { + if (ioctl(this->_socket, HCIGETDEVINFO, (void *)&di) > -1) + { memcpy(_address, &di.bdaddr, sizeof(di.bdaddr)); _addressType = di.type; - if (_addressType == 3) { + if (_addressType == 3) + { // 3 is a weird type, use 1 (public) instead _addressType = 1; } @@ -268,7 +294,8 @@ int BluetoothHciSocket::bindRaw(int* devId) { return this->_devId; } -int BluetoothHciSocket::bindUser(int* devId) { +int BluetoothHciSocket::bindUser(int *devId) +{ struct sockaddr_hci a = {}; memset(&a, 0, sizeof(a)); @@ -279,7 +306,8 @@ int BluetoothHciSocket::bindUser(int* devId) { this->_devId = a.hci_dev; this->_mode = HCI_CHANNEL_USER; - if (bind(this->_socket, (struct sockaddr *) &a, sizeof(a)) < 0) { + if (bind(this->_socket, (struct sockaddr *)&a, sizeof(a)) < 0) + { Nan::ThrowError(Nan::ErrnoException(errno, "bind")); return -1; } @@ -287,7 +315,8 @@ int BluetoothHciSocket::bindUser(int* devId) { return this->_devId; } -void BluetoothHciSocket::bindControl() { +void BluetoothHciSocket::bindControl() +{ struct sockaddr_hci a = {}; memset(&a, 0, sizeof(a)); @@ -297,33 +326,39 @@ void BluetoothHciSocket::bindControl() { this->_mode = HCI_CHANNEL_CONTROL; - if (bind(this->_socket, (struct sockaddr *) &a, sizeof(a)) < 0) { + if (bind(this->_socket, (struct sockaddr *)&a, sizeof(a)) < 0) + { Nan::ThrowError(Nan::ErrnoException(errno, "bind")); return; } } -bool BluetoothHciSocket::isDevUp() { +bool BluetoothHciSocket::isDevUp() +{ struct hci_dev_info di = {}; bool isUp = false; memset(&di, 0x00, sizeof(di)); di.dev_id = this->_devId; - if (ioctl(this->_socket, HCIGETDEVINFO, (void *)&di) > -1) { + if (ioctl(this->_socket, HCIGETDEVINFO, (void *)&di) > -1) + { isUp = (di.flags & (1 << HCI_UP)) != 0; } return isUp; } -void BluetoothHciSocket::setFilter(char* data, int length) { - if (setsockopt(this->_socket, SOL_HCI, HCI_FILTER, data, length) < 0) { +void BluetoothHciSocket::setFilter(char *data, int length) +{ + if (setsockopt(this->_socket, SOL_HCI, HCI_FILTER, data, length) < 0) + { this->emitErrnoError("setsockopt"); } } -void BluetoothHciSocket::poll() { +void BluetoothHciSocket::poll() +{ Nan::HandleScope scope; int length = 0; @@ -331,75 +366,85 @@ void BluetoothHciSocket::poll() { length = read(this->_socket, data, sizeof(data)); - if (length > 0) { - if (this->_mode == HCI_CHANNEL_RAW) { + if (length > 0) + { + if (this->_mode == HCI_CHANNEL_RAW) + { // TODO: This does not check for the retval of this function – should it? this->kernelDisconnectWorkArounds(length, data); } Local argv[2] = { - Nan::New("data").ToLocalChecked(), - Nan::CopyBuffer(data, length).ToLocalChecked() - }; + Nan::New("data").ToLocalChecked(), + Nan::CopyBuffer(data, length).ToLocalChecked()}; Nan::AsyncResource res("BluetoothHciSocket::poll"); res.runInAsyncScope( - Nan::New(this->This), - Nan::New("emit").ToLocalChecked(), - 2, - argv - ).FromMaybe(v8::Local()); + Nan::New(this->This), + Nan::New("emit").ToLocalChecked(), + 2, + argv) + .FromMaybe(v8::Local()); } } -void BluetoothHciSocket::stop() { +void BluetoothHciSocket::stop() +{ uv_poll_stop(&this->_pollHandle); } -void BluetoothHciSocket::write_(char* data, int length) { - if (this->_mode == HCI_CHANNEL_RAW && this->kernelConnectWorkArounds(data, length)) { +void BluetoothHciSocket::write_(char *data, int length) +{ + if (this->_mode == HCI_CHANNEL_RAW && this->kernelConnectWorkArounds(data, length)) + { return; } - if (write(this->_socket, data, length) < 0) { + if (write(this->_socket, data, length) < 0) + { this->emitErrnoError("write"); } } -void BluetoothHciSocket::emitErrnoError(const char *syscall) { +void BluetoothHciSocket::emitErrnoError(const char *syscall) +{ v8::Local error = Nan::ErrnoException(errno, syscall, strerror(errno)); Local argv[2] = { - Nan::New("error").ToLocalChecked(), - error - }; + Nan::New("error").ToLocalChecked(), + error}; Nan::AsyncResource res("BluetoothHciSocket::emitErrnoError"); res.runInAsyncScope( - Nan::New(this->This), - Nan::New("emit").ToLocalChecked(), - 2, - argv - ).FromMaybe(v8::Local()); + Nan::New(this->This), + Nan::New("emit").ToLocalChecked(), + 2, + argv) + .FromMaybe(v8::Local()); } -int BluetoothHciSocket::devIdFor(const int* pDevId, bool isUp) { +int BluetoothHciSocket::devIdFor(const int *pDevId, bool isUp) +{ int devId = 0; // default - if (pDevId == nullptr) { + if (pDevId == nullptr) + { struct hci_dev_list_req *dl; struct hci_dev_req *dr; - dl = (hci_dev_list_req*)calloc(HCI_MAX_DEV * sizeof(*dr) + sizeof(*dl), 1); + dl = (hci_dev_list_req *)calloc(HCI_MAX_DEV * sizeof(*dr) + sizeof(*dl), 1); dr = dl->dev_req; dl->dev_num = HCI_MAX_DEV; - if (ioctl(this->_socket, HCIGETDEVLIST, dl) > -1) { - for (int i = 0; i < dl->dev_num; i++, dr++) { + if (ioctl(this->_socket, HCIGETDEVLIST, dl) > -1) + { + for (int i = 0; i < dl->dev_num; i++, dr++) + { bool devUp = dr->dev_opt & (1 << HCI_UP); bool match = (isUp == devUp); - if (match) { + if (match) + { // choose the first device that is match // later on, it would be good to also HCIGETDEVINFO and check the HCI_RAW flag devId = dr->dev_id; @@ -409,14 +454,17 @@ int BluetoothHciSocket::devIdFor(const int* pDevId, bool isUp) { } free(dl); - } else { + } + else + { devId = *pDevId; } return devId; } -int BluetoothHciSocket::kernelDisconnectWorkArounds(int length, char* data) { +int BluetoothHciSocket::kernelDisconnectWorkArounds(int length, char *data) +{ // HCI Event - LE Meta Event - LE Connection Complete => manually create L2CAP socket to force kernel to book keep // this socket will be closed immediately. @@ -429,8 +477,9 @@ int BluetoothHciSocket::kernelDisconnectWorkArounds(int length, char* data) { // data[5,6] = handle (little endian) // data[7] = role (0x00 = Master) // data[9,] = device bt address - if ((length == 22 && data[0] == 0x04 && data[1] == 0x3e && data[2] == 0x13 && data[3] == 0x01 && data[4] == 0x00) || - (length == 34 && data[0] == 0x04 && data[1] == 0x3e && data[2] == 0x1f && data[3] == 0x0a && data[4] == 0x00)) { // && data[7] == 0x01 + if ((length == 22 && data[0] == 0x04 && data[1] == 0x3e && data[2] == 0x13 && data[3] == 0x01 && data[4] == 0x00) || + (length == 34 && data[0] == 0x04 && data[1] == 0x3e && data[2] == 0x1f && data[3] == 0x0a && data[4] == 0x00)) + { // && data[7] == 0x01 unsigned short handle = *((unsigned short *)(&data[5])); // if (data[3] == 0x01) // printf("HCI_EV_LE_CONN_COMPLETE for handle %d\n", handle); @@ -439,41 +488,49 @@ int BluetoothHciSocket::kernelDisconnectWorkArounds(int length, char* data) { std::shared_ptr l2socket_ptr; - auto it = _l2sockets_connected.find(*(bdaddr_t*)&data[9]); - if(it != _l2sockets_connected.end()){ + auto it = _l2sockets_connected.find(*(bdaddr_t *)&data[9]); + if (it != _l2sockets_connected.end()) + { l2socket_ptr = it->second.lock(); - } else { - auto it2 = _l2sockets_connecting.find(*(bdaddr_t*)&data[9]); + } + else + { + auto it2 = _l2sockets_connecting.find(*(bdaddr_t *)&data[9]); - if(it2 != _l2sockets_connecting.end()){ - //successful connection (we have a handle for the socket!) + if (it2 != _l2sockets_connecting.end()) + { + // successful connection (we have a handle for the socket!) l2socket_ptr = it2->second; l2socket_ptr->expires(0); _l2sockets_connecting.erase(it2); - } else { + } + else + { l2socket_ptr = std::make_shared(this, _address, _addressType, &data[9], data[8] + 1, 0); - if(!l2socket_ptr->connected()){ - //printf("%02x:%02x:%02x:%02x:%02x:%02x handle %d was not connected\n", data[9], data[10], data[11], data[12], data[13], data[14], handle); + if (!l2socket_ptr->connected()) + { + // printf("%02x:%02x:%02x:%02x:%02x:%02x handle %d was not connected\n", data[9], data[10], data[11], data[12], data[13], data[14], handle); return 0; } - this->_l2sockets_connected[*(bdaddr_t*)&data[9]] = l2socket_ptr; + this->_l2sockets_connected[*(bdaddr_t *)&data[9]] = l2socket_ptr; } } - - if(!l2socket_ptr->connected()){ - //printf("%02x:%02x:%02x:%02x:%02x:%02x handle %d was not connected (2)\n", data[9], data[10], data[11], data[12], data[13], data[14], handle); + if (!l2socket_ptr->connected()) + { + // printf("%02x:%02x:%02x:%02x:%02x:%02x handle %d was not connected (2)\n", data[9], data[10], data[11], data[12], data[13], data[14], handle); return 0; } - handle = handle % 256; this->_l2sockets_handles[handle] = l2socket_ptr; - } else if (length == 7 && data[0] == 0x04 && data[1] == 0x05 && data[2] == 0x04 && data[3] == 0x00) { + } + else if (length == 7 && data[0] == 0x04 && data[1] == 0x05 && data[2] == 0x04 && data[3] == 0x00) + { // HCI Event - Disconn Complete =======================> close socket from above - unsigned short handle = *((unsigned short*)(&data[4])); - //printf("Disconn Complete for handle %d (%d)\n", handle, this->_l2sockets_handles.count(handle)); + unsigned short handle = *((unsigned short *)(&data[4])); + // printf("Disconn Complete for handle %d (%d)\n", handle, this->_l2sockets_handles.count(handle)); handle = handle % 256; this->_l2sockets_handles.erase(handle); } @@ -485,23 +542,22 @@ void BluetoothHciSocket::setConnectionParameters( unsigned short connMinInterval, unsigned short connMaxInterval, unsigned short connLatency, - unsigned short supervisionTimeout -){ - char command[128]; + unsigned short supervisionTimeout) +{ + char command[128]; - // override the HCI devices connection parameters using debugfs - sprintf(command, "echo %u > /sys/kernel/debug/bluetooth/hci%d/conn_min_interval", connMinInterval, this->_devId); - system(command); - sprintf(command, "echo %u > /sys/kernel/debug/bluetooth/hci%d/conn_max_interval", connMaxInterval, this->_devId); - system(command); - sprintf(command, "echo %u > /sys/kernel/debug/bluetooth/hci%d/conn_latency", connLatency, this->_devId); - system(command); - sprintf(command, "echo %u > /sys/kernel/debug/bluetooth/hci%d/supervision_timeout", supervisionTimeout, this->_devId); - system(command); + // override the HCI devices connection parameters using debugfs + sprintf(command, "echo %u > /sys/kernel/debug/bluetooth/hci%d/conn_min_interval", connMinInterval, this->_devId); + system(command); + sprintf(command, "echo %u > /sys/kernel/debug/bluetooth/hci%d/conn_max_interval", connMaxInterval, this->_devId); + system(command); + sprintf(command, "echo %u > /sys/kernel/debug/bluetooth/hci%d/conn_latency", connLatency, this->_devId); + system(command); + sprintf(command, "echo %u > /sys/kernel/debug/bluetooth/hci%d/supervision_timeout", supervisionTimeout, this->_devId); + system(command); } - -bool BluetoothHciSocket::kernelConnectWorkArounds(char* data, int length) +bool BluetoothHciSocket::kernelConnectWorkArounds(char *data, int length) { // if statement: // data[0]: HCI_COMMAND_PKT @@ -514,7 +570,8 @@ bool BluetoothHciSocket::kernelConnectWorkArounds(char* data, int length) unsigned short supervisionTimeout = 0; unsigned short connection = HCI_BLE_NO_CON; - if (length == 29 && data[0] == 0x01 && data[1] == 0x0d && data[2] == 0x20 && data[3] == 0x19) { + if (length == 29 && data[0] == 0x01 && data[1] == 0x0d && data[2] == 0x20 && data[3] == 0x19) + { // printf("HCI_OP_LE_CREATE_CONN %02x:%02x:%02x:%02x:%02x:%02x\n", data[10], data[11], data[12], data[13], data[14], data[15]); connection = HCI_BLE_CON; // extract the connection parameter @@ -522,7 +579,9 @@ bool BluetoothHciSocket::kernelConnectWorkArounds(char* data, int length) connMaxInterval = (data[20] << 8) | data[19]; connLatency = (data[22] << 8) | data[21]; supervisionTimeout = (data[24] << 8) | data[23]; - } else if (length == 46 && data[0] == 0x01 && data[1] == 0x43 && data[2] == 0x20 && data[3] == 0x2a) { + } + else if (length == 46 && data[0] == 0x01 && data[1] == 0x43 && data[2] == 0x20 && data[3] == 0x2a) + { // printf("HCI_OP_LE_CREATE_ENCH_CONN %02x:%02x:%02x:%02x:%02x:%02x\n", data[7], data[8], data[9], data[10], data[11], data[12]); connection = HCI_BLE_ENCH_CON; // extract the connection parameter @@ -532,31 +591,37 @@ bool BluetoothHciSocket::kernelConnectWorkArounds(char* data, int length) supervisionTimeout = (data[25] << 8) | data[24]; } - if (connection) { + if (connection) + { this->setConnectionParameters(connMinInterval, connMaxInterval, connLatency, supervisionTimeout); std::shared_ptr l2socket_ptr; - if (this->_l2sockets_connected.find(*(bdaddr_t*)&data[10]) != this->_l2sockets_connected.end() || - this->_l2sockets_connected.find(*(bdaddr_t*)&data[7]) != this->_l2sockets_connected.end()){ + if (this->_l2sockets_connected.find(*(bdaddr_t *)&data[10]) != this->_l2sockets_connected.end() || + this->_l2sockets_connected.find(*(bdaddr_t *)&data[7]) != this->_l2sockets_connected.end()) + { // we are refreshing the connection (which was connected) if (connection == HCI_BLE_CON) - l2socket_ptr = this->_l2sockets_connected[*(bdaddr_t*)&data[10]].lock(); + l2socket_ptr = this->_l2sockets_connected[*(bdaddr_t *)&data[10]].lock(); else - l2socket_ptr = this->_l2sockets_connected[*(bdaddr_t*)&data[7]].lock(); + l2socket_ptr = this->_l2sockets_connected[*(bdaddr_t *)&data[7]].lock(); l2socket_ptr->disconnect(); l2socket_ptr->connect(); // no expiration as we will continue to be "connected" on the other handle which must exist - } else if (this->_l2sockets_connecting.find(*(bdaddr_t*)&data[10]) != this->_l2sockets_connecting.end() || - this->_l2sockets_connecting.find(*(bdaddr_t*)&data[7]) != this->_l2sockets_connecting.end()) { + } + else if (this->_l2sockets_connecting.find(*(bdaddr_t *)&data[10]) != this->_l2sockets_connecting.end() || + this->_l2sockets_connecting.find(*(bdaddr_t *)&data[7]) != this->_l2sockets_connecting.end()) + { // we were connecting but now we connect again if (connection == HCI_BLE_CON) - l2socket_ptr = this->_l2sockets_connecting[*(bdaddr_t*)&data[10]]; + l2socket_ptr = this->_l2sockets_connecting[*(bdaddr_t *)&data[10]]; else - l2socket_ptr = this->_l2sockets_connecting[*(bdaddr_t*)&data[7]]; + l2socket_ptr = this->_l2sockets_connecting[*(bdaddr_t *)&data[7]]; l2socket_ptr->disconnect(); l2socket_ptr->connect(); l2socket_ptr->expires(uv_hrtime() + L2_CONNECT_TIMEOUT); - } else{ + } + else + { // 60000000000 = 1 minute if (connection == HCI_BLE_CON) l2socket_ptr = std::make_shared(this, _address, _addressType, &data[10], data[9] + 1, uv_hrtime() + L2_CONNECT_TIMEOUT); @@ -567,9 +632,9 @@ bool BluetoothHciSocket::kernelConnectWorkArounds(char* data, int length) return false; if (connection == HCI_BLE_CON) - this->_l2sockets_connecting[*(bdaddr_t*)&data[10]] = l2socket_ptr; + this->_l2sockets_connecting[*(bdaddr_t *)&data[10]] = l2socket_ptr; else - this->_l2sockets_connecting[*(bdaddr_t*)&data[7]] = l2socket_ptr; + this->_l2sockets_connecting[*(bdaddr_t *)&data[7]] = l2socket_ptr; } // returns true to skip sending the kernel this commoand // the command will instead be sent by the connect() operation @@ -579,15 +644,16 @@ bool BluetoothHciSocket::kernelConnectWorkArounds(char* data, int length) return false; } -NAN_METHOD(BluetoothHciSocket::Cleanup) { - BluetoothHciSocket* p = node::ObjectWrap::Unwrap(info.This()); +NAN_METHOD(BluetoothHciSocket::Cleanup) +{ + BluetoothHciSocket *p = node::ObjectWrap::Unwrap(info.This()); auto now = uv_hrtime(); for (auto it = p->_l2sockets_connecting.cbegin(); it != p->_l2sockets_connecting.cend() /* not hoisted */; /* no increment */) { if (now < it->second->expires()) { - p->_l2sockets_connecting.erase(it++); // or "it = m.erase(it)" since C++11 + p->_l2sockets_connecting.erase(it++); // or "it = m.erase(it)" since C++11 } else { @@ -596,36 +662,41 @@ NAN_METHOD(BluetoothHciSocket::Cleanup) { } } -NAN_METHOD(BluetoothHciSocket::New) { +NAN_METHOD(BluetoothHciSocket::New) +{ Nan::HandleScope scope; - BluetoothHciSocket* p = new BluetoothHciSocket(); + BluetoothHciSocket *p = new BluetoothHciSocket(); p->Wrap(info.This()); p->This.Reset(info.This()); info.GetReturnValue().Set(info.This()); } -NAN_METHOD(BluetoothHciSocket::Start) { +NAN_METHOD(BluetoothHciSocket::Start) +{ Nan::HandleScope scope; - BluetoothHciSocket* p = node::ObjectWrap::Unwrap(info.This()); + BluetoothHciSocket *p = node::ObjectWrap::Unwrap(info.This()); p->start(); info.GetReturnValue().SetUndefined(); } -NAN_METHOD(BluetoothHciSocket::BindRaw) { +NAN_METHOD(BluetoothHciSocket::BindRaw) +{ Nan::HandleScope scope; - BluetoothHciSocket* p = node::ObjectWrap::Unwrap(info.This()); + BluetoothHciSocket *p = node::ObjectWrap::Unwrap(info.This()); int devId = 0; - int* pDevId = nullptr; + int *pDevId = nullptr; - if (info.Length() > 0) { + if (info.Length() > 0) + { Local arg0 = info[0]; - if (arg0->IsInt32() || arg0->IsUint32()) { + if (arg0->IsInt32() || arg0->IsUint32()) + { devId = Nan::To(arg0).FromJust(); pDevId = &devId; @@ -637,17 +708,20 @@ NAN_METHOD(BluetoothHciSocket::BindRaw) { info.GetReturnValue().Set(devId); } -NAN_METHOD(BluetoothHciSocket::BindUser) { +NAN_METHOD(BluetoothHciSocket::BindUser) +{ Nan::HandleScope scope; - BluetoothHciSocket* p = node::ObjectWrap::Unwrap(info.This()); + BluetoothHciSocket *p = node::ObjectWrap::Unwrap(info.This()); int devId = 0; - int* pDevId = nullptr; + int *pDevId = nullptr; - if (info.Length() > 0) { + if (info.Length() > 0) + { Local arg0 = info[0]; - if (arg0->IsInt32() || arg0->IsUint32()) { + if (arg0->IsInt32() || arg0->IsUint32()) + { devId = Nan::To(arg0).FromJust(); pDevId = &devId; @@ -659,48 +733,54 @@ NAN_METHOD(BluetoothHciSocket::BindUser) { info.GetReturnValue().Set(devId); } -NAN_METHOD(BluetoothHciSocket::BindControl) { +NAN_METHOD(BluetoothHciSocket::BindControl) +{ Nan::HandleScope scope; - BluetoothHciSocket* p = node::ObjectWrap::Unwrap(info.This()); + BluetoothHciSocket *p = node::ObjectWrap::Unwrap(info.This()); p->bindControl(); info.GetReturnValue().SetUndefined(); } -NAN_METHOD(BluetoothHciSocket::IsDevUp) { +NAN_METHOD(BluetoothHciSocket::IsDevUp) +{ Nan::HandleScope scope; - BluetoothHciSocket* p = node::ObjectWrap::Unwrap(info.This()); + BluetoothHciSocket *p = node::ObjectWrap::Unwrap(info.This()); bool isDevUp = p->isDevUp(); info.GetReturnValue().Set(isDevUp); } -NAN_METHOD(BluetoothHciSocket::GetDeviceList) { +NAN_METHOD(BluetoothHciSocket::GetDeviceList) +{ Nan::HandleScope scope; - BluetoothHciSocket* p = node::ObjectWrap::Unwrap(info.This()); + BluetoothHciSocket *p = node::ObjectWrap::Unwrap(info.This()); struct hci_dev_list_req *dl; struct hci_dev_req *dr; - dl = (hci_dev_list_req*)calloc(HCI_MAX_DEV * sizeof(*dr) + sizeof(*dl), 1); + dl = (hci_dev_list_req *)calloc(HCI_MAX_DEV * sizeof(*dr) + sizeof(*dl), 1); dr = dl->dev_req; dl->dev_num = HCI_MAX_DEV; Local deviceList = Nan::New(); - if (ioctl(p->_socket, HCIGETDEVLIST, dl) > -1) { + if (ioctl(p->_socket, HCIGETDEVLIST, dl) > -1) + { int di = 0; - for (int i = 0; i < dl->dev_num; i++, dr++) { + for (int i = 0; i < dl->dev_num; i++, dr++) + { uint16_t devId = dr->dev_id; bool devUp = dr->dev_opt & (1 << HCI_UP); // TODO: smells like there's a bug here (but dr isn't read so...) - if (dr != nullptr) { + if (dr != nullptr) + { v8::Local obj = Nan::New(); Nan::Set(obj, Nan::New("devId").ToLocalChecked(), Nan::New(devId)); Nan::Set(obj, Nan::New("devUp").ToLocalChecked(), Nan::New(devUp)); @@ -718,14 +798,17 @@ NAN_METHOD(BluetoothHciSocket::GetDeviceList) { info.GetReturnValue().Set(deviceList); } -NAN_METHOD(BluetoothHciSocket::SetFilter) { +NAN_METHOD(BluetoothHciSocket::SetFilter) +{ Nan::HandleScope scope; - BluetoothHciSocket* p = node::ObjectWrap::Unwrap(info.This()); + BluetoothHciSocket *p = node::ObjectWrap::Unwrap(info.This()); - if (info.Length() > 0) { + if (info.Length() > 0) + { Local arg0 = info[0]; - if (arg0->IsObject()) { + if (arg0->IsObject()) + { p->setFilter(node::Buffer::Data(arg0), node::Buffer::Length(arg0)); } } @@ -733,23 +816,27 @@ NAN_METHOD(BluetoothHciSocket::SetFilter) { info.GetReturnValue().SetUndefined(); } -NAN_METHOD(BluetoothHciSocket::Stop) { +NAN_METHOD(BluetoothHciSocket::Stop) +{ Nan::HandleScope scope; - BluetoothHciSocket* p = node::ObjectWrap::Unwrap(info.This()); + BluetoothHciSocket *p = node::ObjectWrap::Unwrap(info.This()); p->stop(); info.GetReturnValue().SetUndefined(); } -NAN_METHOD(BluetoothHciSocket::Write) { +NAN_METHOD(BluetoothHciSocket::Write) +{ Nan::HandleScope scope; - BluetoothHciSocket* p = node::ObjectWrap::Unwrap(info.This()); + BluetoothHciSocket *p = node::ObjectWrap::Unwrap(info.This()); - if (info.Length() > 0) { + if (info.Length() > 0) + { Local arg0 = info[0]; - if (arg0->IsObject()) { + if (arg0->IsObject()) + { p->write_(node::Buffer::Data(arg0), node::Buffer::Length(arg0)); } @@ -758,13 +845,14 @@ NAN_METHOD(BluetoothHciSocket::Write) { info.GetReturnValue().SetUndefined(); } - -void BluetoothHciSocket::PollCloseCallback(uv_poll_t* handle) { +void BluetoothHciSocket::PollCloseCallback(uv_poll_t *handle) +{ delete handle; } -void BluetoothHciSocket::PollCallback(uv_poll_t* handle, int status, int events) { - BluetoothHciSocket *p = (BluetoothHciSocket*)handle->data; +void BluetoothHciSocket::PollCallback(uv_poll_t *handle, int status, int events) +{ + BluetoothHciSocket *p = (BluetoothHciSocket *)handle->data; p->poll(); } diff --git a/src/BluetoothHciSocket.h b/src/BluetoothHciSocket.h index f44bff3..d4a72d5 100644 --- a/src/BluetoothHciSocket.h +++ b/src/BluetoothHciSocket.h @@ -9,12 +9,16 @@ // 1 minute in nanoseconds #define L2_CONNECT_TIMEOUT 60000000000 -typedef struct bdaddr_s { +typedef struct bdaddr_s +{ uint8_t b[6]; - bool operator<(const struct bdaddr_s& r) const { - for(int i = 0; i < 6; i++) { - if(b[i] >= r.b[i]) { + bool operator<(const struct bdaddr_s &r) const + { + for (int i = 0; i < 6; i++) + { + if (b[i] >= r.b[i]) + { return false; } } @@ -23,8 +27,9 @@ typedef struct bdaddr_s { } __attribute__((packed)) bdaddr_t; -struct sockaddr_l2 { - sa_family_t l2_family; +struct sockaddr_l2 +{ + sa_family_t l2_family; unsigned short l2_psm; bdaddr_t l2_bdaddr; unsigned short l2_cid; @@ -33,9 +38,10 @@ struct sockaddr_l2 { class BluetoothHciSocket; -class BluetoothHciL2Socket { - public: - BluetoothHciL2Socket(BluetoothHciSocket* parent, unsigned char*, char, char*, char, uint64_t expires); +class BluetoothHciL2Socket +{ +public: + BluetoothHciL2Socket(BluetoothHciSocket *parent, unsigned char *, char, char *, char, uint64_t expires); ~BluetoothHciL2Socket(); void disconnect(); void connect(); @@ -43,16 +49,16 @@ class BluetoothHciL2Socket { uint64_t expires() const; bool connected() const; - - private: +private: int _socket; - BluetoothHciSocket* _parent; + BluetoothHciSocket *_parent; uint64_t _expires; // or 0 if connected struct sockaddr_l2 l2_src; struct sockaddr_l2 l2_dst; }; -class BluetoothHciSocket : public node::ObjectWrap { +class BluetoothHciSocket : public node::ObjectWrap +{ friend class BluetoothHciL2Socket; public: @@ -75,25 +81,25 @@ class BluetoothHciSocket : public node::ObjectWrap { ~BluetoothHciSocket(); void start(); - int bindRaw(int* devId); - int bindUser(int* devId); + int bindRaw(int *devId); + int bindUser(int *devId); void bindControl(); bool isDevUp(); - void setFilter(char* data, int length); + void setFilter(char *data, int length); void stop(); - void write_(char* data, int length); + void write_(char *data, int length); void poll(); void emitErrnoError(const char *syscall); - int devIdFor(const int* devId, bool isUp); - int kernelDisconnectWorkArounds(int length, char* data); - bool kernelConnectWorkArounds(char* data, int length); + int devIdFor(const int *devId, bool isUp); + int kernelDisconnectWorkArounds(int length, char *data); + bool kernelConnectWorkArounds(char *data, int length); void setConnectionParameters(unsigned short connMinInterval, unsigned short connMaxInterval, unsigned short connLatency, unsigned short supervisionTimeout); - static void PollCloseCallback(uv_poll_t* handle); - static void PollCallback(uv_poll_t* handle, int status, int events); + static void PollCloseCallback(uv_poll_t *handle); + static void PollCallback(uv_poll_t *handle, int status, int events); private: Nan::Persistent This;