Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-6.6/google' into for-linus

Add support for Google Stadia force feedback by Fabio Baltieri

+167
+7
drivers/hid/Kconfig
··· 412 412 help 413 413 Say Y here if you have a Google Hammer device. 414 414 415 + config HID_GOOGLE_STADIA_FF 416 + tristate "Google Stadia force feedback" 417 + select INPUT_FF_MEMLESS 418 + help 419 + Say Y here if you want to enable force feedback support for the Google 420 + Stadia controller. 421 + 415 422 config HID_VIVALDI 416 423 tristate "Vivaldi Keyboard" 417 424 select HID_VIVALDI_COMMON
+1
drivers/hid/Makefile
··· 55 55 obj-$(CONFIG_HID_GLORIOUS) += hid-glorious.o 56 56 obj-$(CONFIG_HID_VIVALDI_COMMON) += hid-vivaldi-common.o 57 57 obj-$(CONFIG_HID_GOOGLE_HAMMER) += hid-google-hammer.o 58 + obj-$(CONFIG_HID_GOOGLE_STADIA_FF) += hid-google-stadiaff.o 58 59 obj-$(CONFIG_HID_VIVALDI) += hid-vivaldi.o 59 60 obj-$(CONFIG_HID_GT683R) += hid-gt683r.o 60 61 obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
+158
drivers/hid/hid-google-stadiaff.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Stadia controller rumble support. 4 + * 5 + * Copyright 2023 Google LLC 6 + */ 7 + 8 + #include <linux/hid.h> 9 + #include <linux/input.h> 10 + #include <linux/slab.h> 11 + #include <linux/module.h> 12 + 13 + #include "hid-ids.h" 14 + 15 + #define STADIA_FF_REPORT_ID 5 16 + 17 + struct stadiaff_device { 18 + struct hid_device *hid; 19 + struct hid_report *report; 20 + spinlock_t lock; 21 + bool removed; 22 + uint16_t strong_magnitude; 23 + uint16_t weak_magnitude; 24 + struct work_struct work; 25 + }; 26 + 27 + static void stadiaff_work(struct work_struct *work) 28 + { 29 + struct stadiaff_device *stadiaff = 30 + container_of(work, struct stadiaff_device, work); 31 + struct hid_field *rumble_field = stadiaff->report->field[0]; 32 + unsigned long flags; 33 + 34 + spin_lock_irqsave(&stadiaff->lock, flags); 35 + rumble_field->value[0] = stadiaff->strong_magnitude; 36 + rumble_field->value[1] = stadiaff->weak_magnitude; 37 + spin_unlock_irqrestore(&stadiaff->lock, flags); 38 + 39 + hid_hw_request(stadiaff->hid, stadiaff->report, HID_REQ_SET_REPORT); 40 + } 41 + 42 + static int stadiaff_play(struct input_dev *dev, void *data, 43 + struct ff_effect *effect) 44 + { 45 + struct hid_device *hid = input_get_drvdata(dev); 46 + struct stadiaff_device *stadiaff = hid_get_drvdata(hid); 47 + unsigned long flags; 48 + 49 + spin_lock_irqsave(&stadiaff->lock, flags); 50 + if (!stadiaff->removed) { 51 + stadiaff->strong_magnitude = effect->u.rumble.strong_magnitude; 52 + stadiaff->weak_magnitude = effect->u.rumble.weak_magnitude; 53 + schedule_work(&stadiaff->work); 54 + } 55 + spin_unlock_irqrestore(&stadiaff->lock, flags); 56 + 57 + return 0; 58 + } 59 + 60 + static int stadiaff_init(struct hid_device *hid) 61 + { 62 + struct stadiaff_device *stadiaff; 63 + struct hid_report *report; 64 + struct hid_input *hidinput; 65 + struct input_dev *dev; 66 + int error; 67 + 68 + if (list_empty(&hid->inputs)) { 69 + hid_err(hid, "no inputs found\n"); 70 + return -ENODEV; 71 + } 72 + hidinput = list_entry(hid->inputs.next, struct hid_input, list); 73 + dev = hidinput->input; 74 + 75 + report = hid_validate_values(hid, HID_OUTPUT_REPORT, 76 + STADIA_FF_REPORT_ID, 0, 2); 77 + if (!report) 78 + return -ENODEV; 79 + 80 + stadiaff = devm_kzalloc(&hid->dev, sizeof(struct stadiaff_device), 81 + GFP_KERNEL); 82 + if (!stadiaff) 83 + return -ENOMEM; 84 + 85 + hid_set_drvdata(hid, stadiaff); 86 + 87 + input_set_capability(dev, EV_FF, FF_RUMBLE); 88 + 89 + error = input_ff_create_memless(dev, NULL, stadiaff_play); 90 + if (error) 91 + return error; 92 + 93 + stadiaff->removed = false; 94 + stadiaff->hid = hid; 95 + stadiaff->report = report; 96 + INIT_WORK(&stadiaff->work, stadiaff_work); 97 + spin_lock_init(&stadiaff->lock); 98 + 99 + hid_info(hid, "Force Feedback for Google Stadia controller\n"); 100 + 101 + return 0; 102 + } 103 + 104 + static int stadia_probe(struct hid_device *hdev, const struct hid_device_id *id) 105 + { 106 + int ret; 107 + 108 + ret = hid_parse(hdev); 109 + if (ret) { 110 + hid_err(hdev, "parse failed\n"); 111 + return ret; 112 + } 113 + 114 + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); 115 + if (ret) { 116 + hid_err(hdev, "hw start failed\n"); 117 + return ret; 118 + } 119 + 120 + ret = stadiaff_init(hdev); 121 + if (ret) { 122 + hid_err(hdev, "force feedback init failed\n"); 123 + hid_hw_stop(hdev); 124 + return ret; 125 + } 126 + 127 + return 0; 128 + } 129 + 130 + static void stadia_remove(struct hid_device *hid) 131 + { 132 + struct stadiaff_device *stadiaff = hid_get_drvdata(hid); 133 + unsigned long flags; 134 + 135 + spin_lock_irqsave(&stadiaff->lock, flags); 136 + stadiaff->removed = true; 137 + spin_unlock_irqrestore(&stadiaff->lock, flags); 138 + 139 + cancel_work_sync(&stadiaff->work); 140 + hid_hw_stop(hid); 141 + } 142 + 143 + static const struct hid_device_id stadia_devices[] = { 144 + { HID_USB_DEVICE(USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STADIA) }, 145 + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STADIA) }, 146 + { } 147 + }; 148 + MODULE_DEVICE_TABLE(hid, stadia_devices); 149 + 150 + static struct hid_driver stadia_driver = { 151 + .name = "stadia", 152 + .id_table = stadia_devices, 153 + .probe = stadia_probe, 154 + .remove = stadia_remove, 155 + }; 156 + module_hid_driver(stadia_driver); 157 + 158 + MODULE_LICENSE("GPL");
+1
drivers/hid/hid-ids.h
··· 531 531 #define USB_DEVICE_ID_GOOGLE_DON 0x5050 532 532 #define USB_DEVICE_ID_GOOGLE_EEL 0x5057 533 533 #define USB_DEVICE_ID_GOOGLE_JEWEL 0x5061 534 + #define USB_DEVICE_ID_GOOGLE_STADIA 0x9400 534 535 535 536 #define USB_VENDOR_ID_GOTOP 0x08f2 536 537 #define USB_DEVICE_ID_SUPER_Q2 0x007f