Advertising (This ad goes away for registered users. You can Login or Register)

[Solved] sceKernelRegisterExitCallback in a kernel module

Forum rules
Forum rule Nº 15 is strictly enforced in this subforum.
Locked
Serinda
Posts: 5
Joined: Mon Jun 10, 2013 8:39 am

[Solved] sceKernelRegisterExitCallback in a kernel module

Post by Serinda »

Hello,

I have a kernel module (plugin) that is loaded and executed when I launch any game or homebrew.
I want a function I wrote to be called when the user leaves the game, for example, by using the home screen.

First, I tried to use module_stop but it seems it's not called at all when I use the home screen to leave the game.
Note that it's correctly defined in my exports.exp file and linked in my Makefile.

Then I tried to set a function callback with the sceKernelRegisterExitCallback function.
I created a second thread in the module_start function that registers my function callback.

Code: Select all

/* ... */

int exitCallback()
{
	// This file should be created when I leave a game with the home screen, but it's not.. which means the callback isn't called.
	int fd = sceIoOpen("ms0:/exitCallback_called.txt", PSP_O_WRONLY|PSP_O_CREAT|PSP_O_TRUNC, 0777);
	
	if ( fd >= 0 )
	{
		sceIoWrite(fd, NULL, 0);
		sceIoClose(fd);
	}
	
	return 0;
}
 
int callbackThread()
{
	int cbid = sceKernelCreateCallback("exitCallback", exitCallback, NULL);
	int res = sceKernelRegisterExitCallback(cbid);
	
	// This file is correctly created.
	int fd = sceIoOpen("ms0:/debug_callbackThread.txt", PSP_O_WRONLY|PSP_O_CREAT|PSP_O_TRUNC, 0777);
	char buff[200];
	
	if ( fd >= 0 )
	{
		sprintf(buff, "sceKernelCreateCallback returned 0x%8.8X\nsceKernelRegisterExitCallback returned 0x%8.8X", cbid, res);
		sceIoWrite(fd, buff, strlen(buff));
		sceIoClose(fd);
	}
	
	sceKernelSleepThreadCB();
	return sceKernelExitDeleteThread(0);
}

int module_start(SceSize args, void *argp)
{
	int thid = sceKernelCreateThread("kernel_prx_th", main, 32, MAIN_STACKSIZE, 0, NULL);
	
	if ( sceKernelStartThread(thid, 0, NULL) >= 0 )
	{
		thid = sceKernelCreateThread("callbackThread", callbackThread, 32, 0x500, 0, NULL);
		sceKernelStartThread(thid, 0, NULL);
	}
	
	return 0;
}
Here is the content of the debug_callbackThread.txt file:

Code: Select all

sceKernelCreateCallback returned 0x03C0F02D
sceKernelRegisterExitCallback returned 0x00000000
So as you can see, everything works perfectly except that my exitCallback function is never called.
So my questions are:

- Is it possible my function callback is correctly set but is then replaced by the booted game's one, which would mean we could only register one callback ?
- Does the sceKernelRegisterExitCallback function only work in user mode ?
- When is the module_stop function called exactly ?
- So how can I do to call my function when the user leaves a game, aka when the module is unloaded ?

I've also noticed a weird thing, I have no idea if it's normal or not but sceKernelRegisterExitCallback always returns 0, whether the passed callback ID is valid or not.
Any help appreciated :?
Advertising
Last edited by Serinda on Mon Jun 10, 2013 12:55 pm, edited 1 time in total.
NightStar3
VIP
Posts: 364
Joined: Mon Sep 27, 2010 8:22 pm

