From 955c683971090ad6afd869e3d17f6f470dff6243 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Thu, 28 May 2020 18:35:46 +0200 Subject: [PATCH] Further modularize drivers incl. probe/remove --- src/clevo_keyboard.h | 128 +++++++++++++++++++++++++++++++---- src/tuxedo_keyboard.c | 119 +++++--------------------------- src/tuxedo_keyboard_common.h | 10 +++ 3 files changed, 142 insertions(+), 115 deletions(-) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 6845649..192957c 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -70,7 +70,7 @@ #define WMI_KEYEVENT_CODE_RFKILL1 0x85 #define WMI_KEYEVENT_CODE_RFKILL2 0x86 -static const struct key_entry clevo_wmi_keymap[] = { +static struct key_entry clevo_wmi_keymap[] = { // Keyboard backlight (RGB versions) { KE_KEY, WMI_KEYEVENT_CODE_DECREASE_BACKLIGHT, { KEY_KBDILLUMDOWN } }, { KE_KEY, WMI_KEYEVENT_CODE_INCREASE_BACKLIGHT, { KEY_KBDILLUMUP } }, @@ -615,12 +615,33 @@ static void tuxedo_wmi_notify(u32 value, void *context) } } +// Sysfs attribute file permissions and method linking +static DEVICE_ATTR(state, 0644, show_state_fs, set_state_fs); +static DEVICE_ATTR(color_left, 0644, show_color_left_fs, set_color_left_fs); +static DEVICE_ATTR(color_center, 0644, show_color_center_fs, + set_color_center_fs); +static DEVICE_ATTR(color_right, 0644, show_color_right_fs, set_color_right_fs); +static DEVICE_ATTR(color_extra, 0644, show_color_extra_fs, set_color_extra_fs); +static DEVICE_ATTR(brightness, 0644, show_brightness_fs, set_brightness_fs); +static DEVICE_ATTR(mode, 0644, show_blinking_patterns_fs, set_blinking_pattern_fs); +static DEVICE_ATTR(extra, 0444, show_hasextra_fs, NULL); + static int tuxedo_wmi_probe(struct platform_device *dev) { - int status = wmi_install_notify_handler(CLEVO_EVENT_GUID, - tuxedo_wmi_notify, NULL); + int status, err; - TUXEDO_DEBUG("tuxedo_wmi_probe status: (%0#6x)", status); + if (!wmi_has_guid(CLEVO_EVENT_GUID)) { + TUXEDO_ERROR("No known WMI event notification GUID found\n"); + return -ENODEV; + } + + if (!wmi_has_guid(CLEVO_GET_GUID)) { + TUXEDO_ERROR("No known WMI control method GUID found\n"); + return -ENODEV; + } + + status = wmi_install_notify_handler(CLEVO_EVENT_GUID, tuxedo_wmi_notify, + NULL); if (unlikely(ACPI_FAILURE(status))) { TUXEDO_ERROR("Could not register WMI notify handler (%0#6x)\n", @@ -628,14 +649,98 @@ static int tuxedo_wmi_probe(struct platform_device *dev) return -EIO; } + // Enable WMI events evaluate_wmi_method_clevo(WMI_SUBMETHOD_ID_GET_AP, 0, NULL); + // Setup sysfs + if (device_create_file(&dev->dev, &dev_attr_state) != 0) { + TUXEDO_ERROR("Sysfs attribute file creation failed for state\n"); + } + + if (device_create_file + (&dev->dev, &dev_attr_color_left) != 0) { + TUXEDO_ERROR + ("Sysfs attribute file creation failed for color left\n"); + } + + if (device_create_file + (&dev->dev, &dev_attr_color_center) != 0) { + TUXEDO_ERROR + ("Sysfs attribute file creation failed for color center\n"); + } + + if (device_create_file + (&dev->dev, &dev_attr_color_right) != 0) { + TUXEDO_ERROR + ("Sysfs attribute file creation failed for color right\n"); + } + + if (set_color(REGION_EXTRA, KB_COLOR_DEFAULT) != 0) { + TUXEDO_DEBUG("Keyboard does not support EXTRA Color"); + kbd_led_state.has_extra = 0; + } else { + kbd_led_state.has_extra = 1; + if (device_create_file + (&dev->dev, + &dev_attr_color_extra) != 0) { + TUXEDO_ERROR + ("Sysfs attribute file creation failed for color extra\n"); + } + + set_color(REGION_EXTRA, param_color_extra); + } + + if (device_create_file(&dev->dev, &dev_attr_extra) != + 0) { + TUXEDO_ERROR + ("Sysfs attribute file creation failed for extra information flag\n"); + } + + if (device_create_file(&dev->dev, &dev_attr_mode) != + 0) { + TUXEDO_ERROR("Sysfs attribute file creation failed for blinking pattern\n"); + } + + if (device_create_file + (&dev->dev, &dev_attr_brightness) != 0) { + TUXEDO_ERROR + ("Sysfs attribute file creation failed for brightness\n"); + } + + // Set state variables + kbd_led_state.color.left = param_color_left; + kbd_led_state.color.center = param_color_center; + kbd_led_state.color.right = param_color_right; + kbd_led_state.color.extra = param_color_extra; + + // Write state + set_color(REGION_LEFT, param_color_left); + set_color(REGION_CENTER, param_color_center); + set_color(REGION_RIGHT, param_color_right); + + set_blinking_pattern(param_blinking_pattern); + set_brightness(param_brightness); + set_enabled(param_state); + return 0; } static int tuxedo_wmi_remove(struct platform_device *dev) { wmi_remove_notify_handler(CLEVO_EVENT_GUID); + + device_remove_file(&dev->dev, &dev_attr_state); + device_remove_file(&dev->dev, &dev_attr_color_left); + device_remove_file(&dev->dev, &dev_attr_color_center); + device_remove_file(&dev->dev, &dev_attr_color_right); + device_remove_file(&dev->dev, &dev_attr_extra); + device_remove_file(&dev->dev, &dev_attr_mode); + device_remove_file(&dev->dev, &dev_attr_brightness); + + if (kbd_led_state.has_extra == 1) { + device_remove_file(&dev->dev, &dev_attr_color_extra); + } + return 0; } @@ -673,13 +778,8 @@ static struct platform_driver platform_driver_clevo = { }, }; -// Sysfs attribute file permissions and method linking -static DEVICE_ATTR(state, 0644, show_state_fs, set_state_fs); -static DEVICE_ATTR(color_left, 0644, show_color_left_fs, set_color_left_fs); -static DEVICE_ATTR(color_center, 0644, show_color_center_fs, - set_color_center_fs); -static DEVICE_ATTR(color_right, 0644, show_color_right_fs, set_color_right_fs); -static DEVICE_ATTR(color_extra, 0644, show_color_extra_fs, set_color_extra_fs); -static DEVICE_ATTR(brightness, 0644, show_brightness_fs, set_brightness_fs); -static DEVICE_ATTR(mode, 0644, show_blinking_patterns_fs, set_blinking_pattern_fs); -static DEVICE_ATTR(extra, 0444, show_hasextra_fs, NULL); +struct tuxedo_keyboard_driver clevo_keyboard_driver = { + .platform_driver = &platform_driver_clevo, + .probe = tuxedo_wmi_probe, + .key_map = clevo_wmi_keymap, +}; diff --git a/src/tuxedo_keyboard.c b/src/tuxedo_keyboard.c index ebb761d..780778f 100644 --- a/src/tuxedo_keyboard.c +++ b/src/tuxedo_keyboard.c @@ -39,7 +39,7 @@ MODULE_VERSION("2.0.4"); MODULE_ALIAS("wmi:" CLEVO_EVENT_GUID); MODULE_ALIAS("wmi:" CLEVO_GET_GUID); -static int __init tuxedo_input_init(const struct key_entry key_map[]) +static int tuxedo_input_init(const struct key_entry key_map[]) { int err; @@ -92,100 +92,31 @@ static int __init tuxdeo_keyboard_init(void) { int err; - if (!wmi_has_guid(CLEVO_EVENT_GUID)) { - TUXEDO_ERROR("No known WMI event notification GUID found\n"); - return -ENODEV; - } - - if (!wmi_has_guid(CLEVO_GET_GUID)) { - TUXEDO_ERROR("No known WMI control method GUID found\n"); - return -ENODEV; - } - TUXEDO_INFO("Model '%s' found\n", dmi_get_system_info(DMI_PRODUCT_NAME)); + // Attempt to load each available driver + // Associated probe decides if it fits + // Driver from first successful probe is used tuxedo_platform_device = - platform_create_bundle(&platform_driver_clevo, tuxedo_wmi_probe, - NULL, 0, NULL, 0); + platform_create_bundle(clevo_keyboard_driver.platform_driver, + clevo_keyboard_driver.probe, NULL, 0, + NULL, 0); - if (unlikely(IS_ERR(tuxedo_platform_device))) { - TUXEDO_ERROR("Can not init Platform driver"); - return PTR_ERR(tuxedo_platform_device); - } - - err = tuxedo_input_init(clevo_wmi_keymap); - if (unlikely(err)) { - TUXEDO_ERROR("Could not register input device\n"); - } - - if (device_create_file(&tuxedo_platform_device->dev, &dev_attr_state) != 0) { - TUXEDO_ERROR("Sysfs attribute file creation failed for state\n"); - } - - if (device_create_file - (&tuxedo_platform_device->dev, &dev_attr_color_left) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for color left\n"); - } - - if (device_create_file - (&tuxedo_platform_device->dev, &dev_attr_color_center) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for color center\n"); - } - - if (device_create_file - (&tuxedo_platform_device->dev, &dev_attr_color_right) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for color right\n"); - } - - if (set_color(REGION_EXTRA, KB_COLOR_DEFAULT) != 0) { - TUXEDO_DEBUG("Keyboard does not support EXTRA Color"); - kbd_led_state.has_extra = 0; + if (IS_ERR(tuxedo_platform_device)) { + TUXEDO_ERROR("No matching hardware found\n"); + return -ENODEV; } else { - kbd_led_state.has_extra = 1; - if (device_create_file - (&tuxedo_platform_device->dev, - &dev_attr_color_extra) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for color extra\n"); + current_driver = &clevo_keyboard_driver; + } + + if (current_driver->key_map != NULL) { + err = tuxedo_input_init(current_driver->key_map); + if (unlikely(err)) { + TUXEDO_ERROR("Could not register input device\n"); } - - set_color(REGION_EXTRA, param_color_extra); } - if (device_create_file(&tuxedo_platform_device->dev, &dev_attr_extra) != - 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for extra information flag\n"); - } - - if (device_create_file(&tuxedo_platform_device->dev, &dev_attr_mode) != - 0) { - TUXEDO_ERROR("Sysfs attribute file creation failed for blinking pattern\n"); - } - - if (device_create_file - (&tuxedo_platform_device->dev, &dev_attr_brightness) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for brightness\n"); - } - - kbd_led_state.color.left = param_color_left; - kbd_led_state.color.center = param_color_center; - kbd_led_state.color.right = param_color_right; - kbd_led_state.color.extra = param_color_extra; - - set_color(REGION_LEFT, param_color_left); - set_color(REGION_CENTER, param_color_center); - set_color(REGION_RIGHT, param_color_right); - - set_blinking_pattern(param_blinking_pattern); - set_brightness(param_brightness); - set_enabled(param_state); - return 0; } @@ -193,23 +124,9 @@ static void __exit tuxdeo_keyboard_exit(void) { tuxedo_input_exit(); - device_remove_file(&tuxedo_platform_device->dev, &dev_attr_state); - device_remove_file(&tuxedo_platform_device->dev, &dev_attr_color_left); - device_remove_file(&tuxedo_platform_device->dev, - &dev_attr_color_center); - device_remove_file(&tuxedo_platform_device->dev, &dev_attr_color_right); - device_remove_file(&tuxedo_platform_device->dev, &dev_attr_extra); - device_remove_file(&tuxedo_platform_device->dev, &dev_attr_mode); - device_remove_file(&tuxedo_platform_device->dev, &dev_attr_brightness); - - if (kbd_led_state.has_extra == 1) { - device_remove_file(&tuxedo_platform_device->dev, - &dev_attr_color_extra); - } - platform_device_unregister(tuxedo_platform_device); - platform_driver_unregister(&platform_driver_clevo); + platform_driver_unregister(current_driver->platform_driver); TUXEDO_DEBUG("exit"); } diff --git a/src/tuxedo_keyboard_common.h b/src/tuxedo_keyboard_common.h index 2b2e3e3..ed6718b 100644 --- a/src/tuxedo_keyboard_common.h +++ b/src/tuxedo_keyboard_common.h @@ -28,9 +28,19 @@ #define TUXEDO_ERROR(fmt, ...) __TUXEDO_PR(err, fmt, ##__VA_ARGS__) #define TUXEDO_DEBUG(fmt, ...) __TUXEDO_PR(debug, "[%s:%u] " fmt, __func__, __LINE__, ##__VA_ARGS__) +struct tuxedo_keyboard_driver { + struct platform_driver *platform_driver; + int (*probe)(struct platform_device *); + struct key_entry *key_map; +}; + +// Global module devices static struct platform_device *tuxedo_platform_device; static struct input_dev *tuxedo_input_device; +// Currently chosen driver +static struct tuxedo_keyboard_driver *current_driver; + /** * Basically a copy of the existing report event but doesn't report unknown events */