summaryrefslogtreecommitdiff
path: root/profiles
diff options
context:
space:
mode:
authorWu Zheng <wu.zheng@intel.com>2013-12-12 04:50:37 -0500
committerWu Zheng <wu.zheng@intel.com>2013-12-12 04:50:37 -0500
commit5d363eb448eacca7c3939fd6e8d6ee3c284db7e2 (patch)
treef48817eba8ed8386a9f9c40801d2b6cb196dddfa /profiles
parenta704ad586e3a3480a8e0c60da2d9b772dbd0c887 (diff)
downloadbluez-5d363eb448eacca7c3939fd6e8d6ee3c284db7e2.tar.gz
bluez-5d363eb448eacca7c3939fd6e8d6ee3c284db7e2.tar.bz2
bluez-5d363eb448eacca7c3939fd6e8d6ee3c284db7e2.zip
Imported Upstream version 5.12upstream/5.12
Diffstat (limited to 'profiles')
-rw-r--r--profiles/audio/a2dp.c4
-rw-r--r--profiles/audio/avctp.c22
-rw-r--r--profiles/audio/avdtp.c74
-rw-r--r--profiles/audio/avdtp.h15
-rw-r--r--profiles/audio/sink.c5
-rw-r--r--profiles/audio/sink.h2
-rw-r--r--profiles/audio/source.c5
-rw-r--r--profiles/audio/source.h2
-rw-r--r--profiles/health/hdp.c10
-rw-r--r--profiles/health/hdp_util.c6
-rw-r--r--profiles/input/device.c11
-rw-r--r--profiles/input/manager.c4
-rw-r--r--profiles/input/server.c104
-rw-r--r--profiles/network/bnep.c (renamed from profiles/network/common.c)197
-rw-r--r--profiles/network/bnep.h (renamed from profiles/network/common.h)5
-rw-r--r--profiles/network/connection.c176
-rw-r--r--profiles/network/manager.c2
-rw-r--r--profiles/network/server.c9
-rw-r--r--profiles/sap/server.c3
19 files changed, 379 insertions, 277 deletions
diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index 864cb188..29a15939 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -1887,7 +1887,7 @@ static int a2dp_source_disconnect(struct btd_service *service)
DBG("path %s", path);
- return source_disconnect(service, FALSE);
+ return source_disconnect(service);
}
static int a2dp_sink_connect(struct btd_service *service)
@@ -1919,7 +1919,7 @@ static int a2dp_sink_disconnect(struct btd_service *service)
DBG("path %s", path);
- return sink_disconnect(service, FALSE);
+ return sink_disconnect(service);
}
static int a2dp_source_server_probe(struct btd_profile *p,
diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
index dac7a66c..6669ddc0 100644
--- a/profiles/audio/avctp.c
+++ b/profiles/audio/avctp.c
@@ -1307,11 +1307,11 @@ static void avctp_control_confirm(struct avctp *session, GIOChannel *chan,
avctp_set_state(session, AVCTP_STATE_CONNECTING);
session->control = avctp_channel_create(session, chan, NULL);
- src = adapter_get_address(device_get_adapter(dev));
+ src = btd_adapter_get_address(device_get_adapter(dev));
dst = device_get_address(dev);
session->auth_id = btd_request_authorization(src, dst,
- AVRCP_TARGET_UUID,
+ AVRCP_REMOTE_UUID,
auth_cb, session);
if (session->auth_id == 0)
goto drop;
@@ -1371,7 +1371,7 @@ static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
DBG("AVCTP: incoming connect from %s", address);
- device = adapter_find_device(adapter_find(&src), &dst);
+ device = btd_adapter_find_device(adapter_find(&src), &dst);
if (!device)
return;
@@ -1422,7 +1422,7 @@ static GIOChannel *avctp_server_socket(const bdaddr_t *src, gboolean master,
int avctp_register(struct btd_adapter *adapter, gboolean master)
{
struct avctp_server *server;
- const bdaddr_t *src = adapter_get_address(adapter);
+ const bdaddr_t *src = btd_adapter_get_address(adapter);
server = g_new0(struct avctp_server, 1);
@@ -1488,7 +1488,7 @@ static struct avctp_pending_req *pending_create(struct avctp_channel *chan,
tmp = g_slist_copy(chan->processed);
/* Find first unused transaction id */
- for (l = tmp; l; l = l->next) {
+ for (l = tmp; l; l = g_slist_next(l)) {
struct avctp_pending_req *req = l->data;
if (req->transaction == chan->transaction) {
@@ -1937,6 +1937,7 @@ struct avctp *avctp_connect(struct btd_device *device)
struct avctp *session;
GError *err = NULL;
GIOChannel *io;
+ const bdaddr_t *src;
session = avctp_get_internal(device);
if (!session)
@@ -1947,9 +1948,10 @@ struct avctp *avctp_connect(struct btd_device *device)
avctp_set_state(session, AVCTP_STATE_CONNECTING);
+ src = btd_adapter_get_address(session->server->adapter);
+
io = bt_io_connect(avctp_connect_cb, session, NULL, &err,
- BT_IO_OPT_SOURCE_BDADDR,
- adapter_get_address(session->server->adapter),
+ BT_IO_OPT_SOURCE_BDADDR, src,
BT_IO_OPT_DEST_BDADDR,
device_get_address(session->device),
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
@@ -1971,6 +1973,7 @@ struct avctp *avctp_connect(struct btd_device *device)
int avctp_connect_browsing(struct avctp *session)
{
+ const bdaddr_t *src;
GError *err = NULL;
GIOChannel *io;
@@ -1982,9 +1985,10 @@ int avctp_connect_browsing(struct avctp *session)
avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTING);
+ src = btd_adapter_get_address(session->server->adapter);
+
io = bt_io_connect(avctp_connect_browsing_cb, session, NULL, &err,
- BT_IO_OPT_SOURCE_BDADDR,
- adapter_get_address(session->server->adapter),
+ BT_IO_OPT_SOURCE_BDADDR, src,
BT_IO_OPT_DEST_BDADDR,
device_get_address(session->device),
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index 93783509..f866b392 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -394,9 +394,6 @@ struct avdtp {
avdtp_session_state_t state;
- /* True if the entire device is being disconnected */
- gboolean device_disconnect;
-
guint auth_id;
GIOChannel *io;
@@ -1200,11 +1197,6 @@ static void set_disconnect_timer(struct avdtp *session)
if (session->dc_timer)
remove_disconnect_timer(session);
- if (session->device_disconnect) {
- session->dc_timer = g_idle_add(disconnect_timeout, session);
- return;
- }
-
session->dc_timer = g_timeout_add_seconds(DISCONNECT_TIMEOUT,
disconnect_timeout,
session);
@@ -2475,7 +2467,7 @@ static void avdtp_confirm_cb(GIOChannel *chan, gpointer data)
DBG("AVDTP: incoming connect from %s", address);
- device = adapter_find_device(adapter_find(&src), &dst);
+ device = btd_adapter_find_device(adapter_find(&src), &dst);
if (!device)
goto drop;
@@ -2531,11 +2523,13 @@ static GIOChannel *l2cap_connect(struct avdtp *session)
{
GError *err = NULL;
GIOChannel *io;
+ const bdaddr_t *src;
+
+ src = btd_adapter_get_address(session->server->adapter);
io = bt_io_connect(avdtp_connect_cb, session,
NULL, &err,
- BT_IO_OPT_SOURCE_BDADDR,
- adapter_get_address(session->server->adapter),
+ BT_IO_OPT_SOURCE_BDADDR, src,
BT_IO_OPT_DEST_BDADDR,
device_get_address(session->device),
BT_IO_OPT_PSM, AVDTP_PSM,
@@ -3183,8 +3177,8 @@ struct avdtp_service_capability *avdtp_stream_get_codec(
return NULL;
}
-gboolean avdtp_stream_has_capability(struct avdtp_stream *stream,
- struct avdtp_service_capability *cap)
+static gboolean avdtp_stream_has_capability(struct avdtp_stream *stream,
+ struct avdtp_service_capability *cap)
{
GSList *l;
struct avdtp_service_capability *stream_cap;
@@ -3219,7 +3213,16 @@ gboolean avdtp_stream_has_capabilities(struct avdtp_stream *stream,
struct avdtp_remote_sep *avdtp_stream_get_remote_sep(
struct avdtp_stream *stream)
{
- return avdtp_get_remote_sep(stream->session, stream->rseid);
+ GSList *l;
+
+ for (l = stream->session->seps; l; l = l->next) {
+ struct avdtp_remote_sep *sep = l->data;
+
+ if (sep->seid == stream->rseid)
+ return sep;
+ }
+
+ return NULL;
}
gboolean avdtp_stream_get_transport(struct avdtp_stream *stream, int *sock,
@@ -3268,46 +3271,11 @@ static int process_queue(struct avdtp *session)
return send_req(session, FALSE, req);
}
-struct avdtp_remote_sep *avdtp_get_remote_sep(struct avdtp *session,
- uint8_t seid)
-{
- GSList *l;
-
- for (l = session->seps; l; l = l->next) {
- struct avdtp_remote_sep *sep = l->data;
-
- if (sep->seid == seid)
- return sep;
- }
-
- return NULL;
-}
-
-uint8_t avdtp_get_seid(struct avdtp_remote_sep *sep)
-{
- return sep->seid;
-}
-
-uint8_t avdtp_get_type(struct avdtp_remote_sep *sep)
-{
- return sep->type;
-}
-
struct avdtp_service_capability *avdtp_get_codec(struct avdtp_remote_sep *sep)
{
return sep->codec;
}
-gboolean avdtp_get_delay_reporting(struct avdtp_remote_sep *sep)
-{
- return sep->delay_reporting;
-}
-
-struct avdtp_stream *avdtp_get_stream(struct avdtp_remote_sep *sep)
-{
- return sep->stream;
-}
-
struct avdtp_service_capability *avdtp_service_cap_new(uint8_t category,
void *data, int length)
{
@@ -3709,7 +3677,8 @@ static struct avdtp_server *avdtp_server_init(struct btd_adapter *adapter)
server = g_new0(struct avdtp_server, 1);
- server->io = avdtp_server_socket(adapter_get_address(adapter), TRUE);
+ server->io = avdtp_server_socket(btd_adapter_get_address(adapter),
+ TRUE);
if (!server->io) {
g_free(server);
return NULL;
@@ -3867,11 +3836,6 @@ gboolean avdtp_has_stream(struct avdtp *session, struct avdtp_stream *stream)
return g_slist_find(session->streams, stream) ? TRUE : FALSE;
}
-void avdtp_set_device_disconnect(struct avdtp *session, gboolean dev_dc)
-{
- session->device_disconnect = dev_dc;
-}
-
unsigned int avdtp_add_state_cb(struct btd_device *dev,
avdtp_session_state_cb cb, void *user_data)
{
diff --git a/profiles/audio/avdtp.h b/profiles/audio/avdtp.h
index 56065062..390c154e 100644
--- a/profiles/audio/avdtp.h
+++ b/profiles/audio/avdtp.h
@@ -221,19 +221,8 @@ struct avdtp *avdtp_ref(struct avdtp *session);
struct avdtp_service_capability *avdtp_service_cap_new(uint8_t category,
void *data, int size);
-struct avdtp_remote_sep *avdtp_get_remote_sep(struct avdtp *session,
- uint8_t seid);
-
-uint8_t avdtp_get_seid(struct avdtp_remote_sep *sep);
-
-uint8_t avdtp_get_type(struct avdtp_remote_sep *sep);
-
struct avdtp_service_capability *avdtp_get_codec(struct avdtp_remote_sep *sep);
-gboolean avdtp_get_delay_reporting(struct avdtp_remote_sep *sep);
-
-struct avdtp_stream *avdtp_get_stream(struct avdtp_remote_sep *sep);
-
int avdtp_discover(struct avdtp *session, avdtp_discover_cb_t cb,
void *user_data);
@@ -251,8 +240,6 @@ gboolean avdtp_stream_get_transport(struct avdtp_stream *stream, int *sock,
GSList **caps);
struct avdtp_service_capability *avdtp_stream_get_codec(
struct avdtp_stream *stream);
-gboolean avdtp_stream_has_capability(struct avdtp_stream *stream,
- struct avdtp_service_capability *cap);
gboolean avdtp_stream_has_capabilities(struct avdtp_stream *stream,
GSList *caps);
struct avdtp_remote_sep *avdtp_stream_get_remote_sep(
@@ -306,5 +293,3 @@ int avdtp_error_posix_errno(struct avdtp_error *err);
struct btd_adapter *avdtp_get_adapter(struct avdtp *session);
struct btd_device *avdtp_get_device(struct avdtp *session);
-
-void avdtp_set_device_disconnect(struct avdtp *session, gboolean dev_dc);
diff --git a/profiles/audio/sink.c b/profiles/audio/sink.c
index 400af061..4f39622e 100644
--- a/profiles/audio/sink.c
+++ b/profiles/audio/sink.c
@@ -388,16 +388,13 @@ gboolean sink_new_stream(struct btd_service *service, struct avdtp *session,
return TRUE;
}
-int sink_disconnect(struct btd_service *service, gboolean shutdown)
+int sink_disconnect(struct btd_service *service)
{
struct sink *sink = btd_service_get_user_data(service);
if (!sink->session)
return -ENOTCONN;
- if (shutdown)
- avdtp_set_device_disconnect(sink->session, TRUE);
-
/* cancel pending connect */
if (sink->connect_id > 0) {
a2dp_cancel(sink->connect_id);
diff --git a/profiles/audio/sink.h b/profiles/audio/sink.h
index 904a33d4..93c62a20 100644
--- a/profiles/audio/sink.h
+++ b/profiles/audio/sink.h
@@ -47,4 +47,4 @@ int sink_connect(struct btd_service *service);
gboolean sink_new_stream(struct btd_service *service, struct avdtp *session,
struct avdtp_stream *stream);
gboolean sink_setup_stream(struct btd_service *service, struct avdtp *session);
-int sink_disconnect(struct btd_service *service, gboolean shutdown);
+int sink_disconnect(struct btd_service *service);
diff --git a/profiles/audio/source.c b/profiles/audio/source.c
index 24a43536..7b129b76 100644
--- a/profiles/audio/source.c
+++ b/profiles/audio/source.c
@@ -380,16 +380,13 @@ gboolean source_new_stream(struct btd_service *service, struct avdtp *session,
return TRUE;
}
-int source_disconnect(struct btd_service *service, gboolean shutdown)
+int source_disconnect(struct btd_service *service)
{
struct source *source = btd_service_get_user_data(service);
if (!source->session)
return -ENOTCONN;
- if (shutdown)
- avdtp_set_device_disconnect(source->session, TRUE);
-
/* cancel pending connect */
if (source->connect_id > 0) {
a2dp_cancel(source->connect_id);
diff --git a/profiles/audio/source.h b/profiles/audio/source.h
index c16fb4bc..a014c68d 100644
--- a/profiles/audio/source.h
+++ b/profiles/audio/source.h
@@ -48,4 +48,4 @@ gboolean source_new_stream(struct btd_service *service, struct avdtp *session,
struct avdtp_stream *stream);
gboolean source_setup_stream(struct btd_service *service,
struct avdtp *session);
-int source_disconnect(struct btd_service *service, gboolean shutdown);
+int source_disconnect(struct btd_service *service);
diff --git a/profiles/health/hdp.c b/profiles/health/hdp.c
index 7b4e7995..6203fa8a 100644
--- a/profiles/health/hdp.c
+++ b/profiles/health/hdp.c
@@ -1205,8 +1205,8 @@ static void mcl_connected(struct mcap_mcl *mcl, gpointer data)
struct hdp_adapter *hdp_adapter = data;
struct btd_device *device;
- device = adapter_get_device(hdp_adapter->btd_adapter, &addr,
- BDADDR_BREDR);
+ device = btd_adapter_get_device(hdp_adapter->btd_adapter,
+ &addr, BDADDR_BREDR);
if (!device)
return;
hdp_device = create_health_device(device);
@@ -1322,6 +1322,7 @@ static void release_adapter_instance(struct hdp_adapter *hdp_adapter)
static gboolean update_adapter(struct hdp_adapter *hdp_adapter)
{
GError *err = NULL;
+ const bdaddr_t *src;
if (applications == NULL) {
release_adapter_instance(hdp_adapter);
@@ -1331,8 +1332,9 @@ static gboolean update_adapter(struct hdp_adapter *hdp_adapter)
if (hdp_adapter->mi != NULL)
goto update;
- hdp_adapter->mi = mcap_create_instance(
- adapter_get_address(hdp_adapter->btd_adapter),
+ src = btd_adapter_get_address(hdp_adapter->btd_adapter);
+
+ hdp_adapter->mi = mcap_create_instance(src,
BT_IO_SEC_MEDIUM, 0, 0,
mcl_connected, mcl_reconnected,
mcl_disconnected, mcl_uncached,
diff --git a/profiles/health/hdp_util.c b/profiles/health/hdp_util.c
index 34e4671d..7de87a85 100644
--- a/profiles/health/hdp_util.c
+++ b/profiles/health/hdp_util.c
@@ -853,7 +853,7 @@ gboolean hdp_get_mdep(struct hdp_device *device, struct hdp_application *app,
const bdaddr_t *dst;
uuid_t uuid;
- src = adapter_get_address(device_get_adapter(device->dev));
+ src = btd_adapter_get_address(device_get_adapter(device->dev));
dst = device_get_address(device->dev);
mdep_data = g_new0(struct get_mdep_data, 1);
@@ -1080,7 +1080,7 @@ gboolean hdp_establish_mcl(struct hdp_device *device,
const bdaddr_t *dst;
uuid_t uuid;
- src = adapter_get_address(device_get_adapter(device->dev));
+ src = btd_adapter_get_address(device_get_adapter(device->dev));
dst = device_get_address(device->dev);
conn_data = g_new0(struct conn_mcl_data, 1);
@@ -1151,7 +1151,7 @@ gboolean hdp_get_dcpsm(struct hdp_device *device, hdp_continue_dcpsm_f func,
const bdaddr_t *dst;
uuid_t uuid;
- src = adapter_get_address(device_get_adapter(device->dev));
+ src = btd_adapter_get_address(device_get_adapter(device->dev));
dst = device_get_address(device->dev);
dcpsm_data = g_new0(struct get_dcpsm_data, 1);
diff --git a/profiles/input/device.c b/profiles/input/device.c
index 65231612..62f6dbb2 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -667,7 +667,7 @@ static gboolean input_device_auto_reconnect(gpointer user_data)
/* Stop the recurrent reconnection attempts if the device is reconnected
* or is marked for removal. */
if (device_is_temporary(idev->device) ||
- device_is_connected(idev->device))
+ btd_device_is_connected(idev->device))
return FALSE;
/* Only attempt an auto-reconnect for at most 3 minutes (6 * 30s). */
@@ -713,7 +713,7 @@ static void input_device_enter_reconnect_mode(struct input_device *idev)
/* If the device is temporary we are not required to reconnect with the
* device. This is likely the case of a removing device. */
if (device_is_temporary(idev->device) ||
- device_is_connected(idev->device))
+ btd_device_is_connected(idev->device))
return;
if (idev->reconnect_timer > 0)
@@ -811,8 +811,11 @@ static struct input_device *input_device_new(struct btd_service *service)
struct input_device *idev;
char name[HCI_MAX_NAME_LENGTH + 1];
+ if (!rec)
+ return NULL;
+
idev = g_new0(struct input_device, 1);
- bacpy(&idev->src, adapter_get_address(adapter));
+ bacpy(&idev->src, btd_adapter_get_address(adapter));
bacpy(&idev->dst, device_get_address(device));
idev->service = btd_service_ref(service);
idev->device = btd_device_ref(device);
@@ -880,7 +883,7 @@ static struct input_device *find_device(const bdaddr_t *src,
struct btd_device *device;
struct btd_service *service;
- device = adapter_find_device(adapter_find(src), dst);
+ device = btd_adapter_find_device(adapter_find(src), dst);
if (device == NULL)
return NULL;
diff --git a/profiles/input/manager.c b/profiles/input/manager.c
index 689ccddd..660043ee 100644
--- a/profiles/input/manager.c
+++ b/profiles/input/manager.c
@@ -46,13 +46,13 @@
static int hid_server_probe(struct btd_profile *p, struct btd_adapter *adapter)
{
- return server_start(adapter_get_address(adapter));
+ return server_start(btd_adapter_get_address(adapter));
}
static void hid_server_remove(struct btd_profile *p,
struct btd_adapter *adapter)
{
- server_stop(adapter_get_address(adapter));
+ server_stop(btd_adapter_get_address(adapter));
}
static struct btd_profile input_profile = {
diff --git a/profiles/input/server.c b/profiles/input/server.c
index 21d4562b..f6f85a0d 100644
--- a/profiles/input/server.c
+++ b/profiles/input/server.c
@@ -63,6 +63,100 @@ static int server_cmp(gconstpointer s, gconstpointer user_data)
return bacmp(&server->src, src);
}
+struct sixaxis_data {
+ GIOChannel *chan;
+ uint16_t psm;
+};
+
+static void connect_event_cb(GIOChannel *chan, GError *err, gpointer data);
+
+static void sixaxis_sdp_cb(struct btd_device *dev, int err, void *user_data)
+{
+ struct sixaxis_data *data = user_data;
+ struct input_server *server;
+ GError *gerr = NULL;
+ const bdaddr_t *src;
+ GSList *l;
+
+ DBG("err %d (%s)", err, strerror(-err));
+
+ if (err < 0)
+ goto fail;
+
+ src = btd_adapter_get_address(device_get_adapter(dev));
+
+ l = g_slist_find_custom(servers, src, server_cmp);
+ if (!l)
+ goto fail;
+
+ server = l->data;
+
+ err = input_device_set_channel(src, device_get_address(dev),
+ data->psm, data->chan);
+ if (err < 0)
+ goto fail;
+
+ if (server->confirm) {
+ if (!bt_io_accept(server->confirm, connect_event_cb, server,
+ NULL, &gerr)) {
+ error("bt_io_accept: %s", gerr->message);
+ g_error_free(gerr);
+ goto fail;
+ }
+
+ g_io_channel_unref(server->confirm);
+ server->confirm = NULL;
+ }
+
+ g_io_channel_unref(data->chan);
+ g_free(data);
+
+ return;
+
+fail:
+ g_io_channel_shutdown(data->chan, TRUE, NULL);
+ g_io_channel_unref(data->chan);
+ g_free(data);
+}
+
+static void sixaxis_browse_sdp(const bdaddr_t *src, const bdaddr_t *dst,
+ GIOChannel *chan, uint16_t psm)
+{
+ struct btd_device *device;
+ struct sixaxis_data *data;
+
+ if (psm != L2CAP_PSM_HIDP_CTRL)
+ return;
+
+ device = btd_adapter_find_device(adapter_find(src), dst);
+ if (!device)
+ return;
+
+ data = g_new0(struct sixaxis_data, 1);
+ data->chan = g_io_channel_ref(chan);
+ data->psm = psm;
+
+ device_discover_services(device);
+ device_wait_for_svc_complete(device, sixaxis_sdp_cb, data);
+}
+
+static bool dev_is_sixaxis(const bdaddr_t *src, const bdaddr_t *dst)
+{
+ struct btd_device *device;
+
+ device = btd_adapter_find_device(adapter_find(src), dst);
+ if (!device)
+ return false;
+
+ if (btd_device_get_vendor(device) != 0x054c)
+ return false;
+
+ if (btd_device_get_product(device) != 0x0268)
+ return false;
+
+ return true;
+}
+
static void connect_event_cb(GIOChannel *chan, GError *err, gpointer data)
{
uint16_t psm;
@@ -95,6 +189,11 @@ static void connect_event_cb(GIOChannel *chan, GError *err, gpointer data)
if (ret == 0)
return;
+ if (ret == -ENOENT && dev_is_sixaxis(&src, &dst)) {
+ sixaxis_browse_sdp(&src, &dst, chan, psm);
+ return;
+ }
+
error("Refusing input device connect: %s (%d)", strerror(-ret), -ret);
/* Send unplug virtual cable to unknown devices */
@@ -129,6 +228,9 @@ static void auth_callback(DBusError *derr, void *user_data)
goto reject;
}
+ if (!input_device_exists(&src, &dst) && dev_is_sixaxis(&src, &dst))
+ return;
+
if (!bt_io_accept(server->confirm, connect_event_cb, server,
NULL, &err)) {
error("bt_io_accept: %s", err->message);
@@ -175,7 +277,7 @@ static void confirm_event_cb(GIOChannel *chan, gpointer user_data)
goto drop;
}
- if (!input_device_exists(&src, &dst)) {
+ if (!input_device_exists(&src, &dst) && !dev_is_sixaxis(&src, &dst)) {
error("Refusing connection from %s: unknown device", addr);
goto drop;
}
diff --git a/profiles/network/common.c b/profiles/network/bnep.c
index 0b291bdb..0a719a2e 100644
--- a/profiles/network/common.c
+++ b/profiles/network/bnep.c
@@ -43,9 +43,12 @@
#include <glib.h>
#include "log.h"
-#include "common.h"
+#include "bnep.h"
#include "lib/uuid.h"
+#define CON_SETUP_RETRIES 3
+#define CON_SETUP_TO 9
+
static int ctl;
static struct {
@@ -59,6 +62,35 @@ static struct {
{ NULL }
};
+struct __service_16 {
+ uint16_t dst;
+ uint16_t src;
+} __attribute__ ((packed));
+
+struct bnep_conn {
+ GIOChannel *io;
+ uint16_t src;
+ uint16_t dst;
+ guint attempts;
+ guint setup_to;
+ void *data;
+ bnep_connect_cb conn_cb;
+};
+
+static void free_bnep_connect(struct bnep_conn *bc)
+{
+ if (!bc)
+ return;
+
+ if (bc->io) {
+ g_io_channel_unref(bc->io);
+ bc->io = NULL;
+ }
+
+ g_free(bc);
+ bc = NULL;
+}
+
uint16_t bnep_service_id(const char *svc)
{
int i;
@@ -149,9 +181,9 @@ int bnep_connadd(int sk, uint16_t role, char *dev)
{
struct bnep_connadd_req req;
+ memset(dev, 0, 16);
memset(&req, 0, sizeof(req));
- strncpy(req.device, dev, 16);
- req.device[15] = '\0';
+ strcpy(req.device, "bnep%d");
req.sock = sk;
req.role = role;
if (ioctl(ctl, BNEPCONNADD, &req) < 0) {
@@ -215,6 +247,165 @@ int bnep_if_down(const char *devname)
return 0;
}
+static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ struct bnep_conn *bc = data;
+ struct bnep_control_rsp *rsp;
+ struct timeval timeo;
+ char pkt[BNEP_MTU];
+ char iface[16];
+ ssize_t r;
+ int sk;
+
+ if (cond & G_IO_NVAL)
+ goto failed;
+
+ if (bc->setup_to > 0) {
+ g_source_remove(bc->setup_to);
+ bc->setup_to = 0;
+ }
+
+ if (cond & (G_IO_HUP | G_IO_ERR)) {
+ error("Hangup or error on l2cap server socket");
+ goto failed;
+ }
+
+ sk = g_io_channel_unix_get_fd(chan);
+ memset(pkt, 0, BNEP_MTU);
+ r = read(sk, pkt, sizeof(pkt) - 1);
+ if (r < 0) {
+ error("IO Channel read error");
+ goto failed;
+ }
+
+ if (r == 0) {
+ error("No packet received on l2cap socket");
+ goto failed;
+ }
+
+ errno = EPROTO;
+
+ if ((size_t) r < sizeof(*rsp)) {
+ error("Packet received is not bnep type");
+ goto failed;
+ }
+
+ rsp = (void *) pkt;
+ if (rsp->type != BNEP_CONTROL) {
+ error("Packet received is not bnep type");
+ goto failed;
+ }
+
+ if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
+ return TRUE;
+
+ r = ntohs(rsp->resp);
+ if (r != BNEP_SUCCESS) {
+ error("bnep failed");
+ goto failed;
+ }
+
+ memset(&timeo, 0, sizeof(timeo));
+ timeo.tv_sec = 0;
+ setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
+
+ sk = g_io_channel_unix_get_fd(bc->io);
+ if (bnep_connadd(sk, bc->src, iface)) {
+ error("bnep conn could not be added");
+ goto failed;
+ }
+
+ if (bnep_if_up(iface)) {
+ error("could not up %s", iface);
+ goto failed;
+ }
+
+ bc->conn_cb(chan, iface, 0, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+
+failed:
+ bc->conn_cb(NULL, NULL, -EIO, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+}
+
+static int bnep_setup_conn_req(struct bnep_conn *bc)
+{
+ struct bnep_setup_conn_req *req;
+ struct __service_16 *s;
+ unsigned char pkt[BNEP_MTU];
+ int fd;
+
+ /* Send request */
+ req = (void *) pkt;
+ req->type = BNEP_CONTROL;
+ req->ctrl = BNEP_SETUP_CONN_REQ;
+ req->uuid_size = 2; /* 16bit UUID */
+ s = (void *) req->service;
+ s->src = htons(bc->src);
+ s->dst = htons(bc->dst);
+
+ fd = g_io_channel_unix_get_fd(bc->io);
+ if (write(fd, pkt, sizeof(*req) + sizeof(*s)) < 0) {
+ error("bnep connection req send failed: %s", strerror(errno));
+ return -errno;
+ }
+
+ bc->attempts++;
+
+ return 0;
+}
+
+static gboolean bnep_conn_req_to(gpointer user_data)
+{
+ struct bnep_conn *bc = user_data;
+
+ if (bc->attempts == CON_SETUP_RETRIES) {
+ error("Too many bnep connection attempts");
+ } else {
+ error("bnep connection setup TO, retrying...");
+ if (bnep_setup_conn_req(bc) == 0)
+ return TRUE;
+ }
+
+ bc->conn_cb(NULL, NULL, -ETIMEDOUT, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+}
+
+int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
+ void *data)
+{
+ struct bnep_conn *bc;
+ int err;
+
+ if (!conn_cb)
+ return -EINVAL;
+
+ bc = g_new0(struct bnep_conn, 1);
+ bc->io = g_io_channel_unix_new(sk);
+ bc->attempts = 0;
+ bc->src = src;
+ bc->dst = dst;
+ bc->conn_cb = conn_cb;
+ bc->data = data;
+
+ err = bnep_setup_conn_req(bc);
+ if (err < 0)
+ return err;
+
+ bc->setup_to = g_timeout_add_seconds(CON_SETUP_TO,
+ bnep_conn_req_to, bc);
+ g_io_add_watch(bc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ bnep_setup_cb, bc);
+ return 0;
+}
+
int bnep_add_to_bridge(const char *devname, const char *bridge)
{
int ifindex;
diff --git a/profiles/network/common.h b/profiles/network/bnep.h
index 9a8caac0..9043e46f 100644
--- a/profiles/network/common.h
+++ b/profiles/network/bnep.h
@@ -35,3 +35,8 @@ int bnep_if_up(const char *devname);
int bnep_if_down(const char *devname);
int bnep_add_to_bridge(const char *devname, const char *bridge);
int bnep_del_from_bridge(const char *devname, const char *bridge);
+
+typedef void (*bnep_connect_cb) (GIOChannel *chan, char *iface, int err,
+ void *data);
+int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
+ void *data);
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 960a1fe2..9aff3191 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -47,12 +47,10 @@
#include "service.h"
#include "error.h"
-#include "common.h"
+#include "bnep.h"
#include "connection.h"
#define NETWORK_PEER_INTERFACE "org.bluez.Network1"
-#define CON_SETUP_RETRIES 3
-#define CON_SETUP_TO 9
typedef enum {
CONNECTED,
@@ -73,16 +71,9 @@ struct network_conn {
GIOChannel *io;
guint dc_id;
struct network_peer *peer;
- guint attempt_cnt;
- guint timeout_source;
DBusMessage *connect;
};
-struct __service_16 {
- uint16_t dst;
- uint16_t src;
-} __attribute__ ((packed));
-
static GSList *peers = NULL;
static uint16_t get_service_id(struct btd_service *service)
@@ -163,11 +154,6 @@ static void local_connect_cb(struct network_conn *nc, int err)
static void cancel_connection(struct network_conn *nc, int err)
{
- if (nc->timeout_source > 0) {
- g_source_remove(nc->timeout_source);
- nc->timeout_source = 0;
- }
-
btd_service_connecting_complete(nc->service, err);
if (nc->connect)
local_connect_cb(nc, err);
@@ -200,83 +186,24 @@ static void disconnect_cb(struct btd_device *device, gboolean removal,
connection_destroy(NULL, user_data);
}
-static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
- gpointer data)
+static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
{
struct network_conn *nc = data;
- struct bnep_control_rsp *rsp;
- struct timeval timeo;
- char pkt[BNEP_MTU];
- ssize_t r;
- int sk;
const char *path;
DBusConnection *conn;
- DBG("cond %u", cond);
-
- if (cond & G_IO_NVAL)
- return FALSE;
-
- if (nc->timeout_source > 0) {
- g_source_remove(nc->timeout_source);
- nc->timeout_source = 0;
- }
-
- if (cond & (G_IO_HUP | G_IO_ERR)) {
- error("Hangup or error on l2cap server socket");
- goto failed;
- }
-
- sk = g_io_channel_unix_get_fd(chan);
-
- memset(pkt, 0, BNEP_MTU);
- r = read(sk, pkt, sizeof(pkt) -1);
- if (r < 0) {
- error("IO Channel read error");
- goto failed;
- }
-
- if (r == 0) {
- error("No packet received on l2cap socket");
- goto failed;
- }
-
- errno = EPROTO;
-
- if ((size_t) r < sizeof(*rsp)) {
- error("Packet received is not bnep type");
- goto failed;
- }
-
- rsp = (void *) pkt;
- if (rsp->type != BNEP_CONTROL) {
- error("Packet received is not bnep type");
- goto failed;
- }
-
- if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
- return TRUE;
-
- r = ntohs(rsp->resp);
-
- if (r != BNEP_SUCCESS) {
- error("bnep failed");
- goto failed;
- }
-
- memset(&timeo, 0, sizeof(timeo));
- timeo.tv_sec = 0;
-
- setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
+ DBG("");
- if (bnep_connadd(sk, BNEP_SVC_PANU, nc->dev)) {
- error("%s could not be added", nc->dev);
+ if (err < 0) {
+ error("connect failed %s", strerror(-err));
goto failed;
}
- bnep_if_up(nc->dev);
+ info("%s connected", nc->dev);
+ memcpy(nc->dev, iface, sizeof(nc->dev));
btd_service_connecting_complete(nc->service, 0);
+
if (nc->connect)
local_connect_cb(nc, 0);
@@ -292,101 +219,30 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
nc->state = CONNECTED;
nc->dc_id = device_add_disconnect_watch(nc->peer->device, disconnect_cb,
- nc, NULL);
-
- info("%s connected", nc->dev);
- /* Start watchdog */
+ nc, NULL);
g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) bnep_watchdog_cb, nc);
+ bnep_watchdog_cb, nc);
g_io_channel_unref(nc->io);
nc->io = NULL;
- return FALSE;
+ return;
failed:
cancel_connection(nc, -EIO);
-
- return FALSE;
-}
-
-static int bnep_send_conn_req(struct network_conn *nc)
-{
- struct bnep_setup_conn_req *req;
- struct __service_16 *s;
- unsigned char pkt[BNEP_MTU];
- int fd;
-
- DBG("");
-
- /* Send request */
- req = (void *) pkt;
- req->type = BNEP_CONTROL;
- req->ctrl = BNEP_SETUP_CONN_REQ;
- req->uuid_size = 2; /* 16bit UUID */
- s = (void *) req->service;
- s->dst = htons(nc->id);
- s->src = htons(BNEP_SVC_PANU);
-
- fd = g_io_channel_unix_get_fd(nc->io);
- if (write(fd, pkt, sizeof(*req) + sizeof(*s)) < 0) {
- int err = -errno;
- error("bnep connection req send failed: %s", strerror(errno));
- return err;
- }
-
- nc->attempt_cnt++;
-
- return 0;
-}
-
-static gboolean bnep_conn_req_to(gpointer user_data)
-{
- struct network_conn *nc;
-
- nc = user_data;
- if (nc->attempt_cnt == CON_SETUP_RETRIES) {
- error("Too many bnep connection attempts");
- } else {
- error("bnep connection setup TO, retrying...");
- if (bnep_send_conn_req(nc) == 0)
- return TRUE;
- }
-
- cancel_connection(nc, -ETIMEDOUT);
-
- return FALSE;
-}
-
-static int bnep_connect(struct network_conn *nc)
-{
- int err;
-
- nc->attempt_cnt = 0;
-
- err = bnep_send_conn_req(nc);
- if (err < 0)
- return err;
-
- nc->timeout_source = g_timeout_add_seconds(CON_SETUP_TO,
- bnep_conn_req_to, nc);
-
- g_io_add_watch(nc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- bnep_setup_cb, nc);
-
- return 0;
}
static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
{
struct network_conn *nc = data;
- int perr;
+ int sk, perr;
if (err) {
error("%s", err->message);
goto failed;
}
- perr = bnep_connect(nc);
+ sk = g_io_channel_unix_get_fd(nc->io);
+ perr = bnep_connect(sk, BNEP_SVC_PANU, nc->id, bnep_conn_cb, nc);
if (perr < 0) {
error("bnep connect(): %s (%d)", strerror(-perr), -perr);
goto failed;
@@ -452,7 +308,7 @@ int connection_connect(struct btd_service *service)
if (nc->state != DISCONNECTED)
return -EALREADY;
- src = adapter_get_address(device_get_adapter(peer->device));
+ src = btd_adapter_get_address(device_get_adapter(peer->device));
dst = device_get_address(peer->device);
nc->io = bt_io_connect(connect_cb, nc,
@@ -692,8 +548,6 @@ int connection_register(struct btd_service *service)
nc = g_new0(struct network_conn, 1);
nc->id = id;
- memset(nc->dev, 0, sizeof(nc->dev));
- strcpy(nc->dev, "bnep%d");
nc->service = btd_service_ref(service);
nc->state = DISCONNECTED;
nc->peer = peer;
diff --git a/profiles/network/manager.c b/profiles/network/manager.c
index ab4224de..8ac2decb 100644
--- a/profiles/network/manager.c
+++ b/profiles/network/manager.c
@@ -43,7 +43,7 @@
#include "device.h"
#include "profile.h"
#include "service.h"
-#include "common.h"
+#include "bnep.h"
#include "connection.h"
#include "server.h"
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 7b784e54..b3aab118 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -48,7 +48,7 @@
#include "error.h"
#include "sdpd.h"
-#include "common.h"
+#include "bnep.h"
#include "server.h"
#define NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer1"
@@ -269,9 +269,6 @@ static int server_connadd(struct network_server *ns,
char devname[16];
int err, nsk;
- memset(devname, 0, sizeof(devname));
- strcpy(devname, "bnep%d");
-
nsk = g_io_channel_unix_get_fd(session->io);
err = bnep_connadd(nsk, dst_role, devname);
if (err < 0)
@@ -765,7 +762,7 @@ static struct network_adapter *create_adapter(struct btd_adapter *adapter)
na->io = bt_io_listen(NULL, confirm_event, na,
NULL, &err,
BT_IO_OPT_SOURCE_BDADDR,
- adapter_get_address(adapter),
+ btd_adapter_get_address(adapter),
BT_IO_OPT_PSM, BNEP_PSM,
BT_IO_OPT_OMTU, BNEP_MTU,
BT_IO_OPT_IMTU, BNEP_MTU,
@@ -823,7 +820,7 @@ int server_register(struct btd_adapter *adapter, uint16_t id)
path);
done:
- bacpy(&ns->src, adapter_get_address(adapter));
+ bacpy(&ns->src, btd_adapter_get_address(adapter));
ns->id = id;
ns->na = na;
ns->record_id = 0;
diff --git a/profiles/sap/server.c b/profiles/sap/server.c
index 63314a77..119862df 100644
--- a/profiles/sap/server.c
+++ b/profiles/sap/server.c
@@ -1372,7 +1372,8 @@ int sap_server_register(struct btd_adapter *adapter)
io = bt_io_listen(NULL, connect_confirm_cb, server,
NULL, &gerr,
- BT_IO_OPT_SOURCE_BDADDR, adapter_get_address(adapter),
+ BT_IO_OPT_SOURCE_BDADDR,
+ btd_adapter_get_address(adapter),
BT_IO_OPT_CHANNEL, SAP_SERVER_CHANNEL,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_HIGH,
BT_IO_OPT_MASTER, TRUE,