* [PATCH v2 2/2] Correct UUIDs list to EIR
From: Francisco Alecrim @ 2010-04-07 15:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Francisco Alecrim
In-Reply-To: <1270652663-23107-2-git-send-email-francisco.alecrim@openbossa.org>
Correct create_ext_inquiry_response to response only UUIDs per-adapter.
---
src/adapter.c | 3 ++-
src/sdpd-service.c | 5 +++--
src/sdpd.h | 3 ++-
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index cdd5562..7008410 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -816,7 +816,8 @@ static void update_ext_inquiry_response(struct btd_adapter *adapter)
if (dev->ssp_mode > 0)
create_ext_inquiry_response((char *) dev->name,
- adapter->tx_power, data);
+ adapter->tx_power,
+ adapter->services, data);
if (hci_write_ext_inquiry_response(dd, fec, data,
HCI_REQ_TIMEOUT) < 0)
diff --git a/src/sdpd-service.c b/src/sdpd-service.c
index a8f7d47..4551577 100644
--- a/src/sdpd-service.c
+++ b/src/sdpd-service.c
@@ -167,9 +167,10 @@ uint8_t get_service_classes(const bdaddr_t *bdaddr)
}
void create_ext_inquiry_response(const char *name,
- int8_t tx_power, uint8_t *data)
+ int8_t tx_power, sdp_list_t *services,
+ uint8_t *data)
{
- sdp_list_t *list = sdp_get_record_list();
+ sdp_list_t *list = services;
uint8_t *ptr = data;
uint16_t uuid[24];
int i, index = 0;
diff --git a/src/sdpd.h b/src/sdpd.h
index 1352a83..1f0a229 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -95,4 +95,5 @@ int remove_record_from_server(uint32_t handle);
uint8_t get_service_classes(const bdaddr_t *bdaddr);
void create_ext_inquiry_response(const char *name,
- int8_t tx_power, uint8_t *data);
+ int8_t tx_power, sdp_list_t *services,
+ uint8_t *data);
--
1.6.3.3
^ permalink raw reply related
* [PATCH v2 1/2] Report local services(UUIDs) through DBus
From: Francisco Alecrim @ 2010-04-07 15:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Francisco Alecrim
In-Reply-To: <1270652663-23107-1-git-send-email-francisco.alecrim@openbossa.org>
* Include UUIDs field to method GetProperties(org.bluez.Adapter).
Applications can get local services(UUIDs) available through DBus.
* UUIDs per-adapter stored at btd_adapter to prevent some searches not
necessary regarding it requires information from access_db and service_db.
* Emit Adapter.PropertyChanged signal when UUIDs change.
---
doc/adapter-api.txt | 5 +++
src/adapter.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++-
src/adapter.h | 2 +
src/sdpd-database.c | 4 ++
test/list-devices | 3 ++
5 files changed, 102 insertions(+), 1 deletions(-)
diff --git a/doc/adapter-api.txt b/doc/adapter-api.txt
index 48cab40..6098c76 100644
--- a/doc/adapter-api.txt
+++ b/doc/adapter-api.txt
@@ -270,3 +270,8 @@ Properties string Address [readonly]
array{object} Devices [readonly]
List of device object paths.
+
+ array{string} UUIDs [readonly]
+
+ List of 128-bit UUIDs that represents the available
+ local services.
diff --git a/src/adapter.c b/src/adapter.c
index 5fd0736..cdd5562 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -37,6 +37,7 @@
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
#include <glib.h>
#include <dbus/dbus.h>
@@ -115,6 +116,7 @@ struct btd_adapter {
GSList *mode_sessions; /* Request Mode sessions */
GSList *disc_sessions; /* Discovery sessions */
guint scheduler_id; /* Scheduler handle */
+ sdp_list_t *services; /* Services associated to adapter */
struct hci_dev dev; /* hci info */
int8_t tx_power; /* inq response tx power level */
@@ -1033,6 +1035,76 @@ static void adapter_update_devices(struct btd_adapter *adapter)
g_free(devices);
}
+static void adapter_emit_uuids_updated(struct btd_adapter *adapter)
+{
+ char **uuids;
+ int i;
+ sdp_list_t *list;
+
+ uuids = g_new0(char *, sdp_list_len(adapter->services) + 1);
+
+ for (i = 0, list = adapter->services; list; list = list->next, i++) {
+ sdp_record_t *rec = list->data;
+ uuids[i] = bt_uuid2string(&rec->svclass);
+ }
+
+ emit_array_property_changed(connection, adapter->path,
+ ADAPTER_INTERFACE, "UUIDs",
+ DBUS_TYPE_STRING, &uuids);
+
+ for (i = 0; uuids[i]; i++)
+ g_free(uuids[i]);
+ g_free(uuids);
+}
+
+/*
+ * adapter_services_inc_rem - Insert or remove UUID from adapter
+ */
+static void adapter_service_ins_rem(const bdaddr_t *bdaddr, void *rec,
+ gboolean insert)
+{
+ struct btd_adapter *adapter;
+ GSList *adapters;
+
+ adapters = NULL;
+
+ if (bacmp(bdaddr, BDADDR_ANY) != 0) {
+ /* Only one adapter */
+ adapter = manager_find_adapter(bdaddr);
+ if (!adapter)
+ return;
+
+ adapters = g_slist_append(adapters, adapter);
+ } else
+ /* Emit D-Bus msg to all adapters */
+ adapters = manager_get_adapters();
+
+ for (; adapters; adapters = adapters->next) {
+ adapter = adapters->data;
+
+ if (insert == TRUE)
+ adapter->services = sdp_list_append(adapter->services,
+ rec);
+ else
+ adapter->services = sdp_list_remove(adapter->services,
+ rec);
+
+ adapter_emit_uuids_updated(adapter);
+ }
+}
+
+void adapter_service_insert(const bdaddr_t *bdaddr, void *rec)
+{
+ /* TRUE to include service*/
+ adapter_service_ins_rem(bdaddr, rec, TRUE);
+}
+
+void adapter_service_remove(const bdaddr_t *bdaddr, void *rec)
+{
+ /* FALSE to remove service*/
+ adapter_service_ins_rem(bdaddr, rec, FALSE);
+}
+
struct btd_device *adapter_create_device(DBusConnection *conn,
struct btd_adapter *adapter,
const char *address)
@@ -1196,9 +1268,10 @@ static DBusMessage *get_properties(DBusConnection *conn,
DBusMessageIter dict;
char str[MAX_NAME_LENGTH + 1], srcaddr[18];
gboolean value;
- char **devices;
+ char **devices, **uuids;
int i;
GSList *l;
+ sdp_list_t *list;
ba2str(&adapter->bdaddr, srcaddr);
@@ -1270,6 +1343,20 @@ static DBusMessage *get_properties(DBusConnection *conn,
&devices, i);
g_free(devices);
+ /* UUIDs */
+ uuids = g_new0(char *, sdp_list_len(adapter->services) + 1);
+
+ for (i = 0, list = adapter->services; list; list = list->next, i++) {
+ sdp_record_t *rec = list->data;
+ uuids[i] = bt_uuid2string(&rec->svclass);
+ }
+
+ dict_append_array(&dict, "UUIDs", DBUS_TYPE_STRING, &uuids, i);
+
+ for (i = 0; uuids[i]; i++)
+ g_free(uuids[i]);
+ g_free(uuids);
+
dbus_message_iter_close_container(&iter, &dict);
return reply;
diff --git a/src/adapter.h b/src/adapter.h
index 9b4ce10..e4307d8 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -121,6 +121,8 @@ void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode);
void adapter_setname_complete(bdaddr_t *local, uint8_t status);
void adapter_update_tx_power(bdaddr_t *bdaddr, uint8_t status, void *ptr);
void adapter_update_local_name(bdaddr_t *bdaddr, uint8_t status, void *ptr);
+void adapter_service_insert(const bdaddr_t *bdaddr, void *rec);
+void adapter_service_remove(const bdaddr_t *bdaddr, void *rec);
void adapter_set_class_complete(bdaddr_t *bdaddr, uint8_t status);
struct agent *adapter_get_agent(struct btd_adapter *adapter);
diff --git a/src/sdpd-database.c b/src/sdpd-database.c
index 07a0bc3..224a4e7 100644
--- a/src/sdpd-database.c
+++ b/src/sdpd-database.c
@@ -40,6 +40,7 @@
#include "sdpd.h"
#include "logging.h"
+#include "adapter.h"
static sdp_list_t *service_db;
static sdp_list_t *access_db;
@@ -183,6 +184,8 @@ void sdp_record_add(const bdaddr_t *device, sdp_record_t *rec)
dev->handle = rec->handle;
access_db = sdp_list_insert_sorted(access_db, dev, access_sort);
+
+ adapter_service_insert(device, rec);
}
static sdp_list_t *record_locate(uint32_t handle)
@@ -252,6 +255,7 @@ int sdp_record_remove(uint32_t handle)
if (p) {
a = (sdp_access_t *) p->data;
if (a) {
+ adapter_service_remove(&a->device, r);
access_db = sdp_list_remove(access_db, a);
access_free(a);
}
diff --git a/test/list-devices b/test/list-devices
index 511d0cf..9120714 100755
--- a/test/list-devices
+++ b/test/list-devices
@@ -40,6 +40,9 @@ for i in adapter_list:
if (key == "Devices"):
list = extract_objects(value)
print " %s = %s" % (key, list)
+ elif (key == "UUIDs"):
+ list = extract_uuids(value)
+ print " %s = %s" % (key, list)
else:
print " %s = %s" % (key, value)
--
1.6.3.3
^ permalink raw reply related
* [PATCH v2 0/2] Services through DBus and correct EIR
From: Francisco Alecrim @ 2010-04-07 15:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Francisco Alecrim
* Second version:
** Remove unnecessary braces. Thanks Padovan!
** Correct some lines over 80 characters
* Claudio Takahasi suggested to use a list of uuid_t instead of sdp_list_t at
adapters->services. I consider sdp_list_t easy to use regarding functions
available at sdp_lib.h.
Francisco Alecrim (2):
Report local services(UUIDs) through DBus
Correct UUIDs list to EIR
doc/adapter-api.txt | 5 +++
src/adapter.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++-
src/adapter.h | 2 +
src/sdpd-database.c | 4 ++
src/sdpd-service.c | 5 ++-
src/sdpd.h | 3 +-
test/list-devices | 3 ++
7 files changed, 109 insertions(+), 5 deletions(-)
^ permalink raw reply
* Re: upper limit of bonded devices?
From: Garry Paxinos @ 2010-04-07 13:07 UTC (permalink / raw)
To: Peter Dons Tychsen; +Cc: Iain Hibbert, linux-bluetooth
In-Reply-To: <1270598033.3201.75.camel@donpedro>
Thanks to both of your for your info.
I was able to get RSSI iinfo, but it took a little fiddling with the
extended_inquiry_info structure but I have it working.
I have complete control over the computer but no control over the
device. It would be best if I could cause the device to initiate the
connection but do not have a practical way to implement.
I have seen a couple times when I'm initiating a connection from the
computer to one device, another device will initiate a connection to
the computer without any explicit prompting on my part. But I need to
investigate this further to see if I can reliably repeat this and then
if it is a usable side effect.
Having only a very limited number of active connection is not a
problem for my project.
Thanks again,
Pax.
On Tue, Apr 6, 2010 at 7:53 PM, Peter Dons Tychsen <donpedro@tdcadsl.dk> wrote:
> Hi Iain & Garry,
>
> On Tue, 2010-04-06 at 20:57 +0100, Iain Hibbert wrote:
>> Sure, but consider that the page timeout (time to failure of a
>> connection
>> attempt) is usually around 20 seconds.. and most Bluetooth controllers
>> (that I have tried) can only page a single device at a time.. So, if
>> you
>> don't know which devices are in range, you might be waiting a *long*
>> time
>> before you connect to anything..
>
> 20 seconds for a "page-timeout" is unusual for the reason you just
> mentioned. However, the "link-timeout" is usually around 10-20 seconds,
> but that is only applicable if an existing links needs to drop. The page
> timeout use usually more like 3-5 seconds. Even if it were as high as
> you describe, it is easily re-configurable. Going below ~2 seconds is
> not a good idea though as you push the odds of hitting the page-scan
> window (i do not remember the exact number, look in the spec). Even
> better test it (and tune accordingly). For an application like this you
> want a low page-timeout.
>
> On Tue, 2010-04-06 at 19:11 +0100, Iain Hibbert wrote:
>> you will probably find that because the HS device is very limited in
>> resources, it does not keep records of more than one paired device.
>> So, if
>> you pair with another device it forgets about the first and you will
>> not
>> be able to connect except that you pair it again.
>
> Many headset devices store store 8 devices they have previously paired
> with (the major brands). It is however not a guarantee, so some might
> not have it.
>
>>On Tue, 2010-04-06 at 13:08 -0400, Garry Paxinos wrote:
>> Is there a practical upper limit of the number of devices that can be
>> bonded to a single computer?
>
> The number of devices is almost limitless. However, as Iain said, in
> theory this cannot be done with one controller as the maximum devices
> for a unit is 7. In practice it looks even worse, as many controllers
> become unstable if you go beyond 2 links. The link itself also becomes
> unstable when many devices are connected, as you run out of air-time
> (your radio can only service one at any time), and you risk loosing a
> link. I recommend people to stick with one link pr. application if
> stability and speed is the name of the game. If not, test it!
>
> Recently i created a large setup of lots of BT-USB dongles connected via
> some hubs to a single box running Bluez. To my delight it was remarkably
> easy and stable. The well designed Bluez-API really is a bonus. Doing
> this on any other system has only ended in agony. Just having that many
> USB devices can cause problems on many systems. This is definitely the
> way to go if you are trying to connect to lots of devices in a reliable
> way. It is pretty cheap as well, as even good dongles are getting
> cheaper even as i type (down to $10-$15)! :-)
>
> Good luck on your project,
>
> Thanks,
>
> /Pedro
> --
> 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
>
^ permalink raw reply
* [PATCH] btusb: Raw mode and ACL/SCO data
From: Kim B. Heino @ 2010-04-07 12:53 UTC (permalink / raw)
To: linux-bluetooth, marcel, linux-kernel
This patch allows sending ACL/SCO packets if device is in RAW mode.
Previously only command packets were allowed.
Signed-off-by: Kim B. Heino <Kim.Heino@bluegiga.com>
diff -ur orig/drivers/bluetooth/btusb.c linux-2.6.33.2/drivers/bluetooth/btusb.c
--- orig/drivers/bluetooth/btusb.c 2010-04-02 02:02:33.000000000 +0300
+++ linux-2.6.33.2/drivers/bluetooth/btusb.c 2010-04-07 15:17:55.696672710 +0300
@@ -663,7 +663,9 @@
break;
case HCI_ACLDATA_PKT:
- if (!data->bulk_tx_ep || hdev->conn_hash.acl_num < 1)
+ if (!data->bulk_tx_ep ||
+ (!test_bit(HCI_RAW, &hdev->flags) &&
+ hdev->conn_hash.acl_num < 1))
return -ENODEV;
urb = usb_alloc_urb(0, GFP_ATOMIC);
@@ -680,7 +682,9 @@
break;
case HCI_SCODATA_PKT:
- if (!data->isoc_tx_ep || hdev->conn_hash.sco_num < 1)
+ if (!data->isoc_tx_ep ||
+ (!test_bit(HCI_RAW, &hdev->flags) &&
+ hdev->conn_hash.sco_num < 1))
return -ENODEV;
urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC);
^ permalink raw reply
* Re: Question regarding HS Connection
From: nirav rabara @ 2010-04-07 9:32 UTC (permalink / raw)
To: Iain Hibbert; +Cc: linux-bluetooth
In-Reply-To: <1270577491.816321.874.nullmailer@galant.ukfsn.org>
hi Lain,
Thanks for your suggestion,
> you will probably find that because the HS device is very limited in
> resources, it does not keep records of more than one paired device. So, if
> you pair with another device it forgets about the first and you will not
> be able to connect except that you pair it again.
>
Does it mean that once paired device information stored in our
cellphones, if remote device(HS) doesn't have paired information, out
cellphone will take care of re-pairing.
So ultimately am I need to do pairing again??
--
With Regards,
Nirav Rabara
^ permalink raw reply
* Re: [PATCH 1/2] Report local services(UUIDs) through DBus
From: Gustavo F. Padovan @ 2010-04-07 1:20 UTC (permalink / raw)
To: Francisco Alecrim; +Cc: linux-bluetooth
In-Reply-To: <1270591520-2078-1-git-send-email-francisco.alecrim@openbossa.org>
Hi Alecrim,
* Francisco Alecrim <francisco.alecrim@openbossa.org> [2010-04-06 18:05:19 -0400]:
> * Include UUIDs field to method GetProperties(org.bluez.Adapter).
> Applications can get local services(UUIDs) available through DBus.
> * UUIDs per-adapter stored at btd_adapter to prevent some searches not
> necessary regarding it requires information from access_db and service_db.
> * Emit Adapter.PropertyChanged signal when UUIDs change.
> ---
> doc/adapter-api.txt | 5 +++
> src/adapter.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++-
> src/adapter.h | 2 +
> src/sdpd-database.c | 4 ++
> test/list-devices | 3 ++
> 5 files changed, 101 insertions(+), 1 deletions(-)
>
> diff --git a/doc/adapter-api.txt b/doc/adapter-api.txt
> index 48cab40..6098c76 100644
> --- a/doc/adapter-api.txt
> +++ b/doc/adapter-api.txt
> @@ -270,3 +270,8 @@ Properties string Address [readonly]
> array{object} Devices [readonly]
>
> List of device object paths.
> +
> + array{string} UUIDs [readonly]
> +
> + List of 128-bit UUIDs that represents the available
> + local services.
> diff --git a/src/adapter.c b/src/adapter.c
> index 5fd0736..47cef90 100644
> --- a/src/adapter.c
> +++ b/src/adapter.c
> @@ -37,6 +37,7 @@
> #include <bluetooth/hci.h>
> #include <bluetooth/hci_lib.h>
> #include <bluetooth/sdp.h>
> +#include <bluetooth/sdp_lib.h>
>
> #include <glib.h>
> #include <dbus/dbus.h>
> @@ -115,6 +116,7 @@ struct btd_adapter {
> GSList *mode_sessions; /* Request Mode sessions */
> GSList *disc_sessions; /* Discovery sessions */
> guint scheduler_id; /* Scheduler handle */
> + sdp_list_t *services; /* Services associated to adapter */
>
> struct hci_dev dev; /* hci info */
> int8_t tx_power; /* inq response tx power level */
> @@ -1033,6 +1035,75 @@ static void adapter_update_devices(struct btd_adapter *adapter)
> g_free(devices);
> }
>
> +static void adapter_emit_uuids_updated(struct btd_adapter *adapter)
> +{
> + char **uuids;
> + int i;
> + sdp_list_t *list;
> +
> + uuids = g_new0(char *, sdp_list_len(adapter->services) + 1);
> +
> + for (i = 0, list = adapter->services; list; list = list->next, i++) {
> + sdp_record_t *rec = list->data;
> + uuids[i] = bt_uuid2string(&rec->svclass);
> + }
> +
> + emit_array_property_changed(connection, adapter->path,
> + ADAPTER_INTERFACE, "UUIDs",
> + DBUS_TYPE_STRING, &uuids);
> +
> + for (i = 0; uuids[i]; i++)
> + g_free(uuids[i]);
> + g_free(uuids);
> +}
> +
> +/*
> + * adapter_services_inc_rem - Insert or remove UUID from adapter
> + */
> +static void adapter_service_ins_rem(const bdaddr_t *bdaddr, void *rec,
> + gboolean insert)
> +{
> + struct btd_adapter *adapter;
> + GSList *adapters;
> +
> + adapters = NULL;
> +
> + if (bacmp(bdaddr, BDADDR_ANY) != 0) {
> + /* Only one adapter */
> + adapter = manager_find_adapter(bdaddr);
> + if (!adapter)
> + return;
> +
> + adapters = g_slist_append(adapters, adapter);
> + } else {
> + /* Emit D-Bus msg to all adapters */
> + adapters = manager_get_adapters();
> + }
No need for braces here. :)
> +
> + for (; adapters; adapters = adapters->next) {
> + adapter = adapters->data;
> +
> + if (insert == TRUE)
> + adapter->services = sdp_list_append(adapter->services, rec);
> + else
> + adapter->services = sdp_list_remove(adapter->services, rec);
> +
> + adapter_emit_uuids_updated(adapter);
> + }
> +}
> +
> +void adapter_service_insert(const bdaddr_t *bdaddr, void *rec)
> +{
> + /* TRUE to include service*/
> + adapter_service_ins_rem(bdaddr, rec, TRUE);
> +}
> +
> +void adapter_service_remove(const bdaddr_t *bdaddr, void *rec)
> +{
> + /* FALSE to remove service*/
> + adapter_service_ins_rem(bdaddr, rec, FALSE);
> +}
> +
> struct btd_device *adapter_create_device(DBusConnection *conn,
> struct btd_adapter *adapter,
> const char *address)
> @@ -1196,9 +1267,10 @@ static DBusMessage *get_properties(DBusConnection *conn,
> DBusMessageIter dict;
> char str[MAX_NAME_LENGTH + 1], srcaddr[18];
> gboolean value;
> - char **devices;
> + char **devices, **uuids;
> int i;
> GSList *l;
> + sdp_list_t *list;
>
> ba2str(&adapter->bdaddr, srcaddr);
>
> @@ -1270,6 +1342,20 @@ static DBusMessage *get_properties(DBusConnection *conn,
> &devices, i);
> g_free(devices);
>
> + /* UUIDs */
> + uuids = g_new0(char *, sdp_list_len(adapter->services) + 1);
> +
> + for (i = 0, list = adapter->services; list; list = list->next, i++) {
> + sdp_record_t *rec = list->data;
> + uuids[i] = bt_uuid2string(&rec->svclass);
> + }
> +
> + dict_append_array(&dict, "UUIDs", DBUS_TYPE_STRING, &uuids, i);
> +
> + for (i = 0; uuids[i]; i++)
> + g_free(uuids[i]);
> + g_free(uuids);
> +
> dbus_message_iter_close_container(&iter, &dict);
>
> return reply;
> diff --git a/src/adapter.h b/src/adapter.h
> index 9b4ce10..e4307d8 100644
> --- a/src/adapter.h
> +++ b/src/adapter.h
> @@ -121,6 +121,8 @@ void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode);
> void adapter_setname_complete(bdaddr_t *local, uint8_t status);
> void adapter_update_tx_power(bdaddr_t *bdaddr, uint8_t status, void *ptr);
> void adapter_update_local_name(bdaddr_t *bdaddr, uint8_t status, void *ptr);
> +void adapter_service_insert(const bdaddr_t *bdaddr, void *rec);
> +void adapter_service_remove(const bdaddr_t *bdaddr, void *rec);
> void adapter_set_class_complete(bdaddr_t *bdaddr, uint8_t status);
>
> struct agent *adapter_get_agent(struct btd_adapter *adapter);
> diff --git a/src/sdpd-database.c b/src/sdpd-database.c
> index 07a0bc3..224a4e7 100644
> --- a/src/sdpd-database.c
> +++ b/src/sdpd-database.c
> @@ -40,6 +40,7 @@
>
> #include "sdpd.h"
> #include "logging.h"
> +#include "adapter.h"
>
> static sdp_list_t *service_db;
> static sdp_list_t *access_db;
> @@ -183,6 +184,8 @@ void sdp_record_add(const bdaddr_t *device, sdp_record_t *rec)
> dev->handle = rec->handle;
>
> access_db = sdp_list_insert_sorted(access_db, dev, access_sort);
> +
> + adapter_service_insert(device, rec);
> }
>
> static sdp_list_t *record_locate(uint32_t handle)
> @@ -252,6 +255,7 @@ int sdp_record_remove(uint32_t handle)
> if (p) {
> a = (sdp_access_t *) p->data;
> if (a) {
> + adapter_service_remove(&a->device, r);
> access_db = sdp_list_remove(access_db, a);
> access_free(a);
> }
> diff --git a/test/list-devices b/test/list-devices
> index 511d0cf..9120714 100755
> --- a/test/list-devices
> +++ b/test/list-devices
> @@ -40,6 +40,9 @@ for i in adapter_list:
> if (key == "Devices"):
> list = extract_objects(value)
> print " %s = %s" % (key, list)
> + elif (key == "UUIDs"):
> + list = extract_uuids(value)
> + print " %s = %s" % (key, list)
> else:
> print " %s = %s" % (key, value)
>
> --
> 1.6.3.3
>
> --
> 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
--
Gustavo F. Padovan
http://padovan.org
^ permalink raw reply
* Re: upper limit of bonded devices?
From: Peter Dons Tychsen @ 2010-04-06 23:53 UTC (permalink / raw)
To: Iain Hibbert, Garry Paxinos; +Cc: linux-bluetooth
In-Reply-To: <1270583850.437918.726.nullmailer@galant.ukfsn.org>
Hi Iain & Garry,
On Tue, 2010-04-06 at 20:57 +0100, Iain Hibbert wrote:
> Sure, but consider that the page timeout (time to failure of a
> connection
> attempt) is usually around 20 seconds.. and most Bluetooth controllers
> (that I have tried) can only page a single device at a time.. So, if
> you
> don't know which devices are in range, you might be waiting a *long*
> time
> before you connect to anything..
20 seconds for a "page-timeout" is unusual for the reason you just
mentioned. However, the "link-timeout" is usually around 10-20 seconds,
but that is only applicable if an existing links needs to drop. The page
timeout use usually more like 3-5 seconds. Even if it were as high as
you describe, it is easily re-configurable. Going below ~2 seconds is
not a good idea though as you push the odds of hitting the page-scan
window (i do not remember the exact number, look in the spec). Even
better test it (and tune accordingly). For an application like this you
want a low page-timeout.
On Tue, 2010-04-06 at 19:11 +0100, Iain Hibbert wrote:
> you will probably find that because the HS device is very limited in
> resources, it does not keep records of more than one paired device.
> So, if
> you pair with another device it forgets about the first and you will
> not
> be able to connect except that you pair it again.
Many headset devices store store 8 devices they have previously paired
with (the major brands). It is however not a guarantee, so some might
not have it.
>On Tue, 2010-04-06 at 13:08 -0400, Garry Paxinos wrote:
> Is there a practical upper limit of the number of devices that can be
> bonded to a single computer?
The number of devices is almost limitless. However, as Iain said, in
theory this cannot be done with one controller as the maximum devices
for a unit is 7. In practice it looks even worse, as many controllers
become unstable if you go beyond 2 links. The link itself also becomes
unstable when many devices are connected, as you run out of air-time
(your radio can only service one at any time), and you risk loosing a
link. I recommend people to stick with one link pr. application if
stability and speed is the name of the game. If not, test it!
Recently i created a large setup of lots of BT-USB dongles connected via
some hubs to a single box running Bluez. To my delight it was remarkably
easy and stable. The well designed Bluez-API really is a bonus. Doing
this on any other system has only ended in agony. Just having that many
USB devices can cause problems on many systems. This is definitely the
way to go if you are trying to connect to lots of devices in a reliable
way. It is pretty cheap as well, as even good dongles are getting
cheaper even as i type (down to $10-$15)! :-)
Good luck on your project,
Thanks,
/Pedro
^ permalink raw reply
* [PATCH 2/2] Correct UUIDs list to EIR
From: Francisco Alecrim @ 2010-04-06 22:05 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Francisco Alecrim
In-Reply-To: <1270591520-2078-1-git-send-email-francisco.alecrim@openbossa.org>
Correct create_ext_inquiry_response to response only UUIDs per-adapter.
---
src/adapter.c | 3 ++-
src/sdpd-service.c | 5 +++--
src/sdpd.h | 3 ++-
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 47cef90..9e94d86 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -816,7 +816,8 @@ static void update_ext_inquiry_response(struct btd_adapter *adapter)
if (dev->ssp_mode > 0)
create_ext_inquiry_response((char *) dev->name,
- adapter->tx_power, data);
+ adapter->tx_power, adapter->services,
+ data);
if (hci_write_ext_inquiry_response(dd, fec, data,
HCI_REQ_TIMEOUT) < 0)
diff --git a/src/sdpd-service.c b/src/sdpd-service.c
index a8f7d47..4551577 100644
--- a/src/sdpd-service.c
+++ b/src/sdpd-service.c
@@ -167,9 +167,10 @@ uint8_t get_service_classes(const bdaddr_t *bdaddr)
}
void create_ext_inquiry_response(const char *name,
- int8_t tx_power, uint8_t *data)
+ int8_t tx_power, sdp_list_t *services,
+ uint8_t *data)
{
- sdp_list_t *list = sdp_get_record_list();
+ sdp_list_t *list = services;
uint8_t *ptr = data;
uint16_t uuid[24];
int i, index = 0;
diff --git a/src/sdpd.h b/src/sdpd.h
index 1352a83..1f0a229 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -95,4 +95,5 @@ int remove_record_from_server(uint32_t handle);
uint8_t get_service_classes(const bdaddr_t *bdaddr);
void create_ext_inquiry_response(const char *name,
- int8_t tx_power, uint8_t *data);
+ int8_t tx_power, sdp_list_t *services,
+ uint8_t *data);
--
1.6.3.3
^ permalink raw reply related
* [PATCH 1/2] Report local services(UUIDs) through DBus
From: Francisco Alecrim @ 2010-04-06 22:05 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Francisco Alecrim
* Include UUIDs field to method GetProperties(org.bluez.Adapter).
Applications can get local services(UUIDs) available through DBus.
* UUIDs per-adapter stored at btd_adapter to prevent some searches not
necessary regarding it requires information from access_db and service_db.
* Emit Adapter.PropertyChanged signal when UUIDs change.
---
doc/adapter-api.txt | 5 +++
src/adapter.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++-
src/adapter.h | 2 +
src/sdpd-database.c | 4 ++
test/list-devices | 3 ++
5 files changed, 101 insertions(+), 1 deletions(-)
diff --git a/doc/adapter-api.txt b/doc/adapter-api.txt
index 48cab40..6098c76 100644
--- a/doc/adapter-api.txt
+++ b/doc/adapter-api.txt
@@ -270,3 +270,8 @@ Properties string Address [readonly]
array{object} Devices [readonly]
List of device object paths.
+
+ array{string} UUIDs [readonly]
+
+ List of 128-bit UUIDs that represents the available
+ local services.
diff --git a/src/adapter.c b/src/adapter.c
index 5fd0736..47cef90 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -37,6 +37,7 @@
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
#include <glib.h>
#include <dbus/dbus.h>
@@ -115,6 +116,7 @@ struct btd_adapter {
GSList *mode_sessions; /* Request Mode sessions */
GSList *disc_sessions; /* Discovery sessions */
guint scheduler_id; /* Scheduler handle */
+ sdp_list_t *services; /* Services associated to adapter */
struct hci_dev dev; /* hci info */
int8_t tx_power; /* inq response tx power level */
@@ -1033,6 +1035,75 @@ static void adapter_update_devices(struct btd_adapter *adapter)
g_free(devices);
}
+static void adapter_emit_uuids_updated(struct btd_adapter *adapter)
+{
+ char **uuids;
+ int i;
+ sdp_list_t *list;
+
+ uuids = g_new0(char *, sdp_list_len(adapter->services) + 1);
+
+ for (i = 0, list = adapter->services; list; list = list->next, i++) {
+ sdp_record_t *rec = list->data;
+ uuids[i] = bt_uuid2string(&rec->svclass);
+ }
+
+ emit_array_property_changed(connection, adapter->path,
+ ADAPTER_INTERFACE, "UUIDs",
+ DBUS_TYPE_STRING, &uuids);
+
+ for (i = 0; uuids[i]; i++)
+ g_free(uuids[i]);
+ g_free(uuids);
+}
+
+/*
+ * adapter_services_inc_rem - Insert or remove UUID from adapter
+ */
+static void adapter_service_ins_rem(const bdaddr_t *bdaddr, void *rec,
+ gboolean insert)
+{
+ struct btd_adapter *adapter;
+ GSList *adapters;
+
+ adapters = NULL;
+
+ if (bacmp(bdaddr, BDADDR_ANY) != 0) {
+ /* Only one adapter */
+ adapter = manager_find_adapter(bdaddr);
+ if (!adapter)
+ return;
+
+ adapters = g_slist_append(adapters, adapter);
+ } else {
+ /* Emit D-Bus msg to all adapters */
+ adapters = manager_get_adapters();
+ }
+
+ for (; adapters; adapters = adapters->next) {
+ adapter = adapters->data;
+
+ if (insert == TRUE)
+ adapter->services = sdp_list_append(adapter->services, rec);
+ else
+ adapter->services = sdp_list_remove(adapter->services, rec);
+
+ adapter_emit_uuids_updated(adapter);
+ }
+}
+
+void adapter_service_insert(const bdaddr_t *bdaddr, void *rec)
+{
+ /* TRUE to include service*/
+ adapter_service_ins_rem(bdaddr, rec, TRUE);
+}
+
+void adapter_service_remove(const bdaddr_t *bdaddr, void *rec)
+{
+ /* FALSE to remove service*/
+ adapter_service_ins_rem(bdaddr, rec, FALSE);
+}
+
struct btd_device *adapter_create_device(DBusConnection *conn,
struct btd_adapter *adapter,
const char *address)
@@ -1196,9 +1267,10 @@ static DBusMessage *get_properties(DBusConnection *conn,
DBusMessageIter dict;
char str[MAX_NAME_LENGTH + 1], srcaddr[18];
gboolean value;
- char **devices;
+ char **devices, **uuids;
int i;
GSList *l;
+ sdp_list_t *list;
ba2str(&adapter->bdaddr, srcaddr);
@@ -1270,6 +1342,20 @@ static DBusMessage *get_properties(DBusConnection *conn,
&devices, i);
g_free(devices);
+ /* UUIDs */
+ uuids = g_new0(char *, sdp_list_len(adapter->services) + 1);
+
+ for (i = 0, list = adapter->services; list; list = list->next, i++) {
+ sdp_record_t *rec = list->data;
+ uuids[i] = bt_uuid2string(&rec->svclass);
+ }
+
+ dict_append_array(&dict, "UUIDs", DBUS_TYPE_STRING, &uuids, i);
+
+ for (i = 0; uuids[i]; i++)
+ g_free(uuids[i]);
+ g_free(uuids);
+
dbus_message_iter_close_container(&iter, &dict);
return reply;
diff --git a/src/adapter.h b/src/adapter.h
index 9b4ce10..e4307d8 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -121,6 +121,8 @@ void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode);
void adapter_setname_complete(bdaddr_t *local, uint8_t status);
void adapter_update_tx_power(bdaddr_t *bdaddr, uint8_t status, void *ptr);
void adapter_update_local_name(bdaddr_t *bdaddr, uint8_t status, void *ptr);
+void adapter_service_insert(const bdaddr_t *bdaddr, void *rec);
+void adapter_service_remove(const bdaddr_t *bdaddr, void *rec);
void adapter_set_class_complete(bdaddr_t *bdaddr, uint8_t status);
struct agent *adapter_get_agent(struct btd_adapter *adapter);
diff --git a/src/sdpd-database.c b/src/sdpd-database.c
index 07a0bc3..224a4e7 100644
--- a/src/sdpd-database.c
+++ b/src/sdpd-database.c
@@ -40,6 +40,7 @@
#include "sdpd.h"
#include "logging.h"
+#include "adapter.h"
static sdp_list_t *service_db;
static sdp_list_t *access_db;
@@ -183,6 +184,8 @@ void sdp_record_add(const bdaddr_t *device, sdp_record_t *rec)
dev->handle = rec->handle;
access_db = sdp_list_insert_sorted(access_db, dev, access_sort);
+
+ adapter_service_insert(device, rec);
}
static sdp_list_t *record_locate(uint32_t handle)
@@ -252,6 +255,7 @@ int sdp_record_remove(uint32_t handle)
if (p) {
a = (sdp_access_t *) p->data;
if (a) {
+ adapter_service_remove(&a->device, r);
access_db = sdp_list_remove(access_db, a);
access_free(a);
}
diff --git a/test/list-devices b/test/list-devices
index 511d0cf..9120714 100755
--- a/test/list-devices
+++ b/test/list-devices
@@ -40,6 +40,9 @@ for i in adapter_list:
if (key == "Devices"):
list = extract_objects(value)
print " %s = %s" % (key, list)
+ elif (key == "UUIDs"):
+ list = extract_uuids(value)
+ print " %s = %s" % (key, list)
else:
print " %s = %s" % (key, value)
--
1.6.3.3
^ permalink raw reply related
* Re: upper limit of bonded devices?
From: Iain Hibbert @ 2010-04-06 19:57 UTC (permalink / raw)
To: Garry Paxinos; +Cc: linux-bluetooth
In-Reply-To: <x2xf3ae2ce11004061132gd546fb7emd890e6c096c72bd3@mail.gmail.com>
On Tue, 6 Apr 2010, Garry Paxinos wrote:
> Thanks for the quick reply! We actually have an application that
> could conceivable pair with over 1M devices if the project is
> successful.
>
> There are really two other issues to resolve in this scenario -
>
> 1. Is it possible to have the computer initiate the connection to a
> bonded device without previously knowing what devices are currently in
> the vicinity? Especially when our bonded DB is excessively large.
Sure, but consider that the page timeout (time to failure of a connection
attempt) is usually around 20 seconds.. and most Bluetooth controllers
(that I have tried) can only page a single device at a time.. So, if you
don't know which devices are in range, you might be waiting a *long* time
before you connect to anything..
I have not read the 3.0 spec though, and using another transport (wifi)
might make some things faster and make what you want possible.
> 2. Is there a way (even if we need to do device driver work) to gain
> access to signal strength before bonding to a device? And before
> connecting to a device? We really need to limit ourselves to bonding
> and connecting with devices that are located in a very close
> proximity.
Hrm, you can do inquiry-with-rssi which will tell you the signal strength.
But, that requires the remote device to be discoverable. And, it takes
more time (most Bluetooth controllers are not able to make connections at
the same time as discovering nearby devices). And, I read of experiments
trying to correlate signal strength with distance which were not that
successful anyway.
You don't say too much about the role and ownership of different devices
in your application network, and if you really need the generic
interoperability of Bluetooth. By this, I mean for instance if you need to
be able to contact standard devices (eg phones owned by third-parties,
possibly running your app amongst other things) or if the devices will be
custom built for your application (in which case, you can control
everything about how the device behaves)
There is unused capability in the "class of device" identifier which is
provided in inquiry results and can be used to filter inquiry results
before trying connections. But, in a 'standard' device you might have
trouble using it for your own purposes..
regards,
iain
^ permalink raw reply
* Re: upper limit of bonded devices?
From: Garry Paxinos @ 2010-04-06 18:32 UTC (permalink / raw)
To: Iain Hibbert; +Cc: linux-bluetooth
In-Reply-To: <1270577971.764253.580.nullmailer@galant.ukfsn.org>
Thanks for the quick reply! We actually have an application that
could conceivable pair with over 1M devices if the project is
successful.
There are really two other issues to resolve in this scenario -
1. Is it possible to have the computer initiate the connection to a
bonded device without previously knowing what devices are currently in
the vicinity? Especially when our bonded DB is excessively large.
2. Is there a way (even if we need to do device driver work) to gain
access to signal strength before bonding to a device? And before
connecting to a device? We really need to limit ourselves to bonding
and connecting with devices that are located in a very close
proximity.
Thanks,
Pax.
On Tue, Apr 6, 2010 at 2:19 PM, Iain Hibbert <plunky@rya-online.net> wrote:
> On Tue, 6 Apr 2010, Garry Paxinos wrote:
>
>> Is there a practical upper limit of the number of devices that can be
>> bonded to a single computer?
>>
>> I am considering reworking the bonding code to use a MySQL DB to store
>> the list of devices, but was wondering if there was any other limit
>> (either coding or practical). For example, can a single computer
>> bond with 1k devices? what about 100K or even 1M ?
>
> There is no reason it cannot pair with such a number of devices though I
> can't think how you will fit them all in your pocket..
>
> ..but bear in mind that it cannot connect with more than 7 in a Bluetooth
> piconet at any one time. (perhaps with other transports it can do more)
> and because pairing generally involves human interaction, it is not a
> frequently occurring event.
>
> I suspect the vast majority of usage case is pairing with <10 in the
> lifetime of the device and that using a MySQL database would be just
> overkill.. but perhaps there are other, more minimal, data-storage front
> ends that can be used (cdb?), if you wanted to provide generic access to
> the information..
>
> regards,
> iain
>
^ permalink raw reply
* Re: upper limit of bonded devices?
From: Iain Hibbert @ 2010-04-06 18:19 UTC (permalink / raw)
To: Garry Paxinos; +Cc: linux-bluetooth
In-Reply-To: <j2tf3ae2ce11004061008x26da852el996b017a5115d595@mail.gmail.com>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1131 bytes --]
On Tue, 6 Apr 2010, Garry Paxinos wrote:
> Is there a practical upper limit of the number of devices that can be
> bonded to a single computer?
>
> I am considering reworking the bonding code to use a MySQL DB to store
> the list of devices, but was wondering if there was any other limit
> (either coding or practical). For example, can a single computer
> bond with 1k devices? what about 100K or even 1M ?
There is no reason it cannot pair with such a number of devices though I
can't think how you will fit them all in your pocket..
..but bear in mind that it cannot connect with more than 7 in a Bluetooth
piconet at any one time. (perhaps with other transports it can do more)
and because pairing generally involves human interaction, it is not a
frequently occurring event.
I suspect the vast majority of usage case is pairing with <10 in the
lifetime of the device and that using a MySQL database would be just
overkill.. but perhaps there are other, more minimal, data-storage front
ends that can be used (cdb?), if you wanted to provide generic access to
the information..
regards,
iain
^ permalink raw reply
* Re: Question regarding HS Connection
From: Iain Hibbert @ 2010-04-06 18:11 UTC (permalink / raw)
To: nirav rabara; +Cc: linux-bluetooth
In-Reply-To: <g2p912bb79a1004060553kdec12987gc9c957506b436c1e@mail.gmail.com>
On Tue, 6 Apr 2010, nirav rabara wrote:
> My question is if such the case than how to connect with HS?
you will probably find that because the HS device is very limited in
resources, it does not keep records of more than one paired device. So, if
you pair with another device it forgets about the first and you will not
be able to connect except that you pair it again.
some HS device might be able to store more than one pairing but I don't
know how you would find that out except by trying them all..
iain
^ permalink raw reply
* Re: upper limit of bonded devices?
From: Garry Paxinos @ 2010-04-06 17:08 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <r2if3ae2ce11004061001mc539e7eaq206d43ffb12fb2d2@mail.gmail.com>
Is there a practical upper limit of the number of devices that can be
bonded to a single computer?
I am considering reworking the bonding code to use a MySQL DB to store
the list of devices, but was wondering if there was any other limit
(either coding or practical). For example, can a single computer
bond with 1k devices? what about 100K or even 1M ?
Thanks,
Pax.
^ permalink raw reply
* [PATCH] Multi-Channel Adaptation Protocol.
From: Santiago Carot Nemesio @ 2010-04-06 14:00 UTC (permalink / raw)
To: linux-bluetooth
Support for Standard OP. Codes.
Signed-off-by: Santiago Carot-Nemesio <sancane@gmail.com>
Reviewed-by: Jose Antonio Santos Cadenas <santoscadenas@gmail.com>
---
Makefile.am | 11 +-
acinclude.m4 | 6 +
mcap/mcap.c | 1807 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
mcap/mcap.h | 174 ++++++
mcap/mcap_lib.h | 137 +++++
5 files changed, 2134 insertions(+), 1 deletions(-)
create mode 100644 mcap/mcap.c
create mode 100644 mcap/mcap.h
create mode 100644 mcap/mcap_lib.h
diff --git a/Makefile.am b/Makefile.am
index a9046db..3590cdb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -101,6 +101,7 @@ gdbus_sources = gdbus/gdbus.h gdbus/mainloop.c gdbus/object.c gdbus/watch.c
builtin_modules =
builtin_sources =
builtin_nodist =
+mcap_sources =
if PNATPLUGIN
builtin_modules += pnat
@@ -168,6 +169,10 @@ builtin_modules += service
builtin_sources += plugins/service.c
endif
+if MCAP
+mcap_sources += mcap/mcap_lib.h mcap/mcap.h mcap/mcap.c
+endif
+
builtin_modules += hciops
builtin_sources += plugins/hciops.c
@@ -196,7 +201,8 @@ src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
src/adapter.h src/adapter.c \
src/device.h src/device.c \
src/dbus-common.c src/dbus-common.h \
- src/dbus-hci.h src/dbus-hci.c
+ src/dbus-hci.h src/dbus-hci.c \
+ $(mcap_sources)
src_bluetoothd_LDADD = lib/libbluetooth.la @GLIB_LIBS@ @DBUS_LIBS@ \
@CAPNG_LIBS@ -ldl
src_bluetoothd_LDFLAGS = -Wl,--export-dynamic \
@@ -318,6 +324,9 @@ AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @CAPNG_CFLAGS@ \
INCLUDES = -I$(builddir)/lib -I$(builddir)/src -I$(srcdir)/src \
-I$(srcdir)/audio -I$(srcdir)/sbc -I$(srcdir)/gdbus
+if MCAP
+INCLUDES += -I$(builddir)/mcap
+endif
pkgconfigdir = $(libdir)/pkgconfig
diff --git a/acinclude.m4 b/acinclude.m4
index f7bb047..b512cfb 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -167,6 +167,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
serial_enable=yes
network_enable=yes
service_enable=yes
+ mcap_enable=no
pnat_enable=no
tracer_enable=no
tools_enable=yes
@@ -215,6 +216,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
service_enable=${enableval}
])
+ AC_ARG_ENABLE(mcap, AC_HELP_STRING([--enable-mcap], [enable mcap support]), [
+ mcap_enable=${enableval}
+ ])
+
AC_ARG_ENABLE(pnat, AC_HELP_STRING([--enable-pnat], [enable pnat plugin]), [
pnat_enable=${enableval}
])
@@ -325,6 +330,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
AM_CONDITIONAL(SERIALPLUGIN, test "${serial_enable}" = "yes")
AM_CONDITIONAL(NETWORKPLUGIN, test "${network_enable}" = "yes")
AM_CONDITIONAL(SERVICEPLUGIN, test "${service_enable}" = "yes")
+ AM_CONDITIONAL(MCAP, test "${mcap_enable}" = "yes")
AM_CONDITIONAL(ECHOPLUGIN, test "no" = "yes")
AM_CONDITIONAL(PNATPLUGIN, test "${pnat_enable}" = "yes")
AM_CONDITIONAL(TRACER, test "${tracer_enable}" = "yes")
diff --git a/mcap/mcap.c b/mcap/mcap.c
new file mode 100644
index 0000000..28c586c
--- /dev/null
+++ b/mcap/mcap.c
@@ -0,0 +1,1807 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2010 Santiago Carot Nemesio <sancane at gmail.com>
+ * Copyright (C) 2010 Jose Antonio Santos-Cadenas <santoscadenas at gmail.com>
+ * Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <gdbus.h>
+#include "adapter.h"
+#include "logging.h"
+#include "btio.h"
+#include "error.h"
+
+#include <netinet/in.h>
+
+#include "mcap.h"
+#include "mcap_lib.h"
+
+//#define STATE2STR(_mcl) state2str(_mcl->state)
+#define MCAP_ERROR mcap_error_quark()
+#define SET_DEFAULT_MCL_CB(__mcl) do { \
+ __mcl->cb->mdl_connected = default_mdl_connected_cb; \
+ __mcl->cb->mdl_closed = default_mdl_closed_cb; \
+ __mcl->cb->mdl_deleted = default_mdl_deleted_cb; \
+ __mcl->cb->mdl_conn_req = default_mdl_conn_req_cb; \
+ __mcl->cb->mdl_reconn_req = default_mdl_reconn_req_cb; \
+} while(0)
+#define RELEASE_TIMER(__mcl) do { \
+ g_source_remove(__mcl->tid); \
+ __mcl->tid = 0; \
+} while(0)
+
+#define RESPONSE_TIMER 4 /* seconds */
+
+#define MCAP_IS_STD_OPCODE(_oc) (_oc >= MCAP_ERROR_RSP && \
+ _oc <= MCAP_MD_DELETE_MDL_RSP)
+
+typedef enum {
+ MCL_CONNECTED,
+ MCL_PENDING,
+ MCL_ACTIVE
+} MCLState;
+
+typedef enum {
+ MCL_ACCEPTOR,
+ MCL_INITIATOR,
+} MCLRole;
+
+typedef enum {
+ MCL_AVAILABLE,
+ MCL_WAITING_RSP,
+} MCAPCtrl;
+
+typedef enum {
+ MDL_WAITING,
+ MDL_CONNECTED,
+ MDL_CLOSED
+} MDLState;
+
+struct mcap_mcl_cb {
+ mcap_mdl_event_cb mdl_connected; /* Remote device has created an mdl */
+ mcap_mdl_event_cb mdl_closed; /* Remote device has closed an mdl */
+ mcap_mdl_event_cb mdl_deleted; /* Remote device deleted an mdl */
+ mcap_remote_mdl_conn_req_cb mdl_conn_req; /* Remote deive requested create an mdl */
+ mcap_remote_mdl_reconn_req_cb mdl_reconn_req; /* Remote device requested reconnect previus mdl */
+ gpointer user_data; /* user data */
+};
+
+struct mcap_session {
+ bdaddr_t src; /* Source address */
+ GIOChannel *ccio; /* Control Channel IO */
+ GIOChannel *dcio; /* Data Channel IO */
+ GSList *mcls; /* MCAP session list */
+ BtIOSecLevel sec; /* Security level */
+ mcap_mcl_event_cb mcl_closed_cb; /* Mcl closed callback */
+ mcap_mcl_event_cb mcl_created_cb; /* New Mcl createc callback */
+ gpointer user_data; /* User data for callbacks */
+};
+
+struct mcap_mcl {
+ struct mcap_session *ms; /* MCAP session where this MCL belongs */
+ bdaddr_t addr; /* device address */
+ GIOChannel *cc; /* MCAP Control Channel IO */
+ guint wid; /* MCL Watcher id */
+ GSList *mdls; /* List of Data Channels shorted by mdlid */
+ MCLState state; /* mcap state */
+ MCLRole role; /* initiator or aceptor of this MCL*/
+ MCAPCtrl req; /* Request control flag */
+ void *priv_data; /* Temporal data to manage responses */
+ struct mcap_mcl_cb *cb; /* MCL callbacks */
+ guint tid; /* Timer id for waiting for a resposne */
+ uint8_t *lcmd; /* Last command sent */
+ gboolean sup_opc; /* The remote device supports opcodes */
+};
+
+struct mcap_mdl {
+ struct mcap_mcl *mcl; /* MCAP mcl for this mdl */
+ GIOChannel *dc; /* MCAP Data Channel IO */
+ guint wid; /* MDL Watcher id */
+ uint16_t mdlid; /* MDL id */
+ uint8_t mdep_id; /* MCAP Data End Point */
+ MDLState state; /* MDL state */
+};
+
+struct connect_mcl {
+ struct mcap_mcl *mcl; /* MCL for outgoing connection */
+ mcap_mcl_connect_cb connect_cb; /* Connect callback */
+ gpointer user_data; /* Callback user data */
+};
+
+typedef union {
+ mcap_mdl_operation_cb op;
+ mcap_mdl_operation_conf_cb op_conf;
+ mcap_mdl_del_cb del;
+} mcap_cb_type;
+
+struct mcap_mdl_op_cb {
+ struct mcap_mdl *mdl; /* MCL for outgoing connection */
+ mcap_cb_type cb; /* Operation callback */
+ gpointer user_data; /* Callback user data */
+};
+
+static void mcap_notify_error(struct mcap_mcl *mcl, GError *err);
+static int mcap_send_data(int sock, const uint8_t *buf, uint32_t size);
+static int send4B_cmd(struct mcap_mcl *mcl, uint8_t oc,
+ uint8_t rc, uint16_t mdl);
+static int send5B_cmd(struct mcap_mcl *mcl, uint8_t oc, uint8_t rc,
+ uint16_t mdl, uint8_t param);
+
+/* MCAP finite state machine functions */
+static void proc_req_connected(struct mcap_mcl *mcl, uint8_t *cmd, int len);
+static void proc_req_pending(struct mcap_mcl *mcl, uint8_t *cmd, int len);
+static void proc_req_active(struct mcap_mcl *mcl, uint8_t *cmd, int len);
+
+static void (*proc_req[])(struct mcap_mcl *mcl, uint8_t *cmd, int len) = {
+ proc_req_connected,
+ proc_req_pending,
+ proc_req_active
+ };
+
+static void default_mdl_connected_cb(struct mcap_mdl *mdl, gpointer data)
+{
+ debug("MCAP Unmanaged mdl connection");
+}
+static void default_mdl_closed_cb(struct mcap_mdl *mdl, gpointer data)
+{
+ debug("MCAP Unmanaged mdl clsoed");
+}
+static void default_mdl_deleted_cb(struct mcap_mdl *mdl, gpointer data)
+{
+ debug("MCAP Unmanaged mdl deleted");
+}
+static uint8_t default_mdl_conn_req_cb(struct mcap_mcl *mcl,
+ uint8_t mdepid, uint16_t mdlid,
+ uint8_t *conf, gpointer data)
+{
+ debug("MCAP mdl remote connection aborted");
+ /* Due to this callback is not managed this request won't be supported */
+ return MCAP_REQUEST_NOT_SUPPORTED;
+}
+static uint8_t default_mdl_reconn_req_cb(struct mcap_mdl *mdl,
+ gpointer data)
+{
+ debug("MCAP mdl remote reconnection aborted");
+ /* Due to this callback is not managed this request won't be supported */
+ return MCAP_REQUEST_NOT_SUPPORTED;
+}
+
+GQuark mcap_error_quark(void)
+{
+ return g_quark_from_static_string("mcap-error-quark");
+}
+
+static char *error2str(uint8_t rc)
+{
+ switch (rc) {
+ case MCAP_SUCCESS:
+ return "Success";
+ case MCAP_INVALID_OP_CODE:
+ return "Invalid Op Code";
+ case MCAP_INVALID_PARAM_VALUE:
+ return "Ivalid Parameter Value";
+ case MCAP_INVALID_MDEP:
+ return "Invalid MDEP";
+ case MCAP_MDEP_BUSY:
+ return "MDEP Busy";
+ case MCAP_INVALID_MDL:
+ return "Invalid MDL";
+ case MCAP_MDL_BUSY:
+ return "MDL Busy";
+ case MCAP_INVALID_OPERATION:
+ return "Invalid Operation";
+ case MCAP_RESOURCE_UNAVAILABLE:
+ return "Resource Unavailable";
+ case MCAP_UNESPECIFIED_ERROR:
+ return "Unspecified Error";
+ case MCAP_REQUEST_NOT_SUPPORTED:
+ return "Request Not Supported";
+ case MCAP_CONFIGURATION_REJECTED:
+ return "Configuration Rejected";
+ default:
+ return "Unknown Op Code";
+ }
+}
+
+static struct mcap_mcl *find_mcl(GSList *list, const bdaddr_t *addr)
+{
+ GSList *l;
+ struct mcap_mcl *mcl;
+
+ for (l = list; l; l = l->next) {
+ mcl = l->data;
+
+ if (!bacmp(&mcl->addr, addr))
+ return mcl;
+ }
+
+ return NULL;
+}
+
+static void update_mcl_state(struct mcap_mcl *mcl)
+{
+ GSList *l;
+ struct mcap_mdl *mdl;
+
+ for (l = mcl->mdls; l; l = l->next) {
+ mdl = l->data;
+
+ if (mdl->state == MDL_CONNECTED) {
+ mcl->state = MCL_ACTIVE;
+ return;
+ }
+ }
+
+ mcl->state = MCL_CONNECTED;
+}
+
+static int mcap_send_data(int sock, const uint8_t *buf, uint32_t size)
+{
+ uint32_t sent = 0;
+
+ while (sent < size) {
+ int n = send(sock, buf + sent, size - sent, 0);
+ if (n < 0)
+ return -1;
+ sent += n;
+ }
+ return 0;
+}
+
+static void mcap_send_std_opcode(struct mcap_mcl *mcl, const uint8_t *buf,
+ uint32_t size, GError **err)
+{
+ if (mcl->req != MCL_AVAILABLE) {
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "Pending request");
+ return;
+ }
+
+ if (!mcl->sup_opc) {
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "Remote does not support standard opcodes");
+ return;
+ }
+
+ if (mcap_send_data(g_io_channel_unix_get_fd(mcl->cc), buf, size) < 0)
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "Data can't be sent, write error");
+}
+
+static int send4B_cmd(struct mcap_mcl *mcl, uint8_t oc, uint8_t rc,
+ uint16_t mdl)
+{
+ uint8_t *rsp;
+ mcap4B_rsp *rsp_err;
+ int sent;
+
+
+ rsp = g_malloc0(sizeof(mcap4B_rsp));
+
+ rsp_err = (mcap4B_rsp *)rsp;
+ rsp_err->op = oc;
+ rsp_err->rc = rc;
+ rsp_err->mdl = htons (mdl);
+
+ sent = mcap_send_data(g_io_channel_unix_get_fd(mcl->cc),
+ rsp,
+ sizeof(mcap4B_rsp));
+ g_free(rsp);
+ return sent;
+}
+
+static int send5B_cmd(struct mcap_mcl *mcl, uint8_t oc, uint8_t rc,
+ uint16_t mdl, uint8_t param)
+{
+ uint8_t *rsp;
+ mcap5B_rsp *suc;
+ int sent;
+
+ rsp = g_malloc0(sizeof(mcap5B_rsp));
+
+ suc = (mcap5B_rsp *)rsp;
+ suc->op = oc;
+ suc->rc = rc;
+ suc->mdl = htons(mdl);
+ suc->param = param;
+
+ sent = mcap_send_data(g_io_channel_unix_get_fd(mcl->cc), rsp,
+ sizeof(mcap5B_rsp));
+ g_free(rsp);
+ return sent;
+}
+
+static uint16_t generate_mdlid(struct mcap_mcl *mcl)
+{
+ uint16_t mdlid = MCAP_MDLID_INITIAL;
+ struct mcap_mdl *mdl;
+ GSList *l;
+
+ for (l = mcl->mdls; l; l = l->next) {
+ mdl = l->data;
+ if (mdlid < mdl->mdlid)
+ break;
+ else
+ mdlid = mdl->mdlid + 1;
+ }
+
+ if (mdlid > MCAP_MDLID_FINAL)
+ return 0;
+
+ return mdlid;
+}
+
+static uint8_t *create_req(uint8_t op, uint16_t mdl_id)
+{
+ uint8_t *req;
+ mcap_md_req *req_cmd;
+
+ req = g_malloc0(sizeof(mcap_md_req));
+
+ req_cmd = (mcap_md_req *)req;
+ req_cmd->op = op;
+ req_cmd->mdl = htons(mdl_id);
+
+ return req;
+}
+
+static uint8_t *create_mdl_req(uint16_t mdl_id, uint8_t mdep, uint8_t conf)
+{
+ uint8_t *req;
+ mcap_md_create_mdl_req *req_mdl;
+
+ req = g_malloc0(sizeof(mcap_md_create_mdl_req));
+
+ req_mdl = (mcap_md_create_mdl_req *)req;
+ req_mdl->op = MCAP_MD_CREATE_MDL_REQ;
+ req_mdl->mdl = htons(mdl_id);
+ req_mdl->mdep = mdep;
+ req_mdl->conf = conf;
+
+ return req;
+}
+
+static gint compare_mdl(gconstpointer a, gconstpointer b)
+{
+ const struct mcap_mdl *mdla = a;
+ const struct mcap_mdl *mdlb = b;
+
+ if (mdla->mdlid == mdlb->mdlid)
+ return 0;
+ else if (mdla->mdlid < mdlb->mdlid)
+ return -1;
+ else
+ return 1;
+}
+
+static gboolean wait_response_timer(gpointer data)
+{
+ struct mcap_mcl *mcl = data;
+ struct mcap_mdl_op_cb *con = mcl->priv_data;
+ struct mcap_mdl *mdl = con->mdl;
+
+ GError *gerr = NULL;
+
+ RELEASE_TIMER(mcl);
+ mcl->mdls = g_slist_remove(mcl->mdls, mdl);
+ g_free(mdl);
+
+ mcl->req = MCL_AVAILABLE;
+ update_mcl_state(mcl);
+
+ g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "Timeout waiting response");
+
+ mcap_notify_error(mcl, gerr);
+
+ g_error_free(gerr);
+ mcl->ms->mcl_closed_cb(mcl, mcl->ms->user_data);
+ mcap_close_mcl(mcl);
+ return FALSE;
+}
+
+void mcap_req_mdl_creation(struct mcap_mcl *mcl,
+ uint8_t mdepid,
+ uint8_t conf,
+ GError **err,
+ mcap_mdl_operation_conf_cb connect_cb,
+ gpointer user_data)
+{
+ struct mcap_mdl *mdl;
+ struct mcap_mdl_op_cb *con;
+ uint8_t *cmd = NULL;
+ uint16_t id;
+
+ id = generate_mdlid(mcl);
+ if (!id) {
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "Not more mdlids available");
+ return;
+ }
+
+ mdl = g_new0(struct mcap_mdl, 1);
+ mdl->mcl = mcl;
+ mdl->mdlid = id;
+ mdl->mdep_id = mdepid;
+ mdl->state = MDL_WAITING;
+
+ con = g_new0(struct mcap_mdl_op_cb, 1);
+ con->mdl = mdl;
+ con->cb.op_conf = connect_cb;
+ con->user_data = user_data;
+
+ cmd = create_mdl_req(id, mdepid, conf);
+ mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_create_mdl_req), err);
+ if (*err) {
+ g_free(mdl);
+ g_free(con);
+ g_free(cmd);
+ return;
+ }
+
+ mcl->state = MCL_ACTIVE;
+ mcl->req = MCL_WAITING_RSP;
+ mcl->priv_data = con;
+ mcl->lcmd = cmd;
+ mcl->mdls = g_slist_insert_sorted(mcl->mdls, mdl, compare_mdl);
+ mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer, mcl);
+}
+
+void mcap_req_mdl_reconnect(struct mcap_mdl *mdl,
+ GError **err,
+ mcap_mdl_operation_cb reconnect_cb,
+ gpointer user_data)
+{
+ struct mcap_mdl_op_cb *con;
+ struct mcap_mcl *mcl = mdl->mcl;
+ uint8_t *cmd;
+
+ if (mdl->state != MDL_CLOSED) {
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "MDL is not closed");
+ return;
+ }
+ con = g_new0(struct mcap_mdl_op_cb, 1);
+
+ cmd = create_req(MCAP_MD_RECONNECT_MDL_REQ, mdl->mdlid);
+ mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err);
+ if (*err) {
+ g_free(con);
+ g_free(cmd);
+ return;
+ }
+
+ mdl->state = MDL_WAITING;
+
+ con->mdl = mdl;
+ con->cb.op = reconnect_cb;
+ con->user_data = user_data;
+
+ mcl->lcmd = cmd;
+ mcl->req = MCL_WAITING_RSP;
+ mcl->priv_data = con;
+
+ mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer, mcl);
+}
+
+void mcap_req_mdl_deletion(struct mcap_mdl *mdl, GError **err,
+ mcap_mdl_del_cb delete_cb, gpointer user_data)
+{
+ struct mcap_mcl *mcl= mdl->mcl;
+ struct mcap_mdl_op_cb *con;
+ GSList *l;
+ uint8_t *cmd;
+
+ l = g_slist_find(mcl->mdls, mdl);
+
+ if (!l) {
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_NOT_FOUND,
+ "Mdl not found");
+ return;
+ }
+
+ if (mdl->state == MDL_WAITING) {
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "Not valid petition in this mdl state");
+ return;
+ }
+
+ con = g_new0(struct mcap_mdl_op_cb, 1);
+ con->mdl = mdl;
+ con->cb.del = delete_cb;
+ con->user_data = user_data;
+
+ cmd = create_req(MCAP_MD_DELETE_MDL_REQ, mdl->mdlid);
+ mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err);
+ if (*err) {
+ g_free(con);
+ g_free(cmd);
+ return;
+ }
+
+ mcl->lcmd = cmd;
+ mcl->req = MCL_WAITING_RSP;
+ mcl->priv_data = con;
+
+ mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer, mcl);
+}
+
+void mcap_mdl_abort(struct mcap_mdl *mdl, GError **err,
+ mcap_mdl_del_cb abort_cb, gpointer user_data)
+{
+ struct mcap_mdl_op_cb *con;
+ struct mcap_mcl *mcl = mdl->mcl;
+ uint8_t *cmd;
+
+ if (mdl->state != MDL_WAITING) {
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
+ "Mdl in invalid state");
+ return;
+ }
+
+ con = g_new0(struct mcap_mdl_op_cb, 1);
+ cmd = create_req(MCAP_MD_ABORT_MDL_REQ, mdl->mdlid);
+ mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err);
+ if (*err) {
+ g_free(con);
+ g_free(cmd);
+ return;
+ }
+
+ con->mdl = mdl;
+ con->cb.del = abort_cb;
+ con->user_data = user_data;
+
+ mcl->lcmd = cmd;
+ mcl->req = MCL_WAITING_RSP;
+ mcl->priv_data = con;
+
+ mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer, mcl);
+}
+
+int mcap_mdl_get_fd(struct mcap_mdl *mdl)
+{
+ if (mdl->dc)
+ return g_io_channel_unix_get_fd(mdl->dc);
+ return -1;
+}
+
+static void shutdown_mdl(struct mcap_mdl *mdl)
+{
+ mdl->state = MDL_CLOSED;
+
+ g_source_remove(mdl->wid);
+
+ if (mdl->dc) {
+ g_io_channel_shutdown(mdl->dc, TRUE, NULL);
+ g_io_channel_unref(mdl->dc);
+ mdl->dc = NULL;
+ }
+}
+
+static void mcap_free_mdls(struct mcap_mcl *mcl)
+{
+ GSList *l;
+ struct mcap_mdl *mdl;
+
+ if (!mcl->mdls)
+ return;
+
+ for (l = mcl->mdls; l; l = l->next) {
+ mdl = l->data;
+ shutdown_mdl(mdl);
+ g_free(mdl);
+ }
+
+ g_slist_free(mcl->mdls);
+ mcl->mdls = NULL;
+}
+
+static void mcap_mcl_free(struct mcap_mcl *mcl)
+{
+ if (mcl->tid) {
+ RELEASE_TIMER(mcl);
+ }
+
+ if (mcl->cc) {
+ g_io_channel_shutdown(mcl->cc, TRUE, NULL);
+ g_io_channel_unref(mcl->cc);
+ mcl->cc = NULL;
+ }
+ g_source_remove(mcl->wid);
+ if (mcl->lcmd) {
+ g_free(mcl->lcmd);
+ mcl->lcmd = NULL;
+ }
+ if (mcl->priv_data) {
+ g_free(mcl->priv_data);
+ mcl->priv_data = NULL;
+ }
+
+ mcap_free_mdls(mcl);
+
+ if (mcl->cb)
+ g_free(mcl->cb);
+ g_free(mcl);
+}
+
+void mcap_close_mcl(struct mcap_mcl *mcl)
+{
+ if (!mcl)
+ return;
+ mcl->ms->mcls = g_slist_remove(mcl->ms->mcls, mcl);
+ mcap_mcl_free(mcl);
+}
+
+static gboolean parse_set_opts(struct mcap_mcl_cb *mcl_cb, GError **err,
+ McapMclCb cb1, va_list args)
+{
+ McapMclCb cb = cb1;
+ struct mcap_mcl_cb *c;
+
+ c = g_new0(struct mcap_mcl_cb, 1);
+
+ while (cb != MCAP_MDL_CB_INVALID) {
+ switch (cb) {
+ case MCAP_MDL_CB_CONNECTED:
+ c->mdl_connected = va_arg(args,
+ mcap_mdl_event_cb);
+ break;
+ case MCAP_MDL_CB_CLOSED:
+ c->mdl_closed = va_arg(args,
+ mcap_mdl_event_cb);
+ break;
+ case MCAP_MDL_CB_DELETED:
+ c->mdl_deleted = va_arg(args,
+ mcap_mdl_event_cb);
+ break;
+ case MCAP_MDL_CB_REMOTE_CONN_REQ:
+ c->mdl_conn_req = va_arg(args,
+ mcap_remote_mdl_conn_req_cb);
+ break;
+ case MCAP_MDL_CB_REMOTE_RECONN_REQ:
+ c->mdl_reconn_req = va_arg(args,
+ mcap_remote_mdl_reconn_req_cb);
+ break;
+ default:
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
+ "Unknown option %d", cb);
+ return FALSE;
+ }
+ cb = va_arg(args, int);
+ }
+
+ /* Set new callbacks set */
+ if (c->mdl_connected)
+ mcl_cb->mdl_connected = c->mdl_connected;
+ if (c->mdl_closed)
+ mcl_cb->mdl_closed = c->mdl_closed;
+ if (c->mdl_deleted)
+ mcl_cb->mdl_deleted = c->mdl_deleted;
+ if (c->mdl_conn_req)
+ mcl_cb->mdl_conn_req = c->mdl_conn_req;
+ if (c->mdl_reconn_req)
+ mcl_cb->mdl_reconn_req = c->mdl_reconn_req;
+
+ g_free(c);
+ return TRUE;
+}
+
+void mcap_mcl_set_cb(struct mcap_mcl *mcl, GError **gerr,
+ gpointer user_data, McapMclCb cb1, ...)
+{
+ va_list args;
+ gboolean ret;
+
+ va_start(args, cb1);
+ ret = parse_set_opts(mcl->cb, gerr, cb1, args);
+ va_end(args);
+
+ if (!ret)
+ return;
+
+ mcl->cb->user_data = user_data;
+ return;
+}
+
+bdaddr_t mcap_mcl_get_addr(struct mcap_mcl *mcl)
+{
+ return mcl->addr;
+}
+
+static void proc_sync_cmd(struct mcap_mcl *mcl, uint8_t *cmd, int len)
+{
+ switch (cmd[0]) {
+ case MCAP_MD_SYNC_CAP_REQ:
+ debug("TODO: received MCAP_MD_SYNC_CAP_REQ: %d",
+ MCAP_MD_SYNC_CAP_REQ);
+ break;
+ case MCAP_MD_SYNC_CAP_RSP:
+ debug("TODO: received MCAP_MD_SYNC_CAP_RSP: %d",
+ MCAP_MD_SYNC_CAP_RSP);
+ break;
+ case MCAP_MD_SYNC_SET_REQ:
+ debug("TODO: received MCAP_MD_SYNC_SET_REQ: %d",
+ MCAP_MD_SYNC_SET_REQ);
+ break;
+ case MCAP_MD_SYNC_SET_RSP:
+ debug("TODO: received MCAP_MD_SYNC_SET_RSP: %d",
+ MCAP_MD_SYNC_SET_RSP);
+ break;
+ case MCAP_MD_SYNC_INFO_IND:
+ debug("TODO: received MCAP_MD_SYNC_INFO_IND :%d",
+ MCAP_MD_SYNC_INFO_IND);
+ break;
+ }
+}
+
+static void error_cmd_rsp(struct mcap_mcl *mcl, uint8_t *cmd, int len)
+{
+ uint16_t mdlr;
+
+ if ((cmd[0] >= MCAP_ERROR_RSP) && (cmd[0] <= MCAP_MD_DELETE_MDL_RSP)) {
+ /* Standard Op Code request is invalid in current state */
+ error("Invalid cmd received (op code = %d) in state %d",
+ cmd[0], mcl->state);
+ /* Get mdlid sended to generate appropiate response if it is possible */
+ mdlr = len < sizeof(mcap_md_req) ? MCAP_MDLID_RESERVED :
+ ntohs(((mcap_md_req *)cmd)->mdl);
+ send4B_cmd(mcl, cmd[0]+1, MCAP_INVALID_OPERATION, mdlr);
+ } else {
+ error("Unknown cmd request received (op code = %d) in state %d",
+ cmd[0], mcl->state);
+ send4B_cmd(mcl, MCAP_ERROR_RSP, MCAP_INVALID_OP_CODE,
+ MCAP_MDLID_RESERVED);
+ }
+}
+
+static struct mcap_mdl *get_mdl(struct mcap_mcl *mcl, uint16_t mdlid)
+{
+ GSList *l;
+ struct mcap_mdl *mdl;
+
+ for (l = mcl->mdls; l; l = l->next) {
+ mdl = l->data;
+ if (mdlid == mdl->mdlid)
+ return mdl;
+ }
+
+ return NULL;
+}
+
+/* Functions used to process request */
+
+static void process_md_create_mdl_req(struct mcap_mcl *mcl, uint8_t *cmd, int len)
+{
+ mcap_md_create_mdl_req *req;
+ struct mcap_mdl *mdl;
+ uint16_t mdl_id;
+ uint8_t mdep_id;
+ uint8_t cfga, conf;
+ uint8_t rsp;
+
+ if (len != sizeof(mcap_md_create_mdl_req)) {
+ send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP,
+ MCAP_INVALID_PARAM_VALUE, MCAP_MDLID_RESERVED);
+ return;
+ }
+
+ req = (mcap_md_create_mdl_req *)cmd;
+
+ mdl_id = ntohs(req->mdl);
+ if ((mdl_id < MCAP_MDLID_INITIAL) || (mdl_id > MCAP_MDLID_FINAL)) {
+ send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_INVALID_MDL, mdl_id);
+ return;
+ }
+
+ mdep_id = req->mdep;
+ if (mdep_id > MCAP_MDEPID_FINAL) {
+ send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_INVALID_MDEP, mdl_id);
+ return;
+ }
+
+ cfga = conf = req->conf;
+ /* Callback to upper layer */
+ rsp = mcl->cb->mdl_conn_req(mcl, mdep_id, mdl_id, &conf,
+ mcl->cb->user_data);
+
+ if ((cfga != 0) && (cfga != conf)) {
+ /* Remote device set default configuration but upper profile */
+ /* has changed it. Protocol Error: force closing the MCL by */
+ /* using remote device using UNESPECIFIED_ERROR response*/
+ send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_UNESPECIFIED_ERROR,
+ mdl_id);
+ return;
+ }
+ if (rsp != MCAP_SUCCESS) {
+ send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, rsp, mdl_id);
+ return;
+ }
+
+ mdl = get_mdl(mcl, mdl_id);
+ if (!mdl) {
+ mdl = g_malloc0(sizeof(struct mcap_mdl));
+ mdl->mcl = mcl;
+ mdl->mdlid = mdl_id;
+ } else if (mdl->state == MDL_CONNECTED) {
+ shutdown_mdl(mdl);
+ mcl->cb->mdl_closed(mdl, mcl->cb->user_data);
+ }
+ mdl->state = MDL_WAITING;
+ mdl->mdep_id = mdep_id;
+ mcl->mdls = g_slist_insert_sorted(mcl->mdls, mdl, compare_mdl);
+
+ mcl->state = MCL_PENDING;
+ send5B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_SUCCESS, mdl_id, conf);
+}
+
+static void process_md_reconnect_mdl_req(struct mcap_mcl *mcl, uint8_t *cmd,
+ int len)
+{
+ mcap_md_req *req;
+ struct mcap_mdl *mdl;
+ uint16_t mdl_id;
+ uint8_t rsp;
+ gboolean close;
+
+ if (len != sizeof(mcap_md_req)) {
+ send4B_cmd(mcl, MCAP_MD_RECONNECT_MDL_RSP,
+ MCAP_INVALID_PARAM_VALUE, MCAP_MDLID_RESERVED);
+ return;
+ }
+
+ req = (mcap_md_req *)cmd;
+ mdl_id = ntohs(req->mdl);
+
+ mdl = get_mdl(mcl, mdl_id);
+ if (!mdl) {
+ send4B_cmd(mcl, MCAP_MD_RECONNECT_MDL_RSP,
+ MCAP_INVALID_MDL, mdl_id);
+ return;
+ }
+
+ close = mdl->state == MDL_CONNECTED;
+ if (close)
+ shutdown_mdl(mdl);
+
+ /* Callback to upper layer */
+ rsp = mcl->cb->mdl_reconn_req(mdl, mcl->cb->user_data);
+ if (rsp != MCAP_SUCCESS) {
+ if (close)
+ mcl->cb->mdl_closed(mdl, mcl->cb->user_data);
+ send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, rsp, mdl_id);
+ return;
+ }
+ mdl->state = MDL_WAITING;
+ mcl->state = MCL_PENDING;
+ send4B_cmd(mcl, MCAP_MD_RECONNECT_MDL_RSP, MCAP_SUCCESS, mdl_id);
+}
+
+static void process_md_abort_mdl_req(struct mcap_mcl *mcl, uint8_t *cmd, int len)
+{
+ mcap_md_req *req;
+ GSList *l;
+ struct mcap_mdl *mdl, *del;
+ uint16_t mdl_id;
+
+ if (len != sizeof(mcap_md_req)) {
+ send4B_cmd(mcl, MCAP_MD_ABORT_MDL_RSP,
+ MCAP_INVALID_PARAM_VALUE, MCAP_MDLID_RESERVED);
+ return;
+ }
+
+ req = (mcap_md_req *)cmd;
+ mdl_id = ntohs(req->mdl);
+ mcl->state = MCL_CONNECTED;
+ for (l = mcl->mdls; l; l = l->next) {
+ mdl = l->data;
+ if ((mdl_id == mdl->mdlid) && (mdl->state == MDL_WAITING)) {
+ del = mdl;
+ if (mcl->state != MCL_CONNECTED)
+ break;
+ continue;
+ }
+ if ((mdl->state == MDL_CONNECTED) && (mcl->state != MCL_ACTIVE))
+ mcl->state = MCL_ACTIVE;
+
+ if ((del) && (mcl->state == MCL_ACTIVE))
+ break;
+ }
+
+ if (!del) {
+ send4B_cmd(mcl, MCAP_MD_ABORT_MDL_RSP, MCAP_INVALID_MDL, mdl_id);
+ return;
+ }
+
+ mcl->mdls = g_slist_remove(mcl->mdls, del);
+ g_free(del);
+ send4B_cmd(mcl, MCAP_MD_ABORT_MDL_RSP, MCAP_SUCCESS, mdl_id);
+}
+/* Functions used to process responses */
+static gboolean check_err_rsp(uint16_t rmdl, uint16_t smdl, uint8_t rc,
+ int rlen, int len, GError **gerr)
+{
+ gboolean close = FALSE;
+ char *msg;
+
+ if (rmdl != smdl) {
+ msg = "MDLID received doesn't match with MDLID sended";
+ close = TRUE;
+ goto fail;
+ }
+
+ if (rc != MCAP_SUCCESS) {
+ msg = error2str(rc);
+ goto fail;
+ }
+
+ if (rlen < len) {
+ msg = "Protocol error";
+ close = TRUE;
+ goto fail;
+ }
+ return FALSE;
+fail:
+ g_set_error(gerr, MCAP_ERROR, MCAP_ERROR_FAILED, "%s", msg);
+ return close;
+}
+
+static gboolean process_md_create_mdl_rsp(struct mcap_mcl *mcl,
+ uint8_t *cmd, int len)
+{
+ struct mcap_mdl_op_cb *conn = mcl->priv_data;
+ struct mcap_mdl *mdl = conn->mdl;
+ mcap_mdl_operation_conf_cb connect_cb = conn->cb.op_conf;
+ gpointer user_data = conn->user_data;
+ uint16_t mdlid;
+ mcap5B_rsp *rsp = (mcap5B_rsp *) cmd;
+ mcap_md_create_mdl_req *cmdlast;
+ GError *gerr = NULL;
+ gboolean close = FALSE;
+
+ g_free(mcl->priv_data);
+ mcl->priv_data = NULL;
+
+ cmdlast = (mcap_md_create_mdl_req *) mcl->lcmd;
+ mdlid = ntohs(cmdlast->mdl);
+ rsp->mdl = ntohs(rsp->mdl);
+
+ g_free(mcl->lcmd);
+ mcl->lcmd = NULL;
+ mcl->req = MCL_AVAILABLE;
+ close = check_err_rsp(rsp->mdl, mdlid, rsp->rc, 0, 0, &gerr);
+
+ if (gerr)
+ goto fail;
+
+ if (len < 5) {
+ g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "Protocol error");
+ close = TRUE;
+ goto fail;
+ }
+
+ /* Check if preferences changed */
+ if ((cmdlast->conf != 0x00) && (rsp->param != cmdlast->conf)) {
+ g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "Configutation changed");
+ close = TRUE;
+ goto fail;
+ }
+
+ connect_cb(mdl, rsp->param, gerr, user_data);
+ return close;
+fail:
+ connect_cb(NULL, 0, gerr, user_data);
+ mcl->mdls = g_slist_remove(mcl->mdls, mdl);
+ g_free(mdl);
+ g_error_free(gerr);
+ return close;
+}
+
+static gboolean process_md_reconnect_mdl_rsp(struct mcap_mcl *mcl,
+ uint8_t *cmd, int len)
+{
+ struct mcap_mdl_op_cb *reconn = mcl->priv_data;
+ struct mcap_mdl *mdl = reconn->mdl;
+ mcap_mdl_operation_cb reconn_cb = reconn->cb.op;
+ gpointer user_data = reconn->user_data;
+ mcap4B_rsp *rsp = (mcap4B_rsp *) cmd;
+ mcap_md_req *cmdlast = (mcap_md_req *) mcl->lcmd;
+ uint16_t mdlid = ntohs(cmdlast->mdl);
+ GError *gerr = NULL;
+ gboolean close = FALSE;
+
+ g_free(mcl->priv_data);
+ mcl->priv_data = NULL;
+
+ rsp->mdl = ntohs(rsp->mdl);
+
+ close = check_err_rsp(rsp->mdl, mdlid, rsp->rc, len,
+ sizeof(mcap4B_rsp), &gerr);
+
+ g_free(mcl->lcmd);
+ mcl->lcmd = NULL;
+ mcl->req = MCL_AVAILABLE;
+
+ reconn_cb(mdl, gerr, user_data);
+ if (gerr)
+ g_error_free(gerr);
+
+ return close;
+}
+
+static gboolean process_md_abort_mdl_rsp(struct mcap_mcl *mcl,
+ uint8_t *cmd, int len)
+{
+ struct mcap_mdl_op_cb *abrt = mcl->priv_data;
+ struct mcap_mdl *mdl = abrt->mdl;
+ mcap_mdl_del_cb abrt_cb = abrt->cb.del;
+ gpointer user_data = abrt->user_data;
+ mcap4B_rsp *rsp = (mcap4B_rsp *) cmd;
+ mcap_md_req *cmdlast = (mcap_md_req *) mcl->lcmd;
+ uint16_t mdlid = ntohs(cmdlast->mdl);
+ GError *gerr = NULL;
+ gboolean close = FALSE;
+
+ g_free(mcl->priv_data);
+ mcl->priv_data = NULL;
+
+ rsp->mdl = ntohs(rsp->mdl);
+
+ close = check_err_rsp(rsp->mdl, mdlid, rsp->rc, len,
+ sizeof(mcap4B_rsp), &gerr);
+ g_free(mcl->lcmd);
+ mcl->lcmd = NULL;
+ mcl->req = MCL_AVAILABLE;
+
+ if (gerr) {
+ abrt_cb(gerr, user_data);
+ g_error_free(gerr);
+ return close;
+ }
+
+ mcl->mdls = g_slist_remove(mcl->mdls, mdl);
+ g_free(mdl);
+ update_mcl_state(mcl);
+ abrt_cb(gerr, user_data);
+ return close;
+}
+
+static void mcap_delete_mdl(gpointer elem, gpointer user_data)
+{
+ struct mcap_mdl *mdl = elem;
+ gboolean notify = *(gboolean *)user_data;
+ if (mdl->state == MDL_CONNECTED) {
+ debug("MDL %d already connected, closing it", mdl->mdlid);
+ shutdown_mdl(mdl);
+ }
+ if (notify)
+ mdl->mcl->cb->mdl_deleted(mdl, mdl->mcl->cb->user_data);
+ g_free(mdl);
+}
+
+static gboolean process_md_delete_mdl_rsp(struct mcap_mcl *mcl, uint8_t *cmd,
+ int len)
+{
+ struct mcap_mdl_op_cb *del = mcl->priv_data;
+ struct mcap_mdl *mdl = del->mdl;
+ mcap_mdl_del_cb deleted_cb = del->cb.del;
+ gpointer user_data = del->user_data;
+ mcap4B_rsp *rsp = (mcap4B_rsp *) cmd;
+ mcap_md_req *cmdlast = (mcap_md_req *) mcl->lcmd;
+ uint16_t mdlid = ntohs(cmdlast->mdl);
+ GError *gerr = NULL;
+ gboolean close = FALSE;
+ gboolean notify = FALSE;
+
+ g_free(mcl->priv_data);
+ mcl->priv_data = NULL;
+
+ rsp->mdl = ntohs(rsp->mdl);
+
+ close = check_err_rsp(rsp->mdl, mdlid, rsp->rc, len,
+ sizeof(mcap4B_rsp), &gerr);
+
+ g_free(mcl->lcmd);
+ mcl->lcmd = NULL;
+ mcl->req = MCL_AVAILABLE;
+ if (gerr) {
+ deleted_cb(gerr, user_data);
+ g_error_free(gerr);
+ return close;
+ }
+
+ if (mdlid == MCAP_ALL_MDLIDS) {
+ g_slist_foreach(mcl->mdls, mcap_delete_mdl, ¬ify);
+ g_slist_free(mcl->mdls);
+ mcl->mdls = NULL;
+ mcl->state = MCL_CONNECTED;
+ goto end;
+ }
+
+ mcl->mdls = g_slist_remove(mcl->mdls, mdl);
+ update_mcl_state(mcl);
+ mcap_delete_mdl(mdl, ¬ify);
+end:
+ deleted_cb(gerr, user_data);
+ return close;
+}
+
+static void process_md_delete_mdl_req(struct mcap_mcl *mcl, mcap_md_req *req)
+{
+ struct mcap_mdl *mdl, *aux;
+ uint16_t mdlid = ntohs(req->mdl);
+ gboolean notify;
+ GSList *l;
+
+ debug("process MCAP_MD_DELETE_MDL_REQ");
+
+ if (mdlid == MCAP_ALL_MDLIDS) {
+ notify = FALSE;
+ g_slist_foreach(mcl->mdls, mcap_delete_mdl, ¬ify);
+ g_slist_free(mcl->mdls);
+ mcl->state = MCL_CONNECTED;
+ mcl->mdls = NULL;
+ /* NULL mdl means ALL_MDLS */
+ mcl->cb->mdl_deleted(NULL, mcl->cb->user_data);
+ goto resp;
+ }
+
+ if ((mdlid < MCAP_MDLID_INITIAL) || (mdlid > MCAP_MDLID_FINAL)) {
+ send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_INVALID_MDL, mdlid);
+ return;
+ }
+
+ for (l=mcl->mdls, mdl = NULL; l; l = l->next) {
+ aux = l->data;
+ if (aux->mdlid == mdlid) {
+ mdl = aux;
+ break;
+ }
+ }
+
+ if (!mdl) {
+ send4B_cmd(mcl, MCAP_MD_DELETE_MDL_RSP, MCAP_INVALID_MDL, mdlid);
+ return;
+ }
+
+ mcl->mdls = g_slist_remove(mcl->mdls, mdl);
+ update_mcl_state(mcl);
+ notify = TRUE;
+ mcap_delete_mdl(mdl, ¬ify);
+resp:
+ send4B_cmd(mcl, MCAP_MD_DELETE_MDL_RSP, MCAP_SUCCESS, mdlid);
+}
+
+/* Function used to process commands depending of MCL state */
+
+static void proc_req_connected(struct mcap_mcl *mcl, uint8_t *cmd, int len)
+{
+ debug("Processing in Connected");
+ switch (cmd[0]) {
+ case MCAP_MD_CREATE_MDL_REQ:
+ process_md_create_mdl_req(mcl, cmd, len);
+ break;
+ case MCAP_MD_RECONNECT_MDL_REQ:
+ process_md_reconnect_mdl_req(mcl, cmd, len);
+ break;
+ case MCAP_MD_DELETE_MDL_REQ:
+ process_md_delete_mdl_req(mcl, (mcap_md_req *) cmd);
+ break;
+ default:
+ error_cmd_rsp(mcl, cmd, len);
+ }
+}
+
+static void proc_req_pending(struct mcap_mcl *mcl, uint8_t *cmd, int len)
+{
+ debug("Processing in Pending");
+ if (cmd[0] == MCAP_MD_ABORT_MDL_REQ)
+ process_md_abort_mdl_req(mcl, cmd, len);
+ else
+ error_cmd_rsp(mcl, cmd, len);
+}
+
+static void proc_req_active(struct mcap_mcl *mcl, uint8_t *cmd, int len)
+{
+ debug("Processing in Active");
+ switch (cmd[0]) {
+ case MCAP_MD_CREATE_MDL_REQ:
+ process_md_create_mdl_req(mcl, cmd, len);
+ break;
+ case MCAP_MD_RECONNECT_MDL_REQ:
+ process_md_reconnect_mdl_req(mcl, cmd, len);
+ break;
+ case MCAP_MD_DELETE_MDL_REQ:
+ process_md_delete_mdl_req(mcl, (mcap_md_req *) cmd);
+ break;
+ default:
+ error_cmd_rsp(mcl, cmd, len);
+ }
+}
+
+static void mcap_notify_error(struct mcap_mcl *mcl, GError *err)
+{
+ struct mcap_mdl_op_cb *con = mcl->priv_data;
+
+ if (!con || !mcl->lcmd)
+ return;
+
+ switch (mcl->lcmd[0]){
+ case MCAP_MD_CREATE_MDL_REQ:
+ con->cb.op_conf(NULL, 0, err, con->user_data);
+ break;
+ case MCAP_MD_ABORT_MDL_REQ:
+ case MCAP_MD_DELETE_MDL_REQ:
+ con->cb.del(err, con->user_data);
+ break;
+ case MCAP_MD_RECONNECT_MDL_REQ:
+ con->cb.op(NULL, err, con->user_data);
+ break;
+ }
+
+ g_free(mcl->priv_data);
+ mcl->priv_data = NULL;
+}
+
+static gboolean check_rsp(struct mcap_mcl *mcl, uint8_t *cmd, int len)
+{
+ mcap4B_rsp *rsp;
+ GError *err = NULL;
+
+ /* Check if the response matches with the last request */
+ if ((cmd[0] != MCAP_ERROR_RSP) && ((mcl->lcmd[0] + 1) != cmd[0]))
+ goto close_mcl;
+
+ if (len < 4)
+ goto close_mcl;
+ rsp = (mcap4B_rsp *)cmd;
+
+ if (rsp->rc == MCAP_REQUEST_NOT_SUPPORTED) {
+ debug("Remote does not support opcodes");
+ g_set_error(&err, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "Remote does not support this operation");
+ mcap_notify_error(mcl, err);
+ g_error_free(err);
+
+ g_free(mcl->lcmd);
+ mcl->lcmd = NULL;
+ mcl->sup_opc = FALSE;
+ mcl->req = MCL_AVAILABLE;
+ update_mcl_state(mcl);
+ return FALSE;
+ }
+
+ if (rsp->rc == MCAP_UNESPECIFIED_ERROR)
+ goto close_mcl;
+
+ return TRUE;
+close_mcl:
+ g_set_error(&err, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "Protocol error");
+ mcap_notify_error(mcl, err);
+ g_error_free(err);
+ mcl->ms->mcl_closed_cb(mcl, mcl->ms->user_data);
+ mcap_close_mcl(mcl);
+ return FALSE;
+}
+
+static void proc_response(struct mcap_mcl *mcl, uint8_t *cmd, int len)
+{
+ gboolean close;
+ RELEASE_TIMER(mcl);
+
+ if (!check_rsp(mcl, cmd, len))
+ return;
+
+ switch (cmd[0]) {
+ case MCAP_ERROR_RSP:
+ debug("received MCAP_ERROR_RSP:%d",MCAP_ERROR_RSP);
+ close = TRUE;
+ break;
+ case MCAP_MD_CREATE_MDL_RSP:
+ close = process_md_create_mdl_rsp(mcl, cmd, len);
+ break;
+ case MCAP_MD_RECONNECT_MDL_RSP:
+ close = process_md_reconnect_mdl_rsp(mcl, cmd, len);
+ break;
+ case MCAP_MD_ABORT_MDL_RSP:
+ close = process_md_abort_mdl_rsp(mcl, cmd, len);
+ break;
+ case MCAP_MD_DELETE_MDL_RSP:
+ debug("received MCAP_MD_DELETE_MDL_RSP");
+ close = process_md_delete_mdl_rsp(mcl, cmd, len);
+ break;
+ default:
+ debug("Unknown cmd response received (op code = %d)",cmd[0]);
+ close = TRUE;
+ break;
+ }
+
+ if (close) {
+ mcl->ms->mcl_closed_cb(mcl, mcl->ms->user_data);
+ mcap_close_mcl(mcl);
+ }
+}
+
+static void rsend_req(struct mcap_mcl *mcl)
+{
+ uint8_t *cmd = mcl->lcmd;
+ int len;
+
+ if(!cmd)
+ return;
+
+ switch (cmd[0]) {
+ case MCAP_MD_RECONNECT_MDL_REQ:
+ case MCAP_MD_ABORT_MDL_REQ:
+ case MCAP_MD_DELETE_MDL_REQ:
+ len = 3;
+ break;
+ case MCAP_MD_CREATE_MDL_REQ:
+ len = 5;
+ break;
+ default:
+ return;
+ }
+
+ mcap_send_data(g_io_channel_unix_get_fd(mcl->cc), cmd, len);
+}
+
+static void proc_cmd(struct mcap_mcl *mcl, uint8_t *cmd, int len)
+{
+ if ((cmd[0] >= MCAP_MD_SYNC_CAP_REQ) && (cmd[0] <= MCAP_MD_SYNC_INFO_IND)) {
+ proc_sync_cmd(mcl, cmd, len);
+ return;
+ }
+
+ if (!mcl->sup_opc) {
+ /* In case the remote device doesn't work corerctly */
+ error("Remote device does not support opcodes, cmd ignored");
+ return;
+ }
+
+ if (mcl->req == MCL_WAITING_RSP) {
+ if (cmd[0] & 0x01) {
+ /* Request arrived when a response is expected */
+ if (mcl->role == MCL_INITIATOR)
+ /* ignore */
+ return;
+ proc_req[mcl->state](mcl, cmd, len);
+ /* Initiator will ignore our last request => re-send */
+ rsend_req(mcl);
+ return;
+ }
+ proc_response(mcl, cmd, len);
+ } else if (cmd[0] & 0x01) {
+ proc_req[mcl->state](mcl, cmd, len);
+ }
+}
+
+static gboolean mdl_closing_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
+{
+
+ struct mcap_mdl *mdl = data;
+ gboolean open;
+
+ debug("Close MDL %d", mdl->mdlid);
+
+ open = (mdl->state == MDL_CONNECTED);
+ shutdown_mdl(mdl);
+
+ update_mcl_state(mdl->mcl);
+
+ if (open)
+ /*Callback to upper layer */
+ mdl->mcl->cb->mdl_closed(mdl, mdl->mcl->cb->user_data);
+
+ return FALSE;
+}
+
+static void mcap_connect_mdl_cb(GIOChannel *chan, GError *conn_err,
+ gpointer data)
+{
+ struct mcap_mdl_op_cb *con = data;
+ struct mcap_mdl *mdl = con->mdl;
+ mcap_mdl_operation_cb cb = con->cb.op;
+ gpointer user_data = con->user_data;
+
+ g_free(con);
+ debug("mdl connect callback");
+
+ if (conn_err) {
+ debug("ERROR: mdl connect callback");
+ mdl->state = MDL_CLOSED;
+ g_io_channel_unref(mdl->dc);
+ mdl->dc = NULL;
+ cb(mdl, conn_err, user_data);
+ return;
+ }
+
+ mdl->state = MDL_CONNECTED;
+ mdl->wid = g_io_add_watch(mdl->dc, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) mdl_closing_cb, mdl);
+
+ cb(mdl, conn_err, user_data);
+}
+
+void mcap_mdl_connect(struct mcap_mdl *mdl, BtIOType BtType, uint16_t dcpsm,
+ GError **err, mcap_mdl_operation_cb connect_cb, gpointer user_data)
+{
+ struct mcap_mdl_op_cb *con;
+
+ if (mdl->state != MDL_WAITING) {
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
+ "MDL has not been negotiated.");
+ return;
+ }
+
+ con = g_new0(struct mcap_mdl_op_cb, 1);
+ con->mdl = mdl;
+ con->cb.op = connect_cb;
+ con->user_data = user_data;
+
+ /* TODO: Check if BtIOType is ERTM or Streaming before continue */
+
+ mdl->dc = bt_io_connect(BtType, mcap_connect_mdl_cb, con,
+ NULL, err,
+ BT_IO_OPT_SOURCE_BDADDR, &mdl->mcl->ms->src,
+ BT_IO_OPT_DEST_BDADDR, &mdl->mcl->addr,
+ BT_IO_OPT_PSM, dcpsm,
+ BT_IO_OPT_MTU, MCAP_DC_MTU,
+ BT_IO_OPT_SEC_LEVEL, mdl->mcl->ms->sec,
+ BT_IO_OPT_INVALID);
+ if (*err) {
+ debug("MDL Connection error");
+ mdl->state = MDL_CLOSED;
+ g_free(con);
+ }
+}
+
+static gboolean mcl_control_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
+{
+
+ struct mcap_mcl *mcl = data;
+ int sk, len;
+ uint8_t buf[MCAP_CC_MTU];
+
+ if (cond & G_IO_NVAL) {
+ error("Revise G_IO_NVAL");
+ goto fail;
+ }
+
+ if (cond & (G_IO_ERR | G_IO_HUP))
+ goto fail;
+
+ sk = g_io_channel_unix_get_fd(chan);
+ len = recv(sk, buf, sizeof(buf), 0);
+ if (len < 0)
+ goto fail;
+
+ proc_cmd(mcl, buf, len);
+ return TRUE;
+fail:
+ mcl->ms->mcl_closed_cb(mcl, mcl->ms->user_data);
+ mcap_close_mcl(mcl);
+ return FALSE;
+}
+
+static void mcap_connect_mcl_cb(GIOChannel *chan, GError *conn_err,
+ gpointer user_data)
+{
+ char dstaddr[18];
+ struct connect_mcl *con = user_data;
+ struct mcap_mcl *aux, *mcl = con->mcl;
+ mcap_mcl_connect_cb connect_cb = con->connect_cb;
+ gpointer data = con->user_data;
+ GError *gerr = NULL;
+
+ g_free(con);
+
+ if (conn_err) {
+ mcap_close_mcl(mcl);
+ connect_cb(NULL, conn_err, data);
+ return;
+ }
+
+ ba2str(&mcl->addr, dstaddr);
+
+ aux = find_mcl(mcl->ms->mcls, &mcl->addr);
+ if (aux) {
+ mcap_close_mcl(mcl);
+ error("MCL error: Device %s is already connected", dstaddr);
+ g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_ALREADY_EXISTS,
+ "MCL %s is already connected", dstaddr);
+ connect_cb(NULL, gerr, data);
+ g_error_free(gerr);
+ return;
+ }
+
+ mcl->state = MCL_CONNECTED;
+ mcl->role = MCL_INITIATOR;
+ mcl->req = MCL_AVAILABLE;
+ mcl->sup_opc = TRUE;
+
+ mcl->ms->mcls = g_slist_prepend(mcl->ms->mcls, mcl);
+ mcl->wid = g_io_add_watch(mcl->cc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) mcl_control_cb, mcl);
+ connect_cb(mcl, gerr, data);
+}
+
+void mcap_create_mcl(struct mcap_session *ms,
+ const bdaddr_t *addr,
+ uint16_t ccpsm,
+ GError **err,
+ mcap_mcl_connect_cb connect_cb,
+ gpointer user_data)
+{
+ struct mcap_mcl *mcl;
+ struct connect_mcl *con;
+
+ mcl = find_mcl(ms->mcls, addr);
+ if (mcl) {
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_ALREADY_EXISTS,
+ "MCL is already connected.");
+ return;
+ }
+
+ mcl = g_new0(struct mcap_mcl, 1);
+ mcl->ms = ms;
+ bacpy(&mcl->addr, addr);
+
+ con = g_new0(struct connect_mcl, 1);
+ mcl->cb = g_new0(struct mcap_mcl_cb, 1);
+ SET_DEFAULT_MCL_CB(mcl);
+
+ con->mcl = mcl;
+ con->connect_cb = connect_cb;
+ con->user_data = user_data;
+
+ mcl->cc = bt_io_connect(BT_IO_L2CAP, mcap_connect_mcl_cb, con,
+ NULL, err,
+ BT_IO_OPT_SOURCE_BDADDR, &ms->src,
+ BT_IO_OPT_DEST_BDADDR, addr,
+ BT_IO_OPT_PSM, ccpsm,
+ BT_IO_OPT_MTU, MCAP_CC_MTU,
+ BT_IO_OPT_SEC_LEVEL, ms->sec,
+ BT_IO_OPT_INVALID);
+ if (*err) {
+ g_free(con);
+ mcap_close_mcl(mcl);
+ }
+}
+
+static void connect_dc_event_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+ struct mcap_mdl *mdl = user_data;
+ struct mcap_mcl *mcl = mdl->mcl;
+
+ mdl->state = MDL_CONNECTED;
+ mdl->dc = g_io_channel_ref(chan);
+ mdl->wid = g_io_add_watch(mdl->dc, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) mdl_closing_cb, mdl);
+
+ mcl->state = MCL_ACTIVE;
+ mcl->cb->mdl_connected(mdl, mcl->cb->user_data);
+}
+
+static void confirm_dc_event_cb(GIOChannel *chan, gpointer user_data)
+{
+ struct mcap_session *ms = user_data;
+ struct mcap_mcl *mcl;
+ struct mcap_mdl *mdl;
+ GError *err = NULL;
+ bdaddr_t dst;
+ GSList *l;
+
+ bt_io_get(chan, BT_IO_L2CAP, &err,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_INVALID);
+ if (err) {
+ error("%s", err->message);
+ g_error_free(err);
+ goto drop;
+ }
+
+ mcl = find_mcl(ms->mcls, &dst);
+ if (!mcl || (mcl->state != MCL_PENDING))
+ goto drop;
+
+ for (l = mcl->mdls; l; l = l->next) {
+ mdl = l->data;
+ if (mdl->state == MDL_WAITING) {
+ if (!bt_io_accept(chan, connect_dc_event_cb, mdl, NULL,
+ &err)) {
+ error("MDL accept error %s", err->message);
+ g_error_free(err);
+ goto drop;
+ }
+ return;
+ }
+ }
+drop:
+ g_io_channel_shutdown(chan, TRUE, NULL);
+}
+
+static void connect_mcl_event_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+ struct mcap_mcl *mcl = user_data;
+
+ if (err) {
+ mcap_mcl_free(mcl);
+ return;
+ }
+ mcl->cb = g_new0(struct mcap_mcl_cb, 1);
+ mcl->state = MCL_CONNECTED;
+ mcl->role = MCL_ACCEPTOR;
+ mcl->req = MCL_AVAILABLE;
+ mcl->cc = g_io_channel_ref(chan);
+ mcl->sup_opc = TRUE;
+
+ SET_DEFAULT_MCL_CB(mcl);
+ debug("MCL created");
+ mcl->ms->mcls = g_slist_prepend(mcl->ms->mcls, mcl);
+
+ mcl->wid = g_io_add_watch(mcl->cc,
+ G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) mcl_control_cb, mcl);
+
+ /* Callback to report new entry MCL */
+ mcl->ms->mcl_created_cb(mcl, mcl->ms->user_data);
+}
+
+static void confirm_mcl_event_cb(GIOChannel *chan, gpointer user_data)
+{
+ struct mcap_session *ms = user_data;
+ struct mcap_mcl *mcl;
+ bdaddr_t dst;
+ char address[18], srcstr[18];
+ GError *err = NULL;
+
+ bt_io_get(chan, BT_IO_L2CAP, &err,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_DEST, address,
+ BT_IO_OPT_INVALID);
+ if (err) {
+ error("%s", err->message);
+ g_error_free(err);
+ goto drop;
+ }
+
+ ba2str(&ms->src, srcstr);
+ mcl = find_mcl(ms->mcls, &dst);
+ if (mcl) {
+ error("Control channel already created with %s on adapter %s",
+ address, srcstr);
+ goto drop;
+ }
+
+ mcl = g_new0(struct mcap_mcl, 1);
+
+ mcl->ms = ms;
+ bacpy(&mcl->addr, &dst);
+
+ if (!bt_io_accept(chan, connect_mcl_event_cb, mcl, NULL, &err)) {
+ error("mcap accpet error: %s", err->message);
+ mcap_mcl_free(mcl);
+ g_error_free(err);
+ goto drop;
+ }
+
+ return;
+drop:
+ g_io_channel_shutdown(chan, TRUE, NULL);
+}
+
+struct mcap_session *mcap_create_session(struct btd_adapter *btd_adapter,
+ BtIOSecLevel sec,
+ uint16_t ccpsm,
+ uint16_t dcpsm,
+ GError **gerr,
+ mcap_mcl_event_cb mcl_closed,
+ mcap_mcl_event_cb mcl_created,
+ gpointer user_data)
+{
+ struct mcap_session *ms;
+
+ if (sec < BT_IO_SEC_MEDIUM) {
+ g_set_error(gerr, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
+ "Security level can't be minor of %d",
+ BT_IO_SEC_MEDIUM);
+ return NULL;
+ }
+
+ if (!(mcl_closed && mcl_created)) {
+ g_set_error(gerr, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
+ "The callbacks can't be null");
+ return NULL;
+ }
+
+ ms = g_new0(struct mcap_session, 1);
+
+ adapter_get_address(btd_adapter, &ms->src);
+
+ ms->sec = sec;
+ ms->mcl_closed_cb = mcl_closed;
+ ms->mcl_created_cb = mcl_created;
+ ms->user_data = user_data;
+
+ /* Listen incoming connections in control channel */
+ ms->ccio = bt_io_listen(BT_IO_L2CAP, NULL, confirm_mcl_event_cb, ms,
+ NULL, gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &ms->src,
+ BT_IO_OPT_PSM, ccpsm,
+ BT_IO_OPT_MTU, MCAP_CC_MTU,
+ BT_IO_OPT_SEC_LEVEL, sec,
+ BT_IO_OPT_INVALID);
+ if (!ms->ccio) {
+ error("%s", (*gerr)->message);
+ g_free(ms);
+ return NULL;
+ }
+
+ /* Listen incoming connections in data channels */
+ ms->dcio = bt_io_listen(BT_IO_L2CAP, NULL, confirm_dc_event_cb, ms,
+ NULL, gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &ms->src,
+ BT_IO_OPT_PSM, dcpsm,
+ BT_IO_OPT_MTU, MCAP_DC_MTU,
+ BT_IO_OPT_SEC_LEVEL, sec,
+ BT_IO_OPT_INVALID);
+ if (!ms->dcio) {
+ g_io_channel_shutdown(ms->ccio, TRUE, NULL);
+ g_io_channel_unref(ms->ccio);
+ ms->ccio = NULL;
+ error("%s", (*gerr)->message);
+ g_free(ms);
+ return NULL;
+ }
+
+ return ms;
+}
+
+void mcap_close_session(struct mcap_session *ms)
+{
+ GSList *l;
+
+ if (!ms)
+ return;
+
+ if (ms->ccio) {
+ g_io_channel_shutdown(ms->ccio, TRUE, NULL);
+ g_io_channel_unref(ms->ccio);
+ ms->ccio = NULL;
+ }
+
+ if (ms->dcio) {
+ g_io_channel_shutdown(ms->dcio, TRUE, NULL);
+ g_io_channel_unref(ms->dcio);
+ ms->dcio = NULL;
+ }
+
+ for (l = ms->mcls; l; l = l->next)
+ mcap_mcl_free(l->data);
+
+ g_slist_free(ms->mcls);
+ ms->mcls = NULL;
+
+ g_free(ms);
+}
diff --git a/mcap/mcap.h b/mcap/mcap.h
new file mode 100644
index 0000000..7b45d04
--- /dev/null
+++ b/mcap/mcap.h
@@ -0,0 +1,174 @@
+/*
+ *
+ * MCAP for BlueZ- Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2009-2010 Santiago Carot-Nemesio <sancane at gmail.com>
+ * Copyright (C) 2009-2010 Jose Antonio Santos Cadenas <santoscadenas at gmail.com>
+ * Copyright (C) 2009-2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __MCAP_H
+#define __MCAP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MCAP_VERSION 0x0100 /* current version 01.00 */
+
+/* bytes to get MCAP Supported Procedures */
+#define MCAP_SUP_PROC 0x06
+
+/* maximum transmission unit for channels */
+#define MCAP_CC_MTU 48
+#define MCAP_DC_MTU L2CAP_DEFAULT_MTU
+
+
+/* MCAP Standard Op Codes */
+#define MCAP_ERROR_RSP 0x00
+#define MCAP_MD_CREATE_MDL_REQ 0x01
+#define MCAP_MD_CREATE_MDL_RSP 0x02
+#define MCAP_MD_RECONNECT_MDL_REQ 0x03
+#define MCAP_MD_RECONNECT_MDL_RSP 0x04
+#define MCAP_MD_ABORT_MDL_REQ 0x05
+#define MCAP_MD_ABORT_MDL_RSP 0x06
+#define MCAP_MD_DELETE_MDL_REQ 0x07
+#define MCAP_MD_DELETE_MDL_RSP 0x08
+/*RESERVED 0x09*/
+/*RESERVED 0x10*/
+
+/* MCAP Clock Sync Op Codes */
+#define MCAP_MD_SYNC_CAP_REQ 0x11
+#define MCAP_MD_SYNC_CAP_RSP 0x12
+#define MCAP_MD_SYNC_SET_REQ 0x13
+#define MCAP_MD_SYNC_SET_RSP 0x14
+#define MCAP_MD_SYNC_INFO_IND 0x15
+/*RESERVED 0x16*/
+/*RESERVED 0x17*/
+/*RESERVED 0x18*/
+/*RESERVED 0x19*/
+/*RESERVED 0x20*/
+
+/* MCAP Response codes */
+#define MCAP_SUCCESS 0x00
+#define MCAP_INVALID_OP_CODE 0x01
+#define MCAP_INVALID_PARAM_VALUE 0x02
+#define MCAP_INVALID_MDEP 0x03
+#define MCAP_MDEP_BUSY 0x04
+#define MCAP_INVALID_MDL 0x05
+#define MCAP_MDL_BUSY 0x06
+#define MCAP_INVALID_OPERATION 0x07
+#define MCAP_RESOURCE_UNAVAILABLE 0x08
+#define MCAP_UNESPECIFIED_ERROR 0x09
+#define MCAP_REQUEST_NOT_SUPPORTED 0x0A
+#define MCAP_CONFIGURATION_REJECTED 0x0B
+/*RESERVED 0x0C-0xFF*/
+
+
+/* MDL IDs */
+#define MCAP_MDLID_RESERVED 0x0000
+#define MCAP_MDLID_INITIAL 0x0001
+#define MCAP_MDLID_FINAL 0xFEFF
+/*RESERVED 0xFF00-0xFFFE*/
+#define MCAP_ALL_MDLIDS 0xFFFF
+
+/* MDEP IDs */
+#define MCAP_MDEPID_INITIAL 0x00
+#define MCAP_MDEPID_FINAL 0x7F
+/*RESERVED 0x80-0xFF*/
+
+
+/*
+ * MCAP Request Packet Format
+ */
+
+typedef struct {
+ uint8_t op;
+ uint16_t mdl;
+ uint8_t mdep;
+ uint8_t conf;
+} __attribute__ ((packed)) mcap_md_create_mdl_req;
+
+typedef struct {
+ uint8_t op;
+ uint16_t mdl;
+} __attribute__ ((packed)) mcap_md_req;
+
+
+/*
+ * MCAP Response Packet Format
+ */
+
+typedef struct {
+ uint8_t op;
+ uint8_t rc;
+ uint16_t mdl;
+} __attribute__ ((packed)) mcap4B_rsp;
+
+typedef struct {
+ uint8_t op;
+ uint8_t rc;
+ uint16_t mdl;
+ uint8_t param;
+} __attribute__ ((packed)) mcap5B_rsp;
+
+
+/*
+ * MCAP Clock Synchronization Protocol
+ */
+typedef struct {
+ uint8_t op;
+ uint16_t timest;
+} __attribute__ ((packed)) mcap_md_sync_cap_req;
+
+typedef struct {
+ uint8_t op;
+ uint8_t rc;
+ uint8_t btclock;
+ uint16_t sltime;
+ uint16_t timestnr;
+ uint16_t timestna;
+} __attribute__ ((packed)) mcap_md_sync_cap_rsp;
+
+typedef struct {
+ uint8_t op;
+ uint8_t timestui;
+ uint32_t btclock;
+ uint64_t timestst;
+} __attribute__ ((packed)) mcap_md_sync_set_req;
+
+typedef struct {
+ uint8_t op;
+ uint8_t rc;
+ uint32_t btclock;
+ uint64_t timestst;
+ uint16_t timestsa;
+} __attribute__ ((packed)) mcap_md_sync_set_rsp;
+
+typedef struct {
+ uint8_t op;
+ uint32_t btclock;
+ uint64_t timestst;
+ uint16_t timestsa;
+} __attribute__ ((packed)) mcap_md_sync_info_ind;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCAP_H */
diff --git a/mcap/mcap_lib.h b/mcap/mcap_lib.h
new file mode 100644
index 0000000..530f03a
--- /dev/null
+++ b/mcap/mcap_lib.h
@@ -0,0 +1,137 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2010 Santiago Carot Nemesio <sancane at gmail.com>
+ * Copyright (C) 2010 Jose Antonio Santos-Cadenas <santoscadenas at gmail.com>
+ * Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __MCAP_LIB_H
+#define __MCAP_LIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <pthread.h>
+#include <bluetooth/l2cap.h>
+#include "btio.h"
+#include "mcap.h"
+
+typedef enum {
+ MCAP_ERROR_INVALID_ARGS,
+ MCAP_ERROR_MEMORY,
+ MCAP_ERROR_ALREADY_EXISTS,
+ MCAP_ERROR_FAILED,
+ MCAP_ERROR_NOT_FOUND,
+} McapError;
+
+typedef enum {
+ MCAP_MDL_CB_INVALID,
+ MCAP_MDL_CB_CONNECTED,
+ MCAP_MDL_CB_CLOSED,
+ MCAP_MDL_CB_DELETED,
+ MCAP_MDL_CB_REMOTE_CONN_REQ,
+ MCAP_MDL_CB_REMOTE_RECONN_REQ,
+} McapMclCb;
+
+struct mcap_session;
+struct mcap_mcl;
+struct mcap_mdl;
+
+/************ Callbacks ************/
+
+/* mdl callbacks */
+
+typedef void (* mcap_mdl_event_cb) (struct mcap_mdl *mdl, gpointer data);
+typedef void (* mcap_mdl_operation_conf_cb) (struct mcap_mdl *mdl, uint8_t conf,
+ GError *err, gpointer data);
+typedef void (* mcap_mdl_operation_cb) (struct mcap_mdl *mdl, GError *err,
+ gpointer data);
+typedef void (* mcap_mdl_del_cb) (GError *err, gpointer data);
+
+/* Next function should return an MCAP appropiate response code */
+typedef uint8_t (* mcap_remote_mdl_conn_req_cb) (struct mcap_mcl *mcl,
+ uint8_t mdepid, uint16_t mdlid,
+ uint8_t *conf, gpointer data);
+typedef uint8_t (* mcap_remote_mdl_reconn_req_cb) (struct mcap_mdl *mdl,
+ gpointer data);
+
+/* mcl callbacks */
+
+typedef void (* mcap_mcl_event_cb) (struct mcap_mcl *mcl, gpointer data);
+typedef void (* mcap_mcl_connect_cb) (struct mcap_mcl *mcl, GError *err,
+ gpointer data);
+
+/************ Operations ************/
+
+/* Mdl operations*/
+
+void mcap_req_mdl_creation(struct mcap_mcl *mcl,
+ uint8_t mdepid,
+ uint8_t conf,
+ GError **err,
+ mcap_mdl_operation_conf_cb connect_cb,
+ gpointer user_data);
+void mcap_req_mdl_reconnect(struct mcap_mdl *mdl, GError **err,
+ mcap_mdl_operation_cb reconnect_cb,
+ gpointer user_data);
+void mcap_req_mdl_deletion(struct mcap_mdl *mdl, GError **err,
+ mcap_mdl_del_cb delete_cb, gpointer user_data);
+void mcap_mdl_connect(struct mcap_mdl *mdl,
+ BtIOType BtType,
+ uint16_t dcpsm,
+ GError **err,
+ mcap_mdl_operation_cb connect_cb,
+ gpointer user_data);
+void mcap_mdl_abort(struct mcap_mdl *mdl, GError **err,
+ mcap_mdl_del_cb abort_cb, gpointer user_data);
+int mcap_mdl_get_fd(struct mcap_mdl *mdl);
+
+/* Mcl operations*/
+
+void mcap_create_mcl(struct mcap_session *ms,
+ const bdaddr_t *addr,
+ uint16_t ccpsm,
+ GError **err,
+ mcap_mcl_connect_cb connect_cb,
+ gpointer user_data);
+void mcap_close_mcl(struct mcap_mcl *mcl);
+void mcap_mcl_set_cb(struct mcap_mcl *mcl, GError **gerr,
+ gpointer user_data, McapMclCb cb1, ...);
+bdaddr_t mcap_mcl_get_addr(struct mcap_mcl *mcl);
+
+/* MCAP main operations */
+
+struct mcap_session *mcap_create_session(struct btd_adapter *btd_adapter,
+ BtIOSecLevel sec, uint16_t ccpsm,
+ uint16_t dcpsm,
+ GError **gerr,
+ mcap_mcl_event_cb mcl_closed,
+ mcap_mcl_event_cb mcl_created,
+ gpointer user_data);
+
+void mcap_close_session(struct mcap_session *ms);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCAP_LIB_H */
+
--
1.6.3.3
^ permalink raw reply related
* Question regarding HS Connection
From: nirav rabara @ 2010-04-06 12:53 UTC (permalink / raw)
To: linux-bluetooth
Hi,
I am using Bluez-4.62 on ARM platform, I am using USB Bluetooth
dongle, I use bluez api for the connection and disconnection, I have
strange problem with HS connection.
1) I paired dongle with HS, So now whenever I use Dbus API to get
paired device list I get device as paired device.
2) After that I creat connection to HS, this time I am able to
connect/disconnect with HS. (working)
3) Now I connect HS to some other devices( mycellphone1 then
cellphone2, cellphone3 etc).
4) After that whenever I try to connect with HS, it show me below message.
bluetoothd[410] Unable to get service record: Operation already in progress(114)
-> According to me - This HS is trying to connect with last connected
device with it, and because of this reason it not get connected.
My question is if such the case than how to connect with HS?
Any suggestion would be appreciable.
--
With Regards,
Nirav Rabara
^ permalink raw reply
* Re: obexd and phonebook-ebook.c (PBAP support)
From: commerce @ 2010-04-05 8:36 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <4BB4B789.7070409@hschmitt.de>
commerce@hschmitt.de schrieb:
> Hi,
>
> Is it possible that obexd has to call g_type_init() if phonebook-ebook
> is used?
> I think when you call e_book_new_default_addressbook() somewhere down
> gconf_client_get_default() is called and it insists that g_type_init()
> is called prior to its use.
>
> I tried to make obexd work on my N900, but I did not get there.
> My car kit does not use PBAP because it finds the Nokia SyncML profile
> and uses it, but the N900 does not communicate with bluetooth devices
> other than PC or Mobiles via SyncML.
> Is there a way to unregister a service from SDP?
>
> Regards,
>
> --
> Harald
> --
> 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
>
Now I am using pbap-client from the obexd package from my notebook to
test pbap on my N900. I am pretty far. All my contacts are read, but the
obex message is not sent back successfully.
Here is the syslog (I added some messages):
Apr 5 09:56:35 Nokia-N900-51-1 obexd[1203]: pbap_get: pbap_get()
Apr 5 09:56:35 Nokia-N900-51-1 obexd[1203]: phonebook_pullphonebook:
phonebook_pullphonebook
Apr 5 09:56:36 Nokia-N900-51-1 obexd[1203]: pbap_pullphonebook:
phonebook_pullphonebook had no errors
Apr 5 09:56:36 Nokia-N900-51-1 obexd[1203]:
pbap_add_result_apparam_header: pbap_add_result_apparam_header
maxlistcount=65535 rspsize=0
Apr 5 09:56:36 Nokia-N900-51-1 obexd[1203]: pbap_get: pbap_get() no error
Apr 5 09:56:36 Nokia-N900-51-1 obexd[1203]: pbap_get: pbap_get() addbody
Apr 5 09:56:36 Nokia-N900-51-1 obexd[1203]: pbap_get: pbap_get()
OBEX_ObjectSetRsp()
Apr 5 09:56:36 Nokia-N900-51-1 obexd[1203]: PROGRESS(0x0), GET(0x3),
(null)(0x0)
Apr 5 09:56:36 Nokia-N900-51-1 obexd[1203]: ebookpull_cb: ebookpull_cb
count=305 size=42944
Apr 5 09:56:36 Nokia-N900-51-1 obexd[1203]: STREAMEMPTY(0x8),
CONNECT(0x0), (null)(0x0)
Apr 5 09:56:36 Nokia-N900-51-1 obexd[1203]: obex_write_stream:
name=telecom/pb.vcf type=x-bt/phonebook tx_mtu=3896 file=(nil)
Apr 5 09:56:36 Nokia-N900-51-1 obexd[1203]: STREAMEMPTY(0x8),
CONNECT(0x0), (null)(0x0)
Apr 5 09:56:36 Nokia-N900-51-1 obexd[1203]: obex_write_stream:
name=telecom/pb.vcf type=x-bt/phonebook tx_mtu=3896 file=(nil)
Apr 5 09:56:36 Nokia-N900-51-1 obexd[1203]: PROGRESS(0x0),
(null)(0x10), (null)(0x0)
Apr 5 09:56:37 Nokia-N900-51-1 obexd[1203]: REQDONE(0x3), (null)(0x10),
(null)(0x3)
Apr 5 09:57:00 Nokia-N900-51-1 obexd[1203]: obex_handle_input: poll
event HUP ERR
Best,
Harald
^ permalink raw reply
* Memory corruptions on sdp resolve
From: Manuel Naranjo @ 2010-04-05 1:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Johan Hedberg
In-Reply-To: <t2xa10be5a01004041832lb2f4a3fen8406ab15f5173e9d@mail.gmail.com>
Oops this time in plain text
Hello everyone,
Yesterday I reported over irc (nickname manuelnaranjo) I was
experiencing some memory corruption problems. Johan was kindly enough
to provide a patch, and I tested it over the day.
I was driving for 2 hours with a netbook scanning the air for obex
capable devices and eventually I was able to get a new crash,
different from the one the other day.
I'm attaching logs so you can help me find the problem.
bluetoothd -n -d output:
bluetoothd[4473]: Creating device /org/bluez/4473/hci1/dev_44_F4_59_BB_09_A6
bluetoothd[4473]: btd_device_ref(0x1a0148): ref=1
bluetoothd[4473]: btd_device_ref(0x1a0148): ref=2
bluetoothd[4473]: Discovery session 0x1a02e8 with :1.132 activated
bluetoothd[4473]: session_ref(0x1a02e8): ref=1
bluetoothd[4473]: adapter_get_device(44:F4:59:BB:09:A6)
bluetoothd[4473]: Removing device /org/bluez/4473/hci1/dev_44_F4_59_BB_09_A6
bluetoothd[4473]: btd_device_unref(0x1a0148): ref=1
bluetoothd[4473]: btd_device_unref(0x1a0148): ref=0
bluetoothd[4473]: device_free(0x1a0148)
bluetoothd[4473]: H: : error updating services: Host is down (112)
process 4473: arguments to dbus_connection_send() were incorrect,
assertion "connection != NULL" failed in file dbus-connection.c line
3139.
This is normally a bug in some application using the D-Bus library.
process 4473: arguments to dbus_message_unref() were incorrect,
assertion "!message->in_cache" failed in file dbus-message.c line
1397.
This is normally a bug in some application using the D-Bus library.
bluetoothd[4473]: btd_device_unref(0x1a0148): ref=343
*** glibc detected *** /opt/bluez/sbin/bluetoothd: corrupted
double-linked list: 0x0019c7a8 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0xb7dc9ff1]
/lib/tls/i686/cmov/libc.so.6[0xb7dca23a]
/lib/tls/i686/cmov/libc.so.6[0xb7dcc4e2]
/lib/tls/i686/cmov/libc.so.6(__libc_calloc+0xa9)[0xb7dce039]
/lib/tls/i686/cmov/libc.so.6(open_memstream+0x5d)[0xb7dbe66d]
/lib/tls/i686/cmov/libc.so.6(__vsyslog_chk+0x75)[0xb7e27615]
/opt/bluez/sbin/bluetoothd(debug+0x3e)[0x14428e]
/opt/bluez/sbin/bluetoothd[0x158e5c]
/opt/bluez/sbin/bluetoothd[0x1613da]
/opt/bluez/sbin/bluetoothd[0x145ac2]
/lib/libglib-2.0.so.0[0xb7f73dab]
/lib/libglib-2.0.so.0(g_main_context_dispatch+0x1f8)[0xb7f3ce88]
/lib/libglib-2.0.so.0[0xb7f40730]
/lib/libglib-2.0.so.0(g_main_loop_run+0x1bf)[0xb7f40b9f]
/opt/bluez/sbin/bluetoothd[0x143d3e]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xb7d75b56]
/opt/bluez/sbin/bluetoothd[0x117801]
======= Memory map: ========
00110000-0016e000 r-xp 00000000 08:07 321382 /opt/bluez/sbin/bluetoothd
0016e000-0016f000 r-xp 00000000 00:00 0 [vdso]
0016f000-00170000 r--p 0005e000 08:07 321382 /opt/bluez/sbin/bluetoothd
00170000-00172000 rw-p 0005f000 08:07 321382 /opt/bluez/sbin/bluetoothd
00172000-001aa000 rw-p 00000000 00:00 0 [heap]
b7b00000-b7b21000 rw-p 00000000 00:00 0
b7b21000-b7c00000 ---p 00000000 00:00 0
b7c88000-b7ca4000 r-xp 00000000 08:07 285065 /lib/libgcc_s.so.1
b7ca4000-b7ca5000 r--p 0001b000 08:07 285065 /lib/libgcc_s.so.1
b7ca5000-b7ca6000 rw-p 0001c000 08:07 285065 /lib/libgcc_s.so.1
b7ca6000-b7cca000 r-xp 00000000 08:07 310528
/lib/tls/i686/cmov/libm-2.10.1.so
b7cca000-b7ccb000 r--p 00023000 08:07 310528
/lib/tls/i686/cmov/libm-2.10.1.so
b7ccb000-b7ccc000 rw-p 00024000 08:07 310528
/lib/tls/i686/cmov/libm-2.10.1.so
b7ccc000-b7d19000 r-xp 00000000 08:07 26680 /usr/lib/libnl.so.1.1
b7d19000-b7d1a000 r--p 0004c000 08:07 26680 /usr/lib/libnl.so.1.1
b7d1a000-b7d1d000 rw-p 0004d000 08:07 26680 /usr/lib/libnl.so.1.1
b7d2c000-b7d2d000 rw-p 00000000 00:00 0
b7d2d000-b7d5c000 r-xp 00000000 08:07 285168 /lib/libpcre.so.3.12.1
b7d5c000-b7d5d000 r--p 0002e000 08:07 285168 /lib/libpcre.so.3.12.1
b7d5d000-b7d5e000 rw-p 0002f000 08:07 285168 /lib/libpcre.so.3.12.1
b7d5e000-b7d5f000 rw-p 00000000 00:00 0
b7d5f000-b7e9d000 r-xp 00000000 08:07 310524
/lib/tls/i686/cmov/libc-2.10.1.so
b7e9d000-b7e9e000 ---p 0013e000 08:07 310524
/lib/tls/i686/cmov/libc-2.10.1.so
b7e9e000-b7ea0000 r--p 0013e000 08:07 310524
/lib/tls/i686/cmov/libc-2.10.1.so
b7ea0000-b7ea1000 rw-p 00140000 08:07 310524
/lib/tls/i686/cmov/libc-2.10.1.so
b7ea1000-b7ea4000 rw-p 00000000 00:00 0
b7ea4000-b7ea6000 r-xp 00000000 08:07 310527
/lib/tls/i686/cmov/libdl-2.10.1.so
b7ea6000-b7ea7000 r--p 00001000 08:07 310527
/lib/tls/i686/cmov/libdl-2.10.1.so
b7ea7000-b7ea8000 rw-p 00002000 08:07 310527
/lib/tls/i686/cmov/libdl-2.10.1.so
b7ea8000-b7eaf000 r-xp 00000000 08:07 310540
/lib/tls/i686/cmov/librt-2.10.1.so
b7eaf000-b7eb0000 r--p 00006000 08:07 310540
/lib/tls/i686/cmov/librt-2.10.1.so
b7eb0000-b7eb1000 rw-p 00007000 08:07 310540
/lib/tls/i686/cmov/librt-2.10.1.so
b7eb1000-b7ec6000 r-xp 00000000 08:07 310538
/lib/tls/i686/cmov/libpthread-2.10.1.so
b7ec6000-b7ec7000 r--p 00014000 08:07 310538
/lib/tls/i686/cmov/libpthread-2.10.1.so
b7ec7000-b7ec8000 rw-p 00015000 08:07 310538
/lib/tls/i686/cmov/libpthread-2.10.1.so
b7ec8000-b7eca000 rw-p 00000000 00:00 0
b7eca000-b7f01000 r-xp 00000000 08:07 285099 /lib/libdbus-1.so.3.4.0
b7f01000-b7f02000 r--p 00036000 08:07 285099 /lib/libdbus-1.so.3.4.0
b7f02000-b7f03000 rw-p 00037000 08:07 285099 /lib/libdbus-1.so.3.4.0
b7f03000-b7f04000 rw-p 00000000 00:00 0
b7f04000-b7fb9000 r-xp 00000000 08:07 285198 /lib/libglib-2.0.so.0.2200.3
b7fb9000-b7fba000 r--p 000b4000 08:07 285198 /lib/libglib-2.0.so.0.2200.3
b7fba000-b7fbb000 rw-p 000b5000 08:07 285198 /lib/libglib-2.0.so.0.2200.3
b7fbe000-b7fbf000 rw-p 00000000 08:07 336783
/opt/bluez/var/lib/bluetooth/00:25:BF:01:00:9E/profiles
b7fbf000-b7fc0000 rw-p 00000000 08:07 336783
/opt/bluez/var/lib/bluetooth/00:25:BF:01:00:9E/profiles
b7fc0000-b7fc7000 r--s 00000000 08:07 34219
/usr/lib/gconv/gconv-modules.cache
b7fc7000-b7fc8000 r-xp 00000000 08:07 321444
/opt/bluez/lib/bluetooth/plugins/netlink.so
b7fc8000-b7fc9000 r--p 00000000 08:07 321444
/opt/bluez/lib/bluetooth/plugins/netlink.so
b7fc9000-b7fca000 rw-p 00001000 08:07 321444
/opt/bluez/lib/bluetooth/plugins/netlink.so
b7fca000-b7fde000 r-xp 00000000 08:07 313260
/opt/bluez/lib/libbluetooth.so.3.6.0
b7fde000-b7fdf000 r--p 00013000 08:07 313260
/opt/bluez/lib/libbluetooth.so.3.6.0
b7fdf000-b7fe1000 rw-p 00014000 08:07 313260
/opt/bluez/lib/libbluetooth.so.3.6.0
b7fe1000-b7fe3000 rw-p 00000000 00:00 0
b7fe3000-b7ffe000 r-xp 00000000 08:07 285043 /lib/ld-2.10.1.so
b7ffe000-b7fff000 r--p 0001a000 08:07 285043 /lib/ld-2.10.1.so
b7fff000-b8000000 rw-p 0001b000 08:07 285043 /lib/ld-2.10.1.so
bffeb000-c0000000 rw-p 00000000 00:00 0 [stack]
At this point gdb reports a SIGABRT I think comming from glib,
stacktrace at that time is:
Program received signal SIGABRT, Aborted.
0x0016e422 in __kernel_vsyscall ()
(gdb) bt
#0 0x0016e422 in __kernel_vsyscall ()
#1 0xb7d894d1 in *__GI_raise (sig=6) at
../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2 0xb7d8c932 in *__GI_abort () at abort.c:92
#3 0xb7dbfee5 in __libc_message (do_abort=2, fmt=0xb7e83578 "***
glibc detected *** %s: %s: 0x%s ***\n")
at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
#4 0xb7dc9ff1 in malloc_printerr (action=<value optimized out>,
str=0x6 <Address 0x6 out of bounds>, ptr=0x19c7a8)
at malloc.c:6217
#5 0xb7dca23a in malloc_consolidate (av=<value optimized out>) at malloc.c:5103
#6 0xb7dcc4e2 in _int_malloc (av=<value optimized out>, bytes=<value
optimized out>) at malloc.c:4338
#7 0xb7dce039 in __libc_calloc (n=1, elem_size=8192) at malloc.c:4041
#8 0xb7dbe66d in *__GI_open_memstream (bufloc=0xbfffe1d4,
sizeloc=0xbfffe1d0) at memstream.c:86
#9 0xb7e27615 in *__GI___vsyslog_chk (pri=31, flag=1, fmt=0x16c8d2
"Removing temporary device %s",
ap=0xbfffe214 "\340+\032") at ../misc/syslog.c:169
#10 0x0014428e in vsyslog (format=0x16c8d2 "Removing temporary device
%s") at /usr/include/bits/syslog.h:48
#11 debug (format=0x16c8d2 "Removing temporary device %s") at src/logging.c:72
#12 0x00158e5c in adapter_remove_connection (adapter=0x1a5c60,
device=0x19a170, handle=<value optimized out>)
at src/adapter.c:2835
#13 0x001613da in hcid_dbus_disconn_complete (local=0x19b69a, status=0
'\000', handle=42, reason=8 '\b')
at src/dbus-hci.c:773
#14 0x00145ac2 in disconn_complete (chan=0x19e1e8, cond=<value
optimized out>, data=0x19b690) at src/security.c:901
#15 io_security_event (chan=0x19e1e8, cond=<value optimized out>,
data=0x19b690) at src/security.c:1032
#16 0xb7f73dab in g_io_unix_dispatch (source=0x178bb0,
callback=0x144ef0 <io_security_event>, user_data=0x19b690)
at /build/buildd/glib2.0-2.22.3/glib/giounix.c:162
#17 0xb7f3ce88 in g_main_dispatch (context=0x178b30) at
/build/buildd/glib2.0-2.22.3/glib/gmain.c:1960
#18 IA__g_main_context_dispatch (context=0x178b30) at
/build/buildd/glib2.0-2.22.3/glib/gmain.c:2513
#19 0xb7f40730 in g_main_context_iterate (context=0x178b30,
block=<value optimized out>, dispatch=1, self=0x174b08)
at /build/buildd/glib2.0-2.22.3/glib/gmain.c:2591
#20 0xb7f40b9f in IA__g_main_loop_run (loop=0x1795f0) at
/build/buildd/glib2.0-2.22.3/glib/gmain.c:2799
#21 0x00143d3e in main (argc=1, argv=0xbffff794) at src/main.c:451
I've been moving through the stack and discovered that variable path
isn't actually corrupted:
(gdb) up
#12 0x00158e5c in adapter_remove_connection (adapter=0x1a5c60,
device=0x19a170, handle=<value optimized out>)
at src/adapter.c:2835
2835 debug("Removing temporary device %s", path);
(gdb) print *device
$5 = {bdaddr = {b = "\246\t\273Y\364D"}, path = 0x1a2be0
"/org/bluez/4473/hci0/dev_44_F4_59_BB_09_A6",
name = '\000' <repetidos 248 veces>, adapter = 0x1a5c60, uuids =
0x0, drivers = 0x0, watches = 0x0, temporary = 1,
agent = 0x0, disconn_timer = 0, discov_timer = 0, browse = 0x19e000,
bonding = 0x0, authr = 0x0, disconnects = 0x0,
cap = 0 '\000', auth = 255 '\377', handle = 0, secmode3 = 0,
tmp_records = 0x0, paired = 0, renewed_key = 0,
authorizing = 0, ref = 2}
I guess this problem is related to a broken reference counting, and
glib keeping references coherents. I will take a more cloose look
tomorrow.
Regards,
Manuel Naranjo
--
Manuel Francisco Naranjo
Software Department Argentina
Wireless Cables Inc
www.aircable.net
cel: +5493412010019
skype: naranjomanuelfrancisco
--
Manuel Francisco Naranjo
Software Department Argentina
Wireless Cables Inc
www.aircable.net
cel: +5493412010019
skype: naranjomanuelfrancisco
^ permalink raw reply
* Re: Question about BlueZ's configure script
From: João Paulo Rechi Vita @ 2010-04-04 13:14 UTC (permalink / raw)
To: Daniel Abraham; +Cc: linux-bluetooth
In-Reply-To: <k2h2c3916b71004040340t63dccd5bj11953c26d826d98f@mail.gmail.com>
On Sun, Apr 4, 2010 at 10:40, Daniel Abraham <daniel.shrugged@gmail.com> wrote:
> In BlueZ's README, dev packages for ALSA, Gstreamer (+ plugins base),
> and libsnd are not listed as required or even optional.
>
> However, the configure script does look for them (although it doesn't
> fail if they're missing).
>
> So my question is: why does it look for them? How do they affect BlueZ
> compilation/functionality?
>
Bluetooth audio profiles are implemented in 3 different ways: as an
ALSA driver (soon-to-be deprecated), GStreamer elements (SBC decoder,
A2DP sink, etc), and PulseAudio modules (recommended). These last ones
lives on PulseAudio's tree, the other two live on bluez' tree, so if
configure finds it's headers it enables compilation of the respective
modules.
--
João Paulo Rechi Vita
http://jprvita.wordpress.com/
^ permalink raw reply
* Question about BlueZ's configure script
From: Daniel Abraham @ 2010-04-04 10:40 UTC (permalink / raw)
To: linux-bluetooth
In BlueZ's README, dev packages for ALSA, Gstreamer (+ plugins base),
and libsnd are not listed as required or even optional.
However, the configure script does look for them (although it doesn't
fail if they're missing).
So my question is: why does it look for them? How do they affect BlueZ
compilation/functionality?
Thanks
^ permalink raw reply
* Re: Bluetooth connection from Windows to uClinux
From: Gustavo F. Padovan @ 2010-04-02 9:49 UTC (permalink / raw)
To: Danny.Wijffelaars; +Cc: linux-bluetooth
In-Reply-To: <OF48CCDAB9.2A474A60-ONC12576F9.00324700-C12576F9.0032EEC1@LocalDomain>
Hi Frank,
On Fri, Apr 2, 2010 at 6:15 AM, <Danny.Wijffelaars@humiq.nl> wrote:
> Hey everyone,
> I'm trying to connect my windows xp pc (microsoft stack) to uClinux (bluez
> stack), via Bluetooth.
> The problem I'm having is that Windows wants a PIN for authentication, but
> I can't find a way to get uClinux to give this PIN to Windows.
> Can anybody tell me how to accomplish this?
Are you using any kind of Agent for BlueZ? In the test/ dir of bluez
sources there the simple-agent if you need one.
--
Gustavo F. Padovan
http://padovan.org
^ permalink raw reply
* Bluetooth connection from Windows to uClinux
From: Danny.Wijffelaars @ 2010-04-02 9:15 UTC (permalink / raw)
To: linux-bluetooth
Hey everyone,
I'm trying to connect my windows xp pc (microsoft stack) to uClinux (bluez
stack), via Bluetooth.
The problem I'm having is that Windows wants a PIN for authentication, but
I can't find a way to get uClinux to give this PIN to Windows.
Can anybody tell me how to accomplish this?
Thanks in advance!
Greetings,
Frank
P Think green: do you really need to print this e-mail? We are delighted to announce that, as of 1 January 2010, the specific strengths of ICT Embedded, ICT Solutions and ICT Procos have been united in HUMIQ. As the name suggests, the drivers behind HUMIQ are the Human Factor and IQ. But naturally, like its predecessors, HUMIQ also stands for a leading role in the various markets. Its core values are quality of work and reliability as a partner; its objective is the continuity of our relationship. We would therefore request you to direct all future correspondence relating to ICT Embedded, ICT Solutions and ICT Procos to HUMIQ at the usual address. HUMIQ. Intelligent people. Intelligent solutions.
"The content of this E-mail message, including any attached documentation, is the property of ICT Automatisering NV and/or its subsidiaries (hereinafter "ICT") and may be confidential and is intended to be exclusively for the addressee. If you are not the intended recipient, please do not use the contents herein and you are urged to inform the sender immediately by return e-mail (reply) and remove the message from your system. Any unauthorised use, disclosure or copying of the information, in whole or in part, is prohibited. ICT is not responsible for incorrect, incomplete and/or delayed transfer of messages and possible damage caused by this. Although ICT makes every effort to send messages free of viruses by using a virus checker, ICT cannot guarantee that the message and any attachments are actually completely virus free and consequently are not responsible or liable for possible damage caused by this."
^ permalink raw reply
* Re: S2RAM broken on HP 8530p (btusb involved)
From: Rafael J. Wysocki @ 2010-04-01 22:31 UTC (permalink / raw)
To: Parag Warudkar; +Cc: linux-kernel, Marcel Holtmann, linux-bluetooth
In-Reply-To: <alpine.DEB.2.00.1004011814140.2792@parag-laptop>
On Friday 02 April 2010, Parag Warudkar wrote:
>
> On Thu, 1 Apr 2010, Rafael J. Wysocki wrote:
>
> > On Thursday 01 April 2010, Parag Warudkar wrote:
> > >
> > > On Thu, 1 Apr 2010, Rafael J. Wysocki wrote:
> > >
> > > > Please try:
> > > >
> > > > # echo devices > /sys/power/pm_test
> > > > # echo mem > /sys/power/state
> > > >
> > > > and see if that breaks too (it should get back to the command line in about
> > > > 5-10 seconds).
> > >
> > > That breaks too - hangs similarly during suspend. I enabled RTC tracing
> > > and every time it prints out different hash matches after reboot -
> > > tty/tty21, pcie04 and latest is
> > >
> > > [ 0.865296] pcieport 0000:00:1c.1: hash matches
> > >
> > > Also when the suspend fails the immediate boot after that I get a USB
> > > error on startup - unable to enumerate usb device on port 1. This error is
> > > not present on normal boots.
> >
> > Well, try the above with the USB controller drivers unloaded.
> >
>
> Turns out its not the controller drivers but btusb and friends. Once I
> removed btusb,sco,bnep,l2cap and family I was able to suspend resume just
> like before.
>
> For now I have disabled Bluetooth in BIOS as I don't need it - it is
> likely that it was disabled earlier and so the suspend/resume was
> working but looks like after a BIOS update/reset I left it enabled.
>
> So this does not seem to be a regression to me.
>
> But may be it should be possible to suspend/resume with bluetooth enabled?
> :)
Sure.
Adding CCs to the bluetooth people.
Rafael
^ permalink raw reply
* [PATCH 34/34] Bluetooth: Remove unneeded check for MTU on sco_send_frame()
From: Gustavo F. Padovan @ 2010-04-01 20:23 UTC (permalink / raw)
To: linux-bluetooth; +Cc: marcel, gustavo, jprvita
In-Reply-To: <1270153432-6477-34-git-send-email-padovan@profusion.mobi>
We have
count = min_t(unsigned int, conn->mtu, len);
there, so no need to return on len > conn->mtu.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
net/bluetooth/sco.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 1dc7856..e2da719 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -234,10 +234,6 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
struct sk_buff *skb;
int err, count;
- /* Check outgoing MTU */
- if (len > conn->mtu)
- return -EINVAL;
-
BT_DBG("sk %p len %d", sk, len);
count = min_t(unsigned int, conn->mtu, len);
--
1.6.4.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