Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2521610imu; Thu, 29 Nov 2018 06:21:26 -0800 (PST) X-Google-Smtp-Source: AFSGD/XEXbFuf09N6pXILqV7amGkYO5YlzGkWR20vEpxcbeZy1M1SF4syHecEUK8u2rZ4PboYNZZ X-Received: by 2002:a17:902:4225:: with SMTP id g34mr1708214pld.152.1543501286038; Thu, 29 Nov 2018 06:21:26 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543501286; cv=none; d=google.com; s=arc-20160816; b=nRqozo3EDfzNF3AV51+ikiLbzLuQq2vXhItego+P1vSdmsCi0dWb6WYHwP4kdcKWfS MypLy+vw9b7oRdFVzdfYKs2A6VYdhlB1p1UIKX8x40/CYEIBg0j9Kb667IPlwhl02k09 4BLXDRTh+hesNQ5Z5/dV1tIgwLaNEVZ/GdI7yRTAPf7t+W8faynDdOwtHUt7koAPdCMv L7CESv/R1Qf7iiV0rPNR4bODuLwkueNncYBPN5xNfKvZzJ54urGLquYRttGjNud3zUBN 7n4c3aOLGchPT6cIoayLeBc7nV8Tfchv2XsXJA4M4h9qZdgCzjZ8p7hi6qAMVdngDlW0 4/gg== 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=sjDTZRdWcoo6zPypKPw3cxIR+nOOjB2MJwfqrQ/9/gk=; b=w+Js32RJKUVv4FKwxQc9q7wz/GKdyx/Gtj9ToLrP7St5g7rzFedaT2iSRmmYvRc0Rm fW6Ae6g1PX5SQA0exGQ2REa3Dv1GDpxQ4SzD7qF3elQ1ixAARNotgNSi55RaF3AHI2iZ vmWIT+v3d5nvMMOw7xtTD97KAp1NljqqviKVf5OWaJxwWDPuRz5mpOgkaXPOHqZmePdZ RBLC+y9VZ/n4/r8/Y5RHQhO8eZkzyv/0OzehgdDvf3BgLFu5RHikcsdsY6zHpx/nJzkz /Yk3vOTMplDoro4ZVds9bFFPNt4iH2ahoyJE8q83bG2cKadAl90qEiOwNylG+Y4vt1Ne fsxQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="yuhN/XTK"; 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 u6si2520534pfb.92.2018.11.29.06.21.10; Thu, 29 Nov 2018 06:21:26 -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="yuhN/XTK"; 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 S1730860AbeK3BYS (ORCPT + 99 others); Thu, 29 Nov 2018 20:24:18 -0500 Received: from mail.kernel.org ([198.145.29.99]:46952 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728756AbeK3BYR (ORCPT ); Thu, 29 Nov 2018 20:24:17 -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 44087205C9; Thu, 29 Nov 2018 14:18:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1543501126; bh=1PMTPRkqBNYRXEwgBHxh9qAFdl06KCW3JwTEK5OTyx8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=yuhN/XTK7u+qv5udTQ/Jjjh7A1ku7MeQwR+L4qTATm4EKJ/m3M0vEUKmItCjcof1N 3HXh3290XhpkjEsMkPHVxbUbpVo661gnCPbrFTFQrI4WScrEltLv8wktgo4Oifrq68 P6zdkqd7wdOiPwbXrCoVTRvFD2XC6GI69fwPgSV8= 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 4.4 53/86] Input: xpad - support some quirky Xbox One pads Date: Thu, 29 Nov 2018 15:12:18 +0100 Message-Id: <20181129140114.584651599@linuxfoundation.org> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181129140109.832117862@linuxfoundation.org> References: <20181129140109.832117862@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 4.4-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