@@ -410,6 +410,18 @@ static const char * const joycon_player_led_names[] = {
410
410
LED_FUNCTION_PLAYER4 ,
411
411
};
412
412
#define JC_NUM_LEDS ARRAY_SIZE(joycon_player_led_names)
413
+ #define JC_NUM_LED_PATTERNS 8
414
+ /* Taken from https://www.nintendo.com/my/support/qa/detail/33822 */
415
+ static const enum led_brightness joycon_player_led_patterns [JC_NUM_LED_PATTERNS ][JC_NUM_LEDS ] = {
416
+ { 1 , 0 , 0 , 0 },
417
+ { 1 , 1 , 0 , 0 },
418
+ { 1 , 1 , 1 , 0 },
419
+ { 1 , 1 , 1 , 1 },
420
+ { 1 , 0 , 0 , 1 },
421
+ { 1 , 0 , 1 , 0 },
422
+ { 1 , 0 , 1 , 1 },
423
+ { 0 , 1 , 1 , 0 },
424
+ };
413
425
414
426
/* Each physical controller is associated with a joycon_ctlr struct */
415
427
struct joycon_ctlr {
@@ -699,6 +711,25 @@ static int joycon_set_player_leds(struct joycon_ctlr *ctlr, u8 flash, u8 on)
699
711
return joycon_send_subcmd (ctlr , req , 1 , HZ /4 );
700
712
}
701
713
714
+ static int joycon_set_home_led (struct joycon_ctlr * ctlr , enum led_brightness brightness )
715
+ {
716
+ struct joycon_subcmd_request * req ;
717
+ u8 buffer [sizeof (* req ) + 5 ] = { 0 };
718
+ u8 * data ;
719
+
720
+ req = (struct joycon_subcmd_request * )buffer ;
721
+ req -> subcmd_id = JC_SUBCMD_SET_HOME_LIGHT ;
722
+ data = req -> data ;
723
+ data [0 ] = 0x01 ;
724
+ data [1 ] = brightness << 4 ;
725
+ data [2 ] = brightness | (brightness << 4 );
726
+ data [3 ] = 0x11 ;
727
+ data [4 ] = 0x11 ;
728
+
729
+ hid_dbg (ctlr -> hdev , "setting home led brightness\n" );
730
+ return joycon_send_subcmd (ctlr , req , 5 , HZ /4 );
731
+ }
732
+
702
733
static int joycon_request_spi_flash_read (struct joycon_ctlr * ctlr ,
703
734
u32 start_addr , u8 size , u8 * * reply )
704
735
{
@@ -1840,6 +1871,7 @@ static int joycon_input_create(struct joycon_ctlr *ctlr)
1840
1871
return 0 ;
1841
1872
}
1842
1873
1874
+ /* Because the subcommand sets all the leds at once, the brightness argument is ignored */
1843
1875
static int joycon_player_led_brightness_set (struct led_classdev * led ,
1844
1876
enum led_brightness brightness )
1845
1877
{
@@ -1849,29 +1881,17 @@ static int joycon_player_led_brightness_set(struct led_classdev *led,
1849
1881
int val = 0 ;
1850
1882
int i ;
1851
1883
int ret ;
1852
- int num ;
1853
1884
1854
1885
ctlr = hid_get_drvdata (hdev );
1855
1886
if (!ctlr ) {
1856
1887
hid_err (hdev , "No controller data\n" );
1857
1888
return - ENODEV ;
1858
1889
}
1859
1890
1860
- /* determine which player led this is */
1861
- for (num = 0 ; num < JC_NUM_LEDS ; num ++ ) {
1862
- if (& ctlr -> leds [num ] == led )
1863
- break ;
1864
- }
1865
- if (num >= JC_NUM_LEDS )
1866
- return - EINVAL ;
1891
+ for (i = 0 ; i < JC_NUM_LEDS ; i ++ )
1892
+ val |= ctlr -> leds [i ].brightness << i ;
1867
1893
1868
1894
mutex_lock (& ctlr -> output_mutex );
1869
- for (i = 0 ; i < JC_NUM_LEDS ; i ++ ) {
1870
- if (i == num )
1871
- val |= brightness << i ;
1872
- else
1873
- val |= ctlr -> leds [i ].brightness << i ;
1874
- }
1875
1895
ret = joycon_set_player_leds (ctlr , 0 , val );
1876
1896
mutex_unlock (& ctlr -> output_mutex );
1877
1897
@@ -1884,85 +1904,80 @@ static int joycon_home_led_brightness_set(struct led_classdev *led,
1884
1904
struct device * dev = led -> dev -> parent ;
1885
1905
struct hid_device * hdev = to_hid_device (dev );
1886
1906
struct joycon_ctlr * ctlr ;
1887
- struct joycon_subcmd_request * req ;
1888
- u8 buffer [sizeof (* req ) + 5 ] = { 0 };
1889
- u8 * data ;
1890
1907
int ret ;
1891
1908
1892
1909
ctlr = hid_get_drvdata (hdev );
1893
1910
if (!ctlr ) {
1894
1911
hid_err (hdev , "No controller data\n" );
1895
1912
return - ENODEV ;
1896
1913
}
1897
-
1898
- req = (struct joycon_subcmd_request * )buffer ;
1899
- req -> subcmd_id = JC_SUBCMD_SET_HOME_LIGHT ;
1900
- data = req -> data ;
1901
- data [0 ] = 0x01 ;
1902
- data [1 ] = brightness << 4 ;
1903
- data [2 ] = brightness | (brightness << 4 );
1904
- data [3 ] = 0x11 ;
1905
- data [4 ] = 0x11 ;
1906
-
1907
- hid_dbg (hdev , "setting home led brightness\n" );
1908
1914
mutex_lock (& ctlr -> output_mutex );
1909
- ret = joycon_send_subcmd (ctlr , req , 5 , HZ / 4 );
1915
+ ret = joycon_set_home_led (ctlr , brightness );
1910
1916
mutex_unlock (& ctlr -> output_mutex );
1911
-
1912
1917
return ret ;
1913
1918
}
1914
1919
1915
- static DEFINE_MUTEX ( joycon_input_num_mutex );
1920
+ static DEFINE_SPINLOCK ( joycon_input_num_spinlock );
1916
1921
static int joycon_leds_create (struct joycon_ctlr * ctlr )
1917
1922
{
1918
1923
struct hid_device * hdev = ctlr -> hdev ;
1919
1924
struct device * dev = & hdev -> dev ;
1920
1925
const char * d_name = dev_name (dev );
1921
1926
struct led_classdev * led ;
1927
+ int led_val = 0 ;
1922
1928
char * name ;
1923
- int ret = 0 ;
1929
+ int ret ;
1924
1930
int i ;
1925
- static int input_num = 1 ;
1931
+ unsigned long flags ;
1932
+ int player_led_pattern ;
1933
+ static int input_num ;
1926
1934
1927
- /* Set the default controller player leds based on controller number */
1928
- mutex_lock (& joycon_input_num_mutex );
1929
- mutex_lock (& ctlr -> output_mutex );
1930
- ret = joycon_set_player_leds (ctlr , 0 , 0xF >> (4 - input_num ));
1931
- if (ret )
1932
- hid_warn (ctlr -> hdev , "Failed to set leds; ret=%d\n" , ret );
1933
- mutex_unlock (& ctlr -> output_mutex );
1935
+ /*
1936
+ * Set the player leds based on controller number
1937
+ * Because there is no standard concept of "player number", the pattern
1938
+ * number will simply increase by 1 every time a controller is connected.
1939
+ */
1940
+ spin_lock_irqsave (& joycon_input_num_spinlock , flags );
1941
+ player_led_pattern = input_num ++ % JC_NUM_LED_PATTERNS ;
1942
+ spin_unlock_irqrestore (& joycon_input_num_spinlock , flags );
1934
1943
1935
1944
/* configure the player LEDs */
1936
1945
for (i = 0 ; i < JC_NUM_LEDS ; i ++ ) {
1937
1946
name = devm_kasprintf (dev , GFP_KERNEL , "%s:%s:%s" ,
1938
1947
d_name ,
1939
1948
"green" ,
1940
1949
joycon_player_led_names [i ]);
1941
- if (!name ) {
1942
- mutex_unlock (& joycon_input_num_mutex );
1950
+ if (!name )
1943
1951
return - ENOMEM ;
1944
- }
1945
1952
1946
1953
led = & ctlr -> leds [i ];
1947
1954
led -> name = name ;
1948
- led -> brightness = (( i + 1 ) <= input_num ) ? 1 : 0 ;
1955
+ led -> brightness = joycon_player_led_patterns [ player_led_pattern ][ i ] ;
1949
1956
led -> max_brightness = 1 ;
1950
1957
led -> brightness_set_blocking =
1951
1958
joycon_player_led_brightness_set ;
1952
1959
led -> flags = LED_CORE_SUSPENDRESUME | LED_HW_PLUGGABLE ;
1953
1960
1961
+ led_val |= joycon_player_led_patterns [player_led_pattern ][i ] << i ;
1962
+ }
1963
+ mutex_lock (& ctlr -> output_mutex );
1964
+ ret = joycon_set_player_leds (ctlr , 0 , led_val );
1965
+ mutex_unlock (& ctlr -> output_mutex );
1966
+ if (ret ) {
1967
+ hid_warn (hdev , "Failed to set players LEDs, skipping registration; ret=%d\n" , ret );
1968
+ goto home_led ;
1969
+ }
1970
+
1971
+ for (i = 0 ; i < JC_NUM_LEDS ; i ++ ) {
1972
+ led = & ctlr -> leds [i ];
1954
1973
ret = devm_led_classdev_register (& hdev -> dev , led );
1955
1974
if (ret ) {
1956
- hid_err (hdev , "Failed registering %s LED\n" , led -> name );
1957
- mutex_unlock (& joycon_input_num_mutex );
1975
+ hid_err (hdev , "Failed to register player %d LED; ret=%d\n" , i + 1 , ret );
1958
1976
return ret ;
1959
1977
}
1960
1978
}
1961
1979
1962
- if (++ input_num > 4 )
1963
- input_num = 1 ;
1964
- mutex_unlock (& joycon_input_num_mutex );
1965
-
1980
+ home_led :
1966
1981
/* configure the home LED */
1967
1982
if (jc_type_has_right (ctlr )) {
1968
1983
name = devm_kasprintf (dev , GFP_KERNEL , "%s:%s:%s" ,
@@ -1978,16 +1993,20 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr)
1978
1993
led -> max_brightness = 0xF ;
1979
1994
led -> brightness_set_blocking = joycon_home_led_brightness_set ;
1980
1995
led -> flags = LED_CORE_SUSPENDRESUME | LED_HW_PLUGGABLE ;
1981
- ret = devm_led_classdev_register (& hdev -> dev , led );
1996
+
1997
+ /* Set the home LED to 0 as default state */
1998
+ mutex_lock (& ctlr -> output_mutex );
1999
+ ret = joycon_set_home_led (ctlr , 0 );
2000
+ mutex_unlock (& ctlr -> output_mutex );
1982
2001
if (ret ) {
1983
- hid_err (hdev , "Failed registering home led \n" );
1984
- return ret ;
2002
+ hid_warn (hdev , "Failed to set home LED, skipping registration; ret=%d \n" , ret );
2003
+ return 0 ;
1985
2004
}
1986
- /* Set the home LED to 0 as default state */
1987
- ret = joycon_home_led_brightness_set ( led , 0 );
2005
+
2006
+ ret = devm_led_classdev_register ( & hdev -> dev , led );
1988
2007
if (ret ) {
1989
- hid_warn (hdev , "Failed to set home LED default, unregistering home LED" );
1990
- devm_led_classdev_unregister ( & hdev -> dev , led ) ;
2008
+ hid_err (hdev , "Failed to register home LED; ret=%d\n" , ret );
2009
+ return ret ;
1991
2010
}
1992
2011
}
1993
2012
0 commit comments