mirror of
https://github.com/raphnet/gc_n64_usb-v3
synced 2024-12-21 23:08:53 -05:00
2-player: Re-order joystick and management interfaces
Make sure the management (non-joystick) interface is the last. Works around a presumed Windows bug (Joystick ID confusion where the second controller stops working or gives an error in the Game controller test dialog)
This commit is contained in:
parent
0e0c381fbd
commit
708fb22072
115
main.c
115
main.c
@ -144,12 +144,12 @@ struct cfg0_2p {
|
|||||||
struct usb_hid_descriptor hid;
|
struct usb_hid_descriptor hid;
|
||||||
struct usb_endpoint_descriptor ep1_in;
|
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_interface_descriptor interface_p2;
|
||||||
struct usb_hid_descriptor hid_p2;
|
struct usb_hid_descriptor hid_p2;
|
||||||
|
struct usb_endpoint_descriptor ep2_in;
|
||||||
|
|
||||||
|
struct usb_interface_descriptor interface_admin;
|
||||||
|
struct usb_hid_descriptor hid_data;
|
||||||
struct usb_endpoint_descriptor ep3_in;
|
struct usb_endpoint_descriptor ep3_in;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -193,40 +193,11 @@ static const struct cfg0_2p cfg0_2p PROGMEM = {
|
|||||||
.bInterval = LS_FS_INTERVAL_MS(1),
|
.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),
|
|
||||||
},
|
|
||||||
|
|
||||||
// Main interface, HID (player 2)
|
// Main interface, HID (player 2)
|
||||||
.interface_p2 = {
|
.interface_p2 = {
|
||||||
.bLength = sizeof(struct usb_interface_descriptor),
|
.bLength = sizeof(struct usb_interface_descriptor),
|
||||||
.bDescriptorType = INTERFACE_DESCRIPTOR,
|
.bDescriptorType = INTERFACE_DESCRIPTOR,
|
||||||
.bInterfaceNumber = 2,
|
.bInterfaceNumber = 1,
|
||||||
.bAlternateSetting = 0,
|
.bAlternateSetting = 0,
|
||||||
.bNumEndpoints = 1,
|
.bNumEndpoints = 1,
|
||||||
.bInterfaceClass = USB_DEVICE_CLASS_HID,
|
.bInterfaceClass = USB_DEVICE_CLASS_HID,
|
||||||
@ -242,12 +213,41 @@ static const struct cfg0_2p cfg0_2p PROGMEM = {
|
|||||||
.bClassDescriptorType = REPORT_DESCRIPTOR,
|
.bClassDescriptorType = REPORT_DESCRIPTOR,
|
||||||
.wClassDescriptorLength = sizeof(gcn64_usbHidReportDescriptor),
|
.wClassDescriptorLength = sizeof(gcn64_usbHidReportDescriptor),
|
||||||
},
|
},
|
||||||
|
.ep2_in = {
|
||||||
|
.bLength = sizeof(struct usb_endpoint_descriptor),
|
||||||
|
.bDescriptorType = ENDPOINT_DESCRIPTOR,
|
||||||
|
.bEndpointAddress = USB_RQT_DEVICE_TO_HOST | 2, // 0x82
|
||||||
|
.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 = 2,
|
||||||
|
.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),
|
||||||
|
},
|
||||||
.ep3_in = {
|
.ep3_in = {
|
||||||
.bLength = sizeof(struct usb_endpoint_descriptor),
|
.bLength = sizeof(struct usb_endpoint_descriptor),
|
||||||
.bDescriptorType = ENDPOINT_DESCRIPTOR,
|
.bDescriptorType = ENDPOINT_DESCRIPTOR,
|
||||||
.bEndpointAddress = USB_RQT_DEVICE_TO_HOST | 3, // 0x83
|
.bEndpointAddress = USB_RQT_DEVICE_TO_HOST | 3, // 0x83
|
||||||
.bmAttributes = TRANSFER_TYPE_INT,
|
.bmAttributes = TRANSFER_TYPE_INT,
|
||||||
.wMaxPacketsize = 16,
|
.wMaxPacketsize = 64,
|
||||||
.bInterval = LS_FS_INTERVAL_MS(1),
|
.bInterval = LS_FS_INTERVAL_MS(1),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -306,13 +306,6 @@ static struct usb_parameters usb_params = {
|
|||||||
.setReport = hiddata_set_report,
|
.setReport = hiddata_set_report,
|
||||||
.endpoint_size = 64,
|
.endpoint_size = 64,
|
||||||
},
|
},
|
||||||
[2] = {
|
|
||||||
.reportdesc = gcn64_usbHidReportDescriptor,
|
|
||||||
.reportdesc_len = sizeof(gcn64_usbHidReportDescriptor),
|
|
||||||
.getReport = _usbpad_hid_get_report,
|
|
||||||
.setReport = _usbpad_hid_set_report,
|
|
||||||
.endpoint_size = 16,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -482,44 +475,36 @@ int main(void)
|
|||||||
case CFG_MODE_2P_STANDARD:
|
case CFG_MODE_2P_STANDARD:
|
||||||
usbstrings_changeProductString_P(PSTR("Dual GC/N64 to USB v"VERSIONSTR_SHORT));
|
usbstrings_changeProductString_P(PSTR("Dual GC/N64 to USB v"VERSIONSTR_SHORT));
|
||||||
device_descriptor.idProduct = DUAL_GCN64_USB_PID;
|
device_descriptor.idProduct = DUAL_GCN64_USB_PID;
|
||||||
usb_params.configdesc = (PGM_VOID_P)&cfg0_2p;
|
|
||||||
usb_params.configdesc_ttllen = sizeof(cfg0_2p);
|
|
||||||
usb_params.n_hid_interfaces = 3;
|
|
||||||
num_players = 2;
|
num_players = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CFG_MODE_2P_N64_ONLY:
|
case CFG_MODE_2P_N64_ONLY:
|
||||||
usbstrings_changeProductString_P(PSTR("Dual N64 to USB v"VERSIONSTR_SHORT));
|
usbstrings_changeProductString_P(PSTR("Dual N64 to USB v"VERSIONSTR_SHORT));
|
||||||
device_descriptor.idProduct = DUAL_N64_USB_PID;
|
device_descriptor.idProduct = DUAL_N64_USB_PID;
|
||||||
usb_params.configdesc = (PGM_VOID_P)&cfg0_2p;
|
|
||||||
usb_params.configdesc_ttllen = sizeof(cfg0_2p);
|
|
||||||
usb_params.n_hid_interfaces = 3;
|
|
||||||
num_players = 2;
|
num_players = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CFG_MODE_2P_GC_ONLY:
|
case CFG_MODE_2P_GC_ONLY:
|
||||||
usbstrings_changeProductString_P(PSTR("Dual Gamecube to USB v"VERSIONSTR_SHORT));
|
usbstrings_changeProductString_P(PSTR("Dual Gamecube to USB v"VERSIONSTR_SHORT));
|
||||||
device_descriptor.idProduct = DUAL_GC_USB_PID;
|
device_descriptor.idProduct = DUAL_GC_USB_PID;
|
||||||
usb_params.configdesc = (PGM_VOID_P)&cfg0_2p;
|
|
||||||
usb_params.configdesc_ttllen = sizeof(cfg0_2p);
|
|
||||||
usb_params.n_hid_interfaces = 3;
|
|
||||||
num_players = 2;
|
num_players = 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<num_players; i++) {
|
// 2-players common
|
||||||
int hid_iface_id;
|
if (num_players == 2) {
|
||||||
|
usb_params.configdesc = (PGM_VOID_P)&cfg0_2p;
|
||||||
usbpad_init(&usbpads[i]);
|
usb_params.configdesc_ttllen = sizeof(cfg0_2p);
|
||||||
|
usb_params.n_hid_interfaces = 3;
|
||||||
// Skip interface 1 (always used for the dataReport)
|
// Move the management interface is the last position
|
||||||
if (i>0) {
|
memcpy(usb_params.hid_params + 2, usb_params.hid_params + 1, sizeof(struct usb_hid_parameters));
|
||||||
hid_iface_id = i + 1;
|
// Add a second player interface between them
|
||||||
} else {
|
memcpy(usb_params.hid_params + 1, usb_params.hid_params + 0, sizeof(struct usb_hid_parameters));
|
||||||
hid_iface_id = i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_params.hid_params[hid_iface_id].ctx = &usbpads[i];
|
for (i=0; i<num_players; i++) {
|
||||||
|
usbpad_init(&usbpads[i]);
|
||||||
|
usb_params.hid_params[i].ctx = &usbpads[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
sei();
|
sei();
|
||||||
@ -597,7 +582,7 @@ int main(void)
|
|||||||
|
|
||||||
case STATE_WAIT_INTERRUPT_READY:
|
case STATE_WAIT_INTERRUPT_READY:
|
||||||
/* Wait until one of the interrupt endpoint is ready */
|
/* Wait until one of the interrupt endpoint is ready */
|
||||||
if (usb_interruptReady_ep1() || (num_players>1 && usb_interruptReady_ep3())) {
|
if (usb_interruptReady_ep1() || (num_players>1 && usb_interruptReady_ep2())) {
|
||||||
state = STATE_TRANSMIT;
|
state = STATE_TRANSMIT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -606,8 +591,8 @@ int main(void)
|
|||||||
if (usb_interruptReady_ep1()) {
|
if (usb_interruptReady_ep1()) {
|
||||||
usb_interruptSend_ep1(usbpad_getReportBuffer(&usbpads[0]), usbpad_getReportSize());
|
usb_interruptSend_ep1(usbpad_getReportBuffer(&usbpads[0]), usbpad_getReportSize());
|
||||||
}
|
}
|
||||||
if (num_players>1 && usb_interruptReady_ep3()) {
|
if (num_players>1 && usb_interruptReady_ep2()) {
|
||||||
usb_interruptSend_ep3(usbpad_getReportBuffer(&usbpads[1]), usbpad_getReportSize());
|
usb_interruptSend_ep2(usbpad_getReportBuffer(&usbpads[1]), usbpad_getReportSize());
|
||||||
}
|
}
|
||||||
state = STATE_WAIT_POLLTIME;
|
state = STATE_WAIT_POLLTIME;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user