8
8
#include <linux/hid.h>
9
9
#include <linux/input-event-codes.h>
10
10
#include <linux/input.h>
11
+ #include <linux/leds.h>
11
12
#include <linux/module.h>
12
13
#include <linux/spinlock.h>
13
14
#include <linux/workqueue.h>
35
36
THUNDERSTRIKE_FW_VERSION_UPDATE = 0 ,
36
37
THUNDERSTRIKE_BOARD_INFO_UPDATE ,
37
38
THUNDERSTRIKE_HAPTICS_UPDATE ,
39
+ THUNDERSTRIKE_LED_UPDATE ,
38
40
};
39
41
40
42
enum {
@@ -45,12 +47,19 @@ enum {
45
47
46
48
enum {
47
49
THUNDERSTRIKE_HOSTCMD_ID_FW_VERSION = 1 ,
50
+ THUNDERSTRIKE_HOSTCMD_ID_LED = 6 ,
48
51
THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO = 16 ,
49
52
THUNDERSTRIKE_HOSTCMD_ID_USB_INIT = 53 ,
50
53
THUNDERSTRIKE_HOSTCMD_ID_HAPTICS = 57 ,
51
54
THUNDERSTRIKE_HOSTCMD_ID_BLUETOOTH_INIT = 58 ,
52
55
};
53
56
57
+ enum thunderstrike_led_state {
58
+ THUNDERSTRIKE_LED_OFF = 1 ,
59
+ THUNDERSTRIKE_LED_ON = 8 ,
60
+ } __packed ;
61
+ static_assert (sizeof (enum thunderstrike_led_state ) == 1 );
62
+
54
63
struct thunderstrike_hostcmd_board_info {
55
64
__le16 revision ;
56
65
__le16 serial [7 ];
@@ -70,6 +79,7 @@ struct thunderstrike_hostcmd_resp_report {
70
79
struct thunderstrike_hostcmd_board_info board_info ;
71
80
struct thunderstrike_hostcmd_haptics motors ;
72
81
__le16 fw_version ;
82
+ enum thunderstrike_led_state led_state ;
73
83
u8 payload [30 ];
74
84
};
75
85
} __packed ;
@@ -81,10 +91,16 @@ struct thunderstrike_hostcmd_req_report {
81
91
u8 cmd_id ;
82
92
u8 reserved_at_10 ;
83
93
84
- struct {
85
- u8 update ;
86
- struct thunderstrike_hostcmd_haptics motors ;
87
- } haptics ;
94
+ union {
95
+ struct {
96
+ u8 update ;
97
+ enum thunderstrike_led_state state ;
98
+ } led ;
99
+ struct {
100
+ u8 update ;
101
+ struct thunderstrike_hostcmd_haptics motors ;
102
+ } haptics ;
103
+ };
88
104
u8 reserved_at_30 [27 ];
89
105
} __packed ;
90
106
static_assert (sizeof (struct thunderstrike_hostcmd_req_report ) ==
@@ -108,12 +124,15 @@ struct thunderstrike {
108
124
109
125
/* Sub-devices */
110
126
struct input_dev * haptics_dev ;
127
+ struct led_classdev led_dev ;
111
128
112
129
/* Resources */
113
130
void * req_report_dmabuf ;
114
131
unsigned long update_flags ;
115
132
struct thunderstrike_hostcmd_haptics haptics_val ;
116
133
spinlock_t haptics_update_lock ;
134
+ u8 led_state : 1 ;
135
+ enum thunderstrike_led_state led_value ;
117
136
struct work_struct hostcmd_req_work ;
118
137
};
119
138
@@ -221,6 +240,13 @@ static void thunderstrike_hostcmd_req_work_handler(struct work_struct *work)
221
240
thunderstrike_send_hostcmd_request (ts );
222
241
}
223
242
243
+ if (test_and_clear_bit (THUNDERSTRIKE_LED_UPDATE , & ts -> update_flags )) {
244
+ thunderstrike_hostcmd_req_report_init (report , THUNDERSTRIKE_HOSTCMD_ID_LED );
245
+ report -> led .update = 1 ;
246
+ report -> led .state = ts -> led_value ;
247
+ thunderstrike_send_hostcmd_request (ts );
248
+ }
249
+
224
250
if (test_and_clear_bit (THUNDERSTRIKE_BOARD_INFO_UPDATE , & ts -> update_flags )) {
225
251
thunderstrike_hostcmd_req_report_init (
226
252
report , THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO );
@@ -292,6 +318,40 @@ static int thunderstrike_play_effect(struct input_dev *idev, void *data,
292
318
return thunderstrike_update_haptics (ts , & motors );
293
319
}
294
320
321
+ static enum led_brightness
322
+ thunderstrike_led_get_brightness (struct led_classdev * led )
323
+ {
324
+ struct hid_device * hdev = to_hid_device (led -> dev -> parent );
325
+ struct shield_device * shield_dev = hid_get_drvdata (hdev );
326
+ struct thunderstrike * ts ;
327
+
328
+ ts = container_of (shield_dev , struct thunderstrike , base );
329
+
330
+ return ts -> led_state ;
331
+ }
332
+
333
+ static void thunderstrike_led_set_brightness (struct led_classdev * led ,
334
+ enum led_brightness value )
335
+ {
336
+ struct hid_device * hdev = to_hid_device (led -> dev -> parent );
337
+ struct shield_device * shield_dev = hid_get_drvdata (hdev );
338
+ struct thunderstrike * ts ;
339
+
340
+ ts = container_of (shield_dev , struct thunderstrike , base );
341
+
342
+ switch (value ) {
343
+ case LED_OFF :
344
+ ts -> led_value = THUNDERSTRIKE_LED_OFF ;
345
+ break ;
346
+ default :
347
+ ts -> led_value = THUNDERSTRIKE_LED_ON ;
348
+ break ;
349
+ }
350
+
351
+ set_bit (THUNDERSTRIKE_LED_UPDATE , & ts -> update_flags );
352
+ schedule_work (& ts -> hostcmd_req_work );
353
+ }
354
+
295
355
static void
296
356
thunderstrike_parse_fw_version_payload (struct shield_device * shield_dev ,
297
357
__le16 fw_version )
@@ -338,6 +398,24 @@ thunderstrike_parse_haptics_payload(struct shield_device *shield_dev,
338
398
haptics -> motor_left , haptics -> motor_right );
339
399
}
340
400
401
+ static void
402
+ thunderstrike_parse_led_payload (struct shield_device * shield_dev ,
403
+ enum thunderstrike_led_state led_state )
404
+ {
405
+ struct thunderstrike * ts = container_of (shield_dev , struct thunderstrike , base );
406
+
407
+ switch (led_state ) {
408
+ case THUNDERSTRIKE_LED_OFF :
409
+ ts -> led_state = 0 ;
410
+ break ;
411
+ case THUNDERSTRIKE_LED_ON :
412
+ ts -> led_state = 1 ;
413
+ break ;
414
+ }
415
+
416
+ hid_dbg (shield_dev -> hdev , "Thunderstrike led HOSTCMD response, 0x%02X\n" , led_state );
417
+ }
418
+
341
419
static int thunderstrike_parse_report (struct shield_device * shield_dev ,
342
420
struct hid_report * report , u8 * data ,
343
421
int size )
@@ -364,6 +442,9 @@ static int thunderstrike_parse_report(struct shield_device *shield_dev,
364
442
thunderstrike_parse_fw_version_payload (
365
443
shield_dev , hostcmd_resp_report -> fw_version );
366
444
break ;
445
+ case THUNDERSTRIKE_HOSTCMD_ID_LED :
446
+ thunderstrike_parse_led_payload (shield_dev , hostcmd_resp_report -> led_state );
447
+ break ;
367
448
case THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO :
368
449
thunderstrike_parse_board_info_payload (
369
450
shield_dev , & hostcmd_resp_report -> board_info );
@@ -395,10 +476,24 @@ static int thunderstrike_parse_report(struct shield_device *shield_dev,
395
476
return 0 ;
396
477
}
397
478
479
+ static inline int thunderstrike_led_create (struct thunderstrike * ts )
480
+ {
481
+ struct led_classdev * led = & ts -> led_dev ;
482
+
483
+ led -> name = "thunderstrike:blue:led" ;
484
+ led -> max_brightness = 1 ;
485
+ led -> flags = LED_CORE_SUSPENDRESUME ;
486
+ led -> brightness_get = & thunderstrike_led_get_brightness ;
487
+ led -> brightness_set = & thunderstrike_led_set_brightness ;
488
+
489
+ return led_classdev_register (& ts -> base .hdev -> dev , led );
490
+ }
491
+
398
492
static struct shield_device * thunderstrike_create (struct hid_device * hdev )
399
493
{
400
494
struct shield_device * shield_dev ;
401
495
struct thunderstrike * ts ;
496
+ int ret ;
402
497
403
498
ts = devm_kzalloc (& hdev -> dev , sizeof (* ts ), GFP_KERNEL );
404
499
if (!ts )
@@ -418,12 +513,22 @@ static struct shield_device *thunderstrike_create(struct hid_device *hdev)
418
513
419
514
hid_set_drvdata (hdev , shield_dev );
420
515
516
+ ret = thunderstrike_led_create (ts );
517
+ if (ret ) {
518
+ hid_err (hdev , "Failed to create Thunderstrike LED instance\n" );
519
+ return ERR_PTR (ret );
520
+ }
521
+
421
522
ts -> haptics_dev = shield_haptics_create (shield_dev , thunderstrike_play_effect );
422
523
if (IS_ERR (ts -> haptics_dev ))
423
- return ERR_CAST ( ts -> haptics_dev ) ;
524
+ goto err ;
424
525
425
526
hid_info (hdev , "Registered Thunderstrike controller\n" );
426
527
return shield_dev ;
528
+
529
+ err :
530
+ led_classdev_unregister (& ts -> led_dev );
531
+ return ERR_CAST (ts -> haptics_dev );
427
532
}
428
533
429
534
static int android_input_mapping (struct hid_device * hdev , struct hid_input * hi ,
@@ -599,6 +704,7 @@ static void shield_remove(struct hid_device *hdev)
599
704
ts = container_of (dev , struct thunderstrike , base );
600
705
601
706
hid_hw_close (hdev );
707
+ led_classdev_unregister (& ts -> led_dev );
602
708
if (ts -> haptics_dev )
603
709
input_unregister_device (ts -> haptics_dev );
604
710
cancel_work_sync (& ts -> hostcmd_req_work );
0 commit comments