1616
1717#include <linux/device.h>
1818#include <linux/hid.h>
19+ #include <linux/jiffies.h>
1920#include <linux/module.h>
2021#include <linux/slab.h>
22+ #include <linux/timer.h>
2123
2224#include "hid-ids.h"
2325
3032#define APPLE_INVERT_HWHEEL BIT(6)
3133/* BIT(7) reserved, was: APPLE_IGNORE_HIDINPUT */
3234#define APPLE_NUMLOCK_EMULATION BIT(8)
35+ #define APPLE_RDESC_BATTERY BIT(9)
3336
3437#define APPLE_FLAG_FKEY 0x01
3538
3639#define HID_COUNTRY_INTERNATIONAL_ISO 13
40+ #define APPLE_BATTERY_TIMEOUT_MS 60000
3741
3842static unsigned int fnmode = 1 ;
3943module_param (fnmode , uint , 0644 );
@@ -58,10 +62,12 @@ MODULE_PARM_DESC(swap_fn_leftctrl, "Swap the Fn and left Control keys. "
5862 "[0] = as-is, Mac layout, 1 = swapped, PC layout)" );
5963
6064struct apple_sc {
65+ struct hid_device * hdev ;
6166 unsigned long quirks ;
6267 unsigned int fn_on ;
6368 unsigned int fn_found ;
6469 DECLARE_BITMAP (pressed_numlock , KEY_CNT );
70+ struct timer_list battery_timer ;
6571};
6672
6773struct apple_key_translation {
@@ -333,6 +339,43 @@ static int apple_event(struct hid_device *hdev, struct hid_field *field,
333339 return 0 ;
334340}
335341
342+ static int apple_fetch_battery (struct hid_device * hdev )
343+ {
344+ #ifdef CONFIG_HID_BATTERY_STRENGTH
345+ struct apple_sc * asc = hid_get_drvdata (hdev );
346+ struct hid_report_enum * report_enum ;
347+ struct hid_report * report ;
348+
349+ if (!(asc -> quirks & APPLE_RDESC_BATTERY ) || !hdev -> battery )
350+ return -1 ;
351+
352+ report_enum = & hdev -> report_enum [hdev -> battery_report_type ];
353+ report = report_enum -> report_id_hash [hdev -> battery_report_id ];
354+
355+ if (!report || report -> maxfield < 1 )
356+ return -1 ;
357+
358+ if (hdev -> battery_capacity == hdev -> battery_max )
359+ return -1 ;
360+
361+ hid_hw_request (hdev , report , HID_REQ_GET_REPORT );
362+ return 0 ;
363+ #else
364+ return -1 ;
365+ #endif
366+ }
367+
368+ static void apple_battery_timer_tick (struct timer_list * t )
369+ {
370+ struct apple_sc * asc = from_timer (asc , t , battery_timer );
371+ struct hid_device * hdev = asc -> hdev ;
372+
373+ if (apple_fetch_battery (hdev ) == 0 ) {
374+ mod_timer (& asc -> battery_timer ,
375+ jiffies + msecs_to_jiffies (APPLE_BATTERY_TIMEOUT_MS ));
376+ }
377+ }
378+
336379/*
337380 * MacBook JIS keyboard has wrong logical maximum
338381 * Magic Keyboard JIS has wrong logical maximum
@@ -354,6 +397,30 @@ static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
354397 "fixing up MacBook JIS keyboard report descriptor\n" );
355398 rdesc [53 ] = rdesc [59 ] = 0xe7 ;
356399 }
400+
401+ /*
402+ * Change the usage from:
403+ * 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 0
404+ * 0x09, 0x0b, // Usage (Vendor Usage 0x0b) 3
405+ * To:
406+ * 0x05, 0x01, // Usage Page (Generic Desktop) 0
407+ * 0x09, 0x06, // Usage (Keyboard) 2
408+ */
409+ if ((asc -> quirks & APPLE_RDESC_BATTERY ) && * rsize == 83 &&
410+ rdesc [46 ] == 0x84 && rdesc [58 ] == 0x85 ) {
411+ hid_info (hdev ,
412+ "fixing up Magic Keyboard battery report descriptor\n" );
413+ * rsize = * rsize - 1 ;
414+ rdesc = kmemdup (rdesc + 1 , * rsize , GFP_KERNEL );
415+ if (!rdesc )
416+ return NULL ;
417+
418+ rdesc [0 ] = 0x05 ;
419+ rdesc [1 ] = 0x01 ;
420+ rdesc [2 ] = 0x09 ;
421+ rdesc [3 ] = 0x06 ;
422+ }
423+
357424 return rdesc ;
358425}
359426
@@ -447,6 +514,7 @@ static int apple_probe(struct hid_device *hdev,
447514 return - ENOMEM ;
448515 }
449516
517+ asc -> hdev = hdev ;
450518 asc -> quirks = quirks ;
451519
452520 hid_set_drvdata (hdev , asc );
@@ -463,9 +531,23 @@ static int apple_probe(struct hid_device *hdev,
463531 return ret ;
464532 }
465533
534+ timer_setup (& asc -> battery_timer , apple_battery_timer_tick , 0 );
535+ mod_timer (& asc -> battery_timer ,
536+ jiffies + msecs_to_jiffies (APPLE_BATTERY_TIMEOUT_MS ));
537+ apple_fetch_battery (hdev );
538+
466539 return 0 ;
467540}
468541
542+ static void apple_remove (struct hid_device * hdev )
543+ {
544+ struct apple_sc * asc = hid_get_drvdata (hdev );
545+
546+ del_timer_sync (& asc -> battery_timer );
547+
548+ hid_hw_stop (hdev );
549+ }
550+
469551static const struct hid_device_id apple_devices [] = {
470552 { HID_USB_DEVICE (USB_VENDOR_ID_APPLE , USB_DEVICE_ID_APPLE_MIGHTYMOUSE ),
471553 .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
@@ -540,11 +622,11 @@ static const struct hid_device_id apple_devices[] = {
540622 { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_APPLE , USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS ),
541623 .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
542624 { HID_USB_DEVICE (USB_VENDOR_ID_APPLE , USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015 ),
543- .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
625+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY },
544626 { HID_BLUETOOTH_DEVICE (BT_VENDOR_ID_APPLE , USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015 ),
545627 .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
546628 { HID_USB_DEVICE (USB_VENDOR_ID_APPLE , USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015 ),
547- .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
629+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY },
548630 { HID_BLUETOOTH_DEVICE (BT_VENDOR_ID_APPLE , USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015 ),
549631 .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
550632 { HID_USB_DEVICE (USB_VENDOR_ID_APPLE , USB_DEVICE_ID_APPLE_WELLSPRING_ANSI ),
@@ -650,6 +732,7 @@ static struct hid_driver apple_driver = {
650732 .id_table = apple_devices ,
651733 .report_fixup = apple_report_fixup ,
652734 .probe = apple_probe ,
735+ .remove = apple_remove ,
653736 .event = apple_event ,
654737 .input_mapping = apple_input_mapping ,
655738 .input_mapped = apple_input_mapped ,
0 commit comments