
ã§ããããå€ä»£ã§ã¯ã人ã ã¯ãœããŒã®ãã¬ã€ã¹ããŒã·ã§ã³ã§ãã¬ã€ãããã¹ãŠã«æºè¶³ããŠããŸããã ããããé²æ©ã¯æ¢ãŸããŸããã§ããã è¶ å°ååè·¯ã®éç©åºŠãåäžããŸããã ãšã³ãžãã¢ãªã³ã°ã®èãæ¹ã¯åžžã«æ°ãããã©ãŒã ãã¡ã¯ã¿ãŒãæ¢ããããŒã±ãã£ã³ã°ã®èãæ¹ã¯æ°ããåžå Žãæ¢ããŠããŸããã ãã®ããã2005幎ã«ã¯ãããŒã¿ãã«ã²ãŒã ã·ã¹ãã ã§ããSony Playstation Portableãæ¥æ¬åœå€ã§è²©å£²ãããŸããã 圌女ã®ã²ãŒã ã©ã€ã³ïŒä»ã®ã³ã³ãœãŒã«ãšåæ§ïŒã¯ãPSPã¢ã€ã¢ã³ã²ãŒã çšã«ç¹å¥ã«ã³ã³ãã€ã«ãããŸããã ãããã圌女ã¯ãçµã¿èŸŒã¿ã®ãšãã¥ã¬ãŒã¿ãä»ããŠå ã®PlayStationããã²ãŒã ãå®è¡ããã®ã«ååãªèšç®èœåãåããŠããŸããã ãããããéèŠãªåœ¹å²ã¯ãPlayStationãšPSPã®äž¡æ¹ã«åãã¢ãŒããã¯ãã£ïŒMIPSïŒã®ããã»ããµãæèŒãããŠãããšããäºå®ã«ãã£ãŠæããããŸããã ãããããã®ã·ã¹ãã ã§æã泚ç®ãã¹ãããšã¯ãçºå£²ããã幎ã«ããã«ãPSP SDKã©ã€ãã©ãªããããã¯ãŒã¯ã«ãªãŒã¯ããããšã§ãã ãã®çµæãçºå£²ããã»ãŒ10幎åŸã«ã¯ãèšå€§ãªæ°ã®ã²ãŒã ã©ã€ãã©ãªãšæ©èœæ§ã®é«ãããŒã ããªã¥ãŒããããŸãã ãŸããä»ã§ã¯ãã·ã¢ã®æ倧ã®éœåžã§ã¯ãªããå®å šã«æ©èœããPSPïŒæãæ©èœçãªå€æŽã®ïŒã3000ã«ãŒãã«ã§è³Œå ¥ã§ããŸãã ããããã¹ãŠã«ãããçŸåšãéåžžã«é åçãªäºç®ã®ã²ãŒãã³ã°ã·ã¹ãã ã§ããã巚倧ãªèšçœ®ããŒã¹ãåããŠããŸãã æãæ©èœçãªå€æŽã«ã¯ããã¬ãã«æ¥ç¶ããããã®ã³ã³ããŒãã³ãåºåããããŸãã ãã ããPSPãé·æéã²ãŒã ããããšããŠäœ¿çšãããšããç¹ã§ã¯ãTVã³ãã¯ã¿ã®äœçœ®ãé©åã§ã¯ãããŸããã ããã«ãé·æéã®äœ¿çšã§ã¯ãå é»åšããã®2çªç®ã®ã¯ã€ã€ãæ¥ç¶ããå¿ èŠããããŸãã ãããŠããã®ãããªãã¡ã©ã®äœ¿ããããã¯ãŒãã«ãªãåŸåããããŸãã ãã®åé¡ãæ¯èŒçå®äŸ¡ã§ãã€ãªã¿ã¯ã§è§£æ±ºããæ¹æ³-ããã«ã€ããŠã¯ããã®èšäºã§èª¬æããŸãã ãŸããPSPçšã®USBã¯ã©ã€ã¢ã³ããã©ã€ããŒã®ããã°ã©ãã³ã°ãPSPã«ããã¯é¢æ°ãã€ã³ã¹ããŒã«ããæ¹æ³ãLinuxã§USBããã€ã¹ãšAPIçµç±ã®ãžã§ã€ã¹ãã£ãã¯ã䜿çšããæ¹æ³ã«ã€ããŠãç°¡åã«è§ŠããŸãã å§ããŸããã
ããŒã¿ãã«ã³ã³ãœãŒã«ããã¬ãã«æ¥ç¶ãããšããèãã¯æ°ãããã®ã§ã¯ãããŸãã
ããããå§ããåã«ã1ã€ã®èå³æ·±ãäºå®ã«ã€ããŠèª¬æããŸãã PSPã¯ã»ãŒ10幎åã«ãªãªãŒã¹ãããŠä»¥æ¥ã次äžä»£ã®ãœããŒã®ããŒã¿ãã«ã³ã³ãœãŒã«ãã€ãŸãSony Playstation VitaãçŸåšé¢é£ããŠããŸãã ãããŠäºå®ã¯ãæ¥æ¬ã§ã¯ããŒã¿ãã«ã³ã³ãœãŒã«ã®åºå®ããŒãžã§ã³ããã£ããšããããšã§ãã Sony PlayStation Vita TVã
PS Vita TV

ã²ãŒã ããããšããŠãPlaystation 3ã®éåžžã®Dualshock 3ã䜿çšããŸããUSBãŸãã¯Bluetoothæ¥ç¶ããµããŒãããŠããŸãã Vita TVã¯ãVitaãšåæ§ã«ãVitaãPSPãããã³å ã®Playstationã®ã²ãŒã ããã¬ã€ã§ããŸãã ãããã£ãŠããåºå®ããŒã¿ãã«ãã³ã³ãœãŒã«ã®ã¢ã€ãã¢ã¯éåžžã«äžè²«æ§ããããèå³æ·±ããã®ã§ãã
åéãã²ãŒã ããããšPSPã«ããã«ã¯ã©ãããã°ããã§ããïŒ
次ã«ãå€éšã²ãŒã ããããPSPã«æ¥ç¶ããæ¹æ³ã«ã€ããŠè³ªåããããŸããã PSPã«ã¯USBã³ãã¯ã¿ããããæ奜家ã¯PSP ã« ãæ¥ç¶ãããã³ã³ãã¥ãŒã¿ãŒã®ãã©ã«ããŒããã²ãŒã ãå®è¡ããããã²ãŒã ãšäžç·ã«ç»åå šäœããã®USBæ¥ç¶ãããã³ã³ãã¥ãŒã¿ãŒã®ãŠã£ã³ããŠã«è»¢é ããããã«æããŸããã ãããã å€æããããã« ãPSPã®USBã¯ã¯ã©ã€ã¢ã³ãã«ãããªããŸããã ãŸããå ¬åŒã®ã¢ã¯ã»ãµãªïŒã«ã¡ã©ãªã©ïŒã§ããã¹ãã¢ãŒãã§åäœããŸãïŒã¡ãªã¿ã«ãAndroidã§åšèŸºæ©åšãæäœããå Žåã¯ãã¹ããŒããã©ã³ãã¯ã©ã€ã¢ã³ãã¢ãŒãã«åãæ¿ããããšããå§ãããŸãïŒã ã€ãŸã ã²ãŒã ããããPSPã«çŽæ¥æ¥ç¶ããããšã¯åœ¹ã«ç«ã¡ãŸããã ãããã£ãŠãäœããã®äžéããã€ã¹ãå¿ èŠã§ãã å°å ã®é»æ°åºã§ã¯ãããŸããŸãªçšåºŠã®æ¥åŸé ã®ããŒãããããã°ããã®ã«1ãã1äžã«ãŒãã«ããããŸãã ãããã¯ãã€ã¯ãã³ã³ãããŒã©ã§ãããUSBãã¹ãã«ã€ããŠã¯å¥ã«èããå¿ èŠããããŸãã ãããããRaspberry Piãç®ãåŒããŸããã
ã©ãºããªãŒãã€

