diff --git a/profiles/input/device.c b/profiles/input/device.c
index 3627573..a7bc4d4 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
#include "device.h"
#include "hidp_defs.h"
+#include "server.h"
#define INPUT_INTERFACE "org.bluez.Input1"
static int hidp_add_connection(struct input_device *idev)
{
struct hidp_connadd_req *req;
+ bool cable_pairing;
GError *gerr = NULL;
int err;
if (device_name_known(idev->device))
device_get_name(idev->device, req->name, sizeof(req->name));
+ cable_pairing = device_is_cable_pairing(idev->device);
+
/* Make sure the device is bonded if required */
- if (classic_bonded_only && !input_device_bonded(idev)) {
+ if (!cable_pairing && classic_bonded_only &&
+ !input_device_bonded(idev)) {
error("Rejected connection from !bonded device %s", idev->path);
goto cleanup;
}
/* Some platforms may choose to require encryption for all devices */
/* Note that this only matters for pre 2.1 devices as otherwise the */
/* device is encrypted by default by the lower layers */
- if (classic_bonded_only || idev->type == BT_UHID_KEYBOARD) {
+ /* Don't enforce encryption for cable paired devices because they */
+ /* don't support it */
+ if (!cable_pairing && (classic_bonded_only ||
+ idev->type == BT_UHID_KEYBOARD)) {
if (!bt_io_set(idev->intr_io, &gerr,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
BT_IO_OPT_INVALID)) {
btd_service_set_user_data(service, idev);
device_set_wake_support(device, true);
+ if (device_is_cable_pairing(device)) {
+ struct btd_adapter *adapter = device_get_adapter(device);
+ const bdaddr_t *bdaddr = btd_adapter_get_address(adapter);
+
+ server_set_cable_pairing(bdaddr, true);
+ }
+
return 0;
}
diff --git a/profiles/input/manager.c b/profiles/input/manager.c
index d1accc2..95ca0a7 100644
--- a/profiles/input/manager.c
+++ b/profiles/input/manager.c
static int hid_server_probe(struct btd_profile *p, struct btd_adapter *adapter)
{
- return server_start(btd_adapter_get_address(adapter));
+ return server_start(btd_adapter_get_address(adapter),
+ btd_adapter_has_cable_pairing_devices(adapter));
}
static void hid_server_remove(struct btd_profile *p,
diff --git a/profiles/input/server.c b/profiles/input/server.c
index 79cf08a..c8be445 100644
--- a/profiles/input/server.c
+++ b/profiles/input/server.c
g_io_channel_shutdown(chan, TRUE, NULL);
}
-int server_start(const bdaddr_t *src)
+static BtIOSecLevel get_necessary_sec_level(bool device_cable_pairing)
+{
+ /* Use lower security to allow the cable paired devices to connect. */
+ /* Unless classic bonded only mode is disabled, the security level */
+ /* will be bumped again for non cable paired devices in */
+ /* hidp_add_connection() */
+ if (device_cable_pairing)
+ return BT_IO_SEC_LOW;
+
+ return input_get_classic_bonded_only() ? BT_IO_SEC_MEDIUM :
+ BT_IO_SEC_LOW;
+}
+
+int server_start(const bdaddr_t *src, bool device_sixaxis_cable_pairing)
{
struct input_server *server;
GError *err = NULL;
- BtIOSecLevel sec_level = input_get_classic_bonded_only() ?
- BT_IO_SEC_MEDIUM : BT_IO_SEC_LOW;
+ BtIOSecLevel sec_level;
+
+ sec_level = get_necessary_sec_level(device_sixaxis_cable_pairing);
server = g_new0(struct input_server, 1);
bacpy(&server->src, src);
return 0;
}
+int server_set_cable_pairing(const bdaddr_t *src, bool device_cable_pairing)
+{
+ struct input_server *server;
+ GSList *l;
+ BtIOSecLevel sec_level;
+ BtIOSecLevel new_sec_level;
+ GError *err = NULL;
+
+ l = g_slist_find_custom(servers, src, server_cmp);
+ if (!l)
+ return -1;
+
+ server = l->data;
+
+ bt_io_get(server->ctrl, &err, BT_IO_OPT_SEC_LEVEL, &sec_level,
+ BT_IO_OPT_INVALID);
+ if (err) {
+ error("%s", err->message);
+ g_error_free(err);
+ return -1;
+ }
+
+ new_sec_level = get_necessary_sec_level(device_cable_pairing);
+ if (sec_level == new_sec_level)
+ return -1;
+
+ DBG("Applying the new security level to the listening input server");
+
+ if (!bt_io_set(server->ctrl, &err, BT_IO_OPT_SEC_LEVEL, new_sec_level,
+ BT_IO_OPT_INVALID)) {
+ error("bt_io_set(OPT_SEC_LEVEL): %s", err->message);
+ g_error_free(err);
+ return -1;
+ }
+
+ if (!bt_io_set(server->intr, &err, BT_IO_OPT_SEC_LEVEL, new_sec_level,
+ BT_IO_OPT_INVALID)) {
+ error("bt_io_set(OPT_SEC_LEVEL): %s", err->message);
+ g_error_free(err);
+ return -1;
+ }
+
+ return 0;
+}
+
void server_stop(const bdaddr_t *src)
{
struct input_server *server;
diff --git a/profiles/input/server.h b/profiles/input/server.h
index 50f4b61..4ad82c1 100644
--- a/profiles/input/server.h
+++ b/profiles/input/server.h
*
*/
-int server_start(const bdaddr_t *src);
+int server_start(const bdaddr_t *src, bool device_cable_pairing);
+int server_set_cable_pairing(const bdaddr_t *src, bool device_cable_pairing);
void server_stop(const bdaddr_t *src);