* [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection
@ 2014-01-20 11:08 Szymon Janc
2014-01-20 11:08 ` [PATCH v2 2/5] core: Opencode get_sdp_session in sdp-client Szymon Janc
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Szymon Janc @ 2014-01-20 11:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
From: Szymon Janc <szymon.janc@gmail.com>
This will allow to workaround Dualshock4 not respecting L2CAP MTU
size while sending SDP response. Use same L2CAP MTU value base on
RFCOMM.
---
lib/sdp.c | 27 +++++++++++++++++++++++++++
lib/sdp_lib.h | 1 +
2 files changed, 28 insertions(+)
diff --git a/lib/sdp.c b/lib/sdp.c
index 886e7cf..3b26ec3 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -67,6 +67,9 @@ static uint128_t bluetooth_base_uuid = {
#define SDP_MAX_ATTR_LEN 65535
+/* match MTU used by RFCOMM */
+#define SDP_LARGE_L2CAP_MTU 1013
+
static sdp_data_t *sdp_copy_seq(sdp_data_t *data);
static int sdp_attr_add_new_with_length(sdp_record_t *rec,
uint16_t attr, uint8_t dtd, const void *value, uint32_t len);
@@ -4644,6 +4647,26 @@ static int sdp_connect_local(sdp_session_t *session)
return connect(session->sock, (struct sockaddr *) &sa, sizeof(sa));
}
+static int set_l2cap_mtu(int sk, uint16_t mtu)
+{
+ struct l2cap_options l2o;
+ socklen_t len;
+
+ memset(&l2o, 0, sizeof(l2o));
+ len = sizeof(l2o);
+
+ if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &len) < 0)
+ return -1;
+
+ l2o.imtu = mtu;
+ l2o.omtu = mtu;
+
+ if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o)) < 0)
+ return -1;
+
+ return 0;
+}
+
static int sdp_connect_l2cap(const bdaddr_t *src,
const bdaddr_t *dst, sdp_session_t *session)
{
@@ -4678,6 +4701,10 @@ static int sdp_connect_l2cap(const bdaddr_t *src,
setsockopt(sk, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
}
+ if ((flags & SDP_LARGE_MTU) &&
+ set_l2cap_mtu(sk, SDP_LARGE_L2CAP_MTU) < 0)
+ return -1;
+
sa.l2_psm = htobs(SDP_PSM);
sa.l2_bdaddr = *dst;
diff --git a/lib/sdp_lib.h b/lib/sdp_lib.h
index 6e1eb91..3ded393 100644
--- a/lib/sdp_lib.h
+++ b/lib/sdp_lib.h
@@ -81,6 +81,7 @@ static inline void sdp_list_foreach(sdp_list_t *list, sdp_list_func_t f, void *u
#define SDP_RETRY_IF_BUSY 0x01
#define SDP_WAIT_ON_CLOSE 0x02
#define SDP_NON_BLOCKING 0x04
+#define SDP_LARGE_MTU 0x08
/*
* a session with an SDP server
--
1.8.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 2/5] core: Opencode get_sdp_session in sdp-client 2014-01-20 11:08 [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection Szymon Janc @ 2014-01-20 11:08 ` Szymon Janc 2014-01-20 11:08 ` [PATCH v2 3/5] core: Add flags parameter to bt_search_service Szymon Janc ` (4 subsequent siblings) 5 siblings, 0 replies; 8+ messages in thread From: Szymon Janc @ 2014-01-20 11:08 UTC (permalink / raw) To: linux-bluetooth; +Cc: Szymon Janc From: Szymon Janc <szymon.janc@gmail.com> This is only used once and provides no benefit compared to opencoding. --- src/sdp-client.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/sdp-client.c b/src/sdp-client.c index 51f3048..0599626 100644 --- a/src/sdp-client.c +++ b/src/sdp-client.c @@ -86,17 +86,6 @@ static sdp_session_t *get_cached_sdp_session(const bdaddr_t *src, const bdaddr_t return NULL; } -static sdp_session_t *get_sdp_session(const bdaddr_t *src, const bdaddr_t *dst) -{ - sdp_session_t *session; - - session = get_cached_sdp_session(src, dst); - if (session) - return session; - - return sdp_connect(src, dst, SDP_NON_BLOCKING); -} - static void cache_sdp_session(bdaddr_t *src, bdaddr_t *dst, sdp_session_t *session) { @@ -285,7 +274,10 @@ static int create_search_context(struct search_context **ctxt, if (!ctxt) return -EINVAL; - s = get_sdp_session(src, dst); + s = get_cached_sdp_session(src, dst); + if (!s) + s = sdp_connect(src, dst, SDP_NON_BLOCKING); + if (!s) return -errno; -- 1.8.3.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 3/5] core: Add flags parameter to bt_search_service 2014-01-20 11:08 [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection Szymon Janc 2014-01-20 11:08 ` [PATCH v2 2/5] core: Opencode get_sdp_session in sdp-client Szymon Janc @ 2014-01-20 11:08 ` Szymon Janc 2014-01-20 11:08 ` [PATCH v2 4/5] device: Add workaround for Sony Dualshock 4 broken SDP Szymon Janc ` (3 subsequent siblings) 5 siblings, 0 replies; 8+ messages in thread From: Szymon Janc @ 2014-01-20 11:08 UTC (permalink / raw) To: linux-bluetooth; +Cc: Szymon Janc From: Szymon Janc <szymon.janc@gmail.com> This allows to pass custom SDP flags to sdp_connect. --- android/bluetooth.c | 4 ++-- android/hidhost.c | 4 ++-- android/socket.c | 2 +- profiles/health/hdp_util.c | 6 +++--- src/device.c | 5 +++-- src/profile.c | 2 +- src/sdp-client.c | 8 ++++---- src/sdp-client.h | 2 +- 8 files changed, 17 insertions(+), 16 deletions(-) diff --git a/android/bluetooth.c b/android/bluetooth.c index 505d5a7..83612b4 100644 --- a/android/bluetooth.c +++ b/android/bluetooth.c @@ -693,7 +693,7 @@ static void browse_cb(sdp_list_t *recs, int err, gpointer user_data) if (uuid_list[req->search_uuid]) { sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]); bt_search_service(&adapter.bdaddr, &req->bdaddr, &uuid, - browse_cb, user_data, NULL); + browse_cb, user_data, NULL, 0); return; } @@ -729,7 +729,7 @@ static uint8_t browse_remote_sdp(const bdaddr_t *addr) sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]); if (bt_search_service(&adapter.bdaddr, - &req->bdaddr, &uuid, browse_cb, req, NULL) < 0) { + &req->bdaddr, &uuid, browse_cb, req, NULL , 0) < 0) { browse_req_free(req); return HAL_STATUS_FAILED; } diff --git a/android/hidhost.c b/android/hidhost.c index aed9899..d66e863 100644 --- a/android/hidhost.c +++ b/android/hidhost.c @@ -751,7 +751,7 @@ static void bt_hid_connect(const void *buf, uint16_t len) bt_string2uuid(&uuid, HID_UUID); if (bt_search_service(&adapter_addr, &dev->dst, &uuid, - hid_sdp_search_cb, dev, NULL) < 0) { + hid_sdp_search_cb, dev, NULL, 0) < 0) { error("Failed to search sdp details"); hid_device_free(dev); status = HAL_STATUS_FAILED; @@ -1254,7 +1254,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data) bt_string2uuid(&uuid, HID_UUID); if (bt_search_service(&src, &dev->dst, &uuid, - hid_sdp_search_cb, dev, NULL) < 0) { + hid_sdp_search_cb, dev, NULL, 0) < 0) { error("failed to search sdp details"); hid_device_free(dev); return; diff --git a/android/socket.c b/android/socket.c index 69b39ee..f662e79 100644 --- a/android/socket.c +++ b/android/socket.c @@ -1091,7 +1091,7 @@ static uint8_t connect_rfcomm(const bdaddr_t *addr, int chan, rfsock->profile = get_profile_by_uuid(uuid); if (bt_search_service(&adapter_addr, &rfsock->dst, &uu, - sdp_search_cb, rfsock, NULL) < 0) { + sdp_search_cb, rfsock, NULL, 0) < 0) { error("Failed to search SDP records"); goto failed; } diff --git a/profiles/health/hdp_util.c b/profiles/health/hdp_util.c index 7de87a8..b9a09e9 100644 --- a/profiles/health/hdp_util.c +++ b/profiles/health/hdp_util.c @@ -864,7 +864,7 @@ gboolean hdp_get_mdep(struct hdp_device *device, struct hdp_application *app, bt_string2uuid(&uuid, HDP_UUID); if (bt_search_service(src, dst, &uuid, get_mdep_cb, mdep_data, - free_mdep_data) < 0) { + free_mdep_data, 0) < 0) { g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR, "Can't get remote SDP record"); g_free(mdep_data); @@ -1092,7 +1092,7 @@ gboolean hdp_establish_mcl(struct hdp_device *device, bt_string2uuid(&uuid, HDP_UUID); if (bt_search_service(src, dst, &uuid, search_cb, conn_data, - destroy_con_mcl_data) < 0) { + destroy_con_mcl_data, 0) < 0) { g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR, "Can't get remote SDP record"); g_free(conn_data); @@ -1161,7 +1161,7 @@ gboolean hdp_get_dcpsm(struct hdp_device *device, hdp_continue_dcpsm_f func, bt_string2uuid(&uuid, HDP_UUID); if (bt_search_service(src, dst, &uuid, get_dcpsm_cb, dcpsm_data, - free_dcpsm_data) < 0) { + free_dcpsm_data, 0) < 0) { g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR, "Can't get remote SDP record"); g_free(dcpsm_data); diff --git a/src/device.c b/src/device.c index bcc5561..1bd27a1 100644 --- a/src/device.c +++ b/src/device.c @@ -2971,7 +2971,7 @@ static void browse_cb(sdp_list_t *recs, int err, gpointer user_data) sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]); bt_search_service(btd_adapter_get_address(adapter), &device->bdaddr, &uuid, - browse_cb, user_data, NULL); + browse_cb, user_data, NULL, 0); return; } @@ -3513,7 +3513,8 @@ static int device_browse_sdp(struct btd_device *device, DBusMessage *msg) sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]); err = bt_search_service(btd_adapter_get_address(adapter), - &device->bdaddr, &uuid, browse_cb, req, NULL); + &device->bdaddr, &uuid, browse_cb, req, NULL, + 0); if (err < 0) { browse_request_free(req); return err; diff --git a/src/profile.c b/src/profile.c index 3c0d27c..e833181 100644 --- a/src/profile.c +++ b/src/profile.c @@ -1605,7 +1605,7 @@ static int resolve_service(struct ext_io *conn, const bdaddr_t *src, bt_string2uuid(&uuid, ext->remote_uuid); sdp_uuid128_to_uuid(&uuid); - err = bt_search_service(src, dst, &uuid, record_cb, conn, NULL); + err = bt_search_service(src, dst, &uuid, record_cb, conn, NULL, 0); if (err == 0) conn->resolving = true; diff --git a/src/sdp-client.c b/src/sdp-client.c index 0599626..ff06b4d 100644 --- a/src/sdp-client.c +++ b/src/sdp-client.c @@ -264,7 +264,7 @@ failed: static int create_search_context(struct search_context **ctxt, const bdaddr_t *src, const bdaddr_t *dst, - uuid_t *uuid) + uuid_t *uuid, uint16_t flags) { sdp_session_t *s; GIOChannel *chan; @@ -276,7 +276,7 @@ static int create_search_context(struct search_context **ctxt, s = get_cached_sdp_session(src, dst); if (!s) - s = sdp_connect(src, dst, SDP_NON_BLOCKING); + s = sdp_connect(src, dst, SDP_NON_BLOCKING | flags); if (!s) return -errno; @@ -311,7 +311,7 @@ static int create_search_context(struct search_context **ctxt, int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst, uuid_t *uuid, bt_callback_t cb, void *user_data, - bt_destroy_t destroy) + bt_destroy_t destroy, uint16_t flags) { struct search_context *ctxt = NULL; int err; @@ -319,7 +319,7 @@ int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst, if (!cb) return -EINVAL; - err = create_search_context(&ctxt, src, dst, uuid); + err = create_search_context(&ctxt, src, dst, uuid, flags); if (err < 0) return err; diff --git a/src/sdp-client.h b/src/sdp-client.h index 9191594..9aa5a4d 100644 --- a/src/sdp-client.h +++ b/src/sdp-client.h @@ -26,6 +26,6 @@ typedef void (*bt_destroy_t) (gpointer user_data); int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst, uuid_t *uuid, bt_callback_t cb, void *user_data, - bt_destroy_t destroy); + bt_destroy_t destroy, uint16_t flags); int bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst); void bt_clear_cached_session(const bdaddr_t *src, const bdaddr_t *dst); -- 1.8.3.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 4/5] device: Add workaround for Sony Dualshock 4 broken SDP 2014-01-20 11:08 [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection Szymon Janc 2014-01-20 11:08 ` [PATCH v2 2/5] core: Opencode get_sdp_session in sdp-client Szymon Janc 2014-01-20 11:08 ` [PATCH v2 3/5] core: Add flags parameter to bt_search_service Szymon Janc @ 2014-01-20 11:08 ` Szymon Janc 2014-01-20 11:08 ` [PATCH v2 5/5] device: Match Dualshock4 with name and class Szymon Janc ` (2 subsequent siblings) 5 siblings, 0 replies; 8+ messages in thread From: Szymon Janc @ 2014-01-20 11:08 UTC (permalink / raw) To: linux-bluetooth; +Cc: Szymon Janc From: Szymon Janc <szymon.janc@gmail.com> Sony DualShock 4 is not respecting negotiated L2CAP MTU. This might results in SDP response being dropped by kernel. Workaround this by forcing SDP code to use bigger MTU while connecting. --- src/device.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/device.c b/src/device.c index 1bd27a1..76b876e 100644 --- a/src/device.c +++ b/src/device.c @@ -118,6 +118,7 @@ struct browse_req { int search_uuid; int reconnect_attempt; guint listener_id; + uint16_t sdp_flags; }; struct included_search { @@ -2971,7 +2972,8 @@ static void browse_cb(sdp_list_t *recs, int err, gpointer user_data) sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]); bt_search_service(btd_adapter_get_address(adapter), &device->bdaddr, &uuid, - browse_cb, user_data, NULL, 0); + browse_cb, user_data, NULL, + req->sdp_flags); return; } @@ -3498,6 +3500,23 @@ done: return 0; } +static uint16_t get_sdp_flags(struct btd_device *device) +{ + uint16_t vid, pid; + + vid = btd_device_get_vendor(device); + pid = btd_device_get_product(device); + + /* Sony DualShock 4 is not respecting negotiated L2CAP MTU. This might + * results in SDP response being dropped by kernel. Workaround this by + * forcing SDP code to use bigger MTU while connecting. + */ + if (vid == 0x054c && pid == 0x05c4) + return SDP_LARGE_MTU; + + return 0; +} + static int device_browse_sdp(struct btd_device *device, DBusMessage *msg) { struct btd_adapter *adapter = device->adapter; @@ -3512,9 +3531,11 @@ static int device_browse_sdp(struct btd_device *device, DBusMessage *msg) req->device = device; sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]); + req->sdp_flags = get_sdp_flags(device); + err = bt_search_service(btd_adapter_get_address(adapter), &device->bdaddr, &uuid, browse_cb, req, NULL, - 0); + req->sdp_flags); if (err < 0) { browse_request_free(req); return err; -- 1.8.3.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 5/5] device: Match Dualshock4 with name and class 2014-01-20 11:08 [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection Szymon Janc ` (2 preceding siblings ...) 2014-01-20 11:08 ` [PATCH v2 4/5] device: Add workaround for Sony Dualshock 4 broken SDP Szymon Janc @ 2014-01-20 11:08 ` Szymon Janc 2014-01-20 13:20 ` [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection Johan Hedberg 2014-01-20 18:28 ` simon 5 siblings, 0 replies; 8+ messages in thread From: Szymon Janc @ 2014-01-20 11:08 UTC (permalink / raw) To: linux-bluetooth; +Cc: Szymon Janc From: Szymon Janc <szymon.janc@gmail.com> This allows to use DS4 with legacy adapters. This seems to require general bonding to work correctly i.e. after dedicated bonding connection is rejected with "Authentication Failure" error. --- src/device.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/device.c b/src/device.c index 76b876e..8e2a515 100644 --- a/src/device.c +++ b/src/device.c @@ -3514,6 +3514,14 @@ static uint16_t get_sdp_flags(struct btd_device *device) if (vid == 0x054c && pid == 0x05c4) return SDP_LARGE_MTU; + if (btd_adapter_ssp_enabled(device->adapter)) + return 0; + + /* if no EIR try matching Sony DualShock 4 with name and class */ + if (!strncmp(device->name, "Wireless Controller", MAX_NAME_LENGTH) && + device->class == 0x2508) + return SDP_LARGE_MTU; + return 0; } -- 1.8.3.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection 2014-01-20 11:08 [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection Szymon Janc ` (3 preceding siblings ...) 2014-01-20 11:08 ` [PATCH v2 5/5] device: Match Dualshock4 with name and class Szymon Janc @ 2014-01-20 13:20 ` Johan Hedberg 2014-01-20 18:28 ` simon 5 siblings, 0 replies; 8+ messages in thread From: Johan Hedberg @ 2014-01-20 13:20 UTC (permalink / raw) To: Szymon Janc; +Cc: linux-bluetooth, Szymon Janc Hi Szymon, On Mon, Jan 20, 2014, Szymon Janc wrote: > This will allow to workaround Dualshock4 not respecting L2CAP MTU > size while sending SDP response. Use same L2CAP MTU value base on > RFCOMM. > --- > lib/sdp.c | 27 +++++++++++++++++++++++++++ > lib/sdp_lib.h | 1 + > 2 files changed, 28 insertions(+) All patches in this set have been applied. Thanks. Johan ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection 2014-01-20 11:08 [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection Szymon Janc ` (4 preceding siblings ...) 2014-01-20 13:20 ` [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection Johan Hedberg @ 2014-01-20 18:28 ` simon 2014-01-20 18:48 ` Szymon Janc 5 siblings, 1 reply; 8+ messages in thread From: simon @ 2014-01-20 18:28 UTC (permalink / raw) To: Szymon Janc; +Cc: linux-bluetooth, Szymon Janc > From: Szymon Janc <szymon.janc@gmail.com> > > This will allow to workaround Dualshock4 not respecting L2CAP MTU > size while sending SDP response. Use same L2CAP MTU value base on > RFCOMM. I can confirm that the V2 series of patches work with my DS4 and crappy laptop. Still require particular 'connect' sequence... I note that I do not need the original '[PATCH 3/3] input: Add DualShock 4 detection' patch. I am using just this sequence of 5 patches on top of 5.13. Simon ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection 2014-01-20 18:28 ` simon @ 2014-01-20 18:48 ` Szymon Janc 0 siblings, 0 replies; 8+ messages in thread From: Szymon Janc @ 2014-01-20 18:48 UTC (permalink / raw) To: simon; +Cc: Szymon Janc, linux-bluetooth Hi Simon, On Monday 20 January 2014 13:28:57 simon@mungewell.org wrote: > > From: Szymon Janc <szymon.janc@gmail.com> > > > > This will allow to workaround Dualshock4 not respecting L2CAP MTU > > size while sending SDP response. Use same L2CAP MTU value base on > > RFCOMM. > > I can confirm that the V2 series of patches work with my DS4 and crappy > laptop. Still require particular 'connect' sequence... Thanks for testing, and yes this sequence is about dedicated vs general bonding mentioned in commit message. > > I note that I do not need the original '[PATCH 3/3] input: Add DualShock 4 > detection' patch. I am using just this sequence of 5 patches on top of > 5.13. This detection is used only when using SSP controller. And only in case when dedicated bonding is used - when DS4 tries to connect immediately after pairing is completed, but before bluetoothd was able to retrieve SDP. -- Szymon K. Janc szymon.janc@gmail.com ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2014-01-20 18:48 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-01-20 11:08 [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection Szymon Janc 2014-01-20 11:08 ` [PATCH v2 2/5] core: Opencode get_sdp_session in sdp-client Szymon Janc 2014-01-20 11:08 ` [PATCH v2 3/5] core: Add flags parameter to bt_search_service Szymon Janc 2014-01-20 11:08 ` [PATCH v2 4/5] device: Add workaround for Sony Dualshock 4 broken SDP Szymon Janc 2014-01-20 11:08 ` [PATCH v2 5/5] device: Match Dualshock4 with name and class Szymon Janc 2014-01-20 13:20 ` [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection Johan Hedberg 2014-01-20 18:28 ` simon 2014-01-20 18:48 ` Szymon Janc
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox