142w ago -
Update:
chesteruhi has now made available a
PSGroove BlackCatUSB Fixed Leds hex code version recompiled with working leds- the blue led now lights up once exploit is running blue led turns off basically lets you know you did everything right.
We touched upon this in our
previous article, and now comes more details on a
PSGroove PS3 exploit port for BlackcatUSB devices alongside a few videos of it in action.
Courtesy of
chesteruhi comes the necessary
PSGroove BlackCatUSB hex code which he has
confirmed as working with
BlackcatUSB Flash Memory Programmers.
To quote: "All BlackcatUSBs (from version 1.2 on) use the same microcontroller (AT90USB162) and use the same software, drivers, and avr firmware. The only difference in the pcb versions is cosmetic.
So the BlackcatUSBs will all work no need to worry which one your buying, I have confirmed this. So purchase away before there all gone!
I have attached the blackcatusb hex for flashing and the manager pkg."
Following up on this news, Forum user
thinnpikkins has gave it a try and
shared two videos of it in action with us below along with the BlackcatUSB Flash Memory Programmer specs!
BlackcatUSB Flash Memory Programmers
Features:
• Fast 16MHz RISC processor
• 16KB programmable memory
• 2 DIP switches for mode changes
• Upgradeable firmware over USB
• On board reset button
• Universal CFI Flash programming support
• SPI Mode 0, 1, 2 compatible
• USB 1.1 / 2.0 compatible
This product includes:
• A BlackcatUSB Flash Programmer
• A standard USB A-B cable
• A 10-pin IDC interface jumper cable
• A 10-pin solderless adapter (not bulk packs)
• A regular 10-pin IDC header
• Free future software updates
• Free domestic and international shipping!
First downoad the FLIP Software here:http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3886
Second: You have to put your AT90USB device in programming mode: When you are ready to start programming the device you will need to do a hard reset of the AT90USBKey. To do a hard reset of the key do the following:
Press both “RST” and “HWB” push buttons down simultaneously
First release the “RST” push button
Then release the “HWB” push button
When this is done one of the following will likely occur:
a) You will be prompted for drivers for the new device.
b) The system will already support the device.
Case (b) is most likely going to occur if the device is left in its original configuration. To ensure that the device is in fact connected and detected, check the listing of devices on your machine.
Remaining piece of the flashing can be following from the guides section. Good Luck!
http://www.embeddedcomputers.net/products/BlackcatUSB/
I have attached a newer blackcatusb-fixed-leds hex for flashing and the manager pkg.
This hex is recompiled with working leds, the blue led now lights up once exploit is running blue led turns off "basically lets you know you did everything right"
Also thanks evilsperm for your well written instructions I have included these with the zip.
Thank You!
#include
#include
#include
#include
#include "descriptors.h"
#include "psgroove.h"
#define PSGROOVE_DRIVERNAME "PsGrooveDriver"
#define PSGROOVE_DRIVERPID (0x1C9)
/*------------------------------------------------------------------------------*/
/* USB driver define */
/*------------------------------------------------------------------------------*/
enum UsbEvents {
USB_EVENT_ATTACH = 1,
USB_EVENT_DETACH = 2,
USB_EVENT_ASYNC = 4,
USB_EVENT_CONNECT = 8,
USB_EVENT_ALL = 0xFFFFFFFF
};
enum UsbTransEvents {
USB_TRANSEVENT_BULKOUT_DONE = 1,
USB_TRANSEVENT_BULKIN_DONE = 2,
};
/*------------------------------------------------------------------------------*/
/* USB HUB device descriptor */
/*------------------------------------------------------------------------------*/
struct DeviceDescriptor devdesc_hub = {
.bLength = 0x12,
.bDescriptorType = 0x01,
.bcdUSB = 0x0002, //? 0x0200
.bDeviceClass = 0x09,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x01,
.bMaxPacketSize = 0x08,
.idVendor = 0xAAAA,
.idProduct = 0xCCCC,
.bcdDevice = 0x0001, //? 0x0100
.iManufacturer = 0x00,
.iProduct = 0x00,
.iSerialNumber = 0x00,
.bNumConfigurations = 0x01
};
/*------------------------------------------------------------------------------*/
/* USB HUB configuration descriptor */
/*------------------------------------------------------------------------------*/
struct ConfigDescriptor confdesc_hub = {
.bLength = 0x09,
.bDescriptorType = 0x02,
.wTotalLength = 0x1900, //? 0x0019
.bNumInterfaces = 0x01,
.bConfigurationValue = 0x01,
.iConfiguration = 0x00,
.bmAttributes = 0xE0,
.bMaxPower = 0x32
};
/*------------------------------------------------------------------------------*/
/* USB HUB interface descriptor */
/*------------------------------------------------------------------------------*/
struct InterfaceDescriptor interdesc_hub = {
.bLength = 0x09,
.bDescriptorType = 0x04,
.bInterfaceNumber = 0x00,
.bAlternateSetting = 0x00,
.bNumEndpoints = 0x01,
.bInterfaceClass = 0x09,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.iInterface = 0x00
};
/*------------------------------------------------------------------------------*/
/* USB HUB endpoint descriptor */
/*------------------------------------------------------------------------------*/
struct EndpointDescriptor endpdesc_hub = {
.bLength = 0x07,
.bDescriptorType = 0x05,
.bEndpointAddress = 0x81,
.bmAttributes = 0x03,
.wMaxPacketSize = 0x100,
.bInterval = 0x0C
};
/*------------------------------------------------------------------------------*/
/* USB HUB string description */
/*------------------------------------------------------------------------------*/
static struct StringDescriptor HUBStringDescriptor = { 0x09, 0x29, {0x06, 0xA9, 0x00, 0x32, 0x64, 0x00, 0xff} };
/*------------------------------------------------------------------------------*/
/* USB driver work */
/*------------------------------------------------------------------------------*/
static struct UsbEndpoint UsbEndpoint[3] = { {0,0,0}, {1,0,0}, {2,0,0} };
static struct UsbInterface UsbInterface = { 0xFFFFFFFF, 0, 1, }; //I don't know what is this
static struct UsbData UsbData[2];
static SceUID UsbMainEventFlag = -1;
static SceUID UsbTransEventFlag = -1;
static SceUID UsbMainSemaphore = -1;
static SceUID UsbMainThreadID = -1;
/*------------------------------------------------------------------------------*/
/* Pre declarations */
/*------------------------------------------------------------------------------*/
static int UsbMainThread( SceSize size, void *argp );
unsigned short PsGroove_GetDescription(unsigned char DescriptorType, unsigned char DescriptorNumber, unsigned short wLength, const void** const DescriptorAddress)
void PsGroove_UnhandledControlRequest(struct DeviceRequest USB_ControlRequest);
/*------------------------------------------------------------------------------*/
/* UsbRequest */
/*------------------------------------------------------------------------------*/
static int UsbRequest( int arg1, int arg2, struct DeviceRequest *req )
{
unsigned char DescriptorType = (req->wValue >> 8)
unsigned char DescriptorNumber = ((req->wValue && 0xFF)
unsigned short wLength = req->wLength;
void* DataAddress = NULL;
unsigned short size = 0;
if (req->bRequest == 0x06) {//GetDescriptor Request
if ( (size = psgroove_getDescription(DescriptorType, DescriptorNumber, wLength, &DataAddress)) > 0 )
if (UsbWriteData(DataAddress, size) < size)
return -1;
}
else { //Other request
PsGroove_UnhandledControlRequest(*req);
}
return( 0 );
}
/*------------------------------------------------------------------------------*/
/* UsbUnknown */
/*------------------------------------------------------------------------------*/
static int UsbUnknown( int arg1, int arg2, int arg3 )
{
return( 0 );
}
/*------------------------------------------------------------------------------*/
/* UsbAttach */
/*------------------------------------------------------------------------------*/
static int UsbAttach( int speed, void *arg2, void *arg3 )
{
sceKernelSetEventFlag( UsbMainEventFlag, USB_EVENT_ATTACH );
return( 0 );
}
/*------------------------------------------------------------------------------*/
/* UsbDetach */
/*------------------------------------------------------------------------------*/
static int UsbDetach( int arg1, int arg2, int arg3 )
{
DisplayEnable();
sceKernelSetEventFlag( UsbMainEventFlag, USB_EVENT_DETACH );
return( 0 );
}
/*------------------------------------------------------------------------------*/
/* UsbStartFunc */
/*------------------------------------------------------------------------------*/
static int UsbStartFunc( int size, void *p )
{
memset( UsbData, 0, sizeof(UsbData) );
memcpy( UsbData[0].devdesc, &devdesc_hub, sizeof(devdesc_hub) );
UsbData[0].config.pconfdesc = &UsbData[0].confdesc;
UsbData[0].config.pinterfaces = &UsbData[0].interfaces;
UsbData[0].config.pinterdesc = &UsbData[0].interdesc;
UsbData[0].config.pendp = &UsbData[0].endp[0];
memcpy( UsbData[0].confdesc.desc, &confdesc_hub, sizeof(confdesc_hub) );
UsbData[0].confdesc.pinterfaces = &UsbData[0].interfaces;
UsbData[0].interfaces.pinterdesc[0] = &UsbData[0].interdesc;
UsbData[0].interfaces.intcount = 1;
memcpy( UsbData[0].interdesc.desc, &interdesc_hub, sizeof(interdesc_hub) );
UsbData[0].interdesc.pendp = &UsbData[0].endp[0];
memcpy( UsbData[0].endp[0].desc, &endpdesc_hhub, sizeof(endpdesc_hub) );
//memcpy( UsbData[0].endp[1].desc, &endpdesc_hi[1], sizeof(endpdesc_hub[1]) );
//memcpy( UsbData[0].endp[2].desc, &endpdesc_hi[2], sizeof(endpdesc_hub[2]) );
memcpy( UsbData[1].devdesc, &devdesc_hub, sizeof(devdesc_hub) );
UsbData[1].config.pconfdesc = &UsbData[0].confdesc;
UsbData[1].config.pinterfaces = &UsbData[0].interfaces;
UsbData[1].config.pinterdesc = &UsbData[0].interdesc;
UsbData[1].config.pendp = &UsbData[0].endp[0];
memcpy( UsbData[1].confdesc.desc, &confdesc_hub, sizeof(confdesc_hub) );
UsbData[1].confdesc.pinterfaces = &UsbData[0].interfaces;
UsbData[1].interfaces.pinterdesc[0] = &UsbData[0].interdesc;
UsbData[1].interfaces.intcount = 1;
memcpy( UsbData[1].interdesc.desc, &interdesc_hub, sizeof(interdesc_hub) );
UsbData[1].interdesc.pendp = &UsbData[0].endp[0];
memcpy( UsbData[1].endp[0].desc, &endpdesc_hhub, sizeof(endpdesc_hub) );
//memcpy( UsbData[1].endp[1].desc, &endpdesc_hi[1], sizeof(endpdesc_hub[1]) );
//memcpy( UsbData[1].endp[2].desc, &endpdesc_hi[2], sizeof(endpdesc_hub[2]) );
UsbMainEventFlag = sceKernelCreateEventFlag( "USBMainEvent", 0x200, 0, NULL );
if ( UsbMainEventFlag < 0 ){ return( -1 ); }
UsbTransEventFlag = sceKernelCreateEventFlag( "USBEventTrans", 0x200, 0, NULL );
if ( UsbTransEventFlag < 0 ){ return( -1 ); }
UsbMainSemaphore = sceKernelCreateSema( "USBSemaphore", 0, 1, 1, NULL );
if ( UsbMainSemaphore < 0 ){ return( -1 ); }
UsbMainThreadID = sceKernelCreateThread( "USBMainThread", UsbMainThread, 10, 0x10000, 0, NULL );
if ( UsbMainThreadID < 0 ){ return( -1 ); }
sceKernelStartThread( UsbMainThreadID, 0, NULL );
return( 0 );
}
/*------------------------------------------------------------------------------*/
/* UsbStopFunc */
/*------------------------------------------------------------------------------*/
static int UsbStopFunc( int size, void *p )
{
if ( UsbMainThreadID >= 0 ){ sceKernelTerminateDeleteThread( UsbMainThreadID ); }
UsbMainThreadID = -1;
if ( UsbMainEventFlag >= 0 ){ sceKernelDeleteEventFlag( UsbMainEventFlag ); }
UsbMainEventFlag = -1;
if ( UsbTransEventFlag >= 0 ){ sceKernelDeleteEventFlag( UsbTransEventFlag ); }
UsbTransEventFlag = -1;
if ( UsbMainSemaphore >= 0 ){ sceKernelDeleteSema( UsbMainSemaphore ); }
UsbMainSemaphore = -1;
return( 0 );
}
/*------------------------------------------------------------------------------*/
/* USB driver structure */
/*------------------------------------------------------------------------------*/
struct UsbDriver UsbDriver = {
PSGROOVE_DRIVERNAME,
4,
UsbEndpoint,
&UsbInterface,
&UsbData[0].devdesc[0],
&UsbData[0].config,
&UsbData[1].devdesc[0],
&UsbData[1].config,
&StringDescriptor,
UsbRequest,
UsbUnknown,
UsbAttach,
UsbDetach,
0,
UsbStartFunc,
UsbStopFunc,
NULL
};
/********************************************************************************/
/*------------------------------------------------------------------------------*/
/* usb thread work */
/*------------------------------------------------------------------------------*/
static int UsbReady = 0;
static struct UsbdDeviceReq UsbBulkinReq;
static struct UsbdDeviceReq UsbBulkoutReq;
static char UsbBuff[64*1024] __attribute__((aligned(64)));
static char UsbAsyncBuff[512] __attribute__((aligned(64)));
/*------------------------------------------------------------------------------*/
/* UsbBulkinReqDone */
/*------------------------------------------------------------------------------*/
static int UsbBulkinReqDone( struct UsbdDeviceReq *req, int arg2, int arg3 )
{
sceKernelSetEventFlag( UsbTransEventFlag, USB_TRANSEVENT_BULKIN_DONE );
return( 0 );
}
/*------------------------------------------------------------------------------*/
/* SetUsbBulkinReq */
/*------------------------------------------------------------------------------*/
static int SetUsbBulkinReq( void *data, int size )
{
sceKernelDcacheWritebackRange( data, size );
memset( &UsbBulkinReq, 0, sizeof(UsbBulkinReq) );
UsbBulkinReq.endp = &UsbEndpoint[1];
UsbBulkinReq.data = data;
UsbBulkinReq.size = size;
UsbBulkinReq.func = UsbBulkinReqDone;
sceKernelClearEventFlag( UsbTransEventFlag, ~USB_TRANSEVENT_BULKIN_DONE );
return( sceUsbbdReqSend( &UsbBulkinReq ) );
}
/*------------------------------------------------------------------------------*/
/* UsbBulkoutReqDone */
/*------------------------------------------------------------------------------*/
static int UsbBulkoutReqDone( struct UsbdDeviceReq *req, int arg2, int arg3 )
{
sceKernelSetEventFlag( UsbTransEventFlag, USB_TRANSEVENT_BULKOUT_DONE );
return( 0 );
}
/*------------------------------------------------------------------------------*/
/* SetUsbBulkoutReq */
/*------------------------------------------------------------------------------*/
static int SetUsbBulkoutReq( void *data, int size )
{
u32 upper_size = (size + 0x3F) & 0xFFFFFFC0;
sceKernelDcacheInvalidateRange( data, upper_size );
memset( &UsbBulkoutReq, 0, sizeof(UsbBulkoutReq) );
UsbBulkoutReq.endp = &UsbEndpoint[2];
UsbBulkoutReq.data = data;
UsbBulkoutReq.size = size;
UsbBulkoutReq.func = UsbBulkoutReqDone;
sceKernelClearEventFlag( UsbTransEventFlag, ~USB_TRANSEVENT_BULKOUT_DONE );
return( sceUsbbdReqRecv( &UsbBulkoutReq ) );
}
/*------------------------------------------------------------------------------*/
/* UsbReadData */
/*------------------------------------------------------------------------------*/
static int UsbReadData( void *data, int data_size )
{
u32 result;
int read_size = 0;
while ( read_size < data_size ){
int rest_size = data_size - read_size;
if ( rest_size > sizeof(UsbBuff) ){ rest_size = sizeof(UsbBuff); }
SetUsbBulkoutReq( UsbBuff, rest_size );
int ret = sceKernelWaitEventFlag( UsbTransEventFlag, USB_TRANSEVENT_BULKOUT_DONE,
PSP_EVENT_WAITOR | PSP_EVENT_WAITCLEAR, &result, NULL );
if ( ret == 0 ){
if ( (UsbBulkoutReq.retcode == 0) && (UsbBulkoutReq.recvsize > 0) ){
read_size += UsbBulkoutReq.recvsize;
memcpy( data, UsbBuff, UsbBulkoutReq.recvsize );
data += UsbBulkoutReq.recvsize;
} else {
return( -1 );
}
} else {
return( -1 );
}
}
return( read_size );
}
/*------------------------------------------------------------------------------*/
/* UsbWriteData */
/*------------------------------------------------------------------------------*/
static int UsbWriteData( const void *data, int data_size )
{
u32 result;
int write_size = 0;
if ( (u32)data & 0x3F ){
while ( write_size < data_size ){
int rest_size = data_size - write_size;
if ( rest_size > sizeof(UsbBuff) ){ rest_size = sizeof(UsbBuff); }
memcpy( UsbBuff, data, rest_size );
SetUsbBulkinReq( UsbBuff, rest_size );
int ret = sceKernelWaitEventFlag( UsbTransEventFlag, USB_TRANSEVENT_BULKIN_DONE,
PSP_EVENT_WAITOR | PSP_EVENT_WAITCLEAR, &result, NULL );
if ( ret == 0 ){
if ( (UsbBulkinReq.retcode == 0) && (UsbBulkinReq.recvsize > 0) ){
write_size += UsbBulkinReq.recvsize;
data += UsbBulkinReq.recvsize;
} else {
return( -1 );
}
} else {
return( -1 );
}
}
} else {
while ( write_size < data_size ){
int rest_size = data_size - write_size;
if ( rest_size > sizeof(UsbBuff) ){ rest_size = sizeof(UsbBuff); }
SetUsbBulkinReq( (char *)data, rest_size );
int ret = sceKernelWaitEventFlag( UsbTransEventFlag, USB_TRANSEVENT_BULKIN_DONE,
PSP_EVENT_WAITOR | PSP_EVENT_WAITCLEAR, &result, NULL );
if ( ret == 0 ){
if ( (UsbBulkinReq.retcode == 0) && (UsbBulkinReq.recvsize > 0) ){
write_size += UsbBulkinReq.recvsize;
data += UsbBulkinReq.recvsize;
} else {
return( -1 );
}
} else {
return( -1 );
}
}
}
return( write_size );
}
/*------------------------------------------------------------------------------*/
/* UsbMainThread */
/*------------------------------------------------------------------------------*/
static int UsbMainThread( SceSize size, void *argp )
{
int ret;
u32 result;
while( 1 ){
ret = sceKernelWaitEventFlag( UsbMainEventFlag,
USB_EVENT_ATTACH | USB_EVENT_DETACH | USB_EVENT_ASYNC,
PSP_EVENT_WAITOR | PSP_EVENT_WAITCLEAR, &result, NULL );
if ( ret < 0 ){ sceKernelExitDeleteThread( 0 ); }
if ( result & USB_EVENT_DETACH ){
UsbReady = 0;
sceKernelClearEventFlag( UsbMainEventFlag, ~USB_EVENT_CONNECT );
}
if ( result & USB_EVENT_ATTACH ){
UsbReady = 0;
sceKernelClearEventFlag( UsbMainEventFlag, ~USB_EVENT_CONNECT );
}
}
return( 0 );
}
/********************************************************************************/
/*------------------------------------------------------------------------------*/
/* UsbbdRegister */
/*------------------------------------------------------------------------------*/
void UsbbdRegister( void )
{
sceUsbbdRegister( &UsbDriver );
}
/*------------------------------------------------------------------------------*/
/* UsbbdUnregister */
/*------------------------------------------------------------------------------*/
void UsbbdUnregister( void )
{
sceUsbbdUnregister( &UsbDriver );
}
/*------------------------------------------------------------------------------*/
/* UsbStart */
/*------------------------------------------------------------------------------*/
int UsbStart( void )
{
int ret;
ret = sceUsbStart( PSP_USBBUS_DRIVERNAME, 0, 0 );
if ( ret != 0 ){ return( -1 ); }
ret = sceUsbStart( PSGROOVE_DRIVERNAME, 0, 0 );
if ( ret != 0 ){ return( -1 ); }
ret = sceUsbActivate( PSGROOVE_DRIVERPID );
if ( ret != 0 ){ return( -1 ); }
//TODO: Check if it is the right place
PsGroove_Start();
return( 0 );
}
/*------------------------------------------------------------------------------*/
/* UsbStop */
/*------------------------------------------------------------------------------*/
int UsbStop( void )
{
int ret;
ret = sceUsbDeactivate( PSGROOVE_DRIVERPID );
if ( ret != 0 ){ return( -1 ); }
ret = sceUsbStop( PSGROOVE_DRIVERNAME, 0, 0 );
if ( ret != 0 ){ return( -1 ); }
ret = sceUsbStop( PSP_USBBUS_DRIVERNAME, 0, 0 );
if ( ret != 0 ){ return( -1 ); }
return( 0 );
}
/*------------------------------------------------------------------------------*/
/* UsbResume */
/*------------------------------------------------------------------------------*/
int UsbResume( void )
{
int ret;
ret = sceUsbActivate( PSGROOVE_DRIVERPID );
if ( ret != 0 ){ return( -1 ); }
return( 0 );
}
/*------------------------------------------------------------------------------*/
/* UsbSuspend */
/*------------------------------------------------------------------------------*/
int UsbSuspend( void )
{
int ret;
ret = sceUsbDeactivate( PSGROOVE_DRIVERPID );
if ( ret != 0 ){ return( -1 ); }
return( 0 );
}
/*------------------------------------------------------------------------------*/
/* UsbWait */
/*------------------------------------------------------------------------------*/
int UsbWait( void )
{
int ret;
while ( UsbMainEventFlag < 0 ){ sceKernelDelayThread( 100000 ); }
ret = sceKernelWaitEventFlag( UsbMainEventFlag, USB_EVENT_CONNECT,
PSP_EVENT_WAITOR, NULL, NULL );
return( 0 );
}
/*------------------------------------------------------------------------------*/
/* 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_PsGroove_Switch_Port */
/*------------------------------------------------------------------------------*/
void PsGroove_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 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;
}
}
/*------------------------------------------------------------------------------*/
/*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 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_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!
}
}
}
It seems this guy has tried some to give an idea that maybe someone with enough knowledge can develop further.