Skip to content

Commit 294a828

Browse files
DanielOgorchockJiri Kosina
authored andcommitted
HID: nintendo: add support for charging grip
This patch adds support for the joy-con charging grip. The peripheral essentially behaves the same as a pro controller, but with two joy-cons attached to the grip. However the grip exposes the two joy-cons as separate hid devices, so extra handling is required. The joy-con is queried to check if it is a right or left joy-con (since the product ID is identical between left/right when using the grip). Since controller model detection is now more complicated, the various checks for hid product values have been replaced with helper macros to reduce code duplication. Signed-off-by: Daniel J. Ogorchock <djogorchock@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1 parent 1425247 commit 294a828

2 files changed

Lines changed: 55 additions & 13 deletions

File tree

drivers/hid/hid-ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,7 @@
920920
#define USB_DEVICE_ID_NINTENDO_JOYCONL 0x2006
921921
#define USB_DEVICE_ID_NINTENDO_JOYCONR 0x2007
922922
#define USB_DEVICE_ID_NINTENDO_PROCON 0x2009
923+
#define USB_DEVICE_ID_NINTENDO_CHRGGRIP 0x200E
923924

924925
#define USB_VENDOR_ID_NOVATEK 0x0603
925926
#define USB_DEVICE_ID_NOVATEK_PCT 0x0600

drivers/hid/hid-nintendo.c

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,13 @@ enum joycon_ctlr_state {
233233
JOYCON_CTLR_STATE_REMOVED,
234234
};
235235

