patch to make enabling 64B L2 cache optional (tueidj)
[libogc.git] / wiiuse / wiiuse.c
blobf1bab995621e378a14a0734a570eb97ebe8827e6
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
5 #ifndef WIN32
6 #include <unistd.h>
7 #else
8 #include <Winsock2.h>
9 #endif
11 #include "definitions.h"
12 #include "wiiuse_internal.h"
13 #include "io.h"
15 static struct wiimote_t** __wm = NULL;
17 void wiiuse_send_next_command(struct wiimote_t *wm)
19 struct cmd_blk_t *cmd = wm->cmd_head;
21 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return;
23 if(!cmd) return;
24 if(cmd->state!=CMD_READY) return;
26 cmd->state = CMD_SENT;
27 if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) cmd->data[1] |= 0x01;
29 wiiuse_io_write(wm,cmd->data,cmd->len);
32 static __inline__ void __wiiuse_push_command(struct wiimote_t *wm,struct cmd_blk_t *cmd)
34 uint level;
36 if(!wm || !cmd) return;
38 cmd->next = NULL;
39 cmd->state = CMD_READY;
41 _CPU_ISR_Disable(level);
42 if(wm->cmd_head==NULL) {
43 wm->cmd_head = wm->cmd_tail = cmd;
44 wiiuse_send_next_command(wm);
45 } else {
46 wm->cmd_tail->next = cmd;
47 wm->cmd_tail = cmd;
49 _CPU_ISR_Restore(level);
52 #ifndef GEKKO
53 struct wiimote_t** wiiuse_init(int wiimotes) {
54 #else
55 extern void __wiiuse_sensorbar_enable(int enable);
56 struct wiimote_t** wiiuse_init(int wiimotes, wii_event_cb event_cb) {
57 #endif
58 int i = 0;
60 if (!wiimotes)
61 return NULL;
63 if (!__wm) {
64 __wm = __lwp_wkspace_allocate(sizeof(struct wiimote_t*) * wiimotes);
65 if(!__wm) return NULL;
66 memset(__wm, 0, sizeof(struct wiimote_t*) * wiimotes);
69 for (i = 0; i < wiimotes; ++i) {
70 if(!__wm[i])
71 __wm[i] = __lwp_wkspace_allocate(sizeof(struct wiimote_t));
73 memset(__wm[i], 0, sizeof(struct wiimote_t));
74 __wm[i]->unid = i;
76 #if defined(WIN32)
77 __wm[i]->dev_handle = 0;
78 __wm[i]->stack = WIIUSE_STACK_UNKNOWN;
79 __wm[i]->normal_timeout = WIIMOTE_DEFAULT_TIMEOUT;
80 __wm[i]->exp_timeout = WIIMOTE_EXP_TIMEOUT;
81 __wm[i]->timeout = __wm[i]->normal_timeout;
82 #elif defined(GEKKO)
83 __wm[i]->sock = NULL;
84 __wm[i]->bdaddr = *BD_ADDR_ANY;
85 __wm[i]->event_cb = event_cb;
86 wiiuse_init_cmd_queue(__wm[i]);
87 #elif defined(unix)
88 __wm[i]->bdaddr = *BDADDR_ANY;
89 __wm[i]->out_sock = -1;
90 __wm[i]->in_sock = -1;
91 #endif
93 __wm[i]->state = WIIMOTE_INIT_STATES;
94 __wm[i]->flags = WIIUSE_INIT_FLAGS;
96 __wm[i]->event = WIIUSE_NONE;
98 __wm[i]->exp.type = EXP_NONE;
100 wiiuse_set_aspect_ratio(__wm[i], WIIUSE_ASPECT_4_3);
101 wiiuse_set_ir_position(__wm[i], WIIUSE_IR_ABOVE);
103 __wm[i]->accel_calib.st_alpha = WIIUSE_DEFAULT_SMOOTH_ALPHA;
106 return __wm;
110 * @brief Set flags for the specified wiimote.
112 * @param wm Pointer to a wiimote_t structure.
113 * @param enable Flags to enable.
114 * @param disable Flags to disable.
116 * @return The flags set after 'enable' and 'disable' have been applied.
118 * The values 'enable' and 'disable' may be any flags OR'ed together.
119 * Flags are defined in wiiuse.h.
121 int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable) {
122 if (!wm) return 0;
124 /* remove mutually exclusive flags */
125 enable &= ~disable;
126 disable &= ~enable;
128 wm->flags |= enable;
129 wm->flags &= ~disable;
131 return wm->flags;
135 * @brief Set if the wiimote should report motion sensing.
137 * @param wm Pointer to a wiimote_t structure.
138 * @param status 1 to enable, 0 to disable.
140 * Since reporting motion sensing sends a lot of data,
141 * the wiimote saves power by not transmitting it
142 * by default.
144 void wiiuse_motion_sensing(struct wiimote_t* wm, int status)
146 if (status) {
147 if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_ACC)) return;
148 WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_ACC);
149 } else {
150 if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_ACC)) return;
151 WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC);
154 if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) return;
156 wiiuse_status(wm,NULL);
160 * @brief Toggle the state of the rumble.
162 * @param wm Pointer to a wiimote_t structure.
164 void wiiuse_toggle_rumble(struct wiimote_t* wm)
166 if (!wm) return;
168 WIIMOTE_TOGGLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
169 if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) return;
171 wiiuse_set_leds(wm,wm->leds,NULL);
175 * @brief Enable or disable the rumble.
177 * @param wm Pointer to a wiimote_t structure.
178 * @param status 1 to enable, 0 to disable.
180 void wiiuse_rumble(struct wiimote_t* wm, int status)
182 if (status && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) return;
183 else if(!status && !WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) return;
184 wiiuse_toggle_rumble(wm);
187 void wiiuse_set_leds(struct wiimote_t *wm,int leds,cmd_blk_cb cb)
189 ubyte buf;
191 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return;
193 wm->leds = (leds&0xf0);
195 buf = wm->leds;
196 wiiuse_sendcmd(wm,WM_CMD_LED,&buf,1,cb);
199 int wiiuse_set_report_type(struct wiimote_t *wm,cmd_blk_cb cb)
201 ubyte buf[2];
202 int motion,ir,exp;
204 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
206 buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00); /* set to 0x04 for continuous reporting */
207 buf[1] = 0x00;
209 motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC) || WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
210 exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP);
211 ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
213 if (motion && ir && exp) buf[1] = WM_RPT_BTN_ACC_IR_EXP;
214 else if (motion && exp) buf[1] = WM_RPT_BTN_ACC_EXP;
215 else if (motion && ir) buf[1] = WM_RPT_BTN_ACC_IR;
216 else if (ir && exp) buf[1] = WM_RPT_BTN_IR_EXP;
217 else if (ir) buf[1] = WM_RPT_BTN_ACC_IR;
218 else if (exp) buf[1] = WM_RPT_BTN_EXP;
219 else if (motion) buf[1] = WM_RPT_BTN_ACC;
220 else buf[1] = WM_RPT_BTN;
222 WIIUSE_DEBUG("Setting report type: 0x%x", buf[1]);
224 wiiuse_sendcmd(wm,WM_CMD_REPORT_TYPE,buf,2,cb);
225 return buf[1];
228 void wiiuse_status(struct wiimote_t *wm,cmd_blk_cb cb)
230 ubyte buf;
232 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return;
234 buf = 0x00;
235 wiiuse_sendcmd(wm,WM_CMD_CTRL_STATUS,&buf,1,cb);
238 int wiiuse_read_data(struct wiimote_t *wm,ubyte *buffer,uint addr,uword len,cmd_blk_cb cb)
240 struct op_t *op;
241 struct cmd_blk_t *cmd;
243 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
244 if(!buffer || !len) return 0;
246 cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
247 if(!cmd) return 0;
249 cmd->cb = cb;
250 cmd->len = 7;
252 op = (struct op_t*)cmd->data;
253 op->cmd = WM_CMD_READ_DATA;
254 op->buffer = buffer;
255 op->wait = len;
256 op->readdata.addr = BIG_ENDIAN_LONG(addr);
257 op->readdata.size = BIG_ENDIAN_SHORT(len);
258 __wiiuse_push_command(wm,cmd);
260 return 1;
263 int wiiuse_write_data(struct wiimote_t *wm,uint addr,ubyte *data,ubyte len,cmd_blk_cb cb)
265 struct op_t *op;
266 struct cmd_blk_t *cmd;
268 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
269 if(!data || !len) return 0;
271 cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
272 if(!cmd) return 0;
274 cmd->cb = cb;
275 cmd->len = 22;
277 op = (struct op_t*)cmd->data;
278 op->cmd = WM_CMD_WRITE_DATA;
279 op->buffer = NULL;
280 op->wait = 0;
281 op->writedata.addr = BIG_ENDIAN_LONG(addr);
282 op->writedata.size = (len&0x0f);
283 memcpy(op->writedata.data,data,len);
284 memset(op->writedata.data+len,0,(16 - len));
285 __wiiuse_push_command(wm,cmd);
287 return 1;
290 int wiiuse_write_streamdata(struct wiimote_t *wm,ubyte *data,ubyte len,cmd_blk_cb cb)
292 struct cmd_blk_t *cmd;
294 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
295 if(!data || !len || len>20) return 0;
297 cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
298 if(!cmd) return 0;
300 cmd->cb = cb;
301 cmd->len = 22;
302 cmd->data[0] = WM_CMD_STREAM_DATA;
303 cmd->data[1] = (len<<3);
304 memcpy(cmd->data+2,data,len);
305 __wiiuse_push_command(wm,cmd);
307 return 1;
310 int wiiuse_sendcmd(struct wiimote_t *wm,ubyte report_type,ubyte *msg,int len,cmd_blk_cb cb)
312 struct cmd_blk_t *cmd;
314 cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
315 if(!cmd) return 0;
317 cmd->cb = cb;
318 cmd->len = (1+len);
320 cmd->data[0] = report_type;
321 memcpy(cmd->data+1,msg,len);
322 __wiiuse_push_command(wm,cmd);
324 return 1;