26
26
#define APPLETB_KBD_MODE_OFF 3
27
27
#define APPLETB_KBD_MODE_MAX APPLETB_KBD_MODE_OFF
28
28
29
+ #define APPLETB_DEVID_KEYBOARD 1
30
+
29
31
#define HID_USAGE_MODE 0x00ff0004
30
32
31
33
static int appletb_tb_def_mode = APPLETB_KBD_MODE_SPCL ;
@@ -35,11 +37,18 @@ MODULE_PARM_DESC(mode, "Default touchbar mode:\n"
35
37
" 1 - function-keys\n"
36
38
" [2] - special keys" );
37
39
40
+ static bool appletb_tb_fn_toggle = true;
41
+ module_param_named (fntoggle , appletb_tb_fn_toggle , bool , 0644 );
42
+ MODULE_PARM_DESC (fntoggle , "Switch between Fn and media controls on pressing Fn key" );
43
+
38
44
struct appletb_kbd {
39
45
struct hid_field * mode_field ;
40
46
41
47
u8 saved_mode ;
42
48
u8 current_mode ;
49
+ struct input_handler inp_handler ;
50
+ struct input_handle kbd_handle ;
51
+
43
52
};
44
53
45
54
static const struct key_entry appletb_kbd_keymap [] = {
@@ -172,6 +181,75 @@ static int appletb_kbd_hid_event(struct hid_device *hdev, struct hid_field *fiel
172
181
return kbd -> current_mode == APPLETB_KBD_MODE_OFF ;
173
182
}
174
183
184
+ static void appletb_kbd_inp_event (struct input_handle * handle , unsigned int type ,
185
+ unsigned int code , int value )
186
+ {
187
+ struct appletb_kbd * kbd = handle -> private ;
188
+
189
+ if (type == EV_KEY && code == KEY_FN && appletb_tb_fn_toggle ) {
190
+ if (value == 1 ) {
191
+ kbd -> saved_mode = kbd -> current_mode ;
192
+ if (kbd -> current_mode == APPLETB_KBD_MODE_SPCL )
193
+ appletb_kbd_set_mode (kbd , APPLETB_KBD_MODE_FN );
194
+ else if (kbd -> current_mode == APPLETB_KBD_MODE_FN )
195
+ appletb_kbd_set_mode (kbd , APPLETB_KBD_MODE_SPCL );
196
+ } else if (value == 0 ) {
197
+ if (kbd -> saved_mode != kbd -> current_mode )
198
+ appletb_kbd_set_mode (kbd , kbd -> saved_mode );
199
+ }
200
+ }
201
+ }
202
+
203
+ static int appletb_kbd_inp_connect (struct input_handler * handler ,
204
+ struct input_dev * dev ,
205
+ const struct input_device_id * id )
206
+ {
207
+ struct appletb_kbd * kbd = handler -> private ;
208
+ struct input_handle * handle ;
209
+ int rc ;
210
+
211
+ if (id -> driver_info == APPLETB_DEVID_KEYBOARD ) {
212
+ handle = & kbd -> kbd_handle ;
213
+ handle -> name = "tbkbd" ;
214
+ } else {
215
+ return - ENOENT ;
216
+ }
217
+
218
+ if (handle -> dev )
219
+ return - EEXIST ;
220
+
221
+ handle -> open = 0 ;
222
+ handle -> dev = input_get_device (dev );
223
+ handle -> handler = handler ;
224
+ handle -> private = kbd ;
225
+
226
+ rc = input_register_handle (handle );
227
+ if (rc )
228
+ goto err_free_dev ;
229
+
230
+ rc = input_open_device (handle );
231
+ if (rc )
232
+ goto err_unregister_handle ;
233
+
234
+ return 0 ;
235
+
236
+ err_unregister_handle :
237
+ input_unregister_handle (handle );
238
+ err_free_dev :
239
+ input_put_device (handle -> dev );
240
+ handle -> dev = NULL ;
241
+ return rc ;
242
+ }
243
+
244
+ static void appletb_kbd_inp_disconnect (struct input_handle * handle )
245
+ {
246
+ input_close_device (handle );
247
+ input_unregister_handle (handle );
248
+
249
+ input_put_device (handle -> dev );
250
+ handle -> dev = NULL ;
251
+ }
252
+
175
253
static int appletb_kbd_input_configured (struct hid_device * hdev , struct hid_input * hidinput )
176
254
{
177
255
int idx ;
@@ -195,6 +273,40 @@ static int appletb_kbd_input_configured(struct hid_device *hdev, struct hid_inpu
195
273
return 0 ;
196
274
}
197
275
276
+ static const struct input_device_id appletb_kbd_input_devices [] = {
277
+ {
278
+ .flags = INPUT_DEVICE_ID_MATCH_BUS |
279
+ INPUT_DEVICE_ID_MATCH_VENDOR |
280
+ INPUT_DEVICE_ID_MATCH_KEYBIT ,
281
+ .bustype = BUS_USB ,
282
+ .vendor = USB_VENDOR_ID_APPLE ,
283
+ .keybit = { [BIT_WORD (KEY_FN )] = BIT_MASK (KEY_FN ) },
284
+ .driver_info = APPLETB_DEVID_KEYBOARD ,
285
+ },
286
+ { }
287
+ };
288
+
289
+ static bool appletb_kbd_match_internal_device (struct input_handler * handler ,
290
+ struct input_dev * inp_dev )
291
+ {
292
+ struct device * dev = & inp_dev -> dev ;
293
+
294
+ /* in kernel: dev && !is_usb_device(dev) */
295
+ while (dev && !(dev -> type && dev -> type -> name &&
296
+ !strcmp (dev -> type -> name , "usb_device" )))
297
+ dev = dev -> parent ;
298
+
299
+ /*
300
+ * Apple labels all their internal keyboards and trackpads as such,
301
+ * instead of maintaining an ever expanding list of product-id's we
302
+ * just look at the device's product name.
303
+ */
304
+ if (dev )
305
+ return !!strstr (to_usb_device (dev )-> product , "Internal Keyboard" );
306
+
307
+ return false;
308
+ }
309
+
198
310
static int appletb_kbd_probe (struct hid_device * hdev , const struct hid_device_id * id )
199
311
{
200
312
struct appletb_kbd * kbd ;
@@ -227,6 +339,20 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id
227
339
goto stop_hw ;
228
340
}
229
341
342
+ kbd -> inp_handler .event = appletb_kbd_inp_event ;
343
+ kbd -> inp_handler .connect = appletb_kbd_inp_connect ;
344
+ kbd -> inp_handler .disconnect = appletb_kbd_inp_disconnect ;
345
+ kbd -> inp_handler .name = "appletb" ;
346
+ kbd -> inp_handler .id_table = appletb_kbd_input_devices ;
347
+ kbd -> inp_handler .match = appletb_kbd_match_internal_device ;
348
+ kbd -> inp_handler .private = kbd ;
349
+
350
+ ret = input_register_handler (& kbd -> inp_handler );
351
+ if (ret ) {
352
+ dev_err_probe (dev , ret , "Unable to register keyboard handler\n" );
353
+ goto close_hw ;
354
+ }
355
+
230
356
ret = appletb_kbd_set_mode (kbd , appletb_tb_def_mode );
231
357
if (ret ) {
232
358
dev_err_probe (dev , ret , "Failed to set touchbar mode\n" );
@@ -250,6 +376,8 @@ static void appletb_kbd_remove(struct hid_device *hdev)
250
376
251
377
appletb_kbd_set_mode (kbd , APPLETB_KBD_MODE_OFF );
252
378
379
+ input_unregister_handler (& kbd -> inp_handler );
380
+
253
381
hid_hw_close (hdev );
254
382
hid_hw_stop (hdev );
255
383
}
0 commit comments