From f6e42813212a88e04cffef34f42f6e3da4c7c1f6 Mon Sep 17 00:00:00 2001 From: Raphael Assenat Date: Mon, 10 Oct 2016 14:48:42 -0400 Subject: [PATCH] Dual controller now available as a configured flavor --- main.c | 166 ++++++++++++++++++++++++++++++++++++++++++----------- requests.h | 4 ++ 2 files changed, 135 insertions(+), 35 deletions(-) diff --git a/main.c b/main.c index 8875beb..d7bf5ed 100644 --- a/main.c +++ b/main.c @@ -38,12 +38,16 @@ #include "intervaltimer.h" #include "requests.h" -#define NUM_PLAYERS 2 +#define MAX_PLAYERS 2 #define GCN64_USB_PID 0x001D #define N64_USB_PID 0x0020 #define GC_USB_PID 0x0021 +#define DUAL_GCN64_USB_PID 0x0022 +#define DUAL_N64_USB_PID 0x0030 +#define DUAL_GC_USB_PID 0x0031 + /* Those .c files are included rather than linked for we * want the sizeof() operator to work on the arrays */ #include "reportdesc.c" @@ -60,22 +64,6 @@ struct cfg0 { struct usb_interface_descriptor interface_admin; struct usb_hid_descriptor hid_data; struct usb_endpoint_descriptor ep2_in; - -#if NUM_PLAYERS >= 2 - struct usb_interface_descriptor interface_p2; - struct usb_hid_descriptor hid_p2; - struct usb_endpoint_descriptor ep3_in; -#endif -#if NUM_PLAYERS >= 3 - struct usb_interface_descriptor interface_p3; - struct usb_hid_descriptor hid_p3; - struct usb_endpoint_descriptor ep4_in; -#endif -#if NUM_PLAYERS >= 4 - struct usb_interface_descriptor interface_p4; - struct usb_hid_descriptor hid_p4; - struct usb_endpoint_descriptor ep5_in; -#endif }; static const struct cfg0 cfg0 PROGMEM = { @@ -83,7 +71,92 @@ static const struct cfg0 cfg0 PROGMEM = { .bLength = sizeof(struct usb_configuration_descriptor), .bDescriptorType = CONFIGURATION_DESCRIPTOR, .wTotalLength = sizeof(cfg0), // includes all descriptors returned together - .bNumInterfaces = NUM_PLAYERS + 1, // one interface per player + one management interface + .bNumInterfaces = 1 + 1, // one interface per player + one management interface + .bConfigurationValue = 1, + .bmAttributes = CFG_DESC_ATTR_RESERVED, // set Self-powred and remote-wakeup here if needed. + .bMaxPower = 25, // for 50mA + }, + + // Main interface, HID (player 1) + .interface = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = INTERFACE_DESCRIPTOR, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_DEVICE_CLASS_HID, + .bInterfaceSubClass = HID_SUBCLASS_NONE, + .bInterfaceProtocol = HID_PROTOCOL_NONE, + }, + .hid = { + .bLength = sizeof(struct usb_hid_descriptor), + .bDescriptorType = HID_DESCRIPTOR, + .bcdHid = 0x0101, + .bCountryCode = HID_COUNTRY_NOT_SUPPORTED, + .bNumDescriptors = 1, // Only a report descriptor + .bClassDescriptorType = REPORT_DESCRIPTOR, + .wClassDescriptorLength = sizeof(gcn64_usbHidReportDescriptor), + }, + .ep1_in = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = ENDPOINT_DESCRIPTOR, + .bEndpointAddress = USB_RQT_DEVICE_TO_HOST | 1, // 0x81 + .bmAttributes = TRANSFER_TYPE_INT, + .wMaxPacketsize = 16, + .bInterval = LS_FS_INTERVAL_MS(1), + }, + + // Second HID interface for config and update + .interface_admin = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = INTERFACE_DESCRIPTOR, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_DEVICE_CLASS_HID, + .bInterfaceSubClass = HID_SUBCLASS_NONE, + .bInterfaceProtocol = HID_PROTOCOL_NONE, + }, + .hid_data = { + .bLength = sizeof(struct usb_hid_descriptor), + .bDescriptorType = HID_DESCRIPTOR, + .bcdHid = 0x0101, + .bCountryCode = HID_COUNTRY_NOT_SUPPORTED, + .bNumDescriptors = 1, // Only a report descriptor + .bClassDescriptorType = REPORT_DESCRIPTOR, + .wClassDescriptorLength = sizeof(dataHidReport), + }, + .ep2_in = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = ENDPOINT_DESCRIPTOR, + .bEndpointAddress = USB_RQT_DEVICE_TO_HOST | 2, // 0x82 + .bmAttributes = TRANSFER_TYPE_INT, + .wMaxPacketsize = 64, + .bInterval = LS_FS_INTERVAL_MS(1), + }, +}; + +struct cfg0_2p { + struct usb_configuration_descriptor configdesc; + struct usb_interface_descriptor interface; + struct usb_hid_descriptor hid; + struct usb_endpoint_descriptor ep1_in; + + struct usb_interface_descriptor interface_admin; + struct usb_hid_descriptor hid_data; + struct usb_endpoint_descriptor ep2_in; + + struct usb_interface_descriptor interface_p2; + struct usb_hid_descriptor hid_p2; + struct usb_endpoint_descriptor ep3_in; +}; + +static const struct cfg0_2p cfg0_2p PROGMEM = { + .configdesc = { + .bLength = sizeof(struct usb_configuration_descriptor), + .bDescriptorType = CONFIGURATION_DESCRIPTOR, + .wTotalLength = sizeof(cfg0_2p), // includes all descriptors returned together + .bNumInterfaces = 2 + 1, // one interface per player + one management interface .bConfigurationValue = 1, .bmAttributes = CFG_DESC_ATTR_RESERVED, // set Self-powred and remote-wakeup here if needed. .bMaxPower = 25, // for 50mA @@ -147,7 +220,6 @@ static const struct cfg0 cfg0 PROGMEM = { .bInterval = LS_FS_INTERVAL_MS(1), }, -#if NUM_PLAYERS >= 2 // Main interface, HID (player 2) .interface_p2 = { .bLength = sizeof(struct usb_interface_descriptor), @@ -176,8 +248,6 @@ static const struct cfg0 cfg0 PROGMEM = { .wMaxPacketsize = 16, .bInterval = LS_FS_INTERVAL_MS(1), }, -#endif - }; struct usb_device_descriptor device_descriptor = { @@ -213,12 +283,12 @@ static struct usb_parameters usb_params = { .flags = USB_PARAM_FLAG_CONFDESC_PROGMEM | USB_PARAM_FLAG_REPORTDESC_PROGMEM, .devdesc = (PGM_VOID_P)&device_descriptor, - .configdesc = (PGM_VOID_P)&cfg0, - .configdesc_ttllen = sizeof(cfg0), + .configdesc = (PGM_VOID_P)&cfg0, // Patched in main() for two players + .configdesc_ttllen = sizeof(cfg0), // Patched in main() for two players .num_strings = NUM_USB_STRINGS, .strings = g_usb_strings, - .n_hid_interfaces = 1 + NUM_PLAYERS, + .n_hid_interfaces = 1 + 1, // One per player + one management interface (patched in main() for two players) .hid_params = { [0] = { .reportdesc = gcn64_usbHidReportDescriptor, @@ -232,14 +302,12 @@ static struct usb_parameters usb_params = { .getReport = hiddata_get_report, .setReport = hiddata_set_report, }, -#if NUM_PLAYERS >= 2 [2] = { .reportdesc = gcn64_usbHidReportDescriptor, .reportdesc_len = sizeof(gcn64_usbHidReportDescriptor), .getReport = _usbpad_hid_get_report, .setReport = _usbpad_hid_set_report, }, -#endif }, }; @@ -343,7 +411,7 @@ void pollDelay(void) } } -static struct usbpad usbpads[NUM_PLAYERS]; +static struct usbpad usbpads[MAX_PLAYERS]; static char g_polling_suspended = 0; static void setSuspendPolling(uint8_t suspend) @@ -353,7 +421,7 @@ static void setSuspendPolling(uint8_t suspend) static void forceVibration(uint8_t channel, uint8_t force) { - if (channel < NUM_PLAYERS) { + if (channel < MAX_PLAYERS) { usbpad_forceVibrate(&usbpads[channel], force); } } @@ -372,20 +440,21 @@ static struct hiddata_ops hiddata_ops = { int main(void) { - Gamepad *pads[NUM_PLAYERS] = { }; + Gamepad *pads[MAX_PLAYERS] = { }; gamepad_data pad_data; unsigned char gamepad_vibrate = 0; unsigned char state = STATE_WAIT_POLLTIME; - int error_count[NUM_PLAYERS] = { }; + int error_count[MAX_PLAYERS] = { }; int i; int channel; + int num_players = 1; hwinit(); usart1_init(); eeprom_init(); intervaltimer_init(); - for (i=0; i 1) { + if (num_players > 1) { state = STATE_WAIT_INTERRUPT_READY_P2; } else { state = STATE_WAIT_POLLTIME; @@ -503,7 +599,7 @@ int main(void) } - for (channel=0; channel < NUM_PLAYERS; channel++) { + for (channel=0; channel < num_players; channel++) { gamepad_vibrate = usbpad_mustVibrate(&usbpads[channel]); if (last_v[channel] != gamepad_vibrate) { if (pads[channel] && pads[channel]->setVibration) { diff --git a/requests.h b/requests.h index 058566c..fb55824 100644 --- a/requests.h +++ b/requests.h @@ -20,6 +20,10 @@ #define CFG_MODE_N64_ONLY 0x01 #define CFG_MODE_GC_ONLY 0x02 +#define CFG_MODE_2P_STANDARD 0x10 +#define CFG_MODE_2P_N64_ONLY 0x11 +#define CFG_MODE_2P_GC_ONLY 0x12 + #define CFG_PARAM_SERIAL 0x01 #define CFG_PARAM_POLL_INTERVAL0 0x10