Page 2 of 5

Re: VSH plugin for Bluetooth

Posted: Sat Jan 01, 2011 8:34 am
by JJS
Have some code now :D

This version implements the "syscall stub in user memory" technique I wrote about in the last post. So now not only does the checking function get hooked now, it also writes out a logfile to "ef0:/btfree_log.txt" with the found devices. The function will get called repeatedly with the same values, so there will be duplicates in the file and it will grow every 5 seconds maybe.

Code: Select all

#include <pspsdk.h> 
#include <pspkernel.h> 
#include <systemctrl.h> 
#include <psploadcore.h>
#include <string.h>
#include <stdio.h>


PSP_MODULE_INFO("btfree", 0x1000, 0, 0);


// Prototype not in the PSPSDK
int sceKernelQuerySystemCall(void* function);


// Just some error codes I found in the bt module
#define PSP_ERROR_BLUETOOTH_ALREADY_REGISTERED 0x802F0131
#define PSP_ERROR_BLUETOOTH_UNSUPPORTED_DEVICE 0x802F0135


#define MAKE_CALL(f) (0x0c000000 | (((u32)(f) >> 2)  & 0x03ffffff))
#define MAKE_SYSCALL(n) (0x03ffffff & (((u32)(n) << 6) | 0x0000000c))


// Previous start module handler
STMOD_HANDLER previousStartModuleHandler = NULL; 

// Address for the syscall stub in user memory
int blockAddress = 0;

// This struct is passed to sub_09498 in bluetooth_plugin_module
typedef struct
{
	u32 stuct_size; // size of this struct = 0x54
	u16 item_number; // first item in array has 1, second has 2
	u16 name[32]; // in unicode
	u16 unknown1;
	u8 major_service_class; // probably this
	u8 major_device_class; // 1 = PC, 2 = phone, 4 = audio/video, 5 = peripheral device
	u8 minor_device_class; // different meaning depending on the major class
	u8 unknown2;
	u32 unknown3; // always the same for a given device
	u16 unknown4; // always the same for a given device
	u16 unknown5;
}
btDeviceInfo;


// Function pointer to the original sub_09498 in bluetooth_plugin_module
int (*bluetooth_plugin_module_sub_09498)(int, btDeviceInfo*, int) = NULL;


void fillBufferFromWidechar(unsigned short* inputBuffer, char* outputText)
{
  int i;
  for (i = 0; inputBuffer[i]; i++)
  {
    outputText[i] = inputBuffer[i];
  }

  outputText[i] = 0;
}


void logFilePrintf(char* format, int arg1)
{
	SceUID logfile = sceIoOpen("ef0:/btfree_log.txt", PSP_O_CREAT | PSP_O_WRONLY | PSP_O_APPEND, 0777);

	if (logfile > -1)
	{
		char buffer[100];
		sprintf(buffer, format, arg1);
		sceIoWrite(logfile, buffer, strlen(buffer));
		sceIoClose(logfile);
	}
}



int bluetooth_plugin_module_sub_09498_hook(int unknown, btDeviceInfo* devices, int count)
{
	int k1 = pspSdkSetK1(0);

	if (count > 0)
	{
		// Log the device info
		logFilePrintf("--------------------\n", 0);
		
		char name[32];
		int i;

		for (i = 0; i < count; i++)
		{
			fillBufferFromWidechar(devices[i].name, name);
			logFilePrintf("name         : %s\n", (u32)name);
			logFilePrintf("unknown1     : 0x%08lX\n", (u32)devices[i].unknown1);
			logFilePrintf("major_srv_cl : 0x%08lX\n", (u32)devices[i].major_service_class);
			logFilePrintf("major_dev_cl : 0x%08lX\n", (u32)devices[i].major_device_class);
			logFilePrintf("minor_dev_cl : 0x%08lX\n", (u32)devices[i].minor_device_class);
			logFilePrintf("unknown1     : 0x%08lX\n", (u32)devices[i].unknown2);
			logFilePrintf("unknown2     : 0x%08lX\n", (u32)devices[i].unknown3);
			logFilePrintf("unknown3     : 0x%08lX\n", (u32)devices[i].unknown4);
			logFilePrintf("unknown4     : 0x%08lX\n", (u32)devices[i].unknown5);
			logFilePrintf("\n", 0);

			// Device class can be changed here
			//devices[i].major_device_class = 2;
			//devices[i].minor_device_class = 4;
		}
	}

	pspSdkSetK1(k1);

	// Call the original function
	return bluetooth_plugin_module_sub_09498(unknown, devices, count);
}




