From patchwork Sun Oct 30 22:13:13 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcel Hasler X-Patchwork-Id: 9404809 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id BD52F60586 for ; Sun, 30 Oct 2016 22:13:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9C0F628E93 for ; Sun, 30 Oct 2016 22:13:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 904E628E9A; Sun, 30 Oct 2016 22:13:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E73EA28E93 for ; Sun, 30 Oct 2016 22:13:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754549AbcJ3WNV (ORCPT ); Sun, 30 Oct 2016 18:13:21 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:35625 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754498AbcJ3WNU (ORCPT ); Sun, 30 Oct 2016 18:13:20 -0400 Received: by mail-wm0-f67.google.com with SMTP id 68so9212428wmz.2 for ; Sun, 30 Oct 2016 15:13:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=9iXfAU+8zoFgm0dV2tcTSaE5dKmeEyFsNYOsVO3PKFI=; b=zZjb6ZdTEDd1vP/KfSkUiqjzkNv5fMpy3DTJYtgmazzxX0ZANOA2p6t0T3uyNnP4dk D5rOPb8mt2pY6Zuy9IN6wZwF7X7hL+epn2ZDcn+X+FB0rCFgyZsgsCIasbkTQ/+ypzkQ eh17ZbdWHiBLJIsBs5A7GCtc4bjAKEURBA6lLcmT82YyX0kIse8wRHOhGPyTgQPbFded lcbbOOUKERjkMx2Le5ppTZH+gXghH7ZjUOp21TcwOpa8ujXN8NYqlDWjQS2Cj/iYXE9I Y2yf/Ffws0IA1+QJ59a8MF3AMfLthDuYCI/xAZso/ngITgu7CNwX3m6iNfqK5sfMwSlv D6Sg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=9iXfAU+8zoFgm0dV2tcTSaE5dKmeEyFsNYOsVO3PKFI=; b=lijrKyfj9Lhma7JLoB5uCw1XUTY4vP8BW4/VfNRLteQi+r7aF5il/tYLgEbZh32KkE 9Z+E6akGGlYA4wtCc26RUphNTJwba6wkfSBVxguapnJzxxgk/ul4UOaOznbOXZ2m5RSU yykE/bVQnYaDhAKlzuKZHbNWZOzyV/5I+uDikHvPBtK9FU2komRw/S7qUlzZMuJm6GEo tP0Re1pbPMV9Yvt3qu03hJpqwmyoPGM+Sx478rf3aWqNCIYFxh5OoU+IGyVjbsgylE7O IXNvfYw0adu4xE1JmFtoCEvbYujQTgQkJur9nczdBJ3UcCzr/cbheeQT0JFUTFZUP7uD g2zw== X-Gm-Message-State: ABUngvfX78XT8Dc4N5VK8unVWEYqNC760lVKoU2sFBHlf+fy70tbf6p4BlzCoKUEtbJKmQ== X-Received: by 10.28.137.194 with SMTP id l185mr7448376wmd.88.1477865598997; Sun, 30 Oct 2016 15:13:18 -0700 (PDT) Received: from arch-desktop ([2a02:908:672:a420:922b:34ff:fe11:2b9f]) by smtp.gmail.com with ESMTPSA id l6sm19807980wjc.7.2016.10.30.15.13.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 30 Oct 2016 15:13:18 -0700 (PDT) Date: Sun, 30 Oct 2016 23:13:13 +0100 From: Marcel Hasler To: Jiri Kosina , Benjamin Tissoires Cc: linux-input@vger.kernel.org Subject: [PATCH 2/2] Add new force feedback driver for Mayflash game controller adapters. Message-ID: <20161030221313.GA15445@arch-desktop> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.7.1 (2016-10-04) Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add a new module named hid-mf that implements force feedback for game controller adapters manufactured by Mayflash. Currently only the PS3 adapter is supported, other adapters still need to be tested. Signed-off-by: Marcel Hasler --- drivers/hid/Kconfig | 8 +++ drivers/hid/Makefile | 1 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-mf.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 175 insertions(+) create mode 100644 drivers/hid/hid-mf.c diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index cd4599c..1530d28 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -512,6 +512,14 @@ config HID_MAGICMOUSE Say Y here if you want support for the multi-touch features of the Apple Wireless "Magic" Mouse and the Apple Wireless "Magic" Trackpad. +config HID_MAYFLASH + tristate "Mayflash game controller adapter force feedback" + depends on HID + select INPUT_FF_MEMLESS + ---help--- + Say Y here if you have HJZ Mayflash PS3 game controller adapters + and want to enable force feedback support. + config HID_MICROSOFT tristate "Microsoft non-fully HID-compliant devices" depends on HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 86b2b57..c0453f1 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o obj-$(CONFIG_HID_LOGITECH_HIDPP) += hid-logitech-hidpp.o obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o +obj-$(CONFIG_HID_MAYFLASH) += hid-mf.o obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 2b89c70..8470e22 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1883,6 +1883,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DELCOM, USB_DEVICE_ID_DELCOM_VISUAL_IND) }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3) }, { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) }, { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, diff --git a/drivers/hid/hid-mf.c b/drivers/hid/hid-mf.c new file mode 100644 index 0000000..6791ce7 --- /dev/null +++ b/drivers/hid/hid-mf.c @@ -0,0 +1,165 @@ +/* + * Force feedback support for Mayflash game controller adapters. + * + * These devices are manufactured by Mayflash but identify themselves + * using the vendor ID of DragonRise Inc. + * + * Tested with: + * 0079:1801 "DragonRise Inc. Mayflash PS3 Game Controller Adapter" + * + * The following adapters probably work too, but need to be tested: + * 0079:1800 "DragonRise Inc. Mayflash WIIU Game Controller Adapter" + * 0079:1843 "DragonRise Inc. Mayflash GameCube Game Controller Adapter" + * + * Copyright (c) 2016 Marcel Hasler + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#include "hid-ids.h" + +struct mf_device { + struct hid_report *report; +}; + +static int mf_play(struct input_dev *dev, void *data, struct ff_effect *effect) +{ + struct hid_device *hid = input_get_drvdata(dev); + struct mf_device *mf = data; + int strong, weak; + + strong = effect->u.rumble.strong_magnitude; + weak = effect->u.rumble.weak_magnitude; + + dbg_hid("Called with 0x%04x 0x%04x.\n", strong, weak); + + strong = strong * 0xff / 0xffff; + weak = weak * 0xff / 0xffff; + + dbg_hid("Running with 0x%02x 0x%02x.\n", strong, weak); + + mf->report->field[0]->value[0] = weak; + mf->report->field[0]->value[1] = strong; + hid_hw_request(hid, mf->report, HID_REQ_SET_REPORT); + + return 0; +} + +static int mf_init(struct hid_device *hid) +{ + struct mf_device *mf; + + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; + + struct list_head *report_ptr; + struct hid_report *report; + + struct hid_input *input = + list_first_entry(&hid->inputs, struct hid_input, list); + + struct input_dev *dev; + + int error; + + /* Setup each of the four inputs */ + list_for_each(report_ptr, report_list) { + report = list_entry(report_ptr, struct hid_report, list); + + if (report->maxfield < 1 || report->field[0]->report_count < 2) { + hid_err(hid, "Invalid report, this should never happen!\n"); + return -ENODEV; + } + + if (input == NULL) { + hid_err(hid, "Missing input, this should never happen!\n"); + return -ENODEV; + } + + dev = input->input; + input = list_next_entry(input, list); + + mf = kzalloc(sizeof(struct mf_device), GFP_KERNEL); + if (!mf) + return -ENOMEM; + + set_bit(FF_RUMBLE, dev->ffbit); + + error = input_ff_create_memless(dev, mf, mf_play); + if (error) { + kfree(mf); + return error; + } + + mf->report = report; + mf->report->field[0]->value[0] = 0x00; + mf->report->field[0]->value[1] = 0x00; + hid_hw_request(hid, mf->report, HID_REQ_SET_REPORT); + } + + hid_info(hid, "Force feedback for HJZ Mayflash game controller " + "adapters by Marcel Hasler \n"); + + return 0; +} + +static int mf_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + int error; + + dev_dbg(&hdev->dev, "Mayflash HID hardware probe...\n"); + + /* Split device into four inputs */ + hdev->quirks |= HID_QUIRK_MULTI_INPUT; + + error = hid_parse(hdev); + if (error) { + hid_err(hdev, "HID parse failed.\n"); + return error; + } + + error = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); + if (error) { + hid_err(hdev, "HID hw start failed\n"); + return error; + } + + error = mf_init(hdev); + if (error) { + hid_err(hdev, "Force feedback init failed.\n"); + hid_hw_stop(hdev); + return error; + } + + return 0; +} + +static const struct hid_device_id mf_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3), }, + { } +}; +MODULE_DEVICE_TABLE(hid, mf_devices); + +static struct hid_driver mf_driver = { + .name = "hid_mf", + .id_table = mf_devices, + .probe = mf_probe, +}; +module_hid_driver(mf_driver); + +MODULE_LICENSE("GPL");