mirror of
https://github.com/mist-devel/mist-firmware.git
synced 2026-04-25 20:11:42 +00:00
Add Xbox360 controller support
- tested only with a Retroflag classic USB gamepad - no analogue parts yet (need a real controller for that)
This commit is contained in:
2
Makefile
2
Makefile
@@ -12,7 +12,7 @@ TODAY = `date +"%m/%d/%y"`
|
||||
PRJ = firmware
|
||||
SRC = hw/AT91SAM/Cstartup_SAM7.c hw/AT91SAM/hardware.c hw/AT91SAM/spi.c hw/AT91SAM/mmc.c hw/AT91SAM/at91sam_usb.c hw/AT91SAM/usbdev.c
|
||||
SRC += fdd.c firmware.c fpga.c hdd.c main.c menu.c osd.c state.c syscalls.c user_io.c data_io.c boot.c idxfile.c config.c tos.c ikbd.c xmodem.c ini_parser.c cue_parser.c mist_cfg.c archie.c pcecd.c arc_file.c font.c utils.c
|
||||
SRC += usb/max3421e.c usb/usb.c usb/usbdebug.c usb/hub.c usb/hid.c usb/hidparser.c usb/timer.c usb/asix.c usb/pl2303.c usb/usbrtc.c usb/joymapping.c
|
||||
SRC += usb/max3421e.c usb/usb.c usb/usbdebug.c usb/hub.c usb/hid.c usb/hidparser.c usb/xboxusb.c usb/timer.c usb/asix.c usb/pl2303.c usb/usbrtc.c usb/joymapping.c usb/joystick.c
|
||||
SRC += fat_compat.c
|
||||
SRC += FatFs/diskio.c FatFs/ff.c FatFs/ffunicode.c
|
||||
# SRC += usb/storage.c
|
||||
|
||||
61
usb/hid.c
61
usb/hid.c
@@ -8,6 +8,7 @@
|
||||
#include "hidparser.h"
|
||||
#include "debug.h"
|
||||
#include "joymapping.h"
|
||||
#include "joystick.h"
|
||||
#include "hardware.h"
|
||||
#include "../utils.h"
|
||||
#include "../user_io.h"
|
||||
@@ -17,7 +18,6 @@
|
||||
|
||||
|
||||
static unsigned char kbd_led_state = 0; // default: all leds off
|
||||
static unsigned char joysticks = 0; // number of detected usb joysticks
|
||||
static unsigned char mice = 0; // number of detected usb mice
|
||||
|
||||
// up to 8 buttons can be remapped
|
||||
@@ -74,24 +74,6 @@ void hid_joystick_button_remap(char *s) {
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint8_t hid_get_jindex(usb_hid_iface_info_t *iface) {
|
||||
uint8_t jindex;
|
||||
|
||||
// Get USB joystick index (0,1...)
|
||||
jindex = iface->jindex;
|
||||
|
||||
// If DB9 joystick are preferred: USB joysticks are shifted to 2,3...
|
||||
if(mist_cfg.joystick_db9_fixed_index) {
|
||||
jindex += 2;
|
||||
}
|
||||
|
||||
return jindex;
|
||||
}
|
||||
|
||||
uint8_t hid_get_joysticks(void) {
|
||||
return joysticks;
|
||||
}
|
||||
|
||||
//get HID report descriptor
|
||||
static uint8_t hid_get_report_descr(usb_device_t *dev, uint8_t i, uint16_t size) {
|
||||
// hid_debugf("%s(%x, if=%d, size=%d)", __FUNCTION__, dev->bAddress, iface, size);
|
||||
@@ -108,10 +90,9 @@ static uint8_t hid_get_report_descr(usb_device_t *dev, uint8_t i, uint16_t size)
|
||||
// we got a report descriptor. Try to parse it
|
||||
if(parse_report_descriptor(buf, size, &(info->iface[i].conf))) {
|
||||
if(info->iface[i].conf.type == REPORT_TYPE_JOYSTICK) {
|
||||
hid_debugf("Detected USB joystick #%d", joysticks);
|
||||
hid_debugf("Detected USB joystick #%d", joystick_count());
|
||||
info->iface[i].device_type = HID_DEVICE_JOYSTICK;
|
||||
info->iface[i].jindex = joysticks++;
|
||||
StateNumJoysticksSet(joysticks);
|
||||
info->iface[i].jindex = joystick_add();
|
||||
}
|
||||
} else {
|
||||
// parsing failed. Fall back to boot mode for mice
|
||||
@@ -519,37 +500,9 @@ static uint8_t usb_hid_release(usb_device_t *dev) {
|
||||
for(i=0;i<info->bNumIfaces;i++) {
|
||||
// check if a joystick is released
|
||||
if(info->iface[i].device_type == HID_DEVICE_JOYSTICK) {
|
||||
uint8_t c_jindex = hid_get_jindex(&info->iface[i]);
|
||||
uint8_t c_jindex = joystick_index(info->iface[i].jindex);
|
||||
hid_debugf("releasing joystick #%d, renumbering", c_jindex);
|
||||
|
||||
// walk through all devices and search for sticks with a higher id
|
||||
|
||||
// search for all joystick interfaces on all hid devices
|
||||
usb_device_t *dev = usb_get_devices();
|
||||
uint8_t j;
|
||||
for(j=0;j<USB_NUMDEVICES;j++) {
|
||||
if(dev[j].bAddress && (dev[j].class == &usb_hid_class)) {
|
||||
// search for joystick interfaces
|
||||
uint8_t k;
|
||||
for(k=0;k<MAX_IFACES;k++) {
|
||||
if(dev[j].hid_info.iface[k].device_type == HID_DEVICE_JOYSTICK) {
|
||||
uint8_t jindex = hid_get_jindex(&dev[j].hid_info.iface[k]);
|
||||
if(jindex > c_jindex) {
|
||||
hid_debugf("decreasing jindex of dev #%d from %d to %d", j,
|
||||
jindex, jindex-1);
|
||||
dev[j].hid_info.iface[k].jindex--;
|
||||
StateUsbIdSet( dev[j].hid_info.iface[k].conf.vid, dev[j].hid_info.iface[k].conf.pid, dev[j].hid_info.iface[k].conf.joystick_mouse.button_count, dev[j].hid_info.iface[k].jindex);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// one less joystick in the system ...
|
||||
joysticks--;
|
||||
StateNumJoysticksSet(joysticks);
|
||||
if (joysticks < 6)
|
||||
StateUsbIdSet(0, 0, 0, joysticks);
|
||||
joystick_release(c_jindex);
|
||||
}
|
||||
|
||||
// check if a mouse is released
|
||||
@@ -612,7 +565,7 @@ static void handle_5200daptor(usb_hid_iface_info_t *iface, uint8_t *buf) {
|
||||
|
||||
// keyboard events are only generated for the first
|
||||
// two joysticks in the system
|
||||
uint8_t jindex = hid_get_jindex(iface);
|
||||
uint8_t jindex = joystick_index(iface->jindex);
|
||||
if(jindex > 1) return;
|
||||
|
||||
// build map of pressed keys
|
||||
@@ -882,7 +835,7 @@ static void usb_process_iface (usb_hid_iface_info_t *iface,
|
||||
jmap |= btn << JOY_BTN_SHIFT; // add buttons
|
||||
|
||||
// report joystick 1 to OSD
|
||||
idx = hid_get_jindex(iface);
|
||||
idx = joystick_index(iface->jindex);
|
||||
StateUsbIdSet( conf->vid, conf->pid, conf->joystick_mouse.button_count, idx);
|
||||
StateUsbJoySet( jmap, btn_extra, idx);
|
||||
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
/*
|
||||
This file is part of MiST-firmware
|
||||
|
||||
MiST-firmware 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
MiST-firmware is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
This file defines how to handle mapping in the MiST controllers in various ways:
|
||||
|
||||
@@ -165,6 +182,9 @@ char* get_joystick_alias( uint16_t vid, uint16_t pid ) {
|
||||
if(vid==0x0738 && pid==0x2217)
|
||||
return JOYSTICK_ALIAS_SPEEDLINK_COMP;
|
||||
|
||||
if(vid==0x045E && pid==0x028E)
|
||||
return JOYSTICK_ALIAS_XBOX;
|
||||
|
||||
return JOYSTICK_ALIAS_NONE;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
/*
|
||||
This file is part of MiST-firmware
|
||||
|
||||
MiST-firmware 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
MiST-firmware is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
// Handles Virtual Joystick functions (USB->Joystick mapping and Keyboard bindings)
|
||||
/*****************************************************************************/
|
||||
@@ -22,6 +39,7 @@
|
||||
#define JOYSTICK_ALIAS_RETRO_FREAK "Retro Freak gamepad"
|
||||
#define JOYSTICK_ALIAS_ROYDS_EX "ROYDS Stick.EX"
|
||||
#define JOYSTICK_ALIAS_SPEEDLINK_COMP "Speedlink Competition Pro"
|
||||
#define JOYSTICK_ALIAS_XBOX "Xbox360 Controller"
|
||||
#define JOYSTICK_ALIAS_ATARI_DAPTOR2 "2600-daptor II"
|
||||
#define JOYSTICK_ALIAS_5200_DAPTOR2 "5200-daptor"
|
||||
#define JOYSTICK_ALIAS_NEOGEO_DAPTOR "NEOGEO-daptor"
|
||||
|
||||
85
usb/joystick.c
Normal file
85
usb/joystick.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
This file is part of MiST-firmware
|
||||
|
||||
MiST-firmware 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
MiST-firmware is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "usb.h"
|
||||
#include "debug.h"
|
||||
#include "../utils.h"
|
||||
#include "../mist_cfg.h"
|
||||
#include "../state.h"
|
||||
|
||||
static unsigned char joysticks = 0; // number of detected usb joysticks
|
||||
|
||||
uint8_t joystick_count() {
|
||||
return joysticks;
|
||||
}
|
||||
|
||||
uint8_t joystick_add() {
|
||||
StateNumJoysticksSet(joysticks+1);
|
||||
return joysticks++;
|
||||
}
|
||||
|
||||
uint8_t joystick_index(uint8_t jindex) {
|
||||
// If DB9 joystick are preferred: USB joysticks are shifted to 2,3...
|
||||
if(mist_cfg.joystick_db9_fixed_index) {
|
||||
jindex += 2;
|
||||
}
|
||||
|
||||
return jindex;
|
||||
}
|
||||
|
||||
uint8_t joystick_release(uint8_t c_jindex) {
|
||||
// walk through all devices and search for sticks with a higher id
|
||||
|
||||
// search for all joystick interfaces on all hid devices
|
||||
usb_device_t *dev = usb_get_devices();
|
||||
uint8_t j;
|
||||
for(j=0;j<USB_NUMDEVICES;j++) {
|
||||
if(dev[j].bAddress && (dev[j].class == &usb_hid_class)) {
|
||||
// search for joystick interfaces
|
||||
uint8_t k;
|
||||
for(k=0;k<MAX_IFACES;k++) {
|
||||
if(dev[j].hid_info.iface[k].device_type == HID_DEVICE_JOYSTICK) {
|
||||
uint8_t jindex = joystick_index(dev[j].hid_info.iface[k].jindex);
|
||||
if(jindex > c_jindex) {
|
||||
iprintf("decreasing joystick index of dev #%d from %d to %d\n", j,
|
||||
jindex, jindex-1);
|
||||
dev[j].hid_info.iface[k].jindex--;
|
||||
StateUsbIdSet( dev[j].hid_info.iface[k].conf.vid, dev[j].hid_info.iface[k].conf.pid, dev[j].hid_info.iface[k].conf.joystick_mouse.button_count, dev[j].hid_info.iface[k].jindex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(dev[j].bAddress && (dev[j].class == &usb_xbox_class)) {
|
||||
uint8_t jindex = joystick_index(dev[j].xbox_info.jindex);
|
||||
if(jindex > c_jindex) {
|
||||
iprintf("Decreasing xbox index of dev #%d from %d to %d\n", j, jindex, jindex-1);
|
||||
dev[j].xbox_info.jindex--;
|
||||
StateUsbIdSet( dev[j].xbox_info.vid, dev[j].xbox_info.pid, 8/*button_count*/, dev[j].xbox_info.jindex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// one less joystick in the system ...
|
||||
joysticks--;
|
||||
StateNumJoysticksSet(joysticks);
|
||||
if (joysticks < 6)
|
||||
StateUsbIdSet(0, 0, 0, joysticks);
|
||||
}
|
||||
28
usb/joystick.h
Normal file
28
usb/joystick.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
This file is part of MiST-firmware
|
||||
|
||||
MiST-firmware 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
MiST-firmware is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef JOYSTICK_H
|
||||
#define JOYSTICK_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
uint8_t joystick_count();
|
||||
uint8_t joystick_add();
|
||||
uint8_t joystick_index(uint8_t jindex);
|
||||
uint8_t joystick_release(uint8_t c_jindex);
|
||||
|
||||
#endif
|
||||
@@ -338,6 +338,7 @@ uint8_t usb_ctrl_req(usb_device_t *dev, uint8_t bmReqType,
|
||||
static const usb_device_class_config_t *class_list[] = {
|
||||
&usb_hub_class,
|
||||
&usb_hid_class,
|
||||
&usb_xbox_class,
|
||||
&usb_asix_class,
|
||||
#ifdef USB_STORAGE
|
||||
&usb_storage_class,
|
||||
|
||||
@@ -97,6 +97,7 @@ typedef struct {
|
||||
|
||||
#include "hub.h"
|
||||
#include "hid.h"
|
||||
#include "xboxusb.h"
|
||||
#include "asix.h"
|
||||
#ifdef USB_STORAGE
|
||||
#include "storage.h"
|
||||
@@ -117,6 +118,7 @@ typedef struct usb_device_entry {
|
||||
union {
|
||||
usb_hub_info_t hub_info;
|
||||
usb_hid_info_t hid_info;
|
||||
usb_xbox_info_t xbox_info;
|
||||
usb_asix_info_t asix_info;
|
||||
#ifdef USB_STORAGE
|
||||
usb_storage_info_t storage_info;
|
||||
|
||||
236
usb/xboxusb.c
Normal file
236
usb/xboxusb.c
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
This file is part of MiST-firmware
|
||||
|
||||
MiST-firmware 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
MiST-firmware is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Based on the work of
|
||||
|
||||
Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "max3421e.h"
|
||||
#include "usb.h"
|
||||
#include "timer.h"
|
||||
#include "joystick.h"
|
||||
#include "joymapping.h"
|
||||
#include "mist_cfg.h"
|
||||
#include "state.h"
|
||||
#include "user_io.h"
|
||||
#include "debug.h"
|
||||
|
||||
#if 0
|
||||
static uint8_t usb_xbox_parse_conf(usb_device_t *dev, uint8_t conf, uint16_t len) {
|
||||
uint8_t rcode;
|
||||
|
||||
union buf_u {
|
||||
usb_configuration_descriptor_t conf_desc;
|
||||
usb_interface_descriptor_t iface_desc;
|
||||
usb_endpoint_descriptor_t ep_desc;
|
||||
uint8_t raw[len];
|
||||
} buf, *p;
|
||||
|
||||
// usb_interface_descriptor
|
||||
|
||||
if(rcode = usb_get_conf_descr(dev, len, conf, &buf.conf_desc))
|
||||
return rcode;
|
||||
|
||||
/* scan through all descriptors */
|
||||
p = &buf;
|
||||
while(len > 0) {
|
||||
switch(p->conf_desc.bDescriptorType) {
|
||||
case USB_DESCRIPTOR_CONFIGURATION:
|
||||
// we already had this, so we simply ignore it
|
||||
break;
|
||||
|
||||
case USB_DESCRIPTOR_INTERFACE:
|
||||
usb_dump_interface_descriptor(&p->iface_desc);
|
||||
break;
|
||||
|
||||
case USB_DESCRIPTOR_ENDPOINT:
|
||||
usb_dump_endpoint_descriptor(&p->ep_desc);
|
||||
break;
|
||||
|
||||
default:
|
||||
hid_debugf("unsupported descriptor type %d size %d", p->raw[1], p->raw[0]);
|
||||
}
|
||||
|
||||
// advance to next descriptor
|
||||
len -= p->conf_desc.bLength;
|
||||
p = (union buf_u*)(p->raw + p->conf_desc.bLength);
|
||||
}
|
||||
|
||||
if(len != 0) {
|
||||
hid_debugf("Config underrun: %d", len);
|
||||
return USB_ERROR_CONFIGURAION_SIZE_MISMATCH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t usb_xbox_init(usb_device_t *dev) {
|
||||
uint8_t rcode;
|
||||
uint16_t pid;
|
||||
uint16_t vid;
|
||||
|
||||
union {
|
||||
usb_device_descriptor_t dev_desc;
|
||||
usb_configuration_descriptor_t conf_desc;
|
||||
} buf;
|
||||
|
||||
union {
|
||||
usb_string0_descriptor_t str0_desc;
|
||||
usb_string_descriptor_t str_desc;
|
||||
uint8_t buf[255];
|
||||
} str;
|
||||
|
||||
dev->xbox_info.bPollEnable = false;
|
||||
usb_debugf("%s(%x)", __FUNCTION__, dev->bAddress);
|
||||
|
||||
if(rcode = usb_get_dev_descr( dev, sizeof(usb_device_descriptor_t), &buf.dev_desc ))
|
||||
return rcode;
|
||||
usb_dump_device_descriptor(&buf.dev_desc);
|
||||
|
||||
vid = buf.dev_desc.idVendor;
|
||||
pid = buf.dev_desc.idProduct;
|
||||
|
||||
if(vid != XBOX_VID && vid != MADCATZ_VID && vid != JOYTECH_VID && vid != GAMESTOP_VID) {// Check VID
|
||||
usb_debugf("Not a XBOX VID (%04x)", vid);
|
||||
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
|
||||
}
|
||||
if(pid == XBOX_WIRELESS_PID) {
|
||||
iprintf("You have plugged in a wireless Xbox 360 controller - it doesn't support USB communication\n");
|
||||
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
|
||||
}
|
||||
if(pid == XBOX_WIRELESS_RECEIVER_PID || pid == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) {
|
||||
iprintf("Only Xbox 360 controllers via USB are supported\n");
|
||||
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
|
||||
}
|
||||
if(pid != XBOX_WIRED_PID && pid != MADCATZ_WIRED_PID && pid != GAMESTOP_WIRED_PID && pid != AFTERGLOW_WIRED_PID && pid != JOYTECH_WIRED_PID) {// Check PID
|
||||
usb_debugf("Not a XBOX PID");
|
||||
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
// get the language descriptor 0, Retroflag classic USB joystick doesn't work without querying it
|
||||
if (!usb_get_string_descr(dev, sizeof(str), 0, 0, &str.str_desc)) { // supported languages descriptor
|
||||
uint16_t wLangId = str.str0_desc.wLANGID[0];
|
||||
iprintf("XBOX: wLangId: %04X\n", wLangId);
|
||||
}
|
||||
|
||||
if(rcode = usb_get_conf_descr(dev, sizeof(usb_configuration_descriptor_t), 0, &buf.conf_desc))
|
||||
return rcode;
|
||||
|
||||
usb_dump_conf_descriptor(&buf.conf_desc);
|
||||
|
||||
// Skip parsing the interface and endpoint descriptors, and use known values */
|
||||
//usb_xbox_parse_conf(dev, 0, buf.conf_desc.wTotalLength);
|
||||
dev->xbox_info.interval = 4;
|
||||
dev->xbox_info.inEp.epAddr = 0x01;
|
||||
dev->xbox_info.inEp.maxPktSize = XBOX_EP_MAXPKTSIZE;
|
||||
dev->xbox_info.inEp.bmNakPower = USB_NAK_NOWAIT;
|
||||
dev->xbox_info.inEp.bmSndToggle = 0;
|
||||
dev->xbox_info.inEp.bmRcvToggle = 0;
|
||||
dev->xbox_info.qNextPollTime = 0;
|
||||
|
||||
// Set Configuration Value
|
||||
if(rcode = usb_set_conf(dev, buf.conf_desc.bConfigurationValue)) {
|
||||
iprintf("XBOX: error setting conf value (%d)\n", rcode);
|
||||
return rcode;
|
||||
}
|
||||
dev->xbox_info.vid = vid;
|
||||
dev->xbox_info.pid = pid;
|
||||
dev->xbox_info.jindex = joystick_add();
|
||||
dev->xbox_info.bPollEnable = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t usb_xbox_release(usb_device_t *dev) {
|
||||
joystick_release(dev->xbox_info.jindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define swp2(a, msk) (((a & msk)<<1 | (a & msk)>>1) & msk)
|
||||
static void usb_xbox_read_report(usb_device_t *dev, uint16_t len, uint8_t *buf) {
|
||||
if(!buf) return;
|
||||
// hexdump(buf, len, 0);
|
||||
if(buf[0] != 0x00 || buf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t buttons = (swp2(buf[2], 0xc) >> 2) | (swp2(buf[2], 0x3) << 2) | swp2(buf[3], 0x30) | (swp2(buf[2], 0x30) << 2) | ((buf[3] & 0x03) << 10) | (swp2(buf[3], 0xc0) << 2);
|
||||
uint8_t idx = dev->xbox_info.jindex;
|
||||
StateUsbIdSet(dev->xbox_info.vid, dev->xbox_info.pid, 8, idx);
|
||||
|
||||
/*
|
||||
TODO: handle analogue parts
|
||||
hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]);
|
||||
hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]);
|
||||
hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]);
|
||||
hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]);
|
||||
*/
|
||||
|
||||
// map virtual joypad
|
||||
|
||||
if(buttons != dev->xbox_info.oldButtons) {
|
||||
StateUsbJoySet(buttons, buttons>>8, idx);
|
||||
uint16_t vjoy = virtual_joystick_mapping(dev->xbox_info.vid, dev->xbox_info.pid, buttons);
|
||||
|
||||
StateJoySet(vjoy, idx);
|
||||
StateJoySetExtra( vjoy>>8, idx);
|
||||
|
||||
// swap joystick 0 and 1 since 1 is the one.
|
||||
// used primarily on most systems (most = Amiga and ST...need to get rid of this)
|
||||
if(idx == 0) idx = 1;
|
||||
else if(idx == 1) idx = 0;
|
||||
// if real DB9 mouse is preffered, switch the id back to 1
|
||||
idx = (idx == 0) && mist_cfg.joystick0_prefer_db9 ? 1 : idx;
|
||||
|
||||
user_io_digital_joystick(idx, vjoy & 0xFF);
|
||||
// new API with all extra buttons
|
||||
user_io_digital_joystick_ext(idx, vjoy);
|
||||
|
||||
virtual_joystick_keyboard( vjoy );
|
||||
|
||||
dev->xbox_info.oldButtons = buttons;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t usb_xbox_poll(usb_device_t *dev) {
|
||||
|
||||
if(!dev->xbox_info.bPollEnable)
|
||||
return 0;
|
||||
if (dev->xbox_info.qNextPollTime <= timer_get_msec()) {
|
||||
uint16_t read = dev->xbox_info.inEp.maxPktSize;
|
||||
uint8_t buf[dev->xbox_info.inEp.maxPktSize];
|
||||
// clear buffer
|
||||
memset(buf, 0, dev->xbox_info.inEp.maxPktSize);
|
||||
uint8_t rcode = usb_in_transfer(dev, &(dev->xbox_info.inEp), &read, buf);
|
||||
if (rcode) {
|
||||
if (rcode != hrNAK)
|
||||
usb_debugf("%s() error: %d", __FUNCTION__, rcode);
|
||||
} else {
|
||||
usb_xbox_read_report(dev, read, buf);
|
||||
}
|
||||
dev->xbox_info.qNextPollTime = timer_get_msec() + dev->xbox_info.interval; // poll at requested rate
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const usb_device_class_config_t usb_xbox_class = {
|
||||
usb_xbox_init, usb_xbox_release, usb_xbox_poll };
|
||||
68
usb/xboxusb.h
Normal file
68
usb/xboxusb.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
This file is part of MiST-firmware
|
||||
|
||||
MiST-firmware 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
MiST-firmware is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Based on the work of
|
||||
|
||||
Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _xboxusb_h_
|
||||
#define _xboxusb_h_
|
||||
|
||||
/* Data Xbox 360 taken from descriptors */
|
||||
#define XBOX_EP_MAXPKTSIZE 32 // max size for data via USB
|
||||
|
||||
/* Names we give to the 3 Xbox360 pipes */
|
||||
#define XBOX_CONTROL_PIPE 0
|
||||
#define XBOX_INPUT_PIPE 1
|
||||
#define XBOX_OUTPUT_PIPE 2
|
||||
|
||||
// PID and VID of the different devices
|
||||
#define XBOX_VID 0x045E // Microsoft Corporation
|
||||
#define MADCATZ_VID 0x1BAD // For unofficial Mad Catz controllers
|
||||
#define JOYTECH_VID 0x162E // For unofficial Joytech controllers
|
||||
#define GAMESTOP_VID 0x0E6F // Gamestop controller
|
||||
|
||||
#define XBOX_WIRED_PID 0x028E // Microsoft 360 Wired controller
|
||||
#define XBOX_WIRELESS_PID 0x028F // Wireless controller only support charging
|
||||
#define XBOX_WIRELESS_RECEIVER_PID 0x0719 // Microsoft Wireless Gaming Receiver
|
||||
#define XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID 0x0291 // Third party Wireless Gaming Receiver
|
||||
#define MADCATZ_WIRED_PID 0xF016 // Mad Catz wired controller
|
||||
#define JOYTECH_WIRED_PID 0xBEEF // For Joytech wired controller
|
||||
#define GAMESTOP_WIRED_PID 0x0401 // Gamestop wired controller
|
||||
#define AFTERGLOW_WIRED_PID 0x0213 // Afterglow wired controller - it uses the same VID as a Gamestop controller
|
||||
|
||||
#define XBOX_REPORT_BUFFER_SIZE 14 // Size of the input report buffer
|
||||
|
||||
#define XBOX_MAX_ENDPOINTS 3
|
||||
|
||||
typedef struct {
|
||||
bool bPollEnable; // poll enable flag
|
||||
uint16_t vid;
|
||||
uint16_t pid;
|
||||
uint8_t interval;
|
||||
uint32_t oldButtons;
|
||||
uint32_t qNextPollTime; // next poll time
|
||||
ep_t inEp;
|
||||
uint16_t jindex;
|
||||
} usb_xbox_info_t;
|
||||
|
||||
// interface to usb core
|
||||
extern const usb_device_class_config_t usb_xbox_class;
|
||||
|
||||
#endif
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "cue_parser.h"
|
||||
#include "utils.h"
|
||||
#include "usb/joymapping.h"
|
||||
#include "usb/joystick.h"
|
||||
|
||||
// up to 16 key can be remapped
|
||||
#define MAX_REMAP 16
|
||||
@@ -593,7 +594,7 @@ void user_io_eth_send_rx_frame(uint8_t *s, uint16_t len) {
|
||||
// (mouse port)
|
||||
|
||||
static uint8_t joystick_renumber(uint8_t j) {
|
||||
uint8_t usb_sticks = hid_get_joysticks();
|
||||
uint8_t usb_sticks = joystick_count();
|
||||
|
||||
// no usb sticks present: no changes are being made
|
||||
if(!usb_sticks) return j;
|
||||
@@ -1174,7 +1175,7 @@ void user_io_poll() {
|
||||
|
||||
uint8_t idx = joystick_renumber(0);
|
||||
if (!user_io_osd_is_visible()) user_io_joystick(idx, joy_map);
|
||||
StateJoySet(joy_map, mist_cfg.joystick_db9_fixed_index ? idx : hid_get_joysticks()); // send to OSD
|
||||
StateJoySet(joy_map, mist_cfg.joystick_db9_fixed_index ? idx : joystick_count()); // send to OSD
|
||||
virtual_joystick_keyboard(joy_map);
|
||||
}
|
||||
if(GetDB9(1, &joy_map)) {
|
||||
@@ -1183,7 +1184,7 @@ void user_io_poll() {
|
||||
|
||||
uint8_t idx = joystick_renumber(1);
|
||||
if (!user_io_osd_is_visible()) user_io_joystick(idx, joy_map);
|
||||
StateJoySet(joy_map, mist_cfg.joystick_db9_fixed_index ? idx : hid_get_joysticks() + 1); // send to OSD
|
||||
StateJoySet(joy_map, mist_cfg.joystick_db9_fixed_index ? idx : joystick_count() + 1); // send to OSD
|
||||
virtual_joystick_keyboard(joy_map);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user