int on_module_start(SceModule2* mod) 
{
	// Get active on the Bluetooth VSH plugin
	if (strcmp(mod->modname, "bluetooth_plugin_module") == 0) 
	{ 
		logFilePrintf("Entering on_module_start\n", 0);

		// Store function pointer to the original sub_09498
		bluetooth_plugin_module_sub_09498 = (void*)(mod->text_addr + 0x00009498);
		logFilePrintf("bluetooth_plugin_module_sub_09498 = 0x%08lX\n", (u32)bluetooth_plugin_module_sub_09498);

		// Setup a syscall stub in user memory
		if (blockAddress == 0)
		{
			SceUID blockId = sceKernelAllocPartitionMemory(2, "btfree_stub", PSP_SMEM_Low, 2 * sizeof(int), NULL);
			logFilePrintf("blockId = 0x%08lX\n", (u32)blockId);

			blockAddress = (int)sceKernelGetBlockHeadAddr(blockId);
			logFilePrintf("blockAddress = 0x%08lX\n", (u32)blockAddress);

			// Get syscall of the hook function
			int syscall = sceKernelQuerySystemCall(&bluetooth_plugin_module_sub_09498_hook);
			logFilePrintf("syscall = 0x%08lX\n", (u32)syscall);

			// Write syscall stub
			_sw(0x03E00008, blockAddress); // jr $ra
			_sw(MAKE_SYSCALL(syscall), blockAddress + sizeof(int)); // syscall
		}

		// Hook the call to the original function in bluetooth_plugin_module
		_sw(MAKE_CALL(blockAddress), mod->text_addr + 0x000095A4);


		// Now patch sub_09498 to accept any device class

		// There is a check for the device type that goes something like this:
		//
		// if (((descriptor & 0x000000FF) == 0x00000005) || (...) || (...)))
		//
		// It gets changed to:
		//
		// if (((descriptor & 0x000000FF) != 0x0000FFFF) || (...) || (...)))
		//
		// The result is obviously that the statement always evaluates as true,
		// therefore no devices are rejected early.

		// write "li $t6, 0xFFFF", was "li $t6, 0x5"
		_sw(0x240EFFFF, mod->text_addr + 0x000094A8);

		// write "bne $v0, $t6, loc_000094E4", was "beq $v0, $t6, loc_000094E4"
		_sw(0x144E0003, mod->text_addr + 0x000094D4);
	} 

	// Call previously set start module handler if necessary
	if (previousStartModuleHandler)
		return previousStartModuleHandler(mod);
	else
		return 0;
} 



int module_start(SceSize args, void* argp)
{
	// Establish a handler that gets called before any modules "module_start" function is called.
	// A previous handler gets saved.
	previousStartModuleHandler = sctrlHENSetStartModuleHandler(on_module_start);

	return 0;
}





int module_stop(SceSize args, void* argp)
{
	// Restore the previous start module handler if there was one
	if (previousStartModuleHandler)
		sctrlHENSetStartModuleHandler(previousStartModuleHandler);

	return 0;
}

Edit: I thought it was fishy that bluetooth and usb were mutually exclusive, but now it all makes sense. The bluetooth module is obviously attached to the USB port. The driver for it is usbbsmcdc.prx. I also found were the LED is blinked, you could patch it in there in the function sub_00A24().

Re: VSH plugin for Bluetooth

