xref: /linux/drivers/hid/hid-google-stadiaff.c (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Stadia controller rumble support.
4  *
5  * Copyright 2023 Google LLC
6  */
7 
8 #include <linux/hid.h>
9 #include <linux/input.h>
10 #include <linux/slab.h>
11 #include <linux/module.h>
12 
13 #include "hid-ids.h"
14 
15 #define STADIA_FF_REPORT_ID 5
16 
17 struct stadiaff_device {
18 	struct hid_device *hid;
19 	struct hid_report *report;
20 	u32 magnitudes;
21 	struct work_struct work;
22 };
23 
24 static void stadiaff_work(struct work_struct *work)
25 {
26 	struct stadiaff_device *stadiaff =
27 		container_of(work, struct stadiaff_device, work);
28 	struct hid_field *rumble_field = stadiaff->report->field[0];
29 	u32 mags = READ_ONCE(stadiaff->magnitudes);
30 
31 	rumble_field->value[0] = mags & 0xffff;
32 	rumble_field->value[1] = (mags >> 16) & 0xffff;
33 
34 	hid_hw_request(stadiaff->hid, stadiaff->report, HID_REQ_SET_REPORT);
35 }
36 
37 static int stadiaff_play(struct input_dev *dev, void *data,
38 			 struct ff_effect *effect)
39 {
40 	struct hid_device *hid = input_get_drvdata(dev);
41 	struct stadiaff_device *stadiaff = hid_get_drvdata(hid);
42 	u32 mags = (u32)effect->u.rumble.strong_magnitude |
43 		  ((u32)effect->u.rumble.weak_magnitude << 16);
44 
45 	WRITE_ONCE(stadiaff->magnitudes, mags);
46 	schedule_work(&stadiaff->work);
47 
48 	return 0;
49 }
50 
51 static int stadia_input_open(struct input_dev *dev)
52 {
53 	struct hid_device *hid = input_get_drvdata(dev);
54 	struct stadiaff_device *stadiaff = hid_get_drvdata(hid);
55 	int error;
56 
57 	error = hid_hw_open(hid);
58 	if (error)
59 		return error;
60 
61 	enable_work(&stadiaff->work);
62 	return 0;
63 }
64 
65 static void stadia_input_close(struct input_dev *dev)
66 {
67 	struct hid_device *hid = input_get_drvdata(dev);
68 	struct stadiaff_device *stadiaff = hid_get_drvdata(hid);
69 
70 	WRITE_ONCE(stadiaff->magnitudes, 0);
71 	stadiaff_work(&stadiaff->work);
72 	disable_work_sync(&stadiaff->work);
73 
74 	hid_hw_close(hid);
75 }
76 
77 static int stadia_input_configured(struct hid_device *hid, struct hid_input *hidinput)
78 {
79 	struct stadiaff_device *stadiaff;
80 	struct hid_report *report;
81 	struct input_dev *dev = hidinput->input;
82 	int error;
83 
84 	if (!list_is_first(&hidinput->list, &hid->inputs))
85 		return 0;
86 
87 	report = hid_validate_values(hid, HID_OUTPUT_REPORT,
88 				     STADIA_FF_REPORT_ID, 0, 2);
89 	if (!report)
90 		return -ENODEV;
91 
92 	stadiaff = devm_kzalloc(&hid->dev, sizeof(struct stadiaff_device),
93 				GFP_KERNEL);
94 	if (!stadiaff)
95 		return -ENOMEM;
96 
97 	hid_set_drvdata(hid, stadiaff);
98 
99 	input_set_capability(dev, EV_FF, FF_RUMBLE);
100 
101 	error = input_ff_create_memless(dev, NULL, stadiaff_play);
102 	if (error)
103 		return error;
104 
105 	stadiaff->hid = hid;
106 	stadiaff->report = report;
107 	INIT_WORK(&stadiaff->work, stadiaff_work);
108 	disable_work_sync(&stadiaff->work);
109 
110 	dev->open = stadia_input_open;
111 	dev->close = stadia_input_close;
112 
113 	hid_info(hid, "Force Feedback for Google Stadia controller\n");
114 
115 	return 0;
116 }
117 
118 static const struct hid_device_id stadia_devices[] = {
119 	{ HID_USB_DEVICE(USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STADIA) },
120 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STADIA) },
121 	{ }
122 };
123 MODULE_DEVICE_TABLE(hid, stadia_devices);
124 
125 static struct hid_driver stadia_driver = {
126 	.name = "stadia",
127 	.id_table = stadia_devices,
128 	.input_configured = stadia_input_configured,
129 };
130 module_hid_driver(stadia_driver);
131 
132 MODULE_DESCRIPTION("Google Stadia controller rumble support.");
133 MODULE_LICENSE("GPL");
134