Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2517836imu; Thu, 29 Nov 2018 06:18:34 -0800 (PST) X-Google-Smtp-Source: AFSGD/WaaENF/IUdYpHWWpFB2n9Xq6DiQEYMphTd0Z9Hmy3eZF6lboqV4f3D/W8sseaGPBafIjUc X-Received: by 2002:a17:902:1d4a:: with SMTP id u10mr1584298plu.122.1543501114381; Thu, 29 Nov 2018 06:18:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543501114; cv=none; d=google.com; s=arc-20160816; b=e2t2AfTZhe9nOBgck3gcGVdLDg8ktPxUk7I5UskT+cDvPEaQJXLG+1NXd5x24b5QEf VYdrLwAaKiEwNt/qywjMRcs18c99DK0IRwPZtsEFAreO71gwBnmmsYxHyLVVmKEZ6xzx ve5GGbQhBBizlCsTfgXFGndNyp5Hmb4ueXSlsewq0ko8+bg+/jcDPRjbscbfO0Q8rAgu +9qrjBsmT59sWkaLXVG7Tum/BA455KX0TMfl6Wt5CWNivk/rXFSup1A2e/K2EJ2I6+ZI FEyHu6bKGNS6GCQ93hRp7XfZNR2zMNNlKgDeGuNeBzxCPHY/hw6LXTsHX/5++jRnr3p/ xqNQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=XEoQ3SluBIIrhViAGnitnuTqSFrMO5fxMxGshxPV8J4=; b=THZfgq/OsdNMNJVV8GHlduc69JXbNNXLhte8YMueih6dRHV8DKySf7d2L5NHJDIAJu qm7v/cgYGHocV0JNsZTz+/T0R6j/Wjv+XZS7kUSn5ypyPKxdnCrRZLRGb2mSFpW361b1 GiVXRXTj6Ji6oTG3oH2QYb2P7LpyGRD/iiDJdld2dcuctrEMGxu4BZTTHsPIbLtr0lr5 Zu+kjRIPHl7wWUrp+l/H3u6hvyh5m7smbt3Lo1kQa9jY7CXKtX1ilmDqJW7Ol2ePHZF6 DAwGeUQzR+elejzqc09KqxxOtN1lf2/Y+Ehdxu2OSo7bBjPYKwkovtsT7juGYoPTZ3Zh XDIg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=lvRc9TPj; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n59-v6si2266769plb.416.2018.11.29.06.18.19; Thu, 29 Nov 2018 06:18:34 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=lvRc9TPj; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729693AbeK3BVJ (ORCPT + 99 others); Thu, 29 Nov 2018 20:21:09 -0500 Received: from mail.kernel.org ([198.145.29.99]:42322 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728241AbeK3BVI (ORCPT ); Thu, 29 Nov 2018 20:21:08 -0500 Received: from localhost (5356596B.cm-6-7b.dynamic.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 6BDA0205C9; Thu, 29 Nov 2018 14:15:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1543500937; bh=743jY6vW/66zzUPcV4UAEkIJv9L5M+a+PLNriG4S8kg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lvRc9TPj2Wwig3ymWBX6ko4EySqw5Wz76L47jUeVtfRo2cazXwo42BSlvItU4pPbe 8qefPR/kNDYcxfHda79QnOFcZZ6uz9a+t4bgVhIpMx+IpgAgkGib1tLlXFlRf/XbTI KwO6UZfCYPnbN2718jNE5WKYoXxKc4uOyR0BrEdY= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Cameron Gutman , Dmitry Torokhov , Sasha Levin Subject: [PATCH 3.18 59/83] Input: xpad - support some quirky Xbox One pads Date: Thu, 29 Nov 2018 15:12:17 +0100 Message-Id: <20181129140141.024740292@linuxfoundation.org> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181129140138.002176596@linuxfoundation.org> References: <20181129140138.002176596@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.18-stable review patch. If anyone has any objections, please let me know. ------------------ [ Upstream commit 81093c9848a781b85163d06de92ef8f84528cf6a ] There are several quirky Xbox One pads that depend on initialization packets that the Microsoft pads don't require. To deal with these, I've added a mechanism for issuing device-specific initialization packets using a VID/PID-based quirks list. For the initial set of init quirks, I have added quirk handling from Valve's Steam Link xpad driver[0] and the 360Controller project[1] for macOS to enable some new pads to work properly. This should enable full functionality on the following quirky pads: 0x0e6f:0x0165 - Titanfall 2 gamepad (previously fully non-functional) 0x0f0d:0x0067 - Hori Horipad (analog sticks previously non-functional) 0x24c6:0x541a - PowerA Xbox One pad (previously fully non-functional) 0x24c6:0x542a - PowerA Xbox One pad (previously fully non-functional) 0x24c6:0x543a - PowerA Xbox One pad (previously fully non-functional) [0]: https://github.com/ValveSoftware/steamlink-sdk/blob/master/kernel/drivers/input/joystick/xpad.c [1]: https://github.com/360Controller/360Controller Signed-off-by: Cameron Gutman Signed-off-by: Dmitry Torokhov Signed-off-by: Sasha Levin --- drivers/input/joystick/xpad.c | 114 ++++++++++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 13 deletions(-) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 153b1ee13e03..df83fdc6c0e7 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -339,6 +339,64 @@ static struct usb_device_id xpad_table[] = { MODULE_DEVICE_TABLE(usb, xpad_table); +struct xboxone_init_packet { + u16 idVendor; + u16 idProduct; + const u8 *data; + u8 len; +}; + +#define XBOXONE_INIT_PKT(_vid, _pid, _data) \ + { \ + .idVendor = (_vid), \ + .idProduct = (_pid), \ + .data = (_data), \ + .len = ARRAY_SIZE(_data), \ + } + + +/* + * This packet is required for all Xbox One pads with 2015 + * or later firmware installed (or present from the factory). + */ +static const u8 xboxone_fw2015_init[] = { + 0x05, 0x20, 0x00, 0x01, 0x00 +}; + +/* + * This packet is required for the Titanfall 2 Xbox One pads + * (0x0e6f:0x0165) to finish initialization and for Hori pads + * (0x0f0d:0x0067) to make the analog sticks work. + */ +static const u8 xboxone_hori_init[] = { + 0x01, 0x20, 0x00, 0x09, 0x00, 0x04, 0x20, 0x3a, + 0x00, 0x00, 0x00, 0x80, 0x00 +}; + +/* + * A rumble packet is required for some PowerA pads to start + * sending input reports. One of those pads is (0x24c6:0x543a). + */ +static const u8 xboxone_zerorumble_init[] = { + 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* + * This specifies the selection of init packets that a gamepad + * will be sent on init *and* the order in which they will be + * sent. The correct sequence number will be added when the + * packet is going to be sent. + */ +static const struct xboxone_init_packet xboxone_init_packets[] = { + XBOXONE_INIT_PKT(0x0e6f, 0x0165, xboxone_hori_init), + XBOXONE_INIT_PKT(0x0f0d, 0x0067, xboxone_hori_init), + XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init), + XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_zerorumble_init), + XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_zerorumble_init), + XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_zerorumble_init), +}; + struct xpad_output_packet { u8 data[XPAD_PKT_LEN]; u8 len; @@ -375,6 +433,7 @@ struct usb_xpad { struct xpad_output_packet out_packets[XPAD_NUM_OUT_PACKETS]; int last_out_packet; + int init_seq; #if defined(CONFIG_JOYSTICK_XPAD_LEDS) struct xpad_led *led; @@ -749,12 +808,48 @@ exit: __func__, retval); } +/* Callers must hold xpad->odata_lock spinlock */ +static bool xpad_prepare_next_init_packet(struct usb_xpad *xpad) +{ + const struct xboxone_init_packet *init_packet; + + if (xpad->xtype != XTYPE_XBOXONE) + return false; + + /* Perform initialization sequence for Xbox One pads that require it */ + while (xpad->init_seq < ARRAY_SIZE(xboxone_init_packets)) { + init_packet = &xboxone_init_packets[xpad->init_seq++]; + + if (init_packet->idVendor != 0 && + init_packet->idVendor != xpad->dev->id.vendor) + continue; + + if (init_packet->idProduct != 0 && + init_packet->idProduct != xpad->dev->id.product) + continue; + + /* This packet applies to our device, so prepare to send it */ + memcpy(xpad->odata, init_packet->data, init_packet->len); + xpad->irq_out->transfer_buffer_length = init_packet->len; + + /* Update packet with current sequence number */ + xpad->odata[2] = xpad->odata_serial++; + return true; + } + + return false; +} + /* Callers must hold xpad->odata_lock spinlock */ static bool xpad_prepare_next_out_packet(struct usb_xpad *xpad) { struct xpad_output_packet *pkt, *packet = NULL; int i; + /* We may have init packets to send before we can send user commands */ + if (xpad_prepare_next_init_packet(xpad)) + return true; + for (i = 0; i < XPAD_NUM_OUT_PACKETS; i++) { if (++xpad->last_out_packet >= XPAD_NUM_OUT_PACKETS) xpad->last_out_packet = 0; @@ -940,24 +1035,17 @@ static int xpad_inquiry_pad_presence(struct usb_xpad *xpad) static int xpad_start_xbox_one(struct usb_xpad *xpad) { - struct xpad_output_packet *packet = - &xpad->out_packets[XPAD_OUT_CMD_IDX]; unsigned long flags; int retval; spin_lock_irqsave(&xpad->odata_lock, flags); - /* Xbox one controller needs to be initialized. */ - packet->data[0] = 0x05; - packet->data[1] = 0x20; - packet->data[2] = xpad->odata_serial++; /* packet serial */ - packet->data[3] = 0x01; /* rumble bit enable? */ - packet->data[4] = 0x00; - packet->len = 5; - packet->pending = true; - - /* Reset the sequence so we send out start packet first */ - xpad->last_out_packet = -1; + /* + * Begin the init sequence by attempting to send a packet. + * We will cycle through the init packet sequence before + * sending any packets from the output ring. + */ + xpad->init_seq = 0; retval = xpad_try_sending_next_out_packet(xpad); spin_unlock_irqrestore(&xpad->odata_lock, flags); -- 2.17.1