Re: sceKernelRegisterExitCallback in a kernel module (seplug

Post by NightStar3 »

The function sceKernelCreateCallback's second parameter should be a reference to an SceKernelCallbackFunction, which takes 3 parameters (yours has none)

http://psp.jim.sh/pspsdk-doc/group__ThreadMan.html

Code: Select all

int sceKernelCreateCallback 	( 	const char *  	name,
		SceKernelCallbackFunction  	func,
		void *  	arg	 
	)

Code: Select all

typedef int(* SceKernelCallbackFunction)(int arg1, int arg2, void *arg)
Replace your exitCallback function definition with

Code: Select all

int exitCallback(int arg1, int arg2, void *arg) {
     /* code here*/
 }
and it should work.
Also, sceKernelRegisterExitCallback returns 0 on success.

On a side note, why do all this in a seperate kernel module?
Advertising
Serinda
Posts: 5
Joined: Mon Jun 10, 2013 8:39 am

Re: sceKernelRegisterExitCallback in a kernel module (seplug

Post by Serinda »

I figured out why it didn't work, as I thought we can only register one exit callback.
My callback was succesfully registered but it was before the game's one, therefore it was replaced.

I simply added a delay of 5 sec before registering my callback and I created the callbackThread in the main thread so now my callback is registered after the game's one.
To be sure we can only set one callback, I tried to register two callbacks and the second callback was the only one called so it confirms what I said.

Note that I added the following function call at the end of my exit callback since we are in kernel mode, or it wouldn't quit the game (infinite "Please wait"):

Code: Select all

sceKernelExitVSHVSH(NULL);
About the callback function prototype, I declare it as callbackName() cause I don't need its args.
I need to set an exit callback cause I have to free some ressources when the user goes back to XMB.
Thanks anyway.

Nevertheless, I'd like to know when is the module_stop function called exactly ?
noname120
Developer
Posts: 777
Joined: Thu Oct 07, 2010 4:29 pm

Re: [Solved] sceKernelRegisterExitCallback in a kernel modul

Post by noname120 »

I simply added a delay of 5 sec before registering my callback and I created the callbackThread in the main thread so now my callback is registered after the game's one.
To be sure we can only set one callback, I tried to register two callbacks and the second callback was the only one called so it confirms what I said.
You can instead register yours at the start and then dummy this function out (basically get the address if it, replace the first instruction to a jr $ra and nop, this way no need to care about who is importing it, it won't work whatever the callee is).
I declare it as callbackName() cause I don't need its args.
The fact you don't need it doesn't matter, C conventions require you to follow the prototype.
And if you're very tight about it, you can do the following instead:

Code: Select all

int exitCallback(int arg1 __attribute__((unused)), int arg2 __attribute__((unused)), void *arg __attribute__((unused))) {
     /* code here*/
}
Funny stuff
<yifanlu> I enjoy being loud and obnoxious
<yifanlu> rooting an android is like getting a hooker pregnant
<xerpi> I sometimes think I should leave all this stressing **** and be a farmer instead
Serinda
Posts: 5
Joined: Mon Jun 10, 2013 8:39 am

Re: [Solved] sceKernelRegisterExitCallback in a kernel modul

Post by Serinda »

Good idea about the function nop, I didn't think about it I'm gonna do that.

I don't care about the callback's args since gcc doesn't complain about it, I would care only If my program was coded in C++.
I could have also written: int callback( int, int, void* ) :lol:
noname120
Developer
Posts: 777
Joined: Thu Oct 07, 2010 4:29 pm

Re: [Solved] sceKernelRegisterExitCallback in a kernel modul

Post by noname120 »

Serinda wrote:Good idea about the function nop, I didn't think about it I'm gonna do that.

I don't care about the callback's args since gcc doesn't complain about it, I would care only If my program was coded in C++.
I could have also written: int callback( int, int, void* ) :lol:
And what happens if someone tries your code without using the extern keyword? I won't work!
Funny stuff
<yifanlu> I enjoy being loud and obnoxious
<yifanlu> rooting an android is like getting a hooker pregnant
<xerpi> I sometimes think I should leave all this stressing **** and be a farmer instead
Serinda
Posts: 5
Joined: Mon Jun 10, 2013 8:39 am

Re: [Solved] sceKernelRegisterExitCallback in a kernel modul

Post by Serinda »

noname120 wrote:And what happens if someone tries your code without using the extern keyword? I won't work!
What do you mean ? It does work.
Locked

Return to “Programming and Security”