ãã®ãã·ã³ã«ã¯å¿ èŠãªãã®ããã¹ãŠæã£ãŠããŸã-2ã€ã®USBããŒããšå®å šãªLinuxã ããã»ã©å€§ãããªããã·ã¢ã®éœåžã§ã¯ãå€ãã¢ãã«ïŒ512 MBã®ã¡ã¢ãªãšã€ãŒãµãããïŒã¯ãç¡æã®ãã©ã€ããŒãæ²ç€ºæ¿ã§1,500ã«ãŒãã«ããããŸãã äŸ¡æ Œã¯ãæãå®äŸ¡ãªã³ã³ãããŒã©ãŒãããã°ããŒãã«èŠåã£ããã®ã§ãããæ©èœã¯ãã¯ãäŸã§ã¯ãããŸããã ãŸãããè±åœè£œãã
ç 究éå§
USBã±ãŒãã«ãPSPã«æ¥ç¶ããã ãã§ãUSBãã©ãã·ã¥ãã©ã€ããšããŠè¡šç€ºãããŸãã 圌女ã«ã¯å€éšç®¡çã«é¢ããã³ãã³ããåãå ¥ããå¿ èŠããããŸãã ã€ãŸã USBãä»ããŠæ å ±ãåä¿¡ããPSPèªäœã®ã³ã³ãããŒã«ã®æŒäžãã·ãã¥ã¬ãŒãããã³ãŒãã®ããã€ãã®çš®é¡ãPSPã§ã¹ãã³ããå¿ èŠããããŸãã ã©ã€ã»ã³ã¹ãããã²ãŒã ã«å ããŠããã€ãã®ã³ãŒããå®è¡ããèœåã¯ãæµ·è³çãã¡ãŒã ãŠã§ã¢ã§ã®ã¿å¯èœã§ãã æè¡çã«ã¯ãæµ·è³çãã¡ãŒã ãŠã§ã¢ã¯ãã¡ã¢ãªã«ãŒãã«ããå ¬åŒããã°ã©ã ã®ãµããããããã°ã©ã ã§ãããèµ·åãããšãåäœäžã®ãã¡ãŒã ãŠã§ã¢ã³ãŒããRAMå ã®ä¿®æ£ãããã³ãŒãã«çœ®ãæããŸããããã«ãããPSPã¡ã¢ãªã«ãŒãã®.isoãã¡ã€ã«ããã²ãŒã ãå®è¡ã§ããŸãã ãããã£ãŠããã¡ãŒã ãŠã§ã¢ã¯ã次ã®PSPã®åèµ·åãŸã§ã¹ã ãŒãºã«å®è¡ãããŸãã ããããç§ãã¡ã«ãšã£ãŠéèŠãªã®ã¯ããã§ã¯ãªãããã©ã°ã€ã³ããµããŒãããŠãããšããäºå®ã§ãã ãã©ã°ã€ã³ã¯ãç¹å®ã®åœ¢åŒã§ãªã³ã¯ããããªããžã§ã¯ããã¡ã€ã«ã§ãããã¡ã€ã³ã¡ãã¥ãŒãPSPã²ãŒã ããŸãã¯å ã®ãã¬ã€ã¹ããŒã·ã§ã³ã®ã²ãŒã ã®èµ·åãšäžŠè¡ããŠãå¥ã ã®ã¹ããªãŒã ã§éå§ãããŸãã å ã®PSPãã¡ãŒã ãŠã§ã¢ã®ææ°ããŒãžã§ã³ã¯ãã§ã«6.60ã§ãã ãã¡ãŒã ãŠã§ã¢ã®ä»¥åã®ããŒãžã§ã³çšã«ã·ã£ãŒãåããããã©ã°ã€ã³ã¯ãææ°ã®ãã¡ãŒã ãŠã§ã¢ã§ã¯åäœããªãå ŽåããããŸãã ããã¯ãã®å Žåã«èµ·ãããŸããã USBçµç±ã§PSPããPSPã§çºçãããã¹ãŠã®WindowsããŒã¹ã®PCãããªã«UââSBçµç±ã§è»¢éããPSPå ã®PCã«æ¥ç¶ãããã²ãŒã ãããããUSBçµç±ã§ããŒã¿ãåä¿¡ã§ãããã©ã°ã€ã³ããã¡ãŒã ãŠã§ã¢6.60ã§åäœããã®ã¯ååã ãã§ãã ã²ãŒã ãããããPSPãžã®ããŒã¿ã¯å°éããŸããããPSPã³ã³ãããŒã«ã®ã³ã³ãããŒã«ã®ã·ãã¥ã¬ãŒã·ã§ã³ã¯æ©èœããŸããã§ããã ãã¡ãŒã ãŠã§ã¢6.60ã®ã³ã³ãããŒã«ã§äœããã®åœ¢ã§æ©èœãããã©ã°ã€ã³ãæ¢ãå§ããŸããã ãããŠãããèŠã€ããŸããã å¥ã®ãã©ã°ã€ã³ã¯ãPSPã¢ããã°ã¹ãã£ãã¯ãæäœããããã«äœ¿çšãããææ°ã®ãã¡ãŒã ãŠã§ã¢ã§åäœããŸãã ãã¹ãŠã®PSPãœãŒã¹ã¯ã ãã® homebrew SDKã§ã³ã³ãã€ã«ãããŠããŸãã
PSPãã©ã°ã€ã³ã®ãœãŒã¹ã³ãŒãã®å€æŽã ããã¯
å€æŽãããã©ã°ã€ã³ãããžã§ã¯ãã®åºç€ãšããŠãUSBã¯ã©ã€ã¢ã³ãã®äœæ¥ã³ãŒããæ¢ã«å«ãŸããŠãããã®ãéžæããŸããã ããããéåžžã®ãããã°ãšäžè¬çã«å± å¿å°ã®è¯ãé°å²æ°ã®ããã«ãprintfïŒïŒãå¿ èŠã§ããã PSPã§ã éžæãããã©ã°ã€ã³ã«ã¯ãããŸããã§ããã ããããPSPã³ã³ãããŒã«ã€ãã³ããã€ã³ã¿ãŒã»ããããããã®äœæ¥ã³ãŒããååŸããããã©ã°ã€ã³ã§ã¯ã次ã®ãã¬ãŒã ããã¬ãŒã ãããã¡ãŒã«æç»ããæ©èœãã€ã³ã¿ãŒã»ããããå¿ èŠãªãããã°ã©ã€ã³ããã¬ãŒã ã«è¿œå ããããšã§å®è£ ãããŸããã ã¬ã³ããªã³ã°èªäœã®ãã£ããã£æ©èœïŒããã¯ïŒã¯ã次ã®ããã«å®è£ ãããŸãã
#define GET_JUMP_TARGET_(x) (0x80000000 | (((x) & 0x03FFFFFF) << 2)) int (*g_setframebuf)(int unk, void* addr, int width, int psm, int sync); int setframebuf_hook_func(int unk, void* addr, int width, int psm, int sync) { if(g_info == 1) { dbgprint( debugmsg, addr, psm ); if (!g_info) DEBUG_RESET() } return g_setframebuf(unk, addr, width, psm, sync); } int hook_function(unsigned int* jump, void* hook, unsigned int* result) { unsigned int target; unsigned int func; int inst; target = GET_JUMP_TARGET_(*jump); while (((inst = _lw(target+4)) & ~0x03FFFFFF) != 0x0C000000) // search next JAL instruction target += 4; if((inst & ~0x03FFFFFF) != 0x0C000000) { printf("invalid!\n"); return 1; } *result = GET_JUMP_TARGET_(inst); func = (unsigned int) hook; func = (func & 0x0FFFFFFF) >> 2; _sw(0x0C000000 | func, target+4); return 0; } int module_start( SceSize args, void *argp ) { //... hook_function( (unsigned int*) sceDisplaySetFrameBuf, setframebuf_hook_func, (unsigned int*)&g_setframebuf ); //... }
hook_functionïŒïŒãåŒã³åºããåŸãPSPãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã¯ããã®å éšã«ãŒãã«é¢æ°ãåŒã³åºããšãã«ãsceDisplaySetFrameBufïŒïŒãå®éã«setframebuf_hook_funcïŒïŒãåŒã³åºããŸãã å ã®sceDisplaySetFrameBufïŒïŒãåŒã³åºãã«ã¯ãg_setframebufïŒïŒãåŒã³åºãå¿ èŠããããŸãã ããšãã°ãããã¯ã®ãããã¯ã«èå³ããã人ã¯ã ããã§ãã詳现ã«èŠã€ããããšãã§ããŸãã
PSPãã©ã°ã€ã³ã®ãœãŒã¹ã³ãŒãã®å€æŽã 管çã
次ã«ã管çé¢æ°sceCtrlReadBufferPositiveïŒïŒãsceCtrlPeekBufferPositiveïŒïŒãsceCtrlReadBufferNegativeïŒïŒãããã³sceCtrlPeekBufferNegativeïŒïŒã§å€æŽããã¯ãŒã¯ããã¯ããããžã§ã¯ãã«è¿œå ããåãJoySensããååŸããŸãã ãããã®å éšã®å ¥åããŒã¿ããPCãã¹ãã«æ¥ç¶ãããã²ãŒã ãããã®ç¶æ ã«ã€ããŠPSPã«æåŸã«éä¿¡ãããããŒã¿ã§ããããšã確èªããŸããã å¿ èŠãªãã¹ãŠã®ãã€ããªãšãœãŒã¹ã³ãŒããå«ãã¢ãŒã«ã€ãã次ã«ç€ºããŸãã ããã°ã©ã ã®PCéšåãéå§ããåã«ãUSBãã©ã€ããŒãã€ã³ã¹ããŒã«ããå¿ èŠããããŸãã ãŸããPSPã§ãã©ã°ã€ã³ãå®è¡ããå¿ èŠããããŸãïŒYandexã§ã°ãŒã°ã«ã§ãã©ã°ã€ã³ãå®è¡ããæ¹æ³ãèŠã€ããããšãã§ããŸãïŒã 次ã«ãPSPãåèµ·åããPCã«æ¥ç¶ããŸãã PSPã¿ã€ãBããã€ã¹ãæ€åºãããã¯ãã§ãã次ã«ã ãã©ã€ããŒãããŠã³ããŒãããŸãã ãŠã£ã¶ãŒãïŒbin \ inf-wizard.exeïŒã䜿çšããŠãã©ã€ããŒãã€ã³ã¹ããŒã«ããPSP Type Bããã€ã¹ããã€ã³ãããŠãæåŸã«ãã©ã€ããŒãã€ã³ã¹ããŒã«ããããæ瀺ããŸãã
æå°PSPããŒãžã§ã³ã®æºå
ãã¹ãŠåé¡ãããŸãããããããã¯ãŒã¯ã«ã¯ããŒãžã§ã³0.19 RemoteJoyLiteã®ãœãŒã¹ã³ãŒãã®ã¿ããããŸãã ãŸããäžéšã®ã²ãŒã ã§ã¯æ£åžžã«åäœããŸããïŒããšãã°ã K-OnïŒã¯éåžžã«é ãã Dungeon Siegeã«ã°ã©ãã£ãã¯ã¢ãŒãã£ãã¡ã¯ãã衚瀺ãããŸãïŒã ããŒãžã§ã³0.20ã§ã¯ãããã¯ä¿®æ£ããããšèšãããŠããŸããããã®ããŒãžã§ã³ã®ãœãŒã¹ã³ãŒãã¯å ¬éãããŠããŸããã ãããã£ãŠãã²ãŒã ãããã®ç¶æ ã«é¢ããæå°éã®æ å ±ã®ã¿ãéä¿¡ããPSPããŒãã®ãœãŒã¹ã®ãµã€ãºãæå°åããããã«ãUSBãä»ããŠéä¿¡ãããããŒã¿ã®ãããã³ã«ãå€æŽããããšã決å®ãããŸããã PSPããPCã«è»¢éããããã¹ãŠã®ããŒã¿ã¯ãããã³ã«ããåé€ããã1ã€ã®æ§é ã®ã¿ãPCããPSPã«è»¢éãããŸããããã®çµæããã¬ãŒããšã¢ãŒãã£ãã¡ã¯ãã¯å¿ãå»ãããŸããã
#define USBDATA_PATTERN 0x1234ABFE struct { unsigned int Pattern; unsigned int ButtonData; unsigned int AnalogX; unsigned int AnalogY; } PSPUsbData;
PSPèªäœã®ã¹ãã£ãã¯ããã®ã¢ããã°ããŒã¿ã¯ãå軞ã®ã·ã³ã°ã«ãã€ãã®ç¬Šå·ãªãæŽæ°ãšããŠæ瀺ããïŒ127ãäžå¿ïŒããããã³ã«ã®4ãã€ããå²ãåœãŠãããŸããããã¯ãæ§é ã®ãããã³ã°ãšã¢ã©ã€ã¡ã³ãã®åé¡ããèããªãããã§ãã RemoteJoyLiteèªäœã§ã¯ãããŒã¿ã¯æ¬¡ã®ããã«ããã¯ãããŸãã
struct HostFsCmd { uint32_t magic; uint32_t command; uint32_t extralen; } __attribute__((packed));
ãããŠã察å¿ããåé¡ã«ã€ããŠèããããšããããªãããã«ïŒçµå±ãRemoteJoyLiteèªäœã¯MinGW GCCã«ãã£ãŠã³ã³ãã€ã«ããã次ã®ã¹ãããã¯Microsoft Visual Studioã§ãããžã§ã¯ããäœæãã__ attribute __ïŒïŒpackedïŒïŒãç¥ããªãåãæšãŠããããããã³ã«ã解決ããããšã§ãïŒããã¹ãŠã®ã¢ã©ã€ã¡ã³ããšããã±ãŒãžæ§é ãåé€ããŸãããããã32ãããè¡šçŸã«ããŸãã ãã®çµæã ãã®ã¢ãŒã«ã€ãã«ã¯ãPSPãšWindowsã®äž¡æ¹ã®éšåã§ãããåé€ããããããžã§ã¯ãã®ãœãŒã¹ã³ãŒããšãã€ããªãå«ãŸããŠããŸãã Windowsã¢ããªã±ãŒã·ã§ã³ã¯ãMicrosoft Visual Studio 2010ã®C ++ã®mfcãããžã§ã¯ããšããŠèšèšãããŠããŸããWindowsããã°ã©ããŒã«ãšã£ãŠãã«ãŒãœã«å¶åŸ¡ããŒã¹ãããŒã¯ã®å®è£ æ¹æ³ã確èªãããšåœ¹ç«ã¡ãŸãïŒmfcã¢ããªã±ãŒã·ã§ã³ã§ã¯ãã¢ããªã±ãŒã·ã§ã³å šäœã®ãŠã£ã³ããŠã¡ãã»ãŒãžãã£ã«ã¿ãŒã«ããå Žåã«ã®ã¿æ©èœãããã€ã¢ãã°ã®ããŒã¹ãããŒã¯ã§ã¯ãªãïŒããŸããå¥ã®ã¹ããªãŒã ããã§ãprintfïŒïŒããã©ãŒã äžã§æ£ããæ©èœããããã§ãã PSPããŒãã§ã¯ãUSBãcontrolãprintfïŒïŒã®ã¿ãæ®ãããŠãããæ¥ç¶ããã軜éãœãŒã¹ãç 究ããããšã¯èå³æ·±ãã§ãããã ããšãã°ãUSBããŒã¿åä¿¡ã¯éåæã§ã次ã®ããã«å®è£ ãããŸãã USBãã¹ãã«æ¥ç¶ãããšããUSBãã¹ã®å éšã¢ãã¬ã¹ãååŸããæ£ããæé ïŒUSBã®èª¬æãåç §ïŒã®åŸãUsbAttachïŒïŒåŒã³åºããè¡ãããŸããããã¯ããã®åŒã³åºããåæåäžã«ç»é²ããããã©ã€ããŒæ§é ã«èšè¿°ãããŠããããã§ãïŒ
#define RJLITE_DRIVERNAME "RJLiteDriver" #define RJLITE_DRIVERPID (0x1C9) struct UsbDriver UsbDriver = { RJLITE_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 }; int module_start( SceSize args, void *argp ) { //... sceUsbbdRegister(&UsbDriver); if((sceUsbStart(PSP_USBBUS_DRIVERNAME, 0, 0) == 0) && (sceUsbStart(RJLITE_DRIVERNAME, 0, 0) == 0) && //... { //... } //... }
ããã§ãmodule_startïŒïŒã¯ããã©ã°ã€ã³ãæµ·è³çãã¡ãŒã ãŠã§ã¢ã§èµ·åãããšãã«å¥ã®ã¹ã¬ããã§åŒã³åºãããé¢æ°ã§ãã ãŸãããã©ã€ããŒãèµ·åãããšãintåã®ãã©ã°å€æ°ïŒã€ãŸã32ãã©ã°ïŒãäœæãããPSPãªãã¬ãŒãã£ã³ã°ã·ã¹ãã å ã®ãªããžã§ã¯ãã®äžæã®èå¥åãä»ããŠã¢ã¯ã»ã¹ãããè£å©ã¹ããªãŒã ãèµ·åãããŸãã
static SceUID UsbMainEventFlag = -1; static int UsbStartFunc( int size, void *p ) { //... UsbMainEventFlag = sceKernelCreateEventFlag( "USBMainEvent", 0x200, 0, NULL ); //... UsbMainThreadID = sceKernelCreateThread( "USBMainThread", UsbMainThread, 10, 0x10000, 0, NULL ); //... sceKernelStartThread( UsbMainThreadID, 0, NULL ); //... }
ãããã£ãŠãUsbAttachïŒïŒãšåŒã°ãããšãUsbMainEventFlagãªããžã§ã¯ãã®ãã©ã°å€æ°ã«ãã©ã°USB_EVENT_ATTACHãèšå®ãããŸãã
static int UsbAttach(int speed, void *arg2, void *arg3) { sceKernelSetEventFlag( UsbMainEventFlag, USB_EVENT_ATTACH); return 0; }
åæã«ãUsbStartFuncïŒïŒãåŒã³åºããšãã«ä»¥åã«äœæãããUsbMainThreadïŒïŒã¹ã¬ããã§ã¯ã次ã®ããã«è¡šç€ºãããŸãã
static int UsbMainThread(SceSize size, void *argp) { int ret; u32 result; while(1) { ret = sceKernelWaitEventFlag(UsbMainEventFlag, USB_EVENT_ATTACH | USB_EVENT_ASYNC, PSP_EVENT_WAITOR | PSP_EVENT_WAITCLEAR, &result, NULL); if(ret < 0) { sceKernelExitDeleteThread(0); } if(result&USB_EVENT_ASYNC) { usb_async_events++;//nyashkoshkko: debug SetUsbAyncReq(&PSPUsbData, sizeof(PSPUsbData)); } if(result&USB_EVENT_ATTACH) { usb_attach_events++;//nyashkoshkko: debug SetUsbAyncReq(&PSPUsbData, sizeof(PSPUsbData)); } } return 0; }
ã€ãŸããç¡éã«ãŒãå ã®ã¹ã¬ããã¯ãUSB_EVENT_ATTACHãã©ã°ãŸãã¯USB_EVENT_ASYNCãã©ã°ãUsbMainEventFlagãªããžã§ã¯ãã®ãã©ã°å€æ°ã«èšå®ãããã®ãåŸ æ©ããŸãã USBãã¹ããšã®æ¥ç¶ã«æåãããšãUSB_EVENT_ASYNCãã©ã°ããªã»ãããããUSB_EVENT_ATTACHãã©ã°ãèšå®ãããŸããããã«ããããã®ã¹ã¬ããã¯USB_EVENT_ASYNCãã©ã°ããªã»ããããªãããUSBçµç±ã§ããŒã¿ãã±ãããåä¿¡ããéåæèŠæ±ãå®è¡ããŸãã
static int SetUsbAyncReq( void *data, int size ) { //... UsbAsyncReq.data = data; UsbAsyncReq.size = size; UsbAsyncReq.func = UsbAsyncReqDone; sceKernelClearEventFlag( UsbMainEventFlag, ~USB_EVENT_ASYNC ); return( sceUsbbdReqRecv( &UsbAsyncReq ) ); }
ãã®ãªã¯ãšã¹ãã§ã¯ãã³ãŒã«ããã¯ã¯UsbAsyncReqDoneïŒïŒé¢æ°ã®åŒã³åºããã»ããã¢ããããŸãã
static int UsbAsyncReqDone( struct UsbdDeviceReq *req, int arg2, int arg3 ) { sceKernelSetEventFlag( UsbMainEventFlag, USB_EVENT_ASYNC ); return( 0 ); }
ãã®é¢æ°ã¯ãã芧ã®ãšãããUSBãã¹ãããã®ããŒã¿ãã±ããã®åä¿¡ãå®äºãããšïŒPSP USBã³ã³ãããŒã©ãŒããã®å²ã蟌ã¿ã«ãã£ãŠPSPãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã«ãŒãã«ã«ãã£ãŠåŠçãããŸãïŒãUsbMainEventFlagãªããžã§ã¯ãã®ãã©ã°å€æ°ã«ãã©ã°USB_EVENT_ASYNCãèšå®ããŸãã ãã®äžã§ãç¡éã«ãŒããæ°ããéåæããŒã¿èŠæ±ãã»ããã¢ããããŸãã ãã®ãããªã€ãã³ãã¡ã«ããºã ã䜿çšãããšãsceKernelWaitEventFlagïŒïŒãåŒã³åºããšãå¿ èŠãªã€ãã³ããçºçãããŸã§ã¹ããªãŒã ã«ã¿ã€ã ã¹ã©ã€ã¹ãå²ãåœãŠãããªããããããŒã¿ã¬ãã£ãã©ã°ãç¡éã«ããŒãªã³ã°ããããã«CPUæéã浪費ããããšã¯ã§ããŸãã-ããã¯PSPãªãã¬ãŒãã£ã³ã°ã·ã¹ãã å ã®ã¹ã¬ããã¹ã±ãžã¥ãŒã©ãŒã«ãã£ãŠä¿èšŒãããŸãåºæ¬ååã¯ããã«ãã¿ã¹ã¯ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã§æ©èœããŸãã
Raspberry Piã§LinuxçšUSBã䜿çšããããã®ãµãŒãã¹ãäœæãã
ããã§ãPSPããŒããå®æããŸããã Linuxã§Raspberry Piããªã³ã«ãªã£ããšãã«èªåçã«éå§ãããã¢ããªã±ãŒã·ã§ã³ããŸãã¯ããããµãŒãã¹ãéçºãããšãã§ãã äžè¬ã«ãRaspberry Piçšã®Linuxãã£ã¹ããªãã¥ãŒã·ã§ã³ãããã€ããããŸãã ããããç§ã¯Fedoraã«èœã¡çããŸããã 圌ã¯Red Hatã«ã«ãŒããæã£ãŠããŸããRedHatã§ç§ã¯ä»äºãããã®ã¯ç°¡åãªä»äºã§ã圌ã®ããã±ãŒãžé åžRPMã«æ £ããŸããã Fedora Remix 18ãã€ã³ã¹ããŒã«ããå¿ èŠã«å¿ããŠãããã¯ãŒã¯ãã»ããã¢ããããçŽåŸïŒç§ã®å ŽåãããŒã ãããã¯ãŒã¯ã®DHCPãµãŒããŒãæ£ããæ©èœããªãããããããã¯ãŒã¯ã¢ãã¬ã¹ãšã²ãŒããŠã§ã€ãæåã§èšå®ããå¿ èŠããããŸããïŒãããŠã¹ãæ¥ç¶ããŠã¯ãªãã¯ããå³äžé ã®ãããã¯ãŒã¯æ¥ç¶ã¢ã€ã³ã³ãSSHãµãŒããŒã¯ããã¯ã¹ããçŽæ¥åäœããŸãã ãã ããSMBãµãŒããŒããã°ããæ§æããããšã¯ã§ããªãã£ãããïŒsmbpasswdã®åé¡ïŒããœãŒã¹ã¯æ·±å€ã®åžä»€å®ãä»ããŠSSHçµç±ã§ãªã¢ãŒãã§äœæããã³ç·šéãããŸããã æåã«å§ããã®ã¯ãPSPãžã®æ¥ç¶ã§ãã ãããè¡ãã«ã¯ãLinuxã§USBãšå¯Ÿè©±ããæ¹æ³ãåŠã¶å¿ èŠããããŸããã ãã®ç¹ã§ãã¡ãã£ãšäžæå¿«ãªè©±ããããŸããããã®ããããã¯ãLinuxã®é åå šäœãç§ã®ç®ã®åã§åŽ©ããŠããŸãã äºå®ã¯ãã³ã³ãã€ã«ã®ããã«ã©ã€ãã©ãªãšããããŒãã€ã³ã¹ããŒã«ããããšãããš
> yum install libusb1-devel
ããã±ãŒãžãããŒãžã£ãŒã¯æŠããããŠãããæéåãã ãšèšããŸãããlibusbxã䜿çšããŠãã ããã OKããŒã
> yum install libusbx-devel
å¿ èŠãªãã¡ã€ã«ãããŠã³ããŒãããŸããã ããããå®éã«ã¯ãapiåŒã³åºãã®libusbxã¯libusb1ãšäºææ§ããããŸãããlibusb1ã¯ãWindowsããŒãžã§ã³ã®libusbãšåãã§ããããã¯ãå ã®RemoteJoyLiteãœãŒã¹ã§äœ¿çšãããéåžžã¯Windowsã§æ£åžžã«åäœããŸãã ã§ã倧äžå€«ã usbãæŽçããããã次ã«Linuxããã²ãŒã ãããã«ã¢ã¯ã»ã¹ããŸãã ç§ã¯èªç±ã«äœ¿ããXbox 360ã²ãŒã ããããWindowsã§äœ¿ããé©ãã»ã©ãRaspberry Piã®Fedora Remix 18ã§ç®±ããåºããŠãããã€ã¹/ dev / input / js0ãäœæããŸãã ã ããã«ãããéåžžã®xpadãã©ã€ããŒãæ©èœããŸããã 代æ¿ã®xboxdrvãã©ã€ããŒããããŸã-ããæè»ã«æ§æã§ããŸãã ããããç§ãã¡ã«ã¯ååãªãã«ã¿ã€ã ããããŸãã
ãšããã§ãã¢ã³ããã€ãã¯ãŸã£ããåãã§ãã
xpadãã©ã€ããŒã¯ ãAndroidã®Linuxã«ãŒãã«ã®äžéšã§ãã
åæ§ã«ãããã€ã¹/ dev / input / js0ãäœæãããŸãïŒ
ããšãã°ãAndroidã§å ¥åããã€ã¹ã®ãªã¹ããååŸããæ¹æ³ãæ€èšããŠãã ããã æšå¥šãããAPIã¯ãgetDeviceIdsïŒïŒãåŒã³åºãããšã§ãããè¡ãããã«æ瀺ããŸãã
getInputDeviceIdsïŒïŒ ïŒ
mIm.getInputDeviceIdsïŒïŒ ïŒ
ãããInputManagerãµãŒãã¹ã®åºçªã§ãã
getIdïŒïŒã¯ãç§ãã¡ãããå Žæã«æ¢ã«é£ããŠè¡ã£ãŠãããŸãïŒã¢ã³ããã€ãã¯çŽ æŽãããã§ãïŒïŒ
Androidã®ãã€ãã£ãéšåã§ã¯ãInputDeviceïŒïŒã®ã€ã³ã¹ã¿ã³ã¹ãããã«äœæãããŸã ïŒ toasterããã®è¿ éãªå¿çã®ãããïŒïŒ
ãã®é¢æ°ã¯ããã§åŒã³åºãããŸã ïŒ
notifyInputDevicesChangedïŒïŒé¢æ°ã®åŒã³åºãã¯ããã§ã«ããç¥ãããŠããInputManagerãµãŒãã¹ã®ã³ãŒã«ããã¯ã«ãã£ãŠå床決å®ãããŸãã
ã³ãŒã«ããã¯èªäœã®åŒã³åºãã¯InputReaderã§éå§ãããŸã ã
ãŸããããã§ã¯ãå ¥åããã€ã¹ããã®ã€ãã³ããEventHubInterfaceã¯ã©ã¹ã«ãã£ãŠåä¿¡ãããããšãããããŸãã
ãããŠãæåŸã«ããã®ã¯ã©ã¹EventHub.cppã®å®è£ ã§ã¯ãRaspberry Piã®éåžžã®Linux Fedoraã®ããã«ã/ dev / inputããããã€ã¹ãéããŠæäœããŸãã
äžè¬ã«ãAndroidã®ãã®å ¥åã·ã¹ãã å šäœã«ã€ããŠã¯ããœãŒã¹ã³ãŒãèªäœã§ç°¡åã«èª¬æãããŠããŸã ã
#define DRIVER_DESC "X-Box pad driver"
åæ§ã«ãããã€ã¹/ dev / input / js0ãäœæãããŸãïŒ
MODULE_SUPPORTED_DEVICE("input/js");
ããšãã°ãAndroidã§å ¥åããã€ã¹ã®ãªã¹ããååŸããæ¹æ³ãæ€èšããŠãã ããã æšå¥šãããAPIã¯ãgetDeviceIdsïŒïŒãåŒã³åºãããšã§ãããè¡ãããã«æ瀺ããŸãã
/** * Gets the ids of all input devices in the system. * @return The input device ids. */ public static int[] getDeviceIds() { return InputManager.getInstance().getInputDeviceIds(); }
getInputDeviceIdsïŒïŒ ïŒ
private final IInputManager mIm; //... private SparseArray<InputDevice> mInputDevices; //... /** * Gets the ids of all input devices in the system. * @return The input device ids. */ public int[] getInputDeviceIds() { synchronized (mInputDevicesLock) { populateInputDevicesLocked(); final int count = mInputDevices.size(); final int[] ids = new int[count]; for (int i = 0; i < count; i++) { ids[i] = mInputDevices.keyAt(i); } return ids; } } //... private void populateInputDevicesLocked() { if (mInputDevicesChangedListener == null) { final InputDevicesChangedListener listener = new InputDevicesChangedListener(); try { mIm.registerInputDevicesChangedListener(listener); } catch (RemoteException ex) { throw new RuntimeException( "Could not get register input device changed listener", ex); } mInputDevicesChangedListener = listener; } if (mInputDevices == null) { final int[] ids; try { ids = mIm.getInputDeviceIds(); } catch (RemoteException ex) { throw new RuntimeException("Could not get input device ids.", ex); } mInputDevices = new SparseArray<InputDevice>(); for (int i = 0; i < ids.length; i++) { mInputDevices.put(ids[i], null); } } }
mIm.getInputDeviceIdsïŒïŒ ïŒ
interface IInputManager { // Gets input device information. InputDevice getInputDevice(int deviceId); int[] getInputDeviceIds(); //...
ãããInputManagerãµãŒãã¹ã®åºçªã§ãã
import android.view.InputDevice; //... /* * Wraps the C++ InputManager and provides its callbacks. */ public class InputManagerService extends IInputManager.Stub implements Watchdog.Monitor, DisplayManagerService.InputManagerFuncs { static final String TAG = "InputManager"; static final boolean DEBUG = false; private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml"; //... private InputDevice[] mInputDevices = new InputDevice[0]; //... /** * Gets the ids of all input devices in the system. * @return The input device ids. */ @Override // Binder call public int[] getInputDeviceIds() { synchronized (mInputDevicesLock) { final int count = mInputDevices.length; int[] ids = new int[count]; for (int i = 0; i < count; i++) { ids[i] = mInputDevices[i].getId(); } return ids; } }
getIdïŒïŒã¯ãç§ãã¡ãããå Žæã«æ¢ã«é£ããŠè¡ã£ãŠãããŸãïŒã¢ã³ããã€ãã¯çŽ æŽãããã§ãïŒïŒ
public final class InputDevice implements Parcelable { private final int mId; //... /** * Gets the input device id. * <p> * Each input device receives a unique id when it is first configured * by the system. The input device id may change when the system is restarted or if the * input device is disconnected, reconnected or reconfigured at any time. * If you require a stable identifier for a device that persists across * boots and reconfigurations, use {@link #getDescriptor()}. * </p> * * @return The input device id. */ public int getId() { return mId; } //... // Called by native code. private InputDevice(int id, int generation, int controllerNumber, String name, int vendorId, int productId, String descriptor, boolean isExternal, int sources, int keyboardType, KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasButtonUnderPad) { mId = id; mGeneration = generation; mControllerNumber = controllerNumber; mName = name; mVendorId = vendorId; mProductId = productId; mDescriptor = descriptor; mIsExternal = isExternal; mSources = sources; mKeyboardType = keyboardType; mKeyCharacterMap = keyCharacterMap; mHasVibrator = hasVibrator; mHasButtonUnderPad = hasButtonUnderPad; } private InputDevice(Parcel in) { mId = in.readInt(); mGeneration = in.readInt(); mControllerNumber = in.readInt(); mName = in.readString(); mVendorId = in.readInt(); mProductId = in.readInt(); mDescriptor = in.readString(); mIsExternal = in.readInt() != 0; mSources = in.readInt(); mKeyboardType = in.readInt(); mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in); mHasVibrator = in.readInt() != 0; mHasButtonUnderPad = in.readInt() != 0; for (;;) { int axis = in.readInt(); if (axis < 0) { break; } addMotionRange(axis, in.readInt(), in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); } }
Androidã®ãã€ãã£ãéšåã§ã¯ãInputDeviceïŒïŒã®ã€ã³ã¹ã¿ã³ã¹ãããã«äœæãããŸã ïŒ toasterããã®è¿ éãªå¿çã®ãããïŒïŒ
jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& deviceInfo) { //... ScopedLocalRef<jobject> inputDeviceObj(env, env->NewObject(gInputDeviceClassInfo.clazz, gInputDeviceClassInfo.ctor, deviceInfo.getId(), deviceInfo.getGeneration(), deviceInfo.getControllerNumber(), nameObj.get(), static_cast<int32_t>(ident.vendor), static_cast<int32_t>(ident.product), descriptorObj.get(), deviceInfo.isExternal(), deviceInfo.getSources(), deviceInfo.getKeyboardType(), kcmObj.get(), deviceInfo.hasVibrator(), deviceInfo.hasButtonUnderPad()));
ãã®é¢æ°ã¯ããã§åŒã³åºãããŸã ïŒ
void NativeInputManager::notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) { JNIEnv* env = jniEnv(); //... jobject inputDeviceObj = android_view_InputDevice_create(env, inputDevices.itemAt(i));
notifyInputDevicesChangedïŒïŒé¢æ°ã®åŒã³åºãã¯ããã§ã«ããç¥ãããŠããInputManagerãµãŒãã¹ã®ã³ãŒã«ããã¯ã«ãã£ãŠå床決å®ãããŸãã
// Native callback. private void notifyInputDevicesChanged(InputDevice[] inputDevices) { synchronized (mInputDevicesLock) { if (!mInputDevicesChangedPending) { mInputDevicesChangedPending = true; mHandler.obtainMessage(MSG_DELIVER_INPUT_DEVICES_CHANGED, mInputDevices).sendToTarget(); } mInputDevices = inputDevices; } }
ã³ãŒã«ããã¯èªäœã®åŒã³åºãã¯InputReaderã§éå§ãããŸã ã
void InputReader::loopOnce() { //... size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); //... // Send out a message that the describes the changed input devices. if (inputDevicesChanged) { mPolicy->notifyInputDevicesChanged(inputDevices); }
ãŸããããã§ã¯ãå ¥åããã€ã¹ããã®ã€ãã³ããEventHubInterfaceã¯ã©ã¹ã«ãã£ãŠåä¿¡ãããããšãããããŸãã
sp<EventHubInterface> mEventHub;
ãããŠãæåŸã«ããã®ã¯ã©ã¹EventHub.cppã®å®è£ ã§ã¯ãRaspberry Piã®éåžžã®Linux Fedoraã®ããã«ã/ dev / inputããããã€ã¹ãéããŠæäœããŸãã
static const char *DEVICE_PATH = "/dev/input"; //... char devname[PATH_MAX]; char *filename; //... strcpy(devname, DEVICE_PATH); filename = devname + strlen(devname); *filename++ = '/'; //... strcpy(filename, event->name); //... openDeviceLocked(devname); //... status_t EventHub::openDeviceLocked(const char *devicePath) { char buffer[80]; ALOGV("Opening device: %s", devicePath); int fd = open(devicePath, O_RDWR | O_CLOEXEC); if(fd < 0) { ALOGE("could not open %s, %s\n", devicePath, strerror(errno)); return -1; }
äžè¬ã«ãAndroidã®ãã®å ¥åã·ã¹ãã å šäœã«ã€ããŠã¯ããœãŒã¹ã³ãŒãèªäœã§ç°¡åã«èª¬æãããŠããŸã ã
/* * The input manager is the core of the system event processing. * * The input manager uses two threads. * * 1. The InputReaderThread (called "InputReader") reads and preprocesses raw input events, * applies policy, and posts messages to a queue managed by the DispatcherThread. * 2. The InputDispatcherThread (called "InputDispatcher") thread waits for new events on the * queue and asynchronously dispatches them to applications. * * By design, the InputReaderThread class and InputDispatcherThread class do not share any * internal state. Moreover, all communication is done one way from the InputReaderThread * into the InputDispatcherThread and never the reverse. Both classes may interact with the * InputDispatchPolicy, however. * * The InputManager class never makes any calls into Java itself. Instead, the * InputDispatchPolicy is responsible for performing all external interactions with the * system, including calling DVM services. */ class InputManagerInterface : public virtual RefBase {
ãããã£ãŠããµãŒãã¹ã®æçµãœãŒã¹ã³ãŒãã¯æ¬¡ã®åœ¢åŒã«ãªããŸãã
#include <stdio.h> #include <stdlib.h> #include <termios.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <libusb-1.0/libusb.h> #define SONY_VENDOR_ID 0x054C #define PSP_B_PRODUCT_ID 0x01C9 #define UP 0x00000010 #define DOWN 0x00000040 #define LEFT 0x00000080 #define RIGHT 0x00000020 #define B_X 0x00004000 #define B_O 0x00002000 #define B_KVADRAT 0x00008000 #define B_TREUGOLNIK 0x00001000 #define B_L 0x00000100 #define B_R 0x00000200 #define B_SELECT 0x00000001 #define B_START 0x00000008 #define B_NOTE 0x00800000 struct { unsigned int Pattern; unsigned int Btn; unsigned int X; unsigned int Y; } PS = {0x1234ABFE, 0, 127, 127}; struct js_event { unsigned int time; short value; unsigned char type; unsigned char number; }; int is_usbdevblock(libusb_device *dev) { struct libusb_device_descriptor desc; int r = libusb_get_device_descriptor(dev, &desc); if((desc.idVendor == SONY_VENDOR_ID) && (desc.idProduct == PSP_B_PRODUCT_ID)) { return 1; } return 0; } int main(int argc, char** argv) { unsigned int real_x = 0, real_y = 0; int x, y; int fd = 0; while(1) { libusb_device **list; libusb_device *found = NULL; libusb_context *ctx = NULL; int attached = 0; libusb_init(&ctx); libusb_set_debug(ctx, 3); ssize_t cnt = libusb_get_device_list(ctx, &list); ssize_t i = 0; int err = 0; if(cnt < 0) { return -1; } for(i = 0; i < cnt; i++) { libusb_device *device = list[i]; if(is_usbdevblock(device)) { found = device; break; } } if(found) { libusb_device_handle *handle; err = libusb_open(found, &handle); if (err) { return -1; } if (libusb_kernel_driver_active(handle, 0)) { libusb_detach_kernel_driver(handle, 0); attached = 1; } err = libusb_claim_interface(handle, 0); if (err) { return -1; } if(fd == 0) { fd = open("/dev/input/js0", O_RDONLY); } if(fd < 0) { goto clean; } int nEndpoint = 0x01; int nTimeout = 500; //in milliseconds int BytesWritten = 0; int ret; struct js_event e; int t; while(1) { read(fd, &e, sizeof(struct js_event)); e.type &= ~0x80; t = 0; //transfer = 0; if(e.type == 1) { if(e.value == 1) { if(e.number == 0) {PS.Btn |= B_X; t = 1;} if(e.number == 1) {PS.Btn |= B_O; t = 1;} if(e.number == 2) {PS.Btn |= B_KVADRAT; t = 1;} if(e.number == 3) {PS.Btn |= B_TREUGOLNIK; t = 1;} if(e.number == 4) {PS.Btn |= B_L; t = 1;} if(e.number == 5) {PS.Btn |= B_R; t = 1;} if(e.number == 6) {PS.Btn |= B_SELECT; t = 1;} if(e.number == 7) {PS.Btn |= B_START; t = 1;} if(e.number == 8) {PS.Btn |= B_NOTE; t = 1;}//XBOX_HOME //if(e.number == 9) PS.Btn |= ;//L_STICK_PRESS //if(e.number == 10)PS.Btn |= ;//R_STICK_PRESS } if(e.value == 0) { if(e.number == 0) {PS.Btn &= ~B_X; t = 1;} if(e.number == 1) {PS.Btn &= ~B_O; t = 1;} if(e.number == 2) {PS.Btn &= ~B_KVADRAT; t = 1;} if(e.number == 3) {PS.Btn &= ~B_TREUGOLNIK; t = 1;} if(e.number == 4) {PS.Btn &= ~B_L; t = 1;} if(e.number == 5) {PS.Btn &= ~B_R; t = 1;} if(e.number == 6) {PS.Btn &= ~B_SELECT; t = 1;} if(e.number == 7) {PS.Btn &= ~B_START; t = 1;} if(e.number == 8) {PS.Btn &= ~B_NOTE; t = 1;} } } if(e.type == 2) { if(e.number == 6) { if(e.value == -32767) {PS.Btn |= LEFT; t = 1;} if(e.value == 32767) {PS.Btn |= RIGHT; t = 1;} if(e.value == 0) {PS.Btn &= ~(LEFT | RIGHT); t = 1;} } if(e.number == 7) { if(e.value == -32767) {PS.Btn |= UP; t = 1;} if(e.value == 32767) {PS.Btn |= DOWN; t = 1;} if(e.value == 0) {PS.Btn &= ~(UP | DOWN); t = 1;} } if(e.number == 0) { if(real_x != ((e.value + 32767) / 256)) {real_x = ((e.value + 32767) / 256); t = 1;} } if(e.number == 1) { if(real_y != ((e.value + 32767) / 256)) {real_y = ((e.value + 32767) / 256); t = 1;} } } if(t == 1) { #define KOEF 1.4 //[-128..0..127] x = real_x - 128; y = real_y - 128; x = x * (1. + ((abs(x) * (KOEF-1.))/(127./KOEF))); if(x > 127) x = 127; if(x < -128) x = -128; y = y * (1. + ((abs(y) * (KOEF-1.))/(127./KOEF))); if(y > 127) y = 127; if(y < -128) y = -128; PS.X = 128 + x; PS.Y = 128 + y; ret = libusb_bulk_transfer(handle, nEndpoint, (unsigned char *)&PS, sizeof(PS), &BytesWritten, nTimeout); if(ret < 0) { break; } } } clean: if(fd) { close(fd); fd = 0; } if(attached == 1) { libusb_attach_kernel_driver(handle, 0); } libusb_close(handle); } libusb_free_device_list(list, 1); libusb_exit(ctx); sleep(1); } return 0; }
ããã¯ãµãŒãã¹ãã€ããªãžã®ãªã³ã¯ã§ãã ãŸããm.shã³ã³ãã€ã«ã¹ã¯ãªããã®å 容ã次ã®ãšããã§ãã
gcc xbox2psp.c -o xbox2psp.o -I/usr/local -L/usr/local -lusb-1.0
ãœãŒã¹èªäœã«ãããšãç§ã¯2ã€ã®ç¹ã«æ³šæããããšæããŸãã ãŸããXboxã¢ããã°ã¹ãã£ãã¯ã®ç²ŸåºŠã¯16ãããã§ãããPSPã¹ãã£ãã¯ã®ç²ŸåºŠã¯8ãããã§ãã ãã®ç¹ã§ãXboxã³ã³ãããŒã©ãŒããã®ãœãŒã¹ããŒã¿ãå€æŽããã«ã8ãããã«çž®å°ããã軞ã®å€ãå€æŽããããã«ããã±ãŒãžãéä¿¡ããŸãã 第äºã«ãPSPã§ã¯ã察è§ç·ã®å€ã¯ãã«ã¹ã±ãŒã«ã«å¯Ÿå¿ããŸãïŒã€ãŸããã¹ã±ãŒã«ã«é¢ããäžžãPSPã¹ãã£ãã¯ã¯æ£æ¹åœ¢ã§ãïŒããããŠXboxã§ã¯ãããã§ããããã«ãã¹ã±ãŒã«ã®ååïŒ

ãããã£ãŠãç·åœ¢ã«å¢å ããïŒXboxã³ã³ãããŒã©ãŒã®äžå¿è»žããã®åå·®ã倧ãããªãã»ã©ïŒä¿æ°ã¯æ倧1.4ã§å°å ¥ãããŸããïŒãã ããåŸã§å€æããããã«ãè§åºŠå€ã決å®ããè§åºŠã察è§ç·ã«è¿ã¥ãã»ã©ä¿æ°ã¯å€§ãããªããŸãïŒã ãããã®å€ã䜿çšãããšãXboxã²ãŒã ãããã¯éåæãªãæããããšãã§ããŸãããçŽç²ã«æè¡çã«ã¯æ床ã¯å€±ç€Œã§ããã Doom 0.05ã§ã¯å¶åŸ¡ã䟿å©ã§ããã³ãžã§ã³ã·ãŒãžã§ã¯ïŒã¹ãã£ãã¯ã®ããã¿åã«å¿ããŠïŒ3ã€ã®ç§»åé床ãã¹ãŠãæ©èœããPSPèªäœã®ããã«æããŸãã åé¡ã«çŽé¢ãããšããæåã«åçŽãªä¿æ°ïŒ1.5ãš1.4ã®äž¡æ¹ïŒããã¹ããããåå·®ã«å¿ããŠç·åœ¢ã«å¢å ãããæå®ãããã²ãŒã ã«æ¥æ¿ãªäžå¿«æããããŸãã-ãã¬ã€ããããšã¯äžå¯èœã§ããã
Fedora Remix 18 for Raspberry Piã®ã¹ã¿ãŒãã¢ããã«ç¬èªã®ãµãŒãã¹ãè¿œå ãã
Linuxã§èªåããŒãããããã°ã©ã ã®è¿œå ã«é¢ããè¡šé¢çãªã°ãŒã°ã«ã§ã¯ãäž»ã«init rcã¹ã¯ãªããã®å€æŽã«é¢ããæšå¥šäºé ãæäŸãããŠããŸãã ãããããã®å Žåãå¥ã®æ¹æ³ã§è¡ãå¿ èŠããããŸãã
1.ãŸãããµãŒãã¹xbox2psp.oã/ usr / local / binã«ã³ããŒãããã®èµ·åæš©éãèšå®ããå¿ èŠããããŸãïŒ3ããããã¹ãŠïŒã
2.次ã«ã次ã®å 容ã§/lib/systemd/system/xbox2psp.serviceãã¡ã€ã«ãäœæããŸãã
[Unit] Description=xbox2psp After=syslog.target network.target [Service] Type=simple ExecStart=/usr/local/bin/xbox2psp.o [Install] WantedBy=multi-user.target
3. / etc / systemd / system /ãã©ã«ããŒã«ç§»åããã³ãã³ãã§ãªã³ã¯ãäœæããŸã
> ln -s /lib/systemd/system/xbox2psp.service xbox2psp.service
4.èµ·åããŒã¢ã³æ§æãåããŒãããŸãã
> systemctl daemon-reload
5.æ°ãããµãŒãã¹ã®èªåèµ·åãæå¹ã«ãã
> systemctl enable xbox2psp.service
6.å¿ èŠã«å¿ããŠãã³ãã³ãã䜿çšããŠããã«ãµãŒãã¹ãéå§ã§ããŸã
> systemctl start xbox2psp.service
ãã®çµæãXbox 360ã³ã³ãããŒã©ãŒã䜿çšããŠPSPãå¶åŸ¡ãã䟿å©ãªæ©äŒãåŸãããå¿ èŠã«å¿ããŠããã®ãããžã§ã¯ããå€æŽããŠãããšãã°Bluetoothçµç±ã§Dualshock 3ã«æ¥ç¶ã§ããŸãã