* [PATCH 1/7] android: Remove bt_adapter structure
From: Szymon Janc @ 2013-11-12 0:24 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384215857-19679-1-git-send-email-szymon.janc@tieto.com>
Only one controller is used so there is no need to keep extra
abstraction for it.
---
android/adapter.c | 271 +++++++++++++++++++++++++-----------------------------
1 file changed, 123 insertions(+), 148 deletions(-)
diff --git a/android/adapter.c b/android/adapter.c
index 65b3170..e161f9d 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -58,23 +58,17 @@ static int notification_sk = -1;
/* This list contains addresses which are asked for records */
static GSList *browse_reqs;
-struct bt_adapter {
- uint16_t index;
- struct mgmt *mgmt;
+static uint16_t adapter_index = MGMT_INDEX_NONE;
+static struct mgmt *mgmt_if = NULL;
+static bt_adapter_ready adapter_ready = NULL;
+static bdaddr_t adapter_bdaddr;
+static uint32_t adapter_dev_class = 0;
+static char *adapter_name = NULL;
+static uint32_t current_settings = 0;
- bt_adapter_ready ready;
+static bool adapter_discovering = false;
- bdaddr_t bdaddr;
- uint32_t dev_class;
-
- char *name;
-
- uint32_t supported_settings;
- uint32_t current_settings;
-
- bool discovering;
- uint32_t discoverable_timeout;
-};
+uint32_t adapter_discoverable_timeout = DEFAULT_DISCOVERABLE_TIMEOUT;
struct browse_req {
bdaddr_t bdaddr;
@@ -90,7 +84,6 @@ static const uint16_t uuid_list[] = {
0
};
-static struct bt_adapter *adapter;
static GSList *found_devices = NULL;
static void adapter_name_changed(const uint8_t *name)
@@ -115,13 +108,13 @@ static void adapter_name_changed(const uint8_t *name)
static void adapter_set_name(const uint8_t *name)
{
- if (!g_strcmp0(adapter->name, (const char *) name))
+ if (!g_strcmp0(adapter_name, (const char *) name))
return;
DBG("%s", name);
- g_free(adapter->name);
- adapter->name = g_strdup((const char *) name);
+ g_free(adapter_name);
+ adapter_name = g_strdup((const char *) name);
adapter_name_changed(name);
}
@@ -145,7 +138,7 @@ static void powered_changed(void)
{
struct hal_ev_adapter_state_changed ev;
- ev.state = (adapter->current_settings & MGMT_SETTING_POWERED) ?
+ ev.state = (current_settings & MGMT_SETTING_POWERED) ?
HAL_POWER_ON : HAL_POWER_OFF;
DBG("%u", ev.state);
@@ -158,8 +151,8 @@ static uint8_t settings2scan_mode(void)
{
bool connectable, discoverable;
- connectable = adapter->current_settings & MGMT_SETTING_CONNECTABLE;
- discoverable = adapter->current_settings & MGMT_SETTING_DISCOVERABLE;
+ connectable = current_settings & MGMT_SETTING_CONNECTABLE;
+ discoverable = current_settings & MGMT_SETTING_DISCOVERABLE;
if (connectable && discoverable)
return HAL_ADAPTER_SCAN_MODE_CONN_DISC;
@@ -201,7 +194,7 @@ static void adapter_class_changed(void)
ev->props[0].type = HAL_PROP_ADAPTER_CLASS;
ev->props[0].len = sizeof(uint32_t);
- memcpy(ev->props->val, &adapter->dev_class, sizeof(uint32_t));
+ memcpy(ev->props->val, &adapter_dev_class, sizeof(uint32_t));
ipc_send(notification_sk, HAL_SERVICE_ID_BLUETOOTH,
HAL_EV_ADAPTER_PROPS_CHANGED, sizeof(buf), buf, -1);
@@ -212,9 +205,9 @@ static void settings_changed(uint32_t settings)
uint32_t changed_mask;
uint32_t scan_mode_mask;
- changed_mask = adapter->current_settings ^ settings;
+ changed_mask = current_settings ^ settings;
- adapter->current_settings = settings;
+ current_settings = settings;
DBG("0x%08x", changed_mask);
@@ -229,7 +222,7 @@ static void settings_changed(uint32_t settings)
* Only when powered, the connectable and discoverable
* state changes should be communicated.
*/
- if (adapter->current_settings & MGMT_SETTING_POWERED)
+ if (current_settings & MGMT_SETTING_POWERED)
if (changed_mask & scan_mode_mask)
scan_mode_changed();
}
@@ -246,10 +239,9 @@ static void new_settings_callback(uint16_t index, uint16_t length,
settings = bt_get_le32(param);
- DBG("settings: 0x%8.8x -> 0x%8.8x", adapter->current_settings,
- settings);
+ DBG("settings: 0x%8.8x -> 0x%8.8x", current_settings, settings);
- if (settings == adapter->current_settings)
+ if (settings == current_settings)
return;
settings_changed(settings);
@@ -268,12 +260,12 @@ static void mgmt_dev_class_changed_event(uint16_t index, uint16_t length,
dev_class = rp->val[0] | (rp->val[1] << 8) | (rp->val[2] << 16);
- if (dev_class == adapter->dev_class)
+ if (dev_class == adapter_dev_class)
return;
DBG("Class: 0x%06x", dev_class);
- adapter->dev_class = dev_class;
+ adapter_dev_class = dev_class;
adapter_class_changed();
@@ -410,7 +402,7 @@ static void browse_cb(sdp_list_t *recs, int err, gpointer user_data)
/* Search for mandatory uuids */
if (uuid_list[req->search_uuid]) {
sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
- bt_search_service(&adapter->bdaddr, &req->bdaddr, &uuid,
+ bt_search_service(&adapter_bdaddr, &req->bdaddr, &uuid,
browse_cb, user_data, NULL);
return;
}
@@ -442,7 +434,7 @@ static uint8_t browse_remote_sdp(const bdaddr_t *addr)
bacpy(&req->bdaddr, addr);
sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
- if (bt_search_service(&adapter->bdaddr,
+ if (bt_search_service(&adapter_bdaddr,
&req->bdaddr, &uuid, browse_cb, req, NULL) < 0) {
browse_req_free(req);
return false;
@@ -597,17 +589,17 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
return;
}
- DBG("hci%u type %u discovering %u", adapter->index, ev->type,
+ DBG("hci%u type %u discovering %u", adapter_index, ev->type,
ev->discovering);
- if (adapter->discovering == !!ev->discovering)
+ if (adapter_discovering == !!ev->discovering)
return;
- adapter->discovering = !!ev->discovering;
+ adapter_discovering = !!ev->discovering;
DBG("new discovering state %u", ev->discovering);
- if (adapter->discovering) {
+ if (adapter_discovering) {
cp.state = HAL_DISCOVERY_STATE_STARTED;
} else {
g_slist_free_full(found_devices, g_free);
@@ -628,7 +620,7 @@ static void confirm_device_name(const bdaddr_t *addr, uint8_t addr_type)
bacpy(&cp.addr.bdaddr, addr);
cp.addr.type = addr_type;
- if (mgmt_reply(adapter->mgmt, MGMT_OP_CONFIRM_NAME, adapter->index,
+ if (mgmt_reply(mgmt_if, MGMT_OP_CONFIRM_NAME, adapter_index,
sizeof(cp), &cp, NULL, NULL, NULL) == 0)
error("Failed to send confirm name request");
}
@@ -876,56 +868,49 @@ static void mgmt_device_unpaired_event(uint16_t index, uint16_t length,
static void register_mgmt_handlers(void)
{
- mgmt_register(adapter->mgmt, MGMT_EV_NEW_SETTINGS, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_NEW_SETTINGS, adapter_index,
new_settings_callback, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_CLASS_OF_DEV_CHANGED,
- adapter->index, mgmt_dev_class_changed_event,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_CLASS_OF_DEV_CHANGED, adapter_index,
+ mgmt_dev_class_changed_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_LOCAL_NAME_CHANGED,
- adapter->index, mgmt_local_name_changed_event,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_LOCAL_NAME_CHANGED, adapter_index,
+ mgmt_local_name_changed_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_NEW_LINK_KEY, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_NEW_LINK_KEY, adapter_index,
new_link_key_callback, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_PIN_CODE_REQUEST, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_PIN_CODE_REQUEST, adapter_index,
pin_code_request_callback, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_USER_CONFIRM_REQUEST,
- adapter->index, user_confirm_request_callback,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_USER_CONFIRM_REQUEST, adapter_index,
+ user_confirm_request_callback, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_USER_PASSKEY_REQUEST,
- adapter->index, user_passkey_request_callback,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_USER_PASSKEY_REQUEST, adapter_index,
+ user_passkey_request_callback, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_PASSKEY_NOTIFY, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_PASSKEY_NOTIFY, adapter_index,
user_passkey_notify_callback, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_DISCOVERING, adapter->index,
- mgmt_discovering_event,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_DISCOVERING, adapter_index,
+ mgmt_discovering_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_DEVICE_FOUND,
- adapter->index, mgmt_device_found_event,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_DEVICE_FOUND, adapter_index,
+ mgmt_device_found_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_DEVICE_CONNECTED, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_DEVICE_CONNECTED, adapter_index,
mgmt_device_connected_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_DEVICE_DISCONNECTED,
- adapter->index, mgmt_device_disconnected_event,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_DEVICE_DISCONNECTED, adapter_index,
+ mgmt_device_disconnected_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_CONNECT_FAILED, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_CONNECT_FAILED, adapter_index,
mgmt_connect_failed_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_AUTH_FAILED, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_AUTH_FAILED, adapter_index,
mgmt_auth_failed_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_DEVICE_UNPAIRED, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_DEVICE_UNPAIRED, adapter_index,
mgmt_device_unpaired_event, NULL, NULL);
}
@@ -936,18 +921,18 @@ static void load_link_keys_complete(uint8_t status, uint16_t length,
if (status) {
error("Failed to load link keys for index %u: %s (0x%02x)",
- adapter->index, mgmt_errstr(status), status);
+ adapter_index, mgmt_errstr(status), status);
err = -EIO;
goto failed;
}
DBG("status %u", status);
- adapter->ready(0);
+ adapter_ready(0);
return;
failed:
- adapter->ready(err);
+ adapter_ready(err);
}
static void load_link_keys(GSList *keys)
@@ -975,14 +960,14 @@ static void load_link_keys(GSList *keys)
for (key = cp->keys; keys != NULL; keys = g_slist_next(keys), key++)
memcpy(key, keys->data, sizeof(*key));
- id = mgmt_send(adapter->mgmt, MGMT_OP_LOAD_LINK_KEYS, adapter->index,
+ id = mgmt_send(mgmt_if, MGMT_OP_LOAD_LINK_KEYS, adapter_index,
cp_size, cp, load_link_keys_complete, NULL, NULL);
g_free(cp);
if (id == 0) {
error("Failed to load link keys");
- adapter->ready(-EIO);
+ adapter_ready(-EIO);
}
}
@@ -1000,7 +985,7 @@ static void set_mode_complete(uint8_t status, uint16_t length,
* required in both cases. So it is safe to just call the
* event handling functions here.
*/
- new_settings_callback(adapter->index, length, param, NULL);
+ new_settings_callback(adapter_index, length, param, NULL);
}
static bool set_mode(uint16_t opcode, uint8_t mode)
@@ -1012,7 +997,7 @@ static bool set_mode(uint16_t opcode, uint8_t mode)
DBG("opcode=0x%x mode=0x%x", opcode, mode);
- if (mgmt_send(adapter->mgmt, opcode, adapter->index, sizeof(cp), &cp,
+ if (mgmt_send(mgmt_if, opcode, adapter_index, sizeof(cp), &cp,
set_mode_complete, NULL, NULL) > 0)
return true;
@@ -1028,9 +1013,8 @@ static void set_io_capability(void)
memset(&cp, 0, sizeof(cp));
cp.io_capability = DEFAULT_IO_CAPABILITY;
- if (mgmt_send(adapter->mgmt, MGMT_OP_SET_IO_CAPABILITY,
- adapter->index, sizeof(cp), &cp,
- NULL, NULL, NULL) == 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_SET_IO_CAPABILITY, adapter_index,
+ sizeof(cp), &cp, NULL, NULL, NULL) == 0)
error("Failed to set IO capability");
}
@@ -1048,9 +1032,8 @@ static void set_device_id(void)
cp.product = htobs(0x0247); /* BlueZ for Android */
cp.version = htobs(major << 8 | minor);
- if (mgmt_send(adapter->mgmt, MGMT_OP_SET_DEVICE_ID,
- adapter->index, sizeof(cp), &cp,
- NULL, NULL, NULL) == 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_SET_DEVICE_ID, adapter_index,
+ sizeof(cp), &cp, NULL, NULL, NULL) == 0)
error("Failed to set device id");
}
@@ -1075,9 +1058,9 @@ static uint8_t set_adapter_name(uint8_t *name, uint16_t len)
memset(&cp, 0, sizeof(cp));
memcpy(cp.name, name, len);
- if (mgmt_send(adapter->mgmt, MGMT_OP_SET_LOCAL_NAME, adapter->index,
- sizeof(cp), &cp, set_adapter_name_complete, NULL,
- NULL) > 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_SET_LOCAL_NAME, adapter_index,
+ sizeof(cp), &cp, set_adapter_name_complete,
+ NULL, NULL) > 0)
return HAL_STATUS_SUCCESS;
error("Failed to set name");
@@ -1092,7 +1075,7 @@ static uint8_t set_discoverable_timeout(uint8_t *timeout)
* Just need to store this value here */
/* TODO: This should be in some storage */
- memcpy(&adapter->discoverable_timeout, timeout, sizeof(uint32_t));
+ memcpy(&adapter_discoverable_timeout, timeout, sizeof(uint32_t));
return HAL_STATUS_SUCCESS;
}
@@ -1100,14 +1083,14 @@ static void read_info_complete(uint8_t status, uint16_t length, const void *para
void *user_data)
{
const struct mgmt_rp_read_info *rp = param;
- uint32_t missing_settings;
+ uint32_t missing_settings, supported_settings;
int err;
DBG("");
if (status) {
error("Failed to read info for index %u: %s (0x%02x)",
- adapter->index, mgmt_errstr(status), status);
+ adapter_index, mgmt_errstr(status), status);
err = -EIO;
goto failed;
}
@@ -1125,13 +1108,15 @@ static void read_info_complete(uint8_t status, uint16_t length, const void *para
}
/* Store adapter information */
- bacpy(&adapter->bdaddr, &rp->bdaddr);
- adapter->dev_class = rp->dev_class[0] | (rp->dev_class[1] << 8) |
+ bacpy(&adapter_bdaddr, &rp->bdaddr);
+ adapter_dev_class = rp->dev_class[0] | (rp->dev_class[1] << 8) |
(rp->dev_class[2] << 16);
- adapter->name = g_strdup((const char *) rp->name);
+ adapter_name = g_strdup((const char *) rp->name);
- adapter->supported_settings = btohs(rp->supported_settings);
- adapter->current_settings = btohs(rp->current_settings);
+ supported_settings = btohs(rp->supported_settings);
+ current_settings = btohs(rp->current_settings);
+
+ /* TODO: Read discoverable timeout from storage here */
/* TODO: Register all event notification handlers */
register_mgmt_handlers();
@@ -1141,8 +1126,7 @@ static void read_info_complete(uint8_t status, uint16_t length, const void *para
set_io_capability();
set_device_id();
- missing_settings = adapter->current_settings ^
- adapter->supported_settings;
+ missing_settings = current_settings ^ supported_settings;
if (missing_settings & MGMT_SETTING_SSP)
set_mode(MGMT_OP_SET_SSP, 0x01);
@@ -1153,26 +1137,21 @@ static void read_info_complete(uint8_t status, uint16_t length, const void *para
return;
failed:
- adapter->ready(err);
+ adapter_ready(err);
}
void bt_adapter_init(uint16_t index, struct mgmt *mgmt, bt_adapter_ready cb)
{
- adapter = g_new0(struct bt_adapter, 1);
-
- adapter->mgmt = mgmt_ref(mgmt);
- adapter->index = index;
- adapter->discovering = false;
- adapter->ready = cb;
- /* TODO: Read it from some storage */
- adapter->discoverable_timeout = DEFAULT_DISCOVERABLE_TIMEOUT;
+ mgmt_if = mgmt_ref(mgmt);
+ adapter_index = index;
+ adapter_ready = cb;
if (mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
read_info_complete, NULL, NULL) > 0)
return;
- mgmt_unref(adapter->mgmt);
- adapter->ready(-EIO);
+ mgmt_unref(mgmt_if);
+ adapter_ready(-EIO);
}
static bool set_discoverable(uint8_t mode, uint16_t timeout)
@@ -1185,9 +1164,8 @@ static bool set_discoverable(uint8_t mode, uint16_t timeout)
DBG("mode %u timeout %u", mode, timeout);
- if (mgmt_send(adapter->mgmt, MGMT_OP_SET_DISCOVERABLE,
- adapter->index, sizeof(cp), &cp,
- set_mode_complete, adapter, NULL) > 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_SET_DISCOVERABLE, adapter_index,
+ sizeof(cp), &cp, set_mode_complete, NULL, NULL) > 0)
return true;
error("Failed to set mode discoverable");
@@ -1205,7 +1183,7 @@ static void get_address(void)
ev->props[0].type = HAL_PROP_ADAPTER_ADDR;
ev->props[0].len = sizeof(bdaddr_t);
- bdaddr2android(&adapter->bdaddr, ev->props[0].val);
+ bdaddr2android(&adapter_bdaddr, ev->props[0].val);
ipc_send(notification_sk, HAL_SERVICE_ID_BLUETOOTH,
HAL_EV_ADAPTER_PROPS_CHANGED, sizeof(buf), buf, -1);
@@ -1213,10 +1191,10 @@ static void get_address(void)
static bool get_name(void)
{
- if (!adapter->name)
+ if (!adapter_name)
return false;
- adapter_name_changed((uint8_t *) adapter->name);
+ adapter_name_changed((uint8_t *) adapter_name);
return true;
}
@@ -1288,7 +1266,7 @@ static bool get_discoverable_timeout(void)
ev->props[0].type = HAL_PROP_ADAPTER_DISC_TIMEOUT;
ev->props[0].len = sizeof(uint32_t);
- memcpy(&ev->props[0].val, &adapter->discoverable_timeout,
+ memcpy(&ev->props[0].val, &adapter_discoverable_timeout,
sizeof(uint32_t));
ipc_send(notification_sk, HAL_SERVICE_ID_BLUETOOTH,
@@ -1344,15 +1322,15 @@ static bool start_discovery(void)
struct mgmt_cp_start_discovery cp;
uint8_t type = 1 << BDADDR_BREDR;
- if (adapter->current_settings & type)
+ if (current_settings & type)
cp.type = type;
else
cp.type = 0;
DBG("type=0x%x", type);
- if (mgmt_send(adapter->mgmt, MGMT_OP_START_DISCOVERY, adapter->index,
- sizeof(cp), &cp, NULL, NULL, NULL) > 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_START_DISCOVERY, adapter_index,
+ sizeof(cp), &cp, NULL, NULL, NULL) > 0)
return true;
error("Failed to start discovery");
@@ -1364,15 +1342,15 @@ static bool stop_discovery(void)
struct mgmt_cp_stop_discovery cp;
uint8_t type = 1 << BDADDR_BREDR;
- if (adapter->current_settings & type)
+ if (current_settings & type)
cp.type = type;
else
cp.type = 0;
DBG("type=0x%x", type);
- if (mgmt_send(adapter->mgmt, MGMT_OP_STOP_DISCOVERY, adapter->index,
- sizeof(cp), &cp, NULL, NULL, NULL) > 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_STOP_DISCOVERY, adapter_index,
+ sizeof(cp), &cp, NULL, NULL, NULL) > 0)
return true;
error("Failed to start discovery");
@@ -1384,8 +1362,8 @@ static uint8_t set_scan_mode(void *buf, uint16_t len)
uint8_t *mode = buf;
bool conn, disc, cur_conn, cur_disc;
- cur_conn = adapter->current_settings & MGMT_SETTING_CONNECTABLE;
- cur_disc = adapter->current_settings & MGMT_SETTING_DISCOVERABLE;
+ cur_conn = current_settings & MGMT_SETTING_CONNECTABLE;
+ cur_disc = current_settings & MGMT_SETTING_DISCOVERABLE;
DBG("connectable %u discoverable %d mode %u", cur_conn, cur_disc,
*mode);
@@ -1499,9 +1477,8 @@ static bool create_bond(void *buf, uint16_t len)
cp.addr.type = BDADDR_BREDR;
android2bdaddr(cmd->bdaddr, &cp.addr.bdaddr);
- if (mgmt_send(adapter->mgmt, MGMT_OP_PAIR_DEVICE, adapter->index,
- sizeof(cp), &cp, pair_device_complete, NULL,
- NULL) == 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_PAIR_DEVICE, adapter_index, sizeof(cp),
+ &cp, pair_device_complete, NULL, NULL) == 0)
return false;
send_bond_state_change(&cp.addr.bdaddr, HAL_STATUS_SUCCESS,
@@ -1518,9 +1495,8 @@ static bool cancel_bond(void *buf, uint16_t len)
cp.type = BDADDR_BREDR;
android2bdaddr(cmd->bdaddr, &cp.bdaddr);
- return mgmt_reply(adapter->mgmt, MGMT_OP_CANCEL_PAIR_DEVICE,
- adapter->index, sizeof(cp), &cp, NULL, NULL,
- NULL) > 0;
+ return mgmt_reply(mgmt_if, MGMT_OP_CANCEL_PAIR_DEVICE, adapter_index,
+ sizeof(cp), &cp, NULL, NULL, NULL) > 0;
}
static void unpair_device_complete(uint8_t status, uint16_t length,
@@ -1546,9 +1522,9 @@ static bool remove_bond(void *buf, uint16_t len)
cp.addr.type = BDADDR_BREDR;
android2bdaddr(cmd->bdaddr, &cp.addr.bdaddr);
- return mgmt_send(adapter->mgmt, MGMT_OP_UNPAIR_DEVICE,
- adapter->index, sizeof(cp), &cp,
- unpair_device_complete, NULL, NULL) > 0;
+ return mgmt_send(mgmt_if, MGMT_OP_UNPAIR_DEVICE, adapter_index,
+ sizeof(cp), &cp, unpair_device_complete,
+ NULL, NULL) > 0;
}
static uint8_t pin_reply(void *buf, uint16_t len)
@@ -1575,9 +1551,8 @@ static uint8_t pin_reply(void *buf, uint16_t len)
rp.pin_len = cmd->pin_len;
memcpy(rp.pin_code, cmd->pin_code, rp.pin_len);
- if (mgmt_reply(adapter->mgmt, MGMT_OP_PIN_CODE_REPLY,
- adapter->index, sizeof(rp), &rp,
- NULL, NULL, NULL) == 0)
+ if (mgmt_reply(mgmt_if, MGMT_OP_PIN_CODE_REPLY, adapter_index,
+ sizeof(rp), &rp, NULL, NULL, NULL) == 0)
return HAL_STATUS_FAILED;
} else {
struct mgmt_cp_pin_code_neg_reply rp;
@@ -1585,9 +1560,9 @@ static uint8_t pin_reply(void *buf, uint16_t len)
bacpy(&rp.addr.bdaddr, &bdaddr);
rp.addr.type = BDADDR_BREDR;
- if (mgmt_reply(adapter->mgmt, MGMT_OP_PIN_CODE_NEG_REPLY,
- adapter->index, sizeof(rp), &rp,
- NULL, NULL, NULL) == 0)
+ if (mgmt_reply(mgmt_if, MGMT_OP_PIN_CODE_NEG_REPLY,
+ adapter_index, sizeof(rp), &rp,
+ NULL, NULL, NULL) == 0)
return HAL_STATUS_FAILED;
}
@@ -1607,7 +1582,7 @@ static uint8_t user_confirm_reply(const bdaddr_t *bdaddr, bool accept)
bacpy(&cp.bdaddr, bdaddr);
cp.type = BDADDR_BREDR;
- if (mgmt_reply(adapter->mgmt, opcode, adapter->index, sizeof(cp), &cp,
+ if (mgmt_reply(mgmt_if, opcode, adapter_index, sizeof(cp), &cp,
NULL, NULL, NULL) > 0)
return HAL_STATUS_SUCCESS;
@@ -1627,9 +1602,9 @@ static uint8_t user_passkey_reply(const bdaddr_t *bdaddr, bool accept,
cp.addr.type = BDADDR_BREDR;
cp.passkey = htobl(passkey);
- id = mgmt_reply(adapter->mgmt, MGMT_OP_USER_PASSKEY_REPLY,
- adapter->index, sizeof(cp), &cp,
- NULL, NULL, NULL);
+ id = mgmt_reply(mgmt_if, MGMT_OP_USER_PASSKEY_REPLY,
+ adapter_index, sizeof(cp), &cp,
+ NULL, NULL, NULL);
} else {
struct mgmt_cp_user_passkey_neg_reply cp;
@@ -1637,9 +1612,9 @@ static uint8_t user_passkey_reply(const bdaddr_t *bdaddr, bool accept,
bacpy(&cp.addr.bdaddr, bdaddr);
cp.addr.type = BDADDR_BREDR;
- id = mgmt_reply(adapter->mgmt, MGMT_OP_USER_PASSKEY_NEG_REPLY,
- adapter->index, sizeof(cp), &cp,
- NULL, NULL, NULL);
+ id = mgmt_reply(mgmt_if, MGMT_OP_USER_PASSKEY_NEG_REPLY,
+ adapter_index, sizeof(cp), &cp,
+ NULL, NULL, NULL);
}
if (id == 0)
@@ -1702,7 +1677,7 @@ void bt_adapter_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
* enabling adapter */
get_properties();
- if (adapter->current_settings & MGMT_SETTING_POWERED) {
+ if (current_settings & MGMT_SETTING_POWERED) {
status = HAL_STATUS_DONE;
goto error;
}
@@ -1712,7 +1687,7 @@ void bt_adapter_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
break;
case HAL_OP_DISABLE:
- if (!(adapter->current_settings & MGMT_SETTING_POWERED)) {
+ if (!(current_settings & MGMT_SETTING_POWERED)) {
status = HAL_STATUS_DONE;
goto error;
}
@@ -1763,12 +1738,12 @@ void bt_adapter_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
goto error;
break;
case HAL_OP_START_DISCOVERY:
- if (adapter->discovering) {
+ if (adapter_discovering) {
status = HAL_STATUS_DONE;
goto error;
}
- if (!(adapter->current_settings & MGMT_SETTING_POWERED)) {
+ if (!(current_settings & MGMT_SETTING_POWERED)) {
status = HAL_STATUS_NOT_READY;
goto error;
}
@@ -1778,12 +1753,12 @@ void bt_adapter_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
break;
case HAL_OP_CANCEL_DISCOVERY:
- if (!adapter->discovering) {
+ if (!adapter_discovering) {
status = HAL_STATUS_DONE;
goto error;
}
- if (!(adapter->current_settings & MGMT_SETTING_POWERED)) {
+ if (!(current_settings & MGMT_SETTING_POWERED)) {
status = HAL_STATUS_NOT_READY;
goto error;
}
@@ -1813,7 +1788,7 @@ error:
const bdaddr_t *bt_adapter_get_address(void)
{
- return &adapter->bdaddr;
+ return &adapter_bdaddr;
}
bool bt_adapter_register(int sk)
--
1.8.4.2
^ permalink raw reply related
* [PATCH 0/7] android: Some adapter and mgmt handling code cleanup
From: Szymon Janc @ 2013-11-12 0:24 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
Hi,
This patchset moves mgmt initalization handling from main.c to adapter.c so
now all mgmt handling is done from adaper.c. Adapter.c is also renamed to
bluetooth.c to match service name implemented by it.
Startup and shutdown timeouts are still handled in main.c (mostly due to
both resulting in mainloop shutdown so extra callback are avoided).
IO handling and commands dispatch is still done in main.c
--
BR
Szymon Janc
Szymon Janc (7):
android: Remove bt_adapter structure
android: Move adapter initialization to adapter.c
android/hidhost: Use adapter address provided on register
android: Report adapter address in adapter_ready callback
android: Remove not needed bt_adapter_get_address function
android: Rename adapter.c to bluetooth.c
android: Rename bluetooth service functions to match service name
android/Android.mk | 2 +-
android/Makefile.am | 4 +-
android/adapter.c | 1833 -----------------------------------------------
android/adapter.h | 34 -
android/bluetooth.c | 1985 +++++++++++++++++++++++++++++++++++++++++++++++++++
android/bluetooth.h | 35 +
android/hidhost.c | 21 +-
android/main.c | 314 ++------
8 files changed, 2092 insertions(+), 2136 deletions(-)
delete mode 100644 android/adapter.c
delete mode 100644 android/adapter.h
create mode 100644 android/bluetooth.c
create mode 100644 android/bluetooth.h
--
1.8.4.2
^ permalink raw reply
* Re: [PATCH 1/3] android: Update bond state on incoming bonding
From: Marcel Holtmann @ 2013-11-11 23:19 UTC (permalink / raw)
To: Lukasz Rymanowski
Cc: Lukasz Rymanowski, linux-bluetooth@vger.kernel.org development,
Szymon Janc
In-Reply-To: <CAN_7+Yb9smK8U+UeK8P-3YcBR0pC8spgsnVkw4f86jMO67A+FA@mail.gmail.com>
Hi Lukasz,
>>> Before sending any ssp request or pin code request up to HAL library we
>>> need to send bond state change with bonding state. Otherwise incoming
>>> bonding is impossible.
>>> ---
>>> android/adapter.c | 21 ++++++++++++++++++---
>>> 1 file changed, 18 insertions(+), 3 deletions(-)
>>
>> Wont this cause HAL_BOND_STATE_BONDING to be sent twice if the pairing
>> was locally initiated through create_bond()?
>
> Well, of course we could try to keep track our local bond state and
> send HAL_BOND_STATE_BONDING in smarter way, but we don't need to. It
> is not a problem for Android to handle HAL_BOND_STATE_BONDING twice.
> Actually It works like this even now with current BT stack.
> And of course we need to send this event up as soon as we start
> bonding procedure, so it should stay in create_bond().
I think we should keep track of our bond state internally. I get the feeling we will need that eventually anyway. For example we already know that we need to keep a mapping of BD_ADDR to address types to make LE work.
Regards
Marcel
^ permalink raw reply
* Re: pull request: bluetooth 2013-11-11
From: Marcel Holtmann @ 2013-11-11 23:17 UTC (permalink / raw)
To: Gustavo F. Padovan
Cc: John W. Linville, linux-wireless@vger.kernel.org Wireless,
linux-bluetooth@vger.kernel.org development,
linux-kernel@vger.kernel.org list
In-Reply-To: <20131111182738.GB5648@joana>
Hi Gustavo,
> A few fixes for 3.13. There is 3 fixes to the RFCOMM protocol. One crash fix to
> L2CAP. A simple fix to a bad behaviour in the SMP protocol, and last, an
> revert, that I sent in the last pull request but doesn't seem to be in your
> tree.
>
> Please pull or let me know of any issues. Thanks!
>
>
> Gustavo
>
> ---
> The following changes since commit 8ce9beac4661f576ea0d518b9f086bb52a171a37:
>
> drivers: net: wireless: b43: Fix possible NULL ptr dereference (2013-10-18 13:41:11 -0400)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth master
>
> for you to fetch changes up to 3244d4a55c95708b0fa6fd820a9009534ed08a5f:
>
> Bluetooth: Fix rejecting SMP security request in slave role (2013-11-11 15:48:36 -0200)
>
> ----------------------------------------------------------------
> Hans de Goede (1):
> Bluetooth: revert: "Bluetooth: Add missing reset_resume dev_pm_ops”
this one is already in net-next actually. John pushed bluetooth and bluetooth-next to Dave at the same time.
> Johan Hedberg (1):
> Bluetooth: Fix rejecting SMP security request in slave role
>
> Marcel Holtmann (1):
> Bluetooth: Fix issue with RFCOMM getsockopt operation
>
> Seung-Woo Kim (3):
> Bluetooth: Fix RFCOMM bind fail for L2CAP sock
> Bluetooth: Fix to set proper bdaddr_type for RFCOMM connect
> Bluetooth: Fix crash in l2cap_chan_send after l2cap_chan_del
These 5 fixes are still needed.
Regards
Marcel
^ permalink raw reply
* Re: [RFCv1 7/9] android/hal-sock: Implement RFCOMM events
From: Marcel Holtmann @ 2013-11-11 23:11 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1384173438-21708-8-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
> Copy data from RFCOMM socket to Android framework.
> ---
> android/socket.c | 29 +++++++++++++++++++++++++++++
> 1 file changed, 29 insertions(+)
>
> diff --git a/android/socket.c b/android/socket.c
> index dfad9da..a962cdc 100644
> --- a/android/socket.c
> +++ b/android/socket.c
> @@ -129,6 +129,35 @@ static gboolean sock_stack_event_cb(GIOChannel *io, GIOCondition cond,
> static gboolean sock_rfcomm_event_cb(GIOChannel *io, GIOCondition cond,
> gpointer data)
> {
> + struct rfcomm_slot *rfslot = data;
> + unsigned char buf[1024] = { 0 };
> + int len;
> +
> + DBG("rfslot: fd %d hal_fd %d real_sock %d chan %u sock %d",
> + rfslot->fd, rfslot->hal_fd, rfslot->real_sock, rfslot->channel,
> + g_io_channel_unix_get_fd(io));
> +
> + if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
> + error("Socket error: sock %d cond %d",
> + g_io_channel_unix_get_fd(io), cond);
> + g_io_channel_shutdown(io, TRUE, NULL);
> + return FALSE;
> + }
> +
> + /* FIXME check real_sock vs sock(io) */
> + len = recv(rfslot->real_sock, buf, sizeof(buf), 0);
> + if (len <= 0) {
> + error("recv(): %s sock %d", strerror(errno), rfslot->real_sock);
> + return FALSE;
> + }
> +
> + DBG("read %d bytes, write to fd %d", len, rfslot->fd);
> +
> + if (send(rfslot->fd, buf, len, MSG_DONTWAIT) < 0) {
> + error("send(): %s sock %d", strerror(errno), rfslot->fd);
> + return FALSE;
> + }
> +
since both sockets are SOCK_STREAM there is no guarantee that write() will write exactly the same amount of data that you just got via read(). Especially when using MSG_DONTWAIT. The kernel can decide to interrupt you here any time it wants to.
So you need proper error handling for the send() part in case you get truncated transfers.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH 2/3] android/hidhost: Remove deprecated idle opcode from ipc document
From: Marcel Holtmann @ 2013-11-11 23:05 UTC (permalink / raw)
To: Ravi kumar Veeramally; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1384172130-29837-2-git-send-email-ravikumar.veeramally@linux.intel.com>
Hi Ravi,
> Idle time is deprecated in HID 1_1. So remove it from ipc document
> and update GET_REPORT and VIRTUAL_UNPLUG opcode values.
> ---
> android/hal-ipc-api.txt | 10 ++--------
> android/hal-msg.h | 4 ++--
> 2 files changed, 4 insertions(+), 10 deletions(-)
>
> diff --git a/android/hal-ipc-api.txt b/android/hal-ipc-api.txt
> index 91ea280..57f4c13 100644
> --- a/android/hal-ipc-api.txt
> +++ b/android/hal-ipc-api.txt
> @@ -614,20 +614,14 @@ Notifications:
> 0x01 = Boot
> 0xff = Unsupported
>
> - Opcode 0x84 - Idle Time notification
> -
> - Notification parameters: Remote address (6 octets)
> - Status (1 octet)
> - Idle time (2 octets)
so what does HID_1.1 actually mean? I still see this notification in bt_hh.h.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH 1/3] android: Update bond state on incoming bonding
From: Lukasz Rymanowski @ 2013-11-11 22:23 UTC (permalink / raw)
To: Lukasz Rymanowski, linux-bluetooth, Szymon Janc
In-Reply-To: <20131111083735.GA4541@x220.p-661hnu-f1>
Hi Johan,
On Mon, Nov 11, 2013 at 9:37 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi Lukasz,
>
> On Fri, Nov 08, 2013, Lukasz Rymanowski wrote:
>> Before sending any ssp request or pin code request up to HAL library we
>> need to send bond state change with bonding state. Otherwise incoming
>> bonding is impossible.
>> ---
>> android/adapter.c | 21 ++++++++++++++++++---
>> 1 file changed, 18 insertions(+), 3 deletions(-)
>
> Wont this cause HAL_BOND_STATE_BONDING to be sent twice if the pairing
> was locally initiated through create_bond()?
Well, of course we could try to keep track our local bond state and
send HAL_BOND_STATE_BONDING in smarter way, but we don't need to. It
is not a problem for Android to handle HAL_BOND_STATE_BONDING twice.
Actually It works like this even now with current BT stack.
And of course we need to send this event up as soon as we start
bonding procedure, so it should stay in create_bond().
>
> Johan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
\Łukasz
^ permalink raw reply
* Re: pull request: bluetooth 2013-11-11
From: John W. Linville @ 2013-11-11 19:05 UTC (permalink / raw)
To: Gustavo Padovan, linux-wireless, linux-bluetooth, linux-kernel
In-Reply-To: <20131111182738.GB5648@joana>
On Mon, Nov 11, 2013 at 04:27:38PM -0200, Gustavo Padovan wrote:
> Hi John,
>
> A few fixes for 3.13. There is 3 fixes to the RFCOMM protocol. One crash fix to
> L2CAP. A simple fix to a bad behaviour in the SMP protocol, and last, an
> revert, that I sent in the last pull request but doesn't seem to be in your
> tree.
Are you looking in the wireless-next tree? It seems to be there, no?
John
>
> Please pull or let me know of any issues. Thanks!
>
>
> Gustavo
>
> ---
> The following changes since commit 8ce9beac4661f576ea0d518b9f086bb52a171a37:
>
> drivers: net: wireless: b43: Fix possible NULL ptr dereference (2013-10-18 13:41:11 -0400)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth master
>
> for you to fetch changes up to 3244d4a55c95708b0fa6fd820a9009534ed08a5f:
>
> Bluetooth: Fix rejecting SMP security request in slave role (2013-11-11 15:48:36 -0200)
>
> ----------------------------------------------------------------
> Hans de Goede (1):
> Bluetooth: revert: "Bluetooth: Add missing reset_resume dev_pm_ops"
>
> Johan Hedberg (1):
> Bluetooth: Fix rejecting SMP security request in slave role
>
> Marcel Holtmann (1):
> Bluetooth: Fix issue with RFCOMM getsockopt operation
>
> Seung-Woo Kim (3):
> Bluetooth: Fix RFCOMM bind fail for L2CAP sock
> Bluetooth: Fix to set proper bdaddr_type for RFCOMM connect
> Bluetooth: Fix crash in l2cap_chan_send after l2cap_chan_del
>
> drivers/bluetooth/btusb.c | 1 -
> net/bluetooth/l2cap_core.c | 3 +++
> net/bluetooth/rfcomm/core.c | 3 +++
> net/bluetooth/rfcomm/sock.c | 6 +++++-
> net/bluetooth/smp.c | 3 +++
> 5 files changed, 14 insertions(+), 2 deletions(-)
>
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply
* Re: [RFC BlueZ v1] doc: Add GATT API
From: Scott James Remnant @ 2013-11-11 18:56 UTC (permalink / raw)
To: Claudio Takahasi; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1381862383-9866-1-git-send-email-claudio.takahasi@openbossa.org>
On Tue, Oct 15, 2013 at 11:39 AM, Claudio Takahasi
<claudio.takahasi@openbossa.org> wrote:
> +GATT local and remote services share the same high-level D-Bus API. Local
> +refers to local GATT based service exported by a BlueZ plugin or an external
> +application. Remote refers to GATT services exported by the peer.
If this object format also be used to describe the services and
characteristics of a remote device, how will those be handled? I
assume that we don't want to get the value of every single
characteristic on connection - that seems wasteful, and would quite
rapidly drain the batteries of smaller devices.
How will service changed be handled? How will BlueZ track the set of
applications, and the set of services etc. defined by those
applications in a manner that keeps handles consistent? How will it
handle generating the Services Changed notification in the cases where
the set of applications and/or services change, or the handles change?
> +Characteristic hierarchy
> +========================
:
> +Service org.bluez
> +Interface org.bluez.Characteristic1 [Experimental]
> +Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
This would also need a "Permissions" property akin to the one you have
for Descriptors - characteristics can be "not accessible", read-only,
write-only, read/write - and can also require authorization,
authentication, encryption and minimum encryption key sizes - as with
descriptors.
> + array{byte} Value [read-write]
> +
> + Cached Value of the characteristic. If present, the
> + value will be cached by bluetoothd and updated when the
> + PropertiesChanged signal is emitted.
> +
> + External services must emit this signal when the
> + characteristic supports notification/indication, so
> + that clients can be notified of the new value.
The PropertiesChanged signal explains how Notification will be handled
- but how will Indication? How will a service receive the Indication
Confirmation from the remote devices?
> +Application Manager hierarchy
> +=============================
:
> +Service org.bluez
> +Interface org.bluez.ApplicationManager1 [Experimental]
> +Object path /org/bluez
> +
> +Methods RegisterAgent(object application, dict options)
Shouldn't this be "RegisterApplication" ?
I assume that the object path is the one to which D-Bus Object Manager
queries are sent, allowing a single process to implement multiple
"applications"?
> + UnregisterAgent(object application)
Likewise, "UnregisterApplication" ?
> +Application Agent hierarchy
> +===========================
> +
> +Service unique name
> +Interface org.bluez.ApplicationAgent1 [Experimental]
> +Object path freely definable
> +
"Agent" seems unnnecessary here - if the object is an Application,
then org.bluez.Application1 would be a decent enough name. Thus an
"Application" consists of multiple Services, each of which consists of
multiple Characteristics, each of which has multiple Descriptors
Scott
--
Scott James Remnant | Chrome OS Systems | keybuk@google.com | Google
^ permalink raw reply
* pull request: bluetooth 2013-11-11
From: Gustavo Padovan @ 2013-11-11 18:27 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, linux-bluetooth, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1537 bytes --]
Hi John,
A few fixes for 3.13. There is 3 fixes to the RFCOMM protocol. One crash fix to
L2CAP. A simple fix to a bad behaviour in the SMP protocol, and last, an
revert, that I sent in the last pull request but doesn't seem to be in your
tree.
Please pull or let me know of any issues. Thanks!
Gustavo
---
The following changes since commit 8ce9beac4661f576ea0d518b9f086bb52a171a37:
drivers: net: wireless: b43: Fix possible NULL ptr dereference (2013-10-18 13:41:11 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth master
for you to fetch changes up to 3244d4a55c95708b0fa6fd820a9009534ed08a5f:
Bluetooth: Fix rejecting SMP security request in slave role (2013-11-11 15:48:36 -0200)
----------------------------------------------------------------
Hans de Goede (1):
Bluetooth: revert: "Bluetooth: Add missing reset_resume dev_pm_ops"
Johan Hedberg (1):
Bluetooth: Fix rejecting SMP security request in slave role
Marcel Holtmann (1):
Bluetooth: Fix issue with RFCOMM getsockopt operation
Seung-Woo Kim (3):
Bluetooth: Fix RFCOMM bind fail for L2CAP sock
Bluetooth: Fix to set proper bdaddr_type for RFCOMM connect
Bluetooth: Fix crash in l2cap_chan_send after l2cap_chan_del
drivers/bluetooth/btusb.c | 1 -
net/bluetooth/l2cap_core.c | 3 +++
net/bluetooth/rfcomm/core.c | 3 +++
net/bluetooth/rfcomm/sock.c | 6 +++++-
net/bluetooth/smp.c | 3 +++
5 files changed, 14 insertions(+), 2 deletions(-)
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH BlueZ v2] audio/AVDTP: Remove avdtp_init and avdtp_exit
From: Johan Hedberg @ 2013-11-11 16:50 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1384186675-14940-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Mon, Nov 11, 2013, Luiz Augusto von Dentz wrote:
> This is now done on demand by avdtp_register_sep and avdtp_unregister_sep
> so the server socket is only registered when there is an endpoint
> available and the record is properly registered.
> ---
> v2: Fix return of avdtp_server_init
>
> profiles/audio/a2dp.c | 11 -----
> profiles/audio/avdtp.c | 118 +++++++++++++++++++++++++------------------------
> profiles/audio/avdtp.h | 3 --
> 3 files changed, 60 insertions(+), 72 deletions(-)
Applied. Thanks.
Johan
^ permalink raw reply
* [PATCH BlueZ v2] audio/AVDTP: Remove avdtp_init and avdtp_exit
From: Luiz Augusto von Dentz @ 2013-11-11 16:17 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This is now done on demand by avdtp_register_sep and avdtp_unregister_sep
so the server socket is only registered when there is an endpoint
available and the record is properly registered.
---
v2: Fix return of avdtp_server_init
profiles/audio/a2dp.c | 11 -----
profiles/audio/avdtp.c | 118 +++++++++++++++++++++++++------------------------
profiles/audio/avdtp.h | 3 --
3 files changed, 60 insertions(+), 72 deletions(-)
diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index 8477b5d..6b3d6b2 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -1187,17 +1187,8 @@ static struct a2dp_server *find_server(GSList *list, struct btd_adapter *a)
static struct a2dp_server *a2dp_server_register(struct btd_adapter *adapter)
{
struct a2dp_server *server;
- int av_err;
server = g_new0(struct a2dp_server, 1);
-
- av_err = avdtp_init(adapter);
- if (av_err < 0) {
- DBG("AVDTP not registered");
- g_free(server);
- return NULL;
- }
-
server->adapter = btd_adapter_ref(adapter);
servers = g_slist_append(servers, server);
@@ -1217,8 +1208,6 @@ static void a2dp_unregister_sep(struct a2dp_sep *sep)
static void a2dp_server_unregister(struct a2dp_server *server)
{
- avdtp_exit(server->adapter);
-
servers = g_slist_remove(servers, server);
btd_adapter_unref(server->adapter);
g_free(server);
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index dab8f1c..9378350 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -3683,6 +3683,45 @@ int avdtp_delay_report(struct avdtp *session, struct avdtp_stream *stream,
&req, sizeof(req));
}
+static GIOChannel *avdtp_server_socket(const bdaddr_t *src, gboolean master)
+{
+ GError *err = NULL;
+ GIOChannel *io;
+
+ io = bt_io_listen(NULL, avdtp_confirm_cb,
+ NULL, NULL, &err,
+ BT_IO_OPT_SOURCE_BDADDR, src,
+ BT_IO_OPT_PSM, AVDTP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_MASTER, master,
+ BT_IO_OPT_INVALID);
+ if (!io) {
+ error("%s", err->message);
+ g_error_free(err);
+ }
+
+ return io;
+}
+
+static struct avdtp_server *avdtp_server_init(struct btd_adapter *adapter)
+{
+ struct avdtp_server *server;
+
+ server = g_new0(struct avdtp_server, 1);
+
+ server->io = avdtp_server_socket(adapter_get_address(adapter), TRUE);
+ if (!server->io) {
+ g_free(server);
+ return NULL;
+ }
+
+ server->adapter = btd_adapter_ref(adapter);
+
+ servers = g_slist_append(servers, server);
+
+ return server;
+}
+
struct avdtp_local_sep *avdtp_register_sep(struct btd_adapter *adapter,
uint8_t type,
uint8_t media_type,
@@ -3696,8 +3735,11 @@ struct avdtp_local_sep *avdtp_register_sep(struct btd_adapter *adapter,
struct avdtp_local_sep *sep;
server = find_server(servers, adapter);
- if (!server)
- return NULL;
+ if (!server) {
+ server = avdtp_server_init(adapter);
+ if (!server)
+ return NULL;
+ }
if (g_slist_length(server->seps) > MAX_SEID)
return NULL;
@@ -3722,6 +3764,18 @@ struct avdtp_local_sep *avdtp_register_sep(struct btd_adapter *adapter,
return sep;
}
+static void avdtp_server_destroy(struct avdtp_server *server)
+{
+ g_slist_free_full(server->sessions, avdtp_free);
+
+ servers = g_slist_remove(servers, server);
+
+ g_io_channel_shutdown(server->io, TRUE, NULL);
+ g_io_channel_unref(server->io);
+ btd_adapter_unref(server->adapter);
+ g_free(server);
+}
+
int avdtp_unregister_sep(struct avdtp_local_sep *sep)
{
struct avdtp_server *server;
@@ -3740,27 +3794,12 @@ int avdtp_unregister_sep(struct avdtp_local_sep *sep)
g_free(sep);
- return 0;
-}
-
-static GIOChannel *avdtp_server_socket(const bdaddr_t *src, gboolean master)
-{
- GError *err = NULL;
- GIOChannel *io;
+ if (server->seps)
+ return 0;
- io = bt_io_listen(NULL, avdtp_confirm_cb,
- NULL, NULL, &err,
- BT_IO_OPT_SOURCE_BDADDR, src,
- BT_IO_OPT_PSM, AVDTP_PSM,
- BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
- BT_IO_OPT_MASTER, master,
- BT_IO_OPT_INVALID);
- if (!io) {
- error("%s", err->message);
- g_error_free(err);
- }
+ avdtp_server_destroy(server);
- return io;
+ return 0;
}
const char *avdtp_strerror(struct avdtp_error *err)
@@ -3823,43 +3862,6 @@ struct btd_device *avdtp_get_device(struct avdtp *session)
return session->device;
}
-int avdtp_init(struct btd_adapter *adapter)
-{
- struct avdtp_server *server;
-
- server = g_new0(struct avdtp_server, 1);
-
- server->io = avdtp_server_socket(adapter_get_address(adapter), TRUE);
- if (!server->io) {
- g_free(server);
- return -1;
- }
-
- server->adapter = btd_adapter_ref(adapter);
-
- servers = g_slist_append(servers, server);
-
- return 0;
-}
-
-void avdtp_exit(struct btd_adapter *adapter)
-{
- struct avdtp_server *server;
-
- server = find_server(servers, adapter);
- if (!server)
- return;
-
- g_slist_free_full(server->sessions, avdtp_free);
-
- servers = g_slist_remove(servers, server);
-
- g_io_channel_shutdown(server->io, TRUE, NULL);
- g_io_channel_unref(server->io);
- btd_adapter_unref(server->adapter);
- g_free(server);
-}
-
gboolean avdtp_has_stream(struct avdtp *session, struct avdtp_stream *stream)
{
return g_slist_find(session->streams, stream) ? TRUE : FALSE;
diff --git a/profiles/audio/avdtp.h b/profiles/audio/avdtp.h
index 3bf7503..5606506 100644
--- a/profiles/audio/avdtp.h
+++ b/profiles/audio/avdtp.h
@@ -308,6 +308,3 @@ 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);
-
-int avdtp_init(struct btd_adapter *adapter);
-void avdtp_exit(struct btd_adapter *adapter);
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH BlueZ] audio/AVDTP: Remove avdtp_init and avdtp_exit
From: Luiz Augusto von Dentz @ 2013-11-11 15:34 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org
In-Reply-To: <1384179100-11209-1-git-send-email-luiz.dentz@gmail.com>
Hi,
On Mon, Nov 11, 2013 at 4:11 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This is now done on demand by avdtp_register_sep and avdtp_unregister_sep
> so the server socket is only registered when there is an endpoint
> available and the record is properly registered.
> ---
> profiles/audio/a2dp.c | 11 -----
> profiles/audio/avdtp.c | 118 +++++++++++++++++++++++++------------------------
> profiles/audio/avdtp.h | 3 --
> 3 files changed, 60 insertions(+), 72 deletions(-)
>
> diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
> index 8477b5d..6b3d6b2 100644
> --- a/profiles/audio/a2dp.c
> +++ b/profiles/audio/a2dp.c
> @@ -1187,17 +1187,8 @@ static struct a2dp_server *find_server(GSList *list, struct btd_adapter *a)
> static struct a2dp_server *a2dp_server_register(struct btd_adapter *adapter)
> {
> struct a2dp_server *server;
> - int av_err;
>
> server = g_new0(struct a2dp_server, 1);
> -
> - av_err = avdtp_init(adapter);
> - if (av_err < 0) {
> - DBG("AVDTP not registered");
> - g_free(server);
> - return NULL;
> - }
> -
> server->adapter = btd_adapter_ref(adapter);
> servers = g_slist_append(servers, server);
>
> @@ -1217,8 +1208,6 @@ static void a2dp_unregister_sep(struct a2dp_sep *sep)
>
> static void a2dp_server_unregister(struct a2dp_server *server)
> {
> - avdtp_exit(server->adapter);
> -
> servers = g_slist_remove(servers, server);
> btd_adapter_unref(server->adapter);
> g_free(server);
> diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
> index dab8f1c..9a470f1 100644
> --- a/profiles/audio/avdtp.c
> +++ b/profiles/audio/avdtp.c
> @@ -3683,6 +3683,45 @@ int avdtp_delay_report(struct avdtp *session, struct avdtp_stream *stream,
> &req, sizeof(req));
> }
>
> +static GIOChannel *avdtp_server_socket(const bdaddr_t *src, gboolean master)
> +{
> + GError *err = NULL;
> + GIOChannel *io;
> +
> + io = bt_io_listen(NULL, avdtp_confirm_cb,
> + NULL, NULL, &err,
> + BT_IO_OPT_SOURCE_BDADDR, src,
> + BT_IO_OPT_PSM, AVDTP_PSM,
> + BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
> + BT_IO_OPT_MASTER, master,
> + BT_IO_OPT_INVALID);
> + if (!io) {
> + error("%s", err->message);
> + g_error_free(err);
> + }
> +
> + return io;
> +}
> +
> +static struct avdtp_server *avdtp_server_init(struct btd_adapter *adapter)
> +{
> + struct avdtp_server *server;
> +
> + server = g_new0(struct avdtp_server, 1);
> +
> + server->io = avdtp_server_socket(adapter_get_address(adapter), TRUE);
> + if (!server->io) {
> + g_free(server);
> + return NULL;
> + }
> +
> + server->adapter = btd_adapter_ref(adapter);
> +
> + servers = g_slist_append(servers, server);
> +
> + return 0;
> +}
> +
> struct avdtp_local_sep *avdtp_register_sep(struct btd_adapter *adapter,
> uint8_t type,
> uint8_t media_type,
> @@ -3696,8 +3735,11 @@ struct avdtp_local_sep *avdtp_register_sep(struct btd_adapter *adapter,
> struct avdtp_local_sep *sep;
>
> server = find_server(servers, adapter);
> - if (!server)
> - return NULL;
> + if (!server) {
> + server = avdtp_server_init(adapter);
> + if (!server)
> + return NULL;
> + }
>
> if (g_slist_length(server->seps) > MAX_SEID)
> return NULL;
> @@ -3722,6 +3764,18 @@ struct avdtp_local_sep *avdtp_register_sep(struct btd_adapter *adapter,
> return sep;
> }
>
> +static void avdtp_server_destroy(struct avdtp_server *server)
> +{
> + g_slist_free_full(server->sessions, avdtp_free);
> +
> + servers = g_slist_remove(servers, server);
> +
> + g_io_channel_shutdown(server->io, TRUE, NULL);
> + g_io_channel_unref(server->io);
> + btd_adapter_unref(server->adapter);
> + g_free(server);
> +}
> +
> int avdtp_unregister_sep(struct avdtp_local_sep *sep)
> {
> struct avdtp_server *server;
> @@ -3740,27 +3794,12 @@ int avdtp_unregister_sep(struct avdtp_local_sep *sep)
>
> g_free(sep);
>
> - return 0;
> -}
> -
> -static GIOChannel *avdtp_server_socket(const bdaddr_t *src, gboolean master)
> -{
> - GError *err = NULL;
> - GIOChannel *io;
> + if (server->seps)
> + return 0;
>
> - io = bt_io_listen(NULL, avdtp_confirm_cb,
> - NULL, NULL, &err,
> - BT_IO_OPT_SOURCE_BDADDR, src,
> - BT_IO_OPT_PSM, AVDTP_PSM,
> - BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
> - BT_IO_OPT_MASTER, master,
> - BT_IO_OPT_INVALID);
> - if (!io) {
> - error("%s", err->message);
> - g_error_free(err);
> - }
> + avdtp_server_destroy(server);
>
> - return io;
> + return 0;
> }
>
> const char *avdtp_strerror(struct avdtp_error *err)
> @@ -3823,43 +3862,6 @@ struct btd_device *avdtp_get_device(struct avdtp *session)
> return session->device;
> }
>
> -int avdtp_init(struct btd_adapter *adapter)
> -{
> - struct avdtp_server *server;
> -
> - server = g_new0(struct avdtp_server, 1);
> -
> - server->io = avdtp_server_socket(adapter_get_address(adapter), TRUE);
> - if (!server->io) {
> - g_free(server);
> - return -1;
> - }
> -
> - server->adapter = btd_adapter_ref(adapter);
> -
> - servers = g_slist_append(servers, server);
> -
> - return 0;
> -}
> -
> -void avdtp_exit(struct btd_adapter *adapter)
> -{
> - struct avdtp_server *server;
> -
> - server = find_server(servers, adapter);
> - if (!server)
> - return;
> -
> - g_slist_free_full(server->sessions, avdtp_free);
> -
> - servers = g_slist_remove(servers, server);
> -
> - g_io_channel_shutdown(server->io, TRUE, NULL);
> - g_io_channel_unref(server->io);
> - btd_adapter_unref(server->adapter);
> - g_free(server);
> -}
> -
> gboolean avdtp_has_stream(struct avdtp *session, struct avdtp_stream *stream)
> {
> return g_slist_find(session->streams, stream) ? TRUE : FALSE;
> diff --git a/profiles/audio/avdtp.h b/profiles/audio/avdtp.h
> index 3bf7503..5606506 100644
> --- a/profiles/audio/avdtp.h
> +++ b/profiles/audio/avdtp.h
> @@ -308,6 +308,3 @@ 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);
> -
> -int avdtp_init(struct btd_adapter *adapter);
> -void avdtp_exit(struct btd_adapter *adapter);
> --
> 1.8.3.1
There is apparently a bug in this one, well send a v2 shortly.
--
Luiz Augusto von Dentz
^ permalink raw reply
* [PATCH 4/4] android/pan: Handle connection and control state notifications
From: Ravi kumar Veeramally @ 2013-11-11 14:53 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1384181621-8070-1-git-send-email-ravikumar.veeramally@linux.intel.com>
---
android/hal-pan.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/android/hal-pan.c b/android/hal-pan.c
index 76f5159..4173925 100644
--- a/android/hal-pan.c
+++ b/android/hal-pan.c
@@ -31,10 +31,41 @@ static bool interface_ready(void)
return cbs != NULL;
}
+static void handle_conn_state(void *buf)
+{
+ struct hal_ev_pan_conn_state *ev = buf;
+
+ if (cbs->connection_state_cb)
+ cbs->connection_state_cb(ev->state, ev->status,
+ (bt_bdaddr_t *) ev->bdaddr,
+ ev->local_role, ev->remote_role);
+}
+
+static void handle_ctrl_state(void *buf)
+{
+ struct hal_ev_pan_ctrl_state *ev = buf;
+
+ if (cbs->control_state_cb)
+ cbs->control_state_cb(ev->state, ev->status,
+ ev->local_role, (char *)ev->name);
+}
+
void bt_notify_pan(uint16_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;
+ }
}
static bt_status_t pan_enable(int local_role)
--
1.8.3.2
^ permalink raw reply related
* [PATCH 3/4] android/pan: Add notify method to PAN notifications
From: Ravi kumar Veeramally @ 2013-11-11 14:53 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1384181621-8070-1-git-send-email-ravikumar.veeramally@linux.intel.com>
---
android/hal-pan.c | 6 ++++++
android/hal.h | 1 +
2 files changed, 7 insertions(+)
diff --git a/android/hal-pan.c b/android/hal-pan.c
index a560055..76f5159 100644
--- a/android/hal-pan.c
+++ b/android/hal-pan.c
@@ -31,6 +31,12 @@ static bool interface_ready(void)
return cbs != NULL;
}
+void bt_notify_pan(uint16_t opcode, void *buf, uint16_t len)
+{
+ if (!interface_ready())
+ return;
+}
+
static bt_status_t pan_enable(int local_role)
{
struct hal_cmd_pan_enable cmd;
diff --git a/android/hal.h b/android/hal.h
index 2ce7932..be5d491 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -31,3 +31,4 @@ void bt_thread_associate(void);
void bt_thread_disassociate(void);
void bt_notify_hidhost(uint16_t opcode, void *buf, uint16_t len);
void bt_notify_a2dp(uint16_t opcode, void *buf, uint16_t len);
+void bt_notify_pan(uint16_t opcode, void *buf, uint16_t len);
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/4] android/pan: Add PAN cleanup interface implementation
From: Ravi kumar Veeramally @ 2013-11-11 14:53 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1384181621-8070-1-git-send-email-ravikumar.veeramally@linux.intel.com>
---
android/hal-pan.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/android/hal-pan.c b/android/hal-pan.c
index cacc6c0..a560055 100644
--- a/android/hal-pan.c
+++ b/android/hal-pan.c
@@ -114,16 +114,18 @@ static bt_status_t pan_init(const btpan_callbacks_t *callbacks)
static void pan_cleanup()
{
+ struct hal_cmd_register_module cmd;
+
DBG("");
if (!interface_ready())
return;
- /* TODO: disable service */
-
- /* TODO: stop PAN thread */
-
cbs = NULL;
+ cmd.service_id = HAL_SERVICE_ID_PAN;
+
+ hal_ipc_cmd(HAL_SERVICE_ID_PAN, HAL_OP_UNREGISTER_MODULE,
+ sizeof(cmd), &cmd, 0, NULL, NULL);
}
static btpan_interface_t pan_if = {
--
1.8.3.2
^ permalink raw reply related
* [PATCH 1/4] android/pan: Add PAN related defines and event struct to hsl-msg header
From: Ravi kumar Veeramally @ 2013-11-11 14:53 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1384181621-8070-1-git-send-email-ravikumar.veeramally@linux.intel.com>
---
android/hal-msg.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/android/hal-msg.h b/android/hal-msg.h
index 569c8ea..00d6e39 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -317,6 +317,33 @@ struct hal_cmd_a2dp_disconnect {
/* PAN HAL API */
+/* PAN Roles */
+#define HAL_PAN_ROLE_NONE 0x00
+#define HAL_PAN_ROLE_NAP 0x01
+#define HAL_PAN_ROLE_PANU 0x02
+
+/* PAN Control states */
+#define HAL_PAN_CTRL_ENABLED 0x00
+#define HAL_PAN_CTRL_DISABLED 0x01
+
+/* PAN Connection states */
+#define HAL_PAN_STATE_CONNECTED 0x00
+#define HAL_PAN_STATE_CONNECTING 0x01
+#define HAL_PAN_STATE_DISCONNECTED 0x02
+#define HAL_PAN_STATE_DISCONNECTING 0x03
+
+/* PAN status values */
+#define HAL_PAN_STATUS_FAIL 0x01
+#define HAL_PAN_STATUS_NOT_READY 0x02
+#define HAL_PAN_STATUS_NO_MEMORY 0x03
+#define HAL_PAN_STATUS_BUSY 0x04
+#define HAL_PAN_STATUS_DONE 0x05
+#define HAL_PAN_STATUS_UNSUPORTED 0x06
+#define HAL_PAN_STATUS_INVAL 0x07
+#define HAL_PAN_STATUS_UNHANDLED 0x08
+#define HAL_PAN_STATUS_AUTH_FAILED 0x09
+#define HAL_PAN_STATUS_DEVICE_DOWN 0x0A
+
#define HAL_OP_PAN_ENABLE 0x01
struct hal_cmd_pan_enable {
uint8_t local_role;
@@ -486,6 +513,23 @@ struct hal_ev_hidhost_virtual_unplug {
uint8_t status;
} __attribute__((packed));
+#define HAL_EV_PAN_CONN_STATE 0x81
+struct hal_ev_pan_conn_state {
+ uint8_t state;
+ uint8_t status;
+ uint8_t bdaddr[6];
+ uint8_t local_role;
+ uint8_t remote_role;
+} __attribute__((packed));
+
+#define HAL_EV_PAN_CTRL_STATE 0x82
+struct hal_ev_pan_ctrl_state {
+ uint8_t state;
+ uint8_t status;
+ uint8_t local_role;
+ uint8_t name[17];
+} __attribute__((packed));
+
#define HAL_EV_A2DP_CONNECTION_STATE 0x81
struct hal_ev_a2dp_connection_state {
uint8_t state;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 0/4] Implement missing PAN interface and notifications
From: Ravi kumar Veeramally @ 2013-11-11 14:53 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
Patch set implements missing cleanup interface and adds event structs
to hal-msg.h and implements connection and control state notifications.
Ravi kumar Veeramally (4):
android/pan: Add PAN related defines and event struct to hsl-msg
header
android/pan: Add PAN cleanup interface implementation
android/pan: Add notify method to PAN notifications
android/pan: Handle connection and control state notifications
android/hal-msg.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
android/hal-pan.c | 47 +++++++++++++++++++++++++++++++++++++++++++----
android/hal.h | 1 +
3 files changed, 88 insertions(+), 4 deletions(-)
--
1.8.3.2
^ permalink raw reply
* [PATCH BlueZ] audio/AVDTP: Remove avdtp_init and avdtp_exit
From: Luiz Augusto von Dentz @ 2013-11-11 14:11 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This is now done on demand by avdtp_register_sep and avdtp_unregister_sep
so the server socket is only registered when there is an endpoint
available and the record is properly registered.
---
profiles/audio/a2dp.c | 11 -----
profiles/audio/avdtp.c | 118 +++++++++++++++++++++++++------------------------
profiles/audio/avdtp.h | 3 --
3 files changed, 60 insertions(+), 72 deletions(-)
diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index 8477b5d..6b3d6b2 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -1187,17 +1187,8 @@ static struct a2dp_server *find_server(GSList *list, struct btd_adapter *a)
static struct a2dp_server *a2dp_server_register(struct btd_adapter *adapter)
{
struct a2dp_server *server;
- int av_err;
server = g_new0(struct a2dp_server, 1);
-
- av_err = avdtp_init(adapter);
- if (av_err < 0) {
- DBG("AVDTP not registered");
- g_free(server);
- return NULL;
- }
-
server->adapter = btd_adapter_ref(adapter);
servers = g_slist_append(servers, server);
@@ -1217,8 +1208,6 @@ static void a2dp_unregister_sep(struct a2dp_sep *sep)
static void a2dp_server_unregister(struct a2dp_server *server)
{
- avdtp_exit(server->adapter);
-
servers = g_slist_remove(servers, server);
btd_adapter_unref(server->adapter);
g_free(server);
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index dab8f1c..9a470f1 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -3683,6 +3683,45 @@ int avdtp_delay_report(struct avdtp *session, struct avdtp_stream *stream,
&req, sizeof(req));
}
+static GIOChannel *avdtp_server_socket(const bdaddr_t *src, gboolean master)
+{
+ GError *err = NULL;
+ GIOChannel *io;
+
+ io = bt_io_listen(NULL, avdtp_confirm_cb,
+ NULL, NULL, &err,
+ BT_IO_OPT_SOURCE_BDADDR, src,
+ BT_IO_OPT_PSM, AVDTP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_MASTER, master,
+ BT_IO_OPT_INVALID);
+ if (!io) {
+ error("%s", err->message);
+ g_error_free(err);
+ }
+
+ return io;
+}
+
+static struct avdtp_server *avdtp_server_init(struct btd_adapter *adapter)
+{
+ struct avdtp_server *server;
+
+ server = g_new0(struct avdtp_server, 1);
+
+ server->io = avdtp_server_socket(adapter_get_address(adapter), TRUE);
+ if (!server->io) {
+ g_free(server);
+ return NULL;
+ }
+
+ server->adapter = btd_adapter_ref(adapter);
+
+ servers = g_slist_append(servers, server);
+
+ return 0;
+}
+
struct avdtp_local_sep *avdtp_register_sep(struct btd_adapter *adapter,
uint8_t type,
uint8_t media_type,
@@ -3696,8 +3735,11 @@ struct avdtp_local_sep *avdtp_register_sep(struct btd_adapter *adapter,
struct avdtp_local_sep *sep;
server = find_server(servers, adapter);
- if (!server)
- return NULL;
+ if (!server) {
+ server = avdtp_server_init(adapter);
+ if (!server)
+ return NULL;
+ }
if (g_slist_length(server->seps) > MAX_SEID)
return NULL;
@@ -3722,6 +3764,18 @@ struct avdtp_local_sep *avdtp_register_sep(struct btd_adapter *adapter,
return sep;
}
+static void avdtp_server_destroy(struct avdtp_server *server)
+{
+ g_slist_free_full(server->sessions, avdtp_free);
+
+ servers = g_slist_remove(servers, server);
+
+ g_io_channel_shutdown(server->io, TRUE, NULL);
+ g_io_channel_unref(server->io);
+ btd_adapter_unref(server->adapter);
+ g_free(server);
+}
+
int avdtp_unregister_sep(struct avdtp_local_sep *sep)
{
struct avdtp_server *server;
@@ -3740,27 +3794,12 @@ int avdtp_unregister_sep(struct avdtp_local_sep *sep)
g_free(sep);
- return 0;
-}
-
-static GIOChannel *avdtp_server_socket(const bdaddr_t *src, gboolean master)
-{
- GError *err = NULL;
- GIOChannel *io;
+ if (server->seps)
+ return 0;
- io = bt_io_listen(NULL, avdtp_confirm_cb,
- NULL, NULL, &err,
- BT_IO_OPT_SOURCE_BDADDR, src,
- BT_IO_OPT_PSM, AVDTP_PSM,
- BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
- BT_IO_OPT_MASTER, master,
- BT_IO_OPT_INVALID);
- if (!io) {
- error("%s", err->message);
- g_error_free(err);
- }
+ avdtp_server_destroy(server);
- return io;
+ return 0;
}
const char *avdtp_strerror(struct avdtp_error *err)
@@ -3823,43 +3862,6 @@ struct btd_device *avdtp_get_device(struct avdtp *session)
return session->device;
}
-int avdtp_init(struct btd_adapter *adapter)
-{
- struct avdtp_server *server;
-
- server = g_new0(struct avdtp_server, 1);
-
- server->io = avdtp_server_socket(adapter_get_address(adapter), TRUE);
- if (!server->io) {
- g_free(server);
- return -1;
- }
-
- server->adapter = btd_adapter_ref(adapter);
-
- servers = g_slist_append(servers, server);
-
- return 0;
-}
-
-void avdtp_exit(struct btd_adapter *adapter)
-{
- struct avdtp_server *server;
-
- server = find_server(servers, adapter);
- if (!server)
- return;
-
- g_slist_free_full(server->sessions, avdtp_free);
-
- servers = g_slist_remove(servers, server);
-
- g_io_channel_shutdown(server->io, TRUE, NULL);
- g_io_channel_unref(server->io);
- btd_adapter_unref(server->adapter);
- g_free(server);
-}
-
gboolean avdtp_has_stream(struct avdtp *session, struct avdtp_stream *stream)
{
return g_slist_find(session->streams, stream) ? TRUE : FALSE;
diff --git a/profiles/audio/avdtp.h b/profiles/audio/avdtp.h
index 3bf7503..5606506 100644
--- a/profiles/audio/avdtp.h
+++ b/profiles/audio/avdtp.h
@@ -308,6 +308,3 @@ 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);
-
-int avdtp_init(struct btd_adapter *adapter);
-void avdtp_exit(struct btd_adapter *adapter);
--
1.8.3.1
^ permalink raw reply related
* [RFCv1 9/9] android/hal-sock: Write channel to Android fd
From: Andrei Emeltchenko @ 2013-11-11 14:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384178627-25991-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/socket.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index 20f4e38..0188646 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -27,6 +27,7 @@
#include <glib.h>
#include <stdbool.h>
+#include <unistd.h>
#include <errno.h>
#include "lib/bluetooth.h"
@@ -292,6 +293,10 @@ static int handle_listen(void *buf)
rfslot->real_sock = g_io_channel_unix_get_fd(io);
rfcomm_srv_list = g_list_append(rfcomm_srv_list, rfslot);
+ /* TODO: Check this */
+ if (write(rfslot->fd, &ch, sizeof(ch)) < 0)
+ return -1;
+
DBG("real_sock %d fd %d hal_fd %d",
rfslot->real_sock, rfslot->fd, rfslot->hal_fd);
--
1.7.10.4
^ permalink raw reply related
* [RFCv1 8/9] android/hal-sock: Implement accept signal over Android fd
From: Andrei Emeltchenko @ 2013-11-11 14:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384178627-25991-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Android expects to get accept signal over file descriptor which was
set during listen HAL call.
---
android/socket.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index a962cdc..20f4e38 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -36,6 +36,7 @@
#include "hal-ipc.h"
#include "ipc.h"
#include "adapter.h"
+#include "utils.h"
#include "socket.h"
/* Simple list of RFCOMM server sockets */
@@ -68,6 +69,45 @@ static struct rfcomm_slot *create_rfslot(int sock)
return rfslot;
}
+static int bt_sock_send_fd(int sock_fd, const void *buf, int len, int send_fd)
+{
+ ssize_t ret;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iv;
+ char msgbuf[CMSG_SPACE(1)];
+
+ DBG("len %d sock_fd %d send_fd %d", len, sock_fd, send_fd);
+
+ if (sock_fd == -1 || send_fd == -1)
+ return -1;
+
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_control = msgbuf;
+ msg.msg_controllen = sizeof(msgbuf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(send_fd));
+ memcpy(CMSG_DATA(cmsg), &send_fd, sizeof(send_fd));
+
+ iv.iov_base = (unsigned char *) buf;
+ iv.iov_len = len;
+
+ msg.msg_iov = &iv;
+ msg.msg_iovlen = 1;
+
+ ret = sendmsg(sock_fd, &msg, MSG_NOSIGNAL);
+ if (ret < 0) {
+ error("sendmsg(): sock_fd %d send_fd %d: %s",
+ sock_fd, send_fd, strerror(errno));
+ return ret;
+ }
+
+ return ret;
+}
+
static const uint8_t UUID_PBAP[] = {
0x00, 0x00, 0x11, 0x2F, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
@@ -161,6 +201,21 @@ static gboolean sock_rfcomm_event_cb(GIOChannel *io, GIOCondition cond,
return TRUE;
}
+static void socket_send_accept(struct rfcomm_slot *rfslot, bdaddr_t *bdaddr,
+ int fd_accepted)
+{
+ struct hal_sock_connect_signal cmd;
+
+ DBG("");
+
+ cmd.size = sizeof(cmd);
+ bdaddr2android(bdaddr, cmd.bdaddr);
+ cmd.channel = rfslot->channel;
+ cmd.status = 0;
+
+ bt_sock_send_fd(rfslot->fd, &cmd, sizeof(cmd), fd_accepted);
+}
+
static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
{
struct rfcomm_slot *rfslot = user_data;
@@ -190,6 +245,8 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
rfslot_acc = create_rfslot(sock_acc);
rfcomm_accepted_list = g_list_append(rfcomm_accepted_list, rfslot_acc);
+ socket_send_accept(rfslot, &dst, rfslot_acc->hal_fd);
+
/* Handle events from Android */
io_stack = g_io_channel_unix_new(rfslot_acc->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
* [RFCv1 7/9] android/hal-sock: Implement RFCOMM events
From: Andrei Emeltchenko @ 2013-11-11 14:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384178627-25991-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Copy data from RFCOMM socket to Android framework.
---
android/socket.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index dfad9da..a962cdc 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -129,6 +129,35 @@ static gboolean sock_stack_event_cb(GIOChannel *io, GIOCondition cond,
static gboolean sock_rfcomm_event_cb(GIOChannel *io, GIOCondition cond,
gpointer data)
{
+ struct rfcomm_slot *rfslot = data;
+ unsigned char buf[1024] = { 0 };
+ int len;
+
+ DBG("rfslot: fd %d hal_fd %d real_sock %d chan %u sock %d",
+ rfslot->fd, rfslot->hal_fd, rfslot->real_sock, rfslot->channel,
+ g_io_channel_unix_get_fd(io));
+
+ if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+ error("Socket error: sock %d cond %d",
+ g_io_channel_unix_get_fd(io), cond);
+ g_io_channel_shutdown(io, TRUE, NULL);
+ return FALSE;
+ }
+
+ /* FIXME check real_sock vs sock(io) */
+ len = recv(rfslot->real_sock, buf, sizeof(buf), 0);
+ if (len <= 0) {
+ error("recv(): %s sock %d", strerror(errno), rfslot->real_sock);
+ return FALSE;
+ }
+
+ DBG("read %d bytes, write to fd %d", len, rfslot->fd);
+
+ if (send(rfslot->fd, buf, len, MSG_DONTWAIT) < 0) {
+ error("send(): %s sock %d", strerror(errno), rfslot->fd);
+ return FALSE;
+ }
+
return TRUE;
}
--
1.7.10.4
^ permalink raw reply related
* [RFCv1 6/9] android/hal-sock: Implement Android RFCOMM stack events
From: Andrei Emeltchenko @ 2013-11-11 14:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384178627-25991-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Handle events from Android framework. Write everything to real RFCOMM
socket.
---
android/socket.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index 0ee53ba..dfad9da 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -94,6 +94,35 @@ static int get_rfcomm_chan(const uint8_t *uuid)
static gboolean sock_stack_event_cb(GIOChannel *io, GIOCondition cond,
gpointer data)
{
+ struct rfcomm_slot *rfslot = data;
+ unsigned char buf[1024] = { 0 };
+ int len;
+
+ DBG("rfslot: fd %d hal_fd %d real_sock %d chan %u sock %d",
+ rfslot->fd, rfslot->hal_fd, rfslot->real_sock, rfslot->channel,
+ g_io_channel_unix_get_fd(io));
+
+ if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+ error("Socket error: sock %d cond %d",
+ g_io_channel_unix_get_fd(io), cond);
+ g_io_channel_shutdown(io, TRUE, NULL);
+ return FALSE;
+ }
+
+ /* FIXME check fd vs sock(io) */
+ len = recv(rfslot->fd, buf, sizeof(buf), 0);
+ if (len <= 0) {
+ error("recv(): %s", strerror(errno));
+ return FALSE;
+ }
+
+ DBG("read %d bytes write to %d", len, rfslot->real_sock);
+
+ if (send(rfslot->real_sock, buf, len, 0) < 0) {
+ error("send(): %s", strerror(errno));
+ return FALSE;
+ }
+
return TRUE;
}
--
1.7.10.4
^ permalink raw reply related
* [RFCv1 5/9] android/hal-sock: Implement socket accepted event
From: Andrei Emeltchenko @ 2013-11-11 14:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384178627-25991-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When we get accepted event we create rfcomm slot and start listening
for events from Android framework and from RFCOMM real socket.
---
android/socket.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index 80cb39e..0ee53ba 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -91,8 +91,58 @@ static int get_rfcomm_chan(const uint8_t *uuid)
return -1;
}
+static gboolean sock_stack_event_cb(GIOChannel *io, GIOCondition cond,
+ gpointer data)
+{
+ return TRUE;
+}
+
+static gboolean sock_rfcomm_event_cb(GIOChannel *io, GIOCondition cond,
+ gpointer data)
+{
+ return TRUE;
+}
+
static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
{
+ struct rfcomm_slot *rfslot = user_data;
+ struct rfcomm_slot *rfslot_acc;
+ GIOChannel *io_stack;
+ bdaddr_t dst;
+ char address[18];
+ int sock_acc;
+
+ bt_io_get(io, &err,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_INVALID);
+ if (err) {
+ error("%s", err->message);
+ g_io_channel_shutdown(io, TRUE, NULL);
+ return;
+ }
+
+ ba2str(&dst, address);
+ DBG("Incoming connection from %s rfslot %p", address, rfslot);
+
+ DBG("rfslot: fd %d hal_fd %d real_sock %d chan %u sock %d",
+ rfslot->fd, rfslot->hal_fd, rfslot->real_sock, rfslot->channel,
+ g_io_channel_unix_get_fd(io));
+
+ sock_acc = g_io_channel_unix_get_fd(io);
+ rfslot_acc = create_rfslot(sock_acc);
+ rfcomm_accepted_list = g_list_append(rfcomm_accepted_list, rfslot_acc);
+
+ /* Handle events from Android */
+ io_stack = g_io_channel_unix_new(rfslot_acc->fd);
+ g_io_add_watch(io_stack, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ sock_stack_event_cb, rfslot_acc);
+ 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, rfslot_acc);
+
+ DBG("rfslot %p rfslot_acc %p", rfslot, rfslot_acc);
}
static int handle_listen(void *buf)
--
1.7.10.4
^ permalink raw reply related
* [RFCv1 4/9] android/hal-sock: Initial listen handle
From: Andrei Emeltchenko @ 2013-11-11 14:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384178627-25991-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Handle HAL socket listen call. Create RFCOMM socket and wait for events.
---
android/socket.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 92 insertions(+), 2 deletions(-)
diff --git a/android/socket.c b/android/socket.c
index c283c5f..80cb39e 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -27,22 +27,112 @@
#include <glib.h>
#include <stdbool.h>
+#include <errno.h>
#include "lib/bluetooth.h"
+#include "btio/btio.h"
#include "log.h"
#include "hal-msg.h"
#include "hal-ipc.h"
#include "ipc.h"
+#include "adapter.h"
#include "socket.h"
+/* Simple list of RFCOMM server sockets */
+GList *rfcomm_srv_list = NULL;
+/* Simple list of RFCOMM accepted sockets */
+GList *rfcomm_accepted_list = NULL;
-static int handle_listen(void *buf)
+struct rfcomm_slot {
+ int fd;
+ int hal_fd;
+ int real_sock;
+ uint32_t channel;
+};
+
+static struct rfcomm_slot *create_rfslot(int sock)
{
- DBG("Not implemented");
+ int fds[2] = {-1, -1};
+ struct rfcomm_slot *rfslot;
+
+ if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) < 0) {
+ error("socketpair(): %s", strerror(errno));
+ return NULL;
+ }
+
+ rfslot = g_malloc0(sizeof(*rfslot));
+ rfslot->fd = fds[0];
+ rfslot->hal_fd = fds[1];
+ rfslot->real_sock = sock;
+
+ return rfslot;
+}
+
+static const uint8_t UUID_PBAP[] = {
+ 0x00, 0x00, 0x11, 0x2F, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
+};
+#define RFCOMM_CHAN_PBAP 19
+
+static const uint8_t UUID_OPP[] = {
+ 0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
+};
+#define RFCOMM_CHAN_OPP 12
+
+static int get_rfcomm_chan(const uint8_t *uuid)
+{
+ if (!memcmp(UUID_PBAP, uuid, sizeof(UUID_PBAP)))
+ return RFCOMM_CHAN_PBAP;
+
+ if (!memcmp(UUID_OPP, uuid, sizeof(UUID_OPP)))
+ return RFCOMM_CHAN_OPP;
return -1;
}
+static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+{
+}
+
+static int handle_listen(void *buf)
+{
+ struct hal_cmd_sock_listen *cmd = buf;
+ const bdaddr_t *src = bt_adapter_get_address();
+ struct rfcomm_slot *rfslot;
+ GIOChannel *io;
+ GError *err = NULL;
+ int ch;
+
+ DBG("");
+
+ ch = get_rfcomm_chan(cmd->uuid);
+ if (ch < 0)
+ return -1;
+
+ DBG("rfcomm channel %u", ch);
+
+ rfslot = create_rfslot(-1);
+
+ io = bt_io_listen(connect_cb, NULL, rfslot, NULL, &err,
+ BT_IO_OPT_SOURCE_BDADDR, src,
+ BT_IO_OPT_CHANNEL, ch,
+ BT_IO_OPT_INVALID);
+ if (!io) {
+ error("Failed listen: %s", err->message);
+ g_error_free(err);
+ return -1;
+ }
+
+ rfslot->real_sock = g_io_channel_unix_get_fd(io);
+ rfcomm_srv_list = g_list_append(rfcomm_srv_list, rfslot);
+
+ DBG("real_sock %d fd %d hal_fd %d",
+ rfslot->real_sock, rfslot->fd, rfslot->hal_fd);
+
+ return rfslot->hal_fd;
+}
+
static int handle_connect(void *buf)
{
DBG("Not implemented");
--
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