Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <pspkernel.h>
- #include <pspsdk.h>
- #include <pspusb.h>
- #include <pspusbbus.h>
- #include <string.h>
- #include "descriptors.h"
- #include "usb.h"
- #include "psgroove.h"
- /********************************************************************************/
- /*------------------------------------------------------------------------------*/
- /* PsGroove Emulation */
- /*------------------------------------------------------------------------------*/
- /*------------------------------------------------------------------------------*/
- #define PORT_EMPTY 0x0100 /* powered only */
- #define PORT_FULL 0x0103 /* connected, enabled, powered, full-speed */
- #define C_PORT_CONN 0x0001 /* connection */
- #define C_PORT_RESET 0x0010 /* reset */
- #define C_PORT_NONE 0x0000 /* no change */
- unsigned short port_status[6] = { PORT_EMPTY, PORT_EMPTY, PORT_EMPTY, PORT_EMPTY, PORT_EMPTY, PORT_EMPTY };
- unsigned short port_change[6] = { C_PORT_NONE, C_PORT_NONE, C_PORT_NONE, C_PORT_NONE, C_PORT_NONE, C_PORT_NONE };
- enum {
- init,
- wait_hub_ready,
- hub_ready,
- p1_wait_reset,
- p1_wait_enumerate,
- p1_ready,
- p2_wait_reset,
- p2_wait_enumerate,
- p2_ready,
- p3_wait_reset,
- p3_wait_enumerate,
- p3_ready,
- p2_wait_disconnect,
- p4_wait_connect,
- p4_wait_reset,
- p4_wait_enumerate,
- p4_ready,
- p5_wait_reset,
- p5_wait_enumerate,
- p5_challenged,
- p5_responded,
- p3_wait_disconnect,
- p3_disconnected,
- p5_wait_disconnect,
- p5_disconnected,
- p4_wait_disconnect,
- p4_disconnected,
- p1_wait_disconnect,
- p1_disconnected,
- p6_wait_reset,
- p6_wait_enumerate,
- done,
- } state = init;
- unsigned char hub_int_response = 0x00;
- unsigned char hub_int_force_data0 = 0;
- int last_port_conn_clear = 0;
- int last_port_reset_clear = 0;
- unsigned char port_addr[7] = { -1, -1, -1, -1, -1, -1, -1 };
- unsigned char port_cur = -1;
- /*------------------------------------------------------------------------------*/
- /*------------------------------------------------------------------------------*/
- /*PsGroove_Timer */
- /*------------------------------------------------------------------------------*/
- volatile unsigned char expire = 0; /* counts down every 10 milliseconds */
- void PsGroove_Timer( void )
- {
- if (expire > 0)
- expire--;
- }
- /*------------------------------------------------------------------------------*/
- /*PsGroove_Panic */
- /*------------------------------------------------------------------------------*/
- void PsGroove_Panic()
- {
- //TODO: Don't Panic!
- }
- /*------------------------------------------------------------------------------*/
- /*PsGroove_Switch_Port */
- /*------------------------------------------------------------------------------*/
- void PsGroove_Switch_Port(int8_t port)
- {
- if (port_cur == port) return;
- port_cur = port;
- if (port_addr[port] < 0)
- port_addr[port] = 0;
- //TODO: I can't port this two lines
- //UDADDR = port_addr[port] & 0x7f;
- //UDADDR |= (1 << ADDEN);
- }
- /*------------------------------------------------------------------------------*/
- /*PsGroove_Connect_Port */
- /*------------------------------------------------------------------------------*/
- void PsGroove_Connect_Port(int port)
- {
- last_port_reset_clear = 0;
- hub_int_response = (1 << port);
- port_status[port - 1] = PORT_FULL;
- port_change[port - 1] = C_PORT_CONN;
- }
- /*------------------------------------------------------------------------------*/
- /*PsGroove_Disconnect_Port */
- /*------------------------------------------------------------------------------*/
- void PsGroove_Disconnect_Port(int port)
- {
- last_port_conn_clear = 0;
- hub_int_response = (1 << port);
- port_status[port - 1] = PORT_EMPTY;
- port_change[port - 1] = C_PORT_CONN;
- }
- /*------------------------------------------------------------------------------*/
- /*PsGroove_GetDescription */
- /*------------------------------------------------------------------------------*/
- unsigned short PsGroove_GetDescription(unsigned char DescriptorType, unsigned char DescriptorNumber, unsigned short wLength, const void** const DescriptorAddress)
- {
- void* Address = NULL;
- unsigned short Size = 0;
- switch(DescriptorType)
- {
- case 0x01: //DTYPE_Device
- switch (port_cur) {
- //case 0:
- // Address = (void *) HUB_Device_Descriptor;
- // Size = sizeof(HUB_Device_Descriptor);
- // break;
- case 1:
- Address = (void *) port1_device_descriptor;
- Size = sizeof(port1_device_descriptor);
- break;
- case 2:
- Address = (void *) port2_device_descriptor;
- Size = sizeof(port2_device_descriptor);
- break;
- case 3:
- Address = (void *) port3_device_descriptor;
- Size = sizeof(port3_device_descriptor);
- break;
- case 4:
- Address = (void *) port4_device_descriptor;
- Size = sizeof(port4_device_descriptor);
- break;
- case 5:
- Address = (void *) port5_device_descriptor;
- Size = sizeof(port5_device_descriptor);
- break;
- case 6:
- Address = (void *) port6_device_descriptor;
- Size = sizeof(port6_device_descriptor);
- break;
- }
- break;
- case 0x02: //DTYPE_Configuration
- switch (port_cur) {
- //case 0:
- // Address = (void *) HUB_Config_Descriptor;
- // Size = sizeof(HUB_Config_Descriptor);
- // break;
- case 1:
- // 4 configurations are the same.
- // For the initial 8-byte request, we give a different
- // length response than in the full request.
- if (DescriptorNumber < 4) {
- if (wLength == 8) {
- Address = (void *) port1_short_config_descriptor;
- Size = sizeof(port1_short_config_descriptor);
- } else {
- Address = (void *) port1_config_descriptor;
- Size = sizeof(port1_config_descriptor);
- }
- if (DescriptorNumber == 3 && wLength > 8) {
- state = p1_ready;
- expire = 10;
- }
- }
- break;
- case 2:
- // only 1 config
- Address = (void *) port2_config_descriptor;
- Size = sizeof(port2_config_descriptor);
- state = p2_ready;
- expire = 15;
- break;
- case 3:
- // 2 configurations are the same
- Address = (void *) port3_config_descriptor;
- Size = sizeof(port3_config_descriptor);
- if (DescriptorNumber == 1 && wLength > 8) {
- state = p3_ready;
- expire = 10;
- }
- break;
- case 4:
- // 3 configurations
- if (DescriptorNumber == 0) {
- Address = (void *) port4_config_descriptor_1;
- Size = sizeof(port4_config_descriptor_1);
- } else if (DescriptorNumber == 1) {
- if (wLength == 8) {
- Address = (void *) port4_short_config_descriptor_2;
- Size = sizeof(port4_short_config_descriptor_2);
- } else {
- Address = (void *) port4_config_descriptor_2;
- Size = sizeof(port4_config_descriptor_2);
- }
- } else if (DescriptorNumber == 2) {
- Address = (void *) port4_config_descriptor_3;
- Size = sizeof(port4_config_descriptor_3);
- if (wLength > 8) {
- state = p4_ready;
- expire = 20; // longer seems to help this one?
- }
- }
- break;
- case 5:
- // 1 config
- Address = (void *) port5_config_descriptor;
- Size = sizeof(port5_config_descriptor);
- break;
- case 6:
- // 1 config
- Address = (void *) port6_config_descriptor;
- Size = sizeof(port6_config_descriptor);
- break;
- }
- break;
- //case 0x29: // HUB descriptor (always to port 0 we'll assume)
- // switch (port_cur) {
- // case 0:
- // Address = (void *) HUB_Hub_Descriptor;
- // Size = sizeof(HUB_Hub_Descriptor);
- // break;
- // }
- // break;
- }
- return Size;
- }
- /*------------------------------------------------------------------------------*/
- /*PsGroove_UnhandledControlRequest */
- /*------------------------------------------------------------------------------*/
- void PsGroove_UnhandledControlRequest(struct DeviceRequest USB_ControlRequest)
- {
- if (port_cur == 6 && USB_ControlRequest.bRequest == 0xAA) {
- /* holy crap, it worked! */
- //Endpoint_ClearSETUP();
- //Endpoint_ClearIN();
- //Endpoint_ClearStatusStage();
- state = done;
- return;
- }
- if (port_cur == 5 && USB_ControlRequest.bRequest == 11 /*REQ_SetInterface*/)
- {
- /* can ignore this */
- //Endpoint_ClearSETUP();
- //Endpoint_ClearIN();
- //Endpoint_ClearStatusStage();
- return;
- }
- if (port_cur == 0 &&
- USB_ControlRequest.bmRequestType == 0xA0 &&
- USB_ControlRequest.bRequest == 0x00 && // GET HUB STATUS
- USB_ControlRequest.wValue == 0x00 &&
- USB_ControlRequest.wIndex == 0x00 &&
- USB_ControlRequest.wLength == 0x04) {
- //Endpoint_ClearSETUP();
- //Endpoint_Write_Word_LE(0x0000); // wHubStatus
- //Endpoint_Write_Word_LE(0x0000); // wHubChange
- //Endpoint_ClearIN();
- //Endpoint_ClearStatusStage();
- unsigned short Empty[] = {0x0000, 0x0000};
- UsbWriteData(Empty, 4); // wHubStatus, wHubChange
- return;
- }
- if (port_cur == 0 &&
- USB_ControlRequest.bmRequestType == 0xA3 &&
- USB_ControlRequest.bRequest == 0x00 && // GET PORT STATUS
- USB_ControlRequest.wValue == 0x00 &&
- USB_ControlRequest.wLength == 0x04) {
- unsigned char p = USB_ControlRequest.wIndex;
- if (p < 1 || p > 6) return;
- //Endpoint_ClearSETUP();
- //Endpoint_Write_Word_LE(port_status[p - 1]); // wHubStatus
- //Endpoint_Write_Word_LE(port_change[p - 1]); // wHubChange
- //Endpoint_ClearIN();
- //Endpoint_ClearStatusStage();
- unsigned char Package[] = {port_status[p - 1], port_status[p], port_change[p - 1], port_change[p]};
- UsbWriteData(Package, 4); // wHubStatus, wHubChange
- return;
- }
- if (port_cur == 0 &&
- USB_ControlRequest.bmRequestType == 0x23 &&
- USB_ControlRequest.bRequest == 0x03 && // SET_FEATURE
- USB_ControlRequest.wLength == 0x00) {
- unsigned char p = USB_ControlRequest.wIndex;
- if (p < 1 || p > 6) return;
- //Endpoint_ClearSETUP();
- //Endpoint_ClearIN();
- //Endpoint_ClearStatusStage();
- switch(USB_ControlRequest.wValue) {
- case 0x0008: // PORT_POWER
- if (p == 6 && state == init) {
- /* after the 6th port is powered, wait a bit and continue */
- state = hub_ready;
- expire = 15;
- }
- break;
- case 0x0004: // PORT_RESET
- hub_int_response = (1 << p);
- port_change[p - 1] |= C_PORT_RESET;
- break;
- }
- return;
- }
- if (port_cur == 0 &&
- USB_ControlRequest.bmRequestType == 0x23 &&
- USB_ControlRequest.bRequest == 0x01 && // CLEAR_FEATURE
- USB_ControlRequest.wLength == 0x00) {
- unsigned char p = USB_ControlRequest.wIndex;
- if (p < 1 || p > 6) return;
- //Endpoint_ClearSETUP();
- //Endpoint_ClearIN();
- //Endpoint_ClearStatusStage();
- switch(USB_ControlRequest.wValue) {
- case 0x0010: // C_PORT_CONNECTION
- port_change[p - 1] &= ~C_PORT_CONN;
- last_port_conn_clear = p;
- break;
- case 0x0014: // C_PORT_RESET
- port_change[p - 1] &= ~C_PORT_RESET;
- last_port_reset_clear = p;
- break;
- }
- return;
- }
- PsGroove_Panic();
- }
- /*------------------------------------------------------------------------------*/
- /*PsGroove_JIG_Task */
- /*------------------------------------------------------------------------------*/
- const unsigned char jig_response[64] = {
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xee, 0x78, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xee, 0x88,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x33, 0xe7, 0x20, 0xe8, 0x83, 0xff, 0xf0, 0xe8, 0x63, 0xff, 0xf8,
- 0xe8, 0xa3, 0x00, 0x18, 0x38, 0x63, 0x10, 0x00, 0x7c, 0x04, 0x28, 0x00, 0x40, 0x82, 0xff, 0xf4,
- 0x38, 0xc3, 0xf0, 0x20, 0x7c, 0xc9, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, 0x04, 0x00, 0x00, 0x00,
- };
- void PsGroove_JIG_Task(void)
- {
- static int bytes_out = 0, bytes_in = 0;
- unsigned char buffer[0x100];
- //Endpoint_Discard_Stream(8, NO_STREAM_CALLBACK);
- UsbReadData(buffer, 8);
- bytes_out += 8;
- if (bytes_out >= 64)
- {
- state = p5_challenged;
- expire = 50; // was 90
- }
- if (state == p5_challenged && expire == 0)
- {
- if (bytes_in < 64) {
- UsbWriteData(&jig_response[bytes_in], 8);
- bytes_in += 8;
- if (bytes_in >= 64) {
- state = p5_responded;
- expire = 15;
- }
- }
- }
- }
- /*------------------------------------------------------------------------------*/
- /*PsGroove_Start */
- /*------------------------------------------------------------------------------*/
- void PsGroove_Start()
- {
- //TODO: start the timer.... (PsGroove_Timer each 10 ms.)
- state = init;
- PsGroove_Switch_Port(0);
- for (;;)
- {
- /*if (port_cur == 0)
- HUB_Task();*/
- if (port_cur == 5)
- PsGroove_JIG_Task();
- // connect 1
- if (state == hub_ready && expire == 0)
- {
- PsGroove_Connect_Port(1);
- state = p1_wait_reset;
- }
- if (state == p1_wait_reset && last_port_reset_clear == 1)
- {
- PsGroove_Switch_Port(1);
- state = p1_wait_enumerate;
- }
- // connect 2
- if (state == p1_ready && expire == 0)
- {
- PsGroove_Switch_Port(0);
- PsGroove_Connect_Port(2);
- state = p2_wait_reset;
- }
- if (state == p2_wait_reset && last_port_reset_clear == 2)
- {
- PsGroove_Switch_Port(2);
- state = p2_wait_enumerate;
- }
- // connect 3
- if (state == p2_ready && expire == 0)
- {
- PsGroove_Switch_Port(0);
- PsGroove_Connect_Port(3);
- state = p3_wait_reset;
- }
- if (state == p3_wait_reset && last_port_reset_clear == 3)
- {
- PsGroove_Switch_Port(3);
- state = p3_wait_enumerate;
- }
- // disconnect 2
- if (state == p3_ready && expire == 0)
- {
- PsGroove_Switch_Port(0);
- PsGroove_Disconnect_Port(2);
- state = p2_wait_disconnect;
- }
- if (state == p2_wait_disconnect && last_port_conn_clear == 2)
- {
- state = p4_wait_connect;
- expire = 15;
- }
- // connect 4
- if (state == p4_wait_connect && expire == 0)
- {
- PsGroove_Connect_Port(4);
- state = p4_wait_reset;
- }
- if (state == p4_wait_reset && last_port_reset_clear == 4)
- {
- PsGroove_Switch_Port(4);
- state = p4_wait_enumerate;
- }
- // connect 5
- if (state == p4_ready && expire == 0)
- {
- PsGroove_Switch_Port(0);
- /* When first connecting port 5, we need to
- have the wrong data toggle for the PS3 to
- respond */
- hub_int_force_data0 = 1;
- PsGroove_Connect_Port(5);
- state = p5_wait_reset;
- }
- if (state == p5_wait_reset && last_port_reset_clear == 5)
- {
- PsGroove_Switch_Port(5);
- state = p5_wait_enumerate;
- }
- // disconnect 3
- if (state == p5_responded && expire == 0)
- {
- PsGroove_Switch_Port(0);
- /* Need wrong data toggle again */
- hub_int_force_data0 = 1;
- PsGroove_Disconnect_Port(3);
- state = p3_wait_disconnect;
- }
- if (state == p3_wait_disconnect && last_port_conn_clear == 3)
- {
- state = p3_disconnected;
- expire = 45;
- }
- // disconnect 5
- if (state == p3_disconnected && expire == 0)
- {
- PsGroove_Switch_Port(0);
- PsGroove_Disconnect_Port(5);
- state = p5_wait_disconnect;
- }
- if (state == p5_wait_disconnect && last_port_conn_clear == 5)
- {
- state = p5_disconnected;
- expire = 20;
- }
- // disconnect 4
- if (state == p5_disconnected && expire == 0)
- {
- PsGroove_Switch_Port(0);
- PsGroove_Disconnect_Port(4);
- state = p4_wait_disconnect;
- }
- if (state == p4_wait_disconnect && last_port_conn_clear == 4)
- {
- state = p4_disconnected;
- expire = 20;
- }
- // disconnect 1
- if (state == p4_disconnected && expire == 0)
- {
- PsGroove_Switch_Port(0);
- PsGroove_Disconnect_Port(1);
- state = p1_wait_disconnect;
- }
- if (state == p1_wait_disconnect && last_port_conn_clear == 1)
- {
- state = p1_disconnected;
- expire = 20;
- }
- // connect 6
- if (state == p1_disconnected && expire == 0)
- {
- PsGroove_Switch_Port(0);
- PsGroove_Connect_Port(6);
- state = p6_wait_reset;
- }
- if (state == p6_wait_reset && last_port_reset_clear == 6)
- {
- PsGroove_Switch_Port(6);
- state = p6_wait_enumerate;
- }
- // done
- if (state == done)
- {
- //TODO: Great!
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement