patch to make enabling 64B L2 cache optional (tueidj)
[libogc.git] / wiiuse / wpad.c
blob387cdc0a04b6b6c111052d60bc78d815470a9b07
1 /*-------------------------------------------------------------
3 wpad.c -- Wiimote Application Programmers Interface
5 Copyright (C) 2008
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
8 Hector Martin (marcan)
10 This software is provided 'as-is', without any express or implied
11 warranty. In no event will the authors be held liable for any
12 damages arising from the use of this software.
14 Permission is granted to anyone to use this software for any
15 purpose, including commercial applications, and to alter it and
16 redistribute it freely, subject to the following restrictions:
18 1. The origin of this software must not be misrepresented; you
19 must not claim that you wrote the original software. If you use
20 this software in a product, an acknowledgment in the product
21 documentation would be appreciated but is not required.
23 2. Altered source versions must be plainly marked as such, and
24 must not be misrepresented as being the original software.
26 3. This notice may not be removed or altered from any source
27 distribution.
29 -------------------------------------------------------------*/
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <time.h>
35 #include <unistd.h>
37 #include "asm.h"
38 #include "processor.h"
39 #include "bte.h"
40 #include "conf.h"
41 #include "ir.h"
42 #include "speaker.h"
43 #include "dynamics.h"
44 #include "guitar_hero_3.h"
45 #include "wiiboard.h"
46 #include "wiiuse_internal.h"
47 #include "wiiuse/wpad.h"
48 #include "lwp_threads.h"
49 #include "ogcsys.h"
51 #define MAX_STREAMDATA_LEN 20
52 #define EVENTQUEUE_LENGTH 16
54 #define DISCONNECT_BATTERY_DIED 0x14
55 #define DISCONNECT_POWER_OFF 0x15
57 struct _wpad_thresh{
58 s32 btns;
59 s32 ir;
60 s32 js;
61 s32 acc;
62 s32 wb;
63 s32 mp;
66 struct _wpad_cb {
67 wiimote *wm;
68 s32 data_fmt;
69 s32 queue_head;
70 s32 queue_tail;
71 s32 queue_full;
72 u32 queue_length;
73 u32 dropped_events;
74 s32 idle_time;
75 s32 speaker_enabled;
76 struct _wpad_thresh thresh;
78 void *sound_data;
79 u32 sound_len;
80 u32 sound_off;
81 syswd_t sound_alarm;
83 WPADData lstate;
84 WPADData *queue_ext;
85 WPADData queue_int[EVENTQUEUE_LENGTH];
88 static syswd_t __wpad_timer;
89 static vu32 __wpads_inited = 0;
90 static vs32 __wpads_ponded = 0;
91 static u32 __wpad_idletimeout = 300;
92 static vu32 __wpads_active = 0;
93 static vu32 __wpads_used = 0;
94 static wiimote **__wpads = NULL;
95 static wiimote_listen __wpads_listen[CONF_PAD_MAX_REGISTERED];
96 static WPADData wpaddata[WPAD_MAX_WIIMOTES];
97 static struct _wpad_cb __wpdcb[WPAD_MAX_WIIMOTES];
98 static conf_pads __wpad_devs;
99 static struct linkkey_info __wpad_keys[WPAD_MAX_WIIMOTES];
101 static s32 __wpad_onreset(s32 final);
102 static s32 __wpad_disconnect(struct _wpad_cb *wpdcb);
103 static void __wpad_eventCB(struct wiimote_t *wm,s32 event);
105 static void __wpad_def_powcb(s32 chan);
106 static WPADShutdownCallback __wpad_batcb = NULL;
107 static WPADShutdownCallback __wpad_powcb = __wpad_def_powcb;
109 extern void __wiiuse_sensorbar_enable(int enable);
110 extern void __SYS_DoPowerCB(void);
112 static sys_resetinfo __wpad_resetinfo = {
114 __wpad_onreset,
118 static s32 __wpad_onreset(s32 final)
120 //printf("__wpad_onreset(%d)\n",final);
121 if(final==FALSE) {
122 WPAD_Shutdown();
124 return 1;
127 static void __wpad_def_powcb(s32 chan)
129 __SYS_DoPowerCB();
132 static void __wpad_timeouthandler(syswd_t alarm,void *cbarg)
134 s32 i;
135 struct wiimote_t *wm = NULL;
136 struct _wpad_cb *wpdcb = NULL;
138 if(!__wpads_active) return;
140 __lwp_thread_dispatchdisable();
141 for(i=0;i<WPAD_MAX_WIIMOTES;i++) {
142 wpdcb = &__wpdcb[i];
143 wm = wpdcb->wm;
144 if(wm && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_CONNECTED)) {
145 wpdcb->idle_time++;
146 if(wpdcb->idle_time>=__wpad_idletimeout) {
147 wpdcb->idle_time = 0;
148 wiiuse_disconnect(wm);
152 __lwp_thread_dispatchunnest();
155 static void __wpad_sounddata_alarmhandler(syswd_t alarm,void *cbarg)
157 u8 *snd_data;
158 u32 snd_off;
159 struct wiimote_t *wm;
160 struct _wpad_cb *wpdcb = (struct _wpad_cb*)cbarg;
162 if(!wpdcb) return;
164 if(wpdcb->sound_off>=wpdcb->sound_len) {
165 wpdcb->sound_data = NULL;
166 wpdcb->sound_len = 0;
167 wpdcb->sound_off = 0;
168 SYS_CancelAlarm(wpdcb->sound_alarm);
169 return;
172 wm = wpdcb->wm;
173 snd_data = wpdcb->sound_data;
174 snd_off = wpdcb->sound_off;
175 wpdcb->sound_off += MAX_STREAMDATA_LEN;
176 wiiuse_write_streamdata(wm,(snd_data+snd_off),MAX_STREAMDATA_LEN,NULL);
179 static void __wpad_setfmt(s32 chan)
181 switch(__wpdcb[chan].data_fmt) {
182 case WPAD_FMT_BTNS:
183 wiiuse_set_flags(__wpads[chan], 0, WIIUSE_CONTINUOUS);
184 wiiuse_motion_sensing(__wpads[chan],0);
185 if(chan != WPAD_BALANCE_BOARD) wiiuse_set_ir(__wpads[chan],0);
186 break;
187 case WPAD_FMT_BTNS_ACC:
188 wiiuse_set_flags(__wpads[chan], WIIUSE_CONTINUOUS, 0);
189 wiiuse_motion_sensing(__wpads[chan],1);
190 if(chan != WPAD_BALANCE_BOARD) wiiuse_set_ir(__wpads[chan],0);
191 break;
192 case WPAD_FMT_BTNS_ACC_IR:
193 wiiuse_set_flags(__wpads[chan], WIIUSE_CONTINUOUS, 0);
194 wiiuse_motion_sensing(__wpads[chan],1);
195 if(chan != WPAD_BALANCE_BOARD) wiiuse_set_ir(__wpads[chan],1);
196 break;
197 default:
198 break;
202 wiimote *__wpad_assign_slot(struct bd_addr *pad_addr)
204 u32 i, level;
205 struct bd_addr bdaddr;
206 //printf("WPAD Assigning slot (active: 0x%02x)\n", __wpads_used);
207 _CPU_ISR_Disable(level);
209 // check for balance board
210 BD_ADDR(&(bdaddr),__wpad_devs.balance_board.bdaddr[5],__wpad_devs.balance_board.bdaddr[4],__wpad_devs.balance_board.bdaddr[3],__wpad_devs.balance_board.bdaddr[2],__wpad_devs.balance_board.bdaddr[1],__wpad_devs.balance_board.bdaddr[0]);
211 if(bd_addr_cmp(pad_addr,&bdaddr)) {
212 if(!(__wpads_used&(1<<WPAD_BALANCE_BOARD))) {
213 __wpads_used |= (0x01<<WPAD_BALANCE_BOARD);
214 _CPU_ISR_Restore(level);
215 return __wpads[WPAD_BALANCE_BOARD];
216 } else {
217 _CPU_ISR_Restore(level);
218 return NULL;
222 // Try preassigned slots
223 for(i=0; i<CONF_PAD_MAX_ACTIVE /*&& i<WPAD_MAX_WIIMOTES*/; i++) {
224 BD_ADDR(&(bdaddr),__wpad_devs.active[i].bdaddr[5],__wpad_devs.active[i].bdaddr[4],__wpad_devs.active[i].bdaddr[3],__wpad_devs.active[i].bdaddr[2],__wpad_devs.active[i].bdaddr[1],__wpad_devs.active[i].bdaddr[0]);
225 if(bd_addr_cmp(pad_addr,&bdaddr) && !(__wpads_used & (1<<i))) {
226 //printf("WPAD Got Preassigned Slot %d\n", i);
227 __wpads_used |= (0x01<<i);
228 _CPU_ISR_Restore(level);
229 return __wpads[i];
233 // No match, pick the first free slot
234 for(i=0; i<WPAD_MAX_WIIMOTES; i++) {
235 if(!(__wpads_used & (1<<i))) {
236 //printf("WPAD Got Free Slot %d\n", i);
237 __wpads_used |= (0x01<<i);
238 _CPU_ISR_Restore(level);
239 return __wpads[i];
242 //printf("WPAD All Slots Used\n");
243 _CPU_ISR_Restore(level);
244 return NULL;
247 static s32 __wpad_init_finished(s32 result,void *usrdata)
249 u32 i;
250 struct bd_addr bdaddr;
252 //printf("__wpad_init_finished(%d)\n",result);
254 if(result==ERR_OK) {
255 for(i=0;/*__wpads[i] && */i<__wpad_devs.num_registered;i++) {
256 BD_ADDR(&(bdaddr),__wpad_devs.registered[i].bdaddr[5],__wpad_devs.registered[i].bdaddr[4],__wpad_devs.registered[i].bdaddr[3],__wpad_devs.registered[i].bdaddr[2],__wpad_devs.registered[i].bdaddr[1],__wpad_devs.registered[i].bdaddr[0]);
257 wiiuse_register(&__wpads_listen[i],&(bdaddr),__wpad_assign_slot);
260 BD_ADDR(&(bdaddr),__wpad_devs.balance_board.bdaddr[5],__wpad_devs.balance_board.bdaddr[4],__wpad_devs.balance_board.bdaddr[3],__wpad_devs.balance_board.bdaddr[2],__wpad_devs.balance_board.bdaddr[1],__wpad_devs.balance_board.bdaddr[0]);
261 if(i<CONF_PAD_MAX_REGISTERED && !bd_addr_cmp(&bdaddr,BD_ADDR_ANY)) {
262 wiiuse_register(&__wpads_listen[i],&(bdaddr),__wpad_assign_slot);
264 __wpads_inited = WPAD_STATE_ENABLED;
266 return ERR_OK;
269 static s32 __wpad_patch_finished(s32 result,void *usrdata)
271 //printf("__wpad_patch_finished(%d)\n",result);
272 BTE_InitSub(__wpad_init_finished);
273 return ERR_OK;
276 static s32 __readlinkkey_finished(s32 result,void *usrdata)
278 //printf("__readlinkkey_finished(%d)\n",result);
280 __wpads_ponded = result;
281 BTE_ApplyPatch(__wpad_patch_finished);
283 return ERR_OK;
286 static s32 __initcore_finished(s32 result,void *usrdata)
288 //printf("__initcore_finished(%d)\n",result);
290 if(result==ERR_OK) {
291 BTE_ReadStoredLinkKey(__wpad_keys,WPAD_MAX_WIIMOTES,__readlinkkey_finished);
293 return ERR_OK;
296 static s32 __wpad_disconnect(struct _wpad_cb *wpdcb)
298 struct wiimote_t *wm;
300 if(wpdcb==NULL) return 0;
302 wm = wpdcb->wm;
303 if(wm && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_CONNECTED)) {
304 wiiuse_disconnect(wm);
307 return 0;
310 static void __wpad_calc_data(WPADData *data,WPADData *lstate,struct accel_t *accel_calib,u32 smoothed)
312 if(data->err!=WPAD_ERR_NONE) return;
314 data->orient = lstate->orient;
316 data->ir.state = lstate->ir.state;
317 data->ir.sensorbar = lstate->ir.sensorbar;
318 data->ir.x = lstate->ir.x;
319 data->ir.y = lstate->ir.y;
320 data->ir.sx = lstate->ir.sx;
321 data->ir.sy = lstate->ir.sy;
322 data->ir.ax = lstate->ir.ax;
323 data->ir.ay = lstate->ir.ay;
324 data->ir.distance = lstate->ir.distance;
325 data->ir.z = lstate->ir.z;
326 data->ir.angle = lstate->ir.angle;
327 data->ir.error_cnt = lstate->ir.error_cnt;
328 data->ir.glitch_cnt = lstate->ir.glitch_cnt;
330 data->btns_l = lstate->btns_h;
331 if(data->data_present & WPAD_DATA_ACCEL) {
332 calculate_orientation(accel_calib, &data->accel, &data->orient, smoothed);
333 calculate_gforce(accel_calib, &data->accel, &data->gforce);
335 if(data->data_present & WPAD_DATA_IR) {
336 interpret_ir_data(&data->ir,&data->orient);
338 if(data->data_present & WPAD_DATA_EXPANSION) {
339 switch(data->exp.type) {
340 case EXP_NUNCHUK:
342 struct nunchuk_t *nc = &data->exp.nunchuk;
344 nc->orient = lstate->exp.nunchuk.orient;
345 calc_joystick_state(&nc->js,nc->js.pos.x,nc->js.pos.y);
346 calculate_orientation(&nc->accel_calib,&nc->accel,&nc->orient,smoothed);
347 calculate_gforce(&nc->accel_calib,&nc->accel,&nc->gforce);
348 data->btns_h |= (data->exp.nunchuk.btns<<16);
350 break;
352 case EXP_CLASSIC:
354 struct classic_ctrl_t *cc = &data->exp.classic;
356 cc->r_shoulder = ((f32)cc->rs_raw/0x1F);
357 cc->l_shoulder = ((f32)cc->ls_raw/0x1F);
358 calc_joystick_state(&cc->ljs, cc->ljs.pos.x, cc->ljs.pos.y);
359 calc_joystick_state(&cc->rjs, cc->rjs.pos.x, cc->rjs.pos.y);
360 data->btns_h |= (data->exp.classic.btns<<16);
362 break;
364 case EXP_GUITAR_HERO_3:
366 struct guitar_hero_3_t *gh3 = &data->exp.gh3;
368 gh3->touch_bar = 0;
369 if (gh3->tb_raw > 0x1B)
370 gh3->touch_bar = GUITAR_HERO_3_TOUCH_ORANGE;
371 else if (gh3->tb_raw > 0x18)
372 gh3->touch_bar = GUITAR_HERO_3_TOUCH_ORANGE | GUITAR_HERO_3_TOUCH_BLUE;
373 else if (gh3->tb_raw > 0x15)
374 gh3->touch_bar = GUITAR_HERO_3_TOUCH_BLUE;
375 else if (gh3->tb_raw > 0x13)
376 gh3->touch_bar = GUITAR_HERO_3_TOUCH_BLUE | GUITAR_HERO_3_TOUCH_YELLOW;
377 else if (gh3->tb_raw > 0x10)
378 gh3->touch_bar = GUITAR_HERO_3_TOUCH_YELLOW;
379 else if (gh3->tb_raw > 0x0D)
380 gh3->touch_bar = GUITAR_HERO_3_TOUCH_AVAILABLE;
381 else if (gh3->tb_raw > 0x0B)
382 gh3->touch_bar = GUITAR_HERO_3_TOUCH_YELLOW | GUITAR_HERO_3_TOUCH_RED;
383 else if (gh3->tb_raw > 0x08)
384 gh3->touch_bar = GUITAR_HERO_3_TOUCH_RED;
385 else if (gh3->tb_raw > 0x05)
386 gh3->touch_bar = GUITAR_HERO_3_TOUCH_RED | GUITAR_HERO_3_TOUCH_GREEN;
387 else if (gh3->tb_raw > 0x02)
388 gh3->touch_bar = GUITAR_HERO_3_TOUCH_GREEN;
390 gh3->whammy_bar = (gh3->wb_raw - GUITAR_HERO_3_WHAMMY_BAR_MIN) / (float)(GUITAR_HERO_3_WHAMMY_BAR_MAX - GUITAR_HERO_3_WHAMMY_BAR_MIN);
391 calc_joystick_state(&gh3->js, gh3->js.pos.x, gh3->js.pos.y);
392 data->btns_h |= (data->exp.gh3.btns<<16);
394 break;
396 case EXP_WII_BOARD:
398 struct wii_board_t *wb = &data->exp.wb;
399 calc_balanceboard_state(wb);
401 break;
403 default:
404 break;
407 data->btns_d = data->btns_h & ~data->btns_l;
408 data->btns_u = ~data->btns_h & data->btns_l;
409 *lstate = *data;
412 static void __save_state(struct wiimote_t* wm) {
413 /* wiimote */
414 wm->lstate.btns = wm->btns;
415 wm->lstate.accel = wm->accel;
417 /* ir */
418 wm->lstate.ir = wm->ir;
420 /* expansion */
421 switch (wm->exp.type) {
422 case EXP_NUNCHUK:
423 wm->lstate.exp.nunchuk = wm->exp.nunchuk;
424 break;
425 case EXP_CLASSIC:
426 wm->lstate.exp.classic = wm->exp.classic;
427 break;
428 case EXP_GUITAR_HERO_3:
429 wm->lstate.exp.gh3 = wm->exp.gh3;
430 break;
431 case EXP_WII_BOARD:
432 wm->lstate.exp.wb = wm->exp.wb;
433 break;
434 case EXP_MOTION_PLUS:
435 wm->lstate.exp.mp = wm->exp.mp;
436 break;
440 #define ABS(x) ((s32)(x)>0?(s32)(x):-((s32)(x)))
442 #define STATE_CHECK(thresh, a, b) \
443 if(((thresh) > WPAD_THRESH_IGNORE) && (ABS((a)-(b)) > (thresh))) \
444 state_changed = 1;
446 #define STATE_CHECK_SIMPLE(thresh, a, b) \
447 if(((thresh) > WPAD_THRESH_IGNORE) && ((a) != (b))) \
448 state_changed = 1;
450 static u32 __wpad_read_expansion(struct wiimote_t *wm,WPADData *data, struct _wpad_thresh *thresh)
452 int state_changed = 0;
453 switch(data->exp.type) {
454 case EXP_NUNCHUK:
455 data->exp.nunchuk = wm->exp.nunchuk;
456 STATE_CHECK_SIMPLE(thresh->btns, wm->exp.nunchuk.btns, wm->lstate.exp.nunchuk.btns);
457 STATE_CHECK(thresh->acc, wm->exp.nunchuk.accel.x, wm->lstate.exp.nunchuk.accel.x);
458 STATE_CHECK(thresh->acc, wm->exp.nunchuk.accel.y, wm->lstate.exp.nunchuk.accel.y);
459 STATE_CHECK(thresh->acc, wm->exp.nunchuk.accel.z, wm->lstate.exp.nunchuk.accel.z);
460 STATE_CHECK(thresh->js, wm->exp.nunchuk.js.pos.x, wm->lstate.exp.nunchuk.js.pos.x);
461 STATE_CHECK(thresh->js, wm->exp.nunchuk.js.pos.y, wm->lstate.exp.nunchuk.js.pos.y);
462 break;
463 case EXP_CLASSIC:
464 data->exp.classic = wm->exp.classic;
465 STATE_CHECK_SIMPLE(thresh->btns, wm->exp.classic.btns, wm->lstate.exp.classic.btns);
466 STATE_CHECK(thresh->js, wm->exp.classic.rs_raw, wm->lstate.exp.classic.rs_raw);
467 STATE_CHECK(thresh->js, wm->exp.classic.ls_raw, wm->lstate.exp.classic.ls_raw);
468 STATE_CHECK(thresh->js, wm->exp.classic.ljs.pos.x, wm->lstate.exp.classic.ljs.pos.x);
469 STATE_CHECK(thresh->js, wm->exp.classic.ljs.pos.y, wm->lstate.exp.classic.ljs.pos.y);
470 STATE_CHECK(thresh->js, wm->exp.classic.rjs.pos.x, wm->lstate.exp.classic.rjs.pos.x);
471 STATE_CHECK(thresh->js, wm->exp.classic.rjs.pos.y, wm->lstate.exp.classic.rjs.pos.y);
472 break;
473 case EXP_GUITAR_HERO_3:
474 data->exp.gh3 = wm->exp.gh3;
475 STATE_CHECK_SIMPLE(thresh->btns, wm->exp.gh3.btns, wm->lstate.exp.gh3.btns);
476 STATE_CHECK(thresh->js, wm->exp.gh3.wb_raw, wm->lstate.exp.gh3.wb_raw);
477 STATE_CHECK(thresh->js, wm->exp.gh3.js.pos.x, wm->lstate.exp.gh3.js.pos.x);
478 STATE_CHECK(thresh->js, wm->exp.gh3.js.pos.y, wm->lstate.exp.gh3.js.pos.y);
479 break;
480 case EXP_WII_BOARD:
481 data->exp.wb = wm->exp.wb;
482 STATE_CHECK(thresh->wb,wm->exp.wb.rtl,wm->lstate.exp.wb.rtl);
483 STATE_CHECK(thresh->wb,wm->exp.wb.rtr,wm->lstate.exp.wb.rtr);
484 STATE_CHECK(thresh->wb,wm->exp.wb.rbl,wm->lstate.exp.wb.rbl);
485 STATE_CHECK(thresh->wb,wm->exp.wb.rbr,wm->lstate.exp.wb.rbr);
486 break;
487 case EXP_MOTION_PLUS:
488 data->exp.mp = wm->exp.mp;
489 STATE_CHECK(thresh->mp,wm->exp.mp.rx,wm->lstate.exp.mp.rx);
490 STATE_CHECK(thresh->mp,wm->exp.mp.ry,wm->lstate.exp.mp.ry);
491 STATE_CHECK(thresh->mp,wm->exp.mp.rz,wm->lstate.exp.mp.rz);
492 break;
494 return state_changed;
497 static void __wpad_read_wiimote(struct wiimote_t *wm, WPADData *data, s32 *idle_time, struct _wpad_thresh *thresh)
499 int i;
500 int state_changed = 0;
501 data->err = WPAD_ERR_TRANSFER;
502 data->data_present = 0;
503 data->battery_level = wm->battery_level;
504 data->exp.type = wm->exp.type;
505 if(wm && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_CONNECTED)) {
506 if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) {
507 switch(wm->event_buf[0]) {
508 case WM_RPT_BTN:
509 case WM_RPT_BTN_ACC:
510 case WM_RPT_BTN_ACC_IR:
511 case WM_RPT_BTN_EXP:
512 case WM_RPT_BTN_ACC_EXP:
513 case WM_RPT_BTN_IR_EXP:
514 case WM_RPT_BTN_ACC_IR_EXP:
515 data->btns_h = (wm->btns&0xffff);
516 data->data_present |= WPAD_DATA_BUTTONS;
517 STATE_CHECK_SIMPLE(thresh->btns, wm->btns, wm->lstate.btns);
519 switch(wm->event_buf[0]) {
520 case WM_RPT_BTN_ACC:
521 case WM_RPT_BTN_ACC_IR:
522 case WM_RPT_BTN_ACC_EXP:
523 case WM_RPT_BTN_ACC_IR_EXP:
524 data->accel = wm->accel;
525 data->data_present |= WPAD_DATA_ACCEL;
526 STATE_CHECK(thresh->acc, wm->accel.x, wm->lstate.accel.x);
527 STATE_CHECK(thresh->acc, wm->accel.y, wm->lstate.accel.y);
528 STATE_CHECK(thresh->acc, wm->accel.z, wm->lstate.accel.z);
530 switch(wm->event_buf[0]) {
531 //IR requires acceleration
532 //case WM_RPT_BTN_IR_EXP:
533 case WM_RPT_BTN_ACC_IR:
534 case WM_RPT_BTN_ACC_IR_EXP:
535 data->ir = wm->ir;
536 data->data_present |= WPAD_DATA_IR;
537 for(i=0; i<WPAD_MAX_IR_DOTS; i++) {
538 STATE_CHECK_SIMPLE(thresh->ir, wm->ir.dot[i].visible, wm->lstate.ir.dot[i].visible);
539 STATE_CHECK(thresh->ir, wm->ir.dot[i].rx, wm->lstate.ir.dot[i].rx);
540 STATE_CHECK(thresh->ir, wm->ir.dot[i].ry, wm->lstate.ir.dot[i].ry);
543 switch(wm->event_buf[0]) {
544 case WM_RPT_BTN_EXP:
545 case WM_RPT_BTN_ACC_EXP:
546 case WM_RPT_BTN_IR_EXP:
547 case WM_RPT_BTN_ACC_IR_EXP:
548 state_changed |= __wpad_read_expansion(wm,data,thresh);
549 data->data_present |= WPAD_DATA_EXPANSION;
551 data->err = WPAD_ERR_NONE;
552 if(state_changed) {
553 *idle_time = 0;
554 __save_state(wm);
556 } else
557 data->err = WPAD_ERR_NOT_READY;
558 } else
559 data->err = WPAD_ERR_NO_CONTROLLER;
562 static void __wpad_eventCB(struct wiimote_t *wm,s32 event)
564 s32 chan;
565 u32 maxbufs;
566 WPADData *wpadd = NULL;
567 struct _wpad_cb *wpdcb = NULL;
569 switch(event) {
570 case WIIUSE_EVENT:
571 chan = wm->unid;
572 wpdcb = &__wpdcb[chan];
574 if(wpdcb->queue_ext!=NULL) {
575 maxbufs = wpdcb->queue_length;
576 wpadd = &(wpdcb->queue_ext[wpdcb->queue_tail]);
577 } else {
578 maxbufs = EVENTQUEUE_LENGTH;
579 wpadd = &(wpdcb->queue_int[wpdcb->queue_tail]);
581 if(wpdcb->queue_full == maxbufs) {
582 wpdcb->queue_head++;
583 wpdcb->queue_head %= maxbufs;
584 wpdcb->dropped_events++;
585 } else {
586 wpdcb->queue_full++;
589 __wpad_read_wiimote(wm, wpadd, &wpdcb->idle_time, &wpdcb->thresh);
591 wpdcb->queue_tail++;
592 wpdcb->queue_tail %= maxbufs;
594 break;
595 case WIIUSE_STATUS:
596 break;
597 case WIIUSE_CONNECT:
598 chan = wm->unid;
599 wpdcb = &__wpdcb[chan];
600 wpdcb->wm = wm;
601 wpdcb->queue_head = 0;
602 wpdcb->queue_tail = 0;
603 wpdcb->queue_full = 0;
604 wpdcb->idle_time = 0;
605 memset(&wpdcb->lstate,0,sizeof(WPADData));
606 memset(&wpaddata[chan],0,sizeof(WPADData));
607 memset(wpdcb->queue_int,0,(sizeof(WPADData)*EVENTQUEUE_LENGTH));
608 wiiuse_set_ir_position(wm,(CONF_GetSensorBarPosition()^1));
609 wiiuse_set_ir_sensitivity(wm,CONF_GetIRSensitivity());
610 wiiuse_set_leds(wm,(WIIMOTE_LED_1<<(chan%WPAD_BALANCE_BOARD)),NULL);
611 wiiuse_set_speaker(wm,wpdcb->speaker_enabled);
612 __wpad_setfmt(chan);
613 __wpads_active |= (0x01<<chan);
614 break;
615 case WIIUSE_DISCONNECT:
616 chan = wm->unid;
617 wpdcb = &__wpdcb[chan];
618 wpdcb->wm = wm;
619 wpdcb->queue_head = 0;
620 wpdcb->queue_tail = 0;
621 wpdcb->queue_full = 0;
622 wpdcb->queue_length = 0;
623 wpdcb->queue_ext = NULL;
624 wpdcb->idle_time = -1;
625 memset(&wpdcb->lstate,0,sizeof(WPADData));
626 memset(&wpaddata[chan],0,sizeof(WPADData));
627 memset(wpdcb->queue_int,0,(sizeof(WPADData)*EVENTQUEUE_LENGTH));
628 __wpads_active &= ~(0x01<<chan);
629 __wpads_used &= ~(0x01<<chan);
630 break;
631 default:
632 break;
636 void __wpad_disconnectCB(struct bd_addr *offaddr, u8 reason)
638 struct bd_addr bdaddr;
639 int i;
641 if(__wpads_inited == WPAD_STATE_ENABLED) {
642 for(i=0;i<__wpad_devs.num_registered;i++) {
643 BD_ADDR(&(bdaddr),__wpad_devs.registered[i].bdaddr[5],__wpad_devs.registered[i].bdaddr[4],__wpad_devs.registered[i].bdaddr[3],__wpad_devs.registered[i].bdaddr[2],__wpad_devs.registered[i].bdaddr[1],__wpad_devs.registered[i].bdaddr[0]);
644 if(bd_addr_cmp(offaddr,&bdaddr)) {
645 if(reason == DISCONNECT_BATTERY_DIED) {
646 if(__wpad_batcb) __wpad_batcb(i); //sanity check since this pointer can be NULL.
647 } else if(reason == DISCONNECT_POWER_OFF)
648 __wpad_powcb(i); //no sanity check because there's a default callback iff not otherwise set.
649 break;
655 s32 WPAD_Init()
657 u32 level;
658 struct timespec tb;
659 int i;
661 _CPU_ISR_Disable(level);
662 if(__wpads_inited==WPAD_STATE_DISABLED) {
663 __wpads_ponded = 0;
664 __wpads_active = 0;
666 memset(__wpdcb,0,sizeof(struct _wpad_cb)*WPAD_MAX_WIIMOTES);
667 memset(&__wpad_devs,0,sizeof(conf_pads));
668 memset(__wpad_keys,0,sizeof(struct linkkey_info)*WPAD_MAX_WIIMOTES);
670 for(i=0;i<WPAD_MAX_WIIMOTES;i++) {
671 __wpdcb[i].thresh.btns = WPAD_THRESH_DEFAULT_BUTTONS;
672 __wpdcb[i].thresh.ir = WPAD_THRESH_DEFAULT_IR;
673 __wpdcb[i].thresh.acc = WPAD_THRESH_DEFAULT_ACCEL;
674 __wpdcb[i].thresh.js = WPAD_THRESH_DEFAULT_JOYSTICK;
675 __wpdcb[i].thresh.wb = WPAD_THRESH_DEFAULT_BALANCEBOARD;
676 __wpdcb[i].thresh.mp = WPAD_THRESH_DEFAULT_MOTION_PLUS;
678 if (SYS_CreateAlarm(&__wpdcb[i].sound_alarm) < 0)
680 WPAD_Shutdown();
681 _CPU_ISR_Restore(level);
682 return WPAD_ERR_UNKNOWN;
686 if(CONF_GetPadDevices(&__wpad_devs) < 0) {
687 WPAD_Shutdown();
688 _CPU_ISR_Restore(level);
689 return WPAD_ERR_BADCONF;
692 if(__wpad_devs.num_registered == 0) {
693 WPAD_Shutdown();
694 _CPU_ISR_Restore(level);
695 return WPAD_ERR_NONEREGISTERED;
698 if(__wpad_devs.num_registered > CONF_PAD_MAX_REGISTERED) {
699 WPAD_Shutdown();
700 _CPU_ISR_Restore(level);
701 return WPAD_ERR_BADCONF;
704 __wpads = wiiuse_init(WPAD_MAX_WIIMOTES,__wpad_eventCB);
705 if(__wpads==NULL) {
706 WPAD_Shutdown();
707 _CPU_ISR_Restore(level);
708 return WPAD_ERR_UNKNOWN;
711 __wiiuse_sensorbar_enable(1);
713 BTE_Init();
714 BTE_SetDisconnectCallback(__wpad_disconnectCB);
715 BTE_InitCore(__initcore_finished);
717 if (SYS_CreateAlarm(&__wpad_timer) < 0)
719 WPAD_Shutdown();
720 _CPU_ISR_Restore(level);
721 return WPAD_ERR_UNKNOWN;
724 SYS_RegisterResetFunc(&__wpad_resetinfo);
726 tb.tv_sec = 1;
727 tb.tv_nsec = 0;
728 SYS_SetPeriodicAlarm(__wpad_timer,&tb,&tb,__wpad_timeouthandler,NULL);
729 __wpads_inited = WPAD_STATE_ENABLING;
731 _CPU_ISR_Restore(level);
732 return WPAD_ERR_NONE;
735 s32 WPAD_ReadEvent(s32 chan, WPADData *data)
737 u32 level;
738 u32 maxbufs,smoothed = 0;
739 struct accel_t *accel_calib = NULL;
740 struct _wpad_cb *wpdcb = NULL;
741 WPADData *lstate = NULL,*wpadd = NULL;
743 if(chan<WPAD_CHAN_0 || chan>=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL;
745 _CPU_ISR_Disable(level);
746 if(__wpads_inited==WPAD_STATE_DISABLED) {
747 _CPU_ISR_Restore(level);
748 return WPAD_ERR_NOT_READY;
751 if(__wpads[chan] && WIIMOTE_IS_SET(__wpads[chan],WIIMOTE_STATE_CONNECTED)) {
752 if(WIIMOTE_IS_SET(__wpads[chan],WIIMOTE_STATE_HANDSHAKE_COMPLETE)) {
753 wpdcb = &__wpdcb[chan];
754 if(wpdcb->queue_ext!=NULL) {
755 maxbufs = wpdcb->queue_length;
756 wpadd = wpdcb->queue_ext;
757 } else {
758 maxbufs = EVENTQUEUE_LENGTH;
759 wpadd = wpdcb->queue_int;
761 if(wpdcb->queue_full == 0) {
762 _CPU_ISR_Restore(level);
763 return WPAD_ERR_QUEUE_EMPTY;
765 if(data)
766 *data = wpadd[wpdcb->queue_head];
767 wpdcb->queue_head++;
768 wpdcb->queue_head %= maxbufs;
769 wpdcb->queue_full--;
770 lstate = &wpdcb->lstate;
771 accel_calib = &__wpads[chan]->accel_calib;
772 smoothed = WIIMOTE_IS_FLAG_SET(__wpads[chan], WIIUSE_SMOOTHING);
773 } else {
774 _CPU_ISR_Restore(level);
775 return WPAD_ERR_NOT_READY;
777 } else {
778 _CPU_ISR_Restore(level);
779 return WPAD_ERR_NO_CONTROLLER;
782 _CPU_ISR_Restore(level);
783 if(data)
784 __wpad_calc_data(data,lstate,accel_calib,smoothed);
785 return 0;
788 s32 WPAD_DroppedEvents(s32 chan)
790 u32 level;
791 s32 ret;
792 int i;
793 int dropped = 0;
795 if(chan == WPAD_CHAN_ALL) {
796 for(i=WPAD_CHAN_0; i<WPAD_MAX_WIIMOTES; i++)
797 if((ret = WPAD_DroppedEvents(i)) < WPAD_ERR_NONE)
798 return ret;
799 else
800 dropped += ret;
801 return dropped;
804 if(chan<WPAD_CHAN_0 || chan>=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL;
806 _CPU_ISR_Disable(level);
807 if(__wpads_inited==WPAD_STATE_DISABLED) {
808 _CPU_ISR_Restore(level);
809 return WPAD_ERR_NOT_READY;
812 if(__wpads[chan]!=NULL) {
813 dropped = __wpdcb[chan].dropped_events;
814 __wpdcb[chan].dropped_events = 0;
816 _CPU_ISR_Restore(level);
817 return dropped;
820 s32 WPAD_Flush(s32 chan)
822 s32 ret;
823 int i;
824 int count = 0;
825 if(chan == WPAD_CHAN_ALL) {
826 for(i=WPAD_CHAN_0; i<WPAD_MAX_WIIMOTES; i++)
827 if((ret = WPAD_Flush(i)) < WPAD_ERR_NONE)
828 return ret;
829 else
830 count += ret;
831 return count;
834 while((ret = WPAD_ReadEvent(chan, NULL)) >= 0)
835 count++;
836 if(ret == WPAD_ERR_QUEUE_EMPTY) return count;
837 return ret;
840 s32 WPAD_ReadPending(s32 chan, WPADDataCallback datacb)
842 u32 btns_p = 0;
843 u32 btns_h = 0;
844 u32 btns_l = 0;
845 u32 btns_ch = 0;
846 u32 btns_ev = 0;
847 u32 btns_nh = 0;
848 u32 i;
849 s32 count = 0;
850 s32 ret;
852 if(chan == WPAD_CHAN_ALL) {
853 for(i=WPAD_CHAN_0; i<WPAD_MAX_WIIMOTES; i++)
854 if((ret = WPAD_ReadPending(i, datacb)) >= WPAD_ERR_NONE)
855 count += ret;
856 return count;
859 btns_p = btns_nh = btns_l = wpaddata[chan].btns_h;
860 while(1) {
861 ret = WPAD_ReadEvent(chan,&wpaddata[chan]);
862 if(ret < WPAD_ERR_NONE) break;
863 if(datacb)
864 datacb(chan, &wpaddata[chan]);
866 // we ignore everything except _h, since we have our
867 // own "fake" _l and everything gets recalculated at
868 // the end of the function
869 btns_h = wpaddata[chan].btns_h;
871 /* Button event coalescing:
872 * What we're doing here is get the very first button event
873 * (press or release) for each button. This gets propagated
874 * to the output. Held will therefore report an "old" state
875 * for every button that has changed more than once. This is
876 * intentional: next call to WPAD_ReadPending, if this button
877 * hasn't again changed, the opposite event will fire. This
878 * is the behavior that preserves the most information,
879 * within the limitations of trying to coalesce multiple events
880 * into one. It also keeps the output consistent, if possibly
881 * not fully up to date.
884 // buttons that changed that haven't changed before
885 btns_ch = (btns_h ^ btns_p) & ~btns_ev;
886 btns_p = btns_h;
887 // propagate changes in btns_ch to btns_nd
888 btns_nh = (btns_nh & ~btns_ch) | (btns_h & btns_ch);
889 // store these new changes to btns_ev
890 btns_ev |= btns_ch;
892 count++;
894 wpaddata[chan].btns_h = btns_nh;
895 wpaddata[chan].btns_l = btns_l;
896 wpaddata[chan].btns_d = btns_nh & ~btns_l;
897 wpaddata[chan].btns_u = ~btns_nh & btns_l;
898 if(ret == WPAD_ERR_QUEUE_EMPTY) return count;
899 return ret;
902 s32 WPAD_SetDataFormat(s32 chan, s32 fmt)
904 u32 level;
905 s32 ret;
906 int i;
908 if(chan == WPAD_CHAN_ALL) {
909 for(i=WPAD_CHAN_0; i<WPAD_MAX_WIIMOTES; i++)
910 if((ret = WPAD_SetDataFormat(i, fmt)) < WPAD_ERR_NONE)
911 return ret;
912 return WPAD_ERR_NONE;
915 if(chan<WPAD_CHAN_0 || chan>=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL;
917 _CPU_ISR_Disable(level);
918 if(__wpads_inited==WPAD_STATE_DISABLED) {
919 _CPU_ISR_Restore(level);
920 return WPAD_ERR_NOT_READY;
923 if(__wpads[chan]!=NULL) {
924 switch(fmt) {
925 case WPAD_FMT_BTNS:
926 case WPAD_FMT_BTNS_ACC:
927 case WPAD_FMT_BTNS_ACC_IR:
928 __wpdcb[chan].data_fmt = fmt;
929 __wpad_setfmt(chan);
930 break;
931 default:
932 _CPU_ISR_Restore(level);
933 return WPAD_ERR_BADVALUE;
936 _CPU_ISR_Restore(level);
937 return WPAD_ERR_NONE;
940 s32 WPAD_SetMotionPlus(s32 chan, u8 enable)
942 u32 level;
943 s32 ret;
944 int i;
946 if(chan == WPAD_CHAN_ALL) {
947 for(i=WPAD_CHAN_0; i<WPAD_MAX_WIIMOTES; i++)
948 if((ret = WPAD_SetMotionPlus(i, enable)) < WPAD_ERR_NONE)
949 return ret;
950 return WPAD_ERR_NONE;
953 if(chan<WPAD_CHAN_0 || chan>=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL;
955 _CPU_ISR_Disable(level);
956 if(__wpads_inited==WPAD_STATE_DISABLED) {
957 _CPU_ISR_Restore(level);
958 return WPAD_ERR_NOT_READY;
961 if(__wpads[chan]!=NULL) {
962 wiiuse_set_motion_plus(__wpads[chan], enable);
964 _CPU_ISR_Restore(level);
965 return WPAD_ERR_NONE;
968 s32 WPAD_SetVRes(s32 chan,u32 xres,u32 yres)
970 u32 level;
971 s32 ret;
972 int i;
974 if(chan == WPAD_CHAN_ALL) {
975 for(i=WPAD_CHAN_0; i<WPAD_MAX_WIIMOTES; i++)
976 if((ret = WPAD_SetVRes(i, xres, yres)) < WPAD_ERR_NONE)
977 return ret;
978 return WPAD_ERR_NONE;
981 if(chan<WPAD_CHAN_0 || chan>=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL;
983 _CPU_ISR_Disable(level);
984 if(__wpads_inited==WPAD_STATE_DISABLED) {
985 _CPU_ISR_Restore(level);
986 return WPAD_ERR_NOT_READY;
989 if(__wpads[chan]!=NULL)
990 wiiuse_set_ir_vres(__wpads[chan],xres,yres);
992 _CPU_ISR_Restore(level);
993 return WPAD_ERR_NONE;
996 s32 WPAD_GetStatus()
998 s32 ret;
999 u32 level;
1001 _CPU_ISR_Disable(level);
1002 ret = __wpads_inited;
1003 _CPU_ISR_Restore(level);
1005 return ret;
1008 s32 WPAD_Probe(s32 chan,u32 *type)
1010 s32 ret;
1011 u32 level,dev;
1012 wiimote *wm = NULL;
1014 if(chan<WPAD_CHAN_0 || chan>=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL;
1016 _CPU_ISR_Disable(level);
1017 if(__wpads_inited==WPAD_STATE_DISABLED) {
1018 _CPU_ISR_Restore(level);
1019 return WPAD_ERR_NOT_READY;
1022 wm = __wpads[chan];
1023 if(wm && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_CONNECTED)) {
1024 if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) {
1025 dev = WPAD_EXP_NONE;
1026 if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP)) {
1027 switch(wm->exp.type) {
1028 case WPAD_EXP_NUNCHUK:
1029 case WPAD_EXP_CLASSIC:
1030 case WPAD_EXP_GUITARHERO3:
1031 case WPAD_EXP_WIIBOARD:
1032 dev = wm->exp.type;
1033 break;
1036 if(type!=NULL) *type = dev;
1037 ret = WPAD_ERR_NONE;
1038 } else
1039 ret = WPAD_ERR_NOT_READY;
1040 } else
1041 ret = WPAD_ERR_NO_CONTROLLER;
1042 _CPU_ISR_Restore(level);
1044 return ret;
1047 s32 WPAD_SetEventBufs(s32 chan, WPADData *bufs, u32 cnt)
1049 u32 level;
1050 struct _wpad_cb *wpdcb = NULL;
1052 if(chan<WPAD_CHAN_0 || chan>=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL;
1054 _CPU_ISR_Disable(level);
1055 wpdcb = &__wpdcb[chan];
1056 wpdcb->queue_head = 0;
1057 wpdcb->queue_tail = 0;
1058 wpdcb->queue_full = 0;
1059 wpdcb->queue_length = cnt;
1060 wpdcb->queue_ext = bufs;
1061 _CPU_ISR_Restore(level);
1062 return WPAD_ERR_NONE;
1065 void WPAD_SetPowerButtonCallback(WPADShutdownCallback cb)
1067 u32 level;
1069 _CPU_ISR_Disable(level);
1070 if(cb)
1071 __wpad_powcb = cb;
1072 else
1073 __wpad_powcb = __wpad_def_powcb;
1074 _CPU_ISR_Restore(level);
1077 void WPAD_SetBatteryDeadCallback(WPADShutdownCallback cb)
1079 u32 level;
1081 _CPU_ISR_Disable(level);
1082 __wpad_batcb = cb;
1083 _CPU_ISR_Restore(level);
1086 s32 WPAD_Disconnect(s32 chan)
1088 u32 level, cnt = 0;
1089 struct _wpad_cb *wpdcb = NULL;
1091 if(chan<WPAD_CHAN_0 || chan>=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL;
1093 _CPU_ISR_Disable(level);
1094 if(__wpads_inited==WPAD_STATE_DISABLED) {
1095 _CPU_ISR_Restore(level);
1096 return WPAD_ERR_NOT_READY;
1099 wpdcb = &__wpdcb[chan];
1100 __wpad_disconnect(wpdcb);
1102 _CPU_ISR_Restore(level);
1104 while(__wpads_active&(0x01<<chan)) {
1105 usleep(50);
1106 if(++cnt > 3000) break;
1109 return WPAD_ERR_NONE;
1112 void WPAD_Shutdown()
1114 s32 i;
1115 u32 level;
1116 u32 cnt = 0;
1117 struct _wpad_cb *wpdcb = NULL;
1119 _CPU_ISR_Disable(level);
1121 __wpads_inited = WPAD_STATE_DISABLED;
1122 SYS_RemoveAlarm(__wpad_timer);
1123 for(i=0;i<WPAD_MAX_WIIMOTES;i++) {
1124 wpdcb = &__wpdcb[i];
1125 SYS_RemoveAlarm(wpdcb->sound_alarm);
1126 __wpad_disconnect(wpdcb);
1129 __wiiuse_sensorbar_enable(0);
1130 _CPU_ISR_Restore(level);
1132 while(__wpads_active) {
1133 usleep(50);
1134 if(++cnt > 3000) break;
1137 BTE_Shutdown();
1140 void WPAD_SetIdleTimeout(u32 seconds)
1142 u32 level;
1144 _CPU_ISR_Disable(level);
1145 __wpad_idletimeout = seconds;
1146 _CPU_ISR_Restore(level);
1149 s32 WPAD_ScanPads()
1151 return WPAD_ReadPending(WPAD_CHAN_ALL, NULL);
1154 s32 WPAD_Rumble(s32 chan, int status)
1156 int i;
1157 s32 ret;
1158 u32 level;
1160 if(chan == WPAD_CHAN_ALL) {
1161 for(i=WPAD_CHAN_0; i<WPAD_MAX_WIIMOTES; i++)
1162 if((ret = WPAD_Rumble(i,status)) < WPAD_ERR_NONE)
1163 return ret;
1164 return WPAD_ERR_NONE;
1167 if(chan<WPAD_CHAN_0 || chan>=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL;
1169 _CPU_ISR_Disable(level);
1170 if(__wpads_inited==WPAD_STATE_DISABLED) {
1171 _CPU_ISR_Restore(level);
1172 return WPAD_ERR_NOT_READY;
1175 if(__wpads[chan]!=NULL)
1176 wiiuse_rumble(__wpads[chan],status);
1178 _CPU_ISR_Restore(level);
1179 return WPAD_ERR_NONE;
1182 s32 WPAD_SetIdleThresholds(s32 chan, s32 btns, s32 ir, s32 accel, s32 js, s32 wb, s32 mp)
1184 int i;
1185 s32 ret;
1186 u32 level;
1188 if(chan == WPAD_CHAN_ALL) {
1189 for(i=WPAD_CHAN_0; i<WPAD_MAX_WIIMOTES; i++)
1190 if((ret = WPAD_SetIdleThresholds(i,btns,ir,accel,js,wb,mp)) < WPAD_ERR_NONE)
1191 return ret;
1192 return WPAD_ERR_NONE;
1195 if(chan<WPAD_CHAN_0 || chan>=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL;
1197 _CPU_ISR_Disable(level);
1198 if(__wpads_inited==WPAD_STATE_DISABLED) {
1199 _CPU_ISR_Restore(level);
1200 return WPAD_ERR_NOT_READY;
1203 __wpdcb[chan].thresh.btns = (btns<0) ? -1 : 0;
1204 __wpdcb[chan].thresh.ir = ir;
1205 __wpdcb[chan].thresh.acc = accel;
1206 __wpdcb[chan].thresh.js = js;
1207 __wpdcb[chan].thresh.wb = wb;
1208 __wpdcb[chan].thresh.mp = mp;
1211 _CPU_ISR_Restore(level);
1212 return WPAD_ERR_NONE;
1215 s32 WPAD_ControlSpeaker(s32 chan,s32 enable)
1217 int i;
1218 s32 ret;
1219 u32 level;
1221 if(chan == WPAD_CHAN_ALL) {
1222 for(i=WPAD_CHAN_0; i<WPAD_MAX_WIIMOTES; i++)
1223 if((ret = WPAD_ControlSpeaker(i,enable)) < WPAD_ERR_NONE)
1224 return ret;
1225 return WPAD_ERR_NONE;
1228 if(chan<WPAD_CHAN_0 || chan>=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL;
1230 _CPU_ISR_Disable(level);
1231 if(__wpads_inited==WPAD_STATE_DISABLED) {
1232 _CPU_ISR_Restore(level);
1233 return WPAD_ERR_NOT_READY;
1236 if(__wpads[chan]!=NULL) {
1237 __wpdcb[chan].speaker_enabled = enable;
1238 wiiuse_set_speaker(__wpads[chan],enable);
1241 _CPU_ISR_Restore(level);
1242 return WPAD_ERR_NONE;
1245 s32 WPAD_IsSpeakerEnabled(s32 chan)
1247 s32 ret;
1248 u32 level;
1249 wiimote *wm = NULL;
1251 if(chan<WPAD_CHAN_0 || chan>=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL;
1253 _CPU_ISR_Disable(level);
1254 if(__wpads_inited==WPAD_STATE_DISABLED) {
1255 _CPU_ISR_Restore(level);
1256 return WPAD_ERR_NOT_READY;
1259 wm = __wpads[chan];
1260 ret = WPAD_ERR_NOT_READY;
1261 if(wm && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_CONNECTED)) {
1262 if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)
1263 && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_SPEAKER)) ret = WPAD_ERR_NONE;
1266 _CPU_ISR_Restore(level);
1267 return ret;
1270 s32 WPAD_SendStreamData(s32 chan,void *buf,u32 len)
1272 u32 level;
1273 struct timespec tb;
1274 wiimote *wm = NULL;
1276 if(chan<WPAD_CHAN_0 || chan>=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL;
1278 _CPU_ISR_Disable(level);
1279 if(__wpads_inited==WPAD_STATE_DISABLED) {
1280 _CPU_ISR_Restore(level);
1281 return WPAD_ERR_NOT_READY;
1284 wm = __wpads[chan];
1285 if(wm!=NULL && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_CONNECTED)) {
1286 if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)
1287 && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_SPEAKER)) {
1288 __wpdcb[chan].sound_data = buf;
1289 __wpdcb[chan].sound_len = len;
1290 __wpdcb[chan].sound_off = 0;
1292 tb.tv_sec = 0;
1293 tb.tv_nsec = 6666667;
1294 SYS_SetPeriodicAlarm(__wpdcb[chan].sound_alarm,&tb,&tb,__wpad_sounddata_alarmhandler, &__wpdcb[chan]);
1298 _CPU_ISR_Restore(level);
1299 return WPAD_ERR_NONE;
1302 void WPAD_EncodeData(WPADEncStatus *info,u32 flag,const s16 *pcmSamples,s32 numSamples,u8 *encData)
1304 int n;
1305 short *samples = (short*)pcmSamples;
1306 WENCStatus *status = (WENCStatus*)info;
1308 if(!(flag&WPAD_ENC_CONT)) status->step = 0;
1310 n = (numSamples+1)/2;
1311 for(;n>0;n--) {
1312 int nibble;
1313 nibble = (wencdata(status,samples[0]))<<4;
1314 nibble |= (wencdata(status,samples[1]));
1315 *encData++ = nibble;
1316 samples += 2;
1320 WPADData *WPAD_Data(int chan)
1322 if(chan<0 || chan>=WPAD_MAX_WIIMOTES) return NULL;
1323 return &wpaddata[chan];
1326 u8 WPAD_BatteryLevel(int chan)
1328 if(chan<0 || chan>=WPAD_MAX_WIIMOTES) return 0;
1329 return wpaddata[chan].battery_level;
1332 u32 WPAD_ButtonsUp(int chan)
1334 if(chan<0 || chan>=WPAD_MAX_WIIMOTES) return 0;
1335 return wpaddata[chan].btns_u;
1338 u32 WPAD_ButtonsDown(int chan)
1340 if(chan<0 || chan>=WPAD_MAX_WIIMOTES) return 0;
1341 return wpaddata[chan].btns_d;
1344 u32 WPAD_ButtonsHeld(int chan)
1346 if(chan<0 || chan>=WPAD_MAX_WIIMOTES) return 0;
1347 return wpaddata[chan].btns_h;
1350 void WPAD_IR(int chan, struct ir_t *ir)
1352 if(chan<0 || chan>=WPAD_MAX_WIIMOTES || ir==NULL ) return;
1353 *ir = wpaddata[chan].ir;
1356 void WPAD_Orientation(int chan, struct orient_t *orient)
1358 if(chan<0 || chan>=WPAD_MAX_WIIMOTES || orient==NULL ) return;
1359 *orient = wpaddata[chan].orient;
1362 void WPAD_GForce(int chan, struct gforce_t *gforce)
1364 if(chan<0 || chan>=WPAD_MAX_WIIMOTES || gforce==NULL ) return;
1365 *gforce = wpaddata[chan].gforce;
1368 void WPAD_Accel(int chan, struct vec3w_t *accel)
1370 if(chan<0 || chan>=WPAD_MAX_WIIMOTES || accel==NULL ) return;
1371 *accel = wpaddata[chan].accel;
1374 void WPAD_Expansion(int chan, struct expansion_t *exp)
1376 if(chan<0 || chan>=WPAD_MAX_WIIMOTES || exp==NULL ) return;
1377 *exp = wpaddata[chan].exp;