gecko/dom/bluetooth2/bluez/BluetoothUnixSocketConnector.cpp
Jocelyn Liu bbaef4908c Bug 1009347 - Patch 1/4: Make copy of dom/bluetooth for API refinement, f=btian, r=echou
--HG--
rename : dom/bluetooth/BluetoothAdapter.cpp => dom/bluetooth2/BluetoothAdapter.cpp
rename : dom/bluetooth/BluetoothAdapter.h => dom/bluetooth2/BluetoothAdapter.h
rename : dom/bluetooth/BluetoothCommon.h => dom/bluetooth2/BluetoothCommon.h
rename : dom/bluetooth/BluetoothDevice.cpp => dom/bluetooth2/BluetoothDevice.cpp
rename : dom/bluetooth/BluetoothDevice.h => dom/bluetooth2/BluetoothDevice.h
rename : dom/bluetooth/BluetoothHfpManagerBase.h => dom/bluetooth2/BluetoothHfpManagerBase.h
rename : dom/bluetooth/BluetoothHidManager.cpp => dom/bluetooth2/BluetoothHidManager.cpp
rename : dom/bluetooth/BluetoothHidManager.h => dom/bluetooth2/BluetoothHidManager.h
rename : dom/bluetooth/BluetoothManager.cpp => dom/bluetooth2/BluetoothManager.cpp
rename : dom/bluetooth/BluetoothManager.h => dom/bluetooth2/BluetoothManager.h
rename : dom/bluetooth/BluetoothProfileController.cpp => dom/bluetooth2/BluetoothProfileController.cpp
rename : dom/bluetooth/BluetoothProfileController.h => dom/bluetooth2/BluetoothProfileController.h
rename : dom/bluetooth/BluetoothProfileManagerBase.h => dom/bluetooth2/BluetoothProfileManagerBase.h
rename : dom/bluetooth/BluetoothPropertyContainer.cpp => dom/bluetooth2/BluetoothPropertyContainer.cpp
rename : dom/bluetooth/BluetoothPropertyContainer.h => dom/bluetooth2/BluetoothPropertyContainer.h
rename : dom/bluetooth/BluetoothReplyRunnable.cpp => dom/bluetooth2/BluetoothReplyRunnable.cpp
rename : dom/bluetooth/BluetoothReplyRunnable.h => dom/bluetooth2/BluetoothReplyRunnable.h
rename : dom/bluetooth/BluetoothRilListener.cpp => dom/bluetooth2/BluetoothRilListener.cpp
rename : dom/bluetooth/BluetoothRilListener.h => dom/bluetooth2/BluetoothRilListener.h
rename : dom/bluetooth/BluetoothService.cpp => dom/bluetooth2/BluetoothService.cpp
rename : dom/bluetooth/BluetoothService.h => dom/bluetooth2/BluetoothService.h
rename : dom/bluetooth/BluetoothSocketObserver.h => dom/bluetooth2/BluetoothSocketObserver.h
rename : dom/bluetooth/BluetoothUuid.cpp => dom/bluetooth2/BluetoothUuid.cpp
rename : dom/bluetooth/BluetoothUuid.h => dom/bluetooth2/BluetoothUuid.h
rename : dom/bluetooth/Makefile.in => dom/bluetooth2/Makefile.in
rename : dom/bluetooth/ObexBase.cpp => dom/bluetooth2/ObexBase.cpp
rename : dom/bluetooth/ObexBase.h => dom/bluetooth2/ObexBase.h
rename : dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp => dom/bluetooth2/bluedroid/BluetoothA2dpManager.cpp
rename : dom/bluetooth/bluedroid/BluetoothA2dpManager.h => dom/bluetooth2/bluedroid/BluetoothA2dpManager.h
rename : dom/bluetooth/bluedroid/BluetoothOppManager.cpp => dom/bluetooth2/bluedroid/BluetoothOppManager.cpp
rename : dom/bluetooth/bluedroid/BluetoothOppManager.h => dom/bluetooth2/bluedroid/BluetoothOppManager.h
rename : dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp => dom/bluetooth2/bluedroid/BluetoothServiceBluedroid.cpp
rename : dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h => dom/bluetooth2/bluedroid/BluetoothServiceBluedroid.h
rename : dom/bluetooth/bluedroid/BluetoothSocket.cpp => dom/bluetooth2/bluedroid/BluetoothSocket.cpp
rename : dom/bluetooth/bluedroid/BluetoothSocket.h => dom/bluetooth2/bluedroid/BluetoothSocket.h
rename : dom/bluetooth/bluedroid/BluetoothUtils.cpp => dom/bluetooth2/bluedroid/BluetoothUtils.cpp
rename : dom/bluetooth/bluedroid/BluetoothUtils.h => dom/bluetooth2/bluedroid/BluetoothUtils.h
rename : dom/bluetooth/bluedroid/b2g_bdroid_buildcfg.h => dom/bluetooth2/bluedroid/b2g_bdroid_buildcfg.h
rename : dom/bluetooth/bluedroid/hfp-fallback/BluetoothHfpManager.cpp => dom/bluetooth2/bluedroid/hfp-fallback/BluetoothHfpManager.cpp
rename : dom/bluetooth/bluedroid/hfp-fallback/BluetoothHfpManager.h => dom/bluetooth2/bluedroid/hfp-fallback/BluetoothHfpManager.h
rename : dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp => dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp
rename : dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h => dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.h
rename : dom/bluetooth/bluez/BluetoothA2dpManager.cpp => dom/bluetooth2/bluez/BluetoothA2dpManager.cpp
rename : dom/bluetooth/bluez/BluetoothA2dpManager.h => dom/bluetooth2/bluez/BluetoothA2dpManager.h
rename : dom/bluetooth/bluez/BluetoothDBusService.cpp => dom/bluetooth2/bluez/BluetoothDBusService.cpp
rename : dom/bluetooth/bluez/BluetoothDBusService.h => dom/bluetooth2/bluez/BluetoothDBusService.h
rename : dom/bluetooth/bluez/BluetoothHfpManager.cpp => dom/bluetooth2/bluez/BluetoothHfpManager.cpp
rename : dom/bluetooth/bluez/BluetoothHfpManager.h => dom/bluetooth2/bluez/BluetoothHfpManager.h
rename : dom/bluetooth/bluez/BluetoothOppManager.cpp => dom/bluetooth2/bluez/BluetoothOppManager.cpp
rename : dom/bluetooth/bluez/BluetoothOppManager.h => dom/bluetooth2/bluez/BluetoothOppManager.h
rename : dom/bluetooth/bluez/BluetoothSocket.cpp => dom/bluetooth2/bluez/BluetoothSocket.cpp
rename : dom/bluetooth/bluez/BluetoothSocket.h => dom/bluetooth2/bluez/BluetoothSocket.h
rename : dom/bluetooth/bluez/BluetoothUnixSocketConnector.cpp => dom/bluetooth2/bluez/BluetoothUnixSocketConnector.cpp
rename : dom/bluetooth/bluez/BluetoothUnixSocketConnector.h => dom/bluetooth2/bluez/BluetoothUnixSocketConnector.h
rename : dom/bluetooth/bluez/BluetoothUtils.cpp => dom/bluetooth2/bluez/BluetoothUtils.cpp
rename : dom/bluetooth/bluez/BluetoothUtils.h => dom/bluetooth2/bluez/BluetoothUtils.h
rename : dom/bluetooth/ipc/BluetoothChild.cpp => dom/bluetooth2/ipc/BluetoothChild.cpp
rename : dom/bluetooth/ipc/BluetoothChild.h => dom/bluetooth2/ipc/BluetoothChild.h
rename : dom/bluetooth/ipc/BluetoothMessageUtils.h => dom/bluetooth2/ipc/BluetoothMessageUtils.h
rename : dom/bluetooth/ipc/BluetoothParent.cpp => dom/bluetooth2/ipc/BluetoothParent.cpp
rename : dom/bluetooth/ipc/BluetoothParent.h => dom/bluetooth2/ipc/BluetoothParent.h
rename : dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp => dom/bluetooth2/ipc/BluetoothServiceChildProcess.cpp
rename : dom/bluetooth/ipc/BluetoothServiceChildProcess.h => dom/bluetooth2/ipc/BluetoothServiceChildProcess.h
rename : dom/bluetooth/ipc/BluetoothTypes.ipdlh => dom/bluetooth2/ipc/BluetoothTypes.ipdlh
rename : dom/bluetooth/ipc/PBluetooth.ipdl => dom/bluetooth2/ipc/PBluetooth.ipdl
rename : dom/bluetooth/ipc/PBluetoothRequest.ipdl => dom/bluetooth2/ipc/PBluetoothRequest.ipdl
rename : dom/bluetooth/moz.build => dom/bluetooth2/moz.build
rename : dom/bluetooth/tests/marionette/head.js => dom/bluetooth2/tests/marionette/head.js
rename : dom/bluetooth/tests/marionette/manifest.ini => dom/bluetooth2/tests/marionette/manifest.ini
rename : dom/bluetooth/tests/marionette/test_dom_BluetoothAdapter_discovery.js => dom/bluetooth2/tests/marionette/test_dom_BluetoothAdapter_discovery.js
rename : dom/bluetooth/tests/marionette/test_dom_BluetoothAdapter_getters.js => dom/bluetooth2/tests/marionette/test_dom_BluetoothAdapter_getters.js
rename : dom/bluetooth/tests/marionette/test_dom_BluetoothAdapter_setters.js => dom/bluetooth2/tests/marionette/test_dom_BluetoothAdapter_setters.js
rename : dom/bluetooth/tests/marionette/test_dom_BluetoothManager_adapteradded.js => dom/bluetooth2/tests/marionette/test_dom_BluetoothManager_adapteradded.js
rename : dom/bluetooth/tests/marionette/test_dom_BluetoothManager_enabled.js => dom/bluetooth2/tests/marionette/test_dom_BluetoothManager_enabled.js
2014-05-21 14:11:31 +08:00

