Skip to content

Commit

Permalink
Original Xbox support matlo/GIMX#218
Browse files Browse the repository at this point in the history
  • Loading branch information
matlo committed Dec 17, 2019
1 parent ea49739 commit 7d0059f
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 38 deletions.
2 changes: 1 addition & 1 deletion EMUXBOX/Config/LUFAConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
#define USE_FLASH_DESCRIPTORS
// #define USE_EEPROM_DESCRIPTORS
// #define NO_INTERNAL_SERIAL
#define FIXED_CONTROL_ENDPOINT_SIZE 64
#define FIXED_CONTROL_ENDPOINT_SIZE 8
// #define DEVICE_STATE_AS_GPIOR {Insert Value Here}
#define FIXED_NUM_CONFIGURATIONS 1
// #define CONTROL_ONLY_DEVICE
Expand Down
6 changes: 3 additions & 3 deletions EMUXBOX/Descriptors.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,16 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
{
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},

.USBSpecification = VERSION_BCD(01.10),
.USBSpecification = 0x0110,
.Class = 0x00,
.SubClass = 0x00,
.Protocol = 0x00,

.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,

.VendorID = 0x045e,
.ProductID = 0x0202,
.ReleaseNumber = 0x0100,
.ProductID = 0x0289,
.ReleaseNumber = 0x0120,

.ManufacturerStrIndex = 0x00,
.ProductStrIndex = 0x00,
Expand Down
2 changes: 1 addition & 1 deletion EMUXBOX/Descriptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@

/* Macros: */
/** Endpoint number of the Xbox HID reporting IN endpoint. */
#define XBOX_IN_EPNUM (ENDPOINT_DIR_IN | 2)
#define XBOX_IN_EPNUM (ENDPOINT_DIR_IN | 1)

/** Endpoint number of the Xbox HID reporting OUT endpoint. */
#define XBOX_OUT_EPNUM (ENDPOINT_DIR_OUT | 2)
Expand Down
170 changes: 137 additions & 33 deletions EMUXBOX/xbox_emu.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2013 Mathieu Laurendeau (mat.lau [at] laposte [dot] net)
Copyright 2019 Mathieu Laurendeau (mat.lau [at] laposte [dot] net)
Redistributed under the GPLv3 licence.
Expand Down Expand Up @@ -30,18 +30,19 @@

/** \file
*
* Main source file for the Xbox v1 controller. This file contains the main tasks and
* Main source file for the controller. This file contains the main tasks and
* is responsible for the initial application hardware configuration.
*/

#include "xbox_emu.h"
#include <LUFA/Drivers/Peripheral/Serial.h>
#include "../adapter_protocol.h"

#define USART_BAUDRATE 500000

#define MAX_CONTROL_TRANSFER_SIZE 64

#define USART_BAUDRATE 500000
#define USART_DOUBLE_SPEED false

/*
* The report data.
* see https://euc.jp/periphs/xbox-controller.ja.html
Expand Down Expand Up @@ -77,12 +78,22 @@ static uint8_t* pdata;
static unsigned char i = 0;

/*
* These variables are used in both the main and serial interrupt,
* These variables are used in both the main and the serial interrupt,
* therefore they have to be declared as volatile.
*/
static volatile unsigned char sendReport = 0;
static volatile unsigned char sendReport = 1; // first input report is above
static volatile unsigned char started = 0;
static volatile unsigned char packet_type = 0;
static volatile unsigned char value_len = 0;
static volatile unsigned char initialized = 0; // inhibit further input reports until requested on control endpoint

void forceHardReset(void)
{
LEDs_TurnOnLEDs(LEDS_ALL_LEDS);
cli(); // disable interrupts
wdt_enable(WDTO_15MS); // enable watchdog
while(1); // wait for watchdog to reset processor
}

static inline int16_t Serial_BlockingReceiveByte(void)
{
Expand Down Expand Up @@ -114,13 +125,21 @@ static inline void handle_packet(void)
Serial_SendByte(BYTE_TYPE_XBOX);
break;
case BYTE_STATUS:
Serial_SendByte(BYTE_STATUS);
Serial_SendByte(BYTE_LEN_1_BYTE);
Serial_SendByte(started);
break;
case BYTE_START:
Serial_SendByte(BYTE_START);
Serial_SendByte(BYTE_LEN_1_BYTE);
Serial_SendByte(started);
started = 1;
break;
case BYTE_CONTROL_DATA:
case BYTE_RESET:
forceHardReset();
break;
case BYTE_IN_REPORT:
sendReport = 1;
sendReport |= initialized;
//no answer
break;
}
Expand All @@ -132,7 +151,7 @@ ISR(USART1_RX_vect)
{
packet_type = UDR1;
value_len = Serial_BlockingReceiveByte();
if(packet_type == BYTE_IN_REPORT)
if(packet_type == BYTE_IN_REPORT && initialized)
{
pdata = report;
}
Expand All @@ -150,7 +169,7 @@ ISR(USART1_RX_vect)

void serial_init(void)
{
Serial_Init(USART_BAUDRATE, false);
Serial_Init(USART_BAUDRATE, USART_DOUBLE_SPEED);

UCSR1B |= (1 << RXCIE1); // Enable the USART Receive Complete interrupt (USART_RXC)
}
Expand All @@ -172,6 +191,8 @@ void SetupHardware(void)
/* Hardware Initialization */
LEDs_Init();

while(!started);

USB_Init();
}

