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 5b30171..aab0f90 100644 --- a/10_lightning_node_pro_led/lightning_node_pro_led.c +++ b/10_lightning_node_pro_led/lightning_node_pro_led.c @@ -1,11 +1,12 @@ #include #include #include +#include #define USB_VENDOR_ID_CORSAIR 0x1b1c #define USB_DEVICE_ID_LIGHTNING_NODE_PRO 0x0c0b -#define NUMBER_OF_ZONES_PER_LL120_FAN 16 +#define NUMBER_OF_LEDS_PER_LL120_FAN 16 #define LIGHTNODE_PRO_MAX_FAN 6 #define MSG_SIZE 64 @@ -19,18 +20,155 @@ module_param(number_of_fan, short, 0000); MODULE_PARM_DESC(number_of_fan, "Number of LL120 FAN connected to the lightning node pro"); -struct lightning_node_pro_led_data { - struct hid_device *hdev; - struct mutex lock; +enum LNP_LED_TYPE { + LNP_LED_LL120, }; -static int lightning_node_pro_led_probe(struct hid_device *hdev, - const struct hid_device_id *id) +struct lnp_rgb_led { + struct led_classdev_mc cdev; + uint8_t red; + uint8_t green; + uint8_t blue; +}; + +struct lnp_fan { + int fan_index; + int rgb_leds_count; + struct lnp_rgb_led *rgb_leds_data; +}; + +struct lnp_device { + struct hid_device *hdev; + struct mutex lock; + enum LNP_LED_TYPE type; + int fans_count; + void *fans_data; +}; + +static inline int lnp_register_rgb_led(struct rgb_led *rgb_led_data, + int fan_number) +{ +} + +static inline int lnp_unregister_rgb_led(struct rgb_led *rgb_led_data, + int fan_number) +{ +} + +static inline int lnp_register_fan(struct lnp_fan *fan_data, int rgb_leds_count) +{ + int ret, led_index; + + 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; + } + + 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; + + ret = lnp_register_rgb_led(rgb_led_data, fan_data->fan_index); + if (ret) + goto fail_register_leds; + } + + 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) +{ + int ret, led_index; + 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); + } +} + +static inline int lnp_register_fans(struct lnp_device *data, int rgb_leds_count) +{ + int ret, fan_index, led_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; + fan_data->fan_index = fan_index; + + ret = lnp_register_fan(fan_data, rgb_leds_count); + if (ret) + goto fail; + } + + 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) { pr_info("Détection USB pour Lightning Node Pro\n"); int ret; - struct lightning_node_pro_led_data *data; + struct lnp_device *data; data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) @@ -38,40 +176,66 @@ static int lightning_node_pro_led_probe(struct hid_device *hdev, data->hdev = hdev; mutex_init(&data->lock); + + data->type = LNP_LED_LL120; // Only support LL120 for now + + switch (data->type) { + case LNP_LED_LL120: + ret = lnp_ll120_register(data); + break; + default: + ret = -ENOSYS; + pr_err("Fan type invalid\n"); + break; + } + + if (ret) + goto free_data; + hid_set_drvdata(hdev, data); return 0; -free_ldata: +free_data: kfree(data); return ret; } -static void lightning_node_pro_led_remove(struct hid_device *hdev) +static void lnp_remove(struct hid_device *hdev) { - struct lightning_node_pro_led_data *data = hid_get_drvdata(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 lightning_node_pro_led_table[] = { +static struct hid_device_id lnp_table[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_LIGHTNING_NODE_PRO) }, {} /* Entrée de terminaison */ }; -MODULE_DEVICE_TABLE(hid, lightning_node_pro_led_table); +MODULE_DEVICE_TABLE(hid, lnp_table); -static struct hid_driver lightning_node_pro_led_driver = { +static struct hid_driver lnp_driver = { .name = "lightning-node-pro", - .id_table = lightning_node_pro_led_table, - .probe = lightning_node_pro_led_probe, - .remove = lightning_node_pro_led_remove, + .id_table = lnp_table, + .probe = lnp_probe, + .remove = lnp_remove, }; -module_hid_driver(lightning_node_pro_led_driver); +module_hid_driver(lnp_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Florian RICHER "); -MODULE_DESCRIPTION("Un module noyau pour utiliser le Lightning Node Pro LED"); +MODULE_DESCRIPTION("Un module noyau pour utiliser le Lightning Node Pro"); MODULE_VERSION("1.0"); \ No newline at end of file