From c780a8e8578f82c33e72ebc165dcd008ba2b7816 Mon Sep 17 00:00:00 2001 From: Florian RICHER Date: Sun, 9 Mar 2025 19:34:00 +0100 Subject: [PATCH] Use device linked allocator instead and led registering --- .../lightning_node_pro_led.c | 211 ++++++++---------- 1 file changed, 88 insertions(+), 123 deletions(-) diff --git a/10_lightning_node_pro_led/lightning_node_pro_led.c b/10_lightning_node_pro_led/lightning_node_pro_led.c index aab0f90..cf6e999 100644 --- a/10_lightning_node_pro_led/lightning_node_pro_led.c +++ b/10_lightning_node_pro_led/lightning_node_pro_led.c @@ -26,6 +26,7 @@ enum LNP_LED_TYPE { struct lnp_rgb_led { struct led_classdev_mc cdev; + int led_index; uint8_t red; uint8_t green; uint8_t blue; @@ -45,122 +46,101 @@ struct lnp_device { void *fans_data; }; -static inline int lnp_register_rgb_led(struct rgb_led *rgb_led_data, - int fan_number) +static inline int lnp_register_rgb_led(struct lnp_device *lnp_dev, + struct lnp_fan *fan_data, + struct lnp_rgb_led *rgb_led_data) { -} + struct hid_device *hdev = lnp_dev->hdev; + struct mc_subled *mc_leds_info; + struct led_classdev *led_cdev; + int ret; -static inline int lnp_unregister_rgb_led(struct rgb_led *rgb_led_data, - int fan_number) -{ -} + mc_leds_info = devm_kmalloc_array(&hdev->dev, 3, sizeof(*mc_leds_info), + GFP_KERNEL); -static inline int lnp_register_fan(struct lnp_fan *fan_data, int rgb_leds_count) -{ - int ret, led_index; + if (!mc_leds_info) + return -ENOMEM; - fan_data->rgb_leds_data = kzalloc( - sizeof(struct lnp_rgb_led) * rgb_leds_count, GFP_KERNEL); - if (!fan_data->rgb_leds_data) { - ret = -ENOMEM; - goto fail_alloc_data; - } + mc_leds_info[0].color_index = LED_COLOR_ID_RED; + mc_leds_info[1].color_index = LED_COLOR_ID_GREEN; + mc_leds_info[2].color_index = LED_COLOR_ID_BLUE; - for (led_index = 0; led_index < fan_data->rgb_leds_count; led_index++) { - struct lnp_rgb_led *rgb_led_data = - fan_data->rgb_leds_data + led_index; + rgb_led_data->cdev.subled_info = mc_leds_info; + rgb_led_data->cdev.num_colors = 3; - ret = lnp_register_rgb_led(rgb_led_data, fan_data->fan_index); - if (ret) - goto fail_register_leds; + led_cdev = &rgb_led_data->cdev.led_cdev; + led_cdev->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, + "ll120:rgb:fan-%d-led-%d", + fan_data->fan_index, + rgb_led_data->led_index); + if (!led_cdev->name) + return -ENOMEM; + + led_cdev->brightness = 0; + led_cdev->max_brightness = 255; + + ret = devm_led_classdev_multicolor_register(&hdev->dev, + &rgb_led_data->cdev); + if (ret < 0) { + hid_err(hdev, "Cannot register multicolor LED device\n"); + return ret; } return 0; - -fail_register_leds: - for (led_index--; led_index >= 0; led_index--) { - struct rgb_led *rgb_led_data = - fan_data->rgb_leds_data + led_index; - lnp_unregister_rgb_led(rgb_led_data, fan_data->fan_index); - } - -fail_alloc_data: - kfree(fan_data->rgb_leds_data); - - return ret; } -static inline void lnp_unregister_fan(struct lnp_fan *fan_data) +static inline int led_number_for_device(struct lnp_device *lnp_dev) +{ + switch (lnp_dev->type) { + case LNP_LED_LL120: + return NUMBER_OF_LEDS_PER_LL120_FAN; + default: + return 0; + } +} + +static inline int lnp_register_fan(struct lnp_device *lnp_dev, + struct lnp_fan *fan_data) { int ret, led_index; + + fan_data->rgb_leds_count = led_number_for_device(lnp_dev); + fan_data->rgb_leds_data = devm_kmalloc_array(&lnp_dev->hdev->dev, + fan_data->rgb_leds_count, + sizeof(struct lnp_rgb_led), + GFP_KERNEL | __GFP_ZERO); + if (!fan_data->rgb_leds_data) { + return -ENOMEM; + } + for (led_index = 0; led_index < fan_data->rgb_leds_count; led_index++) { struct lnp_rgb_led *rgb_led_data = fan_data->rgb_leds_data + led_index; - lnp_unregister_rgb_led(rgb_led_data, fan_data->fan_index); + rgb_led_data->led_index = led_index; + + ret = lnp_register_rgb_led(lnp_dev, fan_data, rgb_led_data); + if (ret) + return ret; } + + return 0; } -static inline int lnp_register_fans(struct lnp_device *data, int rgb_leds_count) +static inline int lnp_register_fans(struct lnp_device *lnp_dev) { - int ret, fan_index, led_index; - struct lnp_fan *fans_data = data->fans_data; + int ret, fan_index; + struct lnp_fan *fans_data = lnp_dev->fans_data; - for (fan_index = 0; fan_index < data->fans_count; fan_index++) { + for (fan_index = 0; fan_index < lnp_dev->fans_count; fan_index++) { struct lnp_fan *fan_data = fans_data + fan_index; fan_data->fan_index = fan_index; - ret = lnp_register_fan(fan_data, rgb_leds_count); + ret = lnp_register_fan(lnp_dev, fan_data); if (ret) - goto fail; + return ret; } return 0; - -fail: - for (fan_index--; fan_index >= 0; fan_index--) { - struct ll120_fan *fan_data = fans_data + fan_index; - lnp_unregister_fan(fan_data); - } - return ret; -} - -static inline void lnp_unregister_fans(struct lnp_device *data) -{ - int fan_index; - struct lnp_fan *fans_data = data->fans_data; - - for (fan_index = 0; fan_index < data->fans_count; fan_index++) { - struct lnp_fan *fan_data = fans_data + fan_index; - lnp_unregister_fan(fan_data); - } -} - -static inline int lnp_ll120_register(struct lnp_device *data) -{ - data->fans_count = number_of_fan; - data->fans_data = - kzalloc(sizeof(struct lnp_fan) * data->fans_count, GFP_KERNEL); - - if (!data->fans_data) - return -ENOMEM; - - int ret; - - ret = lnp_register_fans(data, NUMBER_OF_LEDS_PER_LL120_FAN); - if (ret) - goto fans_data_free; - - return 0; - -fans_data_free: - kfree(data->fans_data); - - return ret; -} - -static inline void lnp_ll120_unregister(struct lnp_device *data) -{ - lnp_unregister_fans(data); } static int lnp_probe(struct hid_device *hdev, const struct hid_device_id *id) @@ -168,55 +148,40 @@ static int lnp_probe(struct hid_device *hdev, const struct hid_device_id *id) pr_info("Détection USB pour Lightning Node Pro\n"); int ret; - struct lnp_device *data; + struct lnp_device *lnp_dev; - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) + lnp_dev = devm_kzalloc(&hdev->dev, sizeof(*lnp_dev), GFP_KERNEL); + if (!lnp_dev) return -ENOMEM; - data->hdev = hdev; - mutex_init(&data->lock); + lnp_dev->hdev = hdev; + mutex_init(&lnp_dev->lock); - data->type = LNP_LED_LL120; // Only support LL120 for now + lnp_dev->type = LNP_LED_LL120; // Only support LL120 for now + lnp_dev->fans_count = number_of_fan; - switch (data->type) { - case LNP_LED_LL120: - ret = lnp_ll120_register(data); - break; - default: - ret = -ENOSYS; - pr_err("Fan type invalid\n"); - break; + lnp_dev->fans_data = devm_kmalloc_array(&lnp_dev->hdev->dev, + lnp_dev->fans_count, + sizeof(struct lnp_fan), + GFP_KERNEL | __GFP_ZERO); + + if (!lnp_dev->fans_data) + return -ENOMEM; + + ret = lnp_register_fans(lnp_dev); + if (ret) { + hid_err(lnp_dev->hdev, "Failed to register device\n"); + return ret; } - if (ret) - goto free_data; - - hid_set_drvdata(hdev, data); + hid_set_drvdata(hdev, lnp_dev); return 0; - -free_data: - kfree(data); - - return ret; } static void lnp_remove(struct hid_device *hdev) { - struct lnp_device *data = hid_get_drvdata(hdev); - - switch (data->type) { - case LNP_LED_LL120: - lnp_ll120_unregister(data); - break; - default: - pr_err("Fan type invalid\n"); - break; - } - pr_info("Retrait USB pour Lightning Node Pro\n"); - kfree(data); } static struct hid_device_id lnp_table[] = {