* Re: Wii Balance Board vs. bluez
From: Florian Echtler @ 2012-09-17 15:01 UTC (permalink / raw)
To: David Herrmann; +Cc: linux-bluetooth
In-Reply-To: <CANq1E4RE4ZhfvxhO=MdbMdwUZYrsdYnw=Yn7uLJE4gTAbHhOEw@mail.gmail.com>
Hi David,
On 17.09.2012 11:47, David Herrmann wrote:
> On Sat, Sep 15, 2012 at 5:31 PM, Florian Echtler <floe@butterbrot.org> wrote:
>> never mind - I tested my patch again and noticed that the driver wasn't able
>> to read all 24 calibration bytes in one go, which was the root cause for not
>> getting any data (I am simply disabling the extension when not getting
>> proper calibration data).
> Thanks! I have both patches ready for submission. However, could you
> actually tell me in what range data is submitted? As I said, I cannot
> test these patches. But looking at the code, you get 16bit per value
> raw input. You then calculate the per-kg value and multiply it by
> 17kg. So I guess you fill up the whole 16bit?
> Your second patch does not adjust the MIN/MAX values for the ABS_HATXY
> values and I am just looking for good values here.
OK, I see - the advertised maximum weight for the balance board is 150
kg. In theory, that would mean that every one of the 4 sensors can take
up to 150 kg (if a very heavy person is standing on one foot right in
the corner), which would translate to an absolute maximum value of
15000. In "unweighted" state, my balance board reports slightly negative
values for some sensors, so a minimum of perhaps -500 would be appropriate.
Thanks for integrating my patch!
Florian
--
SENT FROM MY PDP-11
^ permalink raw reply
* Re: [KERNEL PATCH] HID: Add support for Sony BD Remote
From: Bastien Nocera @ 2012-09-17 18:18 UTC (permalink / raw)
To: Luiz Augusto von Dentz
Cc: Antonio Ospite, David Dillow, linux-bluetooth, David Herrmann
In-Reply-To: <CABBYNZLsZRofkV5DDEj84dzzptUhx5YjCzoyk9UyjRJYU16Y5w@mail.gmail.com>
Em Mon, 2012-09-17 às 13:46 +0300, Luiz Augusto von Dentz escreveu:
> I now have the remote, I tried using xinput test and most keys seems
> to be working fine except the special buttons like subtitle, colors,
> x, l1... Im not sure if they are not being mapped because they don't
> have any representation or there is something wrong in the parser
> itself (Bastien do they used to work for you?). Also got a problem on
> suspend but I will have to reproduce it again to see if it is because
> of the new driver or not.
I used evtest for testing. To get access to all the keys in X, you'd
need to forward them, circumventing X.org's XKB limitations, using
something like lirc.
Using evtest is the easiest.
Cheers
^ permalink raw reply
* Re: Dropping connection (bit off-topic)
From: Anderson Lizardo @ 2012-09-17 20:30 UTC (permalink / raw)
To: John Tobias; +Cc: Vinicius Costa Gomes, linux-bluetooth
In-Reply-To: <CACUGKYNEYREQTM4s7vGcjHLij9KB4Sav2Zi-S0SLZREe+K+XPg@mail.gmail.com>
Hi John,
On Fri, Sep 14, 2012 at 3:04 PM, John Tobias <john.tobias.ph@gmail.com> wrote:
> Hi Anderson,
>
> Could you give me some bit of information on how to respond to the
> handle 0x0039?. I'm digging the bluez sources but I'm kind a lost
> right now and I don't know exactly what library/function should I use
> in order to configure it.
I suggest you take a look on GATT Procedures on the Core spec (see
"Discover All Characteristics of a Service" on pages 1916 and the
Figure 4.5 on page 1917). You will see that "Attribute not found" is
used to inform the client that there are no more characteristics to
discover.
Also see channel_handler() in src/attrib-server.c (and the functions
called by it) to understand how BlueZ's GATT server work.
To avoid the GATT disconnection after 30 sec. you really need to
figure out what the iPhone app is trying to do, it is clear from your
hcidump logs that iPhone is disconnecting, not the Linux "client"
side.
Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* [PATCH BlueZ v2 0/4] Support for GATT Find Included
From: Vinicius Costa Gomes @ 2012-09-17 20:46 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
Hi,
Changes from last version:
- Fixed problems found during PTS tests;
- Added a reference count for requests that are running in "parallel"
(if a included service has a 128 bit UUID, it needs to make an
aditional request to resolve this included service);
--
Jefferson Delfes (1):
gatttool: Add "included" command
Vinicius Costa Gomes (3):
gatt: Add support for find included services
core: Add support for included services
attrib: Remove opcode parameter from g_attrib_send()
attrib/client.c | 3 +-
attrib/gatt.c | 242 ++++++++++++++++++++++++++++++++-----
attrib/gatt.h | 9 ++
attrib/gattrib.c | 9 +-
attrib/gattrib.h | 6 +-
attrib/gatttool.c | 2 +-
attrib/interactive.c | 62 +++++++++-
profiles/gatt/gas.c | 2 +-
profiles/thermometer/thermometer.c | 3 +-
src/attrib-server.c | 3 +-
src/device.c | 109 +++++++++++++++--
11 files changed, 394 insertions(+), 56 deletions(-)
--
1.7.12
^ permalink raw reply
* [PATCH BlueZ v2 1/4] gatt: Add support for find included services
From: Vinicius Costa Gomes @ 2012-09-17 20:46 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1347914804-29624-1-git-send-email-vinicius.gomes@openbossa.org>
Some services like HID over LE can reference another service using
included services.
See Vol 3, Part G, section 2.6.3 of Core specification for more
details.
---
attrib/gatt.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
attrib/gatt.h | 9 +++
2 files changed, 203 insertions(+)
diff --git a/attrib/gatt.c b/attrib/gatt.c
index 6880e2d..902ac23 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -45,6 +45,21 @@ struct discover_primary {
void *user_data;
};
+struct find_included {
+ GAttrib *attrib;
+ int refs;
+ int err;
+ uint16_t end_handle;
+ GSList *includes;
+ gatt_cb_t cb;
+ void *user_data;
+};
+
+struct included_uuid_resolve {
+ struct find_included *fi;
+ struct gatt_included *included;
+};
+
struct discover_char {
GAttrib *attrib;
bt_uuid_t *uuid;
@@ -61,6 +76,26 @@ static void discover_primary_free(struct discover_primary *dp)
g_free(dp);
}
+static struct find_included *find_included_ref(struct find_included *fi)
+{
+ g_atomic_int_inc(&fi->refs);
+
+ return fi;
+}
+
+static void find_included_unref(struct find_included *fi)
+{
+ if (g_atomic_int_dec_and_test(&fi->refs) == FALSE)
+ return;
+
+ fi->cb(fi->includes, fi->err, fi->user_data);
+
+ g_slist_free_full(fi->includes, g_free);
+ g_attrib_unref(fi->attrib);
+ g_free(fi);
+}
+
+
static void discover_char_free(struct discover_char *dc)
{
g_slist_free_full(dc->characteristics, g_free);
@@ -248,6 +283,165 @@ guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
return g_attrib_send(attrib, 0, buf[0], buf, plen, cb, dp, NULL);
}
+static void resolve_included_uuid_cb(uint8_t status, const uint8_t *pdu,
+ uint16_t len, gpointer user_data)
+{
+ struct included_uuid_resolve *resolve = user_data;
+ struct find_included *fi = resolve->fi;
+ struct gatt_included *incl = resolve->included;
+ bt_uuid_t uuid;
+ unsigned int err = status;
+ size_t buflen;
+ uint8_t *buf;
+
+ if (err)
+ goto done;
+
+ buf = g_attrib_get_buffer(fi->attrib, &buflen);
+ if (dec_read_resp(pdu, len, buf, buflen) != 16) {
+ err = ATT_ECODE_IO;
+ goto done;
+ }
+
+ uuid = att_get_uuid128(buf);
+ bt_uuid_to_string(&uuid, incl->uuid, sizeof(incl->uuid));
+ fi->includes = g_slist_append(fi->includes, incl);
+
+done:
+ if (err)
+ g_free(incl);
+
+ if (fi->err == 0)
+ fi->err = err;
+
+ find_included_unref(fi);
+
+ g_free(resolve);
+}
+
+static guint resolve_included_uuid(struct find_included *fi,
+ struct gatt_included *incl)
+{
+ size_t buflen;
+ uint8_t *buf = g_attrib_get_buffer(fi->attrib, &buflen);
+ guint16 oplen = enc_read_req(incl->range.start, buf, buflen);
+ struct included_uuid_resolve *resolve;
+
+ resolve = g_new0(struct included_uuid_resolve, 1);
+ resolve->fi = find_included_ref(fi);
+ resolve->included = incl;
+
+ return g_attrib_send(fi->attrib, 0, buf[0], buf, oplen,
+ resolve_included_uuid_cb, resolve, NULL);
+}
+
+static struct gatt_included *included_from_buf(const uint8_t *buf, gsize buflen)
+{
+ struct gatt_included *incl = g_new0(struct gatt_included, 1);
+
+ incl->handle = att_get_u16(&buf[0]);
+ incl->range.start = att_get_u16(&buf[2]);
+ incl->range.end = att_get_u16(&buf[4]);
+
+ if (buflen == 8) {
+ bt_uuid_t uuid128;
+ bt_uuid_t uuid16 = att_get_uuid16(&buf[6]);
+
+ bt_uuid_to_uuid128(&uuid16, &uuid128);
+ bt_uuid_to_string(&uuid128, incl->uuid, sizeof(incl->uuid));
+ }
+
+ return incl;
+}
+
+static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len,
+ gpointer user_data);
+
+static guint find_included(struct find_included *fi, uint16_t start)
+{
+ bt_uuid_t uuid;
+ size_t buflen;
+ uint8_t *buf = g_attrib_get_buffer(fi->attrib, &buflen);
+ guint16 oplen;
+
+ bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
+ oplen = enc_read_by_type_req(start, fi->end_handle, &uuid,
+ buf, buflen);
+
+ find_included_ref(fi);
+
+ return g_attrib_send(fi->attrib, 0, buf[0], buf, oplen,
+ find_included_cb, fi, NULL);
+}
+
+static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len,
+ gpointer user_data)
+{
+ struct find_included *fi = user_data;
+ uint16_t last_handle = fi->end_handle;
+ unsigned int err = status;
+ struct att_data_list *list;
+ int i;
+
+ if (err == ATT_ECODE_ATTR_NOT_FOUND)
+ err = 0;
+
+ if (status)
+ goto done;
+
+ list = dec_read_by_type_resp(pdu, len);
+ if (list == NULL) {
+ err = ATT_ECODE_IO;
+ goto done;
+ }
+
+ if (list->len != 6 && list->len != 8) {
+ err = ATT_ECODE_IO;
+ att_data_list_free(list);
+ goto done;
+ }
+
+ for (i = 0; i < list->num; i++) {
+ struct gatt_included *incl;
+
+ incl = included_from_buf(list->data[i], list->len);
+ last_handle = incl->handle;
+
+ /* 128 bit UUID, needs resolving */
+ if (list->len == 6) {
+ resolve_included_uuid(fi, incl);
+ continue;
+ }
+
+ fi->includes = g_slist_append(fi->includes, incl);
+ }
+
+ att_data_list_free(list);
+
+ if (last_handle < fi->end_handle)
+ find_included(fi, last_handle + 1);
+
+done:
+ if (fi->err == 0)
+ fi->err = err;
+
+ find_included_unref(fi);
+}
+
+unsigned int gatt_find_included(GAttrib *attrib, uint16_t start, uint16_t end,
+ gatt_cb_t func, gpointer user_data)
+{
+ struct find_included *fi;
+
+ fi = g_new0(struct find_included, 1);
+ fi->attrib = g_attrib_ref(attrib);
+ fi->end_handle = end;
+ fi->cb = func;
+ fi->user_data = user_data;
+
+ return find_included(fi, start);
+}
+
static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
gpointer user_data)
{
diff --git a/attrib/gatt.h b/attrib/gatt.h
index 6bb6f0f..2897482 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -61,6 +61,12 @@ struct gatt_primary {
struct att_range range;
};
+struct gatt_included {
+ char uuid[MAX_LEN_UUID_STR + 1];
+ uint16_t handle;
+ struct att_range range;
+};
+
struct gatt_char {
char uuid[MAX_LEN_UUID_STR + 1];
uint16_t handle;
@@ -71,6 +77,9 @@ struct gatt_char {
guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
+unsigned int gatt_find_included(GAttrib *attrib, uint16_t start, uint16_t end,
+ gatt_cb_t func, gpointer user_data);
+
guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
--
1.7.12
^ permalink raw reply related
* [PATCH BlueZ v2 2/4] gatttool: Add "included" command
From: Vinicius Costa Gomes @ 2012-09-17 20:46 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jefferson Delfes
In-Reply-To: <1347914804-29624-1-git-send-email-vinicius.gomes@openbossa.org>
From: Jefferson Delfes <jefferson.delfes@openbossa.org>
New command to find included services in interactive mode.
---
attrib/interactive.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index c96df3e..ec5f2a5 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -209,6 +209,34 @@ static void primary_by_uuid_cb(GSList *ranges, guint8 status,
rl_forced_update_display();
}
+static void included_cb(GSList *includes, guint8 status, gpointer user_data)
+{
+ GSList *l;
+
+ if (status) {
+ printf("Find included services failed: %s\n",
+ att_ecode2str(status));
+ goto done;
+ }
+
+ if (includes == NULL) {
+ printf("No included services found for this range\n");
+ goto done;
+ }
+
+ printf("\n");
+ for (l = includes; l; l = l->next) {
+ struct gatt_included *incl = l->data;
+ printf("handle: 0x%04x, start handle: 0x%04x, "
+ "end handle: 0x%04x uuid: %s\n",
+ incl->handle, incl->range.start,
+ incl->range.end, incl->uuid);
+ }
+
+done:
+ rl_forced_update_display();
+}
+
static void char_cb(GSList *characteristics, guint8 status, gpointer user_data)
{
GSList *l;
@@ -426,6 +454,36 @@ static int strtohandle(const char *src)
return dst;
}
+static void cmd_included(int argcp, char **argvp)
+{
+ int start = 0x0001;
+ int end = 0xffff;
+
+ if (conn_state != STATE_CONNECTED) {
+ printf("Command failed: disconnected\n");
+ return;
+ }
+
+ if (argcp > 1) {
+ start = strtohandle(argvp[1]);
+ if (start < 0) {
+ printf("Invalid start handle: %s\n", argvp[1]);
+ return;
+ }
+ end = start;
+ }
+
+ if (argcp > 2) {
+ end = strtohandle(argvp[2]);
+ if (end < 0) {
+ printf("Invalid end handle: %s\n", argvp[2]);
+ return;
+ }
+ }
+
+ gatt_find_included(attrib, start, end, included_cb, NULL);
+}
+
static void cmd_char(int argcp, char **argvp)
{
int start = 0x0001;
@@ -751,6 +809,8 @@ static struct {
"Disconnect from a remote device" },
{ "primary", cmd_primary, "[UUID]",
"Primary Service Discovery" },
+ { "included", cmd_included, "[start hnd [end hnd]]",
+ "Find Included Services" },
{ "characteristics", cmd_char, "[start hnd [end hnd [UUID]]]",
"Characteristics Discovery" },
{ "char-desc", cmd_char_desc, "[start hnd] [end hnd]",
--
1.7.12
^ permalink raw reply related
* [PATCH BlueZ v2 3/4] core: Add support for included services
From: Vinicius Costa Gomes @ 2012-09-17 20:46 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1347914804-29624-1-git-send-email-vinicius.gomes@openbossa.org>
Soon after the primary service discovery is complete, we do a included
services discovery for all found services and add each included service
to the 'services' list so they can be probe()'d as a normal profile.
This will also make these services to appear on the D-Bus object tree.
---
src/device.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 96 insertions(+), 13 deletions(-)
diff --git a/src/device.c b/src/device.c
index 77215f1..648d2f1 100644
--- a/src/device.c
+++ b/src/device.c
@@ -108,6 +108,12 @@ struct browse_req {
guint listener_id;
};
+struct included_search {
+ struct browse_req *req;
+ GSList *services;
+ GSList *current;
+};
+
struct attio_data {
guint id;
attio_connect_cb cfunc;
@@ -1848,21 +1854,10 @@ static void device_unregister_services(struct btd_device *device)
device->services = NULL;
}
-static void primary_cb(GSList *services, guint8 status, gpointer user_data)
+static void register_all_services(struct browse_req *req, GSList *services)
{
- struct browse_req *req = user_data;
struct btd_device *device = req->device;
- if (status) {
- if (req->msg) {
- DBusMessage *reply;
- reply = btd_error_failed(req->msg,
- att_ecode2str(status));
- g_dbus_send_message(req->conn, reply);
- }
- goto done;
- }
-
device_set_temporary(device, FALSE);
if (device->services)
@@ -1887,11 +1882,99 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)
store_services(device);
-done:
device->browse = NULL;
browse_request_free(req);
}
+static int service_by_range_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct gatt_primary *prim = a;
+ const struct att_range *range = b;
+
+ return memcmp(&prim->range, range, sizeof(*range));
+}
+
+static void find_included_cb(GSList *includes, uint8_t status,
+ gpointer user_data)
+{
+ struct included_search *search = user_data;
+ struct btd_device *device = search->req->device;
+ struct gatt_primary *prim;
+ GSList *l;
+
+ if (includes == NULL)
+ goto done;
+
+ for (l = includes; l; l = l->next) {
+ struct gatt_included *incl = l->data;
+
+ if (g_slist_find_custom(search->services, &incl->range,
+ service_by_range_cmp))
+ continue;
+
+ prim = g_new0(struct gatt_primary, 1);
+ memcpy(prim->uuid, incl->uuid, sizeof(prim->uuid));
+ memcpy(&prim->range, &incl->range, sizeof(prim->range));
+
+ search->services = g_slist_append(search->services, prim);
+ }
+
+done:
+ search->current = search->current->next;
+ if (search->current == NULL) {
+ register_all_services(search->req, search->services);
+ g_slist_free(search->services);
+ g_free(search);
+ return;
+ }
+
+ prim = search->current->data;
+ gatt_find_included(device->attrib, prim->range.start, prim->range.end,
+ find_included_cb, search);
+}
+
+static void find_included_services(struct browse_req *req, GSList *services)
+{
+ struct btd_device *device = req->device;
+ struct included_search *search;
+ struct gatt_primary *prim;
+
+ if (services == NULL)
+ return;
+
+ search = g_new0(struct included_search, 1);
+ search->req = req;
+ search->services = g_slist_copy(services);
+ search->current = search->services;
+
+ prim = search->current->data;
+ gatt_find_included(device->attrib, prim->range.start, prim->range.end,
+ find_included_cb, search);
+
+}
+
+static void primary_cb(GSList *services, guint8 status, gpointer user_data)
+{
+ struct browse_req *req = user_data;
+
+ if (status) {
+ struct btd_device *device = req->device;
+
+ if (req->msg) {
+ DBusMessage *reply;
+ reply = btd_error_failed(req->msg,
+ att_ecode2str(status));
+ g_dbus_send_message(req->conn, reply);
+ }
+
+ device->browse = NULL;
+ browse_request_free(req);
+ return;
+ }
+
+ find_included_services(req, services);
+}
+
static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
{
struct att_callbacks *attcb = user_data;
--
1.7.12
^ permalink raw reply related
* [PATCH BlueZ v2 4/4] attrib: Remove opcode parameter from g_attrib_send()
From: Vinicius Costa Gomes @ 2012-09-17 20:46 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1347914804-29624-1-git-send-email-vinicius.gomes@openbossa.org>
In all uses of g_attrib_send() the opcode of the command/event is
already clear because of the att.h functions used to build the ATT
PDU.
---
attrib/client.c | 3 +-
attrib/gatt.c | 56 ++++++++++++++++----------------------
attrib/gattrib.c | 9 ++++--
attrib/gattrib.h | 6 ++--
attrib/gatttool.c | 2 +-
attrib/interactive.c | 2 +-
profiles/gatt/gas.c | 2 +-
profiles/thermometer/thermometer.c | 3 +-
src/attrib-server.c | 3 +-
9 files changed, 39 insertions(+), 47 deletions(-)
diff --git a/attrib/client.c b/attrib/client.c
index d5d40a1..0fd7fb7 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -368,8 +368,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len,
case ATT_OP_HANDLE_IND:
opdu = g_attrib_get_buffer(gatt->attrib, &plen);
olen = enc_confirmation(opdu, plen);
- g_attrib_send(gatt->attrib, 0, opdu[0], opdu, olen,
- NULL, NULL, NULL);
+ g_attrib_send(gatt->attrib, 0, opdu, olen, NULL, NULL, NULL);
case ATT_OP_HANDLE_NOTIFY:
if (characteristic_set_value(chr, &pdu[3], len - 3) < 0)
DBG("Can't change Characteristic 0x%02x", handle);
diff --git a/attrib/gatt.c b/attrib/gatt.c
index 902ac23..e6db227 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -176,8 +176,7 @@ static void primary_by_uuid_cb(guint8 status, const guint8 *ipdu,
if (oplen == 0)
goto done;
- g_attrib_send(dp->attrib, 0, buf[0], buf, oplen, primary_by_uuid_cb,
- dp, NULL);
+ g_attrib_send(dp->attrib, 0, buf, oplen, primary_by_uuid_cb, dp, NULL);
return;
done:
@@ -242,7 +241,7 @@ static void primary_all_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
guint16 oplen = encode_discover_primary(end + 1, 0xffff, NULL,
buf, buflen);
- g_attrib_send(dp->attrib, 0, buf[0], buf, oplen, primary_all_cb,
+ g_attrib_send(dp->attrib, 0, buf, oplen, primary_all_cb,
dp, NULL);
return;
@@ -280,7 +279,7 @@ guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
} else
cb = primary_all_cb;
- return g_attrib_send(attrib, 0, buf[0], buf, plen, cb, dp, NULL);
+ return g_attrib_send(attrib, 0, buf, plen, cb, dp, NULL);
}
static void resolve_included_uuid_cb(uint8_t status, const uint8_t *pdu,
@@ -331,8 +330,8 @@ static guint resolve_included_uuid(struct find_included *fi,
resolve->fi = find_included_ref(fi);
resolve->included = incl;
- return g_attrib_send(fi->attrib, 0, buf[0], buf, oplen,
- resolve_included_uuid_cb, resolve, NULL);
+ return g_attrib_send(fi->attrib, 0, buf, oplen,
+ resolve_included_uuid_cb, resolve, NULL);
}
static struct gatt_included *included_from_buf(const uint8_t *buf, gsize buflen)
@@ -370,8 +369,8 @@ static guint find_included(struct find_included *fi, uint16_t start)
find_included_ref(fi);
- return g_attrib_send(fi->attrib, 0, buf[0], buf, oplen,
- find_included_cb, fi, NULL);
+ return g_attrib_send(fi->attrib, 0, buf, oplen, find_included_cb,
+ fi, NULL);
}
static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len,
@@ -508,8 +507,8 @@ static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
if (oplen == 0)
return;
- g_attrib_send(dc->attrib, 0, buf[0], buf, oplen,
- char_discovered_cb, dc, NULL);
+ g_attrib_send(dc->attrib, 0, buf, oplen, char_discovered_cb,
+ dc, NULL);
return;
}
@@ -547,7 +546,7 @@ guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
dc->end = end;
dc->uuid = g_memdup(uuid, sizeof(bt_uuid_t));
- return g_attrib_send(attrib, 0, buf[0], buf, plen, char_discovered_cb,
+ return g_attrib_send(attrib, 0, buf, plen, char_discovered_cb,
dc, NULL);
}
@@ -563,8 +562,7 @@ guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,
if (plen == 0)
return 0;
- return g_attrib_send(attrib, 0, ATT_OP_READ_BY_TYPE_REQ,
- buf, plen, func, user_data, NULL);
+ return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
struct read_long_data {
@@ -623,8 +621,7 @@ static void read_blob_helper(guint8 status, const guint8 *rpdu, guint16 rlen,
plen = enc_read_blob_req(long_read->handle, long_read->size - 1,
buf, buflen);
- id = g_attrib_send(long_read->attrib, long_read->id,
- ATT_OP_READ_BLOB_REQ, buf, plen,
+ id = g_attrib_send(long_read->attrib, long_read->id, buf, plen,
read_blob_helper, long_read, read_long_destroy);
if (id != 0) {
@@ -660,9 +657,8 @@ static void read_char_helper(guint8 status, const guint8 *rpdu,
long_read->size = rlen;
plen = enc_read_blob_req(long_read->handle, rlen - 1, buf, buflen);
- id = g_attrib_send(long_read->attrib, long_read->id,
- ATT_OP_READ_BLOB_REQ, buf, plen, read_blob_helper,
- long_read, read_long_destroy);
+ id = g_attrib_send(long_read->attrib, long_read->id, buf, plen,
+ read_blob_helper, long_read, read_long_destroy);
if (id != 0) {
g_atomic_int_inc(&long_read->ref);
@@ -698,12 +694,12 @@ guint gatt_read_char(GAttrib *attrib, uint16_t handle, uint16_t offset,
if (offset > 0) {
plen = enc_read_blob_req(long_read->handle, offset, buf,
buflen);
- id = g_attrib_send(attrib, 0, ATT_OP_READ_BLOB_REQ, buf, plen,
- read_blob_helper, long_read, read_long_destroy);
+ id = g_attrib_send(attrib, 0, buf, plen, read_blob_helper,
+ long_read, read_long_destroy);
} else {
plen = enc_read_req(handle, buf, buflen);
- id = g_attrib_send(attrib, 0, ATT_OP_READ_REQ, buf, plen,
- read_char_helper, long_read, read_long_destroy);
+ id = g_attrib_send(attrib, 0, buf, plen, read_char_helper,
+ long_read, read_long_destroy);
}
if (id == 0)
@@ -738,8 +734,7 @@ static guint execute_write(GAttrib *attrib, uint8_t flags,
if (plen == 0)
return 0;
- return g_attrib_send(attrib, 0, buf[0], buf, plen, func, user_data,
- NULL);
+ return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset,
@@ -788,7 +783,7 @@ static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset,
if (plen == 0)
return 0;
- return g_attrib_send(attrib, 0, buf[0], buf, plen, prepare_write_cb,
+ return g_attrib_send(attrib, 0, buf, plen, prepare_write_cb,
user_data, NULL);
}
@@ -812,7 +807,7 @@ guint gatt_write_char(GAttrib *attrib, uint16_t handle, uint8_t *value,
plen = enc_write_cmd(handle, value, vlen, buf,
buflen);
- return g_attrib_send(attrib, 0, buf[0], buf, plen, func,
+ return g_attrib_send(attrib, 0, buf, plen, func,
user_data, NULL);
}
@@ -841,8 +836,7 @@ guint gatt_exchange_mtu(GAttrib *attrib, uint16_t mtu, GAttribResultFunc func,
buf = g_attrib_get_buffer(attrib, &buflen);
plen = enc_mtu_req(mtu, buf, buflen);
- return g_attrib_send(attrib, 0, ATT_OP_MTU_REQ, buf, plen, func,
- user_data, NULL);
+ return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
guint gatt_find_info(GAttrib *attrib, uint16_t start, uint16_t end,
@@ -857,8 +851,7 @@ guint gatt_find_info(GAttrib *attrib, uint16_t start, uint16_t end,
if (plen == 0)
return 0;
- return g_attrib_send(attrib, 0, ATT_OP_FIND_INFO_REQ, buf, plen, func,
- user_data, NULL);
+ return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen,
@@ -870,8 +863,7 @@ guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen,
buf = g_attrib_get_buffer(attrib, &buflen);
plen = enc_write_cmd(handle, value, vlen, buf, buflen);
- return g_attrib_send(attrib, 0, ATT_OP_WRITE_CMD, buf, plen, NULL,
- user_data, notify);
+ return g_attrib_send(attrib, 0, buf, plen, NULL, user_data, notify);
}
static sdp_data_t *proto_seq_find(sdp_list_t *proto_list)
diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index 108d1d3..6f6942f 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -472,12 +472,13 @@ GAttrib *g_attrib_new(GIOChannel *io)
return g_attrib_ref(attrib);
}
-guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
- const guint8 *pdu, guint16 len, GAttribResultFunc func,
- gpointer user_data, GDestroyNotify notify)
+guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len,
+ GAttribResultFunc func, gpointer user_data,
+ GDestroyNotify notify)
{
struct command *c;
GQueue *queue;
+ uint8_t opcode;
if (attrib->stale)
return 0;
@@ -486,6 +487,8 @@ guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
if (c == NULL)
return 0;
+ opcode = pdu[0];
+
c->opcode = opcode;
c->expected = opcode2expected(opcode);
c->pdu = g_malloc(len);
diff --git a/attrib/gattrib.h b/attrib/gattrib.h
index bcff039..bca966f 100644
--- a/attrib/gattrib.h
+++ b/attrib/gattrib.h
@@ -50,9 +50,9 @@ GIOChannel *g_attrib_get_channel(GAttrib *attrib);
gboolean g_attrib_set_destroy_function(GAttrib *attrib,
GDestroyNotify destroy, gpointer user_data);
-guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
- const guint8 *pdu, guint16 len, GAttribResultFunc func,
- gpointer user_data, GDestroyNotify notify);
+guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len,
+ GAttribResultFunc func, gpointer user_data,
+ GDestroyNotify notify);
gboolean g_attrib_cancel(GAttrib *attrib, guint id);
gboolean g_attrib_cancel_all(GAttrib *attrib);
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 416bb71..dea1fc4 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -105,7 +105,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
olen = enc_confirmation(opdu, plen);
if (olen > 0)
- g_attrib_send(attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL);
+ g_attrib_send(attrib, 0, opdu, olen, NULL, NULL, NULL);
}
static gboolean listen_start(gpointer user_data)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index ec5f2a5..1b0edf4 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -133,7 +133,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
olen = enc_confirmation(opdu, plen);
if (olen > 0)
- g_attrib_send(attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL);
+ g_attrib_send(attrib, 0, opdu, olen, NULL, NULL, NULL);
}
static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
index 28d7fbf..4d8797e 100644
--- a/profiles/gatt/gas.c
+++ b/profiles/gatt/gas.c
@@ -150,7 +150,7 @@ static void indication_cb(const uint8_t *pdu, uint16_t len, gpointer user_data)
/* Confirming indication received */
opdu = g_attrib_get_buffer(gas->attrib, &plen);
olen = enc_confirmation(opdu, plen);
- g_attrib_send(gas->attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL);
+ g_attrib_send(gas->attrib, 0, opdu, olen, NULL, NULL, NULL);
if (gas->changed.start == start && gas->changed.end == end)
return;
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index f58e558..774426b 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -1170,8 +1170,7 @@ static void ind_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
olen = enc_confirmation(opdu, plen);
if (olen > 0)
- g_attrib_send(t->attrib, 0, opdu[0], opdu, olen, NULL, NULL,
- NULL);
+ g_attrib_send(t->attrib, 0, opdu, olen, NULL, NULL, NULL);
}
static void notif_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 9b03e54..afe5e48 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -1031,8 +1031,7 @@ done:
length = enc_error_resp(ipdu[0], 0x0000, status, opdu,
channel->mtu);
- g_attrib_send(channel->attrib, 0, opdu[0], opdu, length,
- NULL, NULL, NULL);
+ g_attrib_send(channel->attrib, 0, opdu, length, NULL, NULL, NULL);
}
guint attrib_channel_attach(GAttrib *attrib)
--
1.7.12
^ permalink raw reply related
* Re: Dropping connection (bit off-topic)
From: John Tobias @ 2012-09-17 21:21 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: Vinicius Costa Gomes, linux-bluetooth
In-Reply-To: <CAJdJm_OfTBZed2aAYQssGS4HhBV5tDt95=NaMy6qevShKCwnBQ@mail.gmail.com>
Hi Anderson,
Thanks for the info., we will be going to snip what the iOS is sending
to understand the scenario. I think iOS stack has some handshaking
procedure or required in order to maintain the connection. I used
gatttool to connect to the CC2540 demo board and it did not disconnect
like the iOS does.
Regards,
John
On Mon, Sep 17, 2012 at 1:30 PM, Anderson Lizardo
<anderson.lizardo@openbossa.org> wrote:
> Hi John,
>
> On Fri, Sep 14, 2012 at 3:04 PM, John Tobias <john.tobias.ph@gmail.com> wrote:
>> Hi Anderson,
>>
>> Could you give me some bit of information on how to respond to the
>> handle 0x0039?. I'm digging the bluez sources but I'm kind a lost
>> right now and I don't know exactly what library/function should I use
>> in order to configure it.
>
> I suggest you take a look on GATT Procedures on the Core spec (see
> "Discover All Characteristics of a Service" on pages 1916 and the
> Figure 4.5 on page 1917). You will see that "Attribute not found" is
> used to inform the client that there are no more characteristics to
> discover.
>
> Also see channel_handler() in src/attrib-server.c (and the functions
> called by it) to understand how BlueZ's GATT server work.
>
> To avoid the GATT disconnection after 30 sec. you really need to
> figure out what the iPhone app is trying to do, it is clear from your
> hcidump logs that iPhone is disconnecting, not the Linux "client"
> side.
>
> Regards,
> --
> Anderson Lizardo
> Instituto Nokia de Tecnologia - INdT
> Manaus - Brazil
^ permalink raw reply
* Re: [KERNEL PATCH] HID: Add support for Sony BD Remote
From: David Dillow @ 2012-09-18 0:52 UTC (permalink / raw)
To: Antonio Ospite
Cc: linux-bluetooth, David Herrmann, Luiz Augusto von Dentz,
Bastien Nocera
In-Reply-To: <20120917120441.a164d2e10bb02aa9a1e8d523@studenti.unina.it>
On Mon, 2012-09-17 at 12:04 +0200, Antonio Ospite wrote:
> On Thu, 13 Sep 2012 23:04:52 -0400
> David Dillow <dave@thedillows.org> wrote:
> > Antonio, if you could test this with the real remote you have, I'd be
> > very appreciative.
> >
>
> Works here as well with original PS3 BR remote, thanks David D.
>
> About multiple key-presses, when I hold two _different_ keys at the same
> time, I get the message:
>
> ps3_remote 0005:054C:0306.0004: Incoherent report, 000000 000000 ff 16
> 01
>
> I just tried a couple of combinations tho.
I found a typo in the custom report descriptor which could cause this --
where it says REPORT COUNT (11), I have 0x95, 0x01 as values in the
array. Those should be 0x95, 0x0b instead. This would prevent it from
looking at any more than the first key reported. Could you fix that up
and retest?
Looking at this gave me an idea that would avoid needing a raw event
handler; I've got a version built and will test in a bit, once the kids
are down. I'll send it along after that.
If both fail, it would be useful to see the output
from /sys/kernel/debug/hid/0005:*:0306:*/event while you are pressing
both single and multiple buttons.
> What about adding a note about the association maneuver? I mean the one
> when we press Start+Enter for a few second when we add the BD remote as
> a new BT device. I forget about it every time I associate the BD
> remote with a new system; I know kernel code is not the most
> user-friendly spot for this documentation but having it here wouldn't
> hurt.
>
> Now I noted it on the back of the battery cover too :)
Indeed; I don't have one of the real remotes -- could you provide text?
> > +static int ps3remote_event(struct hid_device *hdev, struct hid_report *report,
> > + u8 *raw_data, int size)
> > +{
> > + struct ps3remote_data *data = hid_get_drvdata(hdev);
> > + u32 mask, changed;
> > + u8 key, pressed;
>
> The preferred kernel style for declarations is to have one per line, no
> commas, but that's up to you.
I've seen it both ways, so I'll stick with the less vertical space. If
they were initialized here, I'd be more inclined to change.
> > + if (size != 12) {
> > + hid_dbg(hdev, "unsupported report size\n");
> > + return 1;
>
> The raw_event callback should return negative on error, is there a
> reason why 1 is returned here?
I was just eating the event rather than passing it on. It probably makes
more sense to return an error, but I didn't investigate how the rest of
the stack handled that.
I'll likely change this if I need to keep the raw event handler.
Thank you for the review, I've incorporated your other comments into the
driver before I started working on the simpler version.
Dave
^ permalink raw reply
* [PATCH v2] HID: Add support for Sony PS3 BD Remote Control
From: David Dillow @ 2012-09-18 1:33 UTC (permalink / raw)
To: Antonio Ospite
Cc: linux-bluetooth, David Herrmann, Luiz Augusto von Dentz,
Bastien Nocera, linux-input, jkosina
In-Reply-To: <1347929527.29391.9.camel@obelisk.thedillows.org>
The Sony PS3 Blue-ray Disc Remote Control used to be supported by the
BlueZ project's user space, but the code that handled it was recently
removed as its functionality conflicted with a real HSP implementation
and the mapping was thought to be better handled in the kernel. This is
a port of the mapping logic from the fakehid driver by Marcel Holtmann
to the in-kernel HID layer.
We also add support for the Logitech Harmony Adapter for PS3, which
emulates the BD Remote.
Signed-off-by: David Dillow <dave@thedillows.org>
---
drivers/hid/Kconfig | 11 ++-
drivers/hid/Makefile | 1 +
drivers/hid/hid-core.c | 2 +
drivers/hid/hid-ids.h | 2 +
drivers/hid/hid-ps3remote.c | 199 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 214 insertions(+), 1 deletions(-)
Here's an updated version of the HID driver for the PS3 BD Remote. I've
gone ahead and signed off on it as it works for my Harmony adapter, but
it needs testing with a real BD remote before going upstream. Antonio
also asked for some text about the pairing process -- I've left it out
since I don't know what it should be.
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index fbf4950..7bf3b1a 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -534,6 +534,14 @@ config HID_PRIMAX
Support for Primax devices that are not fully compliant with the
HID standard.
+config HID_PS3REMOTE
+ tristate "Sony PS3 BD Remote"
+ depends on BT_HIDP
+ ---help---
+ Support for the Sony PS3 BD Remote and Logitech Harmony Adapter
+ for PS3, which connect over Bluetooth. Support for the 6-axis
+ controllers is provided by HID_SONY.
+
config HID_ROCCAT
tristate "Roccat device support"
depends on USB_HID
@@ -561,7 +569,8 @@ config HID_SONY
tristate "Sony PS3 controller"
depends on USB_HID
---help---
- Support for Sony PS3 controller.
+ Support for Sony PS3 6-axis controllers. Support for the Sony PS3
+ BD Remote is provided by HID_PS3REMOTE.
config HID_SPEEDLINK
tristate "Speedlink VAD Cezanne mouse support"
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index f975485..333ed6c 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o
obj-$(CONFIG_HID_PRIMAX) += hid-primax.o
+obj-$(CONFIG_HID_PS3REMOTE) += hid-ps3remote.o
obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \
hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 60ea284..a9f0439 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1591,6 +1591,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
@@ -1641,6 +1642,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 1dcb76f..0f5c2bb 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -492,6 +492,7 @@
#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
#define USB_VENDOR_ID_LOGITECH 0x046d
+#define USB_DEVICE_ID_LOGITECH_HARMONY_PS3 0x0306
#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110
@@ -684,6 +685,7 @@
#define USB_VENDOR_ID_SONY 0x054c
#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
+#define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306
#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f
#define USB_VENDOR_ID_SOUNDGRAPH 0x15c2
diff --git a/drivers/hid/hid-ps3remote.c b/drivers/hid/hid-ps3remote.c
new file mode 100644
index 0000000..e8caef0
--- /dev/null
+++ b/drivers/hid/hid-ps3remote.c
@@ -0,0 +1,199 @@
+/*
+ * HID driver for Sony PS3 BD Remote
+ *
+ * Copyright (c) 2012 David Dillow <dave@thedillows.org>
+ * Based on a blend of the bluez fakehid user-space code by Marcel Holtmann
+ * and other kernel HID drivers.
+ */
+
+/*
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/*
+ * The first byte of the raw event report seems to contain a fixed number,
+ * possibly a controller number. The next three bytes contain a bitmask,
+ * in big-endian order, of a portion of the buttons available.
+ *
+ * Button Bit Scan Mapped Key
+ * PS 0 0x43 KEY_HOMEPAGE
+ * Unknown 1-2
+ * Enter 3 0x0b KEY_ENTER
+ * Unknown 4-7
+ * L2 8 0x58 BTN_TL2
+ * R2 9 0x59 BTN_TR2
+ * L1 10 0x5a BTN_TL
+ * R1 11 0x5b BTN_TR
+ * Triangle 12 0x5c KEY_OPTION
+ * Circle 13 0x5d KEY_BACK
+ * Cross 14 0x5e BTN_0
+ * Square 15 0x5f KEY_SCREEN
+ * Select 16 0x50 KEY_SELECT
+ * L3 17 0x51 BTN_THUMBL
+ * R3 18 0x52 BTN_THUMBR
+ * Start 19 0x53 BTN_START
+ * Up 20 0x54 KEY_UP
+ * Right 21 0x55 KEY_RIGHT
+ * Down 22 0x56 KEY_DOWN
+ * Left 23 0x57 KEY_LEFT
+ *
+ * The keymap is generally ordered by the physical location of the buttons,
+ * as this makes it easier to verify a correct mapping during testing.
+ */
+static const unsigned int ps3remote_keymap[] = {
+ [0x16] = KEY_EJECTCD,
+ [0x64] = KEY_AUDIO,
+ [0x65] = KEY_ANGLE,
+ [0x63] = KEY_SUBTITLE,
+ [0x0f] = KEY_CLEAR,
+ [0x28] = KEY_TIME,
+ [0x00] = KEY_1,
+ [0x01] = KEY_2,
+ [0x02] = KEY_3,
+ [0x03] = KEY_4,
+ [0x04] = KEY_5,
+ [0x05] = KEY_6,
+ [0x06] = KEY_7,
+ [0x07] = KEY_8,
+ [0x08] = KEY_9,
+ [0x09] = KEY_0,
+ [0x81] = KEY_RED,
+ [0x82] = KEY_GREEN,
+ [0x80] = KEY_BLUE,
+ [0x83] = KEY_YELLOW,
+ [0x70] = KEY_INFO, /* display */
+ [0x1a] = KEY_MENU, /* top menu */
+ [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */
+ [0x0e] = KEY_ESC, /* return */
+ [0x5c] = KEY_OPTION, /* options/triangle */
+ [0x5d] = KEY_BACK, /* back/circle */
+ [0x5f] = KEY_SCREEN, /* view/square */
+ [0x5e] = BTN_0, /* cross */
+ [0x54] = KEY_UP,
+ [0x56] = KEY_DOWN,
+ [0x57] = KEY_LEFT,
+ [0x55] = KEY_RIGHT,
+ [0x0b] = KEY_ENTER,
+ [0x5a] = BTN_TL, /* L1 */
+ [0x58] = BTN_TL2, /* L2 */
+ [0x51] = BTN_THUMBL, /* L3 */
+ [0x5b] = BTN_TR, /* R1 */
+ [0x59] = BTN_TR2, /* R2 */
+ [0x52] = BTN_THUMBR, /* R3 */
+ [0x43] = KEY_HOMEPAGE, /* PS button */
+ [0x50] = KEY_SELECT,
+ [0x53] = BTN_START,
+ [0x33] = KEY_REWIND, /* scan back */
+ [0x32] = KEY_PLAY,
+ [0x34] = KEY_FORWARD, /* scan forward */
+ [0x30] = KEY_PREVIOUS,
+ [0x38] = KEY_STOP,
+ [0x31] = KEY_NEXT,
+ [0x60] = KEY_FRAMEBACK, /* slow/step back */
+ [0x39] = KEY_PAUSE,
+ [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */
+};
+
+static __u8 ps3remote_rdesc[] = {
+ 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */
+ 0x09, 0x05, /* USAGE (Game Pad) */
+ 0xa1, 0x01, /* COLLECTION (Application) */
+
+ /* First four bytes contain a bitmask for some of the buttons, and
+ * possibly a controller number. We don't need this information,
+ * as the keys will be reported in the next field as well.
+ */
+ 0x75, 0x20, /* REPORT SIZE (32) */
+ 0x95, 0x01, /* REPORT COUNT (1) */
+ 0x81, 0x01, /* INPUT (Constant) */
+
+ /* All key presses are reported in this field */
+ 0x05, 0x09, /* USAGE PAGE (Button) */
+ 0x19, 0x00, /* USAGE MINIMUM (0) */
+ 0x29, 0xfe, /* USAGE MAXIMUM (254) */
+ 0x15, 0x00, /* LOGICAL MINIMUM (0) */
+ 0x25, 0xfe, /* LOGICAL MAXIMUM (254) */
+ 0x75, 0x08, /* REPORT SIZE (8) */
+ 0x95, 0x06, /* REPORT COUNT (6) */
+ 0x81, 0x00, /* INPUT (Array, Absolute) */
+
+ /* Ignore press indication */
+ 0x75, 0x08, /* REPORT SIZE (8) */
+ 0x95, 0x01, /* REPORT COUNT (1) */
+ 0x81, 0x01, /* INPUT (Constant) */
+
+ /* Report the battery level */
+ 0x05, 0x06, /* USAGE PAGE (Generic Device) */
+ 0x09, 0x20, /* USAGE (Battery Strength) */
+ 0x15, 0x00, /* LOGICAL MINIMUM (0) */
+ 0x25, 0x05, /* LOGICAL MAXIMUM (5) */
+ 0x75, 0x08, /* REPORT SIZE (8) */
+ 0x95, 0x01, /* REPORT COUNT (1) */
+ 0x81, 0x02, /* INPUT (Variable, Absolute) */
+ 0xc0, /* END_COLLECTION */
+};
+
+static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int *rsize)
+{
+ *rsize = sizeof(ps3remote_rdesc);
+ return ps3remote_rdesc;
+}
+
+static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ unsigned int key = usage->hid & HID_USAGE;
+
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON ||
+ key >= ARRAY_SIZE(ps3remote_keymap))
+ return -1;
+
+ key = ps3remote_keymap[key];
+ if (!key)
+ return -1;
+
+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
+ return 1;
+}
+
+static const struct hid_device_id ps3remote_devices[] = {
+ /* PS3 BD Remote */
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) },
+ /* Logitech Harmony Adapter for PS3 */
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, ps3remote_devices);
+
+static struct hid_driver ps3remote_driver = {
+ .name = "ps3_remote",
+ .id_table = ps3remote_devices,
+ .report_fixup = ps3remote_fixup,
+ .input_mapping = ps3remote_mapping,
+};
+
+static int __init ps3remote_init(void)
+{
+ return hid_register_driver(&ps3remote_driver);
+}
+
+static void __exit ps3remote_exit(void)
+{
+ hid_unregister_driver(&ps3remote_driver);
+}
+
+module_init(ps3remote_init);
+module_exit(ps3remote_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
^ permalink raw reply related
* Re: [PATCH BlueZ V6 1/5] AVRCP: Add TG Record to support AVRCP Browsing
From: Arun K. Singh @ 2012-09-18 6:08 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org
In-Reply-To: <747C1E83C744F44E9ACFB89FAEEC2C7B23D4AD9596@EXDCVYMBSTM005.EQ1STM.local>
Hi Luiz, folks,
On Thu, Aug 30, 2012 at 10:38 AM, Vani-dineshbhai PATEL X
<vani.patel@stericsson.com> wrote:
>
> From 7e32aecb2b13c6398108932e98fdd68faf9315d8 Mon Sep 17 00:00:00 2001
> From: Vani Patel <vani.patel@stericsson.com>
> Date: Tue, 5 Jun 2012 13:44:30 +0530
> Subject: [PATCH BlueZ V6 1/5] AVRCP: Add TG Record to support AVRCP
> Browsing
>
> Adds SDP record to support browsing
> ---
> audio/avctp.c | 4 ++--
> audio/avctp.h | 3 ++-
> audio/avrcp.c | 28 ++++++++++++++++++++++++----
> 3 files changed, 28 insertions(+), 7 deletions(-)
>
> diff --git a/audio/avctp.c b/audio/avctp.c
> index 074eabd..a20dba9 100644
> --- a/audio/avctp.c
> +++ b/audio/avctp.c
Any chance that have you been able to take a look at these patches and review?
Thanks,
Arun
^ permalink raw reply
* Re: [PATCHv5 02/17] Bluetooth: A2MP: Create amp_mgr global list
From: Marcel Holtmann @ 2012-09-18 7:43 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth, mathewm, gustavo
In-Reply-To: <1347888274-30779-3-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
> Create amp_mgr_list global list which will be used by different
> hci devices to find amp_mgr.
>
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
> include/net/bluetooth/a2mp.h | 8 ++++++++
> net/bluetooth/a2mp.c | 29 +++++++++++++++++++++++++++++
> 2 files changed, 37 insertions(+)
>
> diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
> index 6a76e0a..e56d656 100644
> --- a/include/net/bluetooth/a2mp.h
> +++ b/include/net/bluetooth/a2mp.h
> @@ -20,11 +20,15 @@
> #define A2MP_FEAT_EXT 0x8000
>
> struct amp_mgr {
> + struct list_head list;
> struct l2cap_conn *l2cap_conn;
> struct l2cap_chan *a2mp_chan;
> struct kref kref;
> __u8 ident;
> __u8 handle;
> + enum {
> + READ_LOC_AMP_INFO,
> + } state;
I am not a huge fan of these things. Wouldn't it be better to define the
states externally properly.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH BlueZ V6 1/5] AVRCP: Add TG Record to support AVRCP Browsing
From: Luiz Augusto von Dentz @ 2012-09-18 8:05 UTC (permalink / raw)
To: Arun K. Singh; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CAOnmHE_mHvQJO8AEnCUS-UoUDC9NXYgAhAiAxzNULeS9PGu6WA@mail.gmail.com>
Hi Arun,
On Tue, Sep 18, 2012 at 9:08 AM, Arun K. Singh <arunkat@gmail.com> wrote:
> Hi Luiz, folks,
>
> On Thu, Aug 30, 2012 at 10:38 AM, Vani-dineshbhai PATEL X
> <vani.patel@stericsson.com> wrote:
>>
>> From 7e32aecb2b13c6398108932e98fdd68faf9315d8 Mon Sep 17 00:00:00 2001
>> From: Vani Patel <vani.patel@stericsson.com>
>> Date: Tue, 5 Jun 2012 13:44:30 +0530
>> Subject: [PATCH BlueZ V6 1/5] AVRCP: Add TG Record to support AVRCP
>> Browsing
>>
>> Adds SDP record to support browsing
>> ---
>> audio/avctp.c | 4 ++--
>> audio/avctp.h | 3 ++-
>> audio/avrcp.c | 28 ++++++++++++++++++++++++----
>> 3 files changed, 28 insertions(+), 7 deletions(-)
>>
>> diff --git a/audio/avctp.c b/audio/avctp.c
>> index 074eabd..a20dba9 100644
>> --- a/audio/avctp.c
>> +++ b/audio/avctp.c
>
> Any chance that have you been able to take a look at these patches and review?
Im trying to validate the patches together with hcidump changes, but I
don't have any device that make use of the browsing channel. I was
expecting some updates regarding hcidump but it seems I will have to
take care of this myself.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH BlueZ V6 1/5] AVRCP: Add TG Record to support AVRCP Browsing
From: Luiz Augusto von Dentz @ 2012-09-18 8:28 UTC (permalink / raw)
To: Vani-dineshbhai PATEL X; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CABBYNZJN2evUd1BcNfbNLnRg0zFCVCxbFM5-xBUY65B+wFuM+A@mail.gmail.com>
Hi Vani,
On Tue, Sep 18, 2012 at 11:05 AM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> Hi Arun,
>
> On Tue, Sep 18, 2012 at 9:08 AM, Arun K. Singh <arunkat@gmail.com> wrote:
>> Hi Luiz, folks,
>>
>> On Thu, Aug 30, 2012 at 10:38 AM, Vani-dineshbhai PATEL X
>> <vani.patel@stericsson.com> wrote:
>>>
>>> From 7e32aecb2b13c6398108932e98fdd68faf9315d8 Mon Sep 17 00:00:00 2001
>>> From: Vani Patel <vani.patel@stericsson.com>
>>> Date: Tue, 5 Jun 2012 13:44:30 +0530
>>> Subject: [PATCH BlueZ V6 1/5] AVRCP: Add TG Record to support AVRCP
>>> Browsing
>>>
>>> Adds SDP record to support browsing
>>> ---
>>> audio/avctp.c | 4 ++--
>>> audio/avctp.h | 3 ++-
>>> audio/avrcp.c | 28 ++++++++++++++++++++++++----
>>> 3 files changed, 28 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/audio/avctp.c b/audio/avctp.c
>>> index 074eabd..a20dba9 100644
>>> --- a/audio/avctp.c
>>> +++ b/audio/avctp.c
>>
>> Any chance that have you been able to take a look at these patches and review?
>
> Im trying to validate the patches together with hcidump changes, but I
> don't have any device that make use of the browsing channel. I was
> expecting some updates regarding hcidump but it seems I will have to
> take care of this myself.
There seems to be some problem when I try to apply your patches git am
complains:
Applying: AVRCP: Add TG Record to support AVRCP Browsing
fatal: corrupt patch at line 12
Patch failed at 0001 AVRCP: Add TG Record to support AVRCP Browsing
It seems your patches are mangle using windows style line breaks.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCHv5 02/17] Bluetooth: A2MP: Create amp_mgr global list
From: Andrei Emeltchenko @ 2012-09-18 8:45 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-bluetooth, mathewm, gustavo
In-Reply-To: <1347954231.10756.0.camel@aeonflux>
Hi Marcel,
On Tue, Sep 18, 2012 at 09:43:51AM +0200, Marcel Holtmann wrote:
> Hi Andrei,
>
> > Create amp_mgr_list global list which will be used by different
> > hci devices to find amp_mgr.
> >
> > Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > ---
> > include/net/bluetooth/a2mp.h | 8 ++++++++
> > net/bluetooth/a2mp.c | 29 +++++++++++++++++++++++++++++
> > 2 files changed, 37 insertions(+)
> >
> > diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
> > index 6a76e0a..e56d656 100644
> > --- a/include/net/bluetooth/a2mp.h
> > +++ b/include/net/bluetooth/a2mp.h
> > @@ -20,11 +20,15 @@
> > #define A2MP_FEAT_EXT 0x8000
> >
> > struct amp_mgr {
> > + struct list_head list;
> > struct l2cap_conn *l2cap_conn;
> > struct l2cap_chan *a2mp_chan;
> > struct kref kref;
> > __u8 ident;
> > __u8 handle;
> > + enum {
> > + READ_LOC_AMP_INFO,
> > + } state;
>
> I am not a huge fan of these things. Wouldn't it be better to define the
> states externally properly.
Yes, this might be done.
Best regards
Andrei Emeltchenko
^ permalink raw reply
* [PATCH v2 0/2] Bluetooth: broadcom patchram firmware loader
From: Jesse Sung @ 2012-09-18 9:49 UTC (permalink / raw)
To: linux-bluetooth, Marcel Holtmann
From: Wen-chien Jesse Sung <jesse.sung@canonical.com>
There is an user space firmware loading tool which can be found at
http://marc.info/?l=linux-bluetooth&m=132039175324993&w=2
This tool requires hci device to do the firmware loading, but this
may cause some race condition between patchram tool and bluetoothd
or something that also works on hci interface.
Also it needs some hooks to make firmware loads after bootup, s3,
s4, rfkill, and device hotplug events. Implement this loader in kernel
module would make things more easier.
Wen-chien Jesse Sung (2):
Introduced a load_firmware callback to struct hci_dev
broadcom patchram firmware loader
drivers/bluetooth/btusb.c | 75 +++++++++++++++++++++++++++++++++++++-
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_core.c | 2 +
3 files changed, 76 insertions(+), 2 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [PATCH v2 1/2] Bluetooth: Introduced a load_firmware callback to struct hci_dev
From: Jesse Sung @ 2012-09-18 9:49 UTC (permalink / raw)
To: linux-bluetooth, Marcel Holtmann
In-Reply-To: <cover.1347959921.git.jesse.sung@canonical.com>
From: Wen-chien Jesse Sung <jesse.sung@canonical.com>
load_firmware will be called at the end of hci_dev_open() if it
is defined.
Signed-off-by: Wen-chien Jesse Sung <jesse.sung@canonical.com>
---
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_core.c | 2 ++
2 files changed, 3 insertions(+)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 593cd1d..40972a3 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -281,6 +281,7 @@ struct hci_dev {
int (*send)(struct sk_buff *skb);
void (*notify)(struct hci_dev *hdev, unsigned int evt);
int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
+ void (*load_firmware)(struct hci_dev *hdev);
};
struct hci_conn {
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index d4de5db..49be87a 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -725,6 +725,8 @@ int hci_dev_open(__u16 dev)
done:
hci_req_unlock(hdev);
hci_dev_put(hdev);
+ if (!ret && hdev->load_firmware)
+ hdev->load_firmware(hdev);
return ret;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 2/2] Bluetooth: broadcom patchram firmware loader
From: Jesse Sung @ 2012-09-18 9:49 UTC (permalink / raw)
To: linux-bluetooth, Marcel Holtmann
In-Reply-To: <cover.1347959921.git.jesse.sung@canonical.com>
From: Wen-chien Jesse Sung <jesse.sung@canonical.com>
There is an user space firmware loading tool which can be found at
http://marc.info/?l=linux-bluetooth&m=132039175324993&w=2
This tool requires hci device to do the firmware loading, but this
may cause some race condition between patchram tool and bluetoothd
or something that also works on hci interface.
Also it needs some hooks to make firmware loads after bootup, s3,
s4, rfkill, and device hotplug events. Implement this loader in kernel
module would make things more easier.
The supported firmware is in hcd format, which is a collection of
hci commands. The download process would be:
1. reset command
2. download command
3. firmware image in hcd file
4. reset command
/sys/kernel/debug/usb/devices before loading firmware:
T: Bus=01 Lev=02 Prnt=02 Port=04 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=0a5c ProdID=21d3 Rev= 1.12
S: Manufacturer=Broadcom Corp
S: Product=BCM43142A0
S: SerialNumber=3859F9D6199A
C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr= 0mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
/sys/kernel/debug/usb/devices after loading firmware:
T: Bus=01 Lev=02 Prnt=02 Port=04 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=0a5c ProdID=21d3 Rev= 1.12
S: Manufacturer=Broadcom Corp
S: Product=BCM43142A0
S: SerialNumber=3859F9D6199A
C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr= 0mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
Signed-off-by: Wen-chien Jesse Sung <jesse.sung@canonical.com>
---
drivers/bluetooth/btusb.c | 75 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 73 insertions(+), 2 deletions(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index fbfb069..408a5c6 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -23,6 +23,8 @@
#include <linux/module.h>
#include <linux/usb.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -47,6 +49,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_BROKEN_ISOC 0x20
#define BTUSB_WRONG_SCO_MTU 0x40
#define BTUSB_ATH3012 0x80
+#define BTUSB_BCM_PATCHRAM 0x100
static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -97,13 +100,13 @@ static struct usb_device_id btusb_table[] = {
/* Broadcom BCM20702A0 */
{ USB_DEVICE(0x0489, 0xe042) },
- { USB_DEVICE(0x413c, 0x8197) },
+ { USB_DEVICE(0x413c, 0x8197), .driver_info = BTUSB_BCM_PATCHRAM },
/* Foxconn - Hon Hai */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
/*Broadcom devices with vendor specific id */
- { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
+ { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01), .driver_info = BTUSB_BCM_PATCHRAM },
{ } /* Terminating entry */
};
@@ -204,12 +207,14 @@ static struct usb_device_id blacklist_table[] = {
#define BTUSB_ISOC_RUNNING 2
#define BTUSB_SUSPENDING 3
#define BTUSB_DID_ISO_RESUME 4
+#define BTUSB_FIRMWARE_DONE 5
struct btusb_data {
struct hci_dev *hdev;
struct usb_device *udev;
struct usb_interface *intf;
struct usb_interface *isoc;
+ const struct usb_device_id *id;
spinlock_t lock;
@@ -914,6 +919,69 @@ static void btusb_waker(struct work_struct *work)
usb_autopm_put_interface(data->intf);
}
+#define PATCHRAM_TIMEOUT 1000
+#define PATCHRAM_NAME_LEN 20
+
+static void btusb_load_firmware(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ struct usb_device *udev = data->udev;
+ const struct usb_device_id *id = data->id;
+ size_t pos = 0;
+ int err = 0;
+ char filename[PATCHRAM_NAME_LEN];
+ const struct firmware *fw;
+
+ unsigned char reset_cmd[] = { 0x03, 0x0c, 0x00 };
+ unsigned char download_cmd[] = { 0x2e, 0xfc, 0x00 };
+
+ if (!(id->driver_info & BTUSB_BCM_PATCHRAM))
+ return;
+ if (test_and_set_bit(BTUSB_FIRMWARE_DONE, &data->flags))
+ return;
+
+ snprintf(filename, PATCHRAM_NAME_LEN, "fw-%04x_%04x.hcd",
+ id->idVendor, id->idProduct);
+ if (request_firmware(&fw, (const char *) filename, &udev->dev) < 0) {
+ BT_INFO("can't load firmware, may not work correctly");
+ return;
+ }
+
+ if (usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, USB_TYPE_CLASS, 0, 0,
+ reset_cmd, sizeof(reset_cmd), PATCHRAM_TIMEOUT) < 0) {
+ err = -1;
+ goto out;
+ }
+ msleep(300);
+
+ if (usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, USB_TYPE_CLASS, 0, 0,
+ download_cmd, sizeof(download_cmd), PATCHRAM_TIMEOUT) < 0) {
+ err = -1;
+ goto out;
+ }
+ msleep(300);
+
+ while (pos < fw->size) {
+ size_t len;
+ len = fw->data[pos + 2] + 3;
+ if ((pos + len > fw->size) ||
+ (usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0,
+ USB_TYPE_CLASS, 0, 0, (void *)fw->data + pos, len,
+ PATCHRAM_TIMEOUT) < 0)) {
+ err = -1;
+ goto out;
+ }
+ pos += len;
+ }
+
+ err = (usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, USB_TYPE_CLASS, 0, 0,
+ reset_cmd, sizeof(reset_cmd), PATCHRAM_TIMEOUT) < 0);
+out:
+ if (err)
+ BT_INFO("fail to load firmware, may not work correctly");
+ release_firmware(fw);
+}
+
static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -1001,6 +1069,8 @@ static int btusb_probe(struct usb_interface *intf,
init_usb_anchor(&data->isoc_anchor);
init_usb_anchor(&data->deferred);
+ data->id = id;
+
hdev = hci_alloc_dev();
if (!hdev) {
kfree(data);
@@ -1019,6 +1089,7 @@ static int btusb_probe(struct usb_interface *intf,
hdev->flush = btusb_flush;
hdev->send = btusb_send_frame;
hdev->notify = btusb_notify;
+ hdev->load_firmware = btusb_load_firmware;
/* Interface numbers are hardcoded in the specification */
data->isoc = usb_ifnum_to_if(data->udev, 1);
--
1.7.9.5
^ permalink raw reply related
* hstest fails in Android
From: Ahmed Abdelfattah @ 2012-09-18 13:26 UTC (permalink / raw)
To: linux-bluetooth
Hello all,
I am testing a Bluetooth chip on Android . Now, I am in the phase of
testing audio connection functionality but it's failing.I ran hstest
with piantronics Bluetooth headset and the problem seems to happen
after a Parameter Negotiation command to the HS, the HS doesn't reply
with PN RSP but instead with DM and then disconnects what could be .
The same test works fine on ubuntu 11.10 so I am sure the headset is
ok. What could be a possible reason for this behavior ?
Here is hcidump log:
< HCI Command: Read Voice Setting (0x03|0x0025) plen 0
> HCI Event: Command Complete (0x0e) plen 6
Read Voice Setting (0x03|0x0025) ncmd 5
status 0x00 voice setting 0x0060
< HCI Command: Create Connection (0x01|0x0005) plen 13
bdaddr 00:23:7F:EB:4F:10 ptype 0xcc18 rswitch 0x01 clkoffset 0x0000
Packet type: DM1 DM3 DM5 DH1 DH3 DH5
> HCI Event: Command Status (0x0f) plen 4
Create Connection (0x01|0x0005) status 0x00 ncmd 5
> HCI Event: Connect Complete (0x03) plen 11
status 0x00 handle 128 bdaddr 00:23:7F:EB:4F:10 type ACL encrypt 0x00
< HCI Command: Read Remote Supported Features (0x01|0x001b) plen 2
handle 128
> HCI Event: Command Status (0x0f) plen 4
Read Remote Supported Features (0x01|0x001b) status 0x00 ncmd 5
> HCI Event: Read Remote Supported Features (0x0b) plen 11
status 0x00 handle 128
Features: 0xbc 0xec 0x01 0x00 0x18 0x18 0x00 0x00
< HCI Command: Remote Name Request (0x01|0x0019) plen 10
bdaddr 00:23:7F:EB:4F:10 mode 2 clkoffset 0x0000
< ACL data: handle 128 flags 0x00 dlen 10
L2CAP(s): Info req: type 2
> HCI Event: Command Status (0x0f) plen 4
Remote Name Request (0x01|0x0019) status 0x00 ncmd 5
> HCI Event: Number of Completed Packets (0x13) plen 5
handle 128 packets 1
> ACL data: handle 128 flags 0x02 dlen 16
L2CAP(s): Info rsp: type 2 result 0
Extended feature mask 0x0000
< ACL data: handle 128 flags 0x00 dlen 12
L2CAP(s): Connect req: psm 3 scid 0x0040
> HCI Event: Number of Completed Packets (0x13) plen 5
handle 128 packets 1
> HCI Event: Remote Name Req Complete (0x07) plen 255
status 0x00 bdaddr 00:23:7F:EB:4F:10 name 'PLT_MLXX'
> ACL data: handle 128 flags 0x02 dlen 16
L2CAP(s): Connect rsp: dcid 0x004c scid 0x0040 result 1 status 2
Connection pending - Authorization pending
> HCI Event: Link Key Request (0x17) plen 6
bdaddr 00:23:7F:EB:4F:10
< HCI Command: Link Key Request Reply (0x01|0x000b) plen 22
bdaddr 00:23:7F:EB:4F:10 key 81305E3AB5D0447783B7079E1E107374
> HCI Event: Command Complete (0x0e) plen 10
Link Key Request Reply (0x01|0x000b) ncmd 5
status 0x00 bdaddr 00:23:7F:EB:4F:10
> ACL data: handle 128 flags 0x02 dlen 16
L2CAP(s): Connect rsp: dcid 0x004c scid 0x0040 result 0 status 0
Connection successful
< ACL data: handle 128 flags 0x00 dlen 16
L2CAP(s): Config req: dcid 0x004c flags 0x00 clen 4
MTU 1013
> HCI Event: Number of Completed Packets (0x13) plen 5
handle 128 packets 1
> ACL data: handle 128 flags 0x02 dlen 14
L2CAP(s): Config rsp: scid 0x0040 flags 0x00 result 0 clen 0
Success
> ACL data: handle 128 flags 0x02 dlen 16
L2CAP(s): Config req: dcid 0x0040 flags 0x00 clen 4
MTU 1013
< ACL data: handle 128 flags 0x00 dlen 18
L2CAP(s): Config rsp: scid 0x004c flags 0x00 result 0 clen 4
MTU 1013
< ACL data: handle 128 flags 0x00 dlen 8
L2CAP(d): cid 0x004c len 4 [psm 3]
RFCOMM(s): SABM: cr 1 dlci 0 pf 1 ilen 0 fcs 0x1c
> HCI Event: Number of Completed Packets (0x13) plen 5
handle 128 packets 1
> HCI Event: Number of Completed Packets (0x13) plen 5
handle 128 packets 1
> ACL data: handle 128 flags 0x02 dlen 8
L2CAP(d): cid 0x0040 len 4 [psm 3]
RFCOMM(s): UA: cr 1 dlci 0 pf 1 ilen 0 fcs 0xd7
< ACL data: handle 128 flags 0x00 dlen 18
L2CAP(d): cid 0x004c len 14 [psm 3]
RFCOMM(s): PN CMD: cr 1 dlci 0 pf 0 ilen 10 fcs 0x70 mcc_len 8
dlci 12 frame_type 0 credit_flow 15 pri 7 ack_timer 0
frame_size 1008 max_retrans 0 credits 7
> HCI Event: Number of Completed Packets (0x13) plen 5
handle 128 packets 1
> ACL data: handle 128 flags 0x02 dlen 8
L2CAP(d): cid 0x0040 len 4 [psm 3]
RFCOMM(s): DM: cr 1 dlci 12 pf 1 ilen 0 fcs 0x69
< ACL data: handle 128 flags 0x00 dlen 8
L2CAP(d): cid 0x004c len 4 [psm 3]
RFCOMM(s): DISC: cr 1 dlci 0 pf 1 ilen 0 fcs 0xfd
< ACL data: handle 128 flags 0x00 dlen 12
L2CAP(s): Disconn req: dcid 0x004c scid 0x0040
> HCI Event: Number of Completed Packets (0x13) plen 5
handle 128 packets 1
> HCI Event: Number of Completed Packets (0x13) plen 5
handle 128 packets 1
> ACL data: handle 128 flags 0x02 dlen 8
L2CAP(d): cid 0x0040 len 4 [psm 3]
RFCOMM(s): UA: cr 1 dlci 0 pf 1 ilen 0 fcs 0xd7
> ACL data: handle 128 flags 0x02 dlen 12
L2CAP(s): Disconn rsp: dcid 0x004c scid 0x0040
< HCI Command: Disconnect (0x01|0x0006) plen 3
handle 128 reason 0x13
Reason: Remote User Terminated Connection
> HCI Event: Command Status (0x0f) plen 4
Disconnect (0x01|0x0006) status 0x00 ncmd 5
> HCI Event: Disconn Complete (0x05) plen 4
status 0x00 handle 128 reason 0x16
Reason: Connection Terminated by Local Host
--
regards ,
Ahmed Abdelfattah
^ permalink raw reply
* [PATCHv6 00/17] Bluetooth: Create AMP physical link
From: Andrei Emeltchenko @ 2012-09-18 14:28 UTC (permalink / raw)
To: linux-bluetooth; +Cc: mathewm, gustavo, marcel
In-Reply-To: <1347437192-24694-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
This set of patches enhances A2MP protocol and creates physical
link between AMP controllers. This is further iteration towards
Bluetooth High Speed.
Changes:
* p6: Refactoring: moving code from pal.[ch] to amp.[ch]
* p5: Fix issues reported by Mat in mailing list review
* p4: Rebased against recent bluetooth-next, minor fixes
* p3: Use hci_conn for representing physical link(type AMP_LINK) instead of
struct phy_link, refactoring.
* p2: Remove HCI callbacks and use amp_mgr global list, refactor code.
* p1: Fixed locking issues, added basic logical link preparation.
* v3: Remove workqueue from callback processing; change callback functions
names according to reviewers recommendations; create global amp_mgr_list to
have lookup to amp manager, physical and logical links so for those HCI events
which might be identified by __handler__ we have lookup; remove extensive
hexdump from gen_amp_key.
* v2: Fix typos and bugs, add functionality: now physical connection
might be established.
* v1: Fix typos, change debug prints, refactor code for better
splitting functionality.
Andrei Emeltchenko (16):
Bluetooth: Add HCI logical link cmds definitions
Bluetooth: A2MP: Create amp_mgr global list
Bluetooth: AMP: Use HCI cmd to Read AMP Info
Bluetooth: AMP: Use HCI cmd to Read Loc AMP Assoc
Bluetooth: A2MP: Process Discover Response
Bluetooth: AMP: Physical link struct and heplers
Bluetooth: AMP: Remote AMP ctrl definitions
Bluetooth: AMP: Handle create / disc phylink req
Bluetooth: A2MP: Process A2MP Getinfo Rsp
Bluetooth: A2MP: Process A2MP Get AMP Assoc Rsp
Bluetooth: Choose connection based on capabilities
Bluetooth: AMP: Add AMP key calculation
Bluetooth: AMP: Create Physical Link
Bluetooth: AMP: Write remote AMP Assoc
Bluetooth: A2MP: Add fallback to normal l2cap init sequence
Bluetooth: AMP: Process Chan Selected event
Dmitry Kasatkin (1):
Bluetooth: Add function to derive AMP key using hmac
include/net/bluetooth/a2mp.h | 22 ++
include/net/bluetooth/amp.h | 47 +++++
include/net/bluetooth/hci.h | 39 +++-
include/net/bluetooth/hci_core.h | 11 +
include/net/bluetooth/l2cap.h | 4 +
net/bluetooth/Kconfig | 1 +
net/bluetooth/Makefile | 2 +-
net/bluetooth/a2mp.c | 423 +++++++++++++++++++++++++++++++++++---
net/bluetooth/amp.c | 348 +++++++++++++++++++++++++++++++
net/bluetooth/hci_event.c | 106 +++++++++-
net/bluetooth/l2cap_core.c | 35 +++-
11 files changed, 1000 insertions(+), 38 deletions(-)
create mode 100644 include/net/bluetooth/amp.h
create mode 100644 net/bluetooth/amp.c
--
1.7.9.5
^ permalink raw reply
* [PATCHv6 01/17] Bluetooth: Add HCI logical link cmds definitions
From: Andrei Emeltchenko @ 2012-09-18 14:28 UTC (permalink / raw)
To: linux-bluetooth; +Cc: mathewm, gustavo, marcel
In-Reply-To: <1347978509-12133-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/hci.h | 36 +++++++++++++++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 0f28f70..42aae18 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -556,12 +556,46 @@ struct hci_cp_accept_phy_link {
__u8 key[HCI_AMP_LINK_KEY_SIZE];
} __packed;
-#define HCI_OP_DISCONN_PHY_LINK 0x0437
+#define HCI_OP_DISCONN_PHY_LINK 0x0437
struct hci_cp_disconn_phy_link {
__u8 phy_handle;
__u8 reason;
} __packed;
+struct ext_flow_spec {
+ __u8 id;
+ __u8 stype;
+ __le16 msdu;
+ __le32 sdu_itime;
+ __le32 acc_lat;
+ __le32 flush_to;
+} __packed;
+
+#define HCI_OP_CREATE_LOGICAL_LINK 0x0438
+#define HCI_OP_ACCEPT_LOGICAL_LINK 0x0439
+struct hci_cp_create_accept_logical_link {
+ __u8 phy_handle;
+ struct ext_flow_spec tx_flow_spec;
+ struct ext_flow_spec rx_flow_spec;
+} __packed;
+
+#define HCI_OP_DISCONN_LOGICAL_LINK 0x043a
+struct hci_cp_disconn_logical_link {
+ __le16 log_handle;
+} __packed;
+
+#define HCI_OP_LOGICAL_LINK_CANCEL 0x043b
+struct hci_cp_logical_link_cancel {
+ __u8 phy_handle;
+ __u8 flow_spec_id;
+} __packed;
+
+struct hci_rp_logical_link_cancel {
+ __u8 status;
+ __u8 phy_handle;
+ __u8 flow_spec_id;
+} __packed;
+
#define HCI_OP_SNIFF_MODE 0x0803
struct hci_cp_sniff_mode {
__le16 handle;
--
1.7.9.5
^ permalink raw reply related
* [PATCHv6 02/17] Bluetooth: A2MP: Create amp_mgr global list
From: Andrei Emeltchenko @ 2012-09-18 14:28 UTC (permalink / raw)
To: linux-bluetooth; +Cc: mathewm, gustavo, marcel
In-Reply-To: <1347978509-12133-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Create amp_mgr_list global list which will be used by different
hci devices to find amp_mgr.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/a2mp.h | 10 ++++++++++
net/bluetooth/a2mp.c | 29 +++++++++++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index 6a76e0a..316c1c8 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -19,12 +19,18 @@
#define A2MP_FEAT_EXT 0x8000
+enum amp_mgr_state {
+ READ_LOC_AMP_INFO,
+};
+
struct amp_mgr {
+ struct list_head list;
struct l2cap_conn *l2cap_conn;
struct l2cap_chan *a2mp_chan;
struct kref kref;
__u8 ident;
__u8 handle;
+ enum amp_mgr_state state;
unsigned long flags;
};
@@ -118,9 +124,13 @@ struct a2mp_physlink_rsp {
#define A2MP_STATUS_PHYS_LINK_EXISTS 0x05
#define A2MP_STATUS_SECURITY_VIOLATION 0x06
+extern struct list_head amp_mgr_list;
+extern struct mutex amp_mgr_list_lock;
+
void amp_mgr_get(struct amp_mgr *mgr);
int amp_mgr_put(struct amp_mgr *mgr);
struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
struct sk_buff *skb);
+struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
#endif /* __A2MP_H */
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 0760d1f..3f93060 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -17,6 +17,10 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/a2mp.h>
+/* Global AMP Manager list */
+LIST_HEAD(amp_mgr_list);
+DEFINE_MUTEX(amp_mgr_list_lock);
+
/* A2MP build & send command helper functions */
static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
{
@@ -516,6 +520,10 @@ static void amp_mgr_destroy(struct kref *kref)
BT_DBG("mgr %p", mgr);
+ mutex_lock(&_mgr_list_lock);
+ list_del(&mgr->list);
+ mutex_unlock(&_mgr_list_lock);
+
kfree(mgr);
}
@@ -552,6 +560,10 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
kref_init(&mgr->kref);
+ mutex_lock(&_mgr_list_lock);
+ list_add(&mgr->list, &_mgr_list);
+ mutex_unlock(&_mgr_list_lock);
+
return mgr;
}
@@ -570,3 +582,20 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
return mgr->a2mp_chan;
}
+
+struct amp_mgr *amp_mgr_lookup_by_state(u8 state)
+{
+ struct amp_mgr *mgr;
+
+ mutex_lock(&_mgr_list_lock);
+ list_for_each_entry(mgr, &_mgr_list, list) {
+ if (mgr->state == state) {
+ amp_mgr_get(mgr);
+ mutex_unlock(&_mgr_list_lock);
+ return mgr;
+ }
+ }
+ mutex_unlock(&_mgr_list_lock);
+
+ return NULL;
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCHv6 03/17] Bluetooth: AMP: Use HCI cmd to Read AMP Info
From: Andrei Emeltchenko @ 2012-09-18 14:28 UTC (permalink / raw)
To: linux-bluetooth; +Cc: mathewm, gustavo, marcel
In-Reply-To: <1347978509-12133-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When receiving A2MP Get Info Request execute Read Local AMP Info HCI
command to AMP controller with function to be executed upon receiving
command complete event. Function will handle A2MP Get Info Response.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/a2mp.h | 2 ++
net/bluetooth/a2mp.c | 57 ++++++++++++++++++++++++++++++------------
net/bluetooth/hci_event.c | 6 ++++-
3 files changed, 48 insertions(+), 17 deletions(-)
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index 316c1c8..af59468 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -132,5 +132,7 @@ int amp_mgr_put(struct amp_mgr *mgr);
struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
struct sk_buff *skb);
struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
+void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
+void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
#endif /* __A2MP_H */
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 3f93060..0e97b3b 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -41,8 +41,7 @@ static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
return cmd;
}
-static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len,
- void *data)
+void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
{
struct l2cap_chan *chan = mgr->a2mp_chan;
struct a2mp_cmd *cmd;
@@ -185,7 +184,6 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_cmd *hdr)
{
struct a2mp_info_req *req = (void *) skb->data;
- struct a2mp_info_rsp rsp;
struct hci_dev *hdev;
if (le16_to_cpu(hdr->len) < sizeof(*req))
@@ -193,23 +191,23 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
BT_DBG("id %d", req->id);
- rsp.id = req->id;
- rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
-
hdev = hci_dev_get(req->id);
- if (hdev && hdev->amp_type != HCI_BREDR) {
- rsp.status = 0;
- rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
- rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);
- rsp.min_latency = cpu_to_le32(hdev->amp_min_latency);
- rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap);
- rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size);
+ if (!hdev) {
+ struct a2mp_info_rsp rsp;
+
+ rsp.id = req->id;
+ rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+ a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp),
+ &rsp);
}
- if (hdev)
- hci_dev_put(hdev);
+ if (hdev->dev_type != HCI_BREDR) {
+ mgr->state = READ_LOC_AMP_INFO;
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL);
+ }
- a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp), &rsp);
+ hci_dev_put(hdev);
skb_pull(skb, sizeof(*req));
return 0;
@@ -599,3 +597,30 @@ struct amp_mgr *amp_mgr_lookup_by_state(u8 state)
return NULL;
}
+
+void a2mp_send_getinfo_rsp(struct hci_dev *hdev)
+{
+ struct amp_mgr *mgr;
+ struct a2mp_info_rsp rsp;
+
+ mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_INFO);
+ if (!mgr)
+ return;
+
+ BT_DBG("%s mgr %p", hdev->name, mgr);
+
+ rsp.id = hdev->id;
+ rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+ if (hdev->amp_type != HCI_BREDR) {
+ rsp.status = 0;
+ rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
+ rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);
+ rsp.min_latency = cpu_to_le32(hdev->amp_min_latency);
+ rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap);
+ rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size);
+ }
+
+ a2mp_send(mgr, A2MP_GETINFO_RSP, mgr->ident, sizeof(rsp), &rsp);
+ amp_mgr_put(mgr);
+}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 48d7302..5ae5121 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -30,6 +30,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/mgmt.h>
+#include <net/bluetooth/a2mp.h>
/* Handle HCI Event packets */
@@ -846,7 +847,7 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
if (rp->status)
- return;
+ goto a2mp_rsp;
hdev->amp_status = rp->amp_status;
hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
@@ -860,6 +861,9 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
+
+a2mp_rsp:
+ a2mp_send_getinfo_rsp(hdev);
}
static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
--
1.7.9.5
^ permalink raw reply related
* [PATCHv6 04/17] Bluetooth: AMP: Use HCI cmd to Read Loc AMP Assoc
From: Andrei Emeltchenko @ 2012-09-18 14:28 UTC (permalink / raw)
To: linux-bluetooth; +Cc: mathewm, gustavo, marcel
In-Reply-To: <1347978509-12133-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When receiving A2MP Get AMP Assoc Request execute Read Local AMP Assoc
HCI command to AMP controller. If the AMP Assoc data is larger then it
can fit to HCI event only fragment is read. When all fragments are read
send A2MP Get AMP Assoc Response.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/a2mp.h | 2 ++
include/net/bluetooth/amp.h | 21 ++++++++++++++
include/net/bluetooth/hci.h | 2 ++
include/net/bluetooth/hci_core.h | 8 ++++++
net/bluetooth/Makefile | 2 +-
net/bluetooth/a2mp.c | 56 ++++++++++++++++++++++++++++++++++----
net/bluetooth/amp.c | 45 ++++++++++++++++++++++++++++++
net/bluetooth/hci_event.c | 41 ++++++++++++++++++++++++++++
8 files changed, 171 insertions(+), 6 deletions(-)
create mode 100644 include/net/bluetooth/amp.h
create mode 100644 net/bluetooth/amp.c
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index af59468..d547671 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -21,6 +21,7 @@
enum amp_mgr_state {
READ_LOC_AMP_INFO,
+ READ_LOC_AMP_ASSOC,
};
struct amp_mgr {
@@ -134,5 +135,6 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
+void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
#endif /* __A2MP_H */
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
new file mode 100644
index 0000000..e861675
--- /dev/null
+++ b/include/net/bluetooth/amp.h
@@ -0,0 +1,21 @@
+/*
+ Copyright (c) 2011,2012 Intel Corp.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 and
+ only version 2 as published by the Free Software Foundation.
+
+ 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.
+*/
+
+#ifndef __AMP_H
+#define __AMP_H
+
+void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
+void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
+
+#endif /* __AMP_H */
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 42aae18..1cb8b55 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -33,6 +33,8 @@
#define HCI_LINK_KEY_SIZE 16
#define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE)
+#define HCI_MAX_AMP_ASSOC_SIZE 672
+
/* HCI dev events */
#define HCI_DEV_REG 1
#define HCI_DEV_UNREG 2
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6a3337e..1174218 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -124,6 +124,12 @@ struct le_scan_params {
#define HCI_MAX_SHORT_NAME_LENGTH 10
+struct amp_assoc {
+ __u16 len;
+ __u16 offset;
+ __u8 data[HCI_MAX_AMP_ASSOC_SIZE];
+};
+
#define NUM_REASSEMBLY 4
struct hci_dev {
struct list_head list;
@@ -177,6 +183,8 @@ struct hci_dev {
__u32 amp_max_flush_to;
__u32 amp_be_flush_to;
+ struct amp_assoc loc_assoc;
+
__u8 flow_ctl_mode;
unsigned int auto_accept_delay;
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index fa6d94a..dea6a28 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -10,4 +10,4 @@ obj-$(CONFIG_BT_HIDP) += hidp/
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
- a2mp.o
+ a2mp.o amp.o
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 0e97b3b..7140061 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -16,6 +16,7 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
/* Global AMP Manager list */
LIST_HEAD(amp_mgr_list);
@@ -218,26 +219,37 @@ static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb,
{
struct a2mp_amp_assoc_req *req = (void *) skb->data;
struct hci_dev *hdev;
+ struct amp_mgr *tmp;
if (le16_to_cpu(hdr->len) < sizeof(*req))
return -EINVAL;
BT_DBG("id %d", req->id);
+ /* Make sure that other request is not processed */
+ tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
+
hdev = hci_dev_get(req->id);
- if (!hdev || hdev->amp_type == HCI_BREDR) {
+ if (!hdev || hdev->amp_type == HCI_BREDR || tmp) {
struct a2mp_amp_assoc_rsp rsp;
rsp.id = req->id;
- rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+ if (tmp) {
+ rsp.status = A2MP_STATUS_COLLISION_OCCURED;
+ amp_mgr_put(tmp);
+ } else {
+ rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+ }
a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, hdr->ident, sizeof(rsp),
&rsp);
- goto clean;
+
+ goto done;
}
- /* Placeholder for HCI Read AMP Assoc */
+ amp_read_loc_assoc(hdev, mgr);
-clean:
+done:
if (hdev)
hci_dev_put(hdev);
@@ -624,3 +636,37 @@ void a2mp_send_getinfo_rsp(struct hci_dev *hdev)
a2mp_send(mgr, A2MP_GETINFO_RSP, mgr->ident, sizeof(rsp), &rsp);
amp_mgr_put(mgr);
}
+
+void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status)
+{
+ struct amp_mgr *mgr;
+ struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+ struct a2mp_amp_assoc_rsp *rsp;
+ size_t len;
+
+ mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
+ if (!mgr)
+ return;
+
+ BT_DBG("%s mgr %p", hdev->name, mgr);
+
+ len = sizeof(struct a2mp_amp_assoc_rsp) + loc_assoc->len;
+ rsp = kzalloc(len, GFP_KERNEL);
+ if (!rsp) {
+ amp_mgr_put(mgr);
+ return;
+ }
+
+ rsp->id = hdev->id;
+
+ if (status) {
+ rsp->status = A2MP_STATUS_INVALID_CTRL_ID;
+ } else {
+ rsp->status = A2MP_STATUS_SUCCESS;
+ memcpy(rsp->amp_assoc, loc_assoc->data, loc_assoc->len);
+ }
+
+ a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, mgr->ident, len, rsp);
+ amp_mgr_put(mgr);
+ kfree(rsp);
+}
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
new file mode 100644
index 0000000..2d4e79e
--- /dev/null
+++ b/net/bluetooth/amp.c
@@ -0,0 +1,45 @@
+/*
+ Copyright (c) 2011,2012 Intel Corp.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 and
+ only version 2 as published by the Free Software Foundation.
+
+ 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.
+*/
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
+
+void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle)
+{
+ struct hci_cp_read_local_amp_assoc cp;
+ struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+
+ BT_DBG("%s handle %d", hdev->name, phy_handle);
+
+ cp.phy_handle = phy_handle;
+ cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+ cp.len_so_far = cpu_to_le16(loc_assoc->offset);
+
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+}
+
+void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
+{
+ struct hci_cp_read_local_amp_assoc cp;
+
+ memset(&hdev->loc_assoc, 0, sizeof(struct amp_assoc));
+ memset(&cp, 0, sizeof(cp));
+
+ cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+
+ mgr->state = READ_LOC_AMP_ASSOC;
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 5ae5121..6cc44cf 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -31,6 +31,7 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/mgmt.h>
#include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
/* Handle HCI Event packets */
@@ -866,6 +867,42 @@ a2mp_rsp:
a2mp_send_getinfo_rsp(hdev);
}
+static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
+ struct amp_assoc *assoc = &hdev->loc_assoc;
+ size_t rem_len, frag_len;
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+ if (rp->status)
+ goto a2mp_rsp;
+
+ frag_len = skb->len - sizeof(*rp);
+ rem_len = __le16_to_cpu(rp->rem_len);
+
+ if (rem_len > frag_len) {
+ BT_DBG("frag_len %d rem_len %d", frag_len, rem_len);
+
+ memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
+ assoc->offset += frag_len;
+
+ /* Read other fragments */
+ amp_read_loc_assoc_frag(hdev, rp->phy_handle);
+
+ return;
+ }
+
+ memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
+ assoc->len = assoc->offset + rem_len;
+ assoc->offset = 0;
+
+a2mp_rsp:
+ /* Send A2MP Rsp when all fragments are received */
+ a2mp_send_getampassoc_rsp(hdev, rp->status);
+}
+
static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
struct sk_buff *skb)
{
@@ -2302,6 +2339,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cc_read_local_amp_info(hdev, skb);
break;
+ case HCI_OP_READ_LOCAL_AMP_ASSOC:
+ hci_cc_read_local_amp_assoc(hdev, skb);
+ break;
+
case HCI_OP_DELETE_STORED_LINK_KEY:
hci_cc_delete_stored_link_key(hdev, skb);
break;
--
1.7.9.5
^ 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