* [PATCH 4/4] sixaxis: Add support for setting LEDs when connected over USB
From: Szymon Janc @ 2013-12-01 13:41 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385905316-21800-1-git-send-email-szymon.janc@gmail.com>
This allows to setup LEDs when device is connected over USB, not
Bluetooth. This coverts two scenarios:
- user plugged PS3 controller and pressed PS3 button before unplugging,
in that case LEDs are set
- user plugged already BT connected PS3 controller to USB, this results
in new /dev/input/jsX device being create but controller is still
transmitting over BT and old jsX device exists. In that case don't
set LEDs as they are already set.
This is not directly related to Bluetooth itself but change is really
small and provides much better and consistent user experience.
---
plugins/sixaxis.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/plugins/sixaxis.c b/plugins/sixaxis.c
index b8fe287..45fa170 100644
--- a/plugins/sixaxis.c
+++ b/plugins/sixaxis.c
@@ -181,7 +181,7 @@ static gboolean setup_leds(GIOChannel *channel, GIOCondition cond,
return FALSE;
}
-static void setup_device(int fd, int index, struct btd_adapter *adapter)
+static bool setup_device(int fd, int index, struct btd_adapter *adapter)
{
char device_addr[18], master_addr[18], adapter_addr[18];
bdaddr_t device_bdaddr, master_bdaddr;
@@ -189,22 +189,23 @@ static void setup_device(int fd, int index, struct btd_adapter *adapter)
struct btd_device *device;
if (get_device_bdaddr(fd, &device_bdaddr) < 0)
- return;
+ return false;
if (get_master_bdaddr(fd, &master_bdaddr) < 0)
- return;
+ return false;
/* This can happen if controller was plugged while already connected
- * eg. to charge up battery */
+ * eg. to charge up battery.
+ * Don't set LEDs in that case, hence return false */
device = btd_adapter_find_device(adapter, &device_bdaddr);
if (device && btd_device_is_connected(device))
- return;
+ return false;
adapter_bdaddr = btd_adapter_get_address(adapter);
if (bacmp(adapter_bdaddr, &master_bdaddr)) {
if (set_master_bdaddr(fd, adapter_bdaddr) < 0)
- return;
+ return false;
}
ba2str(&device_bdaddr, device_addr);
@@ -218,7 +219,7 @@ static void setup_device(int fd, int index, struct btd_adapter *adapter)
if (g_slist_find_custom(btd_device_get_uuids(device), HID_UUID,
(GCompareFunc)strcasecmp)) {
DBG("device %s already known, skipping", device_addr);
- return;
+ return true;
}
info("sixaxis: setting up new device");
@@ -228,6 +229,8 @@ static void setup_device(int fd, int index, struct btd_adapter *adapter)
devices[index].pid, devices[index].version);
btd_device_set_temporary(device, FALSE);
btd_device_set_trusted(device, TRUE);
+
+ return true;
}
static int get_js_number(struct udev_device *udevice)
@@ -346,8 +349,10 @@ static void device_added(struct udev_device *udevice)
switch (bus) {
case BUS_USB:
- setup_device(fd, index, adapter);
- break;
+ if (!setup_device(fd, index, adapter))
+ break;
+
+ /* fall through */
case BUS_BLUETOOTH:
/* wait for events before setting leds */
g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
--
1.8.5
^ permalink raw reply related
* [PATCH 3/4] sixaxis: Skip controller setup if already connected over Bluetooth
From: Szymon Janc @ 2013-12-01 13:41 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385905316-21800-1-git-send-email-szymon.janc@gmail.com>
If controller is already connected over Bluetooth but was then
plugged-in via USB (eg. to charge battery) there is no need to do
any setup.
---
plugins/sixaxis.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/plugins/sixaxis.c b/plugins/sixaxis.c
index c3ca267..b8fe287 100644
--- a/plugins/sixaxis.c
+++ b/plugins/sixaxis.c
@@ -194,6 +194,12 @@ static void setup_device(int fd, int index, struct btd_adapter *adapter)
if (get_master_bdaddr(fd, &master_bdaddr) < 0)
return;
+ /* This can happen if controller was plugged while already connected
+ * eg. to charge up battery */
+ device = btd_adapter_find_device(adapter, &device_bdaddr);
+ if (device && btd_device_is_connected(device))
+ return;
+
adapter_bdaddr = btd_adapter_get_address(adapter);
if (bacmp(adapter_bdaddr, &master_bdaddr)) {
--
1.8.5
^ permalink raw reply related
* [PATCH 2/4] Rename device_is_connected to btd_device_is_connected
From: Szymon Janc @ 2013-12-01 13:41 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385905316-21800-1-git-send-email-szymon.janc@gmail.com>
Allow this symbol to be exported and usable from external plugins.
---
profiles/input/device.c | 4 ++--
src/adapter.c | 6 +++---
src/device.c | 6 +++---
src/device.h | 2 +-
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/profiles/input/device.c b/profiles/input/device.c
index 0c2089b..521aca8 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -667,7 +667,7 @@ static gboolean input_device_auto_reconnect(gpointer user_data)
/* Stop the recurrent reconnection attempts if the device is reconnected
* or is marked for removal. */
if (device_is_temporary(idev->device) ||
- device_is_connected(idev->device))
+ btd_device_is_connected(idev->device))
return FALSE;
/* Only attempt an auto-reconnect for at most 3 minutes (6 * 30s). */
@@ -713,7 +713,7 @@ static void input_device_enter_reconnect_mode(struct input_device *idev)
/* If the device is temporary we are not required to reconnect with the
* device. This is likely the case of a removing device. */
if (device_is_temporary(idev->device) ||
- device_is_connected(idev->device))
+ btd_device_is_connected(idev->device))
return;
if (idev->reconnect_timer > 0)
diff --git a/src/adapter.c b/src/adapter.c
index 55a41db..41f7bd6 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2158,7 +2158,7 @@ static DBusMessage *remove_device(DBusConnection *conn,
btd_device_set_temporary(device, TRUE);
- if (!device_is_connected(device)) {
+ if (!btd_device_is_connected(device)) {
adapter_remove_device(adapter, device);
return dbus_message_new_method_return(msg);
}
@@ -4195,7 +4195,7 @@ connect_le:
* connect_list stop passive scanning so that a connection
* attempt to it can be made
*/
- if (device_is_le(dev) && !device_is_connected(dev) &&
+ if (device_is_le(dev) && !btd_device_is_connected(dev) &&
g_slist_find(adapter->connect_list, dev)) {
adapter->connect_le = dev;
stop_passive_scanning(adapter);
@@ -5865,7 +5865,7 @@ static void unpaired_callback(uint16_t index, uint16_t length,
btd_device_set_temporary(device, TRUE);
- if (device_is_connected(device))
+ if (btd_device_is_connected(device))
device_request_disconnect(device, NULL);
else
adapter_remove_device(adapter, device);
diff --git a/src/device.c b/src/device.c
index 847ffad..5380c1a 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1355,7 +1355,7 @@ static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
if (device_is_le(dev)) {
int err;
- if (device_is_connected(dev))
+ if (btd_device_is_connected(dev))
return dbus_message_new_method_return(msg);
btd_device_set_temporary(dev, FALSE);
@@ -1645,7 +1645,7 @@ static DBusMessage *pair_device(DBusConnection *conn, DBusMessage *msg,
* channel first and only then start pairing (there's code for
* this in the ATT connect callback)
*/
- if (device_is_le(device) && !device_is_connected(device))
+ if (device_is_le(device) && !btd_device_is_connected(device))
err = device_connect_le(device);
else
err = adapter_create_bonding(adapter, &device->bdaddr,
@@ -1791,7 +1791,7 @@ static const GDBusPropertyTable device_properties[] = {
{ }
};
-gboolean device_is_connected(struct btd_device *device)
+gboolean btd_device_is_connected(struct btd_device *device)
{
return device->connected;
}
diff --git a/src/device.h b/src/device.h
index c3fea4a..3a33cb2 100644
--- a/src/device.h
+++ b/src/device.h
@@ -74,7 +74,7 @@ void btd_device_set_trusted(struct btd_device *device, gboolean trusted);
void device_set_bonded(struct btd_device *device, gboolean bonded);
void device_set_legacy(struct btd_device *device, bool legacy);
void device_set_rssi(struct btd_device *device, int8_t rssi);
-gboolean device_is_connected(struct btd_device *device);
+gboolean btd_device_is_connected(struct btd_device *device);
bool device_is_retrying(struct btd_device *device);
void device_bonding_complete(struct btd_device *device, uint8_t status);
gboolean device_is_bonding(struct btd_device *device, const char *sender);
--
1.8.5
^ permalink raw reply related
* [PATCH 1/4] sixaxis: Add support for setting PS3 controller LEDs
From: Szymon Janc @ 2013-12-01 13:41 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385905316-21800-1-git-send-email-szymon.janc@gmail.com>
This will set controller LEDs according to joystick device number
when controller is connected over Bluetooth. If joystick number is too
big (> 7) or falied to be read, set it to 0 to switch off all LEDs.
This will allow to disable LEDs blinking after connection.
Waiting for events is not really needed when connected over Bluetooth
but this is in preparation for supporting LEDs setup over USB.
---
plugins/sixaxis.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 139 insertions(+), 2 deletions(-)
diff --git a/plugins/sixaxis.c b/plugins/sixaxis.c
index 070b463..c3ca267 100644
--- a/plugins/sixaxis.c
+++ b/plugins/sixaxis.c
@@ -31,6 +31,7 @@
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
+#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/hidraw.h>
#include <linux/input.h>
@@ -124,6 +125,62 @@ static int set_master_bdaddr(int fd, const bdaddr_t *bdaddr)
return ret;
}
+static gboolean setup_leds(GIOChannel *channel, GIOCondition cond,
+ gpointer user_data)
+{
+ /*
+ * the total time the led is active (0xff means forever)
+ * | duty_length: cycle time in deciseconds (0 - "blink very fast")
+ * | | ??? (Maybe a phase shift or duty_length multiplier?)
+ * | | | % of duty_length led is off (0xff means 100%)
+ * | | | | % of duty_length led is on (0xff means 100%)
+ * | | | | |
+ * 0xff, 0x27, 0x10, 0x00, 0x32,
+ */
+ uint8_t leds_report[] = {
+ 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, /* rumble values TBD */
+ 0x00, 0x00, 0x00, 0x00, 0x00, /* LED_1=0x02, LED_2=0x04 ... */
+ 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_4 */
+ 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_3 */
+ 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_2 */
+ 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_1 */
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ int number = GPOINTER_TO_INT(user_data);
+ int ret;
+ int fd;
+
+ if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL))
+ return FALSE;
+
+ DBG("number %d", number);
+
+ /* TODO we could support up to 10 (1 + 2 + 3 + 4) */
+ if (number > 7)
+ return FALSE;
+
+ if (number > 4) {
+ leds_report[10] |= 0x10;
+ number -= 4;
+ }
+
+ leds_report[10] |= 0x01 << number;
+
+ fd = g_io_channel_unix_get_fd(channel);
+
+ ret = write(fd, leds_report, sizeof(leds_report));
+ if (ret == sizeof(leds_report))
+ return FALSE;
+
+ if (ret < 0)
+ error("sixaxis: failed to set LEDS (%s)", strerror(errno));
+ else
+ error("sixaxis: failed to set LEDS (%d bytes written)", ret);
+
+ return FALSE;
+}
+
static void setup_device(int fd, int index, struct btd_adapter *adapter)
{
char device_addr[18], master_addr[18], adapter_addr[18];
@@ -167,6 +224,69 @@ static void setup_device(int fd, int index, struct btd_adapter *adapter)
btd_device_set_trusted(device, TRUE);
}
+static int get_js_number(struct udev_device *udevice)
+{
+ struct udev_list_entry *devices, *dev_list_entry;
+ struct udev_enumerate *enumerate;
+ struct udev_device *hid_parent;
+ const char *hidraw_node;
+ const char *hid_phys;
+ int number = 0;
+
+ hid_parent = udev_device_get_parent_with_subsystem_devtype(udevice,
+ "hid", NULL);
+
+ hid_phys = udev_device_get_property_value(hid_parent, "HID_PHYS");
+ hidraw_node = udev_device_get_devnode(udevice);
+ if (!hid_phys || !hidraw_node)
+ return 0;
+
+ enumerate = udev_enumerate_new(udev_device_get_udev(udevice));
+ udev_enumerate_add_match_sysname(enumerate, "js*");
+ udev_enumerate_scan_devices(enumerate);
+ devices = udev_enumerate_get_list_entry(enumerate);
+
+ udev_list_entry_foreach(dev_list_entry, devices) {
+ struct udev_device *input_parent;
+ struct udev_device *js_dev;
+ const char *input_phys;
+ const char *devname;
+
+ devname = udev_list_entry_get_name(dev_list_entry);
+ js_dev = udev_device_new_from_syspath(
+ udev_device_get_udev(udevice),
+ devname);
+
+ input_parent = udev_device_get_parent_with_subsystem_devtype(
+ js_dev, "input", NULL);
+ if (!input_parent)
+ goto next;
+
+ /* check if this is the joystick relative to the hidraw device
+ * above */
+ input_phys = udev_device_get_sysattr_value(input_parent,
+ "phys");
+ if (!input_phys)
+ goto next;
+
+ if (!strcmp(input_phys, hid_phys)) {
+ number = atoi(udev_device_get_sysnum(js_dev));
+
+ /* joystick numbers start from 0, leds from 1 */
+ number++;
+
+ udev_device_unref(js_dev);
+ break;
+ }
+next:
+ udev_device_unref(js_dev);
+ }
+
+ udev_enumerate_unref(enumerate);
+
+ return number;
+}
+
static int get_supported_device(struct udev_device *udevice, uint16_t *bus)
{
struct udev_device *hid_parent;
@@ -195,6 +315,7 @@ static int get_supported_device(struct udev_device *udevice, uint16_t *bus)
static void device_added(struct udev_device *udevice)
{
struct btd_adapter *adapter;
+ GIOChannel *io;
uint16_t bus;
int index;
int fd;
@@ -215,10 +336,26 @@ static void device_added(struct udev_device *udevice)
if (fd < 0)
return;
- if (bus == BUS_USB)
+ io = g_io_channel_unix_new(fd);
+
+ switch (bus) {
+ case BUS_USB:
setup_device(fd, index, adapter);
+ break;
+ case BUS_BLUETOOTH:
+ /* wait for events before setting leds */
+ g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ setup_leds,
+ GINT_TO_POINTER(get_js_number(udevice)));
+
+ break;
+ default:
+ DBG("uknown bus type (%u)", bus);
+ break;
+ }
- close(fd);
+ g_io_channel_set_close_on_unref(io, TRUE);
+ g_io_channel_unref(io);
}
static gboolean monitor_watch(GIOChannel *source, GIOCondition condition,
--
1.8.5
^ permalink raw reply related
* [PATCH 0/4] more sixaxis goodies
From: Szymon Janc @ 2013-12-01 13:41 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
Hi,
This adds support for setting PS3 controller LEDs both over Bluetooth
and USB. More details in commits messages.
One thing I noticed is that setting LEDs over Bluetooth fails on kernel
3.10+ (write always returns 0). Could this be related to HIDP related
work that was merged in 3.10?
Comments and testing are welcome.
--
BR
Szymon Janc
Szymon Janc (4):
sixaxis: Add support for setting PS3 controller LEDs
Rename device_is_connected to btd_device_is_connected
sixaxis: Skip controller setup if already connected over Bluetooth
sixaxis: Add support for setting LEDs when connected over USB
plugins/sixaxis.c | 164 +++++++++++++++++++++++++++++++++++++++++++++---
profiles/input/device.c | 4 +-
src/adapter.c | 6 +-
src/device.c | 6 +-
src/device.h | 2 +-
5 files changed, 165 insertions(+), 17 deletions(-)
--
1.8.5
^ permalink raw reply
* have to re-pair mouse every few hours
From: Brian J. Murrell @ 2013-11-30 20:37 UTC (permalink / raw)
To: linux-bluetooth
[-- Attachment #1: Type: text/plain, Size: 1066 bytes --]
Hi,
I'm using a Microsoft Sculpt Touch Mouse on a Fedora 19 machine
(kernel-3.11.9-200.fc19.x86_64 and bluez-4.101-9.fc19.x86_64) with a:
Bus 002 Device 019: ID 0a5c:2148 Broadcom Corp. BCM92046DG-CL1ROM Bluetooth 2.1 Adapter
bluetooth adapter. This exact same configuration worked for months just
fine with a Logitech bluetooth mouse. But sadly that mouse was crap
(second one to fail within the warranty period of one of them) so
replaced it with this MS one.
The problem with this MS mouse is that it just goes AWOL and needs to be
delete and re-paired with the machine every few hours. Typically it's
after I have gotten up from the computer and have come back to it. But
I have also had it just happen while using it.
When this happens, the messages log reports messages such as:
Nov 30 12:42:03 pc kernel: [2500032.028982] Bluetooth: Unexpected continuation frame (len 0)
Nov 30 12:42:03 pc kernel: [2500032.115027] Bluetooth: Unexpected continuation frame (len 0)
Any ideas what the problem might be here?
Cheers,
b.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply
* Re: [PATCH_v5 0/6] Refactor bnep code and implement pan methods
From: Luiz Augusto von Dentz @ 2013-11-29 15:16 UTC (permalink / raw)
To: Ravi kumar Veeramally; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1385734845-9725-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Hi Ravi,
On Fri, Nov 29, 2013 at 4:20 PM, Ravi kumar Veeramally
<ravikumar.veeramally@linux.intel.com> wrote:
> v5: Renamed strcut network_peer to pan_device as per Luiz comments.
>
> v4: Fixed Luiz comments (discussed in irc). Merge patch 1 and 2.
> Pass fd in bnep_connect instead of GIOChannel.
>
> v3: Fixed Anderson and Luiz comments and solved rebased conflicts.
>
> v2: Refactored profiles/network/common.* as per Johan's comments
> (renaming common.c|h to bnep.c|h and moving bnep related code to
> bnep.c ro reduce redundancy in profiles/netowrk/connection.c and
> android/pan.c)
>
> v1: This patch set supports PANU role with a minor fix in android. Added
> CAP_NET_RAW capability for bnep services. Creates bnep connection and
> up the inreface on connect call and free the device on disconnect call.
> Interface name(bnepX) will be notified on control state cb. Android
> environment will create IP address with dhcp calls.
>
> Ravi kumar Veeramally (6):
> profiles/network: Refactor bnep connection setup functionality
> profiles/network: Rename common.c|h to bnep.c|h
> android/pan: Implement pan connect method in daemon
> android/pan: Implement pan disconnect method in daemon
> android/pan: Implement the get local role method in daemon
> android: Add reasons for adding capabilites to process
>
> Makefile.plugins | 2 +-
> android/Android.mk | 2 +
> android/Makefile.am | 3 +-
> android/main.c | 3 +
> android/pan.c | 253 ++++++++++++++++++++++++++++++++--
> profiles/network/{common.c => bnep.c} | 197 +++++++++++++++++++++++++-
> profiles/network/{common.h => bnep.h} | 5 +
> profiles/network/connection.c | 174 ++---------------------
> profiles/network/manager.c | 2 +-
> profiles/network/server.c | 5 +-
> 10 files changed, 468 insertions(+), 178 deletions(-)
> rename profiles/network/{common.c => bnep.c} (58%)
> rename profiles/network/{common.h => bnep.h} (87%)
>
> --
> 1.8.3.2
Applied, please have a look as I renamed a few other things and I
found that we were sending uninitialized data while testing.
--
Luiz Augusto von Dentz
^ permalink raw reply
* [PATCH_v5 6/6] android: Add reasons for adding capabilites to process
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385734845-9725-1-git-send-email-ravikumar.veeramally@linux.intel.com>
CAP_NET_ADMIN: Allow use of MGMT interface
CAP_NET_BIND_SERVICE: Allow use of privileged PSM
CAP_NET_RAW: Allow use of bnep ioctl calls
---
android/main.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/android/main.c b/android/main.c
index 3a14af5..eedca58 100644
--- a/android/main.c
+++ b/android/main.c
@@ -534,6 +534,9 @@ static bool set_capabilities(void)
header.version = _LINUX_CAPABILITY_VERSION;
header.pid = 0;
+ /* CAP_NET_ADMIN: Allow use of MGMT interface
+ * CAP_NET_BIND_SERVICE: Allow use of privileged PSM
+ * CAP_NET_RAW: Allow use of bnep ioctl calls */
cap.effective = cap.permitted =
CAP_TO_MASK(CAP_NET_RAW) |
CAP_TO_MASK(CAP_NET_ADMIN) |
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v5 5/6] android/pan: Implement the get local role method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385734845-9725-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Returns local role of the device (NONE, PANU or NAP).
---
android/pan.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/android/pan.c b/android/pan.c
index 7093e4c..9ff14f3 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -278,9 +278,15 @@ static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
{
- DBG("Not Implemented");
+ struct hal_rsp_pan_get_role rsp;
- return HAL_STATUS_FAILED;
+ DBG("");
+
+ rsp.local_role = local_role;
+ ipc_send_rsp_full(HAL_SERVICE_ID_PAN, HAL_OP_PAN_GET_ROLE, sizeof(rsp),
+ &rsp, -1);
+
+ return HAL_STATUS_SUCCESS;
}
void bt_pan_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v5 4/6] android/pan: Implement pan disconnect method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385734845-9725-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Disconnect ongoing PANU role connection betweek devices, free
the device and notify the connection state.
---
android/pan.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/android/pan.c b/android/pan.c
index 031dfff..7093e4c 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -238,9 +238,35 @@ static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
uint16_t len)
{
- DBG("Not Implemented");
+ struct pan_device *dev;
+ GSList *l;
+ bdaddr_t dst;
- return HAL_STATUS_FAILED;
+ DBG("");
+
+ if (len < sizeof(*cmd))
+ return HAL_STATUS_INVALID;
+
+ android2bdaddr(&cmd->bdaddr, &dst);
+
+ l = g_slist_find_custom(peers, &dst, peer_cmp);
+ if (!l)
+ return HAL_STATUS_FAILED;
+
+ dev = l->data;
+
+ if (dev->watch) {
+ g_source_remove(dev->watch);
+ dev->watch = 0;
+ }
+
+ bnep_if_down(dev->dev);
+ bnep_kill_connection(&dst);
+
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+ pan_device_free(dev);
+
+ return HAL_STATUS_SUCCESS;
}
static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v5 3/6] android/pan: Implement pan connect method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385734845-9725-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Implements the PAN connect method in android daemon with PANU role
only. Setting up the bnep environment, adds connection and makes
bnep interface up are part of bnep_connect call. Notifies bnep
interface on control state call back and connection status on
connection state call back.
---
android/Android.mk | 2 +
android/Makefile.am | 3 +-
android/pan.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 216 insertions(+), 8 deletions(-)
diff --git a/android/Android.mk b/android/Android.mk
index c4d722d..549613c 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -42,6 +42,7 @@ LOCAL_SRC_FILES := \
../lib/hci.c \
../btio/btio.c \
../src/sdp-client.c \
+ ../profiles/network/bnep.c \
LOCAL_C_INCLUDES := \
$(call include-path-for, glib) \
@@ -66,6 +67,7 @@ lib_headers := \
sdp.h \
rfcomm.h \
sco.h \
+ bnep.h \
$(shell mkdir -p $(LOCAL_PATH)/../lib/bluetooth)
diff --git a/android/Makefile.am b/android/Makefile.am
index 15ecf35..df04762 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -24,7 +24,8 @@ android_bluetoothd_SOURCES = android/main.c \
android/socket.h android/socket.c \
android/pan.h android/pan.c \
btio/btio.h btio/btio.c \
- src/sdp-client.h src/sdp-client.c
+ src/sdp-client.h src/sdp-client.c \
+ profiles/network/bnep.h profiles/network/bnep.c
android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
diff --git a/android/pan.c b/android/pan.c
index ea15637..031dfff 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -29,35 +29,228 @@
#include <fcntl.h>
#include <glib.h>
+#include "btio/btio.h"
#include "lib/bluetooth.h"
+#include "lib/bnep.h"
+#include "lib/sdp.h"
+#include "lib/sdp_lib.h"
+#include "src/glib-helper.h"
+#include "profiles/network/bnep.h"
+
#include "log.h"
#include "pan.h"
#include "hal-msg.h"
#include "ipc.h"
+#include "utils.h"
+#include "bluetooth.h"
-static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
+static bdaddr_t adapter_addr;
+GSList *peers = NULL;
+uint8_t local_role = HAL_PAN_ROLE_NONE;
+
+struct pan_device {
+ char dev[16];
+ bdaddr_t dst;
+ uint8_t conn_state;
+ uint8_t role;
+ GIOChannel *io;
+ guint watch;
+};
+
+static int peer_cmp(gconstpointer s, gconstpointer user_data)
{
- DBG("Not Implemented");
+ const struct pan_device *dev = s;
+ const bdaddr_t *dst = user_data;
- return HAL_STATUS_FAILED;
+ return bacmp(&dev->dst, dst);
}
-static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
+static void pan_device_free(struct pan_device *dev)
+{
+ local_role = HAL_PAN_ROLE_NONE;
+
+ if (dev->watch > 0) {
+ g_source_remove(dev->watch);
+ dev->watch = 0;
+ }
+
+ if (dev->io) {
+ g_io_channel_unref(dev->io);
+ dev->io = NULL;
+ }
+
+ peers = g_slist_remove(peers, dev);
+ g_free(dev);
+ dev = NULL;
+}
+
+static void bt_pan_notify_conn_state(struct pan_device *dev, uint8_t state)
+{
+ struct hal_ev_pan_conn_state ev;
+ char addr[18];
+
+ if (dev->conn_state == state)
+ return;
+
+ dev->conn_state = state;
+ ba2str(&dev->dst, addr);
+ DBG("device %s state %u", addr, state);
+
+ bdaddr2android(&dev->dst, ev.bdaddr);
+ ev.state = state;
+ ev.local_role = local_role;
+ ev.remote_role = dev->role;
+ ev.status = HAL_STATUS_SUCCESS;
+
+ ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CONN_STATE, sizeof(ev),
+ &ev);
+}
+
+static void bt_pan_notify_ctrl_state(struct pan_device *dev, uint8_t state)
+{
+ struct hal_ev_pan_ctrl_state ev;
+
+ DBG("");
+
+ ev.state = state;
+ ev.local_role = local_role;
+ ev.status = HAL_STATUS_SUCCESS;
+ memcpy(ev.name, dev->dev, sizeof(dev->dev));
+
+ ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CTRL_STATE, sizeof(ev),
+ &ev);
+}
+
+static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ struct pan_device *dev = data;
+
+ DBG("%s disconnected", dev->dev);
+
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+ pan_device_free(dev);
+
+ return FALSE;
+}
+
+static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
+{
+ struct pan_device *dev = data;
+
+ DBG("");
+
+ if (err < 0) {
+ error("bnep connect req failed: %s", strerror(-err));
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+ pan_device_free(dev);
+ return;
+ }
+
+ memcpy(dev->dev, iface, sizeof(dev->dev));
+
+ DBG("%s connected", dev->dev);
+
+ bt_pan_notify_ctrl_state(dev, HAL_PAN_CTRL_ENABLED);
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTED);
+
+ dev->watch = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ bnep_watchdog_cb, dev);
+ g_io_channel_unref(dev->io);
+ dev->io = NULL;
+}
+
+static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
+{
+ struct pan_device *dev = data;
+ uint16_t src, dst;
+ int perr, sk;
+
+ DBG("");
+
+ if (err) {
+ error("%s", err->message);
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+ pan_device_free(dev);
+ }
+
+ src = (local_role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP : BNEP_SVC_PANU;
+ dst = (dev->role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP : BNEP_SVC_PANU;
+ sk = g_io_channel_unix_get_fd(dev->io);
+
+ perr = bnep_connect(sk, src, dst, bnep_conn_cb, dev);
+ if (perr < 0) {
+ error("bnep connect req failed: %s", strerror(-perr));
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
+ pan_device_free(dev);
+ return;
+ }
+}
+
+static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
+{
+ struct pan_device *dev;
+ bdaddr_t dst;
+ char addr[18];
+ GSList *l;
+ GError *gerr = NULL;
+
+ DBG("");
+
+ if (len < sizeof(*cmd))
+ return HAL_STATUS_INVALID;
+
+ android2bdaddr(&cmd->bdaddr, &dst);
+
+ l = g_slist_find_custom(peers, &dst, peer_cmp);
+ if (l)
+ return HAL_STATUS_FAILED;
+
+ dev = g_new0(struct pan_device, 1);
+ bacpy(&dev->dst, &dst);
+ local_role = cmd->local_role;
+ dev->role = cmd->remote_role;
+
+ ba2str(&dev->dst, addr);
+ DBG("connecting to %s %s", addr, dev->dev);
+
+ dev->io = bt_io_connect(connect_cb, dev, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+ BT_IO_OPT_DEST_BDADDR, &dev->dst,
+ BT_IO_OPT_PSM, BNEP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_OMTU, BNEP_MTU,
+ BT_IO_OPT_IMTU, BNEP_MTU,
+ BT_IO_OPT_INVALID);
+ if (!dev->io) {
+ error("%s", gerr->message);
+ g_error_free(gerr);
+ g_free(dev);
+ return HAL_STATUS_FAILED;
+ }
+
+ peers = g_slist_append(peers, dev);
+ bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTING);
+
+ return HAL_STATUS_SUCCESS;
+}
+
+static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
+ uint16_t len)
{
DBG("Not Implemented");
return HAL_STATUS_FAILED;
}
-static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
+static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
{
DBG("Not Implemented");
return HAL_STATUS_FAILED;
}
-static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
- uint16_t len)
+static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
{
DBG("Not Implemented");
@@ -91,12 +284,24 @@ void bt_pan_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
bool bt_pan_register(const bdaddr_t *addr)
{
+ int err;
+
DBG("");
+ bacpy(&adapter_addr, addr);
+
+ err = bnep_init();
+ if (err) {
+ error("bnep init failed");
+ return false;
+ }
+
return true;
}
void bt_pan_unregister(void)
{
DBG("");
+
+ bnep_cleanup();
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v5 2/6] profiles/network: Rename common.c|h to bnep.c|h
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385734845-9725-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Files common.c|h contains only bnep related code, it makes
more sence with bnep.c|h.
---
Makefile.plugins | 2 +-
profiles/network/{common.c => bnep.c} | 2 +-
profiles/network/{common.h => bnep.h} | 0
profiles/network/connection.c | 2 +-
profiles/network/manager.c | 2 +-
profiles/network/server.c | 2 +-
6 files changed, 5 insertions(+), 5 deletions(-)
rename profiles/network/{common.c => bnep.c} (99%)
rename profiles/network/{common.h => bnep.h} (100%)
diff --git a/Makefile.plugins b/Makefile.plugins
index f5025e9..6a1ddbf 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -47,7 +47,7 @@ builtin_sources += profiles/audio/control.h profiles/audio/control.c \
builtin_modules += network
builtin_sources += profiles/network/manager.c \
- profiles/network/common.h profiles/network/common.c \
+ profiles/network/bnep.h profiles/network/bnep.c \
profiles/network/server.h profiles/network/server.c \
profiles/network/connection.h \
profiles/network/connection.c
diff --git a/profiles/network/common.c b/profiles/network/bnep.c
similarity index 99%
rename from profiles/network/common.c
rename to profiles/network/bnep.c
index 71154c8..0a719a2 100644
--- a/profiles/network/common.c
+++ b/profiles/network/bnep.c
@@ -43,7 +43,7 @@
#include <glib.h>
#include "log.h"
-#include "common.h"
+#include "bnep.h"
#include "lib/uuid.h"
#define CON_SETUP_RETRIES 3
diff --git a/profiles/network/common.h b/profiles/network/bnep.h
similarity index 100%
rename from profiles/network/common.h
rename to profiles/network/bnep.h
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index d100580..9aff319 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -47,7 +47,7 @@
#include "service.h"
#include "error.h"
-#include "common.h"
+#include "bnep.h"
#include "connection.h"
#define NETWORK_PEER_INTERFACE "org.bluez.Network1"
diff --git a/profiles/network/manager.c b/profiles/network/manager.c
index ab4224d..8ac2dec 100644
--- a/profiles/network/manager.c
+++ b/profiles/network/manager.c
@@ -43,7 +43,7 @@
#include "device.h"
#include "profile.h"
#include "service.h"
-#include "common.h"
+#include "bnep.h"
#include "connection.h"
#include "server.h"
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 3a7e52a..b3aab11 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -48,7 +48,7 @@
#include "error.h"
#include "sdpd.h"
-#include "common.h"
+#include "bnep.h"
#include "server.h"
#define NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer1"
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v5 1/6] profiles/network: Refactor bnep connection setup functionality
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385734845-9725-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Moving bnep connection setup related functionality to common.c.
Provided bnep_connect call with bnep_connect_cb for status and
bnep interface name. It will be simple if someone want to utilize
this call otherwise they have to reimplement similar functionality
with minimal changes (e.g. android/pan).
---
profiles/network/common.c | 195 +++++++++++++++++++++++++++++++++++++++++-
profiles/network/common.h | 5 ++
profiles/network/connection.c | 172 +++----------------------------------
profiles/network/server.c | 3 -
4 files changed, 211 insertions(+), 164 deletions(-)
diff --git a/profiles/network/common.c b/profiles/network/common.c
index 0b291bd..71154c8 100644
--- a/profiles/network/common.c
+++ b/profiles/network/common.c
@@ -46,6 +46,9 @@
#include "common.h"
#include "lib/uuid.h"
+#define CON_SETUP_RETRIES 3
+#define CON_SETUP_TO 9
+
static int ctl;
static struct {
@@ -59,6 +62,35 @@ static struct {
{ NULL }
};
+struct __service_16 {
+ uint16_t dst;
+ uint16_t src;
+} __attribute__ ((packed));
+
+struct bnep_conn {
+ GIOChannel *io;
+ uint16_t src;
+ uint16_t dst;
+ guint attempts;
+ guint setup_to;
+ void *data;
+ bnep_connect_cb conn_cb;
+};
+
+static void free_bnep_connect(struct bnep_conn *bc)
+{
+ if (!bc)
+ return;
+
+ if (bc->io) {
+ g_io_channel_unref(bc->io);
+ bc->io = NULL;
+ }
+
+ g_free(bc);
+ bc = NULL;
+}
+
uint16_t bnep_service_id(const char *svc)
{
int i;
@@ -149,9 +181,9 @@ int bnep_connadd(int sk, uint16_t role, char *dev)
{
struct bnep_connadd_req req;
+ memset(dev, 0, 16);
memset(&req, 0, sizeof(req));
- strncpy(req.device, dev, 16);
- req.device[15] = '\0';
+ strcpy(req.device, "bnep%d");
req.sock = sk;
req.role = role;
if (ioctl(ctl, BNEPCONNADD, &req) < 0) {
@@ -215,6 +247,165 @@ int bnep_if_down(const char *devname)
return 0;
}
+static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ struct bnep_conn *bc = data;
+ struct bnep_control_rsp *rsp;
+ struct timeval timeo;
+ char pkt[BNEP_MTU];
+ char iface[16];
+ ssize_t r;
+ int sk;
+
+ if (cond & G_IO_NVAL)
+ goto failed;
+
+ if (bc->setup_to > 0) {
+ g_source_remove(bc->setup_to);
+ bc->setup_to = 0;
+ }
+
+ if (cond & (G_IO_HUP | G_IO_ERR)) {
+ error("Hangup or error on l2cap server socket");
+ goto failed;
+ }
+
+ sk = g_io_channel_unix_get_fd(chan);
+ memset(pkt, 0, BNEP_MTU);
+ r = read(sk, pkt, sizeof(pkt) - 1);
+ if (r < 0) {
+ error("IO Channel read error");
+ goto failed;
+ }
+
+ if (r == 0) {
+ error("No packet received on l2cap socket");
+ goto failed;
+ }
+
+ errno = EPROTO;
+
+ if ((size_t) r < sizeof(*rsp)) {
+ error("Packet received is not bnep type");
+ goto failed;
+ }
+
+ rsp = (void *) pkt;
+ if (rsp->type != BNEP_CONTROL) {
+ error("Packet received is not bnep type");
+ goto failed;
+ }
+
+ if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
+ return TRUE;
+
+ r = ntohs(rsp->resp);
+ if (r != BNEP_SUCCESS) {
+ error("bnep failed");
+ goto failed;
+ }
+
+ memset(&timeo, 0, sizeof(timeo));
+ timeo.tv_sec = 0;
+ setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
+
+ sk = g_io_channel_unix_get_fd(bc->io);
+ if (bnep_connadd(sk, bc->src, iface)) {
+ error("bnep conn could not be added");
+ goto failed;
+ }
+
+ if (bnep_if_up(iface)) {
+ error("could not up %s", iface);
+ goto failed;
+ }
+
+ bc->conn_cb(chan, iface, 0, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+
+failed:
+ bc->conn_cb(NULL, NULL, -EIO, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+}
+
+static int bnep_setup_conn_req(struct bnep_conn *bc)
+{
+ struct bnep_setup_conn_req *req;
+ struct __service_16 *s;
+ unsigned char pkt[BNEP_MTU];
+ int fd;
+
+ /* Send request */
+ req = (void *) pkt;
+ req->type = BNEP_CONTROL;
+ req->ctrl = BNEP_SETUP_CONN_REQ;
+ req->uuid_size = 2; /* 16bit UUID */
+ s = (void *) req->service;
+ s->src = htons(bc->src);
+ s->dst = htons(bc->dst);
+
+ fd = g_io_channel_unix_get_fd(bc->io);
+ if (write(fd, pkt, sizeof(*req) + sizeof(*s)) < 0) {
+ error("bnep connection req send failed: %s", strerror(errno));
+ return -errno;
+ }
+
+ bc->attempts++;
+
+ return 0;
+}
+
+static gboolean bnep_conn_req_to(gpointer user_data)
+{
+ struct bnep_conn *bc = user_data;
+
+ if (bc->attempts == CON_SETUP_RETRIES) {
+ error("Too many bnep connection attempts");
+ } else {
+ error("bnep connection setup TO, retrying...");
+ if (bnep_setup_conn_req(bc) == 0)
+ return TRUE;
+ }
+
+ bc->conn_cb(NULL, NULL, -ETIMEDOUT, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+}
+
+int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
+ void *data)
+{
+ struct bnep_conn *bc;
+ int err;
+
+ if (!conn_cb)
+ return -EINVAL;
+
+ bc = g_new0(struct bnep_conn, 1);
+ bc->io = g_io_channel_unix_new(sk);
+ bc->attempts = 0;
+ bc->src = src;
+ bc->dst = dst;
+ bc->conn_cb = conn_cb;
+ bc->data = data;
+
+ err = bnep_setup_conn_req(bc);
+ if (err < 0)
+ return err;
+
+ bc->setup_to = g_timeout_add_seconds(CON_SETUP_TO,
+ bnep_conn_req_to, bc);
+ g_io_add_watch(bc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ bnep_setup_cb, bc);
+ return 0;
+}
+
int bnep_add_to_bridge(const char *devname, const char *bridge)
{
int ifindex;
diff --git a/profiles/network/common.h b/profiles/network/common.h
index 9a8caac..9043e46 100644
--- a/profiles/network/common.h
+++ b/profiles/network/common.h
@@ -35,3 +35,8 @@ int bnep_if_up(const char *devname);
int bnep_if_down(const char *devname);
int bnep_add_to_bridge(const char *devname, const char *bridge);
int bnep_del_from_bridge(const char *devname, const char *bridge);
+
+typedef void (*bnep_connect_cb) (GIOChannel *chan, char *iface, int err,
+ void *data);
+int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
+ void *data);
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 5966268..d100580 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -51,8 +51,6 @@
#include "connection.h"
#define NETWORK_PEER_INTERFACE "org.bluez.Network1"
-#define CON_SETUP_RETRIES 3
-#define CON_SETUP_TO 9
typedef enum {
CONNECTED,
@@ -73,16 +71,9 @@ struct network_conn {
GIOChannel *io;
guint dc_id;
struct network_peer *peer;
- guint attempt_cnt;
- guint timeout_source;
DBusMessage *connect;
};
-struct __service_16 {
- uint16_t dst;
- uint16_t src;
-} __attribute__ ((packed));
-
static GSList *peers = NULL;
static uint16_t get_service_id(struct btd_service *service)
@@ -163,11 +154,6 @@ static void local_connect_cb(struct network_conn *nc, int err)
static void cancel_connection(struct network_conn *nc, int err)
{
- if (nc->timeout_source > 0) {
- g_source_remove(nc->timeout_source);
- nc->timeout_source = 0;
- }
-
btd_service_connecting_complete(nc->service, err);
if (nc->connect)
local_connect_cb(nc, err);
@@ -200,83 +186,24 @@ static void disconnect_cb(struct btd_device *device, gboolean removal,
connection_destroy(NULL, user_data);
}
-static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
- gpointer data)
+static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
{
struct network_conn *nc = data;
- struct bnep_control_rsp *rsp;
- struct timeval timeo;
- char pkt[BNEP_MTU];
- ssize_t r;
- int sk;
const char *path;
DBusConnection *conn;
- DBG("cond %u", cond);
-
- if (cond & G_IO_NVAL)
- return FALSE;
-
- if (nc->timeout_source > 0) {
- g_source_remove(nc->timeout_source);
- nc->timeout_source = 0;
- }
-
- if (cond & (G_IO_HUP | G_IO_ERR)) {
- error("Hangup or error on l2cap server socket");
- goto failed;
- }
-
- sk = g_io_channel_unix_get_fd(chan);
-
- memset(pkt, 0, BNEP_MTU);
- r = read(sk, pkt, sizeof(pkt) -1);
- if (r < 0) {
- error("IO Channel read error");
- goto failed;
- }
-
- if (r == 0) {
- error("No packet received on l2cap socket");
- goto failed;
- }
-
- errno = EPROTO;
-
- if ((size_t) r < sizeof(*rsp)) {
- error("Packet received is not bnep type");
- goto failed;
- }
-
- rsp = (void *) pkt;
- if (rsp->type != BNEP_CONTROL) {
- error("Packet received is not bnep type");
- goto failed;
- }
-
- if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
- return TRUE;
-
- r = ntohs(rsp->resp);
-
- if (r != BNEP_SUCCESS) {
- error("bnep failed");
- goto failed;
- }
-
- memset(&timeo, 0, sizeof(timeo));
- timeo.tv_sec = 0;
-
- setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
+ DBG("");
- if (bnep_connadd(sk, BNEP_SVC_PANU, nc->dev)) {
- error("%s could not be added", nc->dev);
+ if (err < 0) {
+ error("connect failed %s", strerror(-err));
goto failed;
}
- bnep_if_up(nc->dev);
+ info("%s connected", nc->dev);
+ memcpy(nc->dev, iface, sizeof(nc->dev));
btd_service_connecting_complete(nc->service, 0);
+
if (nc->connect)
local_connect_cb(nc, 0);
@@ -292,101 +219,30 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
nc->state = CONNECTED;
nc->dc_id = device_add_disconnect_watch(nc->peer->device, disconnect_cb,
- nc, NULL);
-
- info("%s connected", nc->dev);
- /* Start watchdog */
+ nc, NULL);
g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) bnep_watchdog_cb, nc);
+ bnep_watchdog_cb, nc);
g_io_channel_unref(nc->io);
nc->io = NULL;
- return FALSE;
+ return;
failed:
cancel_connection(nc, -EIO);
-
- return FALSE;
-}
-
-static int bnep_send_conn_req(struct network_conn *nc)
-{
- struct bnep_setup_conn_req *req;
- struct __service_16 *s;
- unsigned char pkt[BNEP_MTU];
- int fd;
-
- DBG("");
-
- /* Send request */
- req = (void *) pkt;
- req->type = BNEP_CONTROL;
- req->ctrl = BNEP_SETUP_CONN_REQ;
- req->uuid_size = 2; /* 16bit UUID */
- s = (void *) req->service;
- s->dst = htons(nc->id);
- s->src = htons(BNEP_SVC_PANU);
-
- fd = g_io_channel_unix_get_fd(nc->io);
- if (write(fd, pkt, sizeof(*req) + sizeof(*s)) < 0) {
- int err = -errno;
- error("bnep connection req send failed: %s", strerror(errno));
- return err;
- }
-
- nc->attempt_cnt++;
-
- return 0;
-}
-
-static gboolean bnep_conn_req_to(gpointer user_data)
-{
- struct network_conn *nc;
-
- nc = user_data;
- if (nc->attempt_cnt == CON_SETUP_RETRIES) {
- error("Too many bnep connection attempts");
- } else {
- error("bnep connection setup TO, retrying...");
- if (bnep_send_conn_req(nc) == 0)
- return TRUE;
- }
-
- cancel_connection(nc, -ETIMEDOUT);
-
- return FALSE;
-}
-
-static int bnep_connect(struct network_conn *nc)
-{
- int err;
-
- nc->attempt_cnt = 0;
-
- err = bnep_send_conn_req(nc);
- if (err < 0)
- return err;
-
- nc->timeout_source = g_timeout_add_seconds(CON_SETUP_TO,
- bnep_conn_req_to, nc);
-
- g_io_add_watch(nc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- bnep_setup_cb, nc);
-
- return 0;
}
static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
{
struct network_conn *nc = data;
- int perr;
+ int sk, perr;
if (err) {
error("%s", err->message);
goto failed;
}
- perr = bnep_connect(nc);
+ sk = g_io_channel_unix_get_fd(nc->io);
+ perr = bnep_connect(sk, BNEP_SVC_PANU, nc->id, bnep_conn_cb, nc);
if (perr < 0) {
error("bnep connect(): %s (%d)", strerror(-perr), -perr);
goto failed;
@@ -692,8 +548,6 @@ int connection_register(struct btd_service *service)
nc = g_new0(struct network_conn, 1);
nc->id = id;
- memset(nc->dev, 0, sizeof(nc->dev));
- strcpy(nc->dev, "bnep%d");
nc->service = btd_service_ref(service);
nc->state = DISCONNECTED;
nc->peer = peer;
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 0050b30..3a7e52a 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -269,9 +269,6 @@ static int server_connadd(struct network_server *ns,
char devname[16];
int err, nsk;
- memset(devname, 0, sizeof(devname));
- strcpy(devname, "bnep%d");
-
nsk = g_io_channel_unix_get_fd(session->io);
err = bnep_connadd(nsk, dst_role, devname);
if (err < 0)
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v5 0/6] Refactor bnep code and implement pan methods
From: Ravi kumar Veeramally @ 2013-11-29 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
v5: Renamed strcut network_peer to pan_device as per Luiz comments.
v4: Fixed Luiz comments (discussed in irc). Merge patch 1 and 2.
Pass fd in bnep_connect instead of GIOChannel.
v3: Fixed Anderson and Luiz comments and solved rebased conflicts.
v2: Refactored profiles/network/common.* as per Johan's comments
(renaming common.c|h to bnep.c|h and moving bnep related code to
bnep.c ro reduce redundancy in profiles/netowrk/connection.c and
android/pan.c)
v1: This patch set supports PANU role with a minor fix in android. Added
CAP_NET_RAW capability for bnep services. Creates bnep connection and
up the inreface on connect call and free the device on disconnect call.
Interface name(bnepX) will be notified on control state cb. Android
environment will create IP address with dhcp calls.
Ravi kumar Veeramally (6):
profiles/network: Refactor bnep connection setup functionality
profiles/network: Rename common.c|h to bnep.c|h
android/pan: Implement pan connect method in daemon
android/pan: Implement pan disconnect method in daemon
android/pan: Implement the get local role method in daemon
android: Add reasons for adding capabilites to process
Makefile.plugins | 2 +-
android/Android.mk | 2 +
android/Makefile.am | 3 +-
android/main.c | 3 +
android/pan.c | 253 ++++++++++++++++++++++++++++++++--
profiles/network/{common.c => bnep.c} | 197 +++++++++++++++++++++++++-
profiles/network/{common.h => bnep.h} | 5 +
profiles/network/connection.c | 174 ++---------------------
profiles/network/manager.c | 2 +-
profiles/network/server.c | 5 +-
10 files changed, 468 insertions(+), 178 deletions(-)
rename profiles/network/{common.c => bnep.c} (58%)
rename profiles/network/{common.h => bnep.h} (87%)
--
1.8.3.2
^ permalink raw reply
* [RFC] android/doc: Add socket-api.txt document
From: Andrei Emeltchenko @ 2013-11-29 13:28 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Document describes how socket HAL is working.
---
android/socket-api.txt | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 android/socket-api.txt
diff --git a/android/socket-api.txt b/android/socket-api.txt
new file mode 100644
index 0000000..9f622f9
--- /dev/null
+++ b/android/socket-api.txt
@@ -0,0 +1,61 @@
+Android Socket protocol for Bluetooth
+=====================================
+
+Since Android switched from BlueZ (where sockets where nicely implemented) to
+Bluedroid user space stack there is a need to emulate bluetooth sockets.
+
+Android Bluetooth Socket Hardware Abstraction Layer (HAL) bt_sock.h has
+only 2 functions:
+
+static btsock_interface_t sock_if = {
+ sizeof(sock_if),
+ sock_listen,
+ sock_connect
+};
+
+with following parameters:
+
+sock_listen(btsock_type_t type, const char *service_name,
+ const uint8_t *uuid, int chan, int *sock_fd, int flags)
+sock_connect(const bt_bdaddr_t *bdaddr, btsock_type_t type,
+ const uint8_t *uuid, int chan, int *sock_fd, int flags)
+
+socket type RFCOMM is only supported at the moment. uuid and channel used
+to decide where to connect.
+
+sockfd is used to return socket fd to Android framework. It is used to inform
+framework when remote device is connected.
+
+listen()
+========
+
+Listens on RFCOMM socket, socket channel is either found based on uuid or
+channel parameter used directly. Returns sock_fd to Android framework.
+
+Through this sock_fd channel number as (int) needs to be written right after
+listen() succeeds.
+
+When remote device is connected to this socket we shall send accept signal
+through sock_fd
+
+connect()
+=========
+
+Connects to remote device specified in bd_addr parameter. Socket channel is
+found by SDP search of remote device by supplied uuid. Returns sock_fd to
+Android framework.
+
+Through this sock_fd channel number as (int) needs to be written right after
+connects() succeeds.
+
+When remote device is connected to this socket we shall send connect signal
+through sock_fd
+
+The format of connect/accept signal is shown below:
+
+struct hal_sock_connect_signal {
+ short size;
+ uint8_t bdaddr[6];
+ int channel;
+ int status;
+} __attribute__((packed));
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 6/6] android: Add reasons for adding capabilites to process
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385730756-32400-1-git-send-email-ravikumar.veeramally@linux.intel.com>
CAP_NET_ADMIN: Allow use of MGMT interface
CAP_NET_BIND_SERVICE: Allow use of privileged PSM
CAP_NET_RAW: Allow use of bnep ioctl calls
---
android/main.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/android/main.c b/android/main.c
index 3a14af5..eedca58 100644
--- a/android/main.c
+++ b/android/main.c
@@ -534,6 +534,9 @@ static bool set_capabilities(void)
header.version = _LINUX_CAPABILITY_VERSION;
header.pid = 0;
+ /* CAP_NET_ADMIN: Allow use of MGMT interface
+ * CAP_NET_BIND_SERVICE: Allow use of privileged PSM
+ * CAP_NET_RAW: Allow use of bnep ioctl calls */
cap.effective = cap.permitted =
CAP_TO_MASK(CAP_NET_RAW) |
CAP_TO_MASK(CAP_NET_ADMIN) |
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 5/6] android/pan: Implement the get local role method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385730756-32400-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Returns local role of the device (NONE, PANU or NAP).
---
android/pan.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/android/pan.c b/android/pan.c
index 34bbbd0..88f96d4 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -278,9 +278,15 @@ static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
{
- DBG("Not Implemented");
+ struct hal_rsp_pan_get_role rsp;
- return HAL_STATUS_FAILED;
+ DBG("");
+
+ rsp.local_role = local_role;
+ ipc_send_rsp_full(HAL_SERVICE_ID_PAN, HAL_OP_PAN_GET_ROLE, sizeof(rsp),
+ &rsp, -1);
+
+ return HAL_STATUS_SUCCESS;
}
void bt_pan_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 4/6] android/pan: Implement pan disconnect method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385730756-32400-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Disconnect ongoing PANU role connection betweek devices, free
the device and notify the connection state.
---
android/pan.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/android/pan.c b/android/pan.c
index 5bd1b0d..34bbbd0 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -238,9 +238,35 @@ static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
uint16_t len)
{
- DBG("Not Implemented");
+ struct network_peer *np;
+ GSList *l;
+ bdaddr_t dst;
- return HAL_STATUS_FAILED;
+ DBG("");
+
+ if (len < sizeof(*cmd))
+ return HAL_STATUS_INVALID;
+
+ android2bdaddr(&cmd->bdaddr, &dst);
+
+ l = g_slist_find_custom(peers, &dst, peer_cmp);
+ if (!l)
+ return HAL_STATUS_FAILED;
+
+ np = l->data;
+
+ if (np->watch) {
+ g_source_remove(np->watch);
+ np->watch = 0;
+ }
+
+ bnep_if_down(np->dev);
+ bnep_kill_connection(&dst);
+
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_DISCONNECTED);
+ network_peer_free(np);
+
+ return HAL_STATUS_SUCCESS;
}
static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 3/6] android/pan: Implement pan connect method in daemon
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385730756-32400-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Implements the PAN connect method in android daemon with PANU role
only. Setting up the bnep environment, adds connection and makes
bnep interface up are part of bnep_connect call. Notifies bnep
interface on control state call back and connection status on
connection state call back.
---
android/Android.mk | 2 +
android/Makefile.am | 3 +-
android/pan.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 216 insertions(+), 8 deletions(-)
diff --git a/android/Android.mk b/android/Android.mk
index c4d722d..549613c 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -42,6 +42,7 @@ LOCAL_SRC_FILES := \
../lib/hci.c \
../btio/btio.c \
../src/sdp-client.c \
+ ../profiles/network/bnep.c \
LOCAL_C_INCLUDES := \
$(call include-path-for, glib) \
@@ -66,6 +67,7 @@ lib_headers := \
sdp.h \
rfcomm.h \
sco.h \
+ bnep.h \
$(shell mkdir -p $(LOCAL_PATH)/../lib/bluetooth)
diff --git a/android/Makefile.am b/android/Makefile.am
index 15ecf35..df04762 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -24,7 +24,8 @@ android_bluetoothd_SOURCES = android/main.c \
android/socket.h android/socket.c \
android/pan.h android/pan.c \
btio/btio.h btio/btio.c \
- src/sdp-client.h src/sdp-client.c
+ src/sdp-client.h src/sdp-client.c \
+ profiles/network/bnep.h profiles/network/bnep.c
android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
diff --git a/android/pan.c b/android/pan.c
index ea15637..5bd1b0d 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -29,35 +29,228 @@
#include <fcntl.h>
#include <glib.h>
+#include "btio/btio.h"
#include "lib/bluetooth.h"
+#include "lib/bnep.h"
+#include "lib/sdp.h"
+#include "lib/sdp_lib.h"
+#include "src/glib-helper.h"
+#include "profiles/network/bnep.h"
+
#include "log.h"
#include "pan.h"
#include "hal-msg.h"
#include "ipc.h"
+#include "utils.h"
+#include "bluetooth.h"
-static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
+static bdaddr_t adapter_addr;
+GSList *peers = NULL;
+uint8_t local_role = HAL_PAN_ROLE_NONE;
+
+struct network_peer {
+ char dev[16];
+ bdaddr_t dst;
+ uint8_t conn_state;
+ uint8_t role;
+ GIOChannel *io;
+ guint watch;
+};
+
+static int peer_cmp(gconstpointer s, gconstpointer user_data)
{
- DBG("Not Implemented");
+ const struct network_peer *np = s;
+ const bdaddr_t *dst = user_data;
- return HAL_STATUS_FAILED;
+ return bacmp(&np->dst, dst);
}
-static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
+static void network_peer_free(struct network_peer *np)
+{
+ local_role = HAL_PAN_ROLE_NONE;
+
+ if (np->watch > 0) {
+ g_source_remove(np->watch);
+ np->watch = 0;
+ }
+
+ if (np->io) {
+ g_io_channel_unref(np->io);
+ np->io = NULL;
+ }
+
+ peers = g_slist_remove(peers, np);
+ g_free(np);
+ np = NULL;
+}
+
+static void bt_pan_notify_conn_state(struct network_peer *np, uint8_t state)
+{
+ struct hal_ev_pan_conn_state ev;
+ char addr[18];
+
+ if (np->conn_state == state)
+ return;
+
+ np->conn_state = state;
+ ba2str(&np->dst, addr);
+ DBG("device %s state %u", addr, state);
+
+ bdaddr2android(&np->dst, ev.bdaddr);
+ ev.state = state;
+ ev.local_role = local_role;
+ ev.remote_role = np->role;
+ ev.status = HAL_STATUS_SUCCESS;
+
+ ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CONN_STATE, sizeof(ev),
+ &ev);
+}
+
+static void bt_pan_notify_ctrl_state(struct network_peer *np, uint8_t state)
+{
+ struct hal_ev_pan_ctrl_state ev;
+
+ DBG("");
+
+ ev.state = state;
+ ev.local_role = local_role;
+ ev.status = HAL_STATUS_SUCCESS;
+ memcpy(ev.name, np->dev, sizeof(np->dev));
+
+ ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CTRL_STATE, sizeof(ev),
+ &ev);
+}
+
+static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ struct network_peer *np = data;
+
+ DBG("%s disconnected", np->dev);
+
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_DISCONNECTED);
+ network_peer_free(np);
+
+ return FALSE;
+}
+
+static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
+{
+ struct network_peer *np = data;
+
+ DBG("");
+
+ if (err < 0) {
+ error("bnep connect req failed: %s", strerror(-err));
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_DISCONNECTED);
+ network_peer_free(np);
+ return;
+ }
+
+ memcpy(np->dev, iface, sizeof(np->dev));
+
+ DBG("%s connected", np->dev);
+
+ bt_pan_notify_ctrl_state(np, HAL_PAN_CTRL_ENABLED);
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_CONNECTED);
+
+ np->watch = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ bnep_watchdog_cb, np);
+ g_io_channel_unref(np->io);
+ np->io = NULL;
+}
+
+static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
+{
+ struct network_peer *np = data;
+ uint16_t src, dst;
+ int perr, sk;
+
+ DBG("");
+
+ if (err) {
+ error("%s", err->message);
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_DISCONNECTED);
+ network_peer_free(np);
+ }
+
+ src = (local_role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP : BNEP_SVC_PANU;
+ dst = (np->role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP : BNEP_SVC_PANU;
+ sk = g_io_channel_unix_get_fd(np->io);
+
+ perr = bnep_connect(sk, src, dst, bnep_conn_cb, np);
+ if (perr < 0) {
+ error("bnep connect req failed: %s", strerror(-perr));
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_DISCONNECTED);
+ network_peer_free(np);
+ return;
+ }
+}
+
+static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
+{
+ struct network_peer *np;
+ bdaddr_t dst;
+ char addr[18];
+ GSList *l;
+ GError *gerr = NULL;
+
+ DBG("");
+
+ if (len < sizeof(*cmd))
+ return HAL_STATUS_INVALID;
+
+ android2bdaddr(&cmd->bdaddr, &dst);
+
+ l = g_slist_find_custom(peers, &dst, peer_cmp);
+ if (l)
+ return HAL_STATUS_FAILED;
+
+ np = g_new0(struct network_peer, 1);
+ bacpy(&np->dst, &dst);
+ local_role = cmd->local_role;
+ np->role = cmd->remote_role;
+
+ ba2str(&np->dst, addr);
+ DBG("connecting to %s %s", addr, np->dev);
+
+ np->io = bt_io_connect(connect_cb, np, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+ BT_IO_OPT_DEST_BDADDR, &np->dst,
+ BT_IO_OPT_PSM, BNEP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_OMTU, BNEP_MTU,
+ BT_IO_OPT_IMTU, BNEP_MTU,
+ BT_IO_OPT_INVALID);
+ if (!np->io) {
+ error("%s", gerr->message);
+ g_error_free(gerr);
+ g_free(np);
+ return HAL_STATUS_FAILED;
+ }
+
+ peers = g_slist_append(peers, np);
+ bt_pan_notify_conn_state(np, HAL_PAN_STATE_CONNECTING);
+
+ return HAL_STATUS_SUCCESS;
+}
+
+static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
+ uint16_t len)
{
DBG("Not Implemented");
return HAL_STATUS_FAILED;
}
-static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
+static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
{
DBG("Not Implemented");
return HAL_STATUS_FAILED;
}
-static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
- uint16_t len)
+static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
{
DBG("Not Implemented");
@@ -91,12 +284,24 @@ void bt_pan_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
bool bt_pan_register(const bdaddr_t *addr)
{
+ int err;
+
DBG("");
+ bacpy(&adapter_addr, addr);
+
+ err = bnep_init();
+ if (err) {
+ error("bnep init failed");
+ return false;
+ }
+
return true;
}
void bt_pan_unregister(void)
{
DBG("");
+
+ bnep_cleanup();
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 2/6] profiles/network: Rename common.c|h to bnep.c|h
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385730756-32400-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Files common.c|h contains only bnep related code, it makes
more sence with bnep.c|h.
---
Makefile.plugins | 2 +-
profiles/network/{common.c => bnep.c} | 2 +-
profiles/network/{common.h => bnep.h} | 0
profiles/network/connection.c | 2 +-
profiles/network/manager.c | 2 +-
profiles/network/server.c | 2 +-
6 files changed, 5 insertions(+), 5 deletions(-)
rename profiles/network/{common.c => bnep.c} (99%)
rename profiles/network/{common.h => bnep.h} (100%)
diff --git a/Makefile.plugins b/Makefile.plugins
index f5025e9..6a1ddbf 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -47,7 +47,7 @@ builtin_sources += profiles/audio/control.h profiles/audio/control.c \
builtin_modules += network
builtin_sources += profiles/network/manager.c \
- profiles/network/common.h profiles/network/common.c \
+ profiles/network/bnep.h profiles/network/bnep.c \
profiles/network/server.h profiles/network/server.c \
profiles/network/connection.h \
profiles/network/connection.c
diff --git a/profiles/network/common.c b/profiles/network/bnep.c
similarity index 99%
rename from profiles/network/common.c
rename to profiles/network/bnep.c
index 71154c8..0a719a2 100644
--- a/profiles/network/common.c
+++ b/profiles/network/bnep.c
@@ -43,7 +43,7 @@
#include <glib.h>
#include "log.h"
-#include "common.h"
+#include "bnep.h"
#include "lib/uuid.h"
#define CON_SETUP_RETRIES 3
diff --git a/profiles/network/common.h b/profiles/network/bnep.h
similarity index 100%
rename from profiles/network/common.h
rename to profiles/network/bnep.h
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index d100580..9aff319 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -47,7 +47,7 @@
#include "service.h"
#include "error.h"
-#include "common.h"
+#include "bnep.h"
#include "connection.h"
#define NETWORK_PEER_INTERFACE "org.bluez.Network1"
diff --git a/profiles/network/manager.c b/profiles/network/manager.c
index ab4224d..8ac2dec 100644
--- a/profiles/network/manager.c
+++ b/profiles/network/manager.c
@@ -43,7 +43,7 @@
#include "device.h"
#include "profile.h"
#include "service.h"
-#include "common.h"
+#include "bnep.h"
#include "connection.h"
#include "server.h"
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 3a7e52a..b3aab11 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -48,7 +48,7 @@
#include "error.h"
#include "sdpd.h"
-#include "common.h"
+#include "bnep.h"
#include "server.h"
#define NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer1"
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 1/6] profiles/network: Refactor bnep connection setup functionality
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1385730756-32400-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Moving bnep connection setup related functionality to common.c.
Provided bnep_connect call with bnep_connect_cb for status and
bnep interface name. It will be simple if someone want to utilize
this call otherwise they have to reimplement similar functionality
with minimal changes (e.g. android/pan).
---
profiles/network/common.c | 195 +++++++++++++++++++++++++++++++++++++++++-
profiles/network/common.h | 5 ++
profiles/network/connection.c | 172 +++----------------------------------
profiles/network/server.c | 3 -
4 files changed, 211 insertions(+), 164 deletions(-)
diff --git a/profiles/network/common.c b/profiles/network/common.c
index 0b291bd..71154c8 100644
--- a/profiles/network/common.c
+++ b/profiles/network/common.c
@@ -46,6 +46,9 @@
#include "common.h"
#include "lib/uuid.h"
+#define CON_SETUP_RETRIES 3
+#define CON_SETUP_TO 9
+
static int ctl;
static struct {
@@ -59,6 +62,35 @@ static struct {
{ NULL }
};
+struct __service_16 {
+ uint16_t dst;
+ uint16_t src;
+} __attribute__ ((packed));
+
+struct bnep_conn {
+ GIOChannel *io;
+ uint16_t src;
+ uint16_t dst;
+ guint attempts;
+ guint setup_to;
+ void *data;
+ bnep_connect_cb conn_cb;
+};
+
+static void free_bnep_connect(struct bnep_conn *bc)
+{
+ if (!bc)
+ return;
+
+ if (bc->io) {
+ g_io_channel_unref(bc->io);
+ bc->io = NULL;
+ }
+
+ g_free(bc);
+ bc = NULL;
+}
+
uint16_t bnep_service_id(const char *svc)
{
int i;
@@ -149,9 +181,9 @@ int bnep_connadd(int sk, uint16_t role, char *dev)
{
struct bnep_connadd_req req;
+ memset(dev, 0, 16);
memset(&req, 0, sizeof(req));
- strncpy(req.device, dev, 16);
- req.device[15] = '\0';
+ strcpy(req.device, "bnep%d");
req.sock = sk;
req.role = role;
if (ioctl(ctl, BNEPCONNADD, &req) < 0) {
@@ -215,6 +247,165 @@ int bnep_if_down(const char *devname)
return 0;
}
+static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ struct bnep_conn *bc = data;
+ struct bnep_control_rsp *rsp;
+ struct timeval timeo;
+ char pkt[BNEP_MTU];
+ char iface[16];
+ ssize_t r;
+ int sk;
+
+ if (cond & G_IO_NVAL)
+ goto failed;
+
+ if (bc->setup_to > 0) {
+ g_source_remove(bc->setup_to);
+ bc->setup_to = 0;
+ }
+
+ if (cond & (G_IO_HUP | G_IO_ERR)) {
+ error("Hangup or error on l2cap server socket");
+ goto failed;
+ }
+
+ sk = g_io_channel_unix_get_fd(chan);
+ memset(pkt, 0, BNEP_MTU);
+ r = read(sk, pkt, sizeof(pkt) - 1);
+ if (r < 0) {
+ error("IO Channel read error");
+ goto failed;
+ }
+
+ if (r == 0) {
+ error("No packet received on l2cap socket");
+ goto failed;
+ }
+
+ errno = EPROTO;
+
+ if ((size_t) r < sizeof(*rsp)) {
+ error("Packet received is not bnep type");
+ goto failed;
+ }
+
+ rsp = (void *) pkt;
+ if (rsp->type != BNEP_CONTROL) {
+ error("Packet received is not bnep type");
+ goto failed;
+ }
+
+ if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
+ return TRUE;
+
+ r = ntohs(rsp->resp);
+ if (r != BNEP_SUCCESS) {
+ error("bnep failed");
+ goto failed;
+ }
+
+ memset(&timeo, 0, sizeof(timeo));
+ timeo.tv_sec = 0;
+ setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
+
+ sk = g_io_channel_unix_get_fd(bc->io);
+ if (bnep_connadd(sk, bc->src, iface)) {
+ error("bnep conn could not be added");
+ goto failed;
+ }
+
+ if (bnep_if_up(iface)) {
+ error("could not up %s", iface);
+ goto failed;
+ }
+
+ bc->conn_cb(chan, iface, 0, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+
+failed:
+ bc->conn_cb(NULL, NULL, -EIO, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+}
+
+static int bnep_setup_conn_req(struct bnep_conn *bc)
+{
+ struct bnep_setup_conn_req *req;
+ struct __service_16 *s;
+ unsigned char pkt[BNEP_MTU];
+ int fd;
+
+ /* Send request */
+ req = (void *) pkt;
+ req->type = BNEP_CONTROL;
+ req->ctrl = BNEP_SETUP_CONN_REQ;
+ req->uuid_size = 2; /* 16bit UUID */
+ s = (void *) req->service;
+ s->src = htons(bc->src);
+ s->dst = htons(bc->dst);
+
+ fd = g_io_channel_unix_get_fd(bc->io);
+ if (write(fd, pkt, sizeof(*req) + sizeof(*s)) < 0) {
+ error("bnep connection req send failed: %s", strerror(errno));
+ return -errno;
+ }
+
+ bc->attempts++;
+
+ return 0;
+}
+
+static gboolean bnep_conn_req_to(gpointer user_data)
+{
+ struct bnep_conn *bc = user_data;
+
+ if (bc->attempts == CON_SETUP_RETRIES) {
+ error("Too many bnep connection attempts");
+ } else {
+ error("bnep connection setup TO, retrying...");
+ if (bnep_setup_conn_req(bc) == 0)
+ return TRUE;
+ }
+
+ bc->conn_cb(NULL, NULL, -ETIMEDOUT, bc->data);
+ free_bnep_connect(bc);
+
+ return FALSE;
+}
+
+int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
+ void *data)
+{
+ struct bnep_conn *bc;
+ int err;
+
+ if (!conn_cb)
+ return -EINVAL;
+
+ bc = g_new0(struct bnep_conn, 1);
+ bc->io = g_io_channel_unix_new(sk);
+ bc->attempts = 0;
+ bc->src = src;
+ bc->dst = dst;
+ bc->conn_cb = conn_cb;
+ bc->data = data;
+
+ err = bnep_setup_conn_req(bc);
+ if (err < 0)
+ return err;
+
+ bc->setup_to = g_timeout_add_seconds(CON_SETUP_TO,
+ bnep_conn_req_to, bc);
+ g_io_add_watch(bc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ bnep_setup_cb, bc);
+ return 0;
+}
+
int bnep_add_to_bridge(const char *devname, const char *bridge)
{
int ifindex;
diff --git a/profiles/network/common.h b/profiles/network/common.h
index 9a8caac..9043e46 100644
--- a/profiles/network/common.h
+++ b/profiles/network/common.h
@@ -35,3 +35,8 @@ int bnep_if_up(const char *devname);
int bnep_if_down(const char *devname);
int bnep_add_to_bridge(const char *devname, const char *bridge);
int bnep_del_from_bridge(const char *devname, const char *bridge);
+
+typedef void (*bnep_connect_cb) (GIOChannel *chan, char *iface, int err,
+ void *data);
+int bnep_connect(int sk, uint16_t src, uint16_t dst, bnep_connect_cb conn_cb,
+ void *data);
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 5966268..d100580 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -51,8 +51,6 @@
#include "connection.h"
#define NETWORK_PEER_INTERFACE "org.bluez.Network1"
-#define CON_SETUP_RETRIES 3
-#define CON_SETUP_TO 9
typedef enum {
CONNECTED,
@@ -73,16 +71,9 @@ struct network_conn {
GIOChannel *io;
guint dc_id;
struct network_peer *peer;
- guint attempt_cnt;
- guint timeout_source;
DBusMessage *connect;
};
-struct __service_16 {
- uint16_t dst;
- uint16_t src;
-} __attribute__ ((packed));
-
static GSList *peers = NULL;
static uint16_t get_service_id(struct btd_service *service)
@@ -163,11 +154,6 @@ static void local_connect_cb(struct network_conn *nc, int err)
static void cancel_connection(struct network_conn *nc, int err)
{
- if (nc->timeout_source > 0) {
- g_source_remove(nc->timeout_source);
- nc->timeout_source = 0;
- }
-
btd_service_connecting_complete(nc->service, err);
if (nc->connect)
local_connect_cb(nc, err);
@@ -200,83 +186,24 @@ static void disconnect_cb(struct btd_device *device, gboolean removal,
connection_destroy(NULL, user_data);
}
-static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
- gpointer data)
+static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
{
struct network_conn *nc = data;
- struct bnep_control_rsp *rsp;
- struct timeval timeo;
- char pkt[BNEP_MTU];
- ssize_t r;
- int sk;
const char *path;
DBusConnection *conn;
- DBG("cond %u", cond);
-
- if (cond & G_IO_NVAL)
- return FALSE;
-
- if (nc->timeout_source > 0) {
- g_source_remove(nc->timeout_source);
- nc->timeout_source = 0;
- }
-
- if (cond & (G_IO_HUP | G_IO_ERR)) {
- error("Hangup or error on l2cap server socket");
- goto failed;
- }
-
- sk = g_io_channel_unix_get_fd(chan);
-
- memset(pkt, 0, BNEP_MTU);
- r = read(sk, pkt, sizeof(pkt) -1);
- if (r < 0) {
- error("IO Channel read error");
- goto failed;
- }
-
- if (r == 0) {
- error("No packet received on l2cap socket");
- goto failed;
- }
-
- errno = EPROTO;
-
- if ((size_t) r < sizeof(*rsp)) {
- error("Packet received is not bnep type");
- goto failed;
- }
-
- rsp = (void *) pkt;
- if (rsp->type != BNEP_CONTROL) {
- error("Packet received is not bnep type");
- goto failed;
- }
-
- if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
- return TRUE;
-
- r = ntohs(rsp->resp);
-
- if (r != BNEP_SUCCESS) {
- error("bnep failed");
- goto failed;
- }
-
- memset(&timeo, 0, sizeof(timeo));
- timeo.tv_sec = 0;
-
- setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
+ DBG("");
- if (bnep_connadd(sk, BNEP_SVC_PANU, nc->dev)) {
- error("%s could not be added", nc->dev);
+ if (err < 0) {
+ error("connect failed %s", strerror(-err));
goto failed;
}
- bnep_if_up(nc->dev);
+ info("%s connected", nc->dev);
+ memcpy(nc->dev, iface, sizeof(nc->dev));
btd_service_connecting_complete(nc->service, 0);
+
if (nc->connect)
local_connect_cb(nc, 0);
@@ -292,101 +219,30 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
nc->state = CONNECTED;
nc->dc_id = device_add_disconnect_watch(nc->peer->device, disconnect_cb,
- nc, NULL);
-
- info("%s connected", nc->dev);
- /* Start watchdog */
+ nc, NULL);
g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) bnep_watchdog_cb, nc);
+ bnep_watchdog_cb, nc);
g_io_channel_unref(nc->io);
nc->io = NULL;
- return FALSE;
+ return;
failed:
cancel_connection(nc, -EIO);
-
- return FALSE;
-}
-
-static int bnep_send_conn_req(struct network_conn *nc)
-{
- struct bnep_setup_conn_req *req;
- struct __service_16 *s;
- unsigned char pkt[BNEP_MTU];
- int fd;
-
- DBG("");
-
- /* Send request */
- req = (void *) pkt;
- req->type = BNEP_CONTROL;
- req->ctrl = BNEP_SETUP_CONN_REQ;
- req->uuid_size = 2; /* 16bit UUID */
- s = (void *) req->service;
- s->dst = htons(nc->id);
- s->src = htons(BNEP_SVC_PANU);
-
- fd = g_io_channel_unix_get_fd(nc->io);
- if (write(fd, pkt, sizeof(*req) + sizeof(*s)) < 0) {
- int err = -errno;
- error("bnep connection req send failed: %s", strerror(errno));
- return err;
- }
-
- nc->attempt_cnt++;
-
- return 0;
-}
-
-static gboolean bnep_conn_req_to(gpointer user_data)
-{
- struct network_conn *nc;
-
- nc = user_data;
- if (nc->attempt_cnt == CON_SETUP_RETRIES) {
- error("Too many bnep connection attempts");
- } else {
- error("bnep connection setup TO, retrying...");
- if (bnep_send_conn_req(nc) == 0)
- return TRUE;
- }
-
- cancel_connection(nc, -ETIMEDOUT);
-
- return FALSE;
-}
-
-static int bnep_connect(struct network_conn *nc)
-{
- int err;
-
- nc->attempt_cnt = 0;
-
- err = bnep_send_conn_req(nc);
- if (err < 0)
- return err;
-
- nc->timeout_source = g_timeout_add_seconds(CON_SETUP_TO,
- bnep_conn_req_to, nc);
-
- g_io_add_watch(nc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- bnep_setup_cb, nc);
-
- return 0;
}
static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
{
struct network_conn *nc = data;
- int perr;
+ int sk, perr;
if (err) {
error("%s", err->message);
goto failed;
}
- perr = bnep_connect(nc);
+ sk = g_io_channel_unix_get_fd(nc->io);
+ perr = bnep_connect(sk, BNEP_SVC_PANU, nc->id, bnep_conn_cb, nc);
if (perr < 0) {
error("bnep connect(): %s (%d)", strerror(-perr), -perr);
goto failed;
@@ -692,8 +548,6 @@ int connection_register(struct btd_service *service)
nc = g_new0(struct network_conn, 1);
nc->id = id;
- memset(nc->dev, 0, sizeof(nc->dev));
- strcpy(nc->dev, "bnep%d");
nc->service = btd_service_ref(service);
nc->state = DISCONNECTED;
nc->peer = peer;
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 0050b30..3a7e52a 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -269,9 +269,6 @@ static int server_connadd(struct network_server *ns,
char devname[16];
int err, nsk;
- memset(devname, 0, sizeof(devname));
- strcpy(devname, "bnep%d");
-
nsk = g_io_channel_unix_get_fd(session->io);
err = bnep_connadd(nsk, dst_role, devname);
if (err < 0)
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v4 0/6] Refactor bnep code and implement pan methods
From: Ravi kumar Veeramally @ 2013-11-29 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
v4: Fixed Luiz comments (discussed in irc). Merge patch 1 and 2.
Pass fd in bnep_connect instead of GIOChannel.
v3: Fixed Anderson and Luiz comments and solved rebased conflicts.
v2: Refactored profiles/network/common.* as per Johan's comments
(renaming common.c|h to bnep.c|h and moving bnep related code to
bnep.c ro reduce redundancy in profiles/netowrk/connection.c and
android/pan.c)
v1: This patch set supports PANU role with a minor fix in android. Added
CAP_NET_RAW capability for bnep services. Creates bnep connection and
up the inreface on connect call and free the device on disconnect call.
Interface name(bnepX) will be notified on control state cb. Android
environment will create IP address with dhcp calls.
Ravi kumar Veeramally (6):
profiles/network: Refactor bnep connection setup functionality
profiles/network: Rename common.c|h to bnep.c|h
android/pan: Implement pan connect method in daemon
android/pan: Implement pan disconnect method in daemon
android/pan: Implement the get local role method in daemon
android: Add reasons for adding capabilites to process
Makefile.plugins | 2 +-
android/Android.mk | 2 +
android/Makefile.am | 3 +-
android/main.c | 3 +
android/pan.c | 253 ++++++++++++++++++++++++++++++++--
profiles/network/{common.c => bnep.c} | 197 +++++++++++++++++++++++++-
profiles/network/{common.h => bnep.h} | 5 +
profiles/network/connection.c | 174 ++---------------------
profiles/network/manager.c | 2 +-
profiles/network/server.c | 5 +-
10 files changed, 468 insertions(+), 178 deletions(-)
rename profiles/network/{common.c => bnep.c} (58%)
rename profiles/network/{common.h => bnep.h} (87%)
--
1.8.3.2
^ permalink raw reply
* [PATCH v2 9/9] android/socket: Use generic IPC message handling for commands
From: Szymon Janc @ 2013-11-29 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385723331-15603-1-git-send-email-szymon.janc@tieto.com>
Handlers are registered on service register and unregistered on
unregister.
---
android/socket.c | 102 ++++++++++++++++++++++++++-----------------------------
1 file changed, 49 insertions(+), 53 deletions(-)
diff --git a/android/socket.c b/android/socket.c
index 4f47861..76b40c8 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -650,15 +650,15 @@ static void accept_cb(GIOChannel *io, GError *err, gpointer user_data)
rfsock_acc->rfcomm_watch);
}
-static int handle_listen(void *buf)
+static void handle_listen(const void *buf, uint16_t len)
{
- struct hal_cmd_sock_listen *cmd = buf;
+ const struct hal_cmd_sock_listen *cmd = buf;
const struct profile_info *profile;
- struct rfcomm_sock *rfsock;
+ struct rfcomm_sock *rfsock = NULL;
BtIOSecLevel sec_level;
GIOChannel *io;
GError *err = NULL;
- int hal_fd;
+ int hal_fd = -1;
int chan;
DBG("");
@@ -666,11 +666,10 @@ static int handle_listen(void *buf)
profile = get_profile_by_uuid(cmd->uuid);
if (!profile) {
if (!cmd->channel)
- return -1;
- else {
- chan = cmd->channel;
- sec_level = BT_IO_SEC_MEDIUM;
- }
+ goto failed;
+
+ chan = cmd->channel;
+ sec_level = BT_IO_SEC_MEDIUM;
} else {
chan = profile->channel;
sec_level = profile->sec_level;
@@ -680,7 +679,7 @@ static int handle_listen(void *buf)
rfsock = create_rfsock(-1, &hal_fd);
if (!rfsock)
- return -1;
+ goto failed;
io = bt_io_listen(accept_cb, NULL, rfsock, NULL, &err,
BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
@@ -690,8 +689,7 @@ static int handle_listen(void *buf)
if (!io) {
error("Failed listen: %s", err->message);
g_error_free(err);
- cleanup_rfsock(rfsock);
- return -1;
+ goto failed;
}
rfsock->real_sock = g_io_channel_unix_get_fd(io);
@@ -703,15 +701,27 @@ static int handle_listen(void *buf)
if (write(rfsock->fd, &chan, sizeof(chan)) != sizeof(chan)) {
error("Error sending RFCOMM channel");
- cleanup_rfsock(rfsock);
- return -1;
+ goto failed;
}
rfsock->service_handle = sdp_service_register(profile, cmd->name);
servers = g_list_append(servers, rfsock);
- return hal_fd;
+ ipc_send_rsp_full(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_LISTEN, 0, NULL,
+ hal_fd);
+ close(hal_fd);
+ return;
+
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_LISTEN,
+ HAL_STATUS_FAILED);
+
+ if (rfsock)
+ cleanup_rfsock(rfsock);
+
+ if (hal_fd >= 0)
+ close(hal_fd);
}
static bool sock_send_connect(struct rfcomm_sock *rfsock, bdaddr_t *bdaddr)
@@ -865,9 +875,9 @@ fail:
cleanup_rfsock(rfsock);
}
-static int handle_connect(void *buf)
+static void handle_connect(const void *buf, uint16_t len)
{
- struct hal_cmd_sock_connect *cmd = buf;
+ const struct hal_cmd_sock_connect *cmd = buf;
struct rfcomm_sock *rfsock;
uuid_t uuid;
int hal_fd = -1;
@@ -876,7 +886,7 @@ static int handle_connect(void *buf)
rfsock = create_rfsock(-1, &hal_fd);
if (!rfsock)
- return -1;
+ goto failed;
android2bdaddr(cmd->bdaddr, &rfsock->dst);
@@ -890,55 +900,41 @@ static int handle_connect(void *buf)
sdp_search_cb, rfsock, NULL) < 0) {
error("Failed to search SDP records");
cleanup_rfsock(rfsock);
- return -1;
+ goto failed;
}
- return hal_fd;
-}
-
-void bt_sock_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
-{
- int fd;
-
- switch (opcode) {
- case HAL_OP_SOCK_LISTEN:
- fd = handle_listen(buf);
- if (fd < 0)
- break;
-
- ipc_send_rsp_full(HAL_SERVICE_ID_SOCK, opcode, 0, NULL, fd);
-
- if (close(fd) < 0)
- error("close() fd %d failed: %s", fd, strerror(errno));
-
- return;
- case HAL_OP_SOCK_CONNECT:
- fd = handle_connect(buf);
- if (fd < 0)
- break;
-
- ipc_send_rsp_full(HAL_SERVICE_ID_SOCK, opcode, 0, NULL, fd);
+ ipc_send_rsp_full(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_CONNECT, 0, NULL,
+ hal_fd);
+ close(hal_fd);
+ return;
- if (close(fd) < 0)
- error("close() fd %d failed: %s", fd, strerror(errno));
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_CONNECT,
+ HAL_STATUS_FAILED);
- return;
- default:
- DBG("Unhandled command, opcode 0x%x", opcode);
- break;
- }
-
- ipc_send_rsp(HAL_SERVICE_ID_SOCK, opcode, HAL_STATUS_FAILED);
+ if (hal_fd >= 0)
+ close(hal_fd);
}
+static const struct ipc_handler cmd_handlers[] = {
+ /* HAL_OP_SOCK_LISTEN */
+ { handle_listen, false, sizeof(struct hal_cmd_sock_listen) },
+ /* HAL_OP_SOCK_CONNECT */
+ { handle_connect, false, sizeof(struct hal_cmd_sock_connect) },
+};
+
void bt_socket_register(const bdaddr_t *addr)
{
DBG("");
bacpy(&adapter_addr, addr);
+ ipc_register(HAL_SERVICE_ID_SOCK, cmd_handlers,
+ sizeof(cmd_handlers)/sizeof(cmd_handlers[0]));
}
void bt_socket_unregister(void)
{
DBG("");
+
+ ipc_unregister(HAL_SERVICE_ID_SOCK);
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 8/9] android/a2dp: Use generic IPC message handling for commands
From: Szymon Janc @ 2013-11-29 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385723331-15603-1-git-send-email-szymon.janc@tieto.com>
Handlers are registered on service register and unregistered on
unregister.
---
android/a2dp.c | 69 +++++++++++++++++++++++++++++-----------------------------
android/a2dp.h | 2 --
2 files changed, 35 insertions(+), 36 deletions(-)
diff --git a/android/a2dp.c b/android/a2dp.c
index 99aa14d..98c138e 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -164,9 +164,11 @@ static void signaling_connect_cb(GIOChannel *chan, GError *err,
bt_a2dp_notify_state(dev, HAL_A2DP_STATE_CONNECTED);
}
-static uint8_t bt_a2dp_connect(struct hal_cmd_a2dp_connect *cmd, uint16_t len)
+static void bt_a2dp_connect(const void *buf, uint16_t len)
{
+ const struct hal_cmd_a2dp_connect *cmd = buf;
struct a2dp_device *dev;
+ uint8_t status;
char addr[18];
bdaddr_t dst;
GSList *l;
@@ -174,14 +176,13 @@ static uint8_t bt_a2dp_connect(struct hal_cmd_a2dp_connect *cmd, uint16_t len)
DBG("");
- if (len < sizeof(*cmd))
- return HAL_STATUS_INVALID;
-
android2bdaddr(&cmd->bdaddr, &dst);
l = g_slist_find_custom(devices, &dst, device_cmp);
- if (l)
- return HAL_STATUS_FAILED;
+ if (l) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
dev = a2dp_device_new(&dst);
dev->io = bt_io_connect(signaling_connect_cb, dev, NULL, &err,
@@ -194,7 +195,8 @@ static uint8_t bt_a2dp_connect(struct hal_cmd_a2dp_connect *cmd, uint16_t len)
error("%s", err->message);
g_error_free(err);
a2dp_device_free(dev);
- return HAL_STATUS_FAILED;
+ status = HAL_STATUS_FAILED;
+ goto failed;
}
ba2str(&dev->dst, addr);
@@ -202,26 +204,29 @@ static uint8_t bt_a2dp_connect(struct hal_cmd_a2dp_connect *cmd, uint16_t len)
bt_a2dp_notify_state(dev, HAL_A2DP_STATE_CONNECTING);
- return HAL_STATUS_SUCCESS;
+ status = HAL_STATUS_SUCCESS;
+
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_A2DP, HAL_OP_A2DP_CONNECT, status);
}
-static uint8_t bt_a2dp_disconnect(struct hal_cmd_a2dp_connect *cmd,
- uint16_t len)
+static void bt_a2dp_disconnect(const void *buf, uint16_t len)
{
+ const struct hal_cmd_a2dp_connect *cmd = buf;
+ uint8_t status;
struct a2dp_device *dev;
GSList *l;
bdaddr_t dst;
DBG("");
- if (len < sizeof(*cmd))
- return HAL_STATUS_INVALID;
-
android2bdaddr(&cmd->bdaddr, &dst);
l = g_slist_find_custom(devices, &dst, device_cmp);
- if (!l)
- return HAL_STATUS_FAILED;
+ if (!l) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
dev = l->data;
@@ -231,28 +236,19 @@ static uint8_t bt_a2dp_disconnect(struct hal_cmd_a2dp_connect *cmd,
bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTING);
- return HAL_STATUS_SUCCESS;
-}
-
-void bt_a2dp_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
-{
- uint8_t status = HAL_STATUS_FAILED;
-
- switch (opcode) {
- case HAL_OP_A2DP_CONNECT:
- status = bt_a2dp_connect(buf, len);
- break;
- case HAL_OP_A2DP_DISCONNECT:
- status = bt_a2dp_disconnect(buf, len);
- break;
- default:
- DBG("Unhandled command, opcode 0x%x", opcode);
- break;
- }
+ status = HAL_STATUS_SUCCESS;
- ipc_send_rsp(HAL_SERVICE_ID_A2DP, opcode, status);
+failed:
+ ipc_send_rsp(HAL_SERVICE_ID_A2DP, HAL_OP_A2DP_DISCONNECT, status);
}
+static const struct ipc_handler cmd_handlers[] = {
+ /* HAL_OP_A2DP_CONNECT */
+ { bt_a2dp_connect, false, sizeof(struct hal_cmd_a2dp_connect) },
+ /* HAL_OP_A2DP_DISCONNECT */
+ { bt_a2dp_disconnect, false, sizeof(struct hal_cmd_a2dp_disconnect) },
+};
+
static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
{
struct a2dp_device *dev;
@@ -380,6 +376,9 @@ bool bt_a2dp_register(const bdaddr_t *addr)
}
record_id = rec->handle;
+ ipc_register(HAL_SERVICE_ID_A2DP, cmd_handlers,
+ sizeof(cmd_handlers)/sizeof(cmd_handlers[0]));
+
return true;
}
@@ -397,6 +396,8 @@ void bt_a2dp_unregister(void)
g_slist_foreach(devices, a2dp_device_disconnected, NULL);
devices = NULL;
+
+ ipc_unregister(HAL_SERVICE_ID_A2DP);
bt_adapter_remove_record(record_id);
record_id = 0;
diff --git a/android/a2dp.h b/android/a2dp.h
index 2a1eb3c..7e9b2f6 100644
--- a/android/a2dp.h
+++ b/android/a2dp.h
@@ -21,7 +21,5 @@
*
*/
-void bt_a2dp_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
-
bool bt_a2dp_register(const bdaddr_t *addr);
void bt_a2dp_unregister(void);
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 7/9] android/pan: Use generic IPC message handling for commands
From: Szymon Janc @ 2013-11-29 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1385723331-15603-1-git-send-email-szymon.janc@tieto.com>
Handlers are registered on service register and unregistered on
unregister.
---
android/pan.c | 57 ++++++++++++++++++++++++---------------------------------
android/pan.h | 2 --
2 files changed, 24 insertions(+), 35 deletions(-)
diff --git a/android/pan.c b/android/pan.c
index ea15637..e15235d 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -35,68 +35,59 @@
#include "hal-msg.h"
#include "ipc.h"
-static uint8_t bt_pan_enable(struct hal_cmd_pan_enable *cmd, uint16_t len)
+static void bt_pan_enable(const void *buf, uint16_t len)
{
DBG("Not Implemented");
- return HAL_STATUS_FAILED;
+ ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE, HAL_STATUS_FAILED);
}
-static uint8_t bt_pan_get_role(void *cmd, uint16_t len)
+static void bt_pan_get_role(const void *buf, uint16_t len)
{
DBG("Not Implemented");
- return HAL_STATUS_FAILED;
+ ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_GET_ROLE,
+ HAL_STATUS_FAILED);
}
-static uint8_t bt_pan_connect(struct hal_cmd_pan_connect *cmd, uint16_t len)
+static void bt_pan_connect(const void *buf, uint16_t len)
{
DBG("Not Implemented");
- return HAL_STATUS_FAILED;
+ ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_CONNECT, HAL_STATUS_FAILED);
}
-static uint8_t bt_pan_disconnect(struct hal_cmd_pan_disconnect *cmd,
- uint16_t len)
+static void bt_pan_disconnect(const void *buf, uint16_t len)
{
DBG("Not Implemented");
- return HAL_STATUS_FAILED;
+ ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT,
+ HAL_STATUS_FAILED);
}
-void bt_pan_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
-{
- uint8_t status = HAL_STATUS_FAILED;
-
- switch (opcode) {
- case HAL_OP_PAN_ENABLE:
- status = bt_pan_enable(buf, len);
- break;
- case HAL_OP_PAN_GET_ROLE:
- status = bt_pan_get_role(buf, len);
- break;
- case HAL_OP_PAN_CONNECT:
- status = bt_pan_connect(buf, len);
- break;
- case HAL_OP_PAN_DISCONNECT:
- status = bt_pan_disconnect(buf, len);
- break;
- default:
- DBG("Unhandled command, opcode 0x%x", opcode);
- break;
- }
-
- ipc_send_rsp(HAL_SERVICE_ID_PAN, opcode, status);
-}
+static const struct ipc_handler cmd_handlers[] = {
+ /* HAL_OP_PAN_ENABLE */
+ { bt_pan_enable, false, sizeof(struct hal_cmd_pan_enable) },
+ /* HAL_OP_PAN_GET_ROLE */
+ { bt_pan_get_role, false, 0 },
+ /* HAL_OP_PAN_CONNECT */
+ { bt_pan_connect, false, sizeof(struct hal_cmd_pan_connect) },
+ /* HAL_OP_PAN_DISCONNECT */
+ { bt_pan_disconnect, false, sizeof(struct hal_cmd_pan_disconnect) },
+};
bool bt_pan_register(const bdaddr_t *addr)
{
DBG("");
+ ipc_register(HAL_SERVICE_ID_PAN, cmd_handlers,
+ sizeof(cmd_handlers)/sizeof(cmd_handlers[0]));
return true;
}
void bt_pan_unregister(void)
{
DBG("");
+
+ ipc_unregister(HAL_SERVICE_ID_PAN);
}
diff --git a/android/pan.h b/android/pan.h
index dd18f68..3178d88 100644
--- a/android/pan.h
+++ b/android/pan.h
@@ -21,7 +21,5 @@
*
*/
-void bt_pan_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
-
bool bt_pan_register(const bdaddr_t *addr);
void bt_pan_unregister(void);
--
1.8.3.2
^ 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