Posted: Sat Jan 01, 2011 3:16 pm
by Strangelove
thought i'd ask where you plan on taking this project. can't remember having seen much bluetooth plugins from before. yet the possibilities seem wast.

here's some ideas:
- redirect audio to stream over bluetooth.
- redirect HID devices input to the PSPs input
- implement a MSC (mass storage device) for file transfer.
- implement a serial console to be used for pretty much anything (shell, debug, file transfer, VNC etc.)

not being a wiz on blutooth or anything... it would seem that you can rely on standard protocols a lot so you can avoid the need for special drivers on the target BT device. this would be ideal.

if you want remote shell you'd probably have to look at porting dash+busybox to the PSP first. ssh would be another app worth looking into porting.

Re: VSH plugin for Bluetooth

Posted: Sun Jan 02, 2011 9:26 am
by JJS
Honestly I don't know if anything really useful will come out of this. I am no bluetooth wizard either, in fact I knew about nothing before I started looking into this.

There are several components to the bluetooth implementation on the GO: the hardware driver, a manager prx (massive in size), some sort of plugin for adding the dial-up feature to the network dialog and the management plugin for the VSH. So I am making baby steps right now in trying to understand how all fits together and what is done in certain functions.

Re: VSH plugin for Bluetooth

Posted: Thu Jan 06, 2011 7:28 pm
by KaZ
JJS, can u register a PS3 controller without the use of the PS3 console via ur plugin? (dont have a ps3, have xbox 360 :D)

because if u can, im gonna go to the shops and buy a ps3 controller to use on my psp go :D

Re: VSH plugin for Bluetooth

Posted: Thu Jan 06, 2011 8:12 pm
by thedicemaster
i'm quite certain that's impossible with just a psp plugin.
you also need to register a mac-address in the controller itself, which can only be done with a device with a proper USB port and drivers.
although if the PSPgo-side of it could be done, there is a ps3-controller "driver" for the PC which allows you to write a mac-address to the controller.

Re: VSH plugin for Bluetooth

Posted: Thu Jan 06, 2011 8:23 pm
by KaZ
thedicemaster wrote:i'm quite certain that's impossible with just a psp plugin.
you also need to register a mac-address in the controller itself, which can only be done with a device with a proper USB port and drivers.
although if the PSPgo-side of it could be done, there is a ps3-controller "driver" for the PC which allows you to write a mac-address to the controller.
Well then, ill wait for a proper answer wen some1 tested it and posts results here (:

Re: VSH plugin for Bluetooth

Posted: Thu Jan 06, 2011 9:08 pm
by JJS
Would indeed be great if someone could try to register a PS3 controller with the plugin enabled. Trying to register without the PS3 I mean. It would be interesting if the controller shows up in the device list and if it can be paired.

Re: VSH plugin for Bluetooth

Posted: Thu Jan 06, 2011 9:24 pm
by thedicemaster
it's impossible to even try, despite being bluetooth PS3 controllers have no pairing mode.
the only way a PS3 controller can be used through bluetooth is by writing a mac-address to a memory chip on the controller through usb.
EDIT: hm, seems the plugin doesn't work on 6.35pro, crashes when entering bluetooth settings.

Re: VSH plugin for Bluetooth

Posted: Thu Jan 06, 2011 9:44 pm
by JJS
Ok, thanks for the explanation. The plugin is written for 6.20, so it will probably not work on any other firmware. Adapting it would be quite easy, I will see about that.

Re: VSH plugin for Bluetooth

Posted: Thu Jan 06, 2011 9:48 pm
by thedicemaster
actually, it's not a complete failure on 6.35.
i don't know if it will help you with making it work for 6.35, but it did log this much:

Code: Select all

Entering on_module_start
bluetooth_plugin_module_sub_09498 = 0x0A56C898
blockId = 0x04D84F77
blockAddress = 0x00000100
syscall = 0x8002013A
Entering on_module_start
bluetooth_plugin_module_sub_09498 = 0x0A56C698
blockId = 0x04D9E065
blockAddress = 0x00000100
syscall = 0x8002013A