@@ -1088,8 +1088,10 @@ static int hidp_add_connection(struct input_device *idev)
if (device_name_known(idev->device))
device_get_name(idev->device, req->name, sizeof(req->name));
+ sixaxis_cable_pairing = device_is_sixaxis_cable_pairing(idev->device);
+
/* Make sure the device is bonded if required */
- if (classic_bonded_only && !input_device_bonded(idev)) {
+ if (!sixaxis_cable_pairing && classic_bonded_only && !input_device_bonded(idev)) {
error("Rejected connection from !bonded device %s", idev->path);
goto cleanup;
}
@@ -1098,7 +1100,7 @@ static int hidp_add_connection(struct input_device *idev)
/* 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) {
+ if (!sixaxis_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)) {
@@ -33,7 +33,8 @@
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_sixaxis_cable_pairing(adapter));
}
static void hid_server_remove(struct btd_profile *p,
@@ -266,12 +266,22 @@ drop:
g_io_channel_shutdown(chan, TRUE, NULL);
}
-int server_start(const bdaddr_t *src)
+static BtIOSecLevel get_necessary_sec_level(bool device_sixaxis_cable_pairing)
+{
+ /* Use lower security to allow the Sixaxis gamepad to connect. */
+ /* Unless classic bonded only mode is disabled, the security level */
+ /* will be bumped again for non sixaxis devices in hidp_add_connection() */
+ if (device_sixaxis_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;
+ const BtIOSecLevel sec_level = get_necessary_sec_level(device_sixaxis_cable_pairing);
server = g_new0(struct input_server, 1);
bacpy(&server->src, src);
@@ -308,6 +318,52 @@ int server_start(const bdaddr_t *src)
return 0;
}
+int server_set_sixaxis_cable_pairing(const bdaddr_t *src, bool device_sixaxis_cable_pairing)
+{
+ struct input_server *server;
+ GSList *l;
+ BtIOSecLevel sec_level;
+ const BtIOSecLevel new_sec_level = get_necessary_sec_level(device_sixaxis_cable_pairing);
+ 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;
+ }
+
+ if (sec_level == new_sec_level) {
+ DBG("The listening input server is already using the expected security 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;
@@ -8,5 +8,6 @@
*
*/
-int server_start(const bdaddr_t *src);
+int server_start(const bdaddr_t *src, bool device_sixaxis_cable_pairing);
+int server_set_sixaxis_cable_pairing(const bdaddr_t *src, bool device_sixaxis_cable_pairing);
void server_stop(const bdaddr_t *src);