mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 823803 - Add L2CAP/EL2CAP Socket support, r=qdot, r=gyeh
This version of BlueZ from Code Aurora has added GOEP_PSM to Object Push Profile service record, which means that remote devices may connect with us via both L2CAP and RFCOMM. This patch completes L2CAP/EL2CAP socket implementation.
This commit is contained in:
parent
9e5e8beab4
commit
0f4f444972
@ -59,8 +59,9 @@ BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
enum BluetoothSocketType {
|
||||
RFCOMM = 1,
|
||||
SCO = 2,
|
||||
L2CAP = 3
|
||||
SCO = 2,
|
||||
L2CAP = 3,
|
||||
EL2CAP = 4
|
||||
};
|
||||
|
||||
class BluetoothSignal;
|
||||
|
@ -28,9 +28,9 @@
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/sco.h>
|
||||
#include <bluetooth/rfcomm.h>
|
||||
#include <bluetooth/l2cap.h>
|
||||
#include <bluetooth/rfcomm.h>
|
||||
#include <bluetooth/sco.h>
|
||||
|
||||
#include "BluetoothUnixSocketConnector.h"
|
||||
#include "nsThreadUtils.h"
|
||||
@ -38,7 +38,10 @@
|
||||
using namespace mozilla::ipc;
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
static const int RFCOMM_SO_SNDBUF = 70 * 1024; // 70 KB send buffer
|
||||
static const int RFCOMM_SO_SNDBUF = 70 * 1024; // 70 KB send buffer
|
||||
static const int L2CAP_SO_SNDBUF = 400 * 1024; // 400 KB send buffer
|
||||
static const int L2CAP_SO_RCVBUF = 400 * 1024; // 400 KB receive buffer
|
||||
static const int L2CAP_MAX_MTU = 65000;
|
||||
|
||||
static
|
||||
int get_bdaddr(const char *str, bdaddr_t *ba)
|
||||
@ -74,7 +77,8 @@ bool
|
||||
BluetoothUnixSocketConnector::SetUp(int aFd)
|
||||
{
|
||||
int lm = 0;
|
||||
int sndbuf;
|
||||
int sndbuf, rcvbuf;
|
||||
|
||||
/* kernel does not yet support LM for SCO */
|
||||
switch (mType) {
|
||||
case BluetoothSocketType::RFCOMM:
|
||||
@ -82,6 +86,7 @@ BluetoothUnixSocketConnector::SetUp(int aFd)
|
||||
lm |= mEncrypt ? RFCOMM_LM_ENCRYPT : 0;
|
||||
break;
|
||||
case BluetoothSocketType::L2CAP:
|
||||
case BluetoothSocketType::EL2CAP:
|
||||
lm |= mAuth ? L2CAP_LM_AUTH : 0;
|
||||
lm |= mEncrypt ? L2CAP_LM_ENCRYPT : 0;
|
||||
break;
|
||||
@ -92,9 +97,17 @@ BluetoothUnixSocketConnector::SetUp(int aFd)
|
||||
}
|
||||
|
||||
if (lm) {
|
||||
if (setsockopt(aFd, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm))) {
|
||||
NS_WARNING("setsockopt(RFCOMM_LM) failed, throwing");
|
||||
return false;
|
||||
if (mType == BluetoothSocketType::RFCOMM) {
|
||||
if (setsockopt(aFd, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm))) {
|
||||
NS_WARNING("setsockopt(RFCOMM_LM) failed, throwing");
|
||||
return false;
|
||||
}
|
||||
} else if (mType == BluetoothSocketType::L2CAP ||
|
||||
mType == BluetoothSocketType::EL2CAP) {
|
||||
if (setsockopt(aFd, SOL_L2CAP, L2CAP_LM, &lm, sizeof(lm))) {
|
||||
NS_WARNING("setsockopt(L2CAP_LM) failed, throwing");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,6 +119,44 @@ BluetoothUnixSocketConnector::SetUp(int aFd)
|
||||
}
|
||||
}
|
||||
|
||||
/* Setting L2CAP socket options */
|
||||
if (mType == BluetoothSocketType::L2CAP ||
|
||||
mType == BluetoothSocketType::EL2CAP) {
|
||||
struct l2cap_options opts;
|
||||
int optlen = sizeof(opts), err;
|
||||
err = getsockopt(aFd, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen);
|
||||
if (!err) {
|
||||
/* setting MTU for [E]L2CAP */
|
||||
opts.omtu = opts.imtu = L2CAP_MAX_MTU;
|
||||
|
||||
/* Enable ERTM for [E]L2CAP */
|
||||
if (mType == BluetoothSocketType::EL2CAP) {
|
||||
opts.flush_to = 0xffff; /* infinite */
|
||||
opts.mode = L2CAP_MODE_ERTM;
|
||||
opts.fcs = 1;
|
||||
opts.txwin_size = 64;
|
||||
opts.max_tx = 10;
|
||||
}
|
||||
|
||||
err = setsockopt(aFd, SOL_L2CAP, L2CAP_OPTIONS, &opts, optlen);
|
||||
}
|
||||
|
||||
/* Set larger SNDBUF & RCVBUF for EL2CAP connections */
|
||||
if (mType == BluetoothSocketType::EL2CAP) {
|
||||
sndbuf = L2CAP_SO_SNDBUF;
|
||||
if (setsockopt(aFd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf))) {
|
||||
NS_WARNING("setsockopt(SO_SNDBUF) failed, throwing");
|
||||
return false;
|
||||
}
|
||||
|
||||
rcvbuf = L2CAP_SO_RCVBUF;
|
||||
if (setsockopt(aFd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) {
|
||||
NS_WARNING("setsockopt(SO_RCVBUF) failed, throwing");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -125,6 +176,9 @@ BluetoothUnixSocketConnector::Create()
|
||||
case BluetoothSocketType::L2CAP:
|
||||
fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
|
||||
break;
|
||||
case BluetoothSocketType::EL2CAP:
|
||||
fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_L2CAP);
|
||||
break;
|
||||
default:
|
||||
MOZ_NOT_REACHED();
|
||||
}
|
||||
@ -136,7 +190,9 @@ BluetoothUnixSocketConnector::Create()
|
||||
|
||||
if (!SetUp(fd)) {
|
||||
NS_WARNING("Could not set up socket!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
@ -156,6 +212,9 @@ BluetoothUnixSocketConnector::CreateAddr(bool aIsServer,
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize
|
||||
memset(&aAddr, 0, sizeof(aAddr));
|
||||
|
||||
switch (mType) {
|
||||
case BluetoothSocketType::RFCOMM:
|
||||
struct sockaddr_rc addr_rc;
|
||||
@ -164,6 +223,14 @@ BluetoothUnixSocketConnector::CreateAddr(bool aIsServer,
|
||||
aAddr.rc.rc_channel = mChannel;
|
||||
memcpy(&aAddr.rc.rc_bdaddr, &bd_address_obj, sizeof(bd_address_obj));
|
||||
break;
|
||||
case BluetoothSocketType::L2CAP:
|
||||
case BluetoothSocketType::EL2CAP:
|
||||
struct sockaddr_l2 addr_l2;
|
||||
aAddrSize = sizeof(addr_l2);
|
||||
aAddr.l2.l2_family = AF_BLUETOOTH;
|
||||
aAddr.l2.l2_psm = mChannel;
|
||||
memcpy(&aAddr.l2.l2_bdaddr, &bd_address_obj, sizeof(bdaddr_t));
|
||||
break;
|
||||
case BluetoothSocketType::SCO:
|
||||
struct sockaddr_sco addr_sco;
|
||||
aAddrSize = sizeof(addr_sco);
|
||||
@ -189,6 +256,10 @@ BluetoothUnixSocketConnector::GetSocketAddr(const sockaddr_any& aAddr,
|
||||
case BluetoothSocketType::SCO:
|
||||
get_bdaddr_as_string((bdaddr_t*)(&aAddr.sco.sco_bdaddr), addr);
|
||||
break;
|
||||
case BluetoothSocketType::L2CAP:
|
||||
case BluetoothSocketType::EL2CAP:
|
||||
get_bdaddr_as_string((bdaddr_t*)(&aAddr.l2.l2_bdaddr), addr);
|
||||
break;
|
||||
default:
|
||||
MOZ_NOT_REACHED("Socket should be either RFCOMM or SCO!");
|
||||
}
|
||||
|
@ -50,12 +50,13 @@ public:
|
||||
// These were hardcoded into android
|
||||
enum BluetoothReservedChannels {
|
||||
CHANNEL_DIALUP_NETWORK = 1,
|
||||
CHANNEL_HANDSFREE_AG = 10,
|
||||
CHANNEL_HEADSET_AG = 11,
|
||||
CHANNEL_OPUSH = 12,
|
||||
CHANNEL_SIM_ACCESS = 15,
|
||||
CHANNEL_PBAP_PSE = 19,
|
||||
CHANNEL_FTP = 20,
|
||||
CHANNEL_HANDSFREE_AG = 10,
|
||||
CHANNEL_HEADSET_AG = 11,
|
||||
CHANNEL_OPUSH = 12,
|
||||
CHANNEL_SIM_ACCESS = 15,
|
||||
CHANNEL_PBAP_PSE = 19,
|
||||
CHANNEL_FTP = 20,
|
||||
CHANNEL_OPUSH_L2CAP = 5255
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -15,6 +15,7 @@
|
||||
#ifdef MOZ_B2G_BT
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/sco.h>
|
||||
#include <bluetooth/l2cap.h>
|
||||
#include <bluetooth/rfcomm.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
@ -33,6 +34,7 @@ union sockaddr_any {
|
||||
#ifdef MOZ_B2G_BT
|
||||
sockaddr_sco sco;
|
||||
sockaddr_rc rc;
|
||||
sockaddr_l2 l2;
|
||||
#endif
|
||||
// ... others
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user