@@ -89,7 +89,7 @@ struct input_device {
};
static int idle_timeout = 0;
-static bool uhid_enabled = true;
+static uhid_state_t uhid_state = UHID_ENABLED;
static bool classic_bonded_only = true;
void input_set_idle_timeout(int timeout)
@@ -97,9 +97,23 @@ void input_set_idle_timeout(int timeout)
idle_timeout = timeout;
}
-void input_enable_userspace_hid(bool state)
+void input_set_userspace_hid(char *state)
{
- uhid_enabled = state;
+ if (!strcasecmp(state, "false") || !strcasecmp(state, "no") ||
+ !strcasecmp(state, "off"))
+ uhid_state = UHID_DISABLED;
+ else if (!strcasecmp(state, "true") || !strcasecmp(state, "yes") ||
+ !strcasecmp(state, "on"))
+ uhid_state = UHID_ENABLED;
+ else if (!strcasecmp(state, "persist"))
+ uhid_state = UHID_PERSIST;
+ else
+ error("Unknown value '%s'", state);
+}
+
+uint8_t input_get_userspace_hid(void)
+{
+ return uhid_state;
}
void input_set_classic_bonded_only(bool state)
@@ -179,6 +193,9 @@ static int uhid_disconnect(struct input_device *idev, bool force)
if (idev->virtual_cable_unplug && !force)
force = true;
+ if (!force && uhid_state != UHID_PERSIST)
+ force = true;
+
err = bt_uhid_destroy(idev->uhid, force);
if (err < 0) {
error("bt_uhid_destroy: %s", strerror(-err));
@@ -1507,7 +1524,7 @@ int input_device_register(struct btd_service *service)
if (!idev)
return -EINVAL;
- if (uhid_enabled) {
+ if (uhid_state) {
idev->uhid = bt_uhid_new_default();
if (!idev->uhid) {
error("bt_uhid_new_default: failed");
@@ -1605,7 +1622,7 @@ int input_device_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm,
if (!idev)
return -ENOENT;
- if (uhid_enabled)
+ if (uhid_state)
cond |= G_IO_IN;
switch (psm) {
@@ -11,11 +11,18 @@
#define L2CAP_PSM_HIDP_CTRL 0x11
#define L2CAP_PSM_HIDP_INTR 0x13
+typedef enum {
+ UHID_DISABLED = 0,
+ UHID_ENABLED,
+ UHID_PERSIST
+} uhid_state_t;
+
struct input_device;
struct input_conn;
void input_set_idle_timeout(int timeout);
-void input_enable_userspace_hid(bool state);
+void input_set_userspace_hid(char *state);
+uint8_t input_get_userspace_hid(void);
void input_set_classic_bonded_only(bool state);
bool input_get_classic_bonded_only(void);
void input_set_auto_sec(bool state);
@@ -208,7 +208,10 @@ static int hog_disconnect(struct btd_service *service)
{
struct hog_device *dev = btd_service_get_user_data(service);
- bt_hog_detach(dev->hog, false);
+ if (input_get_userspace_hid() == UHID_PERSIST)
+ bt_hog_detach(dev->hog, false);
+ else
+ bt_hog_detach(dev->hog, true);
btd_service_disconnecting_complete(service, 0);
@@ -10,7 +10,11 @@
#IdleTimeout=0
# Enable HID protocol handling in userspace input profile
-# Defaults to true (Use UHID instead of kernel HIDP)
+# Possible values:
+# - persist: Use UHID in persistent mode (keyboard only)
+# - true: Use UHID instead
+# - false: User kernel HIDP
+# Defaults to true
#UserspaceHID=true
# Limit HID connections to bonded devices
@@ -83,7 +83,8 @@ static int input_init(void)
config = load_config_file(CONFIGDIR "/input.conf");
if (config) {
int idle_timeout;
- gboolean uhid_enabled, classic_bonded_only, auto_sec;
+ gboolean classic_bonded_only, auto_sec;
+ char *uhid_enabled;
idle_timeout = g_key_file_get_integer(config, "General",
"IdleTimeout", &err);
@@ -93,12 +94,12 @@ static int input_init(void)
} else
g_clear_error(&err);
- uhid_enabled = g_key_file_get_boolean(config, "General",
+ uhid_enabled = g_key_file_get_string(config, "General",
"UserspaceHID", &err);
if (!err) {
- DBG("input.conf: UserspaceHID=%s", uhid_enabled ?
- "true" : "false");
- input_enable_userspace_hid(uhid_enabled);
+ DBG("input.conf: UserspaceHID=%s", uhid_enabled);
+ input_set_userspace_hid(uhid_enabled);
+ free(uhid_enabled);
} else
g_clear_error(&err);
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> This adds support supportfor persist mode via input.conf:UserspaceHID but don't default to it since this appears to create more problems than it solves. Fixes: https://github.com/bluez/bluez/issues/983 Fixes: https://github.com/bluez/bluez/issues/977 Fixes: https://github.com/bluez/bluez/issues/949 --- profiles/input/device.c | 27 ++++++++++++++++++++++----- profiles/input/device.h | 9 ++++++++- profiles/input/hog.c | 5 ++++- profiles/input/input.conf | 6 +++++- profiles/input/manager.c | 11 ++++++----- 5 files changed, 45 insertions(+), 13 deletions(-)