11 #include <sys/types.h>
17 #include "definitions.h"
18 #include "wiiuse_internal.h"
22 #include "guitar_hero_3.h"
24 #include "motion_plus.h"
29 static void event_data_read(struct wiimote_t
*wm
,ubyte
*msg
)
35 struct cmd_blk_t
*cmd
= wm
->cmd_head
;
37 wiiuse_pressed_buttons(wm
,msg
);
40 if(!(cmd
->state
==CMD_SENT
&& cmd
->data
[0]==WM_CMD_READ_DATA
)) return;
42 //printf("event_data_read(%p)\n",cmd);
45 op
= (struct op_t
*)cmd
->data
;
47 wm
->cmd_head
= cmd
->next
;
49 cmd
->state
= CMD_DONE
;
50 if(cmd
->cb
!=NULL
) cmd
->cb(wm
,op
->buffer
,(op
->readdata
.size
- op
->wait
));
52 __lwp_queue_append(&wm
->cmdq
,&cmd
->node
);
53 wiiuse_send_next_command(wm
);
57 len
= ((msg
[2]&0xf0)>>4)+1;
58 offset
= BIG_ENDIAN_SHORT(*(uword
*)(msg
+3));
60 //printf("addr: %08x\noffset: %d\nlen: %d\n",req->addr,offset,len);
62 op
->readdata
.addr
= (op
->readdata
.addr
&0xffff);
64 if(op
->wait
>=op
->readdata
.size
) op
->wait
= 0;
66 memcpy((op
->buffer
+offset
-op
->readdata
.addr
),(msg
+5),len
);
68 wm
->cmd_head
= cmd
->next
;
70 wm
->event
= WIIUSE_READ_DATA
;
71 cmd
->state
= CMD_DONE
;
72 if(cmd
->cb
!=NULL
) cmd
->cb(wm
,op
->buffer
,op
->readdata
.size
);
74 __lwp_queue_append(&wm
->cmdq
,&cmd
->node
);
75 wiiuse_send_next_command(wm
);
79 static void event_data_write(struct wiimote_t
*wm
,ubyte
*msg
)
81 struct cmd_blk_t
*cmd
= wm
->cmd_head
;
83 wiiuse_pressed_buttons(wm
,msg
);
86 if(!(cmd
->state
==CMD_SENT
&& (cmd
->data
[0]==WM_CMD_WRITE_DATA
|| cmd
->data
[0]==WM_CMD_STREAM_DATA
))) return;
88 wm
->cmd_head
= cmd
->next
;
90 wm
->event
= WIIUSE_WRITE_DATA
;
91 cmd
->state
= CMD_DONE
;
92 if(cmd
->cb
) cmd
->cb(wm
,NULL
,0);
94 __lwp_queue_append(&wm
->cmdq
,&cmd
->node
);
95 wiiuse_send_next_command(wm
);
98 static void event_status(struct wiimote_t
*wm
,ubyte
*msg
)
104 struct cmd_blk_t
*cmd
= wm
->cmd_head
;
106 wiiuse_pressed_buttons(wm
,msg
);
108 wm
->event
= WIIUSE_STATUS
;
109 //if(msg[2]&WM_CTRL_STATUS_BYTE1_LED_1) led[0] = 1;
110 //if(msg[2]&WM_CTRL_STATUS_BYTE1_LED_2) led[1] = 1;
111 //if(msg[2]&WM_CTRL_STATUS_BYTE1_LED_3) led[2] = 1;
112 //if(msg[2]&WM_CTRL_STATUS_BYTE1_LED_4) led[3] = 1;
114 if((msg
[2]&WM_CTRL_STATUS_BYTE1_ATTACHMENT
)==WM_CTRL_STATUS_BYTE1_ATTACHMENT
) attachment
= 1;
115 if((msg
[2]&WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED
)==WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED
) speaker
= 1;
116 if((msg
[2]&WM_CTRL_STATUS_BYTE1_IR_ENABLED
)==WM_CTRL_STATUS_BYTE1_IR_ENABLED
) ir
= 1;
118 wm
->battery_level
= msg
[5];
120 if(!ir
&& WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_IR_INIT
)) {
121 WIIMOTE_DISABLE_STATE(wm
, WIIMOTE_STATE_IR_INIT
);
122 wiiuse_set_ir(wm
, 1);
125 if(ir
&& !WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_IR
)) WIIMOTE_ENABLE_STATE(wm
,WIIMOTE_STATE_IR
);
126 else if(!ir
&& WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_IR
)) WIIMOTE_DISABLE_STATE(wm
, WIIMOTE_STATE_IR
);
128 if(!speaker
&& WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_SPEAKER_INIT
)) {
129 WIIMOTE_DISABLE_STATE(wm
,WIIMOTE_STATE_SPEAKER_INIT
);
130 wiiuse_set_speaker(wm
,1);
133 if(speaker
&& !WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_SPEAKER
)) WIIMOTE_ENABLE_STATE(wm
,WIIMOTE_STATE_SPEAKER
);
134 else if(!speaker
&& WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_SPEAKER
)) WIIMOTE_DISABLE_STATE(wm
,WIIMOTE_STATE_SPEAKER
);
137 if(!WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_EXP
) && !WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_EXP_FAILED
) && !WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_EXP_HANDSHAKE
)) {
138 wiiuse_handshake_expansion_start(wm
);
142 WIIMOTE_DISABLE_STATE(wm
,WIIMOTE_STATE_EXP_FAILED
);
143 if(WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_EXP
)) {
144 wiiuse_disable_expansion(wm
);
148 wiiuse_set_report_type(wm
,NULL
);
152 if(!(cmd
->state
==CMD_SENT
&& cmd
->data
[0]==WM_CMD_CTRL_STATUS
)) return;
154 wm
->cmd_head
= cmd
->next
;
156 cmd
->state
= CMD_DONE
;
157 if(cmd
->cb
!=NULL
) cmd
->cb(wm
,msg
,6);
159 __lwp_queue_append(&wm
->cmdq
,&cmd
->node
);
160 wiiuse_send_next_command(wm
);
163 static void handle_expansion(struct wiimote_t
*wm
,ubyte
*msg
)
165 switch (wm
->exp
.type
) {
167 nunchuk_event(&wm
->exp
.nunchuk
, msg
);
170 classic_ctrl_event(&wm
->exp
.classic
, msg
);
172 case EXP_GUITAR_HERO_3
:
173 guitar_hero_3_event(&wm
->exp
.gh3
, msg
);
176 wii_board_event(&wm
->exp
.wb
, msg
);
178 case EXP_MOTION_PLUS
:
179 motion_plus_event(&wm
->exp
.mp
, msg
);
187 * @brief Called on a cycle where no significant change occurs.
189 * @param wm Pointer to a wiimote_t structure.
191 void idle_cycle(struct wiimote_t
* wm
)
196 * This is done to make sure that on every cycle the orientation
197 * angles are smoothed. Normally when an event occurs the angles
198 * are updated and smoothed, but if no packet comes in then the
199 * angles remain the same. This means the angle wiiuse reports
200 * is still an old value. Smoothing needs to be applied in this
201 * case in order for the angle it reports to converge to the true
202 * angle of the device.
204 //printf("idle_cycle()\n");///
205 if (WIIUSE_USING_ACC(wm
) && WIIMOTE_IS_FLAG_SET(wm
, WIIUSE_SMOOTHING
)) {
206 apply_smoothing(&wm
->accel_calib
, &wm
->orient
, SMOOTH_ROLL
);
207 apply_smoothing(&wm
->accel_calib
, &wm
->orient
, SMOOTH_PITCH
);
211 void parse_event(struct wiimote_t
*wm
)
216 event
= wm
->event_buf
[0];
217 msg
= wm
->event_buf
+1;
218 //printf("parse_event(%02x,%p)\n",event,msg);
220 case WM_RPT_CTRL_STATUS
:
221 event_status(wm
,msg
);
224 event_data_read(wm
,msg
);
227 event_data_write(wm
,msg
);
230 wiiuse_pressed_buttons(wm
,msg
);
233 wiiuse_pressed_buttons(wm
,msg
);
235 wm
->accel
.x
= (msg
[2]<<2)|((msg
[0]>>5)&3);
236 wm
->accel
.y
= (msg
[3]<<2)|((msg
[1]>>4)&2);
237 wm
->accel
.z
= (msg
[4]<<2)|((msg
[1]>>5)&2);
239 /* calculate the remote orientation */
240 calculate_orientation(&wm
->accel_calib
, &wm
->accel
, &wm
->orient
, WIIMOTE_IS_FLAG_SET(wm
, WIIUSE_SMOOTHING
));
242 /* calculate the gforces on each axis */
243 calculate_gforce(&wm
->accel_calib
, &wm
->accel
, &wm
->gforce
);
246 case WM_RPT_BTN_ACC_IR
:
247 wiiuse_pressed_buttons(wm
,msg
);
249 wm
->accel
.x
= (msg
[2]<<2)|((msg
[0]>>5)&3);
250 wm
->accel
.y
= (msg
[3]<<2)|((msg
[1]>>4)&2);
251 wm
->accel
.z
= (msg
[4]<<2)|((msg
[1]>>5)&2);
253 /* calculate the remote orientation */
254 calculate_orientation(&wm
->accel_calib
, &wm
->accel
, &wm
->orient
, WIIMOTE_IS_FLAG_SET(wm
, WIIUSE_SMOOTHING
));
256 /* calculate the gforces on each axis */
257 calculate_gforce(&wm
->accel_calib
, &wm
->accel
, &wm
->gforce
);
259 calculate_extended_ir(wm
, msg
+5);
262 wiiuse_pressed_buttons(wm
,msg
);
263 handle_expansion(wm
,msg
+2);
265 case WM_RPT_BTN_ACC_EXP
:
266 /* button - motion - expansion */
267 wiiuse_pressed_buttons(wm
, msg
);
269 wm
->accel
.x
= (msg
[2]<<2)|((msg
[0]>>5)&3);
270 wm
->accel
.y
= (msg
[3]<<2)|((msg
[1]>>4)&2);
271 wm
->accel
.z
= (msg
[4]<<2)|((msg
[1]>>5)&2);
273 calculate_orientation(&wm
->accel_calib
, &wm
->accel
, &wm
->orient
, WIIMOTE_IS_FLAG_SET(wm
, WIIUSE_SMOOTHING
));
274 calculate_gforce(&wm
->accel_calib
, &wm
->accel
, &wm
->gforce
);
276 handle_expansion(wm
, msg
+5);
278 case WM_RPT_BTN_IR_EXP
:
279 wiiuse_pressed_buttons(wm
,msg
);
280 calculate_basic_ir(wm
, msg
+2);
281 handle_expansion(wm
,msg
+12);
283 case WM_RPT_BTN_ACC_IR_EXP
:
284 /* button - motion - ir - expansion */
285 wiiuse_pressed_buttons(wm
, msg
);
287 wm
->accel
.x
= (msg
[2]<<2)|((msg
[0]>>5)&3);
288 wm
->accel
.y
= (msg
[3]<<2)|((msg
[1]>>4)&2);
289 wm
->accel
.z
= (msg
[4]<<2)|((msg
[1]>>5)&2);
291 calculate_orientation(&wm
->accel_calib
, &wm
->accel
, &wm
->orient
, WIIMOTE_IS_FLAG_SET(wm
, WIIUSE_SMOOTHING
));
292 calculate_gforce(&wm
->accel_calib
, &wm
->accel
, &wm
->gforce
);
295 calculate_basic_ir(wm
, msg
+5);
297 handle_expansion(wm
, msg
+15);
300 WIIUSE_WARNING("Unknown event, can not handle it [Code 0x%x].", event
);
304 /* was there an event? */
305 wm
->event
= WIIUSE_EVENT
;
309 * @brief Find what buttons are pressed.
311 * @param wm Pointer to a wiimote_t structure.
312 * @param msg The message specified in the event packet.
314 void wiiuse_pressed_buttons(struct wiimote_t
* wm
, ubyte
* msg
) {
317 /* convert to big endian */
318 now
= BIG_ENDIAN_SHORT(*(short*)msg
) & WIIMOTE_BUTTON_ALL
;
320 /* preserve old btns pressed */
321 wm
->btns_last
= wm
->btns
;
323 /* pressed now & were pressed, then held */
324 wm
->btns_held
= (now
& wm
->btns
);
326 /* were pressed or were held & not pressed now, then released */
327 wm
->btns_released
= ((wm
->btns
| wm
->btns_held
) & ~now
);
329 /* buttons pressed now */