| /* | 
 |  *  HID driver for Retrode 2 controller adapter and plug-in extensions | 
 |  * | 
 |  *  Copyright (c) 2017 Bastien Nocera <hadess@hadess.net> | 
 |  */ | 
 |  | 
 | /* | 
 |  * 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. | 
 |  */ | 
 |  | 
 | #include <linux/input.h> | 
 | #include <linux/slab.h> | 
 | #include <linux/hid.h> | 
 | #include <linux/module.h> | 
 | #include "hid-ids.h" | 
 |  | 
 | #define CONTROLLER_NAME_BASE "Retrode" | 
 |  | 
 | static int retrode_input_configured(struct hid_device *hdev, | 
 | 					struct hid_input *hi) | 
 | { | 
 | 	struct hid_field *field = hi->report->field[0]; | 
 | 	const char *suffix; | 
 | 	int number = 0; | 
 | 	char *name; | 
 |  | 
 | 	switch (field->report->id) { | 
 | 	case 0: | 
 | 		suffix = "SNES Mouse"; | 
 | 		break; | 
 | 	case 1: | 
 | 	case 2: | 
 | 		suffix = "SNES / N64"; | 
 | 		number = field->report->id; | 
 | 		break; | 
 | 	case 3: | 
 | 	case 4: | 
 | 		suffix = "Mega Drive"; | 
 | 		number = field->report->id - 2; | 
 | 		break; | 
 | 	default: | 
 | 		hid_err(hdev, "Got unhandled report id %d\n", field->report->id); | 
 | 		suffix = "Unknown"; | 
 | 	} | 
 |  | 
 | 	if (number) | 
 | 		name = devm_kasprintf(&hdev->dev, GFP_KERNEL, | 
 | 				"%s %s #%d", CONTROLLER_NAME_BASE, | 
 | 				suffix, number); | 
 | 	else | 
 | 		name = devm_kasprintf(&hdev->dev, GFP_KERNEL, | 
 | 				"%s %s", CONTROLLER_NAME_BASE, suffix); | 
 |  | 
 | 	if (!name) | 
 | 		return -ENOMEM; | 
 |  | 
 | 	hi->input->name = name; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int retrode_probe(struct hid_device *hdev, | 
 | 			const struct hid_device_id *id) | 
 | { | 
 |  | 
 | 	int ret; | 
 |  | 
 | 	/* Has no effect on the mouse device */ | 
 | 	hdev->quirks |= HID_QUIRK_MULTI_INPUT; | 
 |  | 
 | 	ret = hid_parse(hdev); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static const struct hid_device_id retrode_devices[] = { | 
 | 	{ HID_USB_DEVICE(USB_VENDOR_ID_FUTURE_TECHNOLOGY, USB_DEVICE_ID_RETRODE2) }, | 
 | 	{ } | 
 | }; | 
 | MODULE_DEVICE_TABLE(hid, retrode_devices); | 
 |  | 
 | static struct hid_driver retrode_driver = { | 
 | 	.name             = "hid-retrode", | 
 | 	.id_table         = retrode_devices, | 
 | 	.input_configured = retrode_input_configured, | 
 | 	.probe            = retrode_probe, | 
 | }; | 
 |  | 
 | module_hid_driver(retrode_driver); | 
 |  | 
 | MODULE_LICENSE("GPL"); |