summaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 17:39:57 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 17:39:57 +0000
commitdc50eab76b709d68175a358d6e23a5a3890764d3 (patch)
treec754d0390db060af0213ff994f0ac310e4cfd6e9 /drivers/hid
parentAdding debian version 6.6.15-2. (diff)
downloadlinux-dc50eab76b709d68175a358d6e23a5a3890764d3.tar.xz
linux-dc50eab76b709d68175a358d6e23a5a3890764d3.zip
Merging upstream version 6.7.7.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/Kconfig8
-rw-r--r--drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c7
-rw-r--r--drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h3
-rw-r--r--drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h21
-rw-r--r--drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c9
-rw-r--r--drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h15
-rw-r--r--drivers/hid/bpf/hid_bpf_dispatch.c83
-rw-r--r--drivers/hid/bpf/hid_bpf_dispatch.h4
-rw-r--r--drivers/hid/bpf/hid_bpf_jmp_table.c40
-rw-r--r--drivers/hid/hid-apple.c2
-rw-r--r--drivers/hid/hid-logitech-hidpp.c128
-rw-r--r--drivers/hid/hid-multitouch.c10
-rw-r--r--drivers/hid/hid-nintendo.c133
-rw-r--r--drivers/hid/hid-nvidia-shield.c25
-rw-r--r--drivers/hid/hid-picolcd_fb.c73
-rw-r--r--drivers/hid/hid-prodikeys.c8
-rw-r--r--drivers/hid/hid-rmi.c10
-rw-r--r--drivers/hid/hidraw.c7
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-of.c1
-rw-r--r--drivers/hid/usbhid/hid-core.c11
-rw-r--r--drivers/hid/wacom_sys.c63
-rw-r--r--drivers/hid/wacom_wac.c9
22 files changed, 367 insertions, 303 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 790aa908e2..4ce74af796 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -880,11 +880,7 @@ config HID_PICOLCD_FB
default !EXPERT
depends on HID_PICOLCD
depends on HID_PICOLCD=FB || FB=y
- select FB_DEFERRED_IO
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
+ select FB_SYSMEM_HELPERS_DEFERRED
help
Provide access to PicoLCD's 256x64 monochrome display via a
framebuffer device.
@@ -1046,7 +1042,7 @@ config HID_SONY
* Guitar Hero PS3 and PC guitar dongles
config SONY_FF
- bool "Sony PS2/3/4 accessories force feedback support"
+ bool "Sony PS2/3/4 accessories force feedback support"
depends on HID_SONY
select INPUT_FF_MEMLESS
help
diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
index 8716a05950..ef1f9be8b8 100644
--- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
+++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
@@ -257,6 +257,13 @@ static u8 get_input_report(u8 current_index, int sensor_idx, int report_id,
else
als_input.illuminance_value =
(int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
+
+ if (sensor_idx == ACS_IDX) {
+ als_input.light_color_temp = sensor_virt_addr[1];
+ als_input.chromaticity_x_value = sensor_virt_addr[2];
+ als_input.chromaticity_y_value = sensor_virt_addr[3];
+ }
+
report_size = sizeof(als_input);
memcpy(input_report, &als_input, sizeof(als_input));
break;
diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
index ebd55675eb..882434b150 100644
--- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
+++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
@@ -99,6 +99,9 @@ struct als_input_report {
struct common_input_property common_property;
/* values specific to this sensor */
int illuminance_value;
+ int light_color_temp;
+ int chromaticity_x_value;
+ int chromaticity_y_value;
} __packed;
struct hpd_feature_report {
diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h
index 697f2791ea..67ec2d6a41 100644
--- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h
+++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h
@@ -641,6 +641,27 @@ static const u8 als_report_descriptor[] = {
0x75, 32, /* HID report size(32) */
0x95, 1, /* HID report count (1) */
0X81, 0x02, /* HID Input (Data_Arr_Abs) */
+0x0A, 0xD2, 0x04, /* HID usage sensor data light temperature */
+0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
+0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
+0x55, 0x0, /* HID unit exponent(0x0) */
+0x75, 32, /* HID report size(32) */
+0x95, 1, /* HID report count (1) */
+0X81, 0x02, /* HID Input (Data_Arr_Abs) */
+0x0A, 0xD4, 0x04, /* HID usage sensor data light chromaticity_x */
+0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
+0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
+0x55, 0x0, /* HID unit exponent(0x0) */
+0x75, 32, /* HID report size(32) */
+0x95, 1, /* HID report count(1) */
+0X81, 0x02, /* HID Input (Data_Var_Abs) */
+0x0A, 0xD5, 0x04, /* HID usage sensor data light chromaticity_y */
+0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
+0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
+0x55, 0x0, /* HID unit exponent(0x0) */
+0x75, 32, /* HID report size(32) */
+0x95, 1, /* HID report count (1) */
+0X81, 0x02, /* HID Input (Data_Var_Abs) */
0xC0 /* HID end collection */
};
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
index 06bdcf072d..8a037de08e 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
@@ -188,6 +188,7 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
struct sfh_mag_data mag_data;
struct sfh_als_data als_data;
struct hpd_status hpdstatus;
+ struct sfh_base_info binfo;
void __iomem *sensoraddr;
u8 report_size = 0;
@@ -235,6 +236,14 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data));
get_common_inputs(&als_input.common_property, report_id);
als_input.illuminance_value = float_to_int(als_data.lux);
+
+ memcpy_fromio(&binfo, mp2->vsbase, sizeof(struct sfh_base_info));
+ if (binfo.sbase.s_prop[ALS_IDX].sf.feat & 0x2) {
+ als_input.light_color_temp = als_data.light_color_temp;
+ als_input.chromaticity_x_value = float_to_int(als_data.chromaticity_x);
+ als_input.chromaticity_y_value = float_to_int(als_data.chromaticity_y);
+ }
+
report_size = sizeof(als_input);
memcpy(input_report, &als_input, sizeof(als_input));
break;
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
index 9d31d5b510..656c3e95ef 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
@@ -88,6 +88,16 @@ struct sfh_sensor_list {
};
};
+struct sfh_sensor_prop {
+ union {
+ u32 sprop;
+ struct {
+ u32 elist : 16;
+ u32 feat : 16;
+ } sf;
+ };
+};
+
struct sfh_base_info {
union {
u32 sfh_base[24];
@@ -95,6 +105,8 @@ struct sfh_base_info {
struct sfh_platform_info plat_info;
struct sfh_firmware_info fw_info;
struct sfh_sensor_list s_list;
+ u32 rsvd;
+ struct sfh_sensor_prop s_prop[16];
} sbase;
};
};
@@ -134,6 +146,9 @@ struct sfh_mag_data {
struct sfh_als_data {
struct sfh_common_data commondata;
u32 lux;
+ u32 light_color_temp;
+ u32 chromaticity_x;
+ u32 chromaticity_y;
};
struct hpd_status {
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index d9ef45fcae..7903c8638e 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -241,6 +241,39 @@ int hid_bpf_reconnect(struct hid_device *hdev)
return 0;
}
+static int do_hid_bpf_attach_prog(struct hid_device *hdev, int prog_fd, struct bpf_prog *prog,
+ __u32 flags)
+{
+ int fd, err, prog_type;
+
+ prog_type = hid_bpf_get_prog_attach_type(prog);
+ if (prog_type < 0)
+ return prog_type;
+
+ if (prog_type >= HID_BPF_PROG_TYPE_MAX)
+ return -EINVAL;
+
+ if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) {
+ err = hid_bpf_allocate_event_data(hdev);
+ if (err)
+ return err;
+ }
+
+ fd = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, prog, flags);
+ if (fd < 0)
+ return fd;
+
+ if (prog_type == HID_BPF_PROG_TYPE_RDESC_FIXUP) {
+ err = hid_bpf_reconnect(hdev);
+ if (err) {
+ close_fd(fd);
+ return err;
+ }
+ }
+
+ return fd;
+}
+
/**
* hid_bpf_attach_prog - Attach the given @prog_fd to the given HID device
*
@@ -257,18 +290,13 @@ noinline int
hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
{
struct hid_device *hdev;
+ struct bpf_prog *prog;
struct device *dev;
- int fd, err, prog_type = hid_bpf_get_prog_attach_type(prog_fd);
+ int err, fd;
if (!hid_bpf_ops)
return -EINVAL;
- if (prog_type < 0)
- return prog_type;
-
- if (prog_type >= HID_BPF_PROG_TYPE_MAX)
- return -EINVAL;
-
if ((flags & ~HID_BPF_FLAG_MASK))
return -EINVAL;
@@ -278,25 +306,29 @@ hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
hdev = to_hid_device(dev);
- if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) {
- err = hid_bpf_allocate_event_data(hdev);
- if (err)
- return err;
+ /*
+ * take a ref on the prog itself, it will be released
+ * on errors or when it'll be detached
+ */
+ prog = bpf_prog_get(prog_fd);
+ if (IS_ERR(prog)) {
+ err = PTR_ERR(prog);
+ goto out_dev_put;
}
- fd = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, flags);
- if (fd < 0)
- return fd;
-
- if (prog_type == HID_BPF_PROG_TYPE_RDESC_FIXUP) {
- err = hid_bpf_reconnect(hdev);
- if (err) {
- close_fd(fd);
- return err;
- }
+ fd = do_hid_bpf_attach_prog(hdev, prog_fd, prog, flags);
+ if (fd < 0) {
+ err = fd;
+ goto out_prog_put;
}
return fd;
+
+ out_prog_put:
+ bpf_prog_put(prog);
+ out_dev_put:
+ put_device(dev);
+ return err;
}
/**
@@ -323,8 +355,10 @@ hid_bpf_allocate_context(unsigned int hid_id)
hdev = to_hid_device(dev);
ctx_kern = kzalloc(sizeof(*ctx_kern), GFP_KERNEL);
- if (!ctx_kern)
+ if (!ctx_kern) {
+ put_device(dev);
return NULL;
+ }
ctx_kern->ctx.hid = hdev;
@@ -341,10 +375,15 @@ noinline void
hid_bpf_release_context(struct hid_bpf_ctx *ctx)
{
struct hid_bpf_ctx_kern *ctx_kern;
+ struct hid_device *hid;
ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
+ hid = (struct hid_device *)ctx_kern->ctx.hid; /* ignore const */
kfree(ctx_kern);
+
+ /* get_device() is called by bus_find_device() */
+ put_device(&hid->dev);
}
/**
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.h b/drivers/hid/bpf/hid_bpf_dispatch.h
index 63dfc8605c..fbe0639d09 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.h
+++ b/drivers/hid/bpf/hid_bpf_dispatch.h
@@ -12,9 +12,9 @@ struct hid_bpf_ctx_kern {
int hid_bpf_preload_skel(void);
void hid_bpf_free_links_and_skel(void);
-int hid_bpf_get_prog_attach_type(int prog_fd);
+int hid_bpf_get_prog_attach_type(struct bpf_prog *prog);
int __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type, int prog_fd,
- __u32 flags);
+ struct bpf_prog *prog, __u32 flags);
void __hid_bpf_destroy_device(struct hid_device *hdev);
int hid_bpf_prog_run(struct hid_device *hdev, enum hid_bpf_prog_type type,
struct hid_bpf_ctx_kern *ctx_kern);
diff --git a/drivers/hid/bpf/hid_bpf_jmp_table.c b/drivers/hid/bpf/hid_bpf_jmp_table.c
index eca34b7372..aa8e1c79cd 100644
--- a/drivers/hid/bpf/hid_bpf_jmp_table.c
+++ b/drivers/hid/bpf/hid_bpf_jmp_table.c
@@ -196,6 +196,7 @@ static void __hid_bpf_do_release_prog(int map_fd, unsigned int idx)
static void hid_bpf_release_progs(struct work_struct *work)
{
int i, j, n, map_fd = -1;
+ bool hdev_destroyed;
if (!jmp_table.map)
return;
@@ -220,6 +221,12 @@ static void hid_bpf_release_progs(struct work_struct *work)
if (entry->hdev) {
hdev = entry->hdev;
type = entry->type;
+ /*
+ * hdev is still valid, even if we are called after hid_destroy_device():
+ * when hid_bpf_attach() gets called, it takes a ref on the dev through
+ * bus_find_device()
+ */
+ hdev_destroyed = hdev->bpf.destroyed;
hid_bpf_populate_hdev(hdev, type);
@@ -232,12 +239,19 @@ static void hid_bpf_release_progs(struct work_struct *work)
if (test_bit(next->idx, jmp_table.enabled))
continue;
- if (next->hdev == hdev && next->type == type)
+ if (next->hdev == hdev && next->type == type) {
+ /*
+ * clear the hdev reference and decrement the device ref
+ * that was taken during bus_find_device() while calling
+ * hid_bpf_attach()
+ */
next->hdev = NULL;
+ put_device(&hdev->dev);
+ }
}
- /* if type was rdesc fixup, reconnect device */
- if (type == HID_BPF_PROG_TYPE_RDESC_FIXUP)
+ /* if type was rdesc fixup and the device is not gone, reconnect device */
+ if (type == HID_BPF_PROG_TYPE_RDESC_FIXUP && !hdev_destroyed)
hid_bpf_reconnect(hdev);
}
}
@@ -333,15 +347,10 @@ static int hid_bpf_insert_prog(int prog_fd, struct bpf_prog *prog)
return err;
}
-int hid_bpf_get_prog_attach_type(int prog_fd)
+int hid_bpf_get_prog_attach_type(struct bpf_prog *prog)
{
- struct bpf_prog *prog = NULL;
- int i;
int prog_type = HID_BPF_PROG_TYPE_UNDEF;
-
- prog = bpf_prog_get(prog_fd);
- if (IS_ERR(prog))
- return PTR_ERR(prog);
+ int i;
for (i = 0; i < HID_BPF_PROG_TYPE_MAX; i++) {
if (hid_bpf_btf_ids[i] == prog->aux->attach_btf_id) {
@@ -350,8 +359,6 @@ int hid_bpf_get_prog_attach_type(int prog_fd)
}
}
- bpf_prog_put(prog);
-
return prog_type;
}
@@ -388,19 +395,13 @@ static const struct bpf_link_ops hid_bpf_link_lops = {
/* called from syscall */
noinline int
__hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type,
- int prog_fd, __u32 flags)
+ int prog_fd, struct bpf_prog *prog, __u32 flags)
{
struct bpf_link_primer link_primer;
struct hid_bpf_link *link;
- struct bpf_prog *prog = NULL;
struct hid_bpf_prog_entry *prog_entry;
int cnt, err = -EINVAL, prog_table_idx = -1;
- /* take a ref on the prog itself */
- prog = bpf_prog_get(prog_fd);
- if (IS_ERR(prog))
- return PTR_ERR(prog);
-
mutex_lock(&hid_bpf_attach_lock);
link = kzalloc(sizeof(*link), GFP_USER);
@@ -467,7 +468,6 @@ __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type,
err_unlock:
mutex_unlock(&hid_bpf_attach_lock);
- bpf_prog_put(prog);
kfree(link);
return err;
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index d9e9829b22..b9c7c0ed7b 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -347,6 +347,8 @@ static const struct apple_non_apple_keyboard non_apple_keyboards[] = {
{ "Hailuck" },
{ "Jamesdonkey" },
{ "A3R" },
+ { "hfd.cn" },
+ { "WKB603" },
};
static bool apple_is_non_apple_keyboard(struct hid_device *hdev)
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 7bf12ca0eb..6ef0c88e3e 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -69,12 +69,11 @@ MODULE_PARM_DESC(disable_tap_to_click,
#define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22)
#define HIDPP_QUIRK_DELAYED_INIT BIT(23)
#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24)
-#define HIDPP_QUIRK_UNIFYING BIT(25)
-#define HIDPP_QUIRK_HIDPP_WHEELS BIT(26)
-#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(27)
-#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(28)
-#define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(29)
-#define HIDPP_QUIRK_WIRELESS_STATUS BIT(30)
+#define HIDPP_QUIRK_HIDPP_WHEELS BIT(25)
+#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(26)
+#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(27)
+#define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(28)
+#define HIDPP_QUIRK_WIRELESS_STATUS BIT(29)
/* These are just aliases for now */
#define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS
@@ -194,7 +193,6 @@ struct hidpp_device {
struct work_struct work;
struct kfifo delayed_work_fifo;
- atomic_t connected;
struct input_dev *delayed_input;
unsigned long quirks;
@@ -235,8 +233,6 @@ struct hidpp_device {
#define HIDPP20_ERROR_UNSUPPORTED 0x09
#define HIDPP20_ERROR 0xff
-static void hidpp_connect_event(struct hidpp_device *hidpp_dev);
-
static int __hidpp_send_report(struct hid_device *hdev,
struct hidpp_report *hidpp_report)
{
@@ -450,13 +446,6 @@ static int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev,
return ret;
}
-static void delayed_work_cb(struct work_struct *work)
-{
- struct hidpp_device *hidpp = container_of(work, struct hidpp_device,
- work);
- hidpp_connect_event(hidpp);
-}
-
static inline bool hidpp_match_answer(struct hidpp_report *question,
struct hidpp_report *answer)
{
@@ -3141,7 +3130,7 @@ static int wtp_allocate(struct hid_device *hdev, const struct hid_device_id *id)
return 0;
};
-static int wtp_connect(struct hid_device *hdev, bool connected)
+static int wtp_connect(struct hid_device *hdev)
{
struct hidpp_device *hidpp = hid_get_drvdata(hdev);
struct wtp_data *wd = hidpp->private_data;
@@ -3203,7 +3192,7 @@ static const u8 m560_config_parameter[] = {0x00, 0xaf, 0x03};
#define M560_SUB_ID 0x0a
#define M560_BUTTON_MODE_REGISTER 0x35
-static int m560_send_config_command(struct hid_device *hdev, bool connected)
+static int m560_send_config_command(struct hid_device *hdev)
{
struct hidpp_report response;
struct hidpp_device *hidpp_dev;
@@ -3398,7 +3387,7 @@ static int k400_allocate(struct hid_device *hdev)
return 0;
};
-static int k400_connect(struct hid_device *hdev, bool connected)
+static int k400_connect(struct hid_device *hdev)
{
struct hidpp_device *hidpp = hid_get_drvdata(hdev);
@@ -3893,8 +3882,6 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
}
if (unlikely(hidpp_report_is_connect_event(hidpp, report))) {
- atomic_set(&hidpp->connected,
- !(report->rap.params[0] & (1 << 6)));
if (schedule_work(&hidpp->work) == 0)
dbg_hid("%s: connect event already queued\n", __func__);
return 1;
@@ -4130,24 +4117,22 @@ static int hidpp_initialize_battery(struct hidpp_device *hidpp)
return ret;
}
-static void hidpp_overwrite_name(struct hid_device *hdev)
+/* Get name + serial for USB and Bluetooth HID++ devices */
+static void hidpp_non_unifying_init(struct hidpp_device *hidpp)
{
- struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+ struct hid_device *hdev = hidpp->hid_dev;
char *name;
- if (hidpp->protocol_major < 2)
- return;
+ /* Bluetooth devices already have their serialnr set */
+ if (hid_is_usb(hdev))
+ hidpp_serial_init(hidpp);
name = hidpp_get_device_name(hidpp);
-
- if (!name) {
- hid_err(hdev, "unable to retrieve the name of the device");
- } else {
+ if (name) {
dbg_hid("HID++: Got name: %s\n", name);
snprintf(hdev->name, sizeof(hdev->name), "%s", name);
+ kfree(name);
}
-
- kfree(name);
}
static int hidpp_input_open(struct input_dev *dev)
@@ -4188,15 +4173,18 @@ static struct input_dev *hidpp_allocate_input(struct hid_device *hdev)
return input_dev;
}
-static void hidpp_connect_event(struct hidpp_device *hidpp)
+static void hidpp_connect_event(struct work_struct *work)
{
+ struct hidpp_device *hidpp = container_of(work, struct hidpp_device, work);
struct hid_device *hdev = hidpp->hid_dev;
- int ret = 0;
- bool connected = atomic_read(&hidpp->connected);
struct input_dev *input;
char *name, *devm_name;
+ int ret;
- if (!connected) {
+ /* Get device version to check if it is connected */
+ ret = hidpp_root_get_protocol_version(hidpp);
+ if (ret) {
+ hid_info(hidpp->hid_dev, "Disconnected\n");
if (hidpp->battery.ps) {
hidpp->battery.online = false;
hidpp->battery.status = POWER_SUPPLY_STATUS_UNKNOWN;
@@ -4207,15 +4195,15 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
}
if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) {
- ret = wtp_connect(hdev, connected);
+ ret = wtp_connect(hdev);
if (ret)
return;
} else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560) {
- ret = m560_send_config_command(hdev, connected);
+ ret = m560_send_config_command(hdev);
if (ret)
return;
} else if (hidpp->quirks & HIDPP_QUIRK_CLASS_K400) {
- ret = k400_connect(hdev, connected);
+ ret = k400_connect(hdev);
if (ret)
return;
}
@@ -4238,16 +4226,6 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
return;
}
- /* the device is already connected, we can ask for its name and
- * protocol */
- if (!hidpp->protocol_major) {
- ret = hidpp_root_get_protocol_version(hidpp);
- if (ret) {
- hid_err(hdev, "Can not get the protocol version.\n");
- return;
- }
- }
-
if (hidpp->protocol_major >= 2) {
u8 feature_index;
@@ -4397,9 +4375,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
struct hidpp_device *hidpp;
int ret;
- bool connected;
unsigned int connect_mask = HID_CONNECT_DEFAULT;
- struct hidpp_ff_private_data data;
/* report_fixup needs drvdata to be set before we call hid_parse */
hidpp = devm_kzalloc(&hdev->dev, sizeof(*hidpp), GFP_KERNEL);
@@ -4428,9 +4404,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
}
- if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE)
- hidpp->quirks |= HIDPP_QUIRK_UNIFYING;
-
if (id->group == HID_GROUP_LOGITECH_27MHZ_DEVICE &&
hidpp_application_equals(hdev, HID_GD_MOUSE))
hidpp->quirks |= HIDPP_QUIRK_HIDPP_WHEELS |
@@ -4450,7 +4423,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
return ret;
}
- INIT_WORK(&hidpp->work, delayed_work_cb);
+ INIT_WORK(&hidpp->work, hidpp_connect_event);
mutex_init(&hidpp->send_mutex);
init_waitqueue_head(&hidpp->wait);
@@ -4482,48 +4455,35 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
/* Allow incoming packets */
hid_device_io_start(hdev);
- if (hidpp->quirks & HIDPP_QUIRK_UNIFYING)
+ /* Get name + serial, store in hdev->name + hdev->uniq */
+ if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE)
hidpp_unifying_init(hidpp);
- else if (hid_is_usb(hidpp->hid_dev))
- hidpp_serial_init(hidpp);
-
- connected = hidpp_root_get_protocol_version(hidpp) == 0;
- atomic_set(&hidpp->connected, connected);
- if (!(hidpp->quirks & HIDPP_QUIRK_UNIFYING)) {
- if (!connected) {
- ret = -ENODEV;
- hid_err(hdev, "Device not connected");
- goto hid_hw_init_fail;
- }
-
- hidpp_overwrite_name(hdev);
- }
-
- if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) {
- ret = wtp_get_config(hidpp);
- if (ret)
- goto hid_hw_init_fail;
- } else if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_G920)) {
- ret = g920_get_config(hidpp, &data);
- if (ret)
- goto hid_hw_init_fail;
- }
-
- schedule_work(&hidpp->work);
- flush_work(&hidpp->work);
+ else
+ hidpp_non_unifying_init(hidpp);
if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
connect_mask &= ~HID_CONNECT_HIDINPUT;
/* Now export the actual inputs and hidraw nodes to the world */
+ hid_device_io_stop(hdev);
ret = hid_connect(hdev, connect_mask);
if (ret) {
hid_err(hdev, "%s:hid_connect returned error %d\n", __func__, ret);
goto hid_hw_init_fail;
}
+ /* Check for connected devices now that incoming packets will not be disabled again */
+ hid_device_io_start(hdev);
+ schedule_work(&hidpp->work);
+ flush_work(&hidpp->work);
+
if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
- ret = hidpp_ff_init(hidpp, &data);
+ struct hidpp_ff_private_data data;
+
+ ret = g920_get_config(hidpp, &data);
+ if (!ret)
+ ret = hidpp_ff_init(hidpp, &data);
+
if (ret)
hid_warn(hidpp->hid_dev,
"Unable to initialize force feedback support, errno %d\n",
@@ -4650,6 +4610,8 @@ static const struct hid_device_id hidpp_devices[] = {
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC088) },
{ /* Logitech G Pro X Superlight Gaming Mouse over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC094) },
+ { /* Logitech G Pro X Superlight 2 Gaming Mouse over USB */
+ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC09b) },
{ /* G935 Gaming Headset */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0x0a87),
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 5ec1f17412..fd5b0637da 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -1802,7 +1802,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
return 0;
}
-#ifdef CONFIG_PM
static int mt_suspend(struct hid_device *hdev, pm_message_t state)
{
struct mt_device *td = hid_get_drvdata(hdev);
@@ -1836,7 +1835,6 @@ static int mt_resume(struct hid_device *hdev)
return 0;
}
-#endif
static void mt_remove(struct hid_device *hdev)
{
@@ -2264,10 +2262,8 @@ static struct hid_driver mt_driver = {
.usage_table = mt_grabbed_usages,
.event = mt_event,
.report = mt_report,
-#ifdef CONFIG_PM
- .suspend = mt_suspend,
- .reset_resume = mt_reset_resume,
- .resume = mt_resume,
-#endif
+ .suspend = pm_ptr(mt_suspend),
+ .reset_resume = pm_ptr(mt_reset_resume),
+ .resume = pm_ptr(mt_resume),
};
module_hid_driver(mt_driver);
diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
index 4850e915a5..997c3a1ada 100644
--- a/drivers/hid/hid-nintendo.c
+++ b/drivers/hid/hid-nintendo.c
@@ -410,6 +410,18 @@ static const char * const joycon_player_led_names[] = {
LED_FUNCTION_PLAYER4,
};
#define JC_NUM_LEDS ARRAY_SIZE(joycon_player_led_names)
+#define JC_NUM_LED_PATTERNS 8
+/* Taken from https://www.nintendo.com/my/support/qa/detail/33822 */
+static const enum led_brightness joycon_player_led_patterns[JC_NUM_LED_PATTERNS][JC_NUM_LEDS] = {
+ { 1, 0, 0, 0 },
+ { 1, 1, 0, 0 },
+ { 1, 1, 1, 0 },
+ { 1, 1, 1, 1 },
+ { 1, 0, 0, 1 },
+ { 1, 0, 1, 0 },
+ { 1, 0, 1, 1 },
+ { 0, 1, 1, 0 },
+};
/* Each physical controller is associated with a joycon_ctlr struct */
struct joycon_ctlr {
@@ -699,6 +711,25 @@ static int joycon_set_player_leds(struct joycon_ctlr *ctlr, u8 flash, u8 on)
return joycon_send_subcmd(ctlr, req, 1, HZ/4);
}
+static int joycon_set_home_led(struct joycon_ctlr *ctlr, enum led_brightness brightness)
+{
+ struct joycon_subcmd_request *req;
+ u8 buffer[sizeof(*req) + 5] = { 0 };
+ u8 *data;
+
+ req = (struct joycon_subcmd_request *)buffer;
+ req->subcmd_id = JC_SUBCMD_SET_HOME_LIGHT;
+ data = req->data;
+ data[0] = 0x01;
+ data[1] = brightness << 4;
+ data[2] = brightness | (brightness << 4);
+ data[3] = 0x11;
+ data[4] = 0x11;
+
+ hid_dbg(ctlr->hdev, "setting home led brightness\n");
+ return joycon_send_subcmd(ctlr, req, 5, HZ/4);
+}
+
static int joycon_request_spi_flash_read(struct joycon_ctlr *ctlr,
u32 start_addr, u8 size, u8 **reply)
{
@@ -1853,6 +1884,7 @@ static int joycon_input_create(struct joycon_ctlr *ctlr)
return 0;
}
+/* Because the subcommand sets all the leds at once, the brightness argument is ignored */
static int joycon_player_led_brightness_set(struct led_classdev *led,
enum led_brightness brightness)
{
@@ -1862,7 +1894,6 @@ static int joycon_player_led_brightness_set(struct led_classdev *led,
int val = 0;
int i;
int ret;
- int num;
ctlr = hid_get_drvdata(hdev);
if (!ctlr) {
@@ -1870,21 +1901,10 @@ static int joycon_player_led_brightness_set(struct led_classdev *led,
return -ENODEV;
}
- /* determine which player led this is */
- for (num = 0; num < JC_NUM_LEDS; num++) {
- if (&ctlr->leds[num] == led)
- break;
- }
- if (num >= JC_NUM_LEDS)
- return -EINVAL;
+ for (i = 0; i < JC_NUM_LEDS; i++)
+ val |= ctlr->leds[i].brightness << i;
mutex_lock(&ctlr->output_mutex);
- for (i = 0; i < JC_NUM_LEDS; i++) {
- if (i == num)
- val |= brightness << i;
- else
- val |= ctlr->leds[i].brightness << i;
- }
ret = joycon_set_player_leds(ctlr, 0, val);
mutex_unlock(&ctlr->output_mutex);
@@ -1897,9 +1917,6 @@ static int joycon_home_led_brightness_set(struct led_classdev *led,
struct device *dev = led->dev->parent;
struct hid_device *hdev = to_hid_device(dev);
struct joycon_ctlr *ctlr;
- struct joycon_subcmd_request *req;
- u8 buffer[sizeof(*req) + 5] = { 0 };
- u8 *data;
int ret;
ctlr = hid_get_drvdata(hdev);
@@ -1907,43 +1924,35 @@ static int joycon_home_led_brightness_set(struct led_classdev *led,
hid_err(hdev, "No controller data\n");
return -ENODEV;
}
-
- req = (struct joycon_subcmd_request *)buffer;
- req->subcmd_id = JC_SUBCMD_SET_HOME_LIGHT;
- data = req->data;
- data[0] = 0x01;
- data[1] = brightness << 4;
- data[2] = brightness | (brightness << 4);
- data[3] = 0x11;
- data[4] = 0x11;
-
- hid_dbg(hdev, "setting home led brightness\n");
mutex_lock(&ctlr->output_mutex);
- ret = joycon_send_subcmd(ctlr, req, 5, HZ/4);
+ ret = joycon_set_home_led(ctlr, brightness);
mutex_unlock(&ctlr->output_mutex);
-
return ret;
}
-static DEFINE_MUTEX(joycon_input_num_mutex);
+static DEFINE_SPINLOCK(joycon_input_num_spinlock);
static int joycon_leds_create(struct joycon_ctlr *ctlr)
{
struct hid_device *hdev = ctlr->hdev;
struct device *dev = &hdev->dev;
const char *d_name = dev_name(dev);
struct led_classdev *led;
+ int led_val = 0;
char *name;
- int ret = 0;
+ int ret;
int i;
- static int input_num = 1;
+ unsigned long flags;
+ int player_led_pattern;
+ static int input_num;
- /* Set the default controller player leds based on controller number */
- mutex_lock(&joycon_input_num_mutex);
- mutex_lock(&ctlr->output_mutex);
- ret = joycon_set_player_leds(ctlr, 0, 0xF >> (4 - input_num));
- if (ret)
- hid_warn(ctlr->hdev, "Failed to set leds; ret=%d\n", ret);
- mutex_unlock(&ctlr->output_mutex);
+ /*
+ * Set the player leds based on controller number
+ * Because there is no standard concept of "player number", the pattern
+ * number will simply increase by 1 every time a controller is connected.
+ */
+ spin_lock_irqsave(&joycon_input_num_spinlock, flags);
+ player_led_pattern = input_num++ % JC_NUM_LED_PATTERNS;
+ spin_unlock_irqrestore(&joycon_input_num_spinlock, flags);
/* configure the player LEDs */
for (i = 0; i < JC_NUM_LEDS; i++) {
@@ -1951,31 +1960,37 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr)
d_name,
"green",
joycon_player_led_names[i]);
- if (!name) {
- mutex_unlock(&joycon_input_num_mutex);
+ if (!name)
return -ENOMEM;
- }
led = &ctlr->leds[i];
led->name = name;
- led->brightness = ((i + 1) <= input_num) ? 1 : 0;
+ led->brightness = joycon_player_led_patterns[player_led_pattern][i];
led->max_brightness = 1;
led->brightness_set_blocking =
joycon_player_led_brightness_set;
led->flags = LED_CORE_SUSPENDRESUME | LED_HW_PLUGGABLE;
+ led_val |= joycon_player_led_patterns[player_led_pattern][i] << i;
+ }
+ mutex_lock(&ctlr->output_mutex);
+ ret = joycon_set_player_leds(ctlr, 0, led_val);
+ mutex_unlock(&ctlr->output_mutex);
+ if (ret) {
+ hid_warn(hdev, "Failed to set players LEDs, skipping registration; ret=%d\n", ret);
+ goto home_led;
+ }
+
+ for (i = 0; i < JC_NUM_LEDS; i++) {
+ led = &ctlr->leds[i];
ret = devm_led_classdev_register(&hdev->dev, led);
if (ret) {
- hid_err(hdev, "Failed registering %s LED\n", led->name);
- mutex_unlock(&joycon_input_num_mutex);
+ hid_err(hdev, "Failed to register player %d LED; ret=%d\n", i + 1, ret);
return ret;
}
}
- if (++input_num > 4)
- input_num = 1;
- mutex_unlock(&joycon_input_num_mutex);
-
+home_led:
/* configure the home LED */
if (jc_type_has_right(ctlr)) {
name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s:%s",
@@ -1991,16 +2006,20 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr)
led->max_brightness = 0xF;
led->brightness_set_blocking = joycon_home_led_brightness_set;
led->flags = LED_CORE_SUSPENDRESUME | LED_HW_PLUGGABLE;
- ret = devm_led_classdev_register(&hdev->dev, led);
+
+ /* Set the home LED to 0 as default state */
+ mutex_lock(&ctlr->output_mutex);
+ ret = joycon_set_home_led(ctlr, 0);
+ mutex_unlock(&ctlr->output_mutex);
if (ret) {
- hid_err(hdev, "Failed registering home led\n");
- return ret;
+ hid_warn(hdev, "Failed to set home LED, skipping registration; ret=%d\n", ret);
+ return 0;
}
- /* Set the home LED to 0 as default state */
- ret = joycon_home_led_brightness_set(led, 0);
+
+ ret = devm_led_classdev_register(&hdev->dev, led);
if (ret) {
- hid_warn(hdev, "Failed to set home LED default, unregistering home LED");
- devm_led_classdev_unregister(&hdev->dev, led);
+ hid_err(hdev, "Failed to register home LED; ret=%d\n", ret);
+ return ret;
}
}
diff --git a/drivers/hid/hid-nvidia-shield.c b/drivers/hid/hid-nvidia-shield.c
index c463e54dec..58b15750db 100644
--- a/drivers/hid/hid-nvidia-shield.c
+++ b/drivers/hid/hid-nvidia-shield.c
@@ -800,6 +800,8 @@ static inline int thunderstrike_led_create(struct thunderstrike *ts)
led->name = devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL,
"thunderstrike%d:blue:led", ts->id);
+ if (!led->name)
+ return -ENOMEM;
led->max_brightness = 1;
led->flags = LED_CORE_SUSPENDRESUME | LED_RETAIN_AT_SHUTDOWN;
led->brightness_get = &thunderstrike_led_get_brightness;
@@ -831,6 +833,8 @@ static inline int thunderstrike_psy_create(struct shield_device *shield_dev)
shield_dev->battery_dev.desc.name =
devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL,
"thunderstrike_%d", ts->id);
+ if (!shield_dev->battery_dev.desc.name)
+ return -ENOMEM;
shield_dev->battery_dev.psy = power_supply_register(
&hdev->dev, &shield_dev->battery_dev.desc, &psy_cfg);
@@ -915,6 +919,15 @@ err_id:
return ERR_PTR(ret);
}
+static void thunderstrike_destroy(struct thunderstrike *ts)
+{
+ led_classdev_unregister(&ts->led_dev);
+ power_supply_unregister(ts->base.battery_dev.psy);
+ if (ts->haptics_dev)
+ input_unregister_device(ts->haptics_dev);
+ ida_free(&thunderstrike_ida, ts->id);
+}
+
static int android_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field,
struct hid_usage *usage, unsigned long **bit,
@@ -1074,11 +1087,7 @@ static int shield_probe(struct hid_device *hdev, const struct hid_device_id *id)
err_stop:
hid_hw_stop(hdev);
err_ts_create:
- power_supply_unregister(ts->base.battery_dev.psy);
- if (ts->haptics_dev)
- input_unregister_device(ts->haptics_dev);
- led_classdev_unregister(&ts->led_dev);
- ida_free(&thunderstrike_ida, ts->id);
+ thunderstrike_destroy(ts);
return ret;
}
@@ -1090,11 +1099,7 @@ static void shield_remove(struct hid_device *hdev)
ts = container_of(dev, struct thunderstrike, base);
hid_hw_close(hdev);
- power_supply_unregister(dev->battery_dev.psy);
- if (ts->haptics_dev)
- input_unregister_device(ts->haptics_dev);
- led_classdev_unregister(&ts->led_dev);
- ida_free(&thunderstrike_ida, ts->id);
+ thunderstrike_destroy(ts);
del_timer_sync(&ts->psy_stats_timer);
cancel_work_sync(&ts->hostcmd_req_work);
hid_hw_stop(hdev);
diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c
index d726aaafb1..a4dccdcda2 100644
--- a/drivers/hid/hid-picolcd_fb.c
+++ b/drivers/hid/hid-picolcd_fb.c
@@ -283,54 +283,6 @@ out:
mutex_unlock(&info->lock);
}
-/* Stub to call the system default and update the image on the picoLCD */
-static void picolcd_fb_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect)
-{
- if (!info->par)
- return;
- sys_fillrect(info, rect);
-
- schedule_delayed_work(&info->deferred_work, 0);
-}
-
-/* Stub to call the system default and update the image on the picoLCD */
-static void picolcd_fb_copyarea(struct fb_info *info,
- const struct fb_copyarea *area)
-{
- if (!info->par)
- return;
- sys_copyarea(info, area);
-
- schedule_delayed_work(&info->deferred_work, 0);
-}
-
-/* Stub to call the system default and update the image on the picoLCD */
-static void picolcd_fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
- if (!info->par)
- return;
- sys_imageblit(info, image);
-
- schedule_delayed_work(&info->deferred_work, 0);
-}
-
-/*
- * this is the slow path from userspace. they can seek and write to
- * the fb. it's inefficient to do anything less than a full screen draw
- */
-static ssize_t picolcd_fb_write(struct fb_info *info, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- ssize_t ret;
- if (!info->par)
- return -ENODEV;
- ret = fb_sys_write(info, buf, count, ppos);
- if (ret >= 0)
- schedule_delayed_work(&info->deferred_work, 0);
- return ret;
-}
-
static int picolcd_fb_blank(int blank, struct fb_info *info)
{
/* We let fb notification do this for us via lcd/backlight device */
@@ -417,18 +369,31 @@ static int picolcd_set_par(struct fb_info *info)
return 0;
}
+static void picolcdfb_ops_damage_range(struct fb_info *info, off_t off, size_t len)
+{
+ if (!info->par)
+ return;
+ schedule_delayed_work(&info->deferred_work, 0);
+}
+
+static void picolcdfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height)
+{
+ if (!info->par)
+ return;
+ schedule_delayed_work(&info->deferred_work, 0);
+}
+
+FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(picolcdfb_ops,
+ picolcdfb_ops_damage_range,
+ picolcdfb_ops_damage_area)
+
static const struct fb_ops picolcdfb_ops = {
.owner = THIS_MODULE,
+ FB_DEFAULT_DEFERRED_OPS(picolcdfb_ops),
.fb_destroy = picolcd_fb_destroy,
- .fb_read = fb_sys_read,
- .fb_write = picolcd_fb_write,
.fb_blank = picolcd_fb_blank,
- .fb_fillrect = picolcd_fb_fillrect,
- .fb_copyarea = picolcd_fb_copyarea,
- .fb_imageblit = picolcd_fb_imageblit,
.fb_check_var = picolcd_fb_check_var,
.fb_set_par = picolcd_set_par,
- .fb_mmap = fb_deferred_io_mmap,
};
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c
index e4e9471d0f..c16d2ba6ea 100644
--- a/drivers/hid/hid-prodikeys.c
+++ b/drivers/hid/hid-prodikeys.c
@@ -639,9 +639,9 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
goto fail;
}
- strncpy(card->driver, shortname, sizeof(card->driver));
- strncpy(card->shortname, shortname, sizeof(card->shortname));
- strncpy(card->longname, longname, sizeof(card->longname));
+ strscpy(card->driver, shortname, sizeof(card->driver));
+ strscpy(card->shortname, shortname, sizeof(card->shortname));
+ strscpy(card->longname, longname, sizeof(card->longname));
/* Set up rawmidi */
err = snd_rawmidi_new(card, card->shortname, 0,
@@ -652,7 +652,7 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
goto fail;
}
pm->rwmidi = rwmidi;
- strncpy(rwmidi->name, card->shortname, sizeof(rwmidi->name));
+ strscpy(rwmidi->name, card->shortname, sizeof(rwmidi->name));
rwmidi->info_flags = SNDRV_RAWMIDI_INFO_INPUT;
rwmidi->private_data = pm;
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
index 84e7ba5314..d4af17fdba 100644
--- a/drivers/hid/hid-rmi.c
+++ b/drivers/hid/hid-rmi.c
@@ -436,7 +436,6 @@ static void rmi_report(struct hid_device *hid, struct hid_report *report)
input_sync(field->hidinput->input);
}
-#ifdef CONFIG_PM
static int rmi_suspend(struct hid_device *hdev, pm_message_t message)
{
struct rmi_data *data = hid_get_drvdata(hdev);
@@ -483,7 +482,6 @@ out:
hid_hw_close(hdev);
return ret;
}
-#endif /* CONFIG_PM */
static int rmi_hid_reset(struct rmi_transport_dev *xport, u16 reset_addr)
{
@@ -774,11 +772,9 @@ static struct hid_driver rmi_driver = {
.report = rmi_report,
.input_mapping = rmi_input_mapping,
.input_configured = rmi_input_configured,
-#ifdef CONFIG_PM
- .suspend = rmi_suspend,
- .resume = rmi_post_resume,
- .reset_resume = rmi_post_resume,
-#endif
+ .suspend = pm_ptr(rmi_suspend),
+ .resume = pm_ptr(rmi_post_resume),
+ .reset_resume = pm_ptr(rmi_post_resume),
};
module_hid_driver(rmi_driver);
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 13c8dd8cd3..2bc762d31a 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -357,8 +357,11 @@ static int hidraw_release(struct inode * inode, struct file * file)
down_write(&minors_rwsem);
spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
- for (int i = list->tail; i < list->head; i++)
- kfree(list->buffer[i].value);
+ while (list->tail != list->head) {
+ kfree(list->buffer[list->tail].value);
+ list->buffer[list->tail].value = NULL;
+ list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
+ }
list_del(&list->node);
spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
kfree(list);
diff --git a/drivers/hid/i2c-hid/i2c-hid-of.c b/drivers/hid/i2c-hid/i2c-hid-of.c
index c4e1fa0273..8be4d576da 100644
--- a/drivers/hid/i2c-hid/i2c-hid-of.c
+++ b/drivers/hid/i2c-hid/i2c-hid-of.c
@@ -87,6 +87,7 @@ static int i2c_hid_of_probe(struct i2c_client *client)
if (!ihid_of)
return -ENOMEM;
+ ihid_of->client = client;
ihid_of->ops.power_up = i2c_hid_of_power_up;
ihid_of->ops.power_down = i2c_hid_of_power_down;
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 257dd73e37..a90ed2ceae 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -1562,7 +1562,6 @@ static int hid_post_reset(struct usb_interface *intf)
return 0;
}
-#ifdef CONFIG_PM
static int hid_resume_common(struct hid_device *hid, bool driver_suspended)
{
int status = 0;
@@ -1654,8 +1653,6 @@ static int hid_reset_resume(struct usb_interface *intf)
return status;
}
-#endif /* CONFIG_PM */
-
static const struct usb_device_id hid_usb_ids[] = {
{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
.bInterfaceClass = USB_INTERFACE_CLASS_HID },
@@ -1668,11 +1665,9 @@ static struct usb_driver hid_driver = {
.name = "usbhid",
.probe = usbhid_probe,
.disconnect = usbhid_disconnect,
-#ifdef CONFIG_PM
- .suspend = hid_suspend,
- .resume = hid_resume,
- .reset_resume = hid_reset_resume,
-#endif
+ .suspend = pm_ptr(hid_suspend),
+ .resume = pm_ptr(hid_resume),
+ .reset_resume = pm_ptr(hid_reset_resume),
.pre_reset = hid_pre_reset,
.post_reset = hid_post_reset,
.id_table = hid_usb_ids,
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 3f704b8072..7659c98d94 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -2080,7 +2080,7 @@ static int wacom_allocate_inputs(struct wacom *wacom)
return 0;
}
-static int wacom_register_inputs(struct wacom *wacom)
+static int wacom_setup_inputs(struct wacom *wacom)
{
struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
@@ -2099,10 +2099,6 @@ static int wacom_register_inputs(struct wacom *wacom)
input_free_device(pen_input_dev);
wacom_wac->pen_input = NULL;
pen_input_dev = NULL;
- } else {
- error = input_register_device(pen_input_dev);
- if (error)
- goto fail;
}
error = wacom_setup_touch_input_capabilities(touch_input_dev, wacom_wac);
@@ -2111,10 +2107,6 @@ static int wacom_register_inputs(struct wacom *wacom)
input_free_device(touch_input_dev);
wacom_wac->touch_input = NULL;
touch_input_dev = NULL;
- } else {
- error = input_register_device(touch_input_dev);
- if (error)
- goto fail;
}
error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac);
@@ -2123,7 +2115,34 @@ static int wacom_register_inputs(struct wacom *wacom)
input_free_device(pad_input_dev);
wacom_wac->pad_input = NULL;
pad_input_dev = NULL;
- } else {
+ }
+
+ return 0;
+}
+
+static int wacom_register_inputs(struct wacom *wacom)
+{
+ struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
+ struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
+ int error = 0;
+
+ pen_input_dev = wacom_wac->pen_input;
+ touch_input_dev = wacom_wac->touch_input;
+ pad_input_dev = wacom_wac->pad_input;
+
+ if (pen_input_dev) {
+ error = input_register_device(pen_input_dev);
+ if (error)
+ goto fail;
+ }
+
+ if (touch_input_dev) {
+ error = input_register_device(touch_input_dev);
+ if (error)
+ goto fail;
+ }
+
+ if (pad_input_dev) {
error = input_register_device(pad_input_dev);
if (error)
goto fail;
@@ -2376,6 +2395,20 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
if (error)
goto fail;
+ error = wacom_setup_inputs(wacom);
+ if (error)
+ goto fail;
+
+ if (features->type == HID_GENERIC)
+ connect_mask |= HID_CONNECT_DRIVER;
+
+ /* Regular HID work starts now */
+ error = hid_hw_start(hdev, connect_mask);
+ if (error) {
+ hid_err(hdev, "hw start failed\n");
+ goto fail;
+ }
+
error = wacom_register_inputs(wacom);
if (error)
goto fail;
@@ -2390,16 +2423,6 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
goto fail;
}
- if (features->type == HID_GENERIC)
- connect_mask |= HID_CONNECT_DRIVER;
-
- /* Regular HID work starts now */
- error = hid_hw_start(hdev, connect_mask);
- if (error) {
- hid_err(hdev, "hw start failed\n");
- goto fail;
- }
-
if (!wireless) {
/* Note that if query fails it is not a hard failure */
wacom_query_tablet_data(wacom);
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 8289ce7637..002cbaa16b 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2574,7 +2574,14 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
wacom_wac->hid_data.tipswitch);
input_report_key(input, wacom_wac->tool[0], sense);
if (wacom_wac->serial[0]) {
- input_event(input, EV_MSC, MSC_SERIAL, wacom_wac->serial[0]);
+ /*
+ * xf86-input-wacom does not accept a serial number
+ * of '0'. Report the low 32 bits if possible, but
+ * if they are zero, report the upper ones instead.
+ */
+ __u32 serial_lo = wacom_wac->serial[0] & 0xFFFFFFFFu;
+ __u32 serial_hi = wacom_wac->serial[0] >> 32;
+ input_event(input, EV_MSC, MSC_SERIAL, (int)(serial_lo ? serial_lo : serial_hi));
input_report_abs(input, ABS_MISC, sense ? id : 0);
}