PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
poweroff.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "types.h"
12#include "defs.h"
13#include "irx.h"
14#include "loadcore.h"
15#include "sysmem.h"
16#include "stdio.h"
17#include "sysclib.h"
18#include "sifcmd.h"
19#include "thbase.h"
20#include "intrman.h"
21#include "loadcore.h"
22#include "thsemap.h"
23#include "poweroff.h"
24#include "pwroff_rpc.h"
25
26//#define DEBUG
27
28#define TYPE_C 1
29#define CDVDreg_PWOFF (*(volatile unsigned char*)0xBF402008)
30
31#define MAX_CALLBACKS 8
32
33#define MODNAME "Poweroff_Handler"
34IRX_ID(MODNAME, 1, 1);
35
36#define M_PRINTF(format, args...) \
37 printf(MODNAME ": " format, ##args)
38
39#ifdef DEBUG
40#define M_DEBUG M_PRINTF
41#else
42#define M_DEBUG(format, args...)
43#endif
44
45extern struct irx_export_table _exp_poweroff;
46
47//---------------------------------------------------------------------
48
49static void Shutdown();
50static void SendCmd(void* data);
51
52//---------------------------------------------------------------------
53typedef int (*intrhandler)(void*);
54
55static intrhandler oldCdHandler=0;
56
58 intrhandler handler;
59 void *param;
60};
61
63{
64 pwoffcb cb;
65 void *data;
66} CallbackTable[MAX_CALLBACKS];
67
68//---------------------------------------------------------------------
69
70static char cmdData[16];
71static pwoffcb poweroff_button_cb = 0;
72static void *poweroff_button_data = 0;
73static struct t_SifRpcDataQueue qd;
74static struct t_SifRpcServerData sd0;
75static int PowerOffThreadID = -1;
76static SifRpcClientData_t client;
77
78static int myCdHandler(void *param)
79{
80 if (((CDVDreg_PWOFF & 1)==0) && (CDVDreg_PWOFF & 4))
81 {
82 /* can't seem to register a sif cmd callback in ps2link so... */
83 /* Clear interrupt bit */
84 CDVDreg_PWOFF = 4;
85 M_DEBUG("Poweroff!!!! %08x\n", CDVDreg_PWOFF);
86
87 if (poweroff_button_cb)
88 poweroff_button_cb(poweroff_button_data);
89 }
90
91 return oldCdHandler(param);
92}
93
94static void Shutdown(void* data)
95{
96 (void)data;
97
98 M_DEBUG("Shutdown\n");
99 int i;
100 /* Do callbacks in reverse order */
101 for(i = MAX_CALLBACKS-1; i >= 0; i--)
102 {
103 if(CallbackTable[i].cb)
104 {
105 CallbackTable[i].cb(CallbackTable[i].data);
106 }
107 }
108
109 // Turn off PS2
110 *((unsigned char *)0xBF402017) = 0;
111 *((unsigned char *)0xBF402016) = 0xF;
112}
113
114static void SendCmd(void* data)
115{
116 (void)data;
117
118 iWakeupThread(PowerOffThreadID);
119}
120
121static void PowerOffThread(void *arg)
122{
123 (void)arg;
124
125 SleepThread();
126 sceSifCallRpc(&client, POFF_RPC_BUTTON, 0, NULL, 0, NULL, 0, NULL, NULL);
127}
128
129static void InitPowerOffThread(void)
130{
132
133 if(PowerOffThreadID < 0)
134 {
135 thread.thread = &PowerOffThread;
136 thread.attr = TH_C;
137 thread.option = PWROFF_IRX;
138 thread.stacksize = 0x400;
139 thread.priority = 0x27;
140 PowerOffThreadID = CreateThread(&thread);
141 StartThread(PowerOffThreadID, NULL);
142
143 client.server = NULL;
144 while(sceSifBindRpc(&client, PWROFF_IRX, 0) < 0 || client.server == NULL) DelayThread(500);
145 }
146}
147
148//---------------------------------------------------------------------
149//-----------------------------------------------------------entrypoint
150//---------------------------------------------------------------------
151
152void SetPowerButtonHandler(pwoffcb func, void* param)
153{
154 poweroff_button_cb = func;
155 poweroff_button_data = param;
156}
157
158void AddPowerOffHandler(pwoffcb func, void* param)
159{
160 int i;
161
162 for(i = 0; i < MAX_CALLBACKS; i++)
163 {
164 if(CallbackTable[i].cb == 0)
165 {
166 CallbackTable[i].cb = func;
167 CallbackTable[i].data = param;
168 M_DEBUG("Added callback at position %d\n", i);
169 break;
170 }
171 }
172
173 if(i == MAX_CALLBACKS)
174 {
175 M_PRINTF("Could not add poweroff callback\n");
176 }
177}
178
179void RemovePowerOffHandler(pwoffcb func)
180{
181 int i;
182
183 for(i = 0; i < MAX_CALLBACKS; i++)
184 {
185 if(CallbackTable[i].cb == func)
186 {
187 break;
188 }
189 }
190
191 if(i < MAX_CALLBACKS)
192 {
193 for(; i < (MAX_CALLBACKS-1); i++)
194 {
195 CallbackTable[i] = CallbackTable[i+1];
196 }
197 memset(&CallbackTable[i], 0, sizeof(struct CallbackEntry));
198 }
199}
200
201void PoweroffShutdown()
202{
203 Shutdown(0);
204}
205
206void* poweroff_rpc_server(int fno, void *data, int size)
207{
208 (void)size;
209
210 switch(fno) {
211 case PWROFF_SHUTDOWN:
212 Shutdown(0);
213 break;
214
215 case PWROFF_ENABLE_AUTO_SHUTOFF:
216 InitPowerOffThread();
217
218 int* sbuff = data;
219 if (sbuff[0])
220 SetPowerButtonHandler(Shutdown, 0);
221 else
222 SetPowerButtonHandler(SendCmd, 0);
223 sbuff[0] = 1;
224 return sbuff;
225 }
226 return NULL;
227}
228
229void poweroff_rpc_Thread(void* param)
230{
231 (void)param;
232
233 sceSifInitRpc(0);
234
235 sceSifSetRpcQueue(&qd, GetThreadId());
236 sceSifRegisterRpc(&sd0, PWROFF_IRX, poweroff_rpc_server, cmdData, NULL, NULL, &qd);
237 sceSifRpcLoop(&qd);
238}
239
240int _start(int argc, char *argv[])
241{
242 register struct handlerTableEntry *handlers=(struct handlerTableEntry*)0x480;//iopmem
243 iop_thread_t mythread;
244
245 (void)argc;
246 (void)argv;
247
248 if(RegisterLibraryEntries(&_exp_poweroff) != 0)
249 {
250 M_PRINTF("Poweroff already registered\n");
251 return MODULE_NO_RESIDENT_END;
252 }
253
254 SetPowerButtonHandler(Shutdown, 0);
255
256#pragma GCC diagnostic push
257#pragma GCC diagnostic ignored "-Warray-bounds"
258 if (handlers[IOP_IRQ_CDVD].handler==0) {
259 M_PRINTF("No CDROM handler. Run CDVDMAN first\n");
260 return MODULE_NO_RESIDENT_END;
261 }
262
263 if (((int)handlers[IOP_IRQ_CDVD].handler & 3) != TYPE_C){
264 M_PRINTF("Cannot chain to non-C handler\n");
265 return MODULE_NO_RESIDENT_END;
266 }
267
268 oldCdHandler=(intrhandler)((int)handlers[IOP_IRQ_CDVD].handler & ~3);
269 handlers[IOP_IRQ_CDVD].handler=(intrhandler)((int)myCdHandler | TYPE_C);
270#pragma GCC diagnostic pop
271
272 memset(CallbackTable, 0, sizeof(struct CallbackEntry) * MAX_CALLBACKS);
273
274 mythread.attr = TH_C;
275 mythread.option = PWROFF_IRX;
276 mythread.thread = poweroff_rpc_Thread;
277 mythread.stacksize = 0x1000;
278 mythread.priority = 0x27;
279
280 int pid = CreateThread(&mythread);
281
282 if (pid > 0) {
283 int i;
284
285 if ((i=StartThread(pid, NULL)) < 0) {
286 M_PRINTF("StartThread failed (%d)\n", i);
287 return MODULE_NO_RESIDENT_END;
288 }
289 }
290 else {
291 M_PRINTF("CreateThread failed (%d)\n", pid);
292 return MODULE_NO_RESIDENT_END;
293 }
294
295 M_PRINTF("Poweroff installed\n");
296 return MODULE_RESIDENT_END;
297}
Definition poweroff.c:63
Definition poweroff.c:57