Skip to content

Commit 034b8c2

Browse files
committed
platform/x86: intel-vbtn: Create 2 separate input-devs for buttons and switches
Create 2 separate input-devs for buttons and switches, this is a preparation for dynamically registering the switches-input device for devices which are not on the switches allow-list, but do make Notify() calls with an event value from the switches sparse-keymap. This also brings the intel-vbtn driver inline with the intel-hid driver which is doing the same thing. Cc: Elia Devito <[email protected]> Signed-off-by: Hans de Goede <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 5862b4d commit 034b8c2

File tree

1 file changed

+62
-36
lines changed

1 file changed

+62
-36
lines changed

drivers/platform/x86/intel-vbtn.c

Lines changed: 62 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,23 @@ static const struct key_entry intel_vbtn_keymap[] = {
4444
{ KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } }, /* volume-down key release */
4545
{ KE_KEY, 0xC8, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key press */
4646
{ KE_KEY, 0xC9, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key release */
47+
{ KE_END }
4748
};
4849

4950
static const struct key_entry intel_vbtn_switchmap[] = {
5051
{ KE_SW, 0xCA, { .sw = { SW_DOCK, 1 } } }, /* Docked */
5152
{ KE_SW, 0xCB, { .sw = { SW_DOCK, 0 } } }, /* Undocked */
5253
{ KE_SW, 0xCC, { .sw = { SW_TABLET_MODE, 1 } } }, /* Tablet */
5354
{ KE_SW, 0xCD, { .sw = { SW_TABLET_MODE, 0 } } }, /* Laptop */
55+
{ KE_END }
5456
};
5557

5658
#define KEYMAP_LEN \
5759
(ARRAY_SIZE(intel_vbtn_keymap) + ARRAY_SIZE(intel_vbtn_switchmap) + 1)
5860

5961
struct intel_vbtn_priv {
60-
struct key_entry keymap[KEYMAP_LEN];
61-
struct input_dev *input_dev;
62+
struct input_dev *buttons_dev;
63+
struct input_dev *switches_dev;
6264
bool has_buttons;
6365
bool has_switches;
6466
bool wakeup_mode;
@@ -77,48 +79,62 @@ static void detect_tablet_mode(struct platform_device *device)
7779
return;
7880

7981
m = !(vgbs & VGBS_TABLET_MODE_FLAGS);
80-
input_report_switch(priv->input_dev, SW_TABLET_MODE, m);
82+
input_report_switch(priv->switches_dev, SW_TABLET_MODE, m);
8183
m = (vgbs & VGBS_DOCK_MODE_FLAG) ? 1 : 0;
82-
input_report_switch(priv->input_dev, SW_DOCK, m);
84+
input_report_switch(priv->switches_dev, SW_DOCK, m);
8385
}
8486

87+
/*
88+
* Note this unconditionally creates the 2 input_dev-s and sets up
89+
* the sparse-keymaps. Only the registration is conditional on
90+
* have_buttons / have_switches. This is done so that the notify
91+
* handler can always call sparse_keymap_entry_from_scancode()
92+
* on the input_dev-s do determine the event type.
93+
*/
8594
static int intel_vbtn_input_setup(struct platform_device *device)
8695
{
8796
struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
88-
int ret, keymap_len = 0;
97+
int ret;
8998

90-
if (priv->has_buttons) {
91-
memcpy(&priv->keymap[keymap_len], intel_vbtn_keymap,
92-
ARRAY_SIZE(intel_vbtn_keymap) *
93-
sizeof(struct key_entry));
94-
keymap_len += ARRAY_SIZE(intel_vbtn_keymap);
95-
}
99+
priv->buttons_dev = devm_input_allocate_device(&device->dev);
100+
if (!priv->buttons_dev)
101+
return -ENOMEM;
96102

97-
if (priv->has_switches) {
98-
memcpy(&priv->keymap[keymap_len], intel_vbtn_switchmap,
99-
ARRAY_SIZE(intel_vbtn_switchmap) *
100-
sizeof(struct key_entry));
101-
keymap_len += ARRAY_SIZE(intel_vbtn_switchmap);
102-
}
103+
ret = sparse_keymap_setup(priv->buttons_dev, intel_vbtn_keymap, NULL);
104+
if (ret)
105+
return ret;
103106

104-
priv->keymap[keymap_len].type = KE_END;
107+
priv->buttons_dev->dev.parent = &device->dev;
108+
priv->buttons_dev->name = "Intel Virtual Buttons";
109+
priv->buttons_dev->id.bustype = BUS_HOST;
110+
111+
if (priv->has_buttons) {
112+
ret = input_register_device(priv->buttons_dev);
113+
if (ret)
114+
return ret;
115+
}
105116

106-
priv->input_dev = devm_input_allocate_device(&device->dev);
107-
if (!priv->input_dev)
117+
priv->switches_dev = devm_input_allocate_device(&device->dev);
118+
if (!priv->switches_dev)
108119
return -ENOMEM;
109120

110-
ret = sparse_keymap_setup(priv->input_dev, priv->keymap, NULL);
121+
ret = sparse_keymap_setup(priv->switches_dev, intel_vbtn_switchmap, NULL);
111122
if (ret)
112123
return ret;
113124

114-
priv->input_dev->dev.parent = &device->dev;
115-
priv->input_dev->name = "Intel Virtual Button driver";
116-
priv->input_dev->id.bustype = BUS_HOST;
125+
priv->switches_dev->dev.parent = &device->dev;
126+
priv->switches_dev->name = "Intel Virtual Switches";
127+
priv->switches_dev->id.bustype = BUS_HOST;
117128

118-
if (priv->has_switches)
129+
if (priv->has_switches) {
119130
detect_tablet_mode(device);
120131

121-
return input_register_device(priv->input_dev);
132+
ret = input_register_device(priv->switches_dev);
133+
if (ret)
134+
return ret;
135+
}
136+
137+
return 0;
122138
}
123139

124140
static void notify_handler(acpi_handle handle, u32 event, void *context)
@@ -127,13 +143,27 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
127143
struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
128144
unsigned int val = !(event & 1); /* Even=press, Odd=release */
129145
const struct key_entry *ke, *ke_rel;
146+
struct input_dev *input_dev;
130147
bool autorelease;
131148

132-
if (priv->wakeup_mode) {
133-
ke = sparse_keymap_entry_from_scancode(priv->input_dev, event);
134-
if (!ke)
135-
goto out_unknown;
149+
if ((ke = sparse_keymap_entry_from_scancode(priv->buttons_dev, event))) {
150+
if (!priv->has_buttons) {
151+
dev_warn(&device->dev, "Warning: received a button event on a device without buttons, please report this.\n");
152+
return;
153+
}
154+
input_dev = priv->buttons_dev;
155+
} else if ((ke = sparse_keymap_entry_from_scancode(priv->switches_dev, event))) {
156+
if (!priv->has_switches) {
157+
dev_warn(&device->dev, "Warning: received a switches event on a device without switchess, please report this.\n");
158+
return;
159+
}
160+
input_dev = priv->switches_dev;
161+
} else {
162+
dev_dbg(&device->dev, "unknown event index 0x%x\n", event);
163+
return;
164+
}
136165

166+
if (priv->wakeup_mode) {
137167
pm_wakeup_hard_event(&device->dev);
138168

139169
/*
@@ -148,14 +178,10 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
148178
* Even press events are autorelease if there is no corresponding odd
149179
* release event, or if the odd event is KE_IGNORE.
150180
*/
151-
ke_rel = sparse_keymap_entry_from_scancode(priv->input_dev, event | 1);
181+
ke_rel = sparse_keymap_entry_from_scancode(input_dev, event | 1);
152182
autorelease = val && (!ke_rel || ke_rel->type == KE_IGNORE);
153183

154-
if (sparse_keymap_report_event(priv->input_dev, event, val, autorelease))
155-
return;
156-
157-
out_unknown:
158-
dev_dbg(&device->dev, "unknown event index 0x%x\n", event);
184+
sparse_keymap_report_event(input_dev, event, val, autorelease);
159185
}
160186

161187
static bool intel_vbtn_has_buttons(acpi_handle handle)

0 commit comments

Comments
 (0)