236+
/* Controller type received as part of device info */
237+
enum joycon_ctlr_type {
238+
JOYCON_CTLR_TYPE_JCL = 0x01,
239+
JOYCON_CTLR_TYPE_JCR = 0x02,
240+
JOYCON_CTLR_TYPE_PRO = 0x03,
241+
};
242+
236243
struct joycon_stick_cal {
237244
s32 max;
238245
s32 min;
@@ -328,6 +335,7 @@ struct joycon_ctlr {
328335
spinlock_t lock;
329336
u8 mac_addr[6];
330337
char *mac_addr_str;
338+
enum joycon_ctlr_type ctlr_type;
331339

332340
/* The following members are used for synchronous sends/receives */
333341
enum joycon_msg_type msg_type;
@@ -366,6 +374,26 @@ struct joycon_ctlr {
366374
u16 rumble_rh_freq;
367375
};
368376

377+
/* Helper macros for checking controller type */
378+
#define jc_type_is_joycon(ctlr) \
379+
(ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_JOYCONL || \
380+
ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_JOYCONR || \
381+
ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_CHRGGRIP)
382+
#define jc_type_is_procon(ctlr) \
383+
(ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_PROCON)
384+
#define jc_type_is_chrggrip(ctlr) \
385+
(ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_CHRGGRIP)
386+
387+
/* Does this controller have inputs associated with left joycon? */
388+
#define jc_type_has_left(ctlr) \
389+
(ctlr->ctlr_type == JOYCON_CTLR_TYPE_JCL || \
390+
ctlr->ctlr_type == JOYCON_CTLR_TYPE_PRO)
391+
392+
/* Does this controller have inputs associated with right joycon? */
393+
#define jc_type_has_right(ctlr) \
394+
(ctlr->ctlr_type == JOYCON_CTLR_TYPE_JCR || \
395+
ctlr->ctlr_type == JOYCON_CTLR_TYPE_PRO)
396+
369397
static int __joycon_hid_send(struct hid_device *hdev, u8 *data, size_t len)
370398
{
371399
u8 *buf;
@@ -662,7 +690,6 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
662690
unsigned long flags;
663691
u8 tmp;
664692
u32 btns;
665-
u32 id = ctlr->hdev->product;
666693
unsigned long msecs = jiffies_to_msecs(jiffies);
667694

668695
spin_lock_irqsave(&ctlr->lock, flags);
@@ -701,7 +728,7 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
701728
/* Parse the buttons and sticks */
702729
btns = hid_field_extract(ctlr->hdev, rep->button_status, 0, 24);
703730

704-
if (id != USB_DEVICE_ID_NINTENDO_JOYCONR) {
731+
if (jc_type_has_left(ctlr)) {
705732
u16 raw_x;
706733
u16 raw_y;
707734
s32 x;
@@ -725,7 +752,7 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
725752
input_report_key(dev, BTN_THUMBL, btns & JC_BTN_LSTICK);
726753
input_report_key(dev, BTN_Z, btns & JC_BTN_CAP);
727754

728-
if (id != USB_DEVICE_ID_NINTENDO_PROCON) {
755+
if (jc_type_is_joycon(ctlr)) {
729756
/* Report the S buttons as the non-existent triggers */
730757
input_report_key(dev, BTN_TR, btns & JC_BTN_SL_L);
731758
input_report_key(dev, BTN_TR2, btns & JC_BTN_SR_L);
@@ -757,7 +784,7 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
757784
input_report_abs(dev, ABS_HAT0Y, haty);
758785
}
759786
}
760-
if (id != USB_DEVICE_ID_NINTENDO_JOYCONL) {
787+
if (jc_type_has_right(ctlr)) {
761788
u16 raw_x;
762789
u16 raw_y;
763790
s32 x;
@@ -777,7 +804,7 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
777804
/* report buttons */
778805
input_report_key(dev, BTN_TR, btns & JC_BTN_R);
779806
input_report_key(dev, BTN_TR2, btns & JC_BTN_ZR);
780-
if (id != USB_DEVICE_ID_NINTENDO_PROCON) {
807+
if (jc_type_is_joycon(ctlr)) {
781808
/* Report the S buttons as the non-existent triggers */
782809
input_report_key(dev, BTN_TL, btns & JC_BTN_SL_R);
783810
input_report_key(dev, BTN_TL2, btns & JC_BTN_SR_R);
@@ -996,6 +1023,12 @@ static int joycon_input_create(struct joycon_ctlr *ctlr)
9961023
case USB_DEVICE_ID_NINTENDO_PROCON:
9971024
name = "Nintendo Switch Pro Controller";
9981025
break;
1026+
case USB_DEVICE_ID_NINTENDO_CHRGGRIP:
1027+
if (jc_type_has_left(ctlr))
1028+
name = "Nintendo Switch Left Joy-Con (Grip)";
1029+
else
1030+
name = "Nintendo Switch Right Joy-Con (Grip)";
1031+
break;
9991032
case USB_DEVICE_ID_NINTENDO_JOYCONL:
10001033
name = "Nintendo Switch Left Joy-Con";
10011034
break;
@@ -1018,9 +1051,8 @@ static int joycon_input_create(struct joycon_ctlr *ctlr)
10181051
ctlr->input->name = name;
10191052
input_set_drvdata(ctlr->input, ctlr);
10201053

1021-
10221054
/* set up sticks and buttons */
1023-
if (hdev->product != USB_DEVICE_ID_NINTENDO_JOYCONR) {
1055+
if (jc_type_has_left(ctlr)) {
10241056
input_set_abs_params(ctlr->input, ABS_X,
10251057
-JC_MAX_STICK_MAG, JC_MAX_STICK_MAG,
10261058
JC_STICK_FUZZ, JC_STICK_FLAT);
@@ -1046,7 +1078,7 @@ static int joycon_input_create(struct joycon_ctlr *ctlr)
10461078
JC_DPAD_FUZZ, JC_DPAD_FLAT);
10471079
}
10481080
}
1049-
if (hdev->product != USB_DEVICE_ID_NINTENDO_JOYCONL) {
1081+
if (jc_type_has_right(ctlr)) {
10501082
input_set_abs_params(ctlr->input, ABS_RX,
10511083
-JC_MAX_STICK_MAG, JC_MAX_STICK_MAG,
10521084
JC_STICK_FUZZ, JC_STICK_FLAT);
@@ -1209,7 +1241,7 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr)
12091241
mutex_unlock(&joycon_input_num_mutex);
12101242

12111243
/* configure the home LED */
1212-
if (ctlr->hdev->product != USB_DEVICE_ID_NINTENDO_JOYCONL) {
1244+
if (jc_type_has_right(ctlr)) {
12131245
name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s:%s",
12141246
d_name,
12151247
"blue",
@@ -1325,7 +1357,7 @@ static int joycon_power_supply_create(struct joycon_ctlr *ctlr)
13251357
return power_supply_powers(ctlr->battery, &hdev->dev);
13261358
}
13271359

1328-
static int joycon_read_mac(struct joycon_ctlr *ctlr)
1360+
static int joycon_read_info(struct joycon_ctlr *ctlr)
13291361
{
13301362
int ret;
13311363
int i;
@@ -1357,6 +1389,9 @@ static int joycon_read_mac(struct joycon_ctlr *ctlr)
13571389
return -ENOMEM;
13581390
hid_info(ctlr->hdev, "controller MAC = %s\n", ctlr->mac_addr_str);
13591391

1392+
/* Retrieve the type so we can distinguish for charging grip */
1393+
ctlr->ctlr_type = report->reply.data[2];
1394+
13601395
return 0;
13611396
}
13621397

@@ -1490,7 +1525,7 @@ static int nintendo_hid_probe(struct hid_device *hdev,
14901525
/* Initialize the controller */
14911526
mutex_lock(&ctlr->output_mutex);
14921527
/* if handshake command fails, assume ble pro controller */
1493-
if (hdev->product == USB_DEVICE_ID_NINTENDO_PROCON &&
1528+
if ((jc_type_is_procon(ctlr) || jc_type_is_chrggrip(ctlr)) &&
14941529
!joycon_send_usb(ctlr, JC_USB_CMD_HANDSHAKE, HZ)) {
14951530
hid_dbg(hdev, "detected USB controller\n");
14961531
/* set baudrate for improved latency */
@@ -1510,6 +1545,10 @@ static int nintendo_hid_probe(struct hid_device *hdev,
15101545
* This doesn't send a response, so ignore the timeout.
15111546
*/
15121547
joycon_send_usb(ctlr, JC_USB_CMD_NO_TIMEOUT, HZ/10);
1548+
} else if (jc_type_is_chrggrip(ctlr)) {
1549+
hid_err(hdev, "Failed charging grip handshake\n");
1550+
ret = -ETIMEDOUT;
1551+
goto err_mutex;
15131552
}
15141553

15151554
/* get controller calibration data, and parse it */
@@ -1536,9 +1575,9 @@ static int nintendo_hid_probe(struct hid_device *hdev,
15361575
goto err_mutex;
15371576
}
15381577

1539-
ret = joycon_read_mac(ctlr);
1578+
ret = joycon_read_info(ctlr);
15401579
if (ret) {
1541-
hid_err(hdev, "Failed to retrieve controller MAC; ret=%d\n",
1580+
hid_err(hdev, "Failed to retrieve controller info; ret=%d\n",
15421581
ret);
15431582
goto err_mutex;
15441583
}
@@ -1606,6 +1645,8 @@ static const struct hid_device_id nintendo_hid_devices[] = {
16061645
USB_DEVICE_ID_NINTENDO_PROCON) },
16071646
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
16081647
USB_DEVICE_ID_NINTENDO_PROCON) },
1648+
{ HID_USB_DEVICE(USB_VENDOR_ID_NINTENDO,
1649+
USB_DEVICE_ID_NINTENDO_CHRGGRIP) },
16091650
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
16101651
USB_DEVICE_ID_NINTENDO_JOYCONL) },
16111652
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,

0 commit comments

Comments
 (0)