* [PATCH v3 6/6] android/hal: Check if command socket was shutdown by peer
From: Szymon Janc @ 2013-11-19 14:02 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384869762-3097-1-git-send-email-szymon.janc@tieto.com>
This will allow to print proper error before exiting.
---
android/hal-ipc.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/android/hal-ipc.c b/android/hal-ipc.c
index 5d622e1..b19704a 100644
--- a/android/hal-ipc.c
+++ b/android/hal-ipc.c
@@ -356,6 +356,12 @@ int hal_ipc_cmd(uint8_t service_id, uint8_t opcode, uint16_t len, void *param,
exit(EXIT_FAILURE);
}
+ /* socket was shutdown */
+ if (ret == 0) {
+ error("Command socket closed, aborting");
+ exit(EXIT_FAILURE);
+ }
+
memset(&msg, 0, sizeof(msg));
memset(&cmd, 0, sizeof(cmd));
--
1.8.4.3
^ permalink raw reply related
* [PATCH v3 5/6] android/hal-a2dp: Use generic IPC message handling for events
From: Szymon Janc @ 2013-11-19 14:02 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384869762-3097-1-git-send-email-szymon.janc@tieto.com>
Register handlers on service init and unregister on cleanup.
---
android/hal-a2dp.c | 41 +++++++++++++++++++++--------------------
android/hal.h | 1 -
2 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/android/hal-a2dp.c b/android/hal-a2dp.c
index e9fadb7..7d91151 100644
--- a/android/hal-a2dp.c
+++ b/android/hal-a2dp.c
@@ -31,7 +31,7 @@ static bool interface_ready(void)
return cbs != NULL;
}
-static void handle_conn_state(void *buf)
+static void handle_conn_state(void *buf, uint16_t len)
{
struct hal_ev_a2dp_conn_state *ev = buf;
@@ -40,7 +40,7 @@ static void handle_conn_state(void *buf)
(bt_bdaddr_t *) (ev->bdaddr));
}
-static void handle_audio_state(void *buf)
+static void handle_audio_state(void *buf, uint16_t len)
{
struct hal_ev_a2dp_audio_state *ev = buf;
@@ -48,24 +48,20 @@ static void handle_audio_state(void *buf)
cbs->audio_state_cb(ev->state, (bt_bdaddr_t *)(ev->bdaddr));
}
-/* will be called from notification thread context */
-void bt_notify_a2dp(uint8_t opcode, void *buf, uint16_t len)
-{
- if (!interface_ready())
- return;
-
- switch (opcode) {
- case HAL_EV_A2DP_CONN_STATE:
- handle_conn_state(buf);
- break;
- case HAL_EV_A2DP_AUDIO_STATE:
- handle_audio_state(buf);
- break;
- default:
- DBG("Unhandled callback opcode=0x%x", opcode);
- break;
- }
-}
+/* handlers will be called from notification thread context,
+ * index in table equals to 'opcode - HAL_MINIMUM_EVENT' */
+static const struct hal_ipc_handler ev_handlers[] = {
+ { /* HAL_EV_A2DP_CONN_STATE */
+ .handler = handle_conn_state,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_pan_conn_state),
+ },
+ { /* HAL_EV_A2DP_AUDIO_STATE */
+ .handler = handle_audio_state,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_pan_ctrl_state),
+ },
+};
static bt_status_t a2dp_connect(bt_bdaddr_t *bd_addr)
{
@@ -105,6 +101,9 @@ static bt_status_t init(btav_callbacks_t *callbacks)
cbs = callbacks;
+ hal_ipc_register(HAL_SERVICE_ID_A2DP, ev_handlers,
+ sizeof(ev_handlers)/sizeof(ev_handlers[0]));
+
cmd.service_id = HAL_SERVICE_ID_A2DP;
return hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
@@ -126,6 +125,8 @@ static void cleanup()
hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
sizeof(cmd), &cmd, 0, NULL, NULL);
+
+ hal_ipc_unregister(HAL_SERVICE_ID_A2DP);
}
static btav_interface_t iface = {
diff --git a/android/hal.h b/android/hal.h
index 6bd4c5a..b475411 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -28,4 +28,3 @@ btav_interface_t *bt_get_a2dp_interface(void);
void bt_thread_associate(void);
void bt_thread_disassociate(void);
-void bt_notify_a2dp(uint8_t opcode, void *buf, uint16_t len);
--
1.8.4.3
^ permalink raw reply related
* [PATCH v3 4/6] android/hal-pan: Use generic IPC message handling for events
From: Szymon Janc @ 2013-11-19 14:02 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384869762-3097-1-git-send-email-szymon.janc@tieto.com>
Register handlers on service init and unregister on cleanup.
---
android/hal-pan.c | 40 +++++++++++++++++++++-------------------
android/hal.h | 1 -
2 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/android/hal-pan.c b/android/hal-pan.c
index 2bc560e..0ca9e12 100644
--- a/android/hal-pan.c
+++ b/android/hal-pan.c
@@ -31,7 +31,7 @@ static bool interface_ready(void)
return cbs != NULL;
}
-static void handle_conn_state(void *buf)
+static void handle_conn_state(void *buf, uint16_t len)
{
struct hal_ev_pan_conn_state *ev = buf;
@@ -41,7 +41,7 @@ static void handle_conn_state(void *buf)
ev->local_role, ev->remote_role);
}
-static void handle_ctrl_state(void *buf)
+static void handle_ctrl_state(void *buf, uint16_t len)
{
struct hal_ev_pan_ctrl_state *ev = buf;
@@ -50,23 +50,20 @@ static void handle_ctrl_state(void *buf)
ev->local_role, (char *)ev->name);
}
-void bt_notify_pan(uint8_t opcode, void *buf, uint16_t len)
-{
- if (!interface_ready())
- return;
-
- switch (opcode) {
- case HAL_EV_PAN_CONN_STATE:
- handle_conn_state(buf);
- break;
- case HAL_EV_PAN_CTRL_STATE:
- handle_ctrl_state(buf);
- break;
- default:
- DBG("Unhandled callback opcode=0x%x", opcode);
- break;
- }
-}
+/* handlers will be called from notification thread context,
+ * index in table equals to 'opcode - HAL_MINIMUM_EVENT' */
+static const struct hal_ipc_handler ev_handlers[] = {
+ { /* HAL_EV_PAN_CTRL_STATE */
+ .handler = handle_conn_state,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_pan_conn_state),
+ },
+ { /* HAL_EV_PAN_CONN_STATE */
+ .handler = handle_ctrl_state,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_pan_ctrl_state),
+ },
+};
static bt_status_t pan_enable(int local_role)
{
@@ -143,6 +140,9 @@ static bt_status_t pan_init(const btpan_callbacks_t *callbacks)
cbs = callbacks;
+ hal_ipc_register(HAL_SERVICE_ID_PAN, ev_handlers,
+ sizeof(ev_handlers)/sizeof(ev_handlers[0]));
+
cmd.service_id = HAL_SERVICE_ID_PAN;
return hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
@@ -164,6 +164,8 @@ static void pan_cleanup()
hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
sizeof(cmd), &cmd, 0, NULL, NULL);
+
+ hal_ipc_unregister(HAL_SERVICE_ID_PAN);
}
static btpan_interface_t pan_if = {
diff --git a/android/hal.h b/android/hal.h
index 58426a9..6bd4c5a 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -29,4 +29,3 @@ btav_interface_t *bt_get_a2dp_interface(void);
void bt_thread_associate(void);
void bt_thread_disassociate(void);
void bt_notify_a2dp(uint8_t opcode, void *buf, uint16_t len);
-void bt_notify_pan(uint8_t opcode, void *buf, uint16_t len);
--
1.8.4.3
^ permalink raw reply related
* [PATCH v3 3/6] android/hal-hidhost: Use generic IPC message handling for events
From: Szymon Janc @ 2013-11-19 14:02 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384869762-3097-1-git-send-email-szymon.janc@tieto.com>
Register handlers on service init and unregister on cleanup.
---
android/hal-hidhost.c | 76 +++++++++++++++++++++++++++++----------------------
android/hal.h | 1 -
2 files changed, 44 insertions(+), 33 deletions(-)
diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index 2ce17a3..0573006 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -32,7 +32,7 @@ static bool interface_ready(void)
return cbacks != NULL;
}
-static void handle_conn_state(void *buf)
+static void handle_conn_state(void *buf, uint16_t len)
{
struct hal_ev_hidhost_conn_state *ev = buf;
@@ -41,7 +41,7 @@ static void handle_conn_state(void *buf)
ev->state);
}
-static void handle_info(void *buf)
+static void handle_info(void *buf, uint16_t len)
{
struct hal_ev_hidhost_info *ev = buf;
bthh_hid_info_t info;
@@ -60,7 +60,7 @@ static void handle_info(void *buf)
cbacks->hid_info_cb((bt_bdaddr_t *) ev->bdaddr, info);
}
-static void handle_proto_mode(void *buf)
+static void handle_proto_mode(void *buf, uint16_t len)
{
struct hal_ev_hidhost_proto_mode *ev = buf;
@@ -69,16 +69,21 @@ static void handle_proto_mode(void *buf)
ev->status, ev->mode);
}
-static void handle_get_report(void *buf)
+static void handle_get_report(void *buf, uint16_t len)
{
struct hal_ev_hidhost_get_report *ev = buf;
+ if (len != sizeof(*ev) + ev->len) {
+ error("invalid get report event, aborting");
+ exit(EXIT_FAILURE);
+ }
+
if (cbacks->get_report_cb)
cbacks->get_report_cb((bt_bdaddr_t *) ev->bdaddr, ev->status,
ev->data, ev->len);
}
-static void handle_virtual_unplug(void *buf)
+static void handle_virtual_unplug(void *buf, uint16_t len)
{
struct hal_ev_hidhost_virtual_unplug *ev = buf;
@@ -87,33 +92,35 @@ static void handle_virtual_unplug(void *buf)
ev->status);
}
-/* will be called from notification thread context */
-void bt_notify_hidhost(uint8_t opcode, void *buf, uint16_t len)
-{
- if (!interface_ready())
- return;
-
- switch (opcode) {
- case HAL_EV_HIDHOST_CONN_STATE:
- handle_conn_state(buf);
- break;
- case HAL_EV_HIDHOST_INFO:
- handle_info(buf);
- break;
- case HAL_EV_HIDHOST_PROTO_MODE:
- handle_proto_mode(buf);
- break;
- case HAL_EV_HIDHOST_GET_REPORT:
- handle_get_report(buf);
- break;
- case HAL_EV_HIDHOST_VIRTUAL_UNPLUG:
- handle_virtual_unplug(buf);
- break;
- default:
- DBG("Unhandled callback opcode=0x%x", opcode);
- break;
- }
-}
+/* handlers will be called from notification thread context,
+ * index in table equals to 'opcode - HAL_MINIMUM_EVENT' */
+static const struct hal_ipc_handler ev_handlers[] = {
+ { /* HAL_EV_HIDHOST_CONN_STATE */
+ .handler = handle_conn_state,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_hidhost_conn_state)
+ },
+ { /* HAL_EV_HIDHOST_INFO */
+ .handler = handle_info,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_hidhost_info),
+ },
+ { /* HAL_EV_HIDHOST_PROTO_MODE */
+ .handler = handle_proto_mode,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_hidhost_proto_mode),
+ },
+ { /* HAL_EV_HIDHOST_GET_REPORT */
+ .handler = handle_get_report,
+ .var_len = true,
+ .data_len = sizeof(struct hal_ev_hidhost_get_report),
+ },
+ { /* HAL_EV_HIDHOST_VIRTUAL_UNPLUG */
+ .handler = handle_virtual_unplug,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_hidhost_virtual_unplug),
+ },
+};
static bt_status_t hidhost_connect(bt_bdaddr_t *bd_addr)
{
@@ -362,6 +369,9 @@ static bt_status_t init(bthh_callbacks_t *callbacks)
/* store reference to user callbacks */
cbacks = callbacks;
+ hal_ipc_register(HAL_SERVICE_ID_HIDHOST, ev_handlers,
+ sizeof(ev_handlers)/sizeof(ev_handlers[0]));
+
cmd.service_id = HAL_SERVICE_ID_HIDHOST;
return hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
@@ -383,6 +393,8 @@ static void cleanup(void)
hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
sizeof(cmd), &cmd, 0, NULL, NULL);
+
+ hal_ipc_unregister(HAL_SERVICE_ID_HIDHOST);
}
static bthh_interface_t hidhost_if = {
diff --git a/android/hal.h b/android/hal.h
index 67dad5d..58426a9 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -28,6 +28,5 @@ btav_interface_t *bt_get_a2dp_interface(void);
void bt_thread_associate(void);
void bt_thread_disassociate(void);
-void bt_notify_hidhost(uint8_t opcode, void *buf, uint16_t len);
void bt_notify_a2dp(uint8_t opcode, void *buf, uint16_t len);
void bt_notify_pan(uint8_t opcode, void *buf, uint16_t len);
--
1.8.4.3
^ permalink raw reply related
* [PATCH v3 2/6] android/hal-bluetooth: Register IPC message handlers
From: Szymon Janc @ 2013-11-19 14:02 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384869762-3097-1-git-send-email-szymon.janc@tieto.com>
Register handlers on service init. Since this requires all handlers to
be registered (unknown opcode is considered IPC error) missing handlers
stubs are provided.
---
android/hal-bluetooth.c | 208 ++++++++++++++++++++++++++++++------------------
android/hal.h | 1 -
2 files changed, 129 insertions(+), 80 deletions(-)
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 078d537..69c304a 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -35,7 +35,7 @@ static const bt_callbacks_t *bt_hal_cbacks = NULL;
*pe = *((uint8_t *) (hal_prop->val)); \
} while (0)
-static void handle_adapter_state_changed(void *buf)
+static void handle_adapter_state_changed(void *buf, uint16_t len)
{
struct hal_ev_adapter_state_changed *ev = buf;
@@ -45,38 +45,35 @@ static void handle_adapter_state_changed(void *buf)
bt_hal_cbacks->adapter_state_changed_cb(ev->state);
}
-static void adapter_props_to_hal(bt_property_t *send_props,
- struct hal_property *hal_prop,
- uint8_t num_props, void *buff_end)
+static void adapter_props_to_hal(bt_property_t *send_props, void *buf,
+ uint8_t num_props)
{
- void *p = hal_prop;
+ struct hal_property *prop = buf;
uint8_t i;
for (i = 0; i < num_props; i++) {
- if (p + sizeof(*hal_prop) + hal_prop->len > buff_end) {
- error("invalid adapter properties event, aborting");
- exit(EXIT_FAILURE);
- }
-
- send_props[i].type = hal_prop->type;
+ send_props[i].type = prop->type;
- switch (hal_prop->type) {
+ switch (prop->type) {
case HAL_PROP_ADAPTER_TYPE:
- create_enum_prop(send_props[i], hal_prop,
+ create_enum_prop(send_props[i], prop,
bt_device_type_t);
break;
case HAL_PROP_ADAPTER_SCAN_MODE:
- create_enum_prop(send_props[i], hal_prop,
+ create_enum_prop(send_props[i], prop,
bt_scan_mode_t);
break;
case HAL_PROP_ADAPTER_SERVICE_REC:
default:
- send_props[i].len = hal_prop->len;
- send_props[i].val = hal_prop->val;
+ send_props[i].len = prop->len;
+ send_props[i].val = prop->val;
break;
}
DBG("prop[%d]: %s", i, btproperty2str(&send_props[i]));
+
+ buf += sizeof(*prop) + prop->len;
+ prop = buf;
}
}
@@ -96,36 +93,30 @@ static void adapter_hal_props_cleanup(bt_property_t *props, uint8_t num)
}
}
-static void device_props_to_hal(bt_property_t *send_props,
- struct hal_property *hal_prop,
- uint8_t num_props, void *buff_end)
+static void device_props_to_hal(bt_property_t *send_props, void *buf,
+ uint8_t num_props)
{
- void *p = hal_prop;
+ struct hal_property *prop = buf;
uint8_t i;
for (i = 0; i < num_props; i++) {
- if (p + sizeof(*hal_prop) + hal_prop->len > buff_end) {
- error("invalid adapter properties event, aborting");
- exit(EXIT_FAILURE);
- }
+ send_props[i].type = prop->type;
- send_props[i].type = hal_prop->type;
-
- switch (hal_prop->type) {
+ switch (prop->type) {
case HAL_PROP_DEVICE_TYPE:
- create_enum_prop(send_props[i], hal_prop,
+ create_enum_prop(send_props[i], prop,
bt_device_type_t);
break;
case HAL_PROP_DEVICE_SERVICE_REC:
case HAL_PROP_DEVICE_VERSION_INFO:
default:
- send_props[i].len = hal_prop->len;
- send_props[i].val = hal_prop->val;
+ send_props[i].len = prop->len;
+ send_props[i].val = prop->val;
break;
}
- p += sizeof(*hal_prop) + hal_prop->len;
- hal_prop = p;
+ buf += sizeof(*prop) + prop->len;
+ prop = buf;
DBG("prop[%d]: %s", i, btproperty2str(&send_props[i]));
}
@@ -147,6 +138,28 @@ static void device_hal_props_cleanup(bt_property_t *props, uint8_t num)
}
}
+static void check_props(int num, const struct hal_property *prop, uint16_t len)
+{
+ int i;
+
+ for (i = 0; i < num; i++) {
+ if (sizeof(*prop) + prop->len > len) {
+ error("invalid properties (%zu > %u), aborting",
+ sizeof(*prop) + prop->len, len);
+ exit(EXIT_FAILURE);
+ }
+
+ len -= sizeof(*prop) + prop->len;
+ prop = ((void *) prop) + sizeof(*prop) + prop->len;
+ }
+
+ if (!len)
+ return;
+
+ error("invalid properties length (%u bytes left), aborting", len);
+ exit(EXIT_FAILURE);
+}
+
static void handle_adapter_props_changed(void *buf, uint16_t len)
{
struct hal_ev_adapter_props_changed *ev = buf;
@@ -154,17 +167,19 @@ static void handle_adapter_props_changed(void *buf, uint16_t len)
DBG("");
+ check_props(ev->num_props, ev->props, len - sizeof(*ev));
+
if (!bt_hal_cbacks->adapter_properties_cb)
return;
- adapter_props_to_hal(props, ev->props, ev->num_props, buf + len);
+ adapter_props_to_hal(props, ev->props, ev->num_props);
bt_hal_cbacks->adapter_properties_cb(ev->status, ev->num_props, props);
adapter_hal_props_cleanup(props, ev->num_props);
}
-static void handle_bond_state_change(void *buf)
+static void handle_bond_state_change(void *buf, uint16_t len)
{
struct hal_ev_bond_state_changed *ev = buf;
bt_bdaddr_t *addr = (bt_bdaddr_t *) ev->bdaddr;
@@ -176,7 +191,7 @@ static void handle_bond_state_change(void *buf)
ev->state);
}
-static void handle_pin_request(void *buf)
+static void handle_pin_request(void *buf, uint16_t len)
{
struct hal_ev_pin_request *ev = buf;
/* Those are declared as packed, so it's safe to assign pointers */
@@ -189,7 +204,7 @@ static void handle_pin_request(void *buf)
bt_hal_cbacks->pin_request_cb(addr, name, ev->class_of_dev);
}
-static void handle_ssp_request(void *buf)
+static void handle_ssp_request(void *buf, uint16_t len)
{
struct hal_ev_ssp_request *ev = buf;
/* Those are declared as packed, so it's safe to assign pointers */
@@ -221,7 +236,7 @@ static bool interface_ready(void)
return bt_hal_cbacks != NULL;
}
-static void handle_discovery_state_changed(void *buf)
+static void handle_discovery_state_changed(void *buf, uint16_t len)
{
struct hal_ev_discovery_state_changed *ev = buf;
@@ -238,10 +253,12 @@ static void handle_device_found(void *buf, uint16_t len)
DBG("");
+ check_props(ev->num_props, ev->props, len - sizeof(*ev));
+
if (!bt_hal_cbacks->device_found_cb)
return;
- device_props_to_hal(props, ev->props, ev->num_props, buf + len);
+ device_props_to_hal(props, ev->props, ev->num_props);
bt_hal_cbacks->device_found_cb(ev->num_props, props);
@@ -255,10 +272,12 @@ static void handle_device_state_changed(void *buf, uint16_t len)
DBG("");
+ check_props(ev->num_props, ev->props, len - sizeof(*ev));
+
if (!bt_hal_cbacks->remote_device_properties_cb)
return;
- device_props_to_hal(props, ev->props, ev->num_props, buf + len);
+ device_props_to_hal(props, ev->props, ev->num_props);
bt_hal_cbacks->remote_device_properties_cb(ev->status,
(bt_bdaddr_t *)ev->bdaddr,
@@ -267,7 +286,7 @@ static void handle_device_state_changed(void *buf, uint16_t len)
device_hal_props_cleanup(props, ev->num_props);
}
-static void handle_acl_state_changed(void *buf)
+static void handle_acl_state_changed(void *buf, uint16_t len)
{
struct hal_ev_acl_state_changed *ev = buf;
bt_bdaddr_t *addr = (bt_bdaddr_t *) ev->bdaddr;
@@ -279,47 +298,70 @@ static void handle_acl_state_changed(void *buf)
ev->state);
}
-/* will be called from notification thread context */
-void bt_notify_adapter(uint8_t opcode, void *buf, uint16_t len)
+static void handle_dut_mode_receive(void *buf, uint16_t len)
{
- if (!interface_ready())
- return;
-
- DBG("opcode 0x%x", opcode);
+ DBG("");
- switch (opcode) {
- case HAL_EV_ADAPTER_STATE_CHANGED:
- handle_adapter_state_changed(buf);
- break;
- case HAL_EV_ADAPTER_PROPS_CHANGED:
- handle_adapter_props_changed(buf, len);
- break;
- case HAL_EV_DISCOVERY_STATE_CHANGED:
- handle_discovery_state_changed(buf);
- break;
- case HAL_EV_DEVICE_FOUND:
- handle_device_found(buf, len);
- break;
- case HAL_EV_REMOTE_DEVICE_PROPS:
- handle_device_state_changed(buf, len);
- break;
- case HAL_EV_BOND_STATE_CHANGED:
- handle_bond_state_change(buf);
- break;
- case HAL_EV_PIN_REQUEST:
- handle_pin_request(buf);
- break;
- case HAL_EV_SSP_REQUEST:
- handle_ssp_request(buf);
- break;
- case HAL_EV_ACL_STATE_CHANGED:
- handle_acl_state_changed(buf);
- break;
- default:
- DBG("Unhandled callback opcode=0x%x", opcode);
- break;
- }
-}
+ /* TODO */
+}
+
+/* handlers will be called from notification thread context,
+ * index in table equals to 'opcode - HAL_MINIMUM_EVENT' */
+static const struct hal_ipc_handler ev_handlers[] = {
+ { /* HAL_EV_ADAPTER_STATE_CHANGED */
+ .handler = handle_adapter_state_changed,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_adapter_state_changed)
+ },
+ { /* HAL_EV_ADAPTER_PROPS_CHANGED */
+ .handler = handle_adapter_props_changed,
+ .var_len = true,
+ .data_len = sizeof(struct hal_ev_adapter_props_changed) +
+ sizeof(struct hal_property),
+ },
+ { /* HAL_EV_REMOTE_DEVICE_PROPS */
+ .handler = handle_device_state_changed,
+ .var_len = true,
+ .data_len = sizeof(struct hal_ev_remote_device_props) +
+ sizeof(struct hal_property),
+ },
+ { /* HAL_EV_DEVICE_FOUND */
+ .handler = handle_device_found,
+ .var_len = true,
+ .data_len = sizeof(struct hal_ev_device_found) +
+ sizeof(struct hal_property),
+ },
+ { /* HAL_EV_DISCOVERY_STATE_CHANGED */
+ .handler = handle_discovery_state_changed,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_discovery_state_changed),
+ },
+ { /* HAL_EV_PIN_REQUEST */
+ .handler = handle_pin_request,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_pin_request),
+ },
+ { /* HAL_EV_SSP_REQUEST */
+ .handler = handle_ssp_request,
+ .var_len = false,
+ .data_len = sizeof(handle_ssp_request),
+ },
+ { /* HAL_EV_BOND_STATE_CHANGED */
+ .handler = handle_bond_state_change,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_bond_state_changed),
+ },
+ { /* HAL_EV_ACL_STATE_CHANGED */
+ .handler = handle_acl_state_changed,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_acl_state_changed),
+ },
+ { /* HAL_EV_DUT_MODE_RECEIVE */
+ .handler = handle_dut_mode_receive,
+ .var_len = true,
+ .data_len = sizeof(struct hal_ev_dut_mode_receive),
+ },
+};
static int init(bt_callbacks_t *callbacks)
{
@@ -333,6 +375,9 @@ static int init(bt_callbacks_t *callbacks)
bt_hal_cbacks = callbacks;
+ hal_ipc_register(HAL_SERVICE_ID_BLUETOOTH, ev_handlers,
+ sizeof(ev_handlers)/sizeof(ev_handlers[0]));
+
if (!hal_ipc_init()) {
bt_hal_cbacks = NULL;
return BT_STATUS_FAIL;
@@ -361,6 +406,9 @@ static int init(bt_callbacks_t *callbacks)
fail:
hal_ipc_cleanup();
bt_hal_cbacks = NULL;
+
+ hal_ipc_unregister(HAL_SERVICE_ID_BLUETOOTH);
+
return status;
}
@@ -396,6 +444,8 @@ static void cleanup(void)
hal_ipc_cleanup();
bt_hal_cbacks = NULL;
+
+ hal_ipc_unregister(HAL_SERVICE_ID_BLUETOOTH);
}
static int get_adapter_properties(void)
diff --git a/android/hal.h b/android/hal.h
index 72090fe..67dad5d 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -26,7 +26,6 @@ bthh_interface_t *bt_get_hidhost_interface(void);
btpan_interface_t *bt_get_pan_interface(void);
btav_interface_t *bt_get_a2dp_interface(void);
-void bt_notify_adapter(uint8_t opcode, void *buf, uint16_t len);
void bt_thread_associate(void);
void bt_thread_disassociate(void);
void bt_notify_hidhost(uint8_t opcode, void *buf, uint16_t len);
--
1.8.4.3
^ permalink raw reply related
* [PATCH v3 1/6] android/hal: Add initial code for IPC message handlers
From: Szymon Janc @ 2013-11-19 14:02 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384869762-3097-1-git-send-email-szymon.janc@tieto.com>
This will allow to register and unregister handlers for IPC messages
Basic sanity check will be done in common code. Commands with variable
length will be verified against minimum size only.
---
android/hal-ipc.c | 117 ++++++++++++++++++++++++++++++++++++------------------
android/hal-ipc.h | 10 +++++
2 files changed, 89 insertions(+), 38 deletions(-)
diff --git a/android/hal-ipc.c b/android/hal-ipc.c
index 5155e04..5d622e1 100644
--- a/android/hal-ipc.c
+++ b/android/hal-ipc.c
@@ -43,26 +43,86 @@ static pthread_mutex_t cmd_sk_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_t notif_th = 0;
-static void notification_dispatch(struct hal_hdr *msg, int fd)
+struct service_handler {
+ const struct hal_ipc_handler *handler;
+ uint8_t size;
+};
+
+static struct service_handler services[HAL_SERVICE_ID_MAX + 1];
+
+void hal_ipc_register(uint8_t service, const struct hal_ipc_handler *handlers,
+ uint8_t size)
+{
+ services[service].handler = handlers;
+ services[service].size = size;
+}
+
+void hal_ipc_unregister(uint8_t service)
{
- switch (msg->service_id) {
- case HAL_SERVICE_ID_BLUETOOTH:
- bt_notify_adapter(msg->opcode, msg->payload, msg->len);
- break;
- case HAL_SERVICE_ID_HIDHOST:
- bt_notify_hidhost(msg->opcode, msg->payload, msg->len);
- break;
- case HAL_SERVICE_ID_A2DP:
- bt_notify_a2dp(msg->opcode, msg->payload, msg->len);
- break;
- case HAL_SERVICE_ID_PAN:
- bt_notify_pan(msg->opcode, msg->payload, msg->len);
- break;
- default:
- DBG("Unhandled notification service=%d opcode=0x%x",
+ services[service].handler = NULL;
+ services[service].size = 0;
+}
+
+static void handle_msg(void *buf, ssize_t len)
+{
+ struct hal_hdr *msg = buf;
+ const struct hal_ipc_handler *handler;
+ uint8_t opcode;
+
+ if (len < (ssize_t) sizeof(*msg)) {
+ error("IPC: message too small (%zd bytes), aborting", len);
+ exit(EXIT_FAILURE);
+ }
+
+ if (len != (ssize_t) (sizeof(*msg) + msg->len)) {
+ error("IPC: message malformed (%zd bytes), aborting", len);
+ exit(EXIT_FAILURE);
+ }
+
+ /* if service is valid */
+ if (msg->service_id > HAL_SERVICE_ID_MAX) {
+ error("IPC: unknown service (0x%x), aborting",
+ msg->service_id);
+ exit(EXIT_FAILURE);
+ }
+
+ /* if service is registered */
+ if (!services[msg->service_id].handler) {
+ error("IPC: unregistered service (0x%x), aborting",
+ msg->service_id);
+ exit(EXIT_FAILURE);
+ }
+
+ /* if opcode fit valid range */
+ if (msg->opcode < HAL_MINIMUM_EVENT) {
+ error("IPC: invalid opcode for service 0x%x (0x%x), aborting",
msg->service_id, msg->opcode);
- break;
+ exit(EXIT_FAILURE);
+ }
+
+ /* opcode is used as table offset and must be adjusted as events start
+ * with HAL_MINIMUM_EVENT offset */
+ opcode = msg->opcode - HAL_MINIMUM_EVENT;
+
+ /* if opcode is valid */
+ if (opcode >= services[msg->service_id].size) {
+ error("IPC: invalid opcode for service 0x%x (0x%x), aborting",
+ msg->service_id, msg->opcode);
+ exit(EXIT_FAILURE);
+ }
+
+ handler = &services[msg->service_id].handler[opcode];
+
+ /* if payload size is valid */
+ if ((handler->var_len && handler->data_len > msg->len) ||
+ (!handler->var_len && handler->data_len != msg->len)) {
+ error("IPC: message size invalid for service 0x%x opcode 0x%x "
+ "(%u bytes), aborting",
+ msg->service_id, msg->opcode, msg->len);
+ exit(EXIT_FAILURE);
}
+
+ handler->handler(msg->payload, msg->len);
}
static void *notification_handler(void *data)
@@ -72,7 +132,6 @@ static void *notification_handler(void *data)
struct cmsghdr *cmsg;
char cmsgbuf[CMSG_SPACE(sizeof(int))];
char buf[BLUEZ_HAL_MTU];
- struct hal_hdr *ev = (void *) buf;
ssize_t ret;
int fd;
@@ -83,7 +142,7 @@ static void *notification_handler(void *data)
memset(buf, 0, sizeof(buf));
memset(cmsgbuf, 0, sizeof(cmsgbuf));
- iv.iov_base = ev;
+ iv.iov_base = buf;
iv.iov_len = sizeof(buf);
msg.msg_iov = &iv;
@@ -108,24 +167,6 @@ static void *notification_handler(void *data)
exit(EXIT_FAILURE);
}
- if (ret < (ssize_t) sizeof(*ev)) {
- error("Too small notification (%zd bytes), aborting",
- ret);
- exit(EXIT_FAILURE);
- }
-
- if (ev->opcode < HAL_MINIMUM_EVENT) {
- error("Invalid notification (0x%x), aborting",
- ev->opcode);
- exit(EXIT_FAILURE);
- }
-
- if (ret != (ssize_t) (sizeof(*ev) + ev->len)) {
- error("Malformed notification(%zd bytes), aborting",
- ret);
- exit(EXIT_FAILURE);
- }
-
fd = -1;
/* Receive auxiliary data in msg */
@@ -138,7 +179,7 @@ static void *notification_handler(void *data)
}
}
- notification_dispatch(ev, fd);
+ handle_msg(buf, ret);
}
close(notif_sk);
diff --git a/android/hal-ipc.h b/android/hal-ipc.h
index ea53e1c..2fbf30f 100644
--- a/android/hal-ipc.h
+++ b/android/hal-ipc.h
@@ -15,8 +15,18 @@
*
*/
+struct hal_ipc_handler {
+ void (*handler) (void *buf, uint16_t len);
+ bool var_len;
+ size_t data_len;
+};
+
bool hal_ipc_init(void);
void hal_ipc_cleanup(void);
int hal_ipc_cmd(uint8_t service_id, uint8_t opcode, uint16_t len, void *param,
size_t *rsp_len, void *rsp, int *fd);
+
+void hal_ipc_register(uint8_t service, const struct hal_ipc_handler *handlers,
+ uint8_t size);
+void hal_ipc_unregister(uint8_t service);
--
1.8.4.3
^ permalink raw reply related
* [PATCH v3 0/6] android: IPC improvements
From: Szymon Janc @ 2013-11-19 14:02 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
v3:
- fixed compilation on android 4.2
Szymon Janc (6):
android/hal: Add initial code for IPC message handlers
android/hal-bluetooth: Register IPC message handlers
android/hal-hidhost: Use generic IPC message handling for events
android/hal-pan: Use generic IPC message handling for events
android/hal-a2dp: Use generic IPC message handling for events
android/hal: Check if command socket was shutdown by peer
android/hal-a2dp.c | 41 +++++-----
android/hal-bluetooth.c | 208 ++++++++++++++++++++++++++++++------------------
android/hal-hidhost.c | 76 ++++++++++--------
android/hal-ipc.c | 123 +++++++++++++++++++---------
android/hal-ipc.h | 10 +++
android/hal-pan.c | 40 +++++-----
android/hal.h | 4 -
7 files changed, 310 insertions(+), 192 deletions(-)
--
1.8.4.3
^ permalink raw reply
* Re: [PATCH 5/5] android/hidhost: Free all connected devices in profile cleanup call
From: Ravi Kumar Veeramally @ 2013-11-19 13:55 UTC (permalink / raw)
To: linux-bluetooth, Johan Hedberg
In-Reply-To: <20131119133506.GE30863@x220.p-661hnu-f1>
Hi Johan,
On 11/19/2013 03:35 PM, Johan Hedberg wrote:
> Hi Ravi,
>
> On Tue, Nov 19, 2013, Ravi kumar Veeramally wrote:
>> ---
>> android/hidhost.c | 10 ++++++++++
>> 1 file changed, 10 insertions(+)
>>
>> diff --git a/android/hidhost.c b/android/hidhost.c
>> index 05a3fe4..20dedc4 100644
>> --- a/android/hidhost.c
>> +++ b/android/hidhost.c
>> @@ -1226,6 +1226,14 @@ bool bt_hid_register(int sk, const bdaddr_t *addr)
>> return true;
>> }
>>
>> +static void free_hid_devices(gpointer data, gpointer user_data)
>> +{
>> + struct hid_device *dev = data;
>> +
>> + bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTED);
>> + hid_device_free(dev);
>> +}
>> +
>> void bt_hid_unregister(void)
>> {
>> DBG("");
>> @@ -1233,6 +1241,8 @@ void bt_hid_unregister(void)
>> if (notification_sk < 0)
>> return;
>>
>> + g_slist_foreach(devices, free_hid_devices, NULL);
> I suppose you also need to set devices = NULL; after this call?
Sure.
Thanks,
Ravi.
^ permalink raw reply
* Re: [PATCH 4/5] android/hidhost: Handle error case properly in interrupt_connect_cb
From: Ravi Kumar Veeramally @ 2013-11-19 13:53 UTC (permalink / raw)
To: linux-bluetooth, Johan Hedberg
In-Reply-To: <20131119133130.GD30863@x220.p-661hnu-f1>
Hi Johan,
On 11/19/2013 03:31 PM, Johan Hedberg wrote:
> Hi Ravi,
>
> On Tue, Nov 19, 2013, Ravi kumar Veeramally wrote:
>> ---
>> android/hidhost.c | 9 ++++++---
>> 1 file changed, 6 insertions(+), 3 deletions(-)
> Could you add a bit more descriptive commit message to this one which
> explains what was broken (and how) and how your patch fixes it. When I
> get a patch with an empty commit message I expect it to be very trivial
> and instantly understandable, but that's not the case here.
I will write more details.
Regards,
Ravi.
^ permalink raw reply
* Re: [PATCH 3/5] android: Handle multiple init(register) and cleanup(unregister) calls properly
From: Ravi Kumar Veeramally @ 2013-11-19 13:52 UTC (permalink / raw)
To: linux-bluetooth, Johan Hedberg
In-Reply-To: <20131119133000.GC30863@x220.p-661hnu-f1>
Hi,
On 11/19/2013 03:30 PM, Johan Hedberg wrote:
> Hi Ravi,
>
> On Tue, Nov 19, 2013, Ravi kumar Veeramally wrote:
>> @@ -2275,6 +2275,9 @@ bool bt_bluetooth_register(int sk)
>> {
>> DBG("");
>>
>> + if (notification_sk > 0)
> 0 is a valid file descriptor value so the check should be >= 0
>
>> @@ -1190,6 +1190,9 @@ bool bt_hid_register(int sk, const bdaddr_t *addr)
>>
>> DBG("");
>>
>> + if (notification_sk > 0)
>> + return false;
> Same here.
>
>> @@ -95,6 +95,9 @@ bool bt_pan_register(int sk, const bdaddr_t *addr)
>> {
>> DBG("");
>>
>> + if (notification_sk > 0)
>> + return false;
> And here.
>
> Johan
>
Ok.
Thanks,
Ravi.
^ permalink raw reply
* Re: [PATCH 2/5] android/hal-pan: Return error in case of unsupported PAN roles
From: Ravi Kumar Veeramally @ 2013-11-19 13:51 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <20131119132753.GB30863@x220.p-661hnu-f1>
On 11/19/2013 03:27 PM, Johan Hedberg wrote:
> Hi Ravi,
>
> On Tue, Nov 19, 2013, Ravi kumar Veeramally wrote:
>> ---
>> android/hal-pan.c | 11 +++++++++++
>> 1 file changed, 11 insertions(+)
>>
>> diff --git a/android/hal-pan.c b/android/hal-pan.c
>> index 2bc560e..30facd4 100644
>> --- a/android/hal-pan.c
>> +++ b/android/hal-pan.c
>> @@ -77,6 +77,9 @@ static bt_status_t pan_enable(int local_role)
>> if (!interface_ready())
>> return BT_STATUS_NOT_READY;
>>
>> + if (!(local_role == BTPAN_ROLE_PANU || local_role == BTPAN_ROLE_PANNAP))
>> + return BT_STATUS_UNSUPPORTED;
>> +
>> cmd.local_role = local_role;
>>
>> return hal_ipc_cmd(HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE,
>> @@ -112,6 +115,14 @@ static bt_status_t pan_connect(const bt_bdaddr_t *bd_addr, int local_role,
>> if (!interface_ready())
>> return BT_STATUS_NOT_READY;
>>
>> + if (!((local_role == BTPAN_ROLE_PANNAP &&
>> + remote_role == BTPAN_ROLE_PANU) ||
>> + (local_role == BTPAN_ROLE_PANU &&
>> + remote_role == BTPAN_ROLE_PANNAP) ||
>> + (local_role == BTPAN_ROLE_PANU &&
>> + remote_role == BTPAN_ROLE_PANU)))
>> + return BT_STATUS_UNSUPPORTED;
> First of all you've got incorrect indentation here which make this hard
> to read (the return statement being on the same column as parts of the
> if-statement. When you break lines indent at least by two tabs to make
> a clear separation from the actual branch code.
Ok.
>
> Secondly, shouldn't we be checking that the given local role has been
> enabled (through pan_enable)? Or does the daemon do that checking? In
> fact is there a clear reason not to let the daemon do all the
> verification checks and return an error status over IPC?
I thought it would be easier to do basic checks on supported combinations
at HAL level to reduce the ipc traffic.
I don't know exactly whether UI can send these combinations, but we
can at least
try with haltest tool.
>
> Thirdly, this if-statement takes a while to parse, so I'm wondering
> whether it'd be clearer to format it in a bit more readable way, e.g.:
>
> switch (local_role) {
> case BTPAN_ROLE_PANNAP:
> if (remote_role != BTPAN_ROLE_PANU)
> return BT_STATUS_UNSUPPORTED;
> break;
> case BTPAN_ROLE_PANU:
> if (remote_role != BTPAN_ROLE_PANNAP &&
> remote_role != BTPAN_ROLE_PANU)
> return BT_STATUS_UNSUPPORTED;
> break;
> default:
> return BT_STATUS_UNSUPPORTED;
> }
>
> Thoughts?
Yes, make sense to use 'switch' for more readability.
Is it ok to send _v2 with switch or better to handle in daemon?
Thanks,
Ravi.
^ permalink raw reply
* Re: [PATCH] autopair: Add special handling for printers
From: Johan Hedberg @ 2013-11-19 13:36 UTC (permalink / raw)
To: Bastien Nocera; +Cc: linux-bluetooth
In-Reply-To: <1384866940.2027.24.camel@nuvo>
Hi Bastien,
On Tue, Nov 19, 2013, Bastien Nocera wrote:
>
> As was done in gnome-bluetooth since 2009:
> https://git.gnome.org/browse/gnome-bluetooth/commit/?id=7a472c151d44a3378ecbd3c2a75c763f5c577fe9
> ---
> plugins/autopair.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
Applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH 5/5] android/hidhost: Free all connected devices in profile cleanup call
From: Johan Hedberg @ 2013-11-19 13:35 UTC (permalink / raw)
To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1384863676-12358-5-git-send-email-ravikumar.veeramally@linux.intel.com>
Hi Ravi,
On Tue, Nov 19, 2013, Ravi kumar Veeramally wrote:
> ---
> android/hidhost.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/android/hidhost.c b/android/hidhost.c
> index 05a3fe4..20dedc4 100644
> --- a/android/hidhost.c
> +++ b/android/hidhost.c
> @@ -1226,6 +1226,14 @@ bool bt_hid_register(int sk, const bdaddr_t *addr)
> return true;
> }
>
> +static void free_hid_devices(gpointer data, gpointer user_data)
> +{
> + struct hid_device *dev = data;
> +
> + bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTED);
> + hid_device_free(dev);
> +}
> +
> void bt_hid_unregister(void)
> {
> DBG("");
> @@ -1233,6 +1241,8 @@ void bt_hid_unregister(void)
> if (notification_sk < 0)
> return;
>
> + g_slist_foreach(devices, free_hid_devices, NULL);
I suppose you also need to set devices = NULL; after this call?
Johan
^ permalink raw reply
* Re: [PATCH 4/5] android/hidhost: Handle error case properly in interrupt_connect_cb
From: Johan Hedberg @ 2013-11-19 13:31 UTC (permalink / raw)
To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1384863676-12358-4-git-send-email-ravikumar.veeramally@linux.intel.com>
Hi Ravi,
On Tue, Nov 19, 2013, Ravi kumar Veeramally wrote:
> ---
> android/hidhost.c | 9 ++++++---
> 1 file changed, 6 insertions(+), 3 deletions(-)
Could you add a bit more descriptive commit message to this one which
explains what was broken (and how) and how your patch fixes it. When I
get a patch with an empty commit message I expect it to be very trivial
and instantly understandable, but that's not the case here.
Johan
^ permalink raw reply
* [PATCHv5 19/19] android/socket: Add SPP SDP record
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/socket.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 63 insertions(+), 1 deletion(-)
diff --git a/android/socket.c b/android/socket.c
index 0c71297..dc73dd1 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -225,9 +225,69 @@ static sdp_record_t *create_pbap_record(uint8_t chan)
sdp_list_free(proto[1], NULL);
sdp_list_free(apseq, NULL);
sdp_list_free(pfseq, NULL);
+ sdp_list_free(aproto, NULL);
sdp_list_free(root, NULL);
sdp_list_free(svclass_id, NULL);
+
+ return record;
+}
+
+static sdp_record_t *create_spp_record(uint8_t chan)
+{
+ sdp_list_t *svclass_id, *apseq, *profiles, *root;
+ uuid_t root_uuid, sp_uuid, rfcomm;
+ sdp_profile_desc_t profile;
+ sdp_list_t *aproto, *proto[1];
+ sdp_data_t *channel;
+ sdp_record_t *record;
+
+ record = sdp_record_alloc();
+ if (!record)
+ return NULL;
+
+ record->handle = sdp_next_handle();
+
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+ root = sdp_list_append(NULL, &root_uuid);
+ sdp_set_browse_groups(record, root);
+
+ sdp_uuid16_create(&sp_uuid, SERIAL_PORT_SVCLASS_ID);
+ svclass_id = sdp_list_append(NULL, &sp_uuid);
+ sdp_set_service_classes(record, svclass_id);
+
+ sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
+ profile.version = 0x0100;
+ profiles = sdp_list_append(NULL, &profile);
+ sdp_set_profile_descs(record, profiles);
+
+ sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
+ proto[0] = sdp_list_append(NULL, &rfcomm);
+ channel = sdp_data_alloc(SDP_UINT8, &chan);
+ proto[0] = sdp_list_append(proto[0], channel);
+ apseq = sdp_list_append(NULL, proto[0]);
+
+ aproto = sdp_list_append(NULL, apseq);
+ sdp_set_access_protos(record, aproto);
+
+ sdp_add_lang_attr(record);
+
+ sdp_set_info_attr(record, "Serial Port", "BlueZ", "COM Port");
+
+ sdp_set_url_attr(record, "http://www.bluez.org/",
+ "http://www.bluez.org/", "http://www.bluez.org/");
+
+ sdp_set_service_id(record, sp_uuid);
+ sdp_set_service_ttl(record, 0xffff);
+ sdp_set_service_avail(record, 0xff);
+ sdp_set_record_state(record, 0x00001234);
+
+ sdp_data_free(channel);
+ sdp_list_free(proto[0], NULL);
+ sdp_list_free(apseq, NULL);
sdp_list_free(aproto, NULL);
+ sdp_list_free(root, NULL);
+ sdp_list_free(svclass_id, NULL);
+ sdp_list_free(profiles, NULL);
return record;
}
@@ -266,7 +326,9 @@ static struct profile_info {
0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
},
- .channel = SPP_DEFAULT_CHANNEL
+ .channel = SPP_DEFAULT_CHANNEL,
+ .svc_hint = 0,
+ .create_record = create_spp_record
},
};
--
1.7.10.4
^ permalink raw reply related
* [PATCHv5 18/19] android/socket: Add PBAP SDP record
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
This adds SDP service record like shown below:
Service Name: OBEX Phonebook Access Server
Service RecHandle: 0x10002
Service Class ID List:
"Phonebook Access - PSE" (0x112f)
Protocol Descriptor List:
"RFCOMM" (0x0003)
Channel: 15
"OBEX" (0x0008)
Profile Descriptor List:
"Phonebook Access" (0x1130)
Version: 0x0100
---
android/socket.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 64 insertions(+), 1 deletion(-)
diff --git a/android/socket.c b/android/socket.c
index 9358d4a..0c71297 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -171,6 +171,67 @@ static sdp_record_t *create_opp_record(uint8_t chan)
return record;
}
+static sdp_record_t *create_pbap_record(uint8_t chan)
+{
+ sdp_list_t *svclass_id, *pfseq, *apseq, *root;
+ uuid_t root_uuid, pbap_uuid, rfcomm_uuid, obex_uuid;
+ sdp_profile_desc_t profile[1];
+ sdp_list_t *aproto, *proto[2];
+ sdp_data_t *channel;
+ uint8_t formats[] = { 0x01 };
+ uint8_t dtd = SDP_UINT8;
+ sdp_data_t *sflist;
+ sdp_record_t *record;
+
+ record = sdp_record_alloc();
+ if (!record)
+ return NULL;
+
+ record->handle = sdp_next_handle();
+
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+ root = sdp_list_append(NULL, &root_uuid);
+ sdp_set_browse_groups(record, root);
+
+ sdp_uuid16_create(&pbap_uuid, PBAP_PSE_SVCLASS_ID);
+ svclass_id = sdp_list_append(NULL, &pbap_uuid);
+ sdp_set_service_classes(record, svclass_id);
+
+ sdp_uuid16_create(&profile[0].uuid, PBAP_PROFILE_ID);
+ profile[0].version = 0x0100;
+ pfseq = sdp_list_append(NULL, profile);
+ sdp_set_profile_descs(record, pfseq);
+
+ sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+ proto[0] = sdp_list_append(NULL, &rfcomm_uuid);
+ channel = sdp_data_alloc(SDP_UINT8, &chan);
+ proto[0] = sdp_list_append(proto[0], channel);
+ apseq = sdp_list_append(NULL, proto[0]);
+
+ sdp_uuid16_create(&obex_uuid, OBEX_UUID);
+ proto[1] = sdp_list_append(NULL, &obex_uuid);
+ apseq = sdp_list_append(apseq, proto[1]);
+
+ aproto = sdp_list_append(NULL, apseq);
+ sdp_set_access_protos(record, aproto);
+
+ sflist = sdp_data_alloc(dtd, formats);
+ sdp_attr_add(record, SDP_ATTR_SUPPORTED_REPOSITORIES, sflist);
+
+ sdp_set_info_attr(record, "OBEX Phonebook Access Server", NULL, NULL);
+
+ sdp_data_free(channel);
+ sdp_list_free(proto[0], NULL);
+ sdp_list_free(proto[1], NULL);
+ sdp_list_free(apseq, NULL);
+ sdp_list_free(pfseq, NULL);
+ sdp_list_free(root, NULL);
+ sdp_list_free(svclass_id, NULL);
+ sdp_list_free(aproto, NULL);
+
+ return record;
+}
+
static struct profile_info {
uint8_t uuid[16];
uint8_t channel;
@@ -183,7 +244,9 @@ static struct profile_info {
0x00, 0x00, 0x11, 0x2F, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
},
- .channel = PBAP_DEFAULT_CHANNEL
+ .channel = PBAP_DEFAULT_CHANNEL,
+ .svc_hint = SVC_HINT_OBEX,
+ .create_record = create_pbap_record
}, {
.uuid = {
0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00,
--
1.7.10.4
^ permalink raw reply related
* [PATCHv5 17/19] android/socket: Add SPP uuid to profile table
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/socket.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/android/socket.c b/android/socket.c
index e3241c9..9358d4a 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -45,6 +45,7 @@
#include "utils.h"
#include "socket.h"
+#define SPP_DEFAULT_CHANNEL 3
#define OPP_DEFAULT_CHANNEL 9
#define PBAP_DEFAULT_CHANNEL 15
#define MAS_DEFAULT_CHANNEL 16
@@ -197,7 +198,13 @@ static struct profile_info {
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
},
.channel = MAS_DEFAULT_CHANNEL
- }
+ }, {
+ .uuid = {
+ 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
+ },
+ .channel = SPP_DEFAULT_CHANNEL
+ },
};
static uint32_t sdp_service_register(struct profile_info *profile)
--
1.7.10.4
^ permalink raw reply related
* [PATCHv5 16/19] android/socket: Add MAS uuid to profile table
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/socket.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index 9890739..e3241c9 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -47,6 +47,7 @@
#define OPP_DEFAULT_CHANNEL 9
#define PBAP_DEFAULT_CHANNEL 15
+#define MAS_DEFAULT_CHANNEL 16
/* Use Object Transfer for all services */
#define SVC_HINT_OBEX 0x10
@@ -190,6 +191,12 @@ static struct profile_info {
.channel = OPP_DEFAULT_CHANNEL,
.svc_hint = SVC_HINT_OBEX,
.create_record = create_opp_record
+ }, {
+ .uuid = {
+ 0x00, 0x00, 0x11, 0x32, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
+ },
+ .channel = MAS_DEFAULT_CHANNEL
}
};
--
1.7.10.4
^ permalink raw reply related
* [PATCHv5 15/19] android/socket: Add SDP record for OPP profile
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
This adds SDP record for OPP shown below:
Service Name: OBEX Object Push
Service RecHandle: 0x10002
Service Class ID List:
"OBEX Object Push" (0x1105)
Protocol Descriptor List:
"RFCOMM" (0x0003)
Channel: 9
"OBEX" (0x0008)
Profile Descriptor List:
"OBEX Object Push" (0x1105)
Version: 0x0100
---
android/socket.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 98 insertions(+), 1 deletion(-)
diff --git a/android/socket.c b/android/socket.c
index d2588cc..9890739 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -35,7 +35,9 @@
#include "lib/sdp.h"
#include "lib/sdp_lib.h"
#include "src/sdp-client.h"
+#include "src/sdpd.h"
+#include "bluetooth.h"
#include "log.h"
#include "hal-msg.h"
#include "hal-ipc.h"
@@ -46,6 +48,9 @@
#define OPP_DEFAULT_CHANNEL 9
#define PBAP_DEFAULT_CHANNEL 15
+/* Use Object Transfer for all services */
+#define SVC_HINT_OBEX 0x10
+
static bdaddr_t adapter_addr;
/* Simple list of RFCOMM server sockets */
@@ -59,6 +64,7 @@ struct rfcomm_sock {
int real_sock; /* real RFCOMM socket */
int channel; /* RFCOMM channel */
bdaddr_t dst;
+ uint32_t service_handle;
};
static struct rfcomm_sock *create_rfsock(int sock, int *hal_fd)
@@ -90,9 +96,79 @@ static void cleanup_rfsock(struct rfcomm_sock *rfsock)
if (rfsock->real_sock > 0)
close(rfsock->real_sock);
+ if (rfsock->service_handle)
+ bt_adapter_remove_record(rfsock->service_handle);
+
g_free(rfsock);
}
+static sdp_record_t *create_opp_record(uint8_t chan)
+{
+ sdp_list_t *svclass_id, *pfseq, *apseq, *root;
+ uuid_t root_uuid, opush_uuid, rfcomm_uuid, obex_uuid;
+ sdp_profile_desc_t profile[1];
+ sdp_list_t *aproto, *proto[2];
+ uint8_t formats[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xff };
+ void *dtds[sizeof(formats)], *values[sizeof(formats)];
+ unsigned int i;
+ uint8_t dtd = SDP_UINT8;
+ sdp_data_t *sflist;
+ sdp_data_t *channel;
+ sdp_record_t *record;
+
+ record = sdp_record_alloc();
+ if (!record)
+ return NULL;
+
+ record->handle = sdp_next_handle();
+
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+ root = sdp_list_append(NULL, &root_uuid);
+ sdp_set_browse_groups(record, root);
+
+ sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID);
+ svclass_id = sdp_list_append(NULL, &opush_uuid);
+ sdp_set_service_classes(record, svclass_id);
+
+ sdp_uuid16_create(&profile[0].uuid, OBEX_OBJPUSH_PROFILE_ID);
+ profile[0].version = 0x0100;
+ pfseq = sdp_list_append(NULL, profile);
+ sdp_set_profile_descs(record, pfseq);
+
+ sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+ proto[0] = sdp_list_append(NULL, &rfcomm_uuid);
+ channel = sdp_data_alloc(SDP_UINT8, &chan);
+ proto[0] = sdp_list_append(proto[0], channel);
+ apseq = sdp_list_append(NULL, proto[0]);
+
+ sdp_uuid16_create(&obex_uuid, OBEX_UUID);
+ proto[1] = sdp_list_append(NULL, &obex_uuid);
+ apseq = sdp_list_append(apseq, proto[1]);
+
+ aproto = sdp_list_append(NULL, apseq);
+ sdp_set_access_protos(record, aproto);
+
+ for (i = 0; i < sizeof(formats); i++) {
+ dtds[i] = &dtd;
+ values[i] = &formats[i];
+ }
+ sflist = sdp_seq_alloc(dtds, values, sizeof(formats));
+ sdp_attr_add(record, SDP_ATTR_SUPPORTED_FORMATS_LIST, sflist);
+
+ sdp_set_info_attr(record, "OBEX Object Push", NULL, NULL);
+
+ sdp_data_free(channel);
+ sdp_list_free(proto[0], NULL);
+ sdp_list_free(proto[1], NULL);
+ sdp_list_free(apseq, NULL);
+ sdp_list_free(pfseq, NULL);
+ sdp_list_free(aproto, NULL);
+ sdp_list_free(root, NULL);
+ sdp_list_free(svclass_id, NULL);
+
+ return record;
+}
+
static struct profile_info {
uint8_t uuid[16];
uint8_t channel;
@@ -111,10 +187,29 @@ static struct profile_info {
0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
},
- .channel = OPP_DEFAULT_CHANNEL
+ .channel = OPP_DEFAULT_CHANNEL,
+ .svc_hint = SVC_HINT_OBEX,
+ .create_record = create_opp_record
}
};
+static uint32_t sdp_service_register(struct profile_info *profile)
+{
+ sdp_record_t *record;
+
+ record = profile->create_record(profile->channel);
+ if (!record)
+ return 0;
+
+ if (bt_adapter_add_record(record, profile->svc_hint) < 0) {
+ error("Failed to register on SDP record");
+ sdp_record_free(record);
+ return 0;
+ }
+
+ return record->handle;
+}
+
static int bt_sock_send_fd(int sock_fd, const void *buf, int len, int send_fd)
{
ssize_t ret;
@@ -387,6 +482,8 @@ static int handle_listen(void *buf)
return -1;
}
+ rfsock->service_handle = sdp_service_register(profile);
+
DBG("real_sock %d fd %d hal_fd %d",
rfsock->real_sock, rfsock->fd, hal_fd);
--
1.7.10.4
^ permalink raw reply related
* [PATCHv5 14/19] android/socket: Close file descriptor after sending
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/socket.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index ee2df1b..d2588cc 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -576,6 +576,7 @@ void bt_sock_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
break;
ipc_send(sk, HAL_SERVICE_ID_SOCK, opcode, 0, NULL, fd);
+ close(fd);
return;
case HAL_OP_SOCK_CONNECT:
fd = handle_connect(buf);
@@ -583,6 +584,7 @@ void bt_sock_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
break;
ipc_send(sk, HAL_SERVICE_ID_SOCK, opcode, 0, NULL, fd);
+ close(fd);
return;
default:
DBG("Unhandled command, opcode 0x%x", opcode);
--
1.7.10.4
^ permalink raw reply related
* [PATCHv5 13/19] android/socket: Send connect signal on connect
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Android framework expects connect signal to be sent when
remote device is connected.
---
android/socket.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index e620d10..ee2df1b 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -393,6 +393,33 @@ static int handle_listen(void *buf)
return hal_fd;
}
+static ssize_t sock_send_connect(struct rfcomm_sock *rfsock, bdaddr_t *bdaddr)
+{
+ struct hal_sock_connect_signal cmd;
+ ssize_t len;
+
+ DBG("");
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.size = sizeof(cmd);
+ bdaddr2android(bdaddr, cmd.bdaddr);
+ cmd.channel = rfsock->channel;
+ cmd.status = 0;
+
+ len = write(rfsock->fd, &cmd, sizeof(cmd));
+ if (len < 0) {
+ error("%s", strerror(errno));
+ return len;
+ }
+
+ if (len != (ssize_t) sizeof(cmd)) {
+ error("Error sending connect signal");
+ return -1;
+ }
+
+ return len;
+}
+
static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
{
struct rfcomm_sock *rfsock = user_data;
@@ -423,6 +450,9 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
rfsock->fd, rfsock->real_sock, rfsock->channel,
g_io_channel_unix_get_fd(io));
+ if (sock_send_connect(rfsock, &dst) < 0)
+ goto fail;
+
/* Handle events from Android */
io_stack = g_io_channel_unix_new(rfsock->fd);
g_io_add_watch(io_stack, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
--
1.7.10.4
^ permalink raw reply related
* [PATCHv5 12/19] android/socket: Send RFCOMM channel to framework
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Framework expects channel to be send.
---
android/socket.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index ad09a2c..e620d10 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -493,6 +493,11 @@ static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
goto fail;
}
+ if (write(rfsock->fd, &chan, sizeof(chan)) != sizeof(chan)) {
+ error("Error sending RFCOMM channel");
+ goto fail;
+ }
+
rfsock->real_sock = g_io_channel_unix_get_fd(io);
rfsock->channel = chan;
connections = g_list_append(connections, rfsock);
--
1.7.10.4
^ permalink raw reply related
* [PATCHv5 11/19] android/socket: Implement HAL connect call
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
HAL connect uses similar event handlers like listen call.
---
android/socket.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index 6d9c69e..ad09a2c 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -395,6 +395,47 @@ static int handle_listen(void *buf)
static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
{
+ struct rfcomm_sock *rfsock = user_data;
+ GIOChannel *io_stack;
+ GError *gerr = NULL;
+ bdaddr_t dst;
+ char address[18];
+ int chan = -1;
+
+ if (err) {
+ error("%s", err->message);
+ goto fail;
+ }
+
+ bt_io_get(io, &gerr,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_INVALID);
+ if (gerr) {
+ error("%s", gerr->message);
+ g_error_free(gerr);
+ goto fail;
+ }
+
+ ba2str(&dst, address);
+ DBG("Connected to %s rfsock %p chan %d", address, rfsock, chan);
+
+ DBG("rfsock: fd %d real_sock %d chan %u sock %d",
+ rfsock->fd, rfsock->real_sock, rfsock->channel,
+ g_io_channel_unix_get_fd(io));
+
+ /* Handle events from Android */
+ io_stack = g_io_channel_unix_new(rfsock->fd);
+ g_io_add_watch(io_stack, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ sock_stack_event_cb, rfsock);
+ g_io_channel_unref(io_stack);
+
+ /* Handle rfcomm events */
+ g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ sock_rfcomm_event_cb, rfsock);
+
+ return;
+fail:
+ cleanup_rfsock(rfsock);
}
static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH 3/5] android: Handle multiple init(register) and cleanup(unregister) calls properly
From: Johan Hedberg @ 2013-11-19 13:30 UTC (permalink / raw)
To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1384863676-12358-3-git-send-email-ravikumar.veeramally@linux.intel.com>
Hi Ravi,
On Tue, Nov 19, 2013, Ravi kumar Veeramally wrote:
> @@ -2275,6 +2275,9 @@ bool bt_bluetooth_register(int sk)
> {
> DBG("");
>
> + if (notification_sk > 0)
0 is a valid file descriptor value so the check should be >= 0
> @@ -1190,6 +1190,9 @@ bool bt_hid_register(int sk, const bdaddr_t *addr)
>
> DBG("");
>
> + if (notification_sk > 0)
> + return false;
Same here.
> @@ -95,6 +95,9 @@ bool bt_pan_register(int sk, const bdaddr_t *addr)
> {
> DBG("");
>
> + if (notification_sk > 0)
> + return false;
And here.
Johan
^ permalink raw reply
* [PATCHv5 10/19] android/socket: Parse SDP response and connect
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Parse SDP response, find RFCOMM channel and connect.
---
android/socket.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index 843fba8..6d9c69e 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -393,9 +393,72 @@ static int handle_listen(void *buf)
return hal_fd;
}
+static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+{
+}
+
static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
{
+ struct rfcomm_sock *rfsock = data;
+ GError *gerr = NULL;
+ sdp_list_t *list;
+ GIOChannel *io;
+ int chan;
+
DBG("");
+
+ if (err < 0) {
+ error("Unable to get SDP record: %s", strerror(-err));
+ goto fail;
+ }
+
+ if (!recs || !recs->data) {
+ error("No SDP records found");
+ goto fail;
+ }
+
+ for (list = recs; list != NULL; list = list->next) {
+ sdp_record_t *rec = list->data;
+ sdp_list_t *protos;
+
+ if (sdp_get_access_protos(rec, &protos) < 0) {
+ error("Unable to get proto list");
+ goto fail;
+ }
+
+ chan = sdp_get_proto_port(protos, RFCOMM_UUID);
+
+ sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free,
+ NULL);
+ sdp_list_free(protos, NULL);
+ }
+
+ if (chan <= 0) {
+ error("Could not get RFCOMM channel %d", chan);
+ goto fail;
+ }
+
+ DBG("Got RFCOMM channel %d", chan);
+
+ io = bt_io_connect(connect_cb, rfsock, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+ BT_IO_OPT_DEST_BDADDR, &rfsock->dst,
+ BT_IO_OPT_CHANNEL, chan,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+ BT_IO_OPT_INVALID);
+ if (!io) {
+ error("Failed connect: %s", gerr->message);
+ g_error_free(gerr);
+ goto fail;
+ }
+
+ rfsock->real_sock = g_io_channel_unix_get_fd(io);
+ rfsock->channel = chan;
+ connections = g_list_append(connections, rfsock);
+ return;
+
+fail:
+ cleanup_rfsock(rfsock);
}
static int handle_connect(void *buf)
--
1.7.10.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox