1 /* 2 * HID driver for Retrode 2 controller adapter and plug-in extensions 3 * 4 * Copyright (c) 2017 Bastien Nocera <hadess@hadess.net> 5 */ 6 7 /* 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the Free 10 * Software Foundation; either version 2 of the License, or (at your option) 11 * any later version. 12 */ 13 14 #include <linux/input.h> 15 #include <linux/slab.h> 16 #include <linux/hid.h> 17 #include <linux/module.h> 18 #include "hid-ids.h" 19 20 #define CONTROLLER_NAME_BASE "Retrode" 21 22 static int retrode_input_configured(struct hid_device *hdev, 23 struct hid_input *hi) 24 { 25 struct hid_field *field = hi->report->field[0]; 26 const char *suffix; 27 int number = 0; 28 char *name; 29 30 switch (field->report->id) { 31 case 0: 32 suffix = "SNES Mouse"; 33 break; 34 case 1: 35 case 2: 36 suffix = "SNES / N64"; 37 number = field->report->id; 38 break; 39 case 3: 40 case 4: 41 suffix = "Mega Drive"; 42 number = field->report->id - 2; 43 break; 44 default: 45 hid_err(hdev, "Got unhandled report id %d\n", field->report->id); 46 suffix = "Unknown"; 47 } 48 49 if (number) 50 name = devm_kasprintf(&hdev->dev, GFP_KERNEL, 51 "%s %s #%d", CONTROLLER_NAME_BASE, 52 suffix, number); 53 else 54 name = devm_kasprintf(&hdev->dev, GFP_KERNEL, 55 "%s %s", CONTROLLER_NAME_BASE, suffix); 56 57 if (!name) 58 return -ENOMEM; 59 60 hi->input->name = name; 61 62 return 0; 63 } 64 65 static int retrode_probe(struct hid_device *hdev, 66 const struct hid_device_id *id) 67 { 68 69 int ret; 70 71 /* Has no effect on the mouse device */ 72 hdev->quirks |= HID_QUIRK_MULTI_INPUT; 73 74 ret = hid_parse(hdev); 75 if (ret) 76 return ret; 77 78 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 79 if (ret) 80 return ret; 81 82 return 0; 83 } 84 85 static const struct hid_device_id retrode_devices[] = { 86 { HID_USB_DEVICE(USB_VENDOR_ID_FUTURE_TECHNOLOGY, USB_DEVICE_ID_RETRODE2) }, 87 { } 88 }; 89 MODULE_DEVICE_TABLE(hid, retrode_devices); 90 91 static struct hid_driver retrode_driver = { 92 .name = "hid-retrode", 93 .id_table = retrode_devices, 94 .input_configured = retrode_input_configured, 95 .probe = retrode_probe, 96 }; 97 98 module_hid_driver(retrode_driver); 99 100 MODULE_LICENSE("GPL"); 101