Skip to content

Commit

Permalink
HID: nintendo: add home led support
Browse files Browse the repository at this point in the history
This patch adds the ability to set the intensity level of the home
button's LED.

Signed-off-by: Daniel J. Ogorchock <djogorchock@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
  • Loading branch information
Daniel J. Ogorchock authored and Jiri Kosina committed Oct 27, 2021
1 parent 08ebba5 commit 697e5c7
Showing 1 changed file with 68 additions and 4 deletions.
72 changes: 68 additions & 4 deletions drivers/hid/hid-nintendo.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ static const char * const joycon_player_led_names[] = {
struct joycon_ctlr {
struct hid_device *hdev;
struct input_dev *input;
struct led_classdev leds[JC_NUM_LEDS];
struct led_classdev leds[JC_NUM_LEDS]; /* player leds */
struct led_classdev home_led;
enum joycon_ctlr_state ctlr_state;
spinlock_t lock;

Expand Down Expand Up @@ -733,8 +734,42 @@ static int joycon_player_led_brightness_set(struct led_classdev *led,
return ret;
}

static int joycon_home_led_brightness_set(struct led_classdev *led,
enum led_brightness brightness)
{
struct device *dev = led->dev->parent;
struct hid_device *hdev = to_hid_device(dev);
struct joycon_ctlr *ctlr;
struct joycon_subcmd_request *req;
u8 buffer[sizeof(*req) + 5] = { 0 };
u8 *data;
int ret;

ctlr = hid_get_drvdata(hdev);
if (!ctlr) {
hid_err(hdev, "No controller data\n");
return -ENODEV;
}

req = (struct joycon_subcmd_request *)buffer;
req->subcmd_id = JC_SUBCMD_SET_HOME_LIGHT;
data = req->data;
data[0] = 0x01;
data[1] = brightness << 4;
data[2] = brightness | (brightness << 4);
data[3] = 0x11;
data[4] = 0x11;

hid_dbg(hdev, "setting home led brightness\n");
mutex_lock(&ctlr->output_mutex);
ret = joycon_send_subcmd(ctlr, req, 5);
mutex_unlock(&ctlr->output_mutex);

return ret;
}

static DEFINE_MUTEX(joycon_input_num_mutex);
static int joycon_player_leds_create(struct joycon_ctlr *ctlr)
static int joycon_leds_create(struct joycon_ctlr *ctlr)
{
struct hid_device *hdev = ctlr->hdev;
struct device *dev = &hdev->dev;
Expand Down Expand Up @@ -773,14 +808,43 @@ static int joycon_player_leds_create(struct joycon_ctlr *ctlr)
ret = devm_led_classdev_register(&hdev->dev, led);
if (ret) {
hid_err(hdev, "Failed registering %s LED\n", led->name);
break;
return ret;
}
}

if (++input_num > 4)
input_num = 1;
mutex_unlock(&joycon_input_num_mutex);

/* configure the home LED */
if (ctlr->hdev->product != USB_DEVICE_ID_NINTENDO_JOYCONL) {
name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s:%s",
d_name,
"blue",
LED_FUNCTION_PLAYER5);
if (!name)
return -ENOMEM;

led = &ctlr->home_led;
led->name = name;
led->brightness = 0;
led->max_brightness = 0xF;
led->brightness_set_blocking = joycon_home_led_brightness_set;
led->flags = LED_CORE_SUSPENDRESUME | LED_HW_PLUGGABLE;
ret = devm_led_classdev_register(&hdev->dev, led);
if (ret) {
hid_err(hdev, "Failed registering home led\n");
return ret;
}
/* Set the home LED to 0 as default state */
ret = joycon_home_led_brightness_set(led, 0);
if (ret) {
hid_err(hdev, "Failed to set home LED dflt; ret=%d\n",
ret);
return ret;
}
}

return 0;
}

Expand Down Expand Up @@ -1027,7 +1091,7 @@ static int nintendo_hid_probe(struct hid_device *hdev,
mutex_unlock(&ctlr->output_mutex);

/* Initialize the leds */
ret = joycon_player_leds_create(ctlr);
ret = joycon_leds_create(ctlr);
if (ret) {
hid_err(hdev, "Failed to create leds; ret=%d\n", ret);
goto err_close;
Expand Down

0 comments on commit 697e5c7

Please sign in to comment.