* [PATCH 4/4] Add proper tracking mechanism to NREC
From: Luiz Augusto von Dentz @ 2011-01-18 10:00 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1295344815-1404-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
NREC may change during the connections so it has to be tracked in order
to signal changes to applications.
---
audio/headset.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
audio/headset.h | 6 +++++
audio/transport.c | 17 ++++++++++++++
3 files changed, 84 insertions(+), 1 deletions(-)
diff --git a/audio/headset.c b/audio/headset.c
index 53a594d..62596c4 100644
--- a/audio/headset.c
+++ b/audio/headset.c
@@ -109,6 +109,12 @@ struct headset_state_callback {
unsigned int id;
};
+struct headset_nrec_callback {
+ unsigned int id;
+ headset_nrec_cb cb;
+ void *user_data;
+};
+
struct connect_cb {
unsigned int id;
headset_stream_cb_t cb;
@@ -137,6 +143,7 @@ struct headset_slc {
gboolean inband_ring;
gboolean nrec;
gboolean nrec_req;
+ GSList *nrec_cbs;
int sp_gain;
int mic_gain;
@@ -1096,8 +1103,17 @@ int telephony_nr_and_ec_rsp(void *telephony_device, cme_error_t err)
struct headset *hs = device->headset;
struct headset_slc *slc = hs->slc;
- if (err == CME_ERROR_NONE)
+ if (err == CME_ERROR_NONE) {
+ GSList *l;
+
+ for (l = slc->nrec_cbs; l; l = l->next) {
+ struct headset_nrec_callback *nrec_cb = l->data;
+
+ nrec_cb->cb(device, slc->nrec_req, nrec_cb->user_data);
+ }
+
slc->nrec = hs->slc->nrec_req;
+ }
return telephony_generic_rsp(telephony_device, err);
}
@@ -2102,6 +2118,9 @@ static int headset_close_rfcomm(struct audio_device *dev)
hs->rfcomm = NULL;
}
+ g_slist_foreach(hs->slc->nrec_cbs, (GFunc) g_free, NULL);
+ g_slist_free(hs->slc->nrec_cbs);
+
g_free(hs->slc);
hs->slc = NULL;
@@ -2638,6 +2657,47 @@ gboolean headset_get_nrec(struct audio_device *dev)
return hs->slc->nrec;
}
+unsigned int headset_add_nrec_cb(struct audio_device *dev,
+ headset_nrec_cb cb, void *user_data)
+{
+ struct headset *hs = dev->headset;
+ struct headset_nrec_callback *nrec_cb;
+ static unsigned int id = 0;
+
+ if (!hs->slc)
+ return 0;
+
+ nrec_cb = g_new(struct headset_nrec_callback, 1);
+ nrec_cb->cb = cb;
+ nrec_cb->user_data = user_data;
+ nrec_cb->id = ++id;
+
+ hs->slc->nrec_cbs = g_slist_prepend(hs->slc->nrec_cbs, nrec_cb);
+
+ return nrec_cb->id;
+}
+
+gboolean headset_remove_nrec_cb(struct audio_device *dev, unsigned int id)
+{
+ struct headset *hs = dev->headset;
+ GSList *l;
+
+ if (!hs->slc)
+ return FALSE;
+
+ for (l = hs->slc->nrec_cbs; l != NULL; l = l->next) {
+ struct headset_nrec_callback *cb = l->data;
+ if (cb && cb->id == id) {
+ hs->slc->nrec_cbs = g_slist_remove(hs->slc->nrec_cbs,
+ cb);
+ g_free(cb);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
gboolean headset_get_inband(struct audio_device *dev)
{
struct headset *hs = dev->headset;
diff --git a/audio/headset.h b/audio/headset.h
index 29dc02c..7ce88c8 100644
--- a/audio/headset.h
+++ b/audio/headset.h
@@ -44,6 +44,9 @@ typedef void (*headset_state_cb) (struct audio_device *dev,
headset_state_t old_state,
headset_state_t new_state,
void *user_data);
+typedef void (*headset_nrec_cb) (struct audio_device *dev,
+ gboolean nrec,
+ void *user_data);
unsigned int headset_add_state_cb(headset_state_cb cb, void *user_data);
gboolean headset_remove_state_cb(unsigned int id);
@@ -90,6 +93,9 @@ int headset_get_channel(struct audio_device *dev);
int headset_get_sco_fd(struct audio_device *dev);
gboolean headset_get_nrec(struct audio_device *dev);
+unsigned int headset_add_nrec_cb(struct audio_device *dev,
+ headset_nrec_cb cb, void *user_data);
+gboolean headset_remove_nrec_cb(struct audio_device *dev, unsigned int id);
gboolean headset_get_inband(struct audio_device *dev);
gboolean headset_get_sco_hci(struct audio_device *dev);
diff --git a/audio/transport.c b/audio/transport.c
index b5a9e48..e2c8237 100644
--- a/audio/transport.c
+++ b/audio/transport.c
@@ -76,6 +76,7 @@ struct media_transport {
uint16_t imtu; /* Transport input mtu */
uint16_t omtu; /* Transport output mtu */
uint16_t delay; /* Transport delay (a2dp only) */
+ unsigned int nrec_id; /* Transport nrec watch (headset only) */
gboolean read_lock;
gboolean write_lock;
gboolean in_use;
@@ -685,6 +686,9 @@ static void media_transport_free(void *data)
if (transport->session)
avdtp_unref(transport->session);
+ if (transport->nrec_id)
+ headset_remove_nrec_cb(transport->device, transport->nrec_id);
+
if (transport->conn)
dbus_connection_unref(transport->conn);
@@ -693,6 +697,16 @@ static void media_transport_free(void *data)
g_free(transport);
}
+static void headset_nrec_changed(struct audio_device *dev, gboolean nrec,
+ void *user_data)
+{
+ struct media_transport *transport = user_data;
+
+ emit_property_changed(transport->conn, transport->path,
+ MEDIA_TRANSPORT_INTERFACE, "NREC",
+ DBUS_TYPE_BOOLEAN, &nrec);
+}
+
struct media_transport *media_transport_create(DBusConnection *conn,
struct media_endpoint *endpoint,
struct audio_device *device,
@@ -728,6 +742,9 @@ struct media_transport *media_transport_create(DBusConnection *conn,
transport->cancel = cancel_headset;
transport->get_properties = get_properties_headset;
transport->set_property = set_property_headset;
+ transport->nrec_id = headset_add_nrec_cb(device,
+ headset_nrec_changed,
+ transport);
} else
goto fail;
--
1.7.1
^ permalink raw reply related
* [PATCH 3/4] Add Routing property to MediaTransport interface
From: Luiz Augusto von Dentz @ 2011-01-18 10:00 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1295344815-1404-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
This should indicate to the endpoint what routing the transport is using
---
audio/transport.c | 4 ++++
doc/media-api.txt | 6 ++++++
2 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/audio/transport.c b/audio/transport.c
index d575590..b5a9e48 100644
--- a/audio/transport.c
+++ b/audio/transport.c
@@ -599,12 +599,16 @@ static void get_properties_headset(struct media_transport *transport,
DBusMessageIter *dict)
{
gboolean nrec, inband;
+ const char *routing;
nrec = headset_get_nrec(transport->device);
dict_append_entry(dict, "NREC", DBUS_TYPE_BOOLEAN, &nrec);
inband = headset_get_inband(transport->device);
dict_append_entry(dict, "InbandRingtone", DBUS_TYPE_BOOLEAN, &inband);
+
+ routing = headset_get_sco_hci(transport->device) ? "HCI" : "PCM";
+ dict_append_entry(dict, "Routing", DBUS_TYPE_STRING, &routing);
}
void transport_get_properties(struct media_transport *transport,
diff --git a/doc/media-api.txt b/doc/media-api.txt
index 92b8b3f..84903d6 100644
--- a/doc/media-api.txt
+++ b/doc/media-api.txt
@@ -152,3 +152,9 @@ Properties object Device [readonly]
Optional. Indicates if the transport support sending
ringtones, this property is only writeable when the
transport was acquired by the sender.
+
+ string Routing [readonly]
+
+ Optional. Indicates where is the transport being routed
+
+ Possible Values: "HCI" or "PCM"
--
1.7.1
^ permalink raw reply related
* [PATCH 2/4] Updade a2dpsink to use new Acquire API
From: Luiz Augusto von Dentz @ 2011-01-18 10:00 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1295344815-1404-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
---
audio/gstavdtpsink.c | 19 +++++++------------
1 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/audio/gstavdtpsink.c b/audio/gstavdtpsink.c
index 95c4811..f3b15b3 100644
--- a/audio/gstavdtpsink.c
+++ b/audio/gstavdtpsink.c
@@ -1281,16 +1281,7 @@ static gboolean gst_avdtp_sink_transport_parse_property(GstAvdtpSink *self,
break;
}
- case DBUS_TYPE_UINT16: {
- uint16_t value;
- dbus_message_iter_get_basic(&variant_i, &value);
-
- if (g_str_equal(key, "OMTU") == TRUE)
- self->data->link_mtu = value;
-
- break;
- }
- case DBUS_TYPE_STRING: {
+ case DBUS_TYPE_STRING: {
const char *value;
dbus_message_iter_get_basic(&variant_i, &value);
@@ -1329,6 +1320,7 @@ static gboolean gst_avdtp_sink_transport_acquire(GstAvdtpSink *self)
DBusError err;
const char *access_type = "w";
int fd;
+ uint16_t imtu, omtu;
dbus_error_init(&err);
@@ -1349,14 +1341,17 @@ static gboolean gst_avdtp_sink_transport_acquire(GstAvdtpSink *self)
goto fail;
if (dbus_message_get_args(reply, &err, DBUS_TYPE_UNIX_FD, &fd,
- DBUS_TYPE_INVALID) == FALSE)
+ DBUS_TYPE_UINT16, &imtu,
+ DBUS_TYPE_UINT16, &omtu,
+ DBUS_TYPE_INVALID) == FALSE)
goto fail;
dbus_message_unref(reply);
self->stream = g_io_channel_unix_new(fd);
g_io_channel_set_close_on_unref(self->stream, TRUE);
- GST_DEBUG_OBJECT(self, "stream_fd=%d", fd);
+ self->data->link_mtu = omtu;
+ GST_DEBUG_OBJECT(self, "stream_fd=%d mtu=%d", fd, omtu);
return TRUE;
--
1.7.1
^ permalink raw reply related
* [PATCH 1/4] Remove IMTU and OMTU properties and return its values on Acquire reply
From: Luiz Augusto von Dentz @ 2011-01-18 10:00 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
This should make Acquire blocking friendly since the client no longer has
to call GetProperties to discover how much it can write/read when using
the acquired file descriptor.
---
audio/transport.c | 56 +++++++++++++++++++++++++++++++---------------------
doc/media-api.txt | 13 ++---------
2 files changed, 36 insertions(+), 33 deletions(-)
diff --git a/audio/transport.c b/audio/transport.c
index bdec157..d575590 100644
--- a/audio/transport.c
+++ b/audio/transport.c
@@ -181,14 +181,6 @@ static gboolean media_transport_set_fd(struct media_transport *transport,
info("%s: fd(%d) ready", transport->path, fd);
- emit_property_changed(transport->conn, transport->path,
- MEDIA_TRANSPORT_INTERFACE, "IMTU",
- DBUS_TYPE_UINT16, &transport->imtu);
-
- emit_property_changed(transport->conn, transport->path,
- MEDIA_TRANSPORT_INTERFACE, "OMTU",
- DBUS_TYPE_UINT16, &transport->omtu);
-
return TRUE;
}
@@ -209,6 +201,7 @@ static void a2dp_resume_complete(struct avdtp *session,
struct avdtp_stream *stream;
int fd;
uint16_t imtu, omtu;
+ gboolean ret;
req->id = 0;
@@ -219,15 +212,24 @@ static void a2dp_resume_complete(struct avdtp *session,
if (stream == NULL)
goto fail;
- if (avdtp_stream_get_transport(stream, &fd, &imtu, &omtu, NULL) ==
- FALSE)
+ ret = avdtp_stream_get_transport(stream, &fd, &imtu, &omtu, NULL);
+ if (ret == FALSE)
goto fail;
media_transport_set_fd(transport, fd, imtu, omtu);
- if (g_dbus_send_reply(transport->conn, req->msg,
- DBUS_TYPE_UNIX_FD, &fd,
- DBUS_TYPE_INVALID) == FALSE)
+ if (g_strstr_len(owner->accesstype, -1, "r") == NULL)
+ imtu = 0;
+
+ if (g_strstr_len(owner->accesstype, -1, "w") == NULL)
+ omtu = 0;
+
+ ret = g_dbus_send_reply(transport->conn, req->msg,
+ DBUS_TYPE_UNIX_FD, &fd,
+ DBUS_TYPE_UINT16, &imtu,
+ DBUS_TYPE_UINT16, &omtu,
+ DBUS_TYPE_INVALID);
+ if (ret == FALSE)
goto fail;
return;
@@ -282,6 +284,8 @@ static void headset_resume_complete(struct audio_device *dev, void *user_data)
struct acquire_request *req = owner->request;
struct media_transport *transport = owner->transport;
int fd;
+ uint16_t imtu, omtu;
+ gboolean ret;
req->id = 0;
@@ -292,11 +296,23 @@ static void headset_resume_complete(struct audio_device *dev, void *user_data)
if (fd < 0)
goto fail;
- media_transport_set_fd(transport, fd, 48, 48);
+ imtu = 48;
+ omtu = 48;
- if (g_dbus_send_reply(transport->conn, req->msg,
- DBUS_TYPE_UNIX_FD, &fd,
- DBUS_TYPE_INVALID) == FALSE)
+ media_transport_set_fd(transport, fd, imtu, omtu);
+
+ if (g_strstr_len(owner->accesstype, -1, "r") == NULL)
+ imtu = 0;
+
+ if (g_strstr_len(owner->accesstype, -1, "w") == NULL)
+ omtu = 0;
+
+ ret = g_dbus_send_reply(transport->conn, req->msg,
+ DBUS_TYPE_UNIX_FD, &fd,
+ DBUS_TYPE_UINT16, &imtu,
+ DBUS_TYPE_UINT16, &omtu,
+ DBUS_TYPE_INVALID);
+ if (ret == FALSE)
goto fail;
return;
@@ -607,12 +623,6 @@ void transport_get_properties(struct media_transport *transport,
dict_append_entry(&dict, "Device", DBUS_TYPE_OBJECT_PATH,
&transport->device->path);
- dict_append_entry(&dict, "IMTU", DBUS_TYPE_UINT16,
- &transport->imtu);
-
- dict_append_entry(&dict, "OMTU", DBUS_TYPE_UINT16,
- &transport->omtu);
-
uuid = media_endpoint_get_uuid(transport->endpoint);
dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &uuid);
diff --git a/doc/media-api.txt b/doc/media-api.txt
index 5338974..92b8b3f 100644
--- a/doc/media-api.txt
+++ b/doc/media-api.txt
@@ -86,9 +86,10 @@ Methods dict GetProperties()
Returns all properties for the interface. See the
properties section for available properties.
- fd Acquire(string accesstype)
+ fd, uint16, uint16 Acquire(string accesstype)
- Acquire transport file descriptor.
+ Acquire transport file descriptor and the MTU for read
+ and write respectively.
possible accesstype:
@@ -118,14 +119,6 @@ Properties object Device [readonly]
Device object which the transport is connected to.
- uint16 IMTU [readonly]
-
- Transport input MTU.
-
- uint16 OMTU [readonly]
-
- Transport output MTU.
-
string UUID [readonly]
UUID of the profile which the transport is for.
--
1.7.1
^ permalink raw reply related
* [PATCH v5 4/4] bt hidp: Add support for hidraw HIDIOCGFEATURE and HIDIOCSFEATURE
From: Alan Ott @ 2011-01-18 8:04 UTC (permalink / raw)
To: Jiri Kosina, Marcel Holtmann, Gustavo F. Padovan, David S. Miller,
Alan Ott, Michael Poole, Eric Dumazet, linux-input, linux-kernel,
linux-usb, linux-bluetooth, netdev
Cc: Alan Ott
In-Reply-To: <1295337880-12452-1-git-send-email-alan@signal11.us>
This patch adds support or getting and setting feature reports for bluetooth
HID devices from HIDRAW.
Signed-off-by: Alan Ott <alan@signal11.us>
---
net/bluetooth/hidp/core.c | 113 +++++++++++++++++++++++++++++++++++++++++++--
net/bluetooth/hidp/hidp.h | 8 +++
2 files changed, 117 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 5383e6c..6df8ea1 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -36,6 +36,7 @@
#include <linux/file.h>
#include <linux/init.h>
#include <linux/wait.h>
+#include <linux/mutex.h>
#include <net/sock.h>
#include <linux/input.h>
@@ -313,6 +314,86 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
return hidp_queue_report(session, buf, rsize);
}
+static int hidp_get_raw_report(struct hid_device *hid,
+ unsigned char report_number,
+ unsigned char *data, size_t count,
+ unsigned char report_type)
+{
+ struct hidp_session *session = hid->driver_data;
+ struct sk_buff *skb;
+ size_t len;
+ int numbered_reports = hid->report_enum[report_type].numbered;
+
+ switch (report_type) {
+ case HID_FEATURE_REPORT:
+ report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
+ break;
+ case HID_INPUT_REPORT:
+ report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_INPUT;
+ break;
+ case HID_OUTPUT_REPORT:
+ report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_OUPUT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (mutex_lock_interruptible(&session->report_mutex))
+ return -ERESTARTSYS;
+
+ /* Set up our wait, and send the report request to the device. */
+ session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
+ session->waiting_report_number = numbered_reports ? report_number : -1;
+ set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
+ data[0] = report_number;
+ if (hidp_send_ctrl_message(hid->driver_data, report_type, data, 1))
+ goto err_eio;
+
+ /* Wait for the return of the report. The returned report
+ gets put in session->report_return. */
+ while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
+ int res;
+
+ res = wait_event_interruptible_timeout(session->report_queue,
+ !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
+ 5*HZ);
+ if (res == 0) {
+ /* timeout */
+ goto err_eio;
+ }
+ if (res < 0) {
+ /* signal */
+ goto err_restartsys;
+ }
+ }
+
+ skb = session->report_return;
+ if (skb) {
+ len = skb->len < count ? skb->len : count;
+ memcpy(data, skb->data, len);
+
+ kfree_skb(skb);
+ session->report_return = NULL;
+ } else {
+ /* Device returned a HANDSHAKE, indicating protocol error. */
+ len = -EIO;
+ }
+
+ clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
+ mutex_unlock(&session->report_mutex);
+
+ return len;
+
+err_restartsys:
+ clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
+ mutex_unlock(&session->report_mutex);
+ return -ERESTARTSYS;
+err_eio:
+ clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
+ mutex_unlock(&session->report_mutex);
+ return -EIO;
+}
+
static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
unsigned char report_type)
{
@@ -409,6 +490,10 @@ static void hidp_process_handshake(struct hidp_session *session,
case HIDP_HSHK_ERR_INVALID_REPORT_ID:
case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
case HIDP_HSHK_ERR_INVALID_PARAMETER:
+ if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
+ clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
+ wake_up_interruptible(&session->report_queue);
+ }
/* FIXME: Call into SET_ GET_ handlers here */
break;
@@ -451,9 +536,11 @@ static void hidp_process_hid_control(struct hidp_session *session,
}
}
-static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
+/* Returns true if the passed-in skb should be freed by the caller. */
+static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
unsigned char param)
{
+ int done_with_skb = 1;
BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
switch (param) {
@@ -465,7 +552,6 @@ static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
if (session->hid)
hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
-
break;
case HIDP_DATA_RTYPE_OTHER:
@@ -477,12 +563,27 @@ static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
__hidp_send_ctrl_message(session,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
}
+
+ if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
+ param == session->waiting_report_type) {
+ if (session->waiting_report_number < 0 ||
+ session->waiting_report_number == skb->data[0]) {
+ /* hidp_get_raw_report() is waiting on this report. */
+ session->report_return = skb;
+ done_with_skb = 0;
+ clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
+ wake_up_interruptible(&session->report_queue);
+ }
+ }
+
+ return done_with_skb;
}
static void hidp_recv_ctrl_frame(struct hidp_session *session,
struct sk_buff *skb)
{
unsigned char hdr, type, param;
+ int free_skb = 1;
BT_DBG("session %p skb %p len %d", session, skb, skb->len);
@@ -502,7 +603,7 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session,
break;
case HIDP_TRANS_DATA:
- hidp_process_data(session, skb, param);
+ free_skb = hidp_process_data(session, skb, param);
break;
default:
@@ -511,7 +612,8 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session,
break;
}
- kfree_skb(skb);
+ if (free_skb)
+ kfree_skb(skb);
}
static void hidp_recv_intr_frame(struct hidp_session *session,
@@ -845,6 +947,7 @@ static int hidp_setup_hid(struct hidp_session *session,
hid->dev.parent = hidp_get_device(session);
hid->ll_driver = &hidp_hid_driver;
+ hid->hid_get_raw_report = hidp_get_raw_report;
hid->hid_output_raw_report = hidp_output_raw_report;
return 0;
@@ -897,6 +1000,8 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
skb_queue_head_init(&session->ctrl_transmit);
skb_queue_head_init(&session->intr_transmit);
+ mutex_init(&session->report_mutex);
+ init_waitqueue_head(&session->report_queue);
init_waitqueue_head(&session->startup_queue);
session->waiting_for_startup = 1;
session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index 92e093e..13de5fa 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -80,6 +80,7 @@
#define HIDP_VIRTUAL_CABLE_UNPLUG 0
#define HIDP_BOOT_PROTOCOL_MODE 1
#define HIDP_BLUETOOTH_VENDOR_ID 9
+#define HIDP_WAITING_FOR_RETURN 10
#define HIDP_WAITING_FOR_SEND_ACK 11
struct hidp_connadd_req {
@@ -155,6 +156,13 @@ struct hidp_session {
struct sk_buff_head ctrl_transmit;
struct sk_buff_head intr_transmit;
+ /* Used in hidp_get_raw_report() */
+ int waiting_report_type; /* HIDP_DATA_RTYPE_* */
+ int waiting_report_number; /* -1 for not numbered */
+ struct mutex report_mutex;
+ struct sk_buff *report_return;
+ wait_queue_head_t report_queue;
+
/* Used in hidp_output_raw_report() */
int output_report_success; /* boolean */
--
1.7.0.4
^ permalink raw reply related
* [PATCH v5 3/4] hid: Add Support for Setting and Getting Feature Reports from hidraw
From: Alan Ott @ 2011-01-18 8:04 UTC (permalink / raw)
To: Jiri Kosina, Marcel Holtmann, Gustavo F. Padovan, David S. Miller,
Alan Ott, Michael Poole, Eric Dumazet, linux-input, linux-kernel,
linux-usb, linux-bluetooth, netdev
Cc: Alan Ott, Antonio Ospite
In-Reply-To: <1295337880-12452-1-git-send-email-alan@signal11.us>
Per the HID Specification, Feature reports must be sent and received on
the Configuration endpoint (EP 0) through the Set_Report/Get_Report
interfaces. This patch adds two ioctls to hidraw to set and get feature
reports to and from the device. Modifications were made to hidraw and
usbhid.
New hidraw ioctls:
HIDIOCSFEATURE - Perform a Set_Report transfer of a Feature report.
HIDIOCGFEATURE - Perform a Get_Report transfer of a Feature report.
Signed-off-by: Alan Ott <alan@signal11.us>
Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
---
drivers/hid/hidraw.c | 106 ++++++++++++++++++++++++++++++++++++++--
drivers/hid/usbhid/hid-core.c | 35 +++++++++++++
include/linux/hid.h | 3 +
include/linux/hidraw.h | 3 +
4 files changed, 141 insertions(+), 6 deletions(-)
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 468e87b..8f06044 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -102,15 +102,14 @@ out:
}
/* the first byte is expected to be a report number */
-static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+/* This function is to be called with the minors_lock mutex held */
+static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type)
{
unsigned int minor = iminor(file->f_path.dentry->d_inode);
struct hid_device *dev;
__u8 *buf;
int ret = 0;
- mutex_lock(&minors_lock);
-
if (!hidraw_table[minor]) {
ret = -ENODEV;
goto out;
@@ -148,14 +147,92 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
goto out_free;
}
- ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT);
+ ret = dev->hid_output_raw_report(dev, buf, count, report_type);
out_free:
kfree(buf);
out:
+ return ret;
+}
+
+/* the first byte is expected to be a report number */
+static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+{
+ ssize_t ret;
+ mutex_lock(&minors_lock);
+ ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT);
mutex_unlock(&minors_lock);
return ret;
}
+
+/* This function performs a Get_Report transfer over the control endpoint
+ per section 7.2.1 of the HID specification, version 1.1. The first byte
+ of buffer is the report number to request, or 0x0 if the defice does not
+ use numbered reports. The report_type parameter can be HID_FEATURE_REPORT
+ or HID_INPUT_REPORT. This function is to be called with the minors_lock
+ mutex held. */
+static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t count, unsigned char report_type)
+{
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ struct hid_device *dev;
+ __u8 *buf;
+ int ret = 0, len;
+ unsigned char report_number;
+
+ dev = hidraw_table[minor]->hid;
+
+ if (!dev->hid_get_raw_report) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (count > HID_MAX_BUFFER_SIZE) {
+ printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
+ task_pid_nr(current));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (count < 2) {
+ printk(KERN_WARNING "hidraw: pid %d passed too short report\n",
+ task_pid_nr(current));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ buf = kmalloc(count * sizeof(__u8), GFP_KERNEL);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Read the first byte from the user. This is the report number,
+ which is passed to dev->hid_get_raw_report(). */
+ if (copy_from_user(&report_number, buffer, 1)) {
+ ret = -EFAULT;
+ goto out_free;
+ }
+
+ ret = dev->hid_get_raw_report(dev, report_number, buf, count, report_type);
+
+ if (ret < 0)
+ goto out_free;
+
+ len = (ret < count) ? ret : count;
+
+ if (copy_to_user(buffer, buf, len)) {
+ ret = -EFAULT;
+ goto out_free;
+ }
+
+ ret = len;
+
+out_free:
+ kfree(buf);
+out:
+ return ret;
+}
+
static unsigned int hidraw_poll(struct file *file, poll_table *wait)
{
struct hidraw_list *list = file->private_data;
@@ -295,7 +372,24 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
default:
{
struct hid_device *hid = dev->hid;
- if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) {
+ if (_IOC_TYPE(cmd) != 'H') {
+ ret = -EINVAL;
+ break;
+ }
+
+ if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSFEATURE(0))) {
+ int len = _IOC_SIZE(cmd);
+ ret = hidraw_send_report(file, user_arg, len, HID_FEATURE_REPORT);
+ break;
+ }
+ if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGFEATURE(0))) {
+ int len = _IOC_SIZE(cmd);
+ ret = hidraw_get_report(file, user_arg, len, HID_FEATURE_REPORT);
+ break;
+ }
+
+ /* Begin Read-only ioctls. */
+ if (_IOC_DIR(cmd) != _IOC_READ) {
ret = -EINVAL;
break;
}
@@ -327,7 +421,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
-EFAULT : len;
break;
}
- }
+ }
ret = -ENOTTY;
}
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index b336dd8..38c261a 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -799,6 +799,40 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
return 0;
}
+static int usbhid_get_raw_report(struct hid_device *hid,
+ unsigned char report_number, __u8 *buf, size_t count,
+ unsigned char report_type)
+{
+ struct usbhid_device *usbhid = hid->driver_data;
+ struct usb_device *dev = hid_to_usb_dev(hid);
+ struct usb_interface *intf = usbhid->intf;
+ struct usb_host_interface *interface = intf->cur_altsetting;
+ int skipped_report_id = 0;
+ int ret;
+
+ /* Byte 0 is the report number. Report data starts at byte 1.*/
+ buf[0] = report_number;
+ if (report_number == 0x0) {
+ /* Offset the return buffer by 1, so that the report ID
+ will remain in byte 0. */
+ buf++;
+ count--;
+ skipped_report_id = 1;
+ }
+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ HID_REQ_GET_REPORT,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ ((report_type + 1) << 8) | report_number,
+ interface->desc.bInterfaceNumber, buf, count,
+ USB_CTRL_SET_TIMEOUT);
+
+ /* count also the report id */
+ if (ret > 0 && skipped_report_id)
+ ret++;
+
+ return ret;
+}
+
static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count,
unsigned char report_type)
{
@@ -1139,6 +1173,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
usb_set_intfdata(intf, hid);
hid->ll_driver = &usb_hid_driver;
+ hid->hid_get_raw_report = usbhid_get_raw_report;
hid->hid_output_raw_report = usbhid_output_raw_report;
hid->ff_init = hid_pidff_init;
#ifdef CONFIG_USB_HIDDEV
diff --git a/include/linux/hid.h b/include/linux/hid.h
index d91c25e..e8ee0a9 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -504,6 +504,9 @@ struct hid_device { /* device report descriptor */
struct hid_usage *, __s32);
void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
+ /* handler for raw input (Get_Report) data, used by hidraw */
+ int (*hid_get_raw_report) (struct hid_device *, unsigned char, __u8 *, size_t, unsigned char);
+
/* handler for raw output data, used by hidraw */
int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t, unsigned char);
diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h
index dd8d692..4b88e69 100644
--- a/include/linux/hidraw.h
+++ b/include/linux/hidraw.h
@@ -35,6 +35,9 @@ struct hidraw_devinfo {
#define HIDIOCGRAWINFO _IOR('H', 0x03, struct hidraw_devinfo)
#define HIDIOCGRAWNAME(len) _IOC(_IOC_READ, 'H', 0x04, len)
#define HIDIOCGRAWPHYS(len) _IOC(_IOC_READ, 'H', 0x05, len)
+/* The first byte of SFEATURE and GFEATURE is the report number */
+#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
+#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
#define HIDRAW_FIRST_MINOR 0
#define HIDRAW_MAX_DEVICES 64
--
1.7.0.4
^ permalink raw reply related
* [PATCH v5 2/4] bt hidp: Wait for ACK on Sent Reports
From: Alan Ott @ 2011-01-18 8:04 UTC (permalink / raw)
To: Jiri Kosina, Marcel Holtmann, Gustavo F. Padovan, David S. Miller,
Alan Ott, Michael Poole, Eric Dumazet, linux-input, linux-kernel,
linux-usb, linux-bluetooth, netdev
Cc: Alan Ott
In-Reply-To: <1295337880-12452-1-git-send-email-alan@signal11.us>
Wait for an ACK from the device before returning from
hidp_output_raw_report(). This way, failures can be returned to the user
application. Also, it prevents ACK/NAK packets from an output packet from
being confused with ACK/NAK packets from an input request packet.
Signed-off-by: Alan Ott <alan@signal11.us>
---
net/bluetooth/hidp/core.c | 54 ++++++++++++++++++++++++++++++++++++++++++--
net/bluetooth/hidp/hidp.h | 4 +++
2 files changed, 55 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 67cc4bc..5383e6c 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -316,6 +316,9 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
unsigned char report_type)
{
+ struct hidp_session *session = hid->driver_data;
+ int ret;
+
switch (report_type) {
case HID_FEATURE_REPORT:
report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
@@ -327,10 +330,47 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s
return -EINVAL;
}
+ if (mutex_lock_interruptible(&session->report_mutex))
+ return -ERESTARTSYS;
+
+ /* Set up our wait, and send the report request to the device. */
+ set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
if (hidp_send_ctrl_message(hid->driver_data, report_type,
- data, count))
- return -ENOMEM;
- return count;
+ data, count)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* Wait for the ACK from the device. */
+ while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
+ int res;
+
+ res = wait_event_interruptible_timeout(session->report_queue,
+ !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags),
+ 10*HZ);
+ if (res == 0) {
+ /* timeout */
+ ret = -EIO;
+ goto err;
+ }
+ if (res < 0) {
+ /* signal */
+ ret = -ERESTARTSYS;
+ goto err;
+ }
+ }
+
+ if (!session->output_report_success) {
+ ret = -EIO;
+ goto err;
+ }
+
+ ret = count;
+
+err:
+ clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
+ mutex_unlock(&session->report_mutex);
+ return ret;
}
static void hidp_idle_timeout(unsigned long arg)
@@ -357,10 +397,12 @@ static void hidp_process_handshake(struct hidp_session *session,
unsigned char param)
{
BT_DBG("session %p param 0x%02x", session, param);
+ session->output_report_success = 0; /* default condition */
switch (param) {
case HIDP_HSHK_SUCCESSFUL:
/* FIXME: Call into SET_ GET_ handlers here */
+ session->output_report_success = 1;
break;
case HIDP_HSHK_NOT_READY:
@@ -385,6 +427,12 @@ static void hidp_process_handshake(struct hidp_session *session,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
break;
}
+
+ /* Wake up the waiting thread. */
+ if (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
+ clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
+ wake_up_interruptible(&session->report_queue);
+ }
}
static void hidp_process_hid_control(struct hidp_session *session,
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index 2cc35dc..92e093e 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -80,6 +80,7 @@
#define HIDP_VIRTUAL_CABLE_UNPLUG 0
#define HIDP_BOOT_PROTOCOL_MODE 1
#define HIDP_BLUETOOTH_VENDOR_ID 9
+#define HIDP_WAITING_FOR_SEND_ACK 11
struct hidp_connadd_req {
int ctrl_sock; // Connected control socket
@@ -154,6 +155,9 @@ struct hidp_session {
struct sk_buff_head ctrl_transmit;
struct sk_buff_head intr_transmit;
+ /* Used in hidp_output_raw_report() */
+ int output_report_success; /* boolean */
+
/* Report descriptor */
__u8 *rd_data;
uint rd_size;
--
1.7.0.4
^ permalink raw reply related
* [PATCH v5 1/4] bt hidp: Move hid_add_device() call to after hidp_session() has started.
From: Alan Ott @ 2011-01-18 8:04 UTC (permalink / raw)
To: Jiri Kosina, Marcel Holtmann, Gustavo F. Padovan, David S. Miller,
Alan Ott, Michael Poole, Eric Dumazet, linux-input, linux-kernel,
linux-usb, linux-bluetooth, netdev
Cc: Alan Ott
In-Reply-To: <1295337880-12452-1-git-send-email-alan@signal11.us>
Move the call to hid_add_device() (which calls a device's probe() function)
to after the kernel_thread() call which starts the hidp_session() thread.
This ensures the Bluetooth receive socket is fully running by the time a
device's probe() function is called. This way, a device can communicate
(send and receive) with the Bluetooth device from its probe() function.
Signed-off-by: Alan Ott <alan@signal11.us>
---
net/bluetooth/hidp/core.c | 28 ++++++++++++++++++++--------
net/bluetooth/hidp/hidp.h | 3 +++
2 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 29544c2..67cc4bc 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -563,6 +563,8 @@ static int hidp_session(void *arg)
init_waitqueue_entry(&intr_wait, current);
add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
add_wait_queue(sk_sleep(intr_sk), &intr_wait);
+ session->waiting_for_startup = 0;
+ wake_up_interruptible(&session->startup_queue);
while (!atomic_read(&session->terminate)) {
set_current_state(TASK_INTERRUPTIBLE);
@@ -754,6 +756,8 @@ static struct hid_ll_driver hidp_hid_driver = {
.hidinput_input_event = hidp_hidinput_event,
};
+/* This function sets up the hid device. It does not add it
+ to the HID system. That is done in hidp_add_connection(). */
static int hidp_setup_hid(struct hidp_session *session,
struct hidp_connadd_req *req)
{
@@ -795,16 +799,8 @@ static int hidp_setup_hid(struct hidp_session *session,
hid->hid_output_raw_report = hidp_output_raw_report;
- err = hid_add_device(hid);
- if (err < 0)
- goto failed;
-
return 0;
-failed:
- hid_destroy_device(hid);
- session->hid = NULL;
-
fault:
kfree(session->rd_data);
session->rd_data = NULL;
@@ -853,6 +849,8 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
skb_queue_head_init(&session->ctrl_transmit);
skb_queue_head_init(&session->intr_transmit);
+ init_waitqueue_head(&session->startup_queue);
+ session->waiting_for_startup = 1;
session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
session->idle_to = req->idle_to;
@@ -875,6 +873,14 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
err = kernel_thread(hidp_session, session, CLONE_KERNEL);
if (err < 0)
goto unlink;
+ while (session->waiting_for_startup) {
+ wait_event_interruptible(session->startup_queue,
+ !session->waiting_for_startup);
+ }
+
+ err = hid_add_device(session->hid);
+ if (err < 0)
+ goto err_add_device;
if (session->input) {
hidp_send_ctrl_message(session,
@@ -888,6 +894,12 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
up_write(&hidp_session_sem);
return 0;
+err_add_device:
+ hid_destroy_device(session->hid);
+ session->hid = NULL;
+ atomic_inc(&session->terminate);
+ hidp_schedule(session);
+
unlink:
hidp_del_timer(session);
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index 8d934a1..2cc35dc 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -157,6 +157,9 @@ struct hidp_session {
/* Report descriptor */
__u8 *rd_data;
uint rd_size;
+
+ wait_queue_head_t startup_queue;
+ int waiting_for_startup;
};
static inline void hidp_schedule(struct hidp_session *session)
--
1.7.0.4
^ permalink raw reply related
* [PATCH v5 0/4] Adding HID Feature Report Support to hidraw
From: Alan Ott @ 2011-01-18 8:04 UTC (permalink / raw)
To: Jiri Kosina, Marcel Holtmann, Gustavo F. Padovan, David S. Miller,
Alan Ott, Michael Poole, Eric Dumazet, linux-input, linux-kernel,
linux-usb, linux-bluetooth, netdev
Cc: Alan Ott
This patch adds Feature Report support for USB and Bluetooth HID devices
through hidraw.
The first two patches prepare the bluetooth side for the change.
a. Make sure the hidp_session() thread is started before
device's probe() functions are called.
b. Wait for ACK/NAK on sent reports, and return proper
error codes.
The third patch is the hidraw core and USB changes.
The fourth patch is the Bluetooth changes.
Thanks to Antonio Ospite and Bill Good for providing testing and feedback.
Alan Ott (4):
bt hidp: Move hid_add_device() call to after hidp_session() has
started.
bt hidp: Wait for ACK on Sent Reports
HID: Add Support for Setting and Getting Feature Reports from hidraw
Bluetooth hidp: Add support for hidraw HIDIOCGFEATURE and
HIDIOCSFEATURE
drivers/hid/hidraw.c | 106 +++++++++++++++++++-
drivers/hid/usbhid/hid-core.c | 35 +++++++
include/linux/hid.h | 3 +
include/linux/hidraw.h | 3 +
net/bluetooth/hidp/core.c | 214 ++++++++++++++++++++++++++++++++++++++---
net/bluetooth/hidp/hidp.h | 15 +++
6 files changed, 355 insertions(+), 21 deletions(-)
^ permalink raw reply
* [PATCH 2/2] Move common code from Discover all Characteristics to GATT library
From: Bruna Moreira @ 2011-01-17 19:37 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1295293069-29637-1-git-send-email-bruna.moreira@openbossa.org>
The attribute client (attrib/client.c) and gatttool share similar code
to parse the PDU coming from server. This commit moves this common code
to attrib/gatt.c, and simplifies the callbacks implemented by the
clients. The client callbacks are now called just once and get a GSList
of characteristics, instead of the raw PDU.
---
attrib/att.h | 7 +++
attrib/client.c | 67 +++++++-------------------------
attrib/gatt.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++-
attrib/gatt.h | 2 +-
attrib/gatttool.c | 59 +++++-----------------------
5 files changed, 140 insertions(+), 106 deletions(-)
diff --git a/attrib/att.h b/attrib/att.h
index 08feeec..a1e0b62 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -143,6 +143,13 @@ struct att_primary {
uint16_t end;
};
+struct att_char {
+ char uuid[MAX_LEN_UUID_STR + 1];
+ uint16_t handle;
+ uint8_t properties;
+ uint16_t value_handle;
+};
+
/* These functions do byte conversion */
static inline uint8_t att_get_u8(const void *ptr)
{
diff --git a/attrib/client.c b/attrib/client.c
index 7f72348..767d1c1 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -85,7 +85,7 @@ struct characteristic {
uint16_t handle;
uint16_t end;
uint8_t perm;
- uuid_t type;
+ char type[MAX_LEN_UUID_STR + 1];
char *name;
char *desc;
struct format *format;
@@ -199,7 +199,7 @@ static void append_char_dict(DBusMessageIter *iter, struct characteristic *chr)
DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
- uuid = bt_uuid2string(&chr->type);
+ uuid = g_strdup(chr->type);
dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &uuid);
g_free(uuid);
@@ -544,19 +544,12 @@ static char *characteristic_list_to_string(GSList *chars)
for (l = chars; l; l = l->next) {
struct characteristic *chr = l->data;
- uuid_t *uuid128;
char chr_str[64];
- char uuidstr[MAX_LEN_UUID_STR];
memset(chr_str, 0, sizeof(chr_str));
- uuid128 = sdp_uuid_to_uuid128(&chr->type);
- sdp_uuid2strn(uuid128, uuidstr, MAX_LEN_UUID_STR);
-
- bt_free(uuid128);
-
snprintf(chr_str, sizeof(chr_str), "%04X#%02X#%04X#%s ",
- chr->handle, chr->perm, chr->end, uuidstr);
+ chr->handle, chr->perm, chr->end, chr->type);
characteristics = g_string_append(characteristics, chr_str);
}
@@ -607,13 +600,12 @@ static GSList *string_to_characteristic_list(struct primary *prim,
for (i = 0; chars[i]; i++) {
struct characteristic *chr;
- char uuidstr[MAX_LEN_UUID_STR + 1];
int ret;
chr = g_new0(struct characteristic, 1);
ret = sscanf(chars[i], "%04hX#%02hhX#%04hX#%s", &chr->handle,
- &chr->perm, &chr->end, uuidstr);
+ &chr->perm, &chr->end, chr->type);
if (ret < 4) {
g_free(chr);
continue;
@@ -623,8 +615,6 @@ static GSList *string_to_characteristic_list(struct primary *prim,
chr->path = g_strdup_printf("%s/characteristic%04x",
prim->path, chr->handle);
- bt_string2uuid(&chr->type, uuidstr);
-
l = g_slist_append(l, chr);
}
@@ -861,54 +851,37 @@ static void update_all_chars(gpointer data, gpointer user_data)
gatt_read_char(gatt->attrib, chr->handle, update_char_value, qvalue);
}
-static void char_discovered_cb(guint8 status, const guint8 *pdu, guint16 plen,
+static void char_discovered_cb(GSList *characteristics, guint8 status,
gpointer user_data)
{
struct query_data *current = user_data;
struct primary *prim = current->prim;
struct att_primary *att = prim->att;
struct gatt_service *gatt = prim->gatt;
- struct att_data_list *list;
- uint16_t last, *previous_end = NULL;
- int i;
-
- if (status == ATT_ECODE_ATTR_NOT_FOUND)
- goto done;
+ uint16_t *previous_end = NULL;
+ GSList *l;
if (status != 0) {
DBG("Discover all characteristics failed: %s",
att_ecode2str(status));
-
goto fail;
}
- DBG("Read by Type Response received");
-
- list = dec_read_by_type_resp(pdu, plen);
- if (list == NULL)
- goto fail;
-
- for (i = 0, last = 0; i < list->num; i++) {
- uint8_t *decl = list->data[i];
+ for (l = characteristics; l; l = l->next) {
+ struct att_char *current_chr = l->data;
struct characteristic *chr;
chr = g_new0(struct characteristic, 1);
chr->prim = prim;
- chr->perm = decl[2];
- chr->handle = att_get_u16(&decl[3]);
+ chr->perm = current_chr->properties;
+ chr->handle = current_chr->value_handle;
chr->path = g_strdup_printf("%s/characteristic%04x",
prim->path, chr->handle);
- if (list->len == 7) {
- sdp_uuid16_create(&chr->type,
- att_get_u16(&decl[5]));
- } else
- sdp_uuid128_create(&chr->type, &decl[5]);
+ strncpy(chr->type, current_chr->uuid, sizeof(chr->type));
- if (previous_end) {
- *previous_end = att_get_u16(decl);
- }
+ if (previous_end)
+ *previous_end = current_chr->handle;
- last = chr->handle;
previous_end = &chr->end;
prim->chars = g_slist_append(prim->chars, chr);
@@ -917,18 +890,6 @@ static void char_discovered_cb(guint8 status, const guint8 *pdu, guint16 plen,
if (previous_end)
*previous_end = att->end;
- att_data_list_free(list);
-
- if (last >= att->end)
- goto done;
-
- /* Fetch remaining characteristics for the CURRENT primary service */
- gatt_discover_char(gatt->attrib, last + 1, att->end,
- char_discovered_cb, current);
-
- return;
-
-done:
store_characteristics(gatt, prim);
register_characteristics(prim);
diff --git a/attrib/gatt.c b/attrib/gatt.c
index 79d8b9d..5d7887e 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -39,6 +39,15 @@ struct discover_primary {
void *user_data;
};
+struct discover_char {
+ GAttrib *attrib;
+ uuid_t uuid;
+ uint16_t end;
+ GSList *characteristics;
+ gatt_cb_t cb;
+ void *user_data;
+};
+
static void discover_primary_free(struct discover_primary *dp)
{
g_slist_free(dp->primaries);
@@ -46,6 +55,14 @@ static void discover_primary_free(struct discover_primary *dp)
g_free(dp);
}
+static void discover_char_free(struct discover_char *dc)
+{
+ g_slist_foreach(dc->characteristics, (GFunc) g_free, NULL);
+ g_slist_free(dc->characteristics);
+ g_attrib_unref(dc->attrib);
+ g_free(dc);
+}
+
static guint16 encode_discover_primary(uint16_t start, uint16_t end,
uuid_t *uuid, uint8_t *pdu, size_t len)
{
@@ -222,15 +239,103 @@ guint gatt_discover_primary(GAttrib *attrib, uuid_t *uuid, gatt_cb_t func,
return g_attrib_send(attrib, 0, pdu[0], pdu, plen, cb, dp, NULL);
}
+static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
+ gpointer user_data)
+{
+ struct discover_char *dc = user_data;
+ struct att_data_list *list;
+ unsigned int i, err;
+ uint8_t opdu[ATT_DEFAULT_MTU];
+ guint16 oplen;
+ uuid_t uuid;
+ uint16_t last = 0;
+
+ if (status) {
+ err = status == ATT_ECODE_ATTR_NOT_FOUND ? 0 : status;
+ goto done;
+ }
+
+ list = dec_read_by_type_resp(ipdu, iplen);
+ if (list == NULL) {
+ err = ATT_ECODE_IO;
+ goto done;
+ }
+
+ for (i = 0; i < list->num; i++) {
+ uint8_t *value = list->data[i];
+ struct att_char *chars;
+ uuid_t u128, u16;
+
+ last = att_get_u16(value);
+
+ if (list->len == 7) {
+ sdp_uuid16_create(&u16, att_get_u16(&value[5]));
+ sdp_uuid16_to_uuid128(&u128, &u16);
+ } else
+ sdp_uuid128_create(&u128, &value[5]);
+
+ chars = g_try_new0(struct att_char, 1);
+ if (!chars) {
+ err = ATT_ECODE_INSUFF_RESOURCES;
+ goto done;
+ }
+
+ chars->handle = last;
+ chars->properties = value[2];
+ chars->value_handle = att_get_u16(&value[3]);
+ sdp_uuid2strn(&u128, chars->uuid, sizeof(chars->uuid));
+ dc->characteristics = g_slist_append(dc->characteristics,
+ chars);
+ }
+
+ att_data_list_free(list);
+ err = 0;
+
+ if (last != 0) {
+ sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+
+ oplen = enc_read_by_type_req(last + 1, dc->end, &uuid, opdu,
+ sizeof(opdu));
+
+ if (oplen == 0)
+ return;
+
+ g_attrib_send(dc->attrib, 0, opdu[0], opdu, oplen,
+ char_discovered_cb, dc, NULL);
+
+ return;
+ }
+
+done:
+ dc->cb(dc->characteristics, err, dc->user_data);
+ discover_char_free(dc);
+}
+
guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
- GAttribResultFunc func, gpointer user_data)
+ gatt_cb_t func, gpointer user_data)
{
+ uint8_t pdu[ATT_DEFAULT_MTU];
+ struct discover_char *dc;
+ guint16 plen;
uuid_t uuid;
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
- return gatt_read_char_by_uuid(attrib, start, end, &uuid, func,
- user_data);
+ plen = enc_read_by_type_req(start, end, &uuid, pdu, sizeof(pdu));
+ if (plen == 0)
+ return 0;
+
+ dc = g_try_new0(struct discover_char, 1);
+ if (dc == NULL)
+ return 0;
+
+ dc->attrib = g_attrib_ref(attrib);
+ dc->cb = func;
+ dc->user_data = user_data;
+ dc->end = end;
+
+ return g_attrib_send(attrib, 0, pdu[0], pdu, plen, char_discovered_cb,
+ dc, NULL);
}
guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,
diff --git a/attrib/gatt.h b/attrib/gatt.h
index 0bdac77..9f69646 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -30,7 +30,7 @@ guint gatt_discover_primary(GAttrib *attrib, uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
- GAttribResultFunc func, gpointer user_data);
+ gatt_cb_t func, gpointer user_data);
guint gatt_read_char(GAttrib *attrib, uint16_t handle, GAttribResultFunc func,
gpointer user_data);
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index ad0216b..8e8ed8e 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -245,73 +245,34 @@ static gboolean primary(gpointer user_data)
return FALSE;
}
-static void char_discovered_cb(guint8 status, const guint8 *pdu, guint16 plen,
+static void char_discovered_cb(GSList *characteristics, guint8 status,
gpointer user_data)
{
- struct characteristic_data *char_data = user_data;
- struct att_data_list *list;
- uint16_t last = char_data->start;
- int i;
-
- if (status == ATT_ECODE_ATTR_NOT_FOUND)
- goto done;
+ GSList *l;
- if (status != 0) {
+ if (status) {
g_printerr("Discover all characteristics failed: %s\n",
att_ecode2str(status));
goto done;
}
- list = dec_read_by_type_resp(pdu, plen);
- if (list == NULL)
- return;
-
- for (i = 0; i < list->num; i++) {
- uint8_t *value = list->data[i];
- char uuidstr[MAX_LEN_UUID_STR];
- uuid_t uuid;
+ for (l = characteristics; l; l = l->next) {
+ struct att_char *chars = l->data;
- last = att_get_u16(value);
-
- g_print("handle = 0x%04x, char properties = 0x%02x, "
- "char value handle = 0x%04x, ", last, value[2],
- att_get_u16(&value[3]));
-
- if (list->len == 7)
- sdp_uuid16_create(&uuid, att_get_u16(&value[5]));
- else
- sdp_uuid128_create(&uuid, value + 5);
-
- sdp_uuid2strn(&uuid, uuidstr, MAX_LEN_UUID_STR);
- g_print("uuid = %s\n", uuidstr);
+ g_print("handle = 0x%04x, char properties = 0x%02x, char value "
+ "handle = 0x%04x, uuid = %s\n", chars->handle,
+ chars->properties, chars->value_handle, chars->uuid);
}
- att_data_list_free(list);
-
- /* Fetch remaining characteristics for the CURRENT primary service */
- gatt_discover_char(char_data->attrib, last + 1, char_data->end,
- char_discovered_cb, char_data);
-
- return;
-
done:
- g_free(char_data);
- if (opt_listen == FALSE)
- g_main_loop_quit(event_loop);
+ g_main_loop_quit(event_loop);
}
static gboolean characteristics(gpointer user_data)
{
GAttrib *attrib = user_data;
- struct characteristic_data *char_data;
-
- char_data = g_new(struct characteristic_data, 1);
- char_data->attrib = attrib;
- char_data->start = opt_start;
- char_data->end = opt_end;
- gatt_discover_char(attrib, opt_start, opt_end, char_discovered_cb,
- char_data);
+ gatt_discover_char(attrib, opt_start, opt_end, char_discovered_cb, NULL);
return FALSE;
}
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/2] Rename gatt_primary_t to more generic name
From: Bruna Moreira @ 2011-01-17 19:37 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
The gatt_primary_t typedef was renamed to gatt_cb_t because it will be
used for primary and characteristic callbacks.
---
attrib/gatt.c | 4 ++--
attrib/gatt.h | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/attrib/gatt.c b/attrib/gatt.c
index 7d09689..79d8b9d 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -35,7 +35,7 @@ struct discover_primary {
GAttrib *attrib;
uuid_t uuid;
GSList *primaries;
- gatt_primary_t cb;
+ gatt_cb_t cb;
void *user_data;
};
@@ -193,7 +193,7 @@ done:
discover_primary_free(dp);
}
-guint gatt_discover_primary(GAttrib *attrib, uuid_t *uuid, gatt_primary_t func,
+guint gatt_discover_primary(GAttrib *attrib, uuid_t *uuid, gatt_cb_t func,
gpointer user_data)
{
struct discover_primary *dp;
diff --git a/attrib/gatt.h b/attrib/gatt.h
index 936c592..0bdac77 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -24,9 +24,9 @@
#define GATT_CID 4
-typedef void (*gatt_primary_t) (GSList *l, guint8 status, gpointer user_data);
+typedef void (*gatt_cb_t) (GSList *l, guint8 status, gpointer user_data);
-guint gatt_discover_primary(GAttrib *attrib, uuid_t *uuid, gatt_primary_t func,
+guint gatt_discover_primary(GAttrib *attrib, uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH 09/11] Bluetooth: Fix leaking blacklist when unregistering a hci device
From: Gustavo F. Padovan @ 2011-01-17 18:25 UTC (permalink / raw)
To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <1294135732-26765-9-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
* johan.hedberg@gmail.com <johan.hedberg@gmail.com> [2011-01-04 12:08:50 +0200]:
> From: Johan Hedberg <johan.hedberg@nokia.com>
>
> The blacklist should be freed before the hci device gets unregistered.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
> ---
> net/bluetooth/hci_core.c | 4 ++++
> 1 files changed, 4 insertions(+), 0 deletions(-)
This one is applied. Thanks.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCH] HCI Commands for LE White List
From: Claudio Takahasi @ 2011-01-17 17:27 UTC (permalink / raw)
To: Sumit Kumar BAJPAI; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <4765B7BC10CB4C488A56C73E15D6FBA31DA381A6A5@EXDCVYMBSTM005.EQ1STM.local>
Hi Sumit,
<snip>
> Is using a separate variable err for return type of a function problem here?
I didn't understand your question here.
hci_* functions return 0 on success or -1 on failure. On failure errno
can be read to get the error number.
> I could see same coding style of defining a variable to carry the error status in hcitool.c function cmd_lecc.
> Please confirm.
The coding style issue is the if else:
At this point "else" is not needed: there is a "exit(1)" inside the
"if" block. But if you need else the correct coding style is:
...
} else {
...
Instead of
...
}
else {
...
<snip>
>> > + err = hci_le_remove_from_white_list(dd, bdaddr ,bdaddr_type);
>> > + if (err < 0) {
>> > + perror("Cant remove from white list");
>> > + exit(1);
>> > + }
>> > + else {
>> > + printf("Device removed from white list");
>> > + }
>> > +
>> > + hci_close_dev(dd);
>> Same coding style issue and close "dd"
>>
>
>
> Ok. Good point. But I could still find premature returns on error conditions via exits at several places in hcitool.c. Can I submit a separate patch for rectifying all such error conditions too?
sure!
Claudio
^ permalink raw reply
* Re: [Patch] Kill off warning: ‘inline’ is not at beginning of declaration
From: Gustavo F. Padovan @ 2011-01-17 16:13 UTC (permalink / raw)
To: Jesper Juhl
Cc: linux-kernel, trivial, alsa-devel, linux-wireless, netdev,
ocfs2-devel, linux-edac, linux-bluetooth, oprofile-list,
Andi Kleen, David Teigland, Jens Axboe, Stephen Hemminger,
Greg Kroah-Hartman, Takashi Iwai, Jaroslav Kysela,
John W. Linville, Johannes Berg, Patrick McHardy,
Hideaki YOSHIFUJI, James Morris, Pekka Savola (ipv6),
Alexey Kuznetsov, David S. Miller, Frederic Weisbecker,
Joel Becker, Mark Fasheh, Mauro Carvalho Chehab, Marcel Holtmann,
x86, H. Peter Anvin, Ingo Molnar, Thomas Gleixner, Robert Richter
In-Reply-To: <alpine.LNX.2.00.1101170000270.13377@swampdragon.chaosbits.net>
* Jesper Juhl <jj@chaosbits.net> [2011-01-17 00:09:38 +0100]:
> Fix a bunch of=20
> warning: =E2=80=98inline=E2=80=99 is not at beginning of declaration
> messages when building a 'make allyesconfig' kernel with -Wextra.
>=20
> These warnings are trivial to kill, yet rather annoying when building wit=
h=20
> -Wextra.
> The more we can cut down on pointless crap like this the better (IMHO).
>=20
> A previous patch to do this for a 'allnoconfig' build has already been=20
> merged. This just takes the cleanup a little further.
>=20
> Signed-off-by: Jesper Juhl <jj@chaosbits.net>
> ---
> arch/x86/oprofile/op_model_p4.c | 2 +-
> drivers/bluetooth/btusb.c | 4 ++--
> drivers/cpuidle/sysfs.c | 2 +-
> drivers/edac/i7300_edac.c | 2 +-
> fs/ocfs2/dir.c | 2 +-
> kernel/trace/ring_buffer.c | 2 +-
> net/ipv6/inet6_hashtables.c | 2 +-
> net/mac80211/tx.c | 2 +-
> sound/pci/au88x0/au88x0.h | 4 ++--
> sound/pci/au88x0/au88x0_core.c | 4 ++--
> 10 files changed, 13 insertions(+), 13 deletions(-)
For drivers/bluetooth
Acked-by: Gustavo F. Padovan <padovan@profusion.mobi>
--=20
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* RE: [PATCH 00/11] mfd and bluetooth: Add CG2900 suppor
From: Par-Gunnar HJALMDAHL @ 2011-01-17 15:32 UTC (permalink / raw)
To: Arnd Bergmann, Pavan Savoy
Cc: Vitaly Wool, Linus Walleij, Alan Cox, Samuel Ortiz,
Marcel Holtmann, linux-kernel@vger.kernel.org,
linux-bluetooth@vger.kernel.org, Lukasz Rymanowski,
Par-Gunnar Hjalmdahl
In-Reply-To: <201101091955.05174.arnd@arndb.de>
SGksDQoNClNvcnJ5IGZvciBub3QgYW5zd2VyaW5nIGVhcmxpZXIuIEkndmUgYmVlbiBvdmVybG9h
ZGVkIHdpdGggdGhpbmdzIHRvIGRvIG5vdyBhZnRlciBOZXcgWWVhci4gU2VlIGJlbG93Lg0KDQo+
IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+IEZyb206IEFybmQgQmVyZ21hbm4gW21haWx0
bzphcm5kQGFybmRiLmRlXQ0KPiBTZW50OiBkZW4gOSBqYW51YXJpIDIwMTEgMTk6NTUNCj4gVG86
IFBhdmFuIFNhdm95DQo+IENjOiBQYXItR3VubmFyIEhKQUxNREFITDsgVml0YWx5IFdvb2w7IExp
bnVzIFdhbGxlaWo7IEFsYW4gQ294OyBTYW11ZWwNCj4gT3J0aXo7IE1hcmNlbCBIb2x0bWFubjsg
bGludXgta2VybmVsQHZnZXIua2VybmVsLm9yZzsgbGludXgtDQo+IGJsdWV0b290aEB2Z2VyLmtl
cm5lbC5vcmc7IEx1a2FzeiBSeW1hbm93c2tpOyBQYXItR3VubmFyIEhqYWxtZGFobA0KPiBTdWJq
ZWN0OiBSZTogW1BBVENIIDAwLzExXSBtZmQgYW5kIGJsdWV0b290aDogQWRkIENHMjkwMCBzdXBw
b3INCj4gDQo+IE9uIFN1bmRheSAwOSBKYW51YXJ5IDIwMTEsIFBhdmFuIFNhdm95IHdyb3RlOg0K
PiA+IE9uIEZyaSwgSmFuIDcsIDIwMTEgYXQgMTI6MTYgQU0sIEFybmQgQmVyZ21hbm4gPGFybmRA
YXJuZGIuZGU+IHdyb3RlOg0KPiA+ID4gT24gV2VkbmVzZGF5IDA1IEphbnVhcnkgMjAxMSwgUGFy
LUd1bm5hciBISkFMTURBSEwgd3JvdGU6DQo+ID4gPg0KPiA+ID4+IFNvcnJ5IGZvciBub3QgYW5z
d2VyaW5nIHNvb25lci4gSSd2ZSBiZWVuIG9uIENocmlzdG1hcyBhbmQgTmV3DQo+IFllYXIgdmFj
YXRpb24uDQo+ID4gPg0KPiA+ID4gSSdtIGFsc28gc3RpbGwgY2F0Y2hpbmcgdXAgd2l0aCBlbWFp
bCB0aGF0IGhhcyBhY2N1bXVsYXRlZCBvdmVyIG15DQo+ID4gPiB2YWNhdGlvbiwgaW5jbHVkaW5n
IHlvdXIgcHJldmlvdXMgcmVzcG9uc2UuDQo+ID4gPg0KPiA+ID4gVGhpcyBzb3VuZHMgd3Jvbmcg
Zm9yIGJvdGggVEkgYW5kIFNULUU6IEFGQUlDVCB0aGV5IGFyZSBhY3R1YWxseQ0KPiBidWlsdA0K
PiA+ID4gYXJvdW5kIGFuIEhDSSBpbnRlcmZhY2UuIEl0J3MgdW5mb3J0dW5hdGUgdGhhdCB0aGUg
VEkgY29kZSBhY3R1YWxseQ0KPiBnb3QNCj4gPiA+IG1lcmdlZCBpbnRvIHRoZSBrZXJuZWwgbGlr
ZSB0aGlzLg0KPiA+DQo+ID4gSSBhbSBub3Qgc3VyZSB3aGF0IGRvZXMgYnVpbHQgYXJvdW5kIEhD
SSBJbnRlcmZhY2UgbWVhbj8gQWxzbyB5ZXMsIGluDQo+IFRJLSBjb2RlDQo+ID4gd2UgZG8gcmVm
ZXIgdG8gQmx1ZXRvb3RoIGhlYWRlcnMuDQo+ID4gSG93ZXZlciB0aGUgZmFjdCB0aGF0IEkgd2Fu
dGVkIHRvIHBvaW50IG91dCB0byBQYXItR3VubmFyIHdhcywgdGhhdA0KPiB3ZQ0KPiA+IGRvbid0
IHdhbnQgdG8gdXNlDQo+ID4gaGNpYXR0YWNoIGFuZCBlbmFibGUgSENJLVVBUlQgKyBIQ0ktSDQg
Zm9yIGVuYWJsaW5nIG91ciBkcml2ZXIgb3Igb3VyDQo+ID4gZHJpdmVyIHNob3VsZCBub3QNCj4g
PiBkZXBlbmQgb24gdGhvc2UgbW9kdWxlcyBhcyBzdWNoLi4uDQo+IA0KPiBHb29kIHBvaW50IGFi
b3V0IGhjaWF0dGFjaCwgeW91IGNlcnRhaW5seSBzaG91bGRuJ3QgbmVlZCB0byB1c2UgdGhhdCBp
Zg0KPiB0aGUga2VybmVsIGFscmVhZHkga25vd3MgdGhhdCBhIHR0eSBpcyBjb25uZWN0ZWQgdG8g
YW4gSENJIGFuZCB3aGF0IHRoZQ0KPiBwYXJhbWV0ZXJzIGFyZS4gRXZlbiBtb3JlIHNvIGlmIHRo
ZSBIQ0kgaXMgbm90IGFjdHVhbGx5IG9uIGEgcnMyMzIgbGluZQ0KPiBidXQgc29tZXRoaW5nIGxp
a2UgaTJjIG9yIHNwaS4gQXV0b21hdGljYWxseSBiaW5kaW5nIHRvIHRoZSByaWdodCBsaW5lDQo+
IGRpc2NpcGxpbmUgc2hvdWxkIGJlIGVhc2lseSBkb2FibGUgaW4gdGhlIGRyaXZlcnMgdGhvdWdo
Lg0KPiANCg0KV2hlbiBoYXZpbmcgVUFSVCBhcyB0cmFuc3BvcnQgeW91IG5lZWQgc29tZXRoaW5n
IHRvIG9wZW4gdGhlIFVBUlQgYW5kIHNldCB0aGUgbGluZSBkaXNjaXBsaW5lLiBJZiB0aGlzIGlz
IGhjaWF0dGFjaCBvciBzb21ldGhpbmcgZWxzZSBpcyB1cCB0byBlYWNoIGRldmVsb3BlciB0byBz
dWl0IHdoYXQgdGhleSBhcmUgZG9pbmcuIEkgZG9uJ3Qgc2VlIGEgcHJvYmxlbSB3aXRoIHVzaW5n
IGhjaWF0dGFjaCBldmVuIGlmIHlvdSBkb24ndCB1c2UgdGhlIEJsdWV0b290aCBwYXJ0IChpZiB0
aGUgZXhlIGlzIHBhcnQgb2YgdGhlIHN5c3RlbSBhbnl3YXkpLCBidXQgaWYgYSBjb21wYW55L2Rl
dmVsb3BlciB3YW50IHRvIHVzZSBzb21ldGhpbmcgZWxzZSB0aGV5IGNhbiBkbyB0aGF0LiBJdCdz
IGEgdXNhZ2Ugb2Ygc3RhbmRhcmQgaW50ZXJmYWNlcyB1c2luZyBvcGVuKCkgYW5kIGlvY3RsKCku
DQpJIHN0aWxsIGRvbid0IHRoaW5rIHRoYXQgeW91IHNob3VsZCBoYXZlIGEgbGluZSBkaXNjaXBs
aW5lIGZvciBvdGhlciB0cmFuc3BvcnRzIHRoYW4gVUFSVC4gSWYgSSB3b3VsZCBsb29rIGF0IGhv
dyBJIHdvdWxkIGltcGxlbWVudCBhbiBTUEkgZHJpdmVyIGZvciBDRzI5MDAsIHRoZXJlIHdvdWxk
IGFsbW9zdCBiZSBubyBjb2RlIHRoYXQgY291bGQgYmUgdXNlZCBpbiBjb21tb24gYmV0d2VlbiBj
ZzI5MDBfdWFydCBhbmQgY2cyOTAwX3NwaS4gU1BJIGRvZXNuJ3QgY2hhbmdlIGJhdWQgcmF0ZSwg
U1BJIHVzZXMgY29tbWFuZHMgZm9yIHNsZWVwL3dha2UgaW5zdGVhZCBvZiBCcmVhaywgU1BJIHBh
Y2tldHMgZG9lc24ndCBuZWVkIGV4dHJhIHBhY2tldGl6aW5nLCBldGMuDQoNCj4gSSBkb24ndCB1
bmRlcnN0YW5kIHRoZSBwcm9ibGVtIHdpdGggcmVseWluZyBvbiB0aGUgaGNpLXVhcnQgb3IgaGNp
LWg0DQo+IG1vZHVsZXMuIElmIHRoZSBoYXJkd2FyZSB1c2VzIHRoZSBINCBwcm90b2NvbCwgd2Ug
Y2VydGFpbmx5IHNob3VsZCB1c2UNCj4gdGhlIGtlcm5lbCBtb2R1bGUgdGhhdCBrbm93cyBob3cg
dG8gZGVhbCB3aXRoIEg0LCBhbmQgd2UgZG9uJ3Qgd2FudA0KPiB0byBoYXZlIHR3byBtb2R1bGVz
IGltcGxlbWVudGluZyB0aGUgc2FtZSBwcm90b2NvbC4NCj4gDQoNCkkgbXVzdCBzYXkgSSBkb24n
dCB1bmRlcnN0YW5kIHRoaXMgcHJvYmxlbSBlaXRoZXIuIFVubGVzcyB0aGUgcHJvdG9jb2wgZHJp
dmVyIGlzIGFjdGl2YXRlZCB0aHJvdWdoIGlvY3RsIFNFVF9QUk9UT0NPTCwgdGhlIGNvZGUgd2ls
bCBub3QgYmUgZXhlY3V0ZWQsIGFuZCB0aGUgYW1vdW50IG9mIFJPTSBuZWVkZWQgaXMgbmVnbGln
aWJsZS4NCklmIHlvdSBsb29rIGF0IG91ciBzdWJtaXNzaW9uLCB0aGUgaGNpLWg0IGNvdWxkIHBv
c3NpYmx5IGJlIHJldXNlZCB0byBzb21lIGV4dGVudC4gQmFzaWNhbGx5IHRoZSBwYWNrZXRpemlu
ZyB0byB0aGUgQmx1ZXRvb3RoIEg0IGNoYW5uZWxzIDEtNCBjb3VsZCBiZSByZS11c2VkLiBJbiBv
cmRlciB0byBhbGxvdyBmb3IgdmVuZG9yIHNwZWNpZmljIGNoYW5uZWxzIHRvIGJlIGhhbmRsZWQg
c29tZSBuZXcgcmVnaXN0cmF0aW9uIHN5c3RlbSBvbiB0b3Agb2YgaGNpLWg0IHBsdXMgYSBjYWxs
YmFjayBzeXN0ZW0gZm9yIGRhdGEgcmVjZXB0aW9uIHdvdWxkIGhhdmUgdG8gYmUgYWRkZWQgKGlu
IG9yZGVyIHRvIGZhY2lsaXRhdGUgc3lzdGVtcyB0aGF0IGRvIG5vdCB3YW50IGFsbCBkYXRhIHRv
IGJlIHNlbnQgZGlyZWN0bHkgdG8gdGhlIEJsdWV0b290aCBzdGFjayBzdWNoIGFzIHRoZSBDRzI5
MDAgZHJpdmVyKS4gSSdtIGFmcmFpZCB0aGF0IHdlIHdvdWxkIGhhdmUgYSBzaWduaWZpY2FudGx5
IG1vcmUgY29tcGxleCBzeXN0ZW0gYW5kIGxhcmdlciBhbW91bnQgb2YgY29kZSBpZiB3ZSB3b3Vs
ZCB0cnkgdG8gZ2VuZXJhbGl6ZSB0aGUgaGNpLWg0IG1vZHVsZS4gSSBkZWZpbml0ZWx5IHByZWZl
ciB0aGUgY3VycmVudCBtb2RlbCB3aGVyZSBhIHZlbmRvciBzcGVjaWZpYyBkcml2ZXIgcmVwbGFj
ZXMgdGhlIGhjaS1oNCBwcm90b2NvbCBkcml2ZXIuDQoNCj4gPiA+PiA+IGluc3RlYWQgb2YgY29t
bW9uLWhjaS1tb2R1bGUsIHdoeSBub3QgY3JlYXRlIGEgYWxnby1kcml2ZXIgbGF5ZXINCj4gJ2Fs
YQ0KPiA+ID4+ID4gaTJjID8gd2hlcmUgaW5kaXZpZHVhbCBkcml2ZXJzIGNhbiByZWdpc3RlciB0
aGVpciByZWNlaXZlDQo+IGhhbmRsZXJzIGZvcg0KPiA+ID4+ID4gZGF0YSBpbnRlcnByZXRhdGlv
biA/DQo+ID4gPg0KPiA+ID4gVGhhdCB3b3VsZCBiZSB3aGF0IEkgc3VnZ2VzdGVkIDstKQ0KPiA+
DQo+ID4gQnV0IGV2ZW4gaGVyZSB0b28sIHRoZSBhbGdvcyBsYXllciBpZiB5b3UgaW1hZ2luZSB3
aGljaCBjYW4gYmUgdGhlDQo+ID4gc29ydCBvZiB0aGUgZmlyc3QNCj4gPiByZWNlaXZlciBvZiBk
YXRhIGZyb20gdGhlIHRyYW5zcG9ydCB3b3VsZCByZWZlciB0byBCVCBoZWFkZXJzIHRvDQo+ID4g
aW50ZXJwcmV0IHRoZSBkYXRhIChub3QganVzdCBCVCwgYnV0IEZNL0dQUykNCj4gPiBhbmQgcGFz
cyBpdCBvbnRvIG90aGVyIHByb3RvY29sL2NsaWVudCBkcml2ZXJzLA0KPiANCj4gUmlnaHQsIHRo
YXQgaXMgdGhlIGVudGlyZSBpZGVhLCBhbmQgSSBkb24ndCBzZWUgYSBwcm9ibGVtIGhlcmUuDQo+
IElmIHlvdSBkbyB0aGlzLCB5b3UgdXNlIHRoZSBoZWFkZXJzIG9mIHRoZSB0d28gc3Vic3lzdGVt
cyB5b3UNCj4gaW50ZXJmYWNlIHdpdGguIFdoYXQgeW91IHNob3VsZCAvbm90LyBpbnN0ZWFkIGlz
IHVzZSBoZWFkZXINCj4gZmlsZXMgb2YgYSBzdWJzeXN0ZW0geW91IGRvbid0IGludGVyZmFjZSB3
aXRoIGFuZCByZWludGVycHJldGUNCj4gdGhlIGRlZmluaXRpb25zIGluIGNyZWF0aXZlIHdheXMs
IHdoaWNoIGlzIHdoYXQgSSB1bmRlcnN0b29kDQo+IHdhcyBiZWluZyBkaXNjdXNzZWQgZWFybGll
ci4NCj4gDQo+ID4gPj4gSW4gc29tZSB3YXkgeW91IHRoZW4gcnVuIGludG8gdGhlIHNhbWUgcHJv
YmxlbSBoYXMgSSBoYWQgaW4NCj4gcHJldmlvdXMgcGF0Y2gNCj4gPiA+PiBzZXRzLiBUaGUgZnVu
Y3Rpb25hbGl0aWVzIHN1cHBvcnRlZCBpcyByZWFsbHkgZGV0ZXJtaW5lZCBieSBlYWNoDQo+IGNo
aXAuDQo+ID4gPj4gWW91IG1pZ2h0IG9yIG1pZ2h0IG5vdCBoYXZlIGZvciBleGFtcGxlIEdQUyBp
biBhIGNlcnRhaW4gY2hpcC4gU28NCj4geW91IGRvIG5vdA0KPiA+ID4+IHdhbnQgYSBjZW50cmFs
IG1vZHVsZSB0byBleHBvc2UgYWxsIHBvc3NpYmxlIGNoYW5uZWxzIHRvIHRoZQ0KPiBzdGFja3Mg
b24gdG9wLg0KPiA+ID4+DQo+ID4gPj4gWW91IG9ubHkgd2FudCB0aGUgYWN0dWFsbHkgc3VwcG9y
dGVkIGZlYXR1cmVzIHRvIGJlIGV4cG9zZWQgdG8NCj4gdXBwZXIgbGF5ZXJzLg0KPiA+ID4+IFRo
ZW4gdGhlIE1GRCBzeXN0ZW0gaXMgcHJldHR5IG5pY2UuIEl0J3MgZWFzeSBhbmQgbW9kdWxhcml6
ZWQgdG8NCj4gZXhwb3NlIHRoZQ0KPiA+ID4+IGRpZmZlcmVudCBjaGFubmVscyBhcyBNRkQgY2Vs
bHMuDQo+ID4gPg0KPiA+ID4gQnV0IGFzIHNvb24gYXMgeW91IGhhdmUgdGhlIGNvbmNlcHQgb2Yg
Y2hhbm5lbHMgd2l0aCBhIGNsZWFybHkNCj4gZGVmaW5lZA0KPiA+ID4gaW50ZXJmYWNlLCB5b3Ug
aGF2ZSBhbG1vc3QgYWJzdHJhY3RlZCBpdCBlbm91Z2ggdG8gZ28gYWxsIHRoZSB3YXkuDQo+ID4N
Cj4gPiBTb21ldGhpbmcgbGlrZSB0aGlzIGlzIHdoYXQgdGhlIHJlY2VudCBSRkMgcG9zdGVkIHRv
DQo+ID4gbGttbC9saW51eC1ibHVldG9vdGgNCj4gPiBodHRwOi8vd3d3LnNwaW5pY3MubmV0L2xp
c3RzL2xpbnV4LWJsdWV0b290aC9tc2cwOTk5MC5odG1sLA0KPiA+IGl0IGtpbmRhIGxvb2tzIGNs
dW1zeQ0KPiA+IGJ1dCB3aGF0IEkgZmVlbCBpcyB3ZSBzaG91bGRuJ3Qgc2h5IGF3YXkgZnJvbSBu
b3QgcmVmZXJlbmNpbmcNCj4gPiBCbHVldG9vdGgsIChvciBtYXkgYmUgdG9tb3Jyb3cgR1BTDQo+
ID4gd2l0aCBOTUVBIGhlYWRlcnMpLi4uLg0KPiANCj4gVGhlIG9uZSBpbXBvcnRhbnQgZ29hbCBo
ZXJlIHNob3VsZCBiZSB0byBhdm9pZCBjb2RlIGR1cGxpY2F0aW9uLg0KPiBVc2luZyB0aGUgaGVh
ZGVyIHRvIGdldCB0aGUgZGF0YSBzdHJ1Y3R1cmVzIGZyb20gc2VwYXJhdGUgY29kZQ0KPiBtZWFu
cyB5b3UgbmVlZCB0byBoYXZlIHNpbWlsYXIgcGFyc2luZyBmdW5jdGlvbnMgaW4gZWFjaCBvZiB0
aGUgbW9kdWxlcw0KPiB1c2luZyBpdC4gTm90IHNoYXJpbmcgdGhlIGhlYWRlciB3b3VsZG4ndCBo
ZWxwLCBiZWNhdXNlIHRoZW4geW91IGVuZA0KPiB1cCBkdXBsaWNhdGluZyBldmVuIG1vcmUuIFRo
ZSByZWFsIHNvbHV0aW9uLCBzcGVha2luZyB2ZXJ5IGJyb2FkbHksDQo+IG11c3QgYmUgdG8gaGF2
ZSBhIGdlbmVyYWwgbW9kdWxlIHRoYXQgZGVhbHMgd2l0aCB3aGF0ZXZlciB0aGUgbW9yZQ0KPiBz
cGVjaWZpYyBtb2R1bGVzIGhhdmUgaW4gY29tbW9uLCBhbmQgaGF2ZSBhIGhlYWRlciBmaWxlIHRo
YXQgZGVmaW5lcw0KPiB0aGUgaW50ZXJmYWNlIHRvIGl0Lg0KPiANCg0KSW4gZ2VuZXJhbCBJIGFn
cmVlIHdpdGggeW91LCBidXQgdGhlcmUgYXJlIHNvbWUgcHJvYmxlbXMgaGVyZS4NClRoZSBtb3N0
IHVzZWQgQlQgSENJIGV2ZW50cyBhcmUgQ29tbWFuZCBTdGF0dXMgYW5kIENvbW1hbmQgQ29tcGxl
dGUuDQpDb21tYW5kIFN0YXR1cyBjb3VsZCBiZSBwYXJzZWQgY29tcGxldGVseSBpbiBhIGdvb2Qg
d2F5IChyZXRyaWV2aW5nIG9wIGNvZGUsIG5iciBvZiBjb21tYW5kcyBhbGxvd2VkLCBhbmQgc3Rh
dHVzIG9mIGNvbW1hbmQgc2VudCkuDQpDb21tYW5kIENvbXBsZXRlIGlzIGhvd2V2ZXIgcXVpdGUg
Y29tcGxleCBzaW5jZSB0aGUgcmV0dXJuZWQgZGF0YSB3aWxsIGRpZmZlciBkZXBlbmRpbmcgb24g
Y29tbWFuZCBzZW50LiBPcCBjb2RlIGFuZCBuYnIgb2YgY29tbWFuZHMgYWxsb3dlZCBjYW4gYmUg
cmV0cmlldmVkIGJ1dCBldmVyeXRoaW5nIGVsc2UgaGF2ZSB0byBiZSBleHRyYWN0ZWQgZGlmZmVy
ZW50bHkgZGVwZW5kaW5nIG9uIGNvbW1hbmQuIFRoaXMgbWVhbnMgdGhhdCB0aGVyZSBpcyBub3Qg
bXVjaCB0aGF0IHdpbGwgYmUgc2F2ZWQgaGVyZS4gQnV0IG1heWJlIHdlIGNvdWxkIGV4dHJhY3Qg
c29tZSBwYXJzaW5nIGludG8gY29tbW9uIGZ1bmN0aW9ucywgYnV0IEkgZG9uJ3QgdGhpbmsgeW91
IHdvdWxkIGdhaW4gdGhhdCBtdWNoLg0KTW9yZW92ZXIsIHRoaXMgd291bGQgbGVhZCB0byBhIG1h
am9yIHJlaW1wbGVtZW50YXRpb24gb2YgdGhlIGhjaV9jb3JlLmMgYW5kIHJlbGF0ZWQgZmlsZXMs
IHNpbmNlIHRoZXkgZG8gbm90IHVzZSBhbnkgZXhwb3J0ZWQgY29tbW9uIGZ1bmN0aW9ucyBhcyBp
dCBpcyB0b2RheS4gSSBkbyBub3Qga25vdyBpZiB0aGV5IChCbHVlWiBjb21tdW5pdHkpIHdvdWxk
IHdhbnQgdGhpcyBhbmQgSSBkbyBub3QgdGhpbmsgdGhhdCB0aGF0IHNob3VsZCBiZSBwYXJ0IG9m
IHRoZSBDRzI5MDAgZHJpdmVyIHRvIGRvLiBJdCBzaG91bGQgaW4gdGhhdCBjYXNlIGJlIGRvbmUg
c2VwYXJhdGVseS4NCg0KPiA+ID4+IEFsc28gbm90ZSB0aGF0IHRoZSBjb21tb24taGNpLW1vZHVs
ZSBpcyBvbmx5IHJlYWxseSB1c2VkIHVudGlsIHRoZQ0KPiBjb25uZWN0ZWQNCj4gPiA+PiBjaGlw
IGhhcyBiZWVuIGRldGVjdGVkLiBUaGUgY2hpcCBoYW5kbGVyIHdpbGwgdGhlbiBzZXQgdGhlDQo+
IGNhbGxiYWNrIGZ1bmN0aW9ucw0KPiA+ID4+IHNvIGFjdHVhbCBkYXRhIHRyYW5zbWlzc2lvbnMg
bmV2ZXIgcGFzcyB0aGUgY29tbW9uLWhjaS1tb2R1bGUuDQo+IFRoZXkgZ28gZGlyZWN0bHkNCj4g
PiA+PiBmcm9tIHRyYW5zcG9ydCB0byBjaGlwIGhhbmRsZXIuIFRoYXQgaXMgbm90IHJlYWxseSBz
aG93biBpbiB0aGUNCj4gcGljdHVyZSBhYm92ZS4NCj4gPiA+PiBKdXN0IGltYWdpbmUgdGhhdCBj
b21tb24taGNpLW1vZHVsZSBpcyByZW1vdmVkIGFmdGVyIGEgY2hpcCBoYXMNCj4gYmVlbiBjb25u
ZWN0ZWQNCj4gPiA+PiBhbmQgYSBjaGlwIGhhbmRsZXIgaGFzIGJlZW4gZGV0ZXJtaW5lZC4NCj4g
PiA+Pg0KPiA+ID4+IEkgaG9wZSBJIGhhdmVuJ3QgbWlzdW5kZXJzdG9vZCB5b3VyIHF1ZXN0aW9u
LiBJIGRvIG5vdCBrbm93IG11Y2gNCj4gYWJvdXQgdGhlIEkyQw0KPiA+ID4+IHN5c3RlbSwgYnV0
IEkgdHJpZWQgdG8gdW5kZXJzdGFuZCB5b3VyIHF1ZXN0aW9uIGFzIGJlc3QgYXMgSQ0KPiBjb3Vs
ZC4NCj4gPiA+DQo+ID4gPiBJIHRoaW5rIHRoZXJlIGlzIGEgZGlzY29ubmVjdCB3aGVuIHRhbGtp
bmcgYWJvdXQgaGllcmFyY2hpZXMsIGFzIGl0DQo+IGNhbiBiZSBhcHBsaWVkDQo+ID4gPiB0byBk
aWZmZXJlbnQgYXJlYXM6DQo+ID4gPg0KPiA+ID4gKiBtb2R1bGUgZGVwZW5kZW5jaWVzDQo+ID4g
PiAqIGRldmljZSBkZXRlY3Rpb24NCj4gPiA+ICogc3lzZnMgb2JqZWN0IGhpZXJhcmNoeQ0KPiA+
ID4gKiBkYXRhIGZsb3cNCj4gPg0KPiA+IG1vZHVsZSBkZXBlbmRlY3ktd2lzZSBJIGFncmVlLA0K
PiA+IEkgd291bGQgd2FudCBGTS1WNEwyIHdpdGhvdXQgQlQgb3IgSSBtaWdodCB3YW50IEdQUyBz
aW1wbGlzdGljIGNoYXINCj4gPiBkcml2ZXIgd2l0aG91dCBCVCBvciBGTSBWNEwyLg0KPiANCj4g
QnV0IHlvdSdkIHN0aWxsIG5lZWQgdG8gaGF2ZSBhbiBIQ0kgbW9kdWxlLiBJIGJlbGlldmUgcmln
aHQgbm93LCB0aGUNCj4gaGNpIG1vZHVsZSBkZXBlbmRzIG9uIHRoZSBibHVldG9vdGggbW9kdWxl
LCBhbmQgeW91IGFyZSByaWdodCB0aGF0IHRoaXMNCj4gaXMgYW4gdW5kZXNpcmFibGUgZGVwZW5k
ZW5jeSB0byBoYXZlIGZvciBhIEdQUyBtb2R1bGUuIEhvd2V2ZXIsIHRoZQ0KPiBzb2x1dGlvbg0K
PiB0byB0aGlzIHNob3VsZCBub3QgYmUgdG8gbWFrZSBHUFMgaW5kZXBlbmRlbnQgb2YgSENJLCBi
dXQgdG8gbWFrZSBwYXJ0cw0KPiBvZiBIQ0kgaW5kZXBlbmRlbnQgb2YgYmx1ZXRvb3RoLg0KPiAN
Cg0KRm9yIHRoZSBDRzI5MDAgdGhhdCBpcyBub3QgcG9zc2libGUuIEV2ZW4gaWYgeW91IGFyZSBy
dW5uaW5nIGp1c3QgR1BTIHlvdSBzdGlsbCBtdXN0IGRvd25sb2FkIHBhdGNoZXMgYW5kIHNldHRp
bmdzIGFuZCB0aGF0IGlzIGRvbmUgdGhyb3VnaCBIQ0kgY29tbWFuZHMgb3ZlciB0aGUgQmx1ZXRv
b3RoIGNvbW1hbmQgaW50ZXJmYWNlLiBXZSBhbHNvIHVzZSBCbHVldG9vdGggY29tbWFuZHMgdG8g
aWRlbnRpZnkgdGhlIGNvbnRyb2xsZXIuDQoNCj4gPiBkZXZpY2UgZGV0ZWN0aW9uIHdpc2UsIEl0
IGlzIGEgcHJvYmxlbSwgdGhlcmUgaXMgbm90ICJfcHJvYmUiDQo+ID4gbWVjaGFuaXNtIGZvciBV
QVJUIGJhc2VkIHRyYW5zcG9ydCBhcyBpdCBpcw0KPiA+IHVuZGVyc3RhbmRhYmxlLCBhbmQgcHJl
dHR5IG11Y2ggdGhlIGRyaXZlciB3b3VsZCBlbmQgdXAgYmVpbmcNCj4gcGxhdGZvcm0NCj4gPiBk
ZXZpY2UgZHJpdmVyIC4uLg0KPiANCj4gVGhlIHBsYXRmb3JtIGRldmljZSBpcyBqdXN0IHRoZSBs
b3dlc3QgbGV2ZWwgaW4gdGhlIGRldmljZSBoaWVyYXJjaHkuDQo+IA0KPiBJZiBlYWNoIEhDSSBj
aGFubmVsIGlzIGEgZGV2aWNlLCB5b3UgY2FuIHN0YWNrIGJ0LCBncHMsIGF1ZGlvLCAuLi4NCj4g
ZGV2aWNlcyBhbGwgb24gdG9wIG9mIHRoZSBIQ0kgZGV2aWNlLCB3aGljaCBpcyBlaXRoZXIgc3Rh
Y2tlZCBvbiB0b3ANCj4gb2YgYSBzZXJpYWwgcG9ydCBvciBpbiBzb21lIG90aGVyIHdheSBjb25u
ZWN0ZWQgdG8gdGhlIHVuZGVyeWluZw0KPiB0cmFuc3BvcnQuDQo+IA0KPiBJbiB0aGlzIGNhc2Us
IHRoZSBjaGFubmVscyB0aGVtc2VsdmVzIGFyZSBub3QgcGxhdGZvcm0gZGV2aWNlcywgYnV0DQo+
IHdvdWxkIGdldCBhIG5ldyBidXMgZm9yIHRoZW0uIFRoYXQgYnVzIGlzIHBvcHVsYXRlZCBieSBh
IGRyaXZlciB0aGF0DQo+IG93bnMgdGhlIEhDSSBhbmQgdGhhdCBrbm93cyAoZS5nLiBmcm9tIGl0
cyBwbGF0Zm9ybSBkYXRhLCBoYXJkd2FyZQ0KPiByZWdpc3RlcnMsIHVzZXIgY29uZmlnIG9yIGRl
dmljZSB0cmVlKSB3aGF0IGNoYW5uZWxzIGFyZSBwcmVzZW50Lg0KPiANCj4gPiBkYXRhIGZsb3cg
aXMgd2hlcmUgSSBndWVzcyB0aGUgYWJzdHJhY3Rpb24gaGFzIHRvIGxpZSBpbiwgZm9yDQo+ID4g
ZGlmZmVyZW50IHZlbmRvcnMuLi4NCj4gDQo+IEkgZG9uJ3Qga25vdyB3aGF0IHlvdSBtZWFuIHdp
dGggdGhhdC4gTXkgcG9pbnQgd2FzIHRoYXQgd2UgbmVlZCB0bw0KPiBjb25zaWRlciBhbGwgdGhl
IGhpZXJhcmNoaWVzLCBhbmQgdGhhdCB0aGV5IG1pZ2h0IGJlIGRpZmZlcmVudC4NCj4gDQo+IAlB
cm5kDQoNCi9QLUcNCg0K
^ permalink raw reply
* Re: [Patch] Kill off warning: ‘inline’ is not at beginning of declaration
From: John W. Linville @ 2011-01-17 13:55 UTC (permalink / raw)
To: Jesper Juhl
Cc: linux-kernel, trivial, alsa-devel, linux-wireless, netdev,
ocfs2-devel, linux-edac, linux-bluetooth, oprofile-list,
Andi Kleen, David Teigland, Jens Axboe, Stephen Hemminger,
Greg Kroah-Hartman, Takashi Iwai, Jaroslav Kysela, Johannes Berg,
Patrick McHardy, Hideaki YOSHIFUJI, James Morris,
Pekka Savola (ipv6), Alexey Kuznetsov, David S. Miller,
Frederic Weisbecker, Joel Becker, Mark Fasheh,
Mauro Carvalho Chehab, Gustavo F. Padovan, Marcel Holtmann, x86,
H. Peter Anvin, Ingo Molnar, Thomas Gleixner, Robert Richter
In-Reply-To: <alpine.LNX.2.00.1101170000270.13377@swampdragon.chaosbits.net>
On Mon, Jan 17, 2011 at 12:09:38AM +0100, Jesper Juhl wrote:
> Fix a bunch of
> warning: ‘inline’ is not at beginning of declaration
> messages when building a 'make allyesconfig' kernel with -Wextra.
>
> These warnings are trivial to kill, yet rather annoying when building with
> -Wextra.
> The more we can cut down on pointless crap like this the better (IMHO).
>
> A previous patch to do this for a 'allnoconfig' build has already been
> merged. This just takes the cleanup a little further.
>
> Signed-off-by: Jesper Juhl <jj@chaosbits.net>
> ---
> net/mac80211/tx.c | 2 +-
ack
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply
* Re: [PATCH] net: bluetooth: fix locking problem
From: Andrei Emeltchenko @ 2011-01-17 10:28 UTC (permalink / raw)
To: Vasiliy Kulikov
Cc: kernel-janitors, Marcel Holtmann, Gustavo F. Padovan,
David S. Miller, linux-bluetooth, netdev, linux-kernel
In-Reply-To: <1295258917-31092-1-git-send-email-segoon@openwall.com>
On Mon, Jan 17, 2011 at 12:08 PM, Vasiliy Kulikov <segoon@openwall.com> wro=
te:
> If alloc_skb() failed we still hold hci_dev_list_lock. =A0The code should
> unlock it before exit.
>
> Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
> ---
> =A0Compile tested only.
>
> =A0net/bluetooth/mgmt.c | =A0 =A04 +++-
> =A01 files changed, 3 insertions(+), 1 deletions(-)
>
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index f827fd9..ace8726 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -111,8 +111,10 @@ static int read_index_list(struct sock *sk)
>
> =A0 =A0 =A0 =A0body_len =3D sizeof(*ev) + sizeof(*rp) + (2 * count);
> =A0 =A0 =A0 =A0skb =3D alloc_skb(sizeof(*hdr) + body_len, GFP_ATOMIC);
> - =A0 =A0 =A0 if (!skb)
> + =A0 =A0 =A0 if (!skb) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 read_unlock(&hci_dev_list_lock);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return -ENOMEM;
> + =A0 =A0 =A0 }
patch was send already on weekend
>
> =A0 =A0 =A0 =A0hdr =3D (void *) skb_put(skb, sizeof(*hdr));
> =A0 =A0 =A0 =A0hdr->opcode =3D cpu_to_le16(MGMT_EV_CMD_COMPLETE);
> --
> 1.7.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" i=
n
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at =A0http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at =A0http://www.tux.org/lkml/
>
^ permalink raw reply
* [PATCH] net: bluetooth: fix locking problem
From: Vasiliy Kulikov @ 2011-01-17 10:08 UTC (permalink / raw)
To: kernel-janitors
Cc: Marcel Holtmann, Gustavo F. Padovan, David S. Miller,
linux-bluetooth, netdev, linux-kernel
If alloc_skb() failed we still hold hci_dev_list_lock. The code should
unlock it before exit.
Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
---
Compile tested only.
net/bluetooth/mgmt.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index f827fd9..ace8726 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -111,8 +111,10 @@ static int read_index_list(struct sock *sk)
body_len = sizeof(*ev) + sizeof(*rp) + (2 * count);
skb = alloc_skb(sizeof(*hdr) + body_len, GFP_ATOMIC);
- if (!skb)
+ if (!skb) {
+ read_unlock(&hci_dev_list_lock);
return -ENOMEM;
+ }
hdr = (void *) skb_put(skb, sizeof(*hdr));
hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH 1/4] Bluetooth: Send an Invalid PDU Size Error Response for Service Search Req
From: Johan Hedberg @ 2011-01-17 9:20 UTC (permalink / raw)
To: Angela Bartholomaus; +Cc: linux-bluetooth, rshaffer, marcel
In-Reply-To: <1282755705-28400-2-git-send-email-angelab@codeaurora.org>
Hi Angela,
On Wed, Aug 25, 2010, Angela Bartholomaus wrote:
> Send error code 0x04 per CoreSpecv2.1, sec 4.4 for TP/SERVER/SS/BI-01-C
> ---
> src/sdpd-request.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/src/sdpd-request.c b/src/sdpd-request.c
> index d56ffc2..cc9fe82 100644
> --- a/src/sdpd-request.c
> +++ b/src/sdpd-request.c
> @@ -367,7 +367,7 @@ static int service_search_req(sdp_req_t *req, sdp_buf_t *buf)
> mlen = scanned + sizeof(uint16_t) + 1;
> // ensure we don't read past buffer
> if (plen < mlen || plen != mlen + *(uint8_t *)(pdata+sizeof(uint16_t))) {
> - status = SDP_INVALID_SYNTAX;
> + status = SDP_INVALID_PDU_SIZE;
> goto done;
> }
I'm not sure exactly what test system you tested this with, but it
breaks TP/SERVER/SS/BI-02-C with the BITE tester with test vector
1.0.40.0. Also, this code path doesn't seem to be traversed at all for
TP/SERVER/SS/BI-01-C which the patch claims to fix. In order to get a
clean test report again from the BITE I went ahead and reverted[1] this
patch. Now both SS/BI-01-C and SS/BI-02-C are passing with the BITE.
Your other SDP patches don't seem to have any issues.
Johan
[1] http://git.kernel.org/?p=bluetooth/bluez.git;a=commitdiff;h=24dbc52388f1ef2e759d24d74cd32f93531c8857
^ permalink raw reply
* Re: [RFC] AVRCP 1.4 : Design proposal for future on Target Role
From: santhosh aj @ 2011-01-17 6:52 UTC (permalink / raw)
To: tim.howes; +Cc: linux-bluetooth
In-Reply-To: <1AFE20D16950C745A2A83986B72E8748011F5775C175@EMEXM3131.dir.svc.accenture.com>
On Tue, Dec 7, 2010 at 3:52 PM, <tim.howes@accenture.com> wrote:
>
> Hi Shivendra,
>
> > AVRCP 1.4
> > ==========
> >
> > - Add SDP record for AVRCP 1.4 to inform CT of the version and features
> > supported by target.
> >
> > Priority: Medium
> > Complexity: C1
>
> One extra issue here is that the SDP record needs to vary according to the players running: if the AVRCP layer statically set the AVRCP version in the SDP record to be 1.4, AND the player(s) was a legacy pre-1.4 application that did not know about browsing then the device integrator would have compliance issues.
>
> So I believe there is a need for an API that the player would set if it can support mandatory v.1.4 target features. If the API is not called (eg by backwards compatibility) then the SDP record would continue to publish version 1.3.
As I understand from AVRCP Spec 1.4 section 6.10.2.1 SDP record is
used as to indicate what the avrcp profile implementation is capable
of supporting. The Player Feature Bitmask provides information on the
capabilities of specific player. So Even if you Publish 1.4 SDP
Record, depending on the player/s registed the capability is exposed.
>
> This may increase your complexity value.
>
> > As per spec section 6.6.1 GetElementAttributes
> > As per spec section 6.10.4.3 GetItemAttributes
>
> Note that by overall spec design these are very similar. Indeed, according to 6.10.4.3, AVRCP 1.4 CTs shall only use GIA when communicating with 1.4 TGs - GEA is effectively deprecated (of course a 1.4 TG may see a GEA from a legacy CT). I believe it would assist media players if these operations were multiplexed through one API to hide their underlying differences. It would be annoying for players to have to implement two callbacks to process these two similar operations.
>
> This may change (decrease?) your complexity for these.
>
>
> Cheers
>
> Tim
>
>
> This message is for the designated recipient only and may contain privileged, proprietary, or otherwise private information. If you have received it in error, please notify the sender immediately and delete the original. Any other use of the email by you is prohibited.
> --
> 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
Regards
Santhosh AJ
^ permalink raw reply
* [Patch] Kill off warning: ‘inline’ is not at beginning of declaration
From: Jesper Juhl @ 2011-01-16 23:09 UTC (permalink / raw)
To: linux-kernel
Cc: trivial, alsa-devel, linux-wireless, netdev, ocfs2-devel,
linux-edac, linux-bluetooth, oprofile-list, Andi Kleen,
David Teigland, Jens Axboe, Stephen Hemminger, Greg Kroah-Hartman,
Takashi Iwai, Jaroslav Kysela, John W. Linville, Johannes Berg,
Patrick McHardy, Hideaki YOSHIFUJI, James Morris,
Pekka Savola (ipv6), Alexey Kuznetsov, David S. Miller,
Frederic Weisbecker, Frederic Weisbecker, Joel Becker,
Mark Fasheh, Mauro Carvalho Chehab, Gustavo F. Padovan,
Marcel Holtmann, x86, H. Peter Anvin, Ingo Molnar,
Thomas Gleixner, Robert Richter
[-- Attachment #1: Type: TEXT/PLAIN, Size: 7170 bytes --]
Fix a bunch of
warning: ‘inline’ is not at beginning of declaration
messages when building a 'make allyesconfig' kernel with -Wextra.
These warnings are trivial to kill, yet rather annoying when building with
-Wextra.
The more we can cut down on pointless crap like this the better (IMHO).
A previous patch to do this for a 'allnoconfig' build has already been
merged. This just takes the cleanup a little further.
Signed-off-by: Jesper Juhl <jj@chaosbits.net>
---
arch/x86/oprofile/op_model_p4.c | 2 +-
drivers/bluetooth/btusb.c | 4 ++--
drivers/cpuidle/sysfs.c | 2 +-
drivers/edac/i7300_edac.c | 2 +-
fs/ocfs2/dir.c | 2 +-
kernel/trace/ring_buffer.c | 2 +-
net/ipv6/inet6_hashtables.c | 2 +-
net/mac80211/tx.c | 2 +-
sound/pci/au88x0/au88x0.h | 4 ++--
sound/pci/au88x0/au88x0_core.c | 4 ++--
10 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/arch/x86/oprofile/op_model_p4.c b/arch/x86/oprofile/op_model_p4.c
index 9fadec0..98ab130 100644
--- a/arch/x86/oprofile/op_model_p4.c
+++ b/arch/x86/oprofile/op_model_p4.c
@@ -50,7 +50,7 @@ static inline void setup_num_counters(void)
#endif
}
-static int inline addr_increment(void)
+static inline int addr_increment(void)
{
#ifdef CONFIG_SMP
return smp_num_siblings == 2 ? 2 : 1;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 1da773f..92d29bf 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -424,7 +424,7 @@ static void btusb_isoc_complete(struct urb *urb)
}
}
-static void inline __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
+static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
{
int i, offset = 0;
@@ -775,7 +775,7 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
}
}
-static int inline __set_isoc_interface(struct hci_dev *hdev, int altsetting)
+static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
{
struct btusb_data *data = hdev->driver_data;
struct usb_interface *intf = data->isoc;
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 0310ffa..be7917ec 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -300,7 +300,7 @@ static struct kobj_type ktype_state_cpuidle = {
.release = cpuidle_state_sysfs_release,
};
-static void inline cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
+static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
{
kobject_put(&device->kobjs[i]->kobj);
wait_for_completion(&device->kobjs[i]->kobj_unregister);
diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c
index 05523b5..76d1f57 100644
--- a/drivers/edac/i7300_edac.c
+++ b/drivers/edac/i7300_edac.c
@@ -162,7 +162,7 @@ static struct edac_pci_ctl_info *i7300_pci;
#define AMBPRESENT_0 0x64
#define AMBPRESENT_1 0x66
-const static u16 mtr_regs[MAX_SLOTS] = {
+static const u16 mtr_regs[MAX_SLOTS] = {
0x80, 0x84, 0x88, 0x8c,
0x82, 0x86, 0x8a, 0x8e
};
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index d417b3f..f97b6f1 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -354,7 +354,7 @@ static inline int ocfs2_match(int len,
/*
* Returns 0 if not found, -1 on failure, and 1 on success
*/
-static int inline ocfs2_search_dirblock(struct buffer_head *bh,
+static inline int ocfs2_search_dirblock(struct buffer_head *bh,
struct inode *dir,
const char *name, int namelen,
unsigned long offset,
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index bd1c35a..6ee56b4 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -669,7 +669,7 @@ static struct list_head *rb_list_head(struct list_head *list)
* the reader page). But if the next page is a header page,
* its flags will be non zero.
*/
-static int inline
+static inline int
rb_is_head_page(struct ring_buffer_per_cpu *cpu_buffer,
struct buffer_page *page, struct list_head *list)
{
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 633a6c2..b531972 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -124,7 +124,7 @@ out:
}
EXPORT_SYMBOL(__inet6_lookup_established);
-static int inline compute_score(struct sock *sk, struct net *net,
+static inline int compute_score(struct sock *sk, struct net *net,
const unsigned short hnum,
const struct in6_addr *daddr,
const int dif)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 5950e3a..a449dd5 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -173,7 +173,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
return cpu_to_le16(dur);
}
-static int inline is_ieee80211_device(struct ieee80211_local *local,
+static inline int is_ieee80211_device(struct ieee80211_local *local,
struct net_device *dev)
{
return local == wdev_priv(dev->ieee80211_ptr);
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index cf46bba..ecb8f4d 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -211,7 +211,7 @@ static void vortex_adbdma_startfifo(vortex_t * vortex, int adbdma);
//static void vortex_adbdma_stopfifo(vortex_t *vortex, int adbdma);
static void vortex_adbdma_pausefifo(vortex_t * vortex, int adbdma);
static void vortex_adbdma_resumefifo(vortex_t * vortex, int adbdma);
-static int inline vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma);
+static inline int vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma);
static void vortex_adbdma_resetup(vortex_t *vortex, int adbdma);
#ifndef CHIP_AU8810
@@ -219,7 +219,7 @@ static void vortex_wtdma_startfifo(vortex_t * vortex, int wtdma);
static void vortex_wtdma_stopfifo(vortex_t * vortex, int wtdma);
static void vortex_wtdma_pausefifo(vortex_t * vortex, int wtdma);
static void vortex_wtdma_resumefifo(vortex_t * vortex, int wtdma);
-static int inline vortex_wtdma_getlinearpos(vortex_t * vortex, int wtdma);
+static inline int vortex_wtdma_getlinearpos(vortex_t * vortex, int wtdma);
#endif
/* global stuff. */
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 23f49f3..d43252a 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -1249,7 +1249,7 @@ static void vortex_adbdma_resetup(vortex_t *vortex, int adbdma) {
}
}
-static int inline vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma)
+static inline int vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma)
{
stream_t *dma = &vortex->dma_adb[adbdma];
int temp;
@@ -1498,7 +1498,7 @@ static int vortex_wtdma_getcursubuffer(vortex_t * vortex, int wtdma)
POS_SHIFT) & POS_MASK);
}
#endif
-static int inline vortex_wtdma_getlinearpos(vortex_t * vortex, int wtdma)
+static inline int vortex_wtdma_getlinearpos(vortex_t * vortex, int wtdma)
{
stream_t *dma = &vortex->dma_wt[wtdma];
int temp;
--
Jesper Juhl <jj@chaosbits.net> http://www.chaosbits.net/
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please.
^ permalink raw reply related
* Re: BCM2045B2
From: Oleg Kravchenko @ 2011-01-16 22:51 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <492EFCDC.1050504@kaa.org.ua>
Any idea?
=D1=87=D0=B5=D1=82=D0=B2=D0=B5=D1=80 27 =D0=BB=D0=B8=D1=81=D1=82=D0=BE=D0=
=BF=D0=B0=D0=B4 2008 22:02:36 Oleg Kravchenko =D0=B2=D0=B8 =D0=BD=D0=B0=D0=
=BF=D0=B8=D1=81=D0=B0=D0=BB=D0=B8:
> Marcel Holtmann =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=B2(=D0=BB=D0=B0):
> > Hi Oleg,
> >=20
> >> Asus P535 details on http://www.kaa.org.ua/asus-p535/hardware.html
> >> Bluetooth chip BCM2045B2 connected to the pxa internal usb host.
> >>=20
> >> I think this chip need firmware, because it is can only search
> >> How I can upload firmware to the this chip?
> >=20
> > no, the chip needs a HCI Reset call. Load btusb with reset=3D1. And send
> > the output of /proc/bus/usb/devices for this dongle.
> >=20
> > Regards
> >=20
> > Marcel
>=20
> I am load modprobe btusb reset=3D1
>=20
> Content of /proc/bus/usb/devices:
>=20
> T: Bus=3D01 Lev=3D00 Prnt=3D00 Port=3D00 Cnt=3D00 Dev#=3D 1 Spd=3D12 M=
xCh=3D 3
> B: Alloc=3D 22/900 us ( 2%), #Int=3D 1, #Iso=3D 0
> D: Ver=3D 1.10 Cls=3D09(hub ) Sub=3D00 Prot=3D00 MxPS=3D64 #Cfgs=3D 1
> P: Vendor=3D1d6b ProdID=3D0001 Rev=3D 2.06
> S: Manufacturer=3DLinux 2.6.27 ohci_hcd
> S: Product=3DPXA27x OHCI
> S: SerialNumber=3Dpxa27x
> C:* #Ifs=3D 1 Cfg#=3D 1 Atr=3De0 MxPwr=3D 0mA
> I:* If#=3D 0 Alt=3D 0 #EPs=3D 1 Cls=3D09(hub ) Sub=3D00 Prot=3D00 Driver=
=3Dhub
> E: Ad=3D81(I) Atr=3D03(Int.) MxPS=3D 2 Ivl=3D255ms
>=20
> T: Bus=3D01 Lev=3D01 Prnt=3D01 Port=3D00 Cnt=3D01 Dev#=3D 2 Spd=3D12 M=
xCh=3D 0
> D: Ver=3D 2.00 Cls=3De0(unk. ) Sub=3D01 Prot=3D01 MxPS=3D64 #Cfgs=3D 1
> P: Vendor=3D0a5c ProdID=3D2045 Rev=3D 1.12
> S: Manufacturer=3DBroadcom Corp
> S: Product=3DBCM2045A
> S: SerialNumber=3D000000000000
> C:* #Ifs=3D 4 Cfg#=3D 1 Atr=3Da0 MxPwr=3D100mA
> I:* If#=3D 0 Alt=3D 0 #EPs=3D 3 Cls=3De0(unk. ) Sub=3D01 Prot=3D01 Driver=
=3Dbtusb
> E: Ad=3D81(I) Atr=3D03(Int.) MxPS=3D 16 Ivl=3D1ms
> E: Ad=3D82(I) Atr=3D02(Bulk) MxPS=3D 64 Ivl=3D0ms
> E: Ad=3D02(O) Atr=3D02(Bulk) MxPS=3D 64 Ivl=3D0ms
> I:* If#=3D 1 Alt=3D 0 #EPs=3D 2 Cls=3De0(unk. ) Sub=3D01 Prot=3D01 Driver=
=3Dbtusb
> E: Ad=3D83(I) Atr=3D01(Isoc) MxPS=3D 0 Ivl=3D1ms
> E: Ad=3D03(O) Atr=3D01(Isoc) MxPS=3D 0 Ivl=3D1ms
> I: If#=3D 1 Alt=3D 1 #EPs=3D 2 Cls=3De0(unk. ) Sub=3D01 Prot=3D01 Driver=
=3Dbtusb
> E: Ad=3D83(I) Atr=3D01(Isoc) MxPS=3D 9 Ivl=3D1ms
> E: Ad=3D03(O) Atr=3D01(Isoc) MxPS=3D 9 Ivl=3D1ms
> I: If#=3D 1 Alt=3D 2 #EPs=3D 2 Cls=3De0(unk. ) Sub=3D01 Prot=3D01 Driver=
=3Dbtusb
> E: Ad=3D83(I) Atr=3D01(Isoc) MxPS=3D 17 Ivl=3D1ms
> E: Ad=3D03(O) Atr=3D01(Isoc) MxPS=3D 17 Ivl=3D1ms
> I: If#=3D 1 Alt=3D 3 #EPs=3D 2 Cls=3De0(unk. ) Sub=3D01 Prot=3D01 Driver=
=3Dbtusb
> E: Ad=3D83(I) Atr=3D01(Isoc) MxPS=3D 25 Ivl=3D1ms
> E: Ad=3D03(O) Atr=3D01(Isoc) MxPS=3D 25 Ivl=3D1ms
> I: If#=3D 1 Alt=3D 4 #EPs=3D 2 Cls=3De0(unk. ) Sub=3D01 Prot=3D01 Driver=
=3Dbtusb
> E: Ad=3D83(I) Atr=3D01(Isoc) MxPS=3D 33 Ivl=3D1ms
> E: Ad=3D03(O) Atr=3D01(Isoc) MxPS=3D 33 Ivl=3D1ms
> I: If#=3D 1 Alt=3D 5 #EPs=3D 2 Cls=3De0(unk. ) Sub=3D01 Prot=3D01 Driver=
=3Dbtusb
> E: Ad=3D83(I) Atr=3D01(Isoc) MxPS=3D 49 Ivl=3D1ms
> E: Ad=3D03(O) Atr=3D01(Isoc) MxPS=3D 49 Ivl=3D1ms
> I:* If#=3D 2 Alt=3D 0 #EPs=3D 2 Cls=3Dff(vend.) Sub=3Dff Prot=3Dff Driver=
=3D(none)
> E: Ad=3D84(I) Atr=3D02(Bulk) MxPS=3D 32 Ivl=3D0ms
> E: Ad=3D04(O) Atr=3D02(Bulk) MxPS=3D 32 Ivl=3D0ms
> I:* If#=3D 3 Alt=3D 0 #EPs=3D 0 Cls=3Dfe(app. ) Sub=3D01 Prot=3D00 Driver=
=3D(none)
>=20
> When I try establish bnep connection:
> localhost ~ # ifconfig bnep0 10.9.0.2
> SIOCSIFFLAGS: Cannot assign requested address
>=20
> So when I enable bluetooth in Windows Mobile
> localhost ~ # ifconfig bnep0 10.9.0.2
> work's fine :)
>=20
> This is a Windows bluetooth log:
> 15:16:55:512 RadioInitPreLoad Start
> 15:16:55:553 Using USB, no PreLoad code
> 15:16:55:579 RadioInitPreLoad End
> 15:16:56:351 RadioInitPostLoad Start
> 15:16:56:365 BRCM_PostLoad TOP
> 15:16:56:385 Send_HCI_Read_BDaddr was successful
> 15:16:56:399 BRCM2045CFG2RAMmain(USB) TOP
> 15:16:56:412 Sending HCI_DOWNLOAD_MINIDRIVER
> 15:16:57:946 Writing config binary image through HCI_WRITE_RAM commands
> 15:16:57:971 Loaded config data file
> \Windows\BCM2045B2_002.002.011.0131.0001.hcd, length=3D9459 bytes
> 15:16:57:985 Using USB, and using an external .hcd config file
> 15:16:57:000 target_ram_addr =3D 0x00:08:5c:70
> 15:16:57:014 launch_ram_addr =3D 0x00:08:8b:d8
> 15:16:57:039 HCIVSWriteRAM(addr=3D0x70:0x5c:0x08:0x00, nbytes=3D139)
> 15:16:57:067 HCIVSWriteRAM(addr=3D0xf7:0x5c:0x08:0x00, nbytes=3D255)
> 15:16:57:106 HCIVSWriteRAM(addr=3D0xf2:0x5d:0x08:0x00, nbytes=3D255)
> 15:16:57:136 HCIVSWriteRAM(addr=3D0xed:0x5e:0x08:0x00, nbytes=3D255)
> 15:16:57:165 HCIVSWriteRAM(addr=3D0xe8:0x5f:0x08:0x00, nbytes=3D255)
> 15:16:57:195 HCIVSWriteRAM(addr=3D0xe3:0x60:0x08:0x00, nbytes=3D255)
> 15:16:57:226 HCIVSWriteRAM(addr=3D0xde:0x61:0x08:0x00, nbytes=3D255)
> 15:16:57:257 HCIVSWriteRAM(addr=3D0xd9:0x62:0x08:0x00, nbytes=3D255)
> 15:16:57:287 HCIVSWriteRAM(addr=3D0xd4:0x63:0x08:0x00, nbytes=3D255)
> 15:16:57:317 HCIVSWriteRAM(addr=3D0xcf:0x64:0x08:0x00, nbytes=3D255)
> 15:16:57:347 HCIVSWriteRAM(addr=3D0xca:0x65:0x08:0x00, nbytes=3D255)
> 15:16:57:377 HCIVSWriteRAM(addr=3D0xc5:0x66:0x08:0x00, nbytes=3D255)
> 15:16:57:429 HCIVSWriteRAM(addr=3D0xc0:0x67:0x08:0x00, nbytes=3D255)
> 15:16:57:459 HCIVSWriteRAM(addr=3D0xbb:0x68:0x08:0x00, nbytes=3D255)
> 15:16:57:489 HCIVSWriteRAM(addr=3D0xb6:0x69:0x08:0x00, nbytes=3D255)
> 15:16:57:553 HCIVSWriteRAM(addr=3D0xb1:0x6a:0x08:0x00, nbytes=3D255)
> 15:16:57:654 HCIVSWriteRAM(addr=3D0xac:0x6b:0x08:0x00, nbytes=3D255)
> 15:16:57:729 HCIVSWriteRAM(addr=3D0xa7:0x6c:0x08:0x00, nbytes=3D255)
> 15:16:58:767 HCIVSWriteRAM(addr=3D0xa2:0x6d:0x08:0x00, nbytes=3D255)
> 15:16:58:890 HCIVSWriteRAM(addr=3D0x9d:0x6e:0x08:0x00, nbytes=3D255)
> 15:16:58:973 HCIVSWriteRAM(addr=3D0x98:0x6f:0x08:0x00, nbytes=3D255)
> 15:16:58:208 HCIVSWriteRAM(addr=3D0x93:0x70:0x08:0x00, nbytes=3D255)
> 15:16:58:384 HCIVSWriteRAM(addr=3D0x8e:0x71:0x08:0x00, nbytes=3D255)
> 15:16:58:607 HCIVSWriteRAM(addr=3D0x89:0x72:0x08:0x00, nbytes=3D255)
> 15:16:58:737 HCIVSWriteRAM(addr=3D0x84:0x73:0x08:0x00, nbytes=3D255)
> 15:16:59:972 HCIVSWriteRAM(addr=3D0x7f:0x74:0x08:0x00, nbytes=3D255)
> 15:16:59:025 HCIVSWriteRAM(addr=3D0x7a:0x75:0x08:0x00, nbytes=3D255)
> 15:16:59:126 HCIVSWriteRAM(addr=3D0x75:0x76:0x08:0x00, nbytes=3D255)
> 15:16:59:155 HCIVSWriteRAM(addr=3D0x70:0x77:0x08:0x00, nbytes=3D255)
> 15:16:59:372 HCIVSWriteRAM(addr=3D0x6b:0x78:0x08:0x00, nbytes=3D255)
> 15:16:59:447 HCIVSWriteRAM(addr=3D0x66:0x79:0x08:0x00, nbytes=3D255)
> 15:16:59:590 HCIVSWriteRAM(addr=3D0x61:0x7a:0x08:0x00, nbytes=3D255)
> 15:16:59:621 HCIVSWriteRAM(addr=3D0x5c:0x7b:0x08:0x00, nbytes=3D255)
> 15:16:59:670 HCIVSWriteRAM(addr=3D0x57:0x7c:0x08:0x00, nbytes=3D255)
> 15:16:59:711 HCIVSWriteRAM(addr=3D0x52:0x7d:0x08:0x00, nbytes=3D255)
> 15:16:59:752 HCIVSWriteRAM(addr=3D0x4d:0x7e:0x08:0x00, nbytes=3D255)
> 15:17:00:807 HCIVSWriteRAM(addr=3D0x48:0x7f:0x08:0x00, nbytes=3D222)
> 15:17:00:930 HCIVSWriteRAM(addr=3D0xd8:0x8b:0x08:0x00, nbytes=3D52)
> 15:17:00:949 HCI_WRITE_RAM commands done
> 15:17:00:964 Sending HCI_LAUNCH_RAM command
> 15:17:00:984 HCI_LAUNCH_RAM was successful
> 15:17:00:499 BRCM2045CFG2RAMmain() END, config data downloaded successful=
ly
> 15:17:00:519 Send_HCI_Read_BDaddr was successful
> 15:17:00:534 Read BDAddr [00:1a:92:ab:e3:31] from the registry
> 15:17:00:554 Send_Broadcom_Write_BD_ADDR was successful
> 15:17:00:574 Send_HCI_Read_BDaddr was successful
> 15:17:00:599 HCIWriteChannelClassificationMode : bResult=3D1
> 15:17:00:614 HCIVSSetSleepModeParam() Mode=3DUSB with
> HOST_WAKE,HostIdleThreshold=3D10, HCIdleThreshold=3D10, BT_WAKE active HI=
GH,
> HOST_WAKE active HIGH
> 15:17:00:628 USB AutoSleepOnSuspend=3D1, USB Resume Timeout =3D 3
> 15:17:00:650 HCIVSSetSleepModeParam(mode=3D5, timeout=3D3000ms): bResult=
=3D1
> 15:17:00:665 BRCM_PostLoad : RadioInitConfigureAudio set, configuring
> 2045 audio
> 15:17:00:686 HCIVSWriteSCOPCMIntParameters(0,2,0,0,0) : bResult=3D1
> 15:17:00:705 HCIVSWritePCMDataFormatParameters(0,0,2,3,1) : bResult=3D1
> 15:17:00:721 HCIVSWriteSCOTimeSlot(SCO Time Slot=3D0)
> 15:17:00:741 HCIVSWriteSCOTimeSlot : bResult=3D1
> 15:17:00:754 BRCM_PostLoad : RadioInitEnableCoexistence set, configuring
> 2045 BT/WLAN coexistence
> 15:17:01:774 HCIVSWriteCollaborationMode(1,1,0xcb7fbdb0,10) : bResult=3D1
> 15:17:01:787 BRCM_PostLoad END
> 15:17:01:801 RadioInitPostLoad End
^ permalink raw reply
* Re: [PATCH v0 0/2] gdbus introspection fixes
From: Luiz Augusto von Dentz @ 2011-01-15 14:34 UTC (permalink / raw)
To: Elvis Pfützenreuter
Cc: Jose Antonio Santos Cadenas, Daniel Wagner, Johan Hedberg,
linux-bluetooth, Daniel Wagner
In-Reply-To: <E5842985-417B-4ECF-9611-89E4B288B882@signove.com>
Hi,
On Sat, Jan 15, 2011 at 3:31 PM, Elvis Pfützenreuter <epx@signove.com> wrote:
>
> On Jan 15, 2011, at 11:05 AM, Jose Antonio Santos Cadenas wrote:
>
>> Hi,
>>
>> 2011/1/14 Daniel Wagner <wagi@monom.org>:
>>> From: Daniel Wagner <daniel.wagner@bmw-carit.de>
>>>
>>> Hi Johan,
>>>
>>> During some connman debug session I found some small hickups in the
>>> introspection code in gdbus. Marcel ask me to check with you first.
>>>
>>
>> I've been thinking about the way that dbus is used in BlueZ and I am
>> concerned about why we don't use glib-dbus instead of dbus directly.
>> This way the dbus specific code will be maintained by glib-dbus.
>>
>> I've thought it several times and I've never said anything because is
>> a big change and as everything was working I preferred not to make
>> noise with this. But now that some bugs appeared we can probably think
>> on this changing the BlueZ DBus code and all the plugins interfaces.
>> The only problem I see is that this will probably require a version
>> change because the way plugins expose their interface will change.
>
>
> One (big) thing that makes me not to like glib-dbus is having to cope with GObject. ALso, it makes certain things more complicated and convoluted than they are in low-level API (e.g passing an array), it is poorly documented, and, incredibly enough, lacks things like the uint16 type.
Exactly, GObject code doesn't really helps us, in fact I consider
glib-dbus very bad for using in a daemon/server code. Also there is
another nice thing about gdbus, it keeps us away of wrappers libraries
to use other D-Bus services because our mainloop integration is not
compatible with glib-dbus nor QDbus.
> My feeling goes the other way round: I wish we had the gdbus API *outside* BlueZ, as a library, so any C application could enjoy it
It probably easier to maintain this way, less build dependencies and
no compromise with API changes, besides iirc gdbus name has been taken
by the new GObject binding. If gnome guys could take it as part of
glib's code and build GObject binding on top of our gdbus, IMO that
would be very convenient for everybody.
--
Luiz Augusto von Dentz
Computer Engineer
^ permalink raw reply
* Re: [PATCH v0 0/2] gdbus introspection fixes
From: Jose Antonio Santos Cadenas @ 2011-01-15 14:31 UTC (permalink / raw)
To: Elvis Pfützenreuter
Cc: Daniel Wagner, Johan Hedberg, linux-bluetooth, Daniel Wagner
In-Reply-To: <E5842985-417B-4ECF-9611-89E4B288B882@signove.com>
Hi Elvis,
2011/1/15 Elvis Pfützenreuter <epx@signove.com>:
>
> On Jan 15, 2011, at 11:05 AM, Jose Antonio Santos Cadenas wrote:
>
>> Hi,
>>
>> 2011/1/14 Daniel Wagner <wagi@monom.org>:
>>> From: Daniel Wagner <daniel.wagner@bmw-carit.de>
>>>
>>> Hi Johan,
>>>
>>> During some connman debug session I found some small hickups in the
>>> introspection code in gdbus. Marcel ask me to check with you first.
>>>
>>
>> I've been thinking about the way that dbus is used in BlueZ and I am
>> concerned about why we don't use glib-dbus instead of dbus directly.
>> This way the dbus specific code will be maintained by glib-dbus.
>>
>> I've thought it several times and I've never said anything because is
>> a big change and as everything was working I preferred not to make
>> noise with this. But now that some bugs appeared we can probably think
>> on this changing the BlueZ DBus code and all the plugins interfaces.
>> The only problem I see is that this will probably require a version
>> change because the way plugins expose their interface will change.
>
>
> One (big) thing that makes me not to like glib-dbus is having to cope with GObject. ALso, it makes certain things more complicated and convoluted than they are in low-level API (e.g passing an array), it is poorly documented, and, incredibly enough, lacks things like the uint16 type.
I've been studying the problem of types, specially uint16. You are
right, they are not implemented, and they never will because GObject
will never support them, nevertheless it is not very important since
other types like unit32 can hold them (read this email thread for more
info http://mail.gnome.org/archives/gtk-devel-list/2001-August/msg00492.html).
The array issue that you mentioned I think is not as complicated, it
uses specific Glib types, you only have to learn how to use them (and
the Glib documentation is quite good).
>
> My feeling goes the other way round: I wish we had the gdbus API *outside* BlueZ, as a library, so any C application could enjoy it.
It's a different view of the problem :), let's see if they are more
opinions out there.
Regards
^ permalink raw reply
* Re: [PATCH v0 0/2] gdbus introspection fixes
From: Elvis Pfützenreuter @ 2011-01-15 13:31 UTC (permalink / raw)
To: Jose Antonio Santos Cadenas
Cc: Daniel Wagner, Johan Hedberg, linux-bluetooth, Daniel Wagner
In-Reply-To: <AANLkTimj_-AjrC16MzTb+6kMjtkXQkbKjOb5NO9jXCSa@mail.gmail.com>
On Jan 15, 2011, at 11:05 AM, Jose Antonio Santos Cadenas wrote:
> Hi,
>
> 2011/1/14 Daniel Wagner <wagi@monom.org>:
>> From: Daniel Wagner <daniel.wagner@bmw-carit.de>
>>
>> Hi Johan,
>>
>> During some connman debug session I found some small hickups in the
>> introspection code in gdbus. Marcel ask me to check with you first.
>>
>
> I've been thinking about the way that dbus is used in BlueZ and I am
> concerned about why we don't use glib-dbus instead of dbus directly.
> This way the dbus specific code will be maintained by glib-dbus.
>
> I've thought it several times and I've never said anything because is
> a big change and as everything was working I preferred not to make
> noise with this. But now that some bugs appeared we can probably think
> on this changing the BlueZ DBus code and all the plugins interfaces.
> The only problem I see is that this will probably require a version
> change because the way plugins expose their interface will change.
One (big) thing that makes me not to like glib-dbus is having to cope with GObject. ALso, it makes certain things more complicated and convoluted than they are in low-level API (e.g passing an array), it is poorly documented, and, incredibly enough, lacks things like the uint16 type.
My feeling goes the other way round: I wish we had the gdbus API *outside* BlueZ, as a library, so any C application could enjoy it.
^ permalink raw reply
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