Expand Down Expand Up @@ -205,23 +226,83 @@ void EVENT_USB_Device_ConfigurationChanged(void)
//LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}

/*if (!(Endpoint_ConfigureEndpoint(XBOX_OUT_EPNUM, EP_TYPE_INTERRUPT,
ENDPOINT_DIR_OUT, XBOX_EPSIZE,
ENDPOINT_BANK_SINGLE)))
{
//LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}*/
if (!(Endpoint_ConfigureEndpoint(XBOX_OUT_EPNUM, EP_TYPE_INTERRUPT, XBOX_EPSIZE, 1)))
{
//LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}

//USB_Device_EnableSOFEvents();
}

const char PROGMEM vendor1[] =
{
0x10, 0x42, 0x00, 0x01, 0x01, 0x02, 0x14, 0x06,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

const char PROGMEM vendor2[] =
{
0x00, 0x06, 0xff, 0xff, 0xff, 0xff
};

const char PROGMEM vendor3[] =
{
0x00, 0x14, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff
};

/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
* the device from the USB host before passing along unhandled control requests to the library for processing
* internally.
*/
void EVENT_USB_Device_ControlRequest(void)
{

Serial_SendByte(BYTE_DEBUG);
Serial_SendByte(sizeof(USB_ControlRequest));
Serial_SendData(&USB_ControlRequest, sizeof(USB_ControlRequest));

if(USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_INTERFACE))
{
if (USB_ControlRequest.bRequest == 6) // vendor-defined request
{
if (USB_ControlRequest.wValue == 0x4200)
{
Endpoint_ClearSETUP();
Endpoint_Write_Control_PStream_LE(vendor1, USB_ControlRequest.wLength);
Endpoint_ClearOUT();
}
}
else if (USB_ControlRequest.bRequest == REQ_GetReport)
{
if (USB_ControlRequest.wValue == 0x0200)
{
Endpoint_ClearSETUP();
Endpoint_Write_Control_PStream_LE(vendor2, USB_ControlRequest.wLength);
Endpoint_ClearOUT();
}
else if (USB_ControlRequest.wValue == 0x0100)
{
Endpoint_ClearSETUP();
Endpoint_Write_Control_PStream_LE(vendor3, USB_ControlRequest.wLength);
Endpoint_ClearOUT();
}
}
}
else if(USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
if (USB_ControlRequest.bRequest == REQ_GetReport)
{
if (USB_ControlRequest.wValue == 0x0100)
{
report[12] = report[14] = report[16] = report[18] = 0x80;
Endpoint_ClearSETUP();
Endpoint_Write_Control_Stream_LE(report, USB_ControlRequest.wLength);
Endpoint_ClearOUT();
initialized = 1;
}
}
}
}

/** Event handler for the USB device Start Of Frame event. */
Expand Down Expand Up @@ -258,22 +339,45 @@ void SendNextReport(void)
/** Reads the next OUT report from the host from the OUT endpoint, if one has been sent. */
void ReceiveNextReport(void)
{
/* Select the OUT Report Endpoint */
Endpoint_SelectEndpoint(XBOX_OUT_EPNUM);

/* Check if OUT Endpoint contains a packet */
if (Endpoint_IsOUTReceived())
{
/* Check to see if the packet contains data */
if (Endpoint_IsReadWriteAllowed())
{
/* Discard data */
Endpoint_Discard_Stream(6, NULL);
}

/* Handshake the OUT Endpoint - clear endpoint and ready for next report */
Endpoint_ClearOUT();
}
static struct
{
struct
{
unsigned char type;
unsigned char length;
} header;
unsigned char buffer[XBOX_EPSIZE];
} packet = { .header.type = BYTE_OUT_REPORT };

uint16_t length = 0;

/* Select the OUT Report Endpoint */
Endpoint_SelectEndpoint(XBOX_OUT_EPNUM);

/* Check if OUT Endpoint contains a packet */
if (Endpoint_IsOUTReceived())
{

/* Check to see if the packet contains data */
if (Endpoint_IsReadWriteAllowed())
{
/* Read OUT Report Data */
uint8_t ErrorCode = Endpoint_Read_Stream_LE(packet.buffer, sizeof(packet.buffer), &length);
if (ErrorCode == ENDPOINT_RWSTREAM_NoError)
{
length = sizeof(packet.buffer);
}
}

/* Handshake the OUT Endpoint - clear endpoint and ready for next report */
Endpoint_ClearOUT();

if (length)
{
packet.header.length = length & 0xFF;
Serial_SendData(&packet, sizeof(packet.header) + packet.header.length);
}
}
}

/** Function to manage HID report generation and transmission to the host, when in report mode. */
Expand Down

0 comments on commit 7d0059f

Please sign in to comment.