286 lines
7.8 KiB
C++

/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/*
* Copyright 2009, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTE: Due to being based on the dbus compatibility layer for
* android's bluetooth implementation, this file is licensed under the
* apache license instead of MPL.
*
*/
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#ifdef MOZ_B2G_BT_BLUEZ
#include <bluetooth/bluetooth.h>
#include <bluetooth/l2cap.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/sco.h>
#endif
#include "BluetoothUnixSocketConnector.h"
#include "nsThreadUtils.h"
using namespace mozilla::ipc;
USING_BLUETOOTH_NAMESPACE
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;
#ifdef MOZ_B2G_BT_BLUEZ
static
int get_bdaddr(const char *str, bdaddr_t *ba)
{
char *d = ((char*)ba) + 5, *endp;
for (int i = 0; i < 6; i++) {
*d-- = strtol(str, &endp, 16);
MOZ_ASSERT(!(*endp != ':' && i != 5));
str = endp + 1;
}
return 0;
}
static
void get_bdaddr_as_string(const bdaddr_t *ba, char *str) {
const uint8_t *b = (const uint8_t *)ba;
sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
b[5], b[4], b[3], b[2], b[1], b[0]);
}
#endif
BluetoothUnixSocketConnector::BluetoothUnixSocketConnector(
BluetoothSocketType aType,
int aChannel,
bool aAuth,
bool aEncrypt) : mType(aType)
, mChannel(aChannel)
, mAuth(aAuth)
, mEncrypt(aEncrypt)
{
}
bool
BluetoothUnixSocketConnector::SetUp(int aFd)
{
#ifdef MOZ_B2G_BT_BLUEZ
int lm = 0;
int sndbuf, rcvbuf;
/* kernel does not yet support LM for SCO */
switch (mType) {
case BluetoothSocketType::RFCOMM:
lm |= mAuth ? RFCOMM_LM_AUTH : 0;
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;
case BluetoothSocketType::SCO:
break;
default:
MOZ_CRASH("Unknown socket type!");
}
if (lm) {
if (mType == BluetoothSocketType::RFCOMM) {
if (setsockopt(aFd, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm))) {
BT_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))) {
BT_WARNING("setsockopt(L2CAP_LM) failed, throwing");
return false;
}
}
}
if (mType == BluetoothSocketType::RFCOMM) {
sndbuf = RFCOMM_SO_SNDBUF;
if (setsockopt(aFd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf))) {
BT_WARNING("setsockopt(SO_SNDBUF) failed, throwing");
return false;
}
}
/* Setting L2CAP socket options */
if (mType == BluetoothSocketType::L2CAP ||
mType == BluetoothSocketType::EL2CAP) {
struct l2cap_options opts;
socklen_t optlen = sizeof(opts);
int 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))) {
BT_WARNING("setsockopt(SO_SNDBUF) failed, throwing");
return false;
}
rcvbuf = L2CAP_SO_RCVBUF;
if (setsockopt(aFd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) {
BT_WARNING("setsockopt(SO_RCVBUF) failed, throwing");
return false;
}
}
}
#endif
return true;
}
bool
BluetoothUnixSocketConnector::SetUpListenSocket(int aFd)
{
// Nothing to do here.
return true;
}
int
BluetoothUnixSocketConnector::Create()
{
MOZ_ASSERT(!NS_IsMainThread());
int fd = -1;
#ifdef MOZ_B2G_BT_BLUEZ
switch (mType) {
case BluetoothSocketType::RFCOMM:
fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
break;
case BluetoothSocketType::SCO:
fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
break;
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_CRASH();
}
if (fd < 0) {
BT_WARNING("Could not open bluetooth socket!");
return -1;
}
if (!SetUp(fd)) {
BT_WARNING("Could not set up socket!");
return -1;
}
#endif
return fd;
}
bool
BluetoothUnixSocketConnector::CreateAddr(bool aIsServer,
socklen_t& aAddrSize,
sockaddr_any& aAddr,
const char* aAddress)
{
#ifdef MOZ_B2G_BT_BLUEZ
// Set to BDADDR_ANY, if it's not a server, we'll reset.
bdaddr_t bd_address_obj = {{0, 0, 0, 0, 0, 0}};
if (!aIsServer && aAddress && strlen(aAddress) > 0) {
if (get_bdaddr(aAddress, &bd_address_obj)) {
BT_WARNING("Can't get bluetooth address!");
return false;
}
}
// Initialize
memset(&aAddr, 0, sizeof(aAddr));
switch (mType) {
case BluetoothSocketType::RFCOMM:
struct sockaddr_rc addr_rc;
aAddrSize = sizeof(addr_rc);
aAddr.rc.rc_family = AF_BLUETOOTH;
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);
aAddr.sco.sco_family = AF_BLUETOOTH;
memcpy(&aAddr.sco.sco_bdaddr, &bd_address_obj, sizeof(bd_address_obj));
break;
default:
BT_WARNING("Socket type unknown!");
return false;
}
#endif
return true;
}
void
BluetoothUnixSocketConnector::GetSocketAddr(const sockaddr_any& aAddr,
nsAString& aAddrStr)
{
#ifdef MOZ_B2G_BT_BLUEZ
char addr[18];
switch (mType) {
case BluetoothSocketType::RFCOMM:
get_bdaddr_as_string((bdaddr_t*)(&aAddr.rc.rc_bdaddr), addr);
break;
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_CRASH("Socket should be either RFCOMM or SCO!");
}
aAddrStr.AssignASCII(addr);
#endif
}