Четвертый день я пытаюсь написать программку на PSP, которая могла бы отлавливать нажатия специальных клавиш снизу (кнопки громкости, регулирования экрана и т.д). Для примера, FuSa Gamepad успешно делает это. Дело в том, что эти кнопки можно прочитать только в режиме ядра. Можно сделать программу, работающую в режиме ядра, всего лишь указав флаг 0x1000 в информации модуля:
	PSP_MODULE_INFO("Sample program", 0x1000, 1, 1);
 
И тогда эти кнопки действительно отлавливаются, но PSP намертво зависает и выключается при попытке выхода любым способом, или при установке колбеков.
Если посмотреть на Fusa Gamepad, можно заметить, что он загружает PRX-плагин. Если декомпилировать Fusa Gamepad и посмотреть в секцию moduleinfo, видно что EBOOT.PBP стартует в пользовательском режиме (0x0), а плагин в режиме ядра (0x1006). Выходит, эти кнопки отлавливает именно плагин.
Разобравшись с загрузкой плагинов и функций из него, сделал свой плагин и пытался разными отлавливать кнопки из него, но безуспешно. Вот исходник самой "игры" (main.c) и плагина (module.c)
 main.c
  
	#include <pspkernel.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <pspsdk.h>
#include <pspctrl.h>
#include <string.h>
PSP_MODULE_INFO("PRXLOADER", 0x0, 1, 1);
/* Define the main thread's attribute value (optional) */
PSP_MAIN_THREAD_ATTR(0);
/* Define printf, just to make typing easier */
#define printf	pspDebugScreenPrintf
/* Imported function */
void *getModuleInfo(void);
int plus(int a, int b);
int waitForX(void);
void kReadBuffer(SceCtrlData *pad_data, int count);
void kReadBuffer2(SceCtrlData *pad_data, int count);
void updatePadData(void);
SceCtrlData getPadData(void);
int main(void)
{
	SceUID modid;
	SceModule *mod;
	SceCtrlData pad, pad2, pad3;
	int i;
	int ret;
	int fd;
	pspDebugScreenInit();
	/* Start mymodule.prx and dump its information */
	printf("\nStart my module\n");
	modid = pspSdkLoadStartModule("ms0:/mymodule.prx", PSP_MEMORY_PARTITION_KERNEL);
	printf("Module ID %08X\n", modid);
	/* Let's test the module's exports */
	printf("Module Info %p\n", getModuleInfo());
	printf("plus(41, 92): %d\n", plus(41, 92));
	printf("waitForX()... ");
	i = waitForX();
	printf("%08X\n", i);
	printf("Press X to continue\n");
	while(1) {
		sceCtrlReadBufferPositive(&pad, 1);
		if(pad.Buttons & PSP_CTRL_CROSS) break;
	}
	pspDebugScreenClear();
	while(1) {
		kReadBuffer(&pad, 1);
		kReadBuffer2(&pad2, 1);
		pspDebugScreenSetXY(0, 2);
		updatePadData();
		pad3 = getPadData();
		printf("B1: %08X\nB2: %08X\nB3: %08X\nPress O to exit\n", pad.Buttons, pad2.Buttons, pad3.Buttons);
		if(pad.Buttons & PSP_CTRL_CIRCLE)
			break;
		sceKernelDelayThread(100000);
	}
	printf("Exiting...");
	sceKernelExitGame();
//	sceKernelExitDeleteThread(0);
	return 0;
}
 
    module.c
  
	#include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
#include <stdio.h>
PSP_MODULE_INFO("TESTPRX", 0x5006, 1, 0);
//PSP_MAIN_THREAD_ATTR(0);
SceCtrlData gpad = {0, 0x42, 0, 0, NULL};
#define WELCOME_MESSAGE "Hello from the PRX\n"
#define printf pspDebugScreenPrintf
int main(int argc, char **argv)
{
	int i;
	printf(WELCOME_MESSAGE);
	for(i = 0; i < argc; i++)
	{
		printf("Arg %d: %s\n", i, argv[i]);
	}
	sceKernelSleepThread();
	return 0;
}
/* Exported function returns the address of module_info */
void* getModuleInfo(void)
{
	return (void *) &module_info;
}
int plus(int a, int b) {
	return a+b;
}
void updatePadData(void) {
	sceCtrlReadBufferPositive(&gpad, 1);
}
SceCtrlData getPadData(void) {
	return gpad;
}
void kReadBuffer2(SceCtrlData *pad_data, int count) {
	SceCtrlData pad;
	sceCtrlReadBufferPositive(&pad, count);
	*pad_data = pad;
	return;
}
void kReadBuffer(SceCtrlData *pad_data, int count) {
	sceCtrlReadBufferPositive(pad_data, count);
	return;
}
int waitForX(void) {
	SceCtrlData pad;
	while(1) {
		sceCtrlReadBufferPositive(&pad, 1);
		if (pad.Buttons & PSP_CTRL_CROSS) break;
	}
	return 0;
}
int module_start(SceSize args, void *argp) {
	return 0;
}
int module_stop(void) {
	return 0;
}
 
   
Вот экспорты функций:
Как видно, я пытался ловить кнопки несколькими способами:
1) Обычная обертка над стандарттной функцией - работает так-же как в пользовательском режиме (не возвращает состояние специальных клавиш)
2) Функция которая считывает кнопки в локальную переменную и присваивает структуру параметру - всегда возвращает 0xDEADBEEF, видимо какая-то заглушка?
3) Пара функций, одна из них считывает кнопки в глобальную переменную, а вторая возвращает эту глобальную переменную. Эта глобальная переменная не изменяется вообще! (всегда возвращает значение 0x42 которым я ее проинициализировал)
Ну и еще эта функция waitForX() - мой эксперимент, из которого понятно, что я вообще не понимаю каким образом выполняются функции в плагине. waitForX() по неизвестным мне причинам, будто бы сразу возвращает 0, проигнорировав вечный цикл.
Вот архив со всем проектом 
TestPRX.zip
А тут уже скомпилированный плагин и EBOOT.PBP, который можно закинуть в PSP/GAME/ и посмотреть на код в действии (mymodule.prx кидать в корень карты памяти) 
TestPRX_EBOOT.zip 
В общем нужна просто программа которая способна отлавливать эти кнопки и корректно завершаться. Мне бы помогли исходники FuSa Gamepad или любой программы которая проделывает подобное, и вообще любая информация про это.