* [PATCH 0/2] keep ti-st staging updated
From: pavan_savoy @ 2010-12-14 12:06 UTC (permalink / raw)
To: gregkh, linux-kernel; +Cc: padovan, marcel, linux-bluetooth, Pavan Savoy
From: Pavan Savoy <pavan_savoy@ti.com>
Greg,
In my attempt to upstream BT driver based on TI ST driver,
I had posted several patches to linux-bluetooth.
At this point, there are no review comments as such specifically
to bluetooth driver but there are few concerns regarding the TI-ST driver itself.
As I await the responses from Gustavo, Marcel on how best to proceed
in improving btwilink driver, I am deleting the very old bt_drv from
the staging and updating it with relatively acceptable btwilink driver.
Pavan Savoy (2):
drivers:staging: ti-st: remove bt_drv
drivers:staging: ti-st: update the TI ST BT driver
drivers/staging/ti-st/Kconfig | 25 +-
drivers/staging/ti-st/Makefile | 6 +-
drivers/staging/ti-st/bt_drv.c | 509 --------------------------------------
drivers/staging/ti-st/bt_drv.h | 61 -----
drivers/staging/ti-st/btwilink.c | 363 +++++++++++++++++++++++++++
drivers/staging/ti-st/sysfs-uim | 28 --
6 files changed, 376 insertions(+), 616 deletions(-)
delete mode 100644 drivers/staging/ti-st/bt_drv.c
delete mode 100644 drivers/staging/ti-st/bt_drv.h
create mode 100644 drivers/staging/ti-st/btwilink.c
delete mode 100644 drivers/staging/ti-st/sysfs-uim
^ permalink raw reply
* [PATCH 2/2] Bluetooth: Fix __hci_request synchronization for hci_open_dev
From: johan.hedberg @ 2010-12-14 12:04 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292328244-5335-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@nokia.com>
The initialization function used by hci_open_dev (hci_init_req) sends
many different HCI commands. The __hci_request function should only
return when all of these commands have completed (or a timeout occurs).
Several of these commands cause hci_req_complete to be called which
causes __hci_request to return prematurely.
This patch fixes the issue by making use of the HCI_INIT flag which is
set during the initialization procedure. The hci_req_comple function
will no longer do anything when this flag is set and a new
hci_init_complete function is added which ignores the flag and gets
called when the last hci_init_req HCI command completes.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_core.c | 14 ++++++++++++++
net/bluetooth/hci_event.c | 14 ++++++++++++++
3 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3786ee8..1f421df 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -694,5 +694,6 @@ struct hci_sec_filter {
#define hci_req_unlock(d) mutex_unlock(&d->req_lock)
void hci_req_complete(struct hci_dev *hdev, int result);
+void hci_init_complete(struct hci_dev *hdev, int result);
#endif /* __HCI_CORE_H */
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 6374054..8d08538 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -91,10 +91,24 @@ static void hci_notify(struct hci_dev *hdev, int event)
/* ---- HCI requests ---- */
+void hci_init_complete(struct hci_dev *hdev, int result)
+{
+ BT_DBG("%s result 0x%2.2x", hdev->name, result);
+
+ if (hdev->req_status == HCI_REQ_PEND) {
+ hdev->req_result = result;
+ hdev->req_status = HCI_REQ_DONE;
+ wake_up_interruptible(&hdev->req_wait_q);
+ }
+}
+
void hci_req_complete(struct hci_dev *hdev, int result)
{
BT_DBG("%s result 0x%2.2x", hdev->name, result);
+ if (test_bit(HCI_INIT, &hdev->flags))
+ return;
+
if (hdev->req_status == HCI_REQ_PEND) {
hdev->req_result = result;
hdev->req_status = HCI_REQ_DONE;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8923b36..939ba9f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -539,6 +539,16 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
hci_req_complete(hdev, rp->status);
}
+static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+
+ BT_DBG("%s status 0x%x", hdev->name, status);
+
+ if (test_bit(HCI_INIT, &hdev->flags))
+ hci_init_complete(hdev, status);
+}
+
static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1379,6 +1389,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_read_bd_addr(hdev, skb);
break;
+ case HCI_OP_WRITE_CA_TIMEOUT:
+ hci_cc_write_ca_timeout(hdev, skb);
+ break;
+
default:
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
break;
--
1.7.2.3
^ permalink raw reply related
* [PATCH 1/2] Bluetooth: Introduce a new HCI_CLOSE flag for hci_dev_close()
From: johan.hedberg @ 2010-12-14 12:04 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292328244-5335-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@nokia.com>
To be able to handle the intialization state differently from the
closing state (e.g. different sets of HCI commands are sent in them) a
distinct state flag should be used when closing a device.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
include/net/bluetooth/hci.h | 1 +
net/bluetooth/hci_core.c | 10 ++++++----
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 29a7a8c..517a652 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -68,6 +68,7 @@ enum {
HCI_UP,
HCI_INIT,
HCI_RUNNING,
+ HCI_CLOSE,
HCI_PSCAN,
HCI_ISCAN,
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 1a4ec97..6374054 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -581,10 +581,10 @@ static int hci_dev_do_close(struct hci_dev *hdev)
skb_queue_purge(&hdev->cmd_q);
atomic_set(&hdev->cmd_cnt, 1);
if (!test_bit(HCI_RAW, &hdev->flags)) {
- set_bit(HCI_INIT, &hdev->flags);
+ set_bit(HCI_CLOSE, &hdev->flags);
__hci_request(hdev, hci_reset_req, 0,
msecs_to_jiffies(250));
- clear_bit(HCI_INIT, &hdev->flags);
+ clear_bit(HCI_CLOSE, &hdev->flags);
}
/* Kill cmd task */
@@ -1029,7 +1029,8 @@ int hci_recv_frame(struct sk_buff *skb)
{
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
if (!hdev || (!test_bit(HCI_UP, &hdev->flags)
- && !test_bit(HCI_INIT, &hdev->flags))) {
+ && !test_bit(HCI_INIT, &hdev->flags)
+ && !test_bit(HCI_CLOSE, &hdev->flags))) {
kfree_skb(skb);
return -ENXIO;
}
@@ -1695,7 +1696,8 @@ static void hci_rx_task(unsigned long arg)
continue;
}
- if (test_bit(HCI_INIT, &hdev->flags)) {
+ if (test_bit(HCI_INIT, &hdev->flags) ||
+ test_bit(HCI_CLOSE, &hdev->flags)) {
/* Don't process data packets in this states. */
switch (bt_cb(skb)->pkt_type) {
case HCI_ACLDATA_PKT:
--
1.7.2.3
^ permalink raw reply related
* Patches to fix kernel side init/deinit of adapters
From: johan.hedberg @ 2010-12-14 12:04 UTC (permalink / raw)
To: linux-bluetooth
Hi,
Before I start implementing support for powering on and off adapters
through the management interface some basic things in the current code
need fixing. The first issue is that the __hci_request doesn't work the
way it's supposed to when called from hci_open_dev. It's supposed to
return when the entire request is complete but right now it returns as
soon as the first command in the request is complete.
The first patch in this set is needed to make it possible to take
advantage of the HCI_INIT flag in the second patch.
Johan
^ permalink raw reply
* Re: [PATCH 00/10] More btd_error_* patches
From: Johan Hedberg @ 2010-12-14 8:56 UTC (permalink / raw)
To: Gustavo F. Padovan; +Cc: linux-bluetooth
In-Reply-To: <1292275987-13799-1-git-send-email-padovan@profusion.mobi>
Hi Gustavo,
On Mon, Dec 13, 2010, Gustavo F. Padovan wrote:
> This patch set adds a new error function btd_error_failed(), which has a str
> parameter to enable a more accurate error report in the case the usual
> btd_error_* does not fit.
>
> After this patch set there will 10 occurrences of g_dbus_create_error() inside
> bluez code (not counting health/ here)
Thanks. The patches are now upstream. However, I did have to push other
fixes on top of them since a few functions that you assumed were
returning a proper negative errno value were in fact only returning -1.
Johan
^ permalink raw reply
* Re: [RFC] Bluetooth: Use non-flushable pb flag by default for ACL data on capable chipsets.
From: Suraj Sumangala @ 2010-12-14 6:34 UTC (permalink / raw)
To: Emeltchenko Andrei; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1292251105-31130-2-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On 12/13/2010 8:08 PM, Emeltchenko Andrei wrote:
> static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
> {
> struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
> + u8 flags;
>
> BT_DBG("code 0x%2.2x", code);
>
> if (!skb)
> return;
>
> - hci_send_acl(conn->hcon, skb, 0);
> + if (lmp_no_flush_capable(conn->hcon->hdev))
> + flags = ACL_START_NO_FLUSH;
> + else
> + flags = ACL_START;
> +
> + hci_send_acl(conn->hcon, skb, flags);
> }
>
Should we send L2CAP command packets also as flushable packets? Should
it be non-flushable?
I thought only L2CAP data frames should be sent as flushable.
Regards
Suraj
^ permalink raw reply
* LE Compound Procedure strategy
From: Brian Gix @ 2010-12-13 21:46 UTC (permalink / raw)
To: Vinicius Costa Gomes; +Cc: linux-bluetooth
Hi Vinicius,
I am breaking this out into a new conversation.
How about we create a new parameter to g_attrib_send, which is a boolean
that indicates wether or not the command being sent may be the start (or
continuation) of a Compound GATT procedure?
If this flag is TRUE, then when gattrib.c creates the command record for
it, it will see if it is continuing a prior procedure, and if so add it
to the head of the queue. Perhaps even *replace* the current head, which
would presumably be recognized as the original command.
This would allow it to reuse the Command ID (allowing the upper layers
to cancel as needed) and ensure the single-threaded intent of compound
GATT procedures.
An additional gattrib.c API could then be added which must be called at
the conclusion of all compound GATT procedures. This new API would
perform final clean-up on the procedure, including allowing the next
(following) items in the command queue to be serviced.
Your Thoughts?
--
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply
* Re: [PATCH 1/1] Support for reading long Characteristic Values.
From: Brian Gix @ 2010-12-13 21:33 UTC (permalink / raw)
To: Vinicius Costa Gomes; +Cc: linux-bluetooth, padovan, rshaffer
In-Reply-To: <20101213203336.GC7549@eris>
Hi Vinicius,
On 12/13/2010 12:33 PM, Vinicius Costa Gomes wrote:
> On 11:56 Mon 13 Dec, Brian Gix wrote:
> [trimmed]
>
>>>> +
>>>> + if (ret_val != 0)
>>>> + return;
>>>> +
>>>> + status = ATT_ECODE_INSUFF_RESOURCES;
>>>> +
>>>> +done:
>>>> + long_read->func(status, res_pdu, res_len, long_read->user_data);
>>>
>>> If g_attrib_send() fails, load_read->result_data may be leaking here.
>>
>> Is there no guarantee that the GAttribResultFunc parameter will be
>> invoked if there is a non-Zero return value from g_attrib_send?
>>
>> If there is paths that could result in a non-response (abnormal link
>> termination?) then you are correct, and I will need to rethink clean-up.
>
> The case I was referring was when g_attrib_send() cannot allocate memory for
> the command.
>
I don't think this is an issue, because if g_attrib_send() cannot
allocate memory, then it will return a 0, and fall through to the
completion and clean-up. However, I like the idea of doing all clean-up
in the destructor anyway, which resolves the memory leak potential.
>>> [...]
>> Also:
>> If we intend to use the ID of the (original) command to cancel the GATT
>> procedure, I propose the following:
>>
>> Compound GATT procedure such as the Read Long procedure that I am
>> implementing, should save the original ID returned by g_attrib_send in
>> the nested user_data structure such as I have done. When subsequent ATT
>> commands are sent as part of the same GATT procedure, the new command
>> shall be assigned the same ID as the original. This could be done with
>> a function in gattrib.c with the prototype:
>>
>> g_attrib_set_id(GAttrib *attrib, guint old_id, guint new_id);
>>
>> This would allow the upper layer to cancel the entire GATT procedure,
>> even if it is partially completed.
>>
>> This same methodology could then be applied to long writes, and other
>> compound GATT procedures.
>>
>> What do you think?
>
> Sounds good, I just don't know about messing with the commands id's,
> maybe having some thing like command groups.
>
> For example, adding these funtions:
>
> guint g_attrib_send_full(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
> guint16 len, guint group, GAttribResultFunc func,
> gpointer user_data, GDestroyNotify notify);
>
> gboolean g_attrib_cancel_group(GAttrib *attrib, guint group);
>
> How do this look?
>
My biggest objection would be that to go this route, I think we would
want to extend this "command group" to all GATT procedures, and not just
the ones known or suspected to be Compound. I don't think that
canceling a "Characteristic Value Read" procedure should be any
different (or use a different parameter type) than canceling "Find
Primary Service", for example.
Do you think everything in gatt.c should use these "command groups"?
And if so, by what mechanism would the "group number" remain unique?
It doesn't seem to me to be such a horrible overloading of the id. I do
see that when a cancel is called, that it is important that only one
command with that ID is in the queue. However, this reclaimation/reuse
of the old ID would only occur after the prior instance is in the
process of being destroyed. The danger I suppose would be the misuse of
this renumbering capability by an entity other than gatt.c.
I'm sorry this is getting long winded BUT:
This also highlights the inherent danger of allowing multiple Requests
to be queued up. If are to allow a Read-Value, Write-Value, Read-Value
sequence of commands to be enqueued onto the attrib->queue, it will be
impossible to correctly implement any of the compound Read or Write
commands, because the subsequent "Read-Blob" would be added to the end
of the queue, and the read could be split around a write. GATT/ATT was
always intended to be a single outstanding request (and procedure) at a
time kind of protocol, and having a FIFO attrib->queue subverts that intent.
To get compound GATT procedures to work properly (while maintaining the
Attrib queuing mechanism) we may need to restructure gattrib.c such that
we can add the subsequent commands to the *head* of the queue, and not
call wake_up_sender in the received_data() function until after the
cmd->func() has been invoked, and given the opportunity to "continue the
current procedure".
>
> Cheers,
--
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply
* [PATCH 10/10] src: use btd_error_failed()
From: Gustavo F. Padovan @ 2010-12-13 21:33 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292275987-13799-10-git-send-email-padovan@profusion.mobi>
---
src/adapter.c | 37 +++++++++++++------------------------
src/device.c | 44 ++++++++++++--------------------------------
2 files changed, 25 insertions(+), 56 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index e37b200..47ee26a 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -146,12 +146,6 @@ static inline DBusMessage *adapter_not_ready(DBusMessage *msg)
"Adapter is not ready");
}
-static inline DBusMessage *failed_strerror(DBusMessage *msg, int err)
-{
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", strerror(err));
-}
-
static inline DBusMessage *not_in_progress(DBusMessage *msg, const char *str)
{
return g_dbus_create_error(msg, ERROR_INTERFACE ".NotInProgress",
@@ -523,7 +517,7 @@ static DBusMessage *set_discoverable(DBusConnection *conn, DBusMessage *msg,
err = set_mode(adapter, mode, msg);
if (err < 0)
- return failed_strerror(msg, -err);
+ return btd_error_failed(msg, strerror(-err));
return NULL;
}
@@ -548,7 +542,7 @@ static DBusMessage *set_powered(DBusConnection *conn, DBusMessage *msg,
err = set_mode(adapter, mode, msg);
if (err < 0)
- return failed_strerror(msg, -err);
+ return btd_error_failed(msg, strerror(-err));
return NULL;
}
@@ -570,7 +564,7 @@ static DBusMessage *set_pairable(DBusConnection *conn, DBusMessage *msg,
err = set_mode(adapter, MODE_DISCOVERABLE, NULL);
if (err < 0 && msg)
- return failed_strerror(msg, -err);
+ return btd_error_failed(msg, strerror(-err));
store:
@@ -775,7 +769,7 @@ static void confirm_mode_cb(struct agent *agent, DBusError *derr, void *data)
err = set_mode(req->adapter, req->mode, NULL);
if (err < 0)
- reply = failed_strerror(req->msg, -err);
+ reply = btd_error_failed(req->msg, strerror(-err));
else
reply = dbus_message_new_method_return(req->msg);
@@ -906,7 +900,7 @@ static DBusMessage *set_name(DBusConnection *conn, DBusMessage *msg,
if (adapter->up) {
int err = adapter_ops->set_name(adapter->dev_id, name);
if (err < 0)
- return failed_strerror(msg, err);
+ return btd_error_failed(msg, strerror(-err));
adapter->name_stored = TRUE;
}
@@ -1185,7 +1179,7 @@ static DBusMessage *adapter_start_discovery(DBusConnection *conn,
err = start_discovery(adapter);
if (err < 0)
- return failed_strerror(msg, -err);
+ return btd_error_failed(msg, strerror(-err));
done:
req = create_session(adapter, conn, msg, 0,
@@ -1208,8 +1202,7 @@ static DBusMessage *adapter_stop_discovery(DBusConnection *conn,
req = find_session(adapter->disc_sessions, sender);
if (!req)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "Invalid discovery session");
+ return btd_error_failed(msg, "Invalid discovery session");
session_unref(req);
info("Stopping discovery");
@@ -1446,7 +1439,7 @@ static DBusMessage *request_session(DBusConnection *conn,
confirm_mode_cb, req, NULL);
if (err < 0) {
session_unref(req);
- return failed_strerror(msg, -err);
+ return btd_error_failed(msg, strerror(-err));
}
return NULL;
@@ -1461,8 +1454,7 @@ static DBusMessage *release_session(DBusConnection *conn,
req = find_session(adapter->mode_sessions, sender);
if (!req)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "No Mode to release");
+ return btd_error_failed(msg, "Invalid Session");
session_unref(req);
@@ -1622,7 +1614,7 @@ static DBusMessage *create_device(DBusConnection *conn,
err = device_browse(device, conn, msg, NULL, FALSE);
if (err < 0) {
adapter_remove_device(conn, adapter, device, TRUE);
- return failed_strerror(msg, -err);
+ return btd_error_failed(msg, strerror(-err));
}
return NULL;
@@ -1676,8 +1668,7 @@ static DBusMessage *create_paired_device(DBusConnection *conn,
device = adapter_get_device(conn, adapter, address);
if (!device)
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".Failed",
+ return btd_error_failed(msg,
"Unable to create a new device object");
return device_create_bonding(device, conn, msg, agent_path, cap);
@@ -1788,9 +1779,7 @@ static DBusMessage *register_agent(DBusConnection *conn, DBusMessage *msg,
agent = agent_create(adapter, name, path, cap,
(agent_remove_cb) agent_removed, adapter);
if (!agent)
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".Failed",
- "Failed to create a new agent");
+ return btd_error_failed(msg, "Failed to create a new agent");
adapter->agent = agent;
@@ -2334,7 +2323,7 @@ static void set_mode_complete(struct btd_adapter *adapter)
DBusMessage *reply;
if (err < 0)
- reply = failed_strerror(msg, -err);
+ reply = btd_error_failed(msg, strerror(-err));
else
reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
diff --git a/src/device.c b/src/device.c
index 0f4dc0b..cec2153 100644
--- a/src/device.c
+++ b/src/device.c
@@ -157,20 +157,6 @@ static uint16_t uuid_list[] = {
static GSList *device_drivers = NULL;
-static DBusHandlerResult error_failed(DBusConnection *conn,
- DBusMessage *msg, const char * desc)
-{
- return error_common_reply(conn, msg, ERROR_INTERFACE ".Failed", desc);
-}
-
-static DBusHandlerResult error_failed_errno(DBusConnection *conn,
- DBusMessage *msg, int err)
-{
- const char *desc = strerror(err);
-
- return error_failed(conn, msg, desc);
-}
-
static void browse_request_free(struct browse_req *req)
{
if (req->listener_id)
@@ -380,9 +366,7 @@ static DBusMessage *set_alias(DBusConnection *conn, DBusMessage *msg,
err = write_device_alias(srcaddr, dstaddr,
g_str_equal(alias, "") ? NULL : alias);
if (err < 0)
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".Failed",
- "%s", strerror(-err));
+ return btd_error_failed(msg, strerror(-err));
g_free(device->alias);
device->alias = g_str_equal(alias, "") ? NULL : g_strdup(alias);
@@ -412,9 +396,7 @@ static DBusMessage *set_trust(DBusConnection *conn, DBusMessage *msg,
err = write_trust(srcaddr, dstaddr, GLOBAL_TRUST, value);
if (err < 0)
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".Failed",
- "%s", strerror(-err));
+ return btd_error_failed(msg, strerror(-err));
device->trusted = value;
@@ -526,12 +508,9 @@ static DBusMessage *set_blocked(DBusConnection *conn, DBusMessage *msg,
case 0:
return dbus_message_new_method_return(msg);
case EINVAL:
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".NotSupported",
- "Kernel lacks blacklist support");
+ return btd_error_failed(msg, "Kernel lacks blacklist support");
default:
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", strerror(-err));
+ return btd_error_failed(msg, strerror(-err));
}
}
@@ -627,8 +606,7 @@ static DBusMessage *discover_services(DBusConnection *conn,
return NULL;
fail:
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "Discovery Failed");
+ return btd_error_failed(msg, strerror(-err));
}
static const char *browse_request_get_requestor(struct browse_req *req)
@@ -1473,7 +1451,9 @@ send_reply:
else if (dbus_message_is_method_call(req->msg, ADAPTER_INTERFACE,
"CreateDevice")) {
if (err < 0) {
- error_failed_errno(req->conn, req->msg, -err);
+ DBusMessage *reply;
+ reply = btd_error_failed(req->msg, strerror(-err));
+ g_dbus_send_message(req->conn, reply);
goto cleanup;
}
@@ -1544,7 +1524,9 @@ static void primary_cb(GSList *services, int err, gpointer user_data)
struct btd_device *device = req->device;
if (err) {
- error_failed_errno(req->conn, req->msg, -err);
+ DBusMessage *reply;
+ reply = btd_error_failed(req->msg, strerror(-err));
+ g_dbus_send_message(req->conn, reply);
goto done;
}
@@ -2000,9 +1982,7 @@ DBusMessage *device_create_bonding(struct btd_device *device,
BT_IO_OPT_INVALID);
if (io == NULL) {
DBusMessage *reply;
- reply = g_dbus_create_error(msg,
- ERROR_INTERFACE ".ConnectionAttemptFailed",
- "%s", err->message);
+ reply = btd_error_failed(msg, err->message);
error("bt_io_connect: %s", err->message);
g_error_free(err);
return reply;
--
1.7.3.2
^ permalink raw reply related
* [PATCH 09/10] serial: use btd_error_failed()
From: Gustavo F. Padovan @ 2010-12-13 21:33 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292275987-13799-9-git-send-email-padovan@profusion.mobi>
---
serial/port.c | 20 +++++++++-----------
serial/proxy.c | 8 ++------
2 files changed, 11 insertions(+), 17 deletions(-)
diff --git a/serial/port.c b/serial/port.c
index 0d1e600..1458f06 100644
--- a/serial/port.c
+++ b/serial/port.c
@@ -248,7 +248,7 @@ static void open_notify(int fd, int err, struct serial_port *port)
if (err) {
/* Max tries exceeded */
port_release(port);
- reply = failed(port->msg, strerror(err));
+ reply = btd_error_failed(port->msg, strerror(err));
} else {
port->fd = fd;
reply = g_dbus_create_reply(port->msg,
@@ -316,7 +316,7 @@ static void rfcomm_connect_cb(GIOChannel *chan, GError *conn_err,
if (conn_err) {
error("%s", conn_err->message);
- reply = failed(port->msg, conn_err->message);
+ reply = btd_error_failed(port->msg, conn_err->message);
goto fail;
}
@@ -335,7 +335,7 @@ static void rfcomm_connect_cb(GIOChannel *chan, GError *conn_err,
if (port->id < 0) {
int err = errno;
error("ioctl(RFCOMMCREATEDEV): %s (%d)", strerror(err), err);
- reply = failed(port->msg, strerror(err));
+ reply = btd_error_failed(port->msg, strerror(err));
g_io_channel_shutdown(chan, TRUE, NULL);
goto fail;
}
@@ -378,13 +378,13 @@ static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
if (err < 0) {
error("Unable to get service record: %s (%d)", strerror(-err),
-err);
- reply = failed(port->msg, strerror(-err));
+ reply = btd_error_failed(port->msg, strerror(-err));
goto failed;
}
if (!recs || !recs->data) {
error("No record found");
- reply = failed(port->msg, "No record found");
+ reply = btd_error_failed(port->msg, "No record found");
goto failed;
}
@@ -392,7 +392,7 @@ static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
if (sdp_get_access_protos(record, &protos) < 0) {
error("Unable to get access protos from port record");
- reply = failed(port->msg, "Invalid channel");
+ reply = btd_error_failed(port->msg, "Invalid channel");
goto failed;
}
@@ -409,7 +409,7 @@ static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
BT_IO_OPT_INVALID);
if (!port->io) {
error("%s", gerr->message);
- reply = failed(port->msg, gerr->message);
+ reply = btd_error_failed(port->msg, gerr->message);
g_error_free(gerr);
goto failed;
}
@@ -505,13 +505,11 @@ static DBusMessage *port_connect(DBusConnection *conn,
err = connect_port(port);
if (err < 0) {
- DBusMessage *reply;
-
error("%s", strerror(-err));
g_dbus_remove_watch(conn, port->listener_id);
port->listener_id = 0;
- reply = failed(msg, strerror(-err));
- return reply;
+
+ return btd_error_failed(msg, strerror(-err));
}
return NULL;
diff --git a/serial/proxy.c b/serial/proxy.c
index c779c4e..20aea7d 100644
--- a/serial/proxy.c
+++ b/serial/proxy.c
@@ -553,11 +553,8 @@ static DBusMessage *proxy_enable(DBusConnection *conn,
err = enable_proxy(prx);
if (err == -EALREADY)
return failed(msg, "Already enabled");
- else if (err == -ENOMEM)
- return failed(msg, "Unable to allocate new service record");
else if (err < 0)
- return g_dbus_create_error(msg, ERROR_INTERFACE "Failed",
- "Proxy enable failed (%s)", strerror(-err));
+ return btd_error_failed(msg, strerror(-err));
return dbus_message_new_method_return(msg);
}
@@ -1051,8 +1048,7 @@ static DBusMessage *create_proxy(DBusConnection *conn,
else if (err == -EALREADY)
return btd_error_already_exists(msg);
else if (err < 0)
- return g_dbus_create_error(msg, ERROR_INTERFACE "Failed",
- "Proxy creation failed (%s)", strerror(-err));
+ return btd_error_failed(msg, strerror(-err));
proxy->owner = g_strdup(dbus_message_get_sender(msg));
proxy->watch = g_dbus_add_disconnect_watch(conn, proxy->owner,
--
1.7.3.2
^ permalink raw reply related
* [PATCH 08/10] audio: use btd_error_failed()
From: Gustavo F. Padovan @ 2010-12-13 21:33 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292275987-13799-8-git-send-email-padovan@profusion.mobi>
---
audio/control.c | 6 ++----
audio/device.c | 14 +++++---------
audio/gateway.c | 11 +++++------
audio/headset.c | 18 +++++-------------
audio/sink.c | 9 +++------
audio/source.c | 9 +++------
audio/transport.c | 7 +------
7 files changed, 24 insertions(+), 50 deletions(-)
diff --git a/audio/control.c b/audio/control.c
index 98b6682..75c0b51 100644
--- a/audio/control.c
+++ b/audio/control.c
@@ -1021,8 +1021,7 @@ static DBusMessage *volume_up(DBusConnection *conn, DBusMessage *msg,
err = avctp_send_passthrough(control, VOL_UP_OP);
if (err < 0)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", strerror(-err));
+ return btd_error_failed(msg, strerror(-err));
return dbus_message_new_method_return(msg);
}
@@ -1047,8 +1046,7 @@ static DBusMessage *volume_down(DBusConnection *conn, DBusMessage *msg,
err = avctp_send_passthrough(control, VOL_DOWN_OP);
if (err < 0)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", strerror(-err));
+ return btd_error_failed(msg, strerror(-err));
return dbus_message_new_method_return(msg);
}
diff --git a/audio/device.c b/audio/device.c
index fe7aed4..e38e598 100644
--- a/audio/device.c
+++ b/audio/device.c
@@ -271,10 +271,9 @@ static void device_set_state(struct audio_device *dev, audio_state_t new_state)
if (new_state == AUDIO_STATE_CONNECTED)
reply = dbus_message_new_method_return(priv->conn_req);
else
- reply = g_dbus_create_error(priv->conn_req,
- ERROR_INTERFACE
- ".ConnectFailed",
- "Connecting failed");
+ reply = btd_error_failed(priv->conn_req,
+ "Connect Failed");
+
dbus_message_unref(priv->conn_req);
priv->conn_req = NULL;
g_dbus_send_message(dev->conn, reply);
@@ -532,8 +531,7 @@ static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
struct avdtp *session = avdtp_get(&dev->src, &dev->dst);
if (!session)
- return g_dbus_create_error(msg, ERROR_INTERFACE
- ".Failed",
+ return btd_error_failed(msg,
"Failed to get AVDTP session");
sink_setup_stream(dev->sink, session);
@@ -543,9 +541,7 @@ static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
/* The previous calls should cause a call to the state callback to
* indicate AUDIO_STATE_CONNECTING */
if (priv->state != AUDIO_STATE_CONNECTING)
- return g_dbus_create_error(msg, ERROR_INTERFACE
- ".ConnectFailed",
- "Headset connect failed");
+ return btd_error_failed(msg, "Connect Failed");
priv->conn_req = dbus_message_ref(msg);
diff --git a/audio/gateway.c b/audio/gateway.c
index 05b9ff7..4d38be7 100644
--- a/audio/gateway.c
+++ b/audio/gateway.c
@@ -247,8 +247,7 @@ static void rfcomm_connect_cb(GIOChannel *chan, GError *err,
if (ret)
reply = dbus_message_new_method_return(gw->msg);
else
- reply = g_dbus_create_error(gw->msg, ERROR_INTERFACE ".Failed",
- "Can not pass file descriptor");
+ reply = btd_error_failed(gw->msg, "Can't pass file descriptor");
g_dbus_send_message(dev->conn, reply);
@@ -365,15 +364,15 @@ static DBusMessage *ag_connect(DBusConnection *conn, DBusMessage *msg,
{
struct audio_device *au_dev = (struct audio_device *) data;
struct gateway *gw = au_dev->gateway;
+ int err;
if (!gw->agent)
return g_dbus_create_error(msg, ERROR_INTERFACE
".Failed", "Agent not assigned");
- if (get_records(au_dev) < 0)
- return g_dbus_create_error(msg, ERROR_INTERFACE
- ".ConnectAttemptFailed",
- "Connect Attempt Failed");
+ err = get_records(au_dev);
+ if (err < 0)
+ return btd_error_failed(msg, strerror(-err));
gw->msg = dbus_message_ref(msg);
diff --git a/audio/headset.c b/audio/headset.c
index 18fd866..34b2b89 100644
--- a/audio/headset.c
+++ b/audio/headset.c
@@ -1709,13 +1709,8 @@ static DBusMessage *hs_connect(DBusConnection *conn, DBusMessage *msg,
device->auto_connect = FALSE;
err = rfcomm_connect(device, NULL, NULL, NULL);
- if (err == -ECONNREFUSED)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAllowed",
- "Too many connected devices");
- else if (err < 0)
- return g_dbus_create_error(msg, ERROR_INTERFACE
- ".ConnectAttemptFailed",
- "Connect Attempt Failed");
+ if (err < 0)
+ return btd_error_failed(msg, strerror(-err));
hs->auto_dc = FALSE;
@@ -1747,8 +1742,7 @@ static DBusMessage *hs_ring(DBusConnection *conn, DBusMessage *msg,
err = headset_send(hs, "\r\nRING\r\n");
if (err < 0) {
dbus_message_unref(reply);
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", strerror(-err));
+ return btd_error_failed(msg, strerror(-err));
}
ring_timer_cb(NULL);
@@ -1815,8 +1809,7 @@ static DBusMessage *hs_play(DBusConnection *conn, DBusMessage *msg,
err = sco_connect(device, NULL, NULL, NULL);
if (err < 0)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", strerror(-err));
+ return btd_error_failed(msg, strerror(-err));
hs->pending->msg = dbus_message_ref(msg);
@@ -1900,8 +1893,7 @@ static DBusMessage *hs_set_gain(DBusConnection *conn,
err = headset_send(hs, "\r\n+VG%c=%u\r\n", type, gain);
if (err < 0) {
dbus_message_unref(reply);
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", strerror(-err));
+ return btd_error_failed(msg, strerror(-err));
}
}
diff --git a/audio/sink.c b/audio/sink.c
index 176a4ed..5746c55 100644
--- a/audio/sink.c
+++ b/audio/sink.c
@@ -435,8 +435,7 @@ static DBusMessage *sink_connect(DBusConnection *conn,
sink->session = avdtp_get(&dev->src, &dev->dst);
if (!sink->session)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "Unable to get a session");
+ return btd_error_failed(msg, "Unable to get a session");
if (sink->connect || sink->disconnect)
return btd_error_busy(msg);
@@ -445,8 +444,7 @@ static DBusMessage *sink_connect(DBusConnection *conn,
return btd_error_already_connected(msg);
if (!sink_setup_stream(sink, NULL))
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "Failed to create a stream");
+ return btd_error_failed(msg, "Failed to create a stream");
dev->auto_connect = FALSE;
@@ -485,8 +483,7 @@ static DBusMessage *sink_disconnect(DBusConnection *conn,
err = avdtp_close(sink->session, sink->stream, FALSE);
if (err < 0)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", strerror(-err));
+ return btd_error_failed(msg, strerror(-err));
pending = g_new0(struct pending_request, 1);
pending->conn = dbus_connection_ref(conn);
diff --git a/audio/source.c b/audio/source.c
index c106eaa..29ceb0f 100644
--- a/audio/source.c
+++ b/audio/source.c
@@ -386,8 +386,7 @@ static DBusMessage *source_connect(DBusConnection *conn,
source->session = avdtp_get(&dev->src, &dev->dst);
if (!source->session)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "Unable to get a session");
+ return btd_error_failed(msg, "Unable to get a session");
if (source->connect || source->disconnect)
return btd_error_busy(msg);
@@ -396,8 +395,7 @@ static DBusMessage *source_connect(DBusConnection *conn,
return btd_error_already_connected(msg);
if (!source_setup_stream(source, NULL))
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "Failed to create a stream");
+ return btd_error_failed(msg, "Failed to create a stream");
dev->auto_connect = FALSE;
@@ -436,8 +434,7 @@ static DBusMessage *source_disconnect(DBusConnection *conn,
err = avdtp_close(source->session, source->stream, FALSE);
if (err < 0)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", strerror(-err));
+ return btd_error_failed(msg, strerror(-err));
pending = g_new0(struct pending_request, 1);
pending->conn = dbus_connection_ref(conn);
diff --git a/audio/transport.c b/audio/transport.c
index e2ee400..bdec157 100644
--- a/audio/transport.c
+++ b/audio/transport.c
@@ -93,11 +93,6 @@ struct media_transport {
DBusMessageIter *value);
};
-static inline DBusMessage *error_failed(DBusMessage *msg, const char *desc)
-{
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "%s", desc);
-}
-
void media_transport_remove(struct media_transport *transport)
{
char *path;
@@ -572,7 +567,7 @@ static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
if (err < 0) {
if (err == -EINVAL)
return btd_error_invalid_args(msg);
- return error_failed(msg, strerror(-err));
+ return btd_error_failed(msg, strerror(-err));
}
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
--
1.7.3.2
^ permalink raw reply related
* [PATCH 07/10] input: use btd_error_failed()
From: Gustavo F. Padovan @ 2010-12-13 21:33 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292275987-13799-7-git-send-email-padovan@profusion.mobi>
---
input/device.c | 31 ++++++++-----------------------
1 files changed, 8 insertions(+), 23 deletions(-)
diff --git a/input/device.c b/input/device.c
index dee943b..0543fe6 100644
--- a/input/device.c
+++ b/input/device.c
@@ -315,14 +315,6 @@ failed:
return FALSE;
}
-static inline DBusMessage *connection_attempt_failed(DBusMessage *msg,
- const char *err)
-{
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".ConnectionAttemptFailed",
- "%s", err ? err : "Connection attempt failed");
-}
-
static void rfcomm_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
{
struct input_conn *iconn = user_data;
@@ -331,8 +323,7 @@ static void rfcomm_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
DBusMessage *reply;
if (err) {
- reply = connection_attempt_failed(iconn->pending_connect,
- err->message);
+ reply = btd_error_failed(iconn->pending_connect, err->message);
goto failed;
}
@@ -345,7 +336,7 @@ static void rfcomm_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
fake->uinput = uinput_create(idev->name);
if (fake->uinput < 0) {
g_io_channel_shutdown(chan, TRUE, NULL);
- reply = connection_attempt_failed(iconn->pending_connect,
+ reply = btd_error_failed(iconn->pending_connect,
strerror(errno));
goto failed;
}
@@ -834,7 +825,7 @@ static void interrupt_connect_cb(GIOChannel *chan, GError *conn_err,
failed:
error("%s", err_msg);
- reply = connection_attempt_failed(iconn->pending_connect, err_msg);
+ reply = btd_error_failed(iconn->pending_connect, err_msg);
g_dbus_send_message(idev->conn, reply);
if (iconn->ctrl_io)
@@ -859,8 +850,8 @@ static void control_connect_cb(GIOChannel *chan, GError *conn_err,
if (conn_err) {
error("%s", conn_err->message);
- reply = connection_attempt_failed(iconn->pending_connect,
- conn_err->message);
+ reply = btd_error_failed(iconn->pending_connect,
+ conn_err->message);
goto failed;
}
@@ -874,7 +865,7 @@ static void control_connect_cb(GIOChannel *chan, GError *conn_err,
BT_IO_OPT_INVALID);
if (!io) {
error("%s", err->message);
- reply = connection_attempt_failed(iconn->pending_connect,
+ reply = btd_error_failed(iconn->pending_connect,
err->message);
g_error_free(err);
g_io_channel_shutdown(chan, TRUE, NULL);
@@ -960,17 +951,11 @@ static DBusMessage *input_device_connect(DBusConnection *conn,
error("%s", err->message);
dbus_message_unref(iconn->pending_connect);
iconn->pending_connect = NULL;
- reply = connection_attempt_failed(msg, err->message);
+ reply = btd_error_failed(msg, err->message);
g_error_free(err);
return reply;
}
-static DBusMessage *create_errno_message(DBusMessage *msg, int err)
-{
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", strerror(err));
-}
-
static DBusMessage *input_device_disconnect(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -979,7 +964,7 @@ static DBusMessage *input_device_disconnect(DBusConnection *conn,
err = disconnect(idev, 0);
if (err < 0)
- return create_errno_message(msg, -err);
+ return btd_error_failed(msg, strerror(-err));
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
--
1.7.3.2
^ permalink raw reply related
* [PATCH 06/10] network: use btd_error_failed()
From: Gustavo F. Padovan @ 2010-12-13 21:33 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292275987-13799-6-git-send-email-padovan@profusion.mobi>
---
network/connection.c | 30 ++----------------------------
network/server.c | 13 +++----------
2 files changed, 5 insertions(+), 38 deletions(-)
diff --git a/network/connection.c b/network/connection.c
index 89c38d8..09a4f3c 100644
--- a/network/connection.c
+++ b/network/connection.c
@@ -111,32 +111,6 @@ static struct network_conn *find_connection(GSList *list, uint16_t id)
return NULL;
}
-static inline DBusMessage *not_supported(DBusMessage *msg)
-{
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "Not supported");
-}
-
-static inline DBusMessage *already_connected(DBusMessage *msg)
-{
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "Device already connected");
-}
-
-static inline DBusMessage *not_permited(DBusMessage *msg)
-{
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "Operation not permited");
-}
-
-static inline DBusMessage *connection_attempt_failed(DBusMessage *msg,
- const char *err)
-{
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".ConnectionAttemptFailed",
- "%s", err ? err : "Connection attempt failed");
-}
-
static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
gpointer data)
{
@@ -182,7 +156,7 @@ static void cancel_connection(struct network_conn *nc, const char *err_msg)
}
if (nc->msg && err_msg) {
- reply = connection_attempt_failed(nc->msg, err_msg);
+ reply = btd_error_failed(nc->msg, err_msg);
g_dbus_send_message(connection, reply);
}
@@ -409,7 +383,7 @@ static DBusMessage *connection_connect(DBusConnection *conn,
if (!nc->io) {
DBusMessage *reply;
error("%s", err->message);
- reply = connection_attempt_failed(msg, err->message);
+ reply = btd_error_failed(msg, err->message);
g_error_free(err);
return reply;
}
diff --git a/network/server.c b/network/server.c
index 60e1a81..7c63c3e 100644
--- a/network/server.c
+++ b/network/server.c
@@ -566,13 +566,6 @@ static uint32_t register_server_record(struct network_server *ns)
return record->handle;
}
-
-static inline DBusMessage *failed(DBusMessage *msg, const char *description)
-{
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", description);
-}
-
static void server_disconnect(DBusConnection *conn, void *user_data)
{
struct network_server *ns = user_data;
@@ -600,7 +593,7 @@ static DBusMessage *register_server(DBusConnection *conn,
return NULL;
if (g_strcmp0(uuid, "nap"))
- return failed(msg, "Invalid UUID");
+ return btd_error_failed(msg, "Invalid UUID");
if (ns->record_id)
return btd_error_already_exists(msg);
@@ -611,7 +604,7 @@ static DBusMessage *register_server(DBusConnection *conn,
ns->record_id = register_server_record(ns);
if (!ns->record_id)
- return failed(msg, "SDP record registration failed");
+ return btd_error_failed(msg, "SDP record registration failed");
g_free(ns->bridge);
ns->bridge = g_strdup(bridge);
@@ -635,7 +628,7 @@ static DBusMessage *unregister_server(DBusConnection *conn,
return NULL;
if (g_strcmp0(uuid, "nap"))
- return failed(msg, "Invalid UUID");
+ return btd_error_failed(msg, "Invalid UUID");
reply = dbus_message_new_method_return(msg);
if (!reply)
--
1.7.3.2
^ permalink raw reply related
* [PATCH 05/10] attrib: use btd_error_failed()
From: Gustavo F. Padovan @ 2010-12-13 21:33 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292275987-13799-5-git-send-email-padovan@profusion.mobi>
---
attrib/client.c | 10 ++--------
1 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/attrib/client.c b/attrib/client.c
index 0805492..8e96af4 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -457,11 +457,8 @@ static DBusMessage *register_watcher(DBusConnection *conn,
return btd_error_invalid_args(msg);
if (l2cap_connect(prim->gatt, &gerr, TRUE) < 0) {
- DBusMessage *reply;
- reply = g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", gerr->message);
+ DBusMessage *reply = btd_error_failed(msg, gerr->message);
g_error_free(gerr);
-
return reply;
}
@@ -533,11 +530,8 @@ static DBusMessage *set_value(DBusConnection *conn, DBusMessage *msg,
dbus_message_iter_get_fixed_array(&sub, &value, &len);
if (l2cap_connect(gatt, &gerr, FALSE) < 0) {
- DBusMessage *reply;
- reply = g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", gerr->message);
+ DBusMessage *reply = btd_error_failed(msg, gerr->message);
g_error_free(gerr);
-
return reply;
}
--
1.7.3.2
^ permalink raw reply related
* [PATCH 04/10] plugins: use btd_error_failed()
From: Gustavo F. Padovan @ 2010-12-13 21:33 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292275987-13799-4-git-send-email-padovan@profusion.mobi>
---
plugins/service.c | 22 ++++------------------
1 files changed, 4 insertions(+), 18 deletions(-)
diff --git a/plugins/service.c b/plugins/service.c
index a442d53..f44aa92 100644
--- a/plugins/service.c
+++ b/plugins/service.c
@@ -337,17 +337,6 @@ static void exit_callback(DBusConnection *conn, void *user_data)
g_free(user_record);
}
-static inline DBusMessage *failed(DBusMessage *msg)
-{
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "Failed");
-}
-
-static inline DBusMessage *failed_strerror(DBusMessage *msg, int err)
-{
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", strerror(err));
-}
-
static int add_xml_record(DBusConnection *conn, const char *sender,
struct service_adapter *serv_adapter,
const char *record, dbus_uint32_t *handle)
@@ -412,9 +401,7 @@ static DBusMessage *update_record(DBusConnection *conn, DBusMessage *msg,
if (err < 0) {
sdp_record_free(sdp_record);
error("Failed to update the service record");
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".Failed",
- "%s", strerror(EIO));
+ return btd_error_failed(msg, strerror(-err));
}
return dbus_message_new_method_return(msg);
@@ -449,9 +436,8 @@ static DBusMessage *update_xml_record(DBusConnection *conn,
if (!sdp_record) {
error("Parsing of XML service record failed");
sdp_record_free(sdp_record);
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".Failed",
- "%s", strerror(EIO));
+ return btd_error_failed(msg,
+ "Parsing of XML service record failed");
}
return update_record(conn, msg, serv_adapter, handle, sdp_record);
@@ -494,7 +480,7 @@ static DBusMessage *add_service_record(DBusConnection *conn,
sender = dbus_message_get_sender(msg);
err = add_xml_record(conn, sender, serv_adapter, record, &handle);
if (err < 0)
- return failed_strerror(msg, err);
+ return btd_error_failed(msg, strerror(-err));
reply = dbus_message_new_method_return(msg);
if (!reply)
--
1.7.3.2
^ permalink raw reply related
* [PATCH 03/10] Add btd_error_failed()
From: Gustavo F. Padovan @ 2010-12-13 21:33 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292275987-13799-3-git-send-email-padovan@profusion.mobi>
This is a special error type. It has a more general meaning and allows you
to add a string to the error.
---
src/error.c | 6 ++++++
src/error.h | 1 +
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/src/error.c b/src/error.c
index 013de96..3a78628 100644
--- a/src/error.c
+++ b/src/error.c
@@ -114,3 +114,9 @@ DBusMessage *btd_error_no_such_adapter(DBusMessage *msg)
return g_dbus_create_error(msg, ERROR_INTERFACE ".NoSuchAdapter",
"No such adapter");
}
+
+DBusMessage *btd_error_failed(DBusMessage *msg, const char *str)
+{
+ return g_dbus_create_error(msg, ERROR_INTERFACE
+ ".Failed", "%s", str);
+}
diff --git a/src/error.h b/src/error.h
index a4e32fe..faaef0a 100644
--- a/src/error.h
+++ b/src/error.h
@@ -41,3 +41,4 @@ DBusMessage *btd_error_in_progress(DBusMessage *msg);
DBusMessage *btd_error_does_not_exist(DBusMessage *msg);
DBusMessage *btd_error_not_authorized(DBusMessage *msg);
DBusMessage *btd_error_no_such_adapter(DBusMessage *msg);
+DBusMessage *btd_error_failed(DBusMessage *msg, const char *str);
--
1.7.3.2
^ permalink raw reply related
* [PATCH 02/10] src: use btd_error_invalid_args()
From: Gustavo F. Padovan @ 2010-12-13 21:32 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292275987-13799-2-git-send-email-padovan@profusion.mobi>
---
src/device.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/device.c b/src/device.c
index 7ceac8b..0f4dc0b 100644
--- a/src/device.c
+++ b/src/device.c
@@ -605,7 +605,7 @@ static DBusMessage *discover_services(DBusConnection *conn,
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
DBUS_TYPE_INVALID) == FALSE)
- goto fail;
+ return btd_error_invalid_args(msg);
if (strlen(pattern) == 0) {
err = device_browse(device, conn, msg, NULL, FALSE);
--
1.7.3.2
^ permalink raw reply related
* [PATCH 01/10] Add btd_error_no_such_adapter()
From: Gustavo F. Padovan @ 2010-12-13 21:32 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292275987-13799-1-git-send-email-padovan@profusion.mobi>
---
src/device.c | 6 ------
src/error.c | 6 ++++++
src/error.h | 1 +
src/manager.c | 13 +++----------
4 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/src/device.c b/src/device.c
index 91b9d23..7ceac8b 100644
--- a/src/device.c
+++ b/src/device.c
@@ -171,12 +171,6 @@ static DBusHandlerResult error_failed_errno(DBusConnection *conn,
return error_failed(conn, msg, desc);
}
-static inline DBusMessage *no_such_adapter(DBusMessage *msg)
-{
- return g_dbus_create_error(msg, ERROR_INTERFACE ".NoSuchAdapter",
- "No such adapter");
-}
-
static void browse_request_free(struct browse_req *req)
{
if (req->listener_id)
diff --git a/src/error.c b/src/error.c
index e1f0598..013de96 100644
--- a/src/error.c
+++ b/src/error.c
@@ -108,3 +108,9 @@ DBusMessage *btd_error_not_authorized(DBusMessage *msg)
return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAuthorized",
"Operation Not Authorized");
}
+
+DBusMessage *btd_error_no_such_adapter(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".NoSuchAdapter",
+ "No such adapter");
+}
diff --git a/src/error.h b/src/error.h
index 9d80fa0..a4e32fe 100644
--- a/src/error.h
+++ b/src/error.h
@@ -40,3 +40,4 @@ DBusMessage *btd_error_not_available(DBusMessage *msg);
DBusMessage *btd_error_in_progress(DBusMessage *msg);
DBusMessage *btd_error_does_not_exist(DBusMessage *msg);
DBusMessage *btd_error_not_authorized(DBusMessage *msg);
+DBusMessage *btd_error_no_such_adapter(DBusMessage *msg);
diff --git a/src/manager.c b/src/manager.c
index ccaa1a2..c8ec7e5 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -59,13 +59,6 @@ const char *manager_get_base_path(void)
return base_path;
}
-static inline DBusMessage *no_such_adapter(DBusMessage *msg)
-{
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".NoSuchAdapter",
- "No such adapter");
-}
-
static DBusMessage *default_adapter(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -75,7 +68,7 @@ static DBusMessage *default_adapter(DBusConnection *conn,
adapter = manager_find_adapter_by_id(default_adapter_id);
if (!adapter)
- return no_such_adapter(msg);
+ return btd_error_no_such_adapter(msg);
reply = dbus_message_new_method_return(msg);
if (!reply)
@@ -108,7 +101,7 @@ static DBusMessage *find_adapter(DBusConnection *conn,
path = adapter_any_get_path();
if (path != NULL)
goto done;
- return no_such_adapter(msg);
+ return btd_error_no_such_adapter(msg);
} else if (!strncmp(pattern, "hci", 3) && strlen(pattern) >= 4) {
dev_id = atoi(pattern + 3);
adapter = manager_find_adapter_by_id(dev_id);
@@ -116,7 +109,7 @@ static DBusMessage *find_adapter(DBusConnection *conn,
adapter = manager_find_adapter_by_address(pattern);
if (!adapter)
- return no_such_adapter(msg);
+ return btd_error_no_such_adapter(msg);
path = adapter_get_path(adapter);
--
1.7.3.2
^ permalink raw reply related
* [PATCH 00/10] More btd_error_* patches
From: Gustavo F. Padovan @ 2010-12-13 21:32 UTC (permalink / raw)
To: linux-bluetooth
Hi,
This patch set adds a new error function btd_error_failed(), which has a str
parameter to enable a more accurate error report in the case the usual
btd_error_* does not fit.
After this patch set there will 10 occurrences of g_dbus_create_error() inside
bluez code (not counting health/ here)
Please review!
Gustavo F. Padovan (10):
Add btd_error_no_such_adapter()
src: use btd_error_invalid_args()
Add btd_error_failed()
plugins: use btd_error_failed()
attrib: use btd_error_failed()
network: use btd_error_failed()
input: use btd_error_failed()
audio: use btd_error_failed()
serial: use btd_error_failed()
src: use btd_error_failed()
attrib/client.c | 10 +-------
audio/control.c | 6 +---
audio/device.c | 14 ++++--------
audio/gateway.c | 11 ++++-----
audio/headset.c | 18 ++++------------
audio/sink.c | 9 ++-----
audio/source.c | 9 ++-----
audio/transport.c | 7 +-----
input/device.c | 31 +++++++----------------------
network/connection.c | 30 +--------------------------
network/server.c | 13 ++---------
plugins/service.c | 22 +++-----------------
serial/port.c | 20 ++++++++----------
serial/proxy.c | 8 +-----
src/adapter.c | 37 ++++++++++++-----------------------
src/device.c | 52 ++++++++++++-------------------------------------
src/error.c | 12 +++++++++++
src/error.h | 2 +
src/manager.c | 13 ++---------
19 files changed, 97 insertions(+), 227 deletions(-)
--
1.7.3.2
^ permalink raw reply
* Re: [PATCH 1/1] Support for reading long Characteristic Values.
From: Vinicius Costa Gomes @ 2010-12-13 20:33 UTC (permalink / raw)
To: Brian Gix; +Cc: linux-bluetooth, padovan, rshaffer
In-Reply-To: <4D067A6C.6080404@codeaurora.org>
On 11:56 Mon 13 Dec, Brian Gix wrote:
> Hi Vinicius,
>
> On 12/13/2010 10:39 AM, Vinicius Costa Gomes wrote:
> > On 09:24 Mon 13 Dec, Brian Gix wrote:
> >> Modify existing gatt_read_char() function support the reading of
> >> attributes (specifically Characteristic Values) that are longer than
> >> the MTU would otherwise allow. When a result to an ATT_OP_READ_REQ
> >> is received, it will be passed to the requester as always if the total
> >> result was shorter than the Default MTU (23). Any results equal to or
> >> longer will cause a series of READ_BLOB requests to be made, with the
> >> additional results built up until the end of the Attribute is detected.
> >> The full result will then be passed to the original requester.
> >>
> >> The end of the Attribute is detected by either a successful result to
> >> the READ_BLOB request that is shorter than the Default MTU, or by an
> >> error result that indicates that a read is being attempted beyond the
> >> length of the attribute, or that the Attribute wasn't "Long".
> >>
> >> This patch is dependant on the earlier patch:
> >> 0001-Implempent-READ_BLOB-encoding-for-ATT.patch
> >>
> >> The packet composed conforms to the Bluetooth Core v4.0 specification.
> >>
> >> Brian Gix
> >> bgix@codeaurora.org
> >> Employee of Qualcomm Innovation Center, Inc.
> >> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
>
> I will omit the sig in the annotation in the future.
>
> Also, I will examine the subsequent submissions for non-TAB ws. I need
> to work on my gvim settings a bit, I think.
>
> >>
> >> ---
> >> attrib/gatt.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> >> 1 files changed, 112 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/attrib/gatt.c b/attrib/gatt.c
> >> index bca8b49..d888f1d 100644
> >> --- a/attrib/gatt.c
> >> +++ b/attrib/gatt.c
> >> @@ -97,15 +97,125 @@ guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,
> >> pdu, plen, func, user_data, NULL);
> >> }
> >>
> >> +struct read_long_data {
> >> + GAttrib *attrib;
> >> + GAttribResultFunc func;
> >> + gpointer user_data;
> >> + guint8 *result_data;
> >> + guint16 result_len;
> >
> > I would call result_data "buffer" (or something like it) and result_len "size"
> > (or total). What do you think?
>
> Will rename to buffer and size. I often avoid "size" to avoid keyword
> collisions, but I don't believe it applies here.
>
> >
> >> + guint16 handle;
> >> +};
> >> +
> >> +static void read_blob_helper(guint8 status, const guint8 *res_pdu,
> >> + guint16 res_len, gpointer user_data)
> >> +{
> >> + struct read_long_data *long_read = user_data;
> >> + uint8_t pdu[ATT_DEFAULT_MTU];
> >> + guint8 *tmp;
> >> + guint16 plen;
> >> + guint ret_val;
> >> +
> >> + if (status == ATT_ECODE_ATTR_NOT_LONG ||
> >> + status == ATT_ECODE_INVALID_OFFSET) {
> >> + status = 0;
> >> + goto done;
> >> + }
> >> +
> >> + if (status != 0 || res_len == 1)
> >> + goto done;
> >> +
> >> + tmp = g_try_realloc(long_read->result_data,
> >> + long_read->result_len + res_len - 1);
> >> +
> >> + if (tmp == NULL) {
> >> + status = ATT_ECODE_INSUFF_RESOURCES;
> >> + goto done;
> >> + }
> >> +
> >> + memcpy(&tmp[long_read->result_len],&res_pdu[1], res_len-1);
> >
> > It should be "res - 1".
> >
> >> + long_read->result_data = tmp;
> >> + long_read->result_len += res_len-1;
> >
> > Same here.
> >
> >> +
> >> + if (res_len< ATT_DEFAULT_MTU)
> >> + goto done;
> >> +
> >> + plen = enc_read_blob_req(long_read->handle, long_read->result_len-1,
> >
> > And here.
>
> done, done, done.
>
> >
> >> + pdu, sizeof(pdu));
> >> + ret_val = g_attrib_send(long_read->attrib, ATT_OP_READ_BLOB_REQ, pdu,
> >> + plen, read_blob_helper, long_read, NULL);
> >> +
> >> + if (ret_val != 0)
> >> + return;
> >> +
> >> + status = ATT_ECODE_INSUFF_RESOURCES;
> >> +
> >> +done:
> >> + long_read->func(status, long_read->result_data, long_read->result_len,
> >> + long_read->user_data);
> >> + g_free(long_read->result_data);
> >> + g_free(long_read);
> >> +}
> >> +
> >> +static void read_char_helper(guint8 status, const guint8 *res_pdu,
> >> + guint16 res_len, gpointer user_data)
> >> +{
> >> + struct read_long_data *long_read = user_data;
> >> + uint8_t pdu[ATT_DEFAULT_MTU];
> >> + guint16 plen;
> >> + guint ret_val;
> >> +
> >> + if (status != 0 || res_len< ATT_DEFAULT_MTU)
> >> + goto done;
> >> +
> >> + long_read->result_data = g_malloc(res_len);
> >> +
> >> + if (long_read->result_data == NULL)
> >> + goto done;
> >> +
> >> + memcpy(long_read->result_data, res_pdu, res_len);
> >> + long_read->result_len = res_len;
> >> +
> >> + plen = enc_read_blob_req(long_read->handle, res_len-1, pdu,
> >> + sizeof(pdu));
> >> + ret_val = g_attrib_send(long_read->attrib, ATT_OP_READ_BLOB_REQ,
> >> + pdu, plen, read_blob_helper, long_read, NULL);
> >
> > g_attrib_send() returns an command id (something that could be used to cancel
> > the command later, if needed), so I think it would make more sense to call
> > ret_val "id" or just "ret". And thinking about it, I guess that the "res_"
> > prefix doesn't add much meaning to "res_pdu" and "res_len". Do you agree?
>
> renamed res_pdu to "rpdu", to avoid name collision with outbound local
> pdu variable.
>
> renamed res_len to "rlen" to keep the two together, and distinct from
> plen, which is also used for the outbound pdu.
>
> renamed ret_val to "ret". In two of the functions, it has lost the
> ability to be used to cancel the GATT procedure. It can cancel the
> original ATT_OP_READ_REQ opcodes, but not the subsequent
> ATT_OP_READ_BLOB_REQ opcodes.
>
> >
> >> +
> >> + if (ret_val != 0)
> >> + return;
> >> +
> >> + status = ATT_ECODE_INSUFF_RESOURCES;
> >> +
> >> +done:
> >> + long_read->func(status, res_pdu, res_len, long_read->user_data);
> >
> > If g_attrib_send() fails, load_read->result_data may be leaking here.
>
> Is there no guarantee that the GAttribResultFunc parameter will be
> invoked if there is a non-Zero return value from g_attrib_send?
>
> If there is paths that could result in a non-response (abnormal link
> termination?) then you are correct, and I will need to rethink clean-up.
The case I was referring was when g_attrib_send() cannot allocate memory for
the command.
>
> If I am correctly reading the code, I can pass a function to the
> GDestroyNotify parameter of g_attrib_send, which will alert me to the
> destruction of the command, at which point I could do clean-up. Is that
> path foolproof? This would also entail removing all g_free clean-ups
> from the helper functions, because the destroy function is always
> called, including after invoking the GAttribResultFunc function.
>
Yeah, this path should be foolproof. The destroy function should be called
even for abnormal cases, the ResultFunc is called just when the command
finishes (with a response or an error).
> Also:
> If we intend to use the ID of the (original) command to cancel the GATT
> procedure, I propose the following:
>
> Compound GATT procedure such as the Read Long procedure that I am
> implementing, should save the original ID returned by g_attrib_send in
> the nested user_data structure such as I have done. When subsequent ATT
> commands are sent as part of the same GATT procedure, the new command
> shall be assigned the same ID as the original. This could be done with
> a function in gattrib.c with the prototype:
>
> g_attrib_set_id(GAttrib *attrib, guint old_id, guint new_id);
>
> This would allow the upper layer to cancel the entire GATT procedure,
> even if it is partially completed.
>
> This same methodology could then be applied to long writes, and other
> compound GATT procedures.
>
> What do you think?
Sounds good, I just don't know about messing with the commands id's,
maybe having some thing like command groups.
For example, adding these funtions:
guint g_attrib_send_full(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
guint16 len, guint group, GAttribResultFunc func,
gpointer user_data, GDestroyNotify notify);
gboolean g_attrib_cancel_group(GAttrib *attrib, guint group);
How do this look?
>
> >
> >> + g_free(long_read);
> >> +}
> >> +
> >> guint gatt_read_char(GAttrib *attrib, uint16_t handle, GAttribResultFunc func,
> >> gpointer user_data)
> >> {
> >> uint8_t pdu[ATT_DEFAULT_MTU];
> >> guint16 plen;
> >> + guint ret_val;
> >> + struct read_long_data *long_read;
> >> +
> >> + long_read = g_try_new0(struct read_long_data, 1);
> >> +
> >> + if (long_read == NULL)
> >> + return 0;
> >> +
> >> + long_read->attrib = attrib;
> >> + long_read->func = func;
> >> + long_read->user_data = user_data;
> >> + long_read->handle = handle;
> >>
> >> plen = enc_read_req(handle, pdu, sizeof(pdu));
> >> - return g_attrib_send(attrib, ATT_OP_READ_REQ, pdu, plen, func,
> >> - user_data, NULL);
> >> + ret_val = g_attrib_send(attrib, ATT_OP_READ_REQ, pdu, plen,
> >> + read_char_helper, long_read, NULL);
> >> +
> >> + if (ret_val == 0)
> >> + g_free(long_read);
> >> +
> >> + return ret_val;
> >> }
> >>
> >> guint gatt_write_char(GAttrib *attrib, uint16_t handle, uint8_t *value,
> >> --
> >> 1.7.1
> >>
> >> --
> >> 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
> >
> > Cheers,
>
> Thanks,
>
> --
> Brian Gix
> bgix@codeaurora.org
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Cheers,
--
Vinicius
^ permalink raw reply
* Re: [PATCH 1/1] Support for reading long Characteristic Values.
From: Brian Gix @ 2010-12-13 19:56 UTC (permalink / raw)
To: Vinicius Costa Gomes; +Cc: linux-bluetooth, padovan, rshaffer
In-Reply-To: <20101213183951.GB7549@eris>
Hi Vinicius,
On 12/13/2010 10:39 AM, Vinicius Costa Gomes wrote:
> On 09:24 Mon 13 Dec, Brian Gix wrote:
>> Modify existing gatt_read_char() function support the reading of
>> attributes (specifically Characteristic Values) that are longer than
>> the MTU would otherwise allow. When a result to an ATT_OP_READ_REQ
>> is received, it will be passed to the requester as always if the total
>> result was shorter than the Default MTU (23). Any results equal to or
>> longer will cause a series of READ_BLOB requests to be made, with the
>> additional results built up until the end of the Attribute is detected.
>> The full result will then be passed to the original requester.
>>
>> The end of the Attribute is detected by either a successful result to
>> the READ_BLOB request that is shorter than the Default MTU, or by an
>> error result that indicates that a read is being attempted beyond the
>> length of the attribute, or that the Attribute wasn't "Long".
>>
>> This patch is dependant on the earlier patch:
>> 0001-Implempent-READ_BLOB-encoding-for-ATT.patch
>>
>> The packet composed conforms to the Bluetooth Core v4.0 specification.
>>
>> Brian Gix
>> bgix@codeaurora.org
>> Employee of Qualcomm Innovation Center, Inc.
>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
I will omit the sig in the annotation in the future.
Also, I will examine the subsequent submissions for non-TAB ws. I need
to work on my gvim settings a bit, I think.
>>
>> ---
>> attrib/gatt.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>> 1 files changed, 112 insertions(+), 2 deletions(-)
>>
>> diff --git a/attrib/gatt.c b/attrib/gatt.c
>> index bca8b49..d888f1d 100644
>> --- a/attrib/gatt.c
>> +++ b/attrib/gatt.c
>> @@ -97,15 +97,125 @@ guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,
>> pdu, plen, func, user_data, NULL);
>> }
>>
>> +struct read_long_data {
>> + GAttrib *attrib;
>> + GAttribResultFunc func;
>> + gpointer user_data;
>> + guint8 *result_data;
>> + guint16 result_len;
>
> I would call result_data "buffer" (or something like it) and result_len "size"
> (or total). What do you think?
Will rename to buffer and size. I often avoid "size" to avoid keyword
collisions, but I don't believe it applies here.
>
>> + guint16 handle;
>> +};
>> +
>> +static void read_blob_helper(guint8 status, const guint8 *res_pdu,
>> + guint16 res_len, gpointer user_data)
>> +{
>> + struct read_long_data *long_read = user_data;
>> + uint8_t pdu[ATT_DEFAULT_MTU];
>> + guint8 *tmp;
>> + guint16 plen;
>> + guint ret_val;
>> +
>> + if (status == ATT_ECODE_ATTR_NOT_LONG ||
>> + status == ATT_ECODE_INVALID_OFFSET) {
>> + status = 0;
>> + goto done;
>> + }
>> +
>> + if (status != 0 || res_len == 1)
>> + goto done;
>> +
>> + tmp = g_try_realloc(long_read->result_data,
>> + long_read->result_len + res_len - 1);
>> +
>> + if (tmp == NULL) {
>> + status = ATT_ECODE_INSUFF_RESOURCES;
>> + goto done;
>> + }
>> +
>> + memcpy(&tmp[long_read->result_len],&res_pdu[1], res_len-1);
>
> It should be "res - 1".
>
>> + long_read->result_data = tmp;
>> + long_read->result_len += res_len-1;
>
> Same here.
>
>> +
>> + if (res_len< ATT_DEFAULT_MTU)
>> + goto done;
>> +
>> + plen = enc_read_blob_req(long_read->handle, long_read->result_len-1,
>
> And here.
done, done, done.
>
>> + pdu, sizeof(pdu));
>> + ret_val = g_attrib_send(long_read->attrib, ATT_OP_READ_BLOB_REQ, pdu,
>> + plen, read_blob_helper, long_read, NULL);
>> +
>> + if (ret_val != 0)
>> + return;
>> +
>> + status = ATT_ECODE_INSUFF_RESOURCES;
>> +
>> +done:
>> + long_read->func(status, long_read->result_data, long_read->result_len,
>> + long_read->user_data);
>> + g_free(long_read->result_data);
>> + g_free(long_read);
>> +}
>> +
>> +static void read_char_helper(guint8 status, const guint8 *res_pdu,
>> + guint16 res_len, gpointer user_data)
>> +{
>> + struct read_long_data *long_read = user_data;
>> + uint8_t pdu[ATT_DEFAULT_MTU];
>> + guint16 plen;
>> + guint ret_val;
>> +
>> + if (status != 0 || res_len< ATT_DEFAULT_MTU)
>> + goto done;
>> +
>> + long_read->result_data = g_malloc(res_len);
>> +
>> + if (long_read->result_data == NULL)
>> + goto done;
>> +
>> + memcpy(long_read->result_data, res_pdu, res_len);
>> + long_read->result_len = res_len;
>> +
>> + plen = enc_read_blob_req(long_read->handle, res_len-1, pdu,
>> + sizeof(pdu));
>> + ret_val = g_attrib_send(long_read->attrib, ATT_OP_READ_BLOB_REQ,
>> + pdu, plen, read_blob_helper, long_read, NULL);
>
> g_attrib_send() returns an command id (something that could be used to cancel
> the command later, if needed), so I think it would make more sense to call
> ret_val "id" or just "ret". And thinking about it, I guess that the "res_"
> prefix doesn't add much meaning to "res_pdu" and "res_len". Do you agree?
renamed res_pdu to "rpdu", to avoid name collision with outbound local
pdu variable.
renamed res_len to "rlen" to keep the two together, and distinct from
plen, which is also used for the outbound pdu.
renamed ret_val to "ret". In two of the functions, it has lost the
ability to be used to cancel the GATT procedure. It can cancel the
original ATT_OP_READ_REQ opcodes, but not the subsequent
ATT_OP_READ_BLOB_REQ opcodes.
>
>> +
>> + if (ret_val != 0)
>> + return;
>> +
>> + status = ATT_ECODE_INSUFF_RESOURCES;
>> +
>> +done:
>> + long_read->func(status, res_pdu, res_len, long_read->user_data);
>
> If g_attrib_send() fails, load_read->result_data may be leaking here.
Is there no guarantee that the GAttribResultFunc parameter will be
invoked if there is a non-Zero return value from g_attrib_send?
If there is paths that could result in a non-response (abnormal link
termination?) then you are correct, and I will need to rethink clean-up.
If I am correctly reading the code, I can pass a function to the
GDestroyNotify parameter of g_attrib_send, which will alert me to the
destruction of the command, at which point I could do clean-up. Is that
path foolproof? This would also entail removing all g_free clean-ups
from the helper functions, because the destroy function is always
called, including after invoking the GAttribResultFunc function.
Also:
If we intend to use the ID of the (original) command to cancel the GATT
procedure, I propose the following:
Compound GATT procedure such as the Read Long procedure that I am
implementing, should save the original ID returned by g_attrib_send in
the nested user_data structure such as I have done. When subsequent ATT
commands are sent as part of the same GATT procedure, the new command
shall be assigned the same ID as the original. This could be done with
a function in gattrib.c with the prototype:
g_attrib_set_id(GAttrib *attrib, guint old_id, guint new_id);
This would allow the upper layer to cancel the entire GATT procedure,
even if it is partially completed.
This same methodology could then be applied to long writes, and other
compound GATT procedures.
What do you think?
>
>> + g_free(long_read);
>> +}
>> +
>> guint gatt_read_char(GAttrib *attrib, uint16_t handle, GAttribResultFunc func,
>> gpointer user_data)
>> {
>> uint8_t pdu[ATT_DEFAULT_MTU];
>> guint16 plen;
>> + guint ret_val;
>> + struct read_long_data *long_read;
>> +
>> + long_read = g_try_new0(struct read_long_data, 1);
>> +
>> + if (long_read == NULL)
>> + return 0;
>> +
>> + long_read->attrib = attrib;
>> + long_read->func = func;
>> + long_read->user_data = user_data;
>> + long_read->handle = handle;
>>
>> plen = enc_read_req(handle, pdu, sizeof(pdu));
>> - return g_attrib_send(attrib, ATT_OP_READ_REQ, pdu, plen, func,
>> - user_data, NULL);
>> + ret_val = g_attrib_send(attrib, ATT_OP_READ_REQ, pdu, plen,
>> + read_char_helper, long_read, NULL);
>> +
>> + if (ret_val == 0)
>> + g_free(long_read);
>> +
>> + return ret_val;
>> }
>>
>> guint gatt_write_char(GAttrib *attrib, uint16_t handle, uint8_t *value,
>> --
>> 1.7.1
>>
>> --
>> 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
>
> Cheers,
Thanks,
--
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply
* [PATCH 5/5] Bluetooth: Add management events for controller addition & removal
From: johan.hedberg @ 2010-12-13 19:07 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292267227-22028-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@nokia.com>
This patch adds Bluetooth Management interface events for controller
addition and removal. The events correspond to the existing HCI_DEV_REG
and HCI_DEV_UNREG stack internal events.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
include/net/bluetooth/hci_core.h | 2 +
include/net/bluetooth/mgmt.h | 10 +++++++++
net/bluetooth/hci_core.c | 2 +
net/bluetooth/mgmt.c | 41 ++++++++++++++++++++++++++++++++++++++
4 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 1992fac..3786ee8 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -662,6 +662,8 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb);
/* Management interface */
int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len);
+int mgmt_index_added(u16 index);
+int mgmt_index_removed(u16 index);
/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 70985aa..ca29c13 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -75,3 +75,13 @@ struct mgmt_ev_controller_error {
__le16 index;
__u8 error_code;
} __packed;
+
+#define MGMT_EV_INDEX_ADDED 0x0004
+struct mgmt_ev_index_added {
+ __le16 index;
+} __packed;
+
+#define MGMT_EV_INDEX_REMOVED 0x0005
+struct mgmt_ev_index_removed {
+ __le16 index;
+} __packed;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 51c61f7..1a4ec97 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -960,6 +960,7 @@ int hci_register_dev(struct hci_dev *hdev)
}
}
+ mgmt_index_added(hdev->id);
hci_notify(hdev, HCI_DEV_REG);
return id;
@@ -989,6 +990,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
for (i = 0; i < NUM_REASSEMBLY; i++)
kfree_skb(hdev->reassembly[i]);
+ mgmt_index_removed(hdev->id);
hci_notify(hdev, HCI_DEV_UNREG);
if (hdev->rfkill) {
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index d6c5a32..f827fd9 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -265,3 +265,44 @@ done:
kfree(buf);
return err;
}
+
+static int mgmt_event(u16 event, void *data, u16 data_len)
+{
+ struct sk_buff *skb;
+ struct mgmt_hdr *hdr;
+
+ skb = alloc_skb(sizeof(*hdr) + data_len, GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ bt_cb(skb)->channel = HCI_CHANNEL_CONTROL;
+
+ hdr = (void *) skb_put(skb, sizeof(*hdr));
+ hdr->opcode = cpu_to_le16(event);
+ hdr->len = cpu_to_le16(data_len);
+
+ memcpy(skb_put(skb, data_len), data, data_len);
+
+ hci_send_to_sock(NULL, skb);
+ kfree_skb(skb);
+
+ return 0;
+}
+
+int mgmt_index_added(u16 index)
+{
+ struct mgmt_ev_index_added ev;
+
+ put_unaligned_le16(index, &ev.index);
+
+ return mgmt_event(MGMT_EV_INDEX_ADDED, &ev, sizeof(ev));
+}
+
+int mgmt_index_removed(u16 index)
+{
+ struct mgmt_ev_index_added ev;
+
+ put_unaligned_le16(index, &ev.index);
+
+ return mgmt_event(MGMT_EV_INDEX_REMOVED, &ev, sizeof(ev));
+}
--
1.7.2.3
^ permalink raw reply related
* [PATCH 4/5] Bluetooth: Add read_info management command
From: johan.hedberg @ 2010-12-13 19:07 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292267227-22028-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@nokia.com>
This patch implements the read_info command which is used to fetch basic
info about an adapter.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
include/net/bluetooth/mgmt.h | 19 +++++++++
net/bluetooth/mgmt.c | 90 ++++++++++++++++++++++++++++++++++++++----
2 files changed, 101 insertions(+), 8 deletions(-)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index c2b4c83..70985aa 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -39,6 +39,25 @@ struct mgmt_rp_read_index_list {
__le16 index[0];
} __packed;
+#define MGMT_OP_READ_INFO 0x0004
+struct mgmt_cp_read_info {
+ __le16 index;
+} __packed;
+struct mgmt_rp_read_info {
+ __le16 index;
+ __u8 type;
+ __u8 powered;
+ __u8 discoverable;
+ __u8 pairable;
+ __u8 sec_mode;
+ bdaddr_t bdaddr;
+ __u8 dev_class[3];
+ __u8 features[8];
+ __u16 manufacturer;
+ __u8 hci_ver;
+ __u16 hci_rev;
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 7a8e321..d6c5a32 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -32,6 +32,33 @@
#define MGMT_VERSION 0
#define MGMT_REVISION 1
+static int cmd_status(struct sock *sk, u16 cmd, u8 status)
+{
+ struct sk_buff *skb;
+ struct mgmt_hdr *hdr;
+ struct mgmt_ev_cmd_status *ev;
+
+ BT_DBG("sock %p", sk);
+
+ skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ hdr = (void *) skb_put(skb, sizeof(*hdr));
+
+ hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
+ hdr->len = cpu_to_le16(sizeof(*ev));
+
+ ev = (void *) skb_put(skb, sizeof(*ev));
+ ev->status = status;
+ put_unaligned_le16(cmd, &ev->opcode);
+
+ if (sock_queue_rcv_skb(sk, skb) < 0)
+ kfree_skb(skb);
+
+ return 0;
+}
+
static int read_version(struct sock *sk)
{
struct sk_buff *skb;
@@ -112,26 +139,70 @@ static int read_index_list(struct sock *sk)
return 0;
}
-static int cmd_status(struct sock *sk, u16 cmd, u8 status)
+static int read_controller_info(struct sock *sk, unsigned char *data, u16 len)
{
struct sk_buff *skb;
struct mgmt_hdr *hdr;
- struct mgmt_ev_cmd_status *ev;
+ struct mgmt_ev_cmd_complete *ev;
+ struct mgmt_rp_read_info *rp;
+ struct mgmt_cp_read_info *cp;
+ struct hci_dev *hdev;
+ u16 dev_id;
BT_DBG("sock %p", sk);
- skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_ATOMIC);
+ if (len != 2)
+ return cmd_status(sk, MGMT_OP_READ_INFO, EINVAL);
+
+ skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + sizeof(*rp), GFP_ATOMIC);
if (!skb)
return -ENOMEM;
hdr = (void *) skb_put(skb, sizeof(*hdr));
-
- hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
- hdr->len = cpu_to_le16(sizeof(*ev));
+ hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
+ hdr->len = cpu_to_le16(sizeof(*ev) + sizeof(*rp));
ev = (void *) skb_put(skb, sizeof(*ev));
- ev->status = status;
- put_unaligned_le16(cmd, &ev->opcode);
+ put_unaligned_le16(MGMT_OP_READ_INFO, &ev->opcode);
+
+ rp = (void *) skb_put(skb, sizeof(*rp));
+
+ cp = (void *) data;
+ dev_id = get_unaligned_le16(&cp->index);
+
+ BT_DBG("request for hci%u", dev_id);
+
+ hdev = hci_dev_get(dev_id);
+ if (!hdev) {
+ kfree_skb(skb);
+ return cmd_status(sk, MGMT_OP_READ_INFO, ENODEV);
+ }
+
+ hci_dev_lock_bh(hdev);
+
+ put_unaligned_le16(hdev->id, &rp->index);
+ rp->type = hdev->dev_type;
+
+ rp->powered = test_bit(HCI_UP, &hdev->flags);
+ rp->discoverable = test_bit(HCI_ISCAN, &hdev->flags);
+ rp->pairable = test_bit(HCI_PSCAN, &hdev->flags);
+
+ if (test_bit(HCI_AUTH, &hdev->flags))
+ rp->sec_mode = 3;
+ else if (hdev->ssp_mode > 0)
+ rp->sec_mode = 4;
+ else
+ rp->sec_mode = 2;
+
+ bacpy(&rp->bdaddr, &hdev->bdaddr);
+ memcpy(rp->features, hdev->features, 8);
+ memcpy(rp->dev_class, hdev->dev_class, 3);
+ put_unaligned_le16(hdev->manufacturer, &rp->manufacturer);
+ rp->hci_ver = hdev->hci_ver;
+ put_unaligned_le16(hdev->hci_rev, &rp->hci_rev);
+
+ hci_dev_unlock_bh(hdev);
+ hci_dev_put(hdev);
if (sock_queue_rcv_skb(sk, skb) < 0)
kfree_skb(skb);
@@ -176,6 +247,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
case MGMT_OP_READ_INDEX_LIST:
err = read_index_list(sk);
break;
+ case MGMT_OP_READ_INFO:
+ err = read_controller_info(sk, buf + sizeof(*hdr), len);
+ break;
default:
BT_DBG("Unknown op %u", opcode);
err = cmd_status(sk, opcode, 0x01);
--
1.7.2.3
^ permalink raw reply related
* [PATCH 3/5] Bluetooth: Add read_index_list management command
From: johan.hedberg @ 2010-12-13 19:07 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292267227-22028-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@nokia.com>
This patch implements the read_index_list command through which
userspace can get a list of current adapter indices.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
include/net/bluetooth/mgmt.h | 6 ++++
net/bluetooth/mgmt.c | 53 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index d353d64..c2b4c83 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -33,6 +33,12 @@ struct mgmt_rp_read_version {
__le16 revision;
} __packed;
+#define MGMT_OP_READ_INDEX_LIST 0x0003
+struct mgmt_rp_read_index_list {
+ __le16 num_controllers;
+ __le16 index[0];
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 3e24c0b..7a8e321 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -62,6 +62,56 @@ static int read_version(struct sock *sk)
return 0;
}
+static int read_index_list(struct sock *sk)
+{
+ struct sk_buff *skb;
+ struct mgmt_hdr *hdr;
+ struct mgmt_ev_cmd_complete *ev;
+ struct mgmt_rp_read_index_list *rp;
+ struct list_head *p;
+ size_t body_len;
+ u16 count;
+ int i;
+
+ BT_DBG("sock %p", sk);
+
+ read_lock(&hci_dev_list_lock);
+
+ count = 0;
+ list_for_each(p, &hci_dev_list) {
+ count++;
+ }
+
+ body_len = sizeof(*ev) + sizeof(*rp) + (2 * count);
+ skb = alloc_skb(sizeof(*hdr) + body_len, GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ hdr = (void *) skb_put(skb, sizeof(*hdr));
+ hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
+ hdr->len = cpu_to_le16(body_len);
+
+ ev = (void *) skb_put(skb, sizeof(*ev));
+ put_unaligned_le16(MGMT_OP_READ_INDEX_LIST, &ev->opcode);
+
+ rp = (void *) skb_put(skb, sizeof(*rp) + (2 * count));
+ put_unaligned_le16(count, &rp->num_controllers);
+
+ i = 0;
+ list_for_each(p, &hci_dev_list) {
+ struct hci_dev *d = list_entry(p, struct hci_dev, list);
+ put_unaligned_le16(d->id, &rp->index[i++]);
+ BT_DBG("Added hci%u", d->id);
+ }
+
+ read_unlock(&hci_dev_list_lock);
+
+ if (sock_queue_rcv_skb(sk, skb) < 0)
+ kfree_skb(skb);
+
+ return 0;
+}
+
static int cmd_status(struct sock *sk, u16 cmd, u8 status)
{
struct sk_buff *skb;
@@ -123,6 +173,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
case MGMT_OP_READ_VERSION:
err = read_version(sk);
break;
+ case MGMT_OP_READ_INDEX_LIST:
+ err = read_index_list(sk);
+ break;
default:
BT_DBG("Unknown op %u", opcode);
err = cmd_status(sk, opcode, 0x01);
--
1.7.2.3
^ permalink raw reply related
* [PATCH 2/5] Bluetooth: Add read_version management command
From: johan.hedberg @ 2010-12-13 19:07 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1292267227-22028-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@nokia.com>
This patch implements the initial read_version command that userspace
will use before any other management interface operations.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
include/net/bluetooth/mgmt.h | 6 ++++++
net/bluetooth/mgmt.c | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+), 0 deletions(-)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 95974da..d353d64 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -27,6 +27,12 @@ struct mgmt_hdr {
} __packed;
#define MGMT_HDR_SIZE 4
+#define MGMT_OP_READ_VERSION 0x0001
+struct mgmt_rp_read_version {
+ __u8 version;
+ __le16 revision;
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 7ea5489..3e24c0b 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -29,6 +29,39 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/mgmt.h>
+#define MGMT_VERSION 0
+#define MGMT_REVISION 1
+
+static int read_version(struct sock *sk)
+{
+ struct sk_buff *skb;
+ struct mgmt_hdr *hdr;
+ struct mgmt_ev_cmd_complete *ev;
+ struct mgmt_rp_read_version *rp;
+
+ BT_DBG("sock %p", sk);
+
+ skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + sizeof(*rp), GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ hdr = (void *) skb_put(skb, sizeof(*hdr));
+ hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
+ hdr->len = cpu_to_le16(sizeof(*ev) + sizeof(*rp));
+
+ ev = (void *) skb_put(skb, sizeof(*ev));
+ put_unaligned_le16(MGMT_OP_READ_VERSION, &ev->opcode);
+
+ rp = (void *) skb_put(skb, sizeof(*rp));
+ rp->version = MGMT_VERSION;
+ put_unaligned_le16(MGMT_REVISION, &rp->revision);
+
+ if (sock_queue_rcv_skb(sk, skb) < 0)
+ kfree_skb(skb);
+
+ return 0;
+}
+
static int cmd_status(struct sock *sk, u16 cmd, u8 status)
{
struct sk_buff *skb;
@@ -87,6 +120,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
}
switch (opcode) {
+ case MGMT_OP_READ_VERSION:
+ err = read_version(sk);
+ break;
default:
BT_DBG("Unknown op %u", opcode);
err = cmd_status(sk, opcode, 0x01);
--
1.7.2.3
^ 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