11 #include <sys/types.h>
17 #include "definitions.h"
18 #include "wiiuse_internal.h"
22 #include "guitar_hero_3.h"
28 static void event_data_read(struct wiimote_t
*wm
,ubyte
*msg
)
34 struct cmd_blk_t
*cmd
= wm
->cmd_head
;
36 wiiuse_pressed_buttons(wm
,msg
);
39 if(!(cmd
->state
==CMD_SENT
&& cmd
->data
[0]==WM_CMD_READ_DATA
)) return;
41 //printf("event_data_read(%p)\n",cmd);
44 op
= (struct op_t
*)cmd
->data
;
46 wm
->cmd_head
= cmd
->next
;
48 cmd
->state
= CMD_DONE
;
49 if(cmd
->cb
!=NULL
) cmd
->cb(wm
,op
->buffer
,(op
->readdata
.size
- op
->wait
));
51 __lwp_queue_append(&wm
->cmdq
,&cmd
->node
);
52 wiiuse_send_next_command(wm
);
56 len
= ((msg
[2]&0xf0)>>4)+1;
57 offset
= BIG_ENDIAN_SHORT(*(uword
*)(msg
+3));
59 //printf("addr: %08x\noffset: %d\nlen: %d\n",req->addr,offset,len);
61 op
->readdata
.addr
= (op
->readdata
.addr
&0xffff);
63 if(op
->wait
>=op
->readdata
.size
) op
->wait
= 0;
65 memcpy((op
->buffer
+offset
-op
->readdata
.addr
),(msg
+5),len
);
67 wm
->cmd_head
= cmd
->next
;
69 wm
->event
= WIIUSE_READ_DATA
;
70 cmd
->state
= CMD_DONE
;
71 if(cmd
->cb
!=NULL
) cmd
->cb(wm
,op
->buffer
,op
->readdata
.size
);
73 __lwp_queue_append(&wm
->cmdq
,&cmd
->node
);
74 wiiuse_send_next_command(wm
);
78 static void event_data_write(struct wiimote_t
*wm
,ubyte
*msg
)
80 struct cmd_blk_t
*cmd
= wm
->cmd_head
;
82 wiiuse_pressed_buttons(wm
,msg
);
85 if(!(cmd
->state
==CMD_SENT
&& (cmd
->data
[0]==WM_CMD_WRITE_DATA
|| cmd
->data
[0]==WM_CMD_STREAM_DATA
))) return;
87 wm
->cmd_head
= cmd
->next
;
89 wm
->event
= WIIUSE_WRITE_DATA
;
90 cmd
->state
= CMD_DONE
;
91 if(cmd
->cb
) cmd
->cb(wm
,NULL
,0);
93 __lwp_queue_append(&wm
->cmdq
,&cmd
->node
);
94 wiiuse_send_next_command(wm
);
97 static void event_status(struct wiimote_t
*wm
,ubyte
*msg
)
103 struct cmd_blk_t
*cmd
= wm
->cmd_head
;
105 wiiuse_pressed_buttons(wm
,msg
);
107 wm
->event
= WIIUSE_STATUS
;
108 if(msg
[2]&WM_CTRL_STATUS_BYTE1_LED_1
) led
[0] = 1;
109 if(msg
[2]&WM_CTRL_STATUS_BYTE1_LED_2
) led
[1] = 1;
110 if(msg
[2]&WM_CTRL_STATUS_BYTE1_LED_3
) led
[2] = 1;
111 if(msg
[2]&WM_CTRL_STATUS_BYTE1_LED_4
) led
[3] = 1;
113 if((msg
[2]&WM_CTRL_STATUS_BYTE1_ATTACHMENT
)==WM_CTRL_STATUS_BYTE1_ATTACHMENT
) attachment
= 1;
114 if((msg
[2]&WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED
)==WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED
) speaker
= 1;
115 if((msg
[2]&WM_CTRL_STATUS_BYTE1_IR_ENABLED
)==WM_CTRL_STATUS_BYTE1_IR_ENABLED
) ir
= 1;
117 wm
->battery_level
= msg
[5];
119 if(!ir
&& WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_IR_INIT
)) {
120 WIIMOTE_DISABLE_STATE(wm
, WIIMOTE_STATE_IR_INIT
);
121 wiiuse_set_ir(wm
, 1);
124 if(ir
&& !WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_IR
)) WIIMOTE_ENABLE_STATE(wm
,WIIMOTE_STATE_IR
);
125 else if(!ir
&& WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_IR
)) WIIMOTE_DISABLE_STATE(wm
, WIIMOTE_STATE_IR
);
127 if(!speaker
&& WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_SPEAKER_INIT
)) {
128 WIIMOTE_DISABLE_STATE(wm
,WIIMOTE_STATE_SPEAKER_INIT
);
129 wiiuse_set_speaker(wm
,1);
132 if(speaker
&& !WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_SPEAKER
)) WIIMOTE_ENABLE_STATE(wm
,WIIMOTE_STATE_SPEAKER
);
133 else if(!speaker
&& WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_SPEAKER
)) WIIMOTE_DISABLE_STATE(wm
,WIIMOTE_STATE_SPEAKER
);
136 if(!WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_EXP
) && !WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_EXP_FAILED
) && !WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_EXP_HANDSHAKE
)) {
137 wiiuse_handshake_expansion_start(wm
);
141 WIIMOTE_DISABLE_STATE(wm
,WIIMOTE_STATE_EXP_FAILED
);
142 if(WIIMOTE_IS_SET(wm
,WIIMOTE_STATE_EXP
)) {
143 wiiuse_disable_expansion(wm
);
147 wiiuse_set_report_type(wm
,NULL
);
151 if(!(cmd
->state
==CMD_SENT
&& cmd
->data
[0]==WM_CMD_CTRL_STATUS
)) return;
153 wm
->cmd_head
= cmd
->next
;
155 cmd
->state
= CMD_DONE
;
156 if(cmd
->cb
!=NULL
) cmd
->cb(wm
,msg
,6);
158 __lwp_queue_append(&wm
->cmdq
,&cmd
->node
);
159 wiiuse_send_next_command(wm
);
162 static void handle_expansion(struct wiimote_t
*wm
,ubyte
*msg
)
164 switch (wm
->exp
.type
) {
166 nunchuk_event(&wm
->exp
.nunchuk
, msg
);
169 classic_ctrl_event(&wm
->exp
.classic
, msg
);
171 case EXP_GUITAR_HERO_3
:
172 guitar_hero_3_event(&wm
->exp
.gh3
, msg
);
175 wii_board_event(&wm
->exp
.wb
, msg
);
183 * @brief Called on a cycle where no significant change occurs.
185 * @param wm Pointer to a wiimote_t structure.
187 void idle_cycle(struct wiimote_t
* wm
)
192 * This is done to make sure that on every cycle the orientation
193 * angles are smoothed. Normally when an event occurs the angles
194 * are updated and smoothed, but if no packet comes in then the
195 * angles remain the same. This means the angle wiiuse reports
196 * is still an old value. Smoothing needs to be applied in this
197 * case in order for the angle it reports to converge to the true
198 * angle of the device.
200 //printf("idle_cycle()\n");///
201 if (WIIUSE_USING_ACC(wm
) && WIIMOTE_IS_FLAG_SET(wm
, WIIUSE_SMOOTHING
)) {
202 apply_smoothing(&wm
->accel_calib
, &wm
->orient
, SMOOTH_ROLL
);
203 apply_smoothing(&wm
->accel_calib
, &wm
->orient
, SMOOTH_PITCH
);
207 void parse_event(struct wiimote_t
*wm
)
212 event
= wm
->event_buf
[0];
213 msg
= wm
->event_buf
+1;
214 //printf("parse_event(%02x,%p)\n",event,msg);
216 case WM_RPT_CTRL_STATUS
:
217 event_status(wm
,msg
);
220 event_data_read(wm
,msg
);
223 event_data_write(wm
,msg
);
226 wiiuse_pressed_buttons(wm
,msg
);
229 wiiuse_pressed_buttons(wm
,msg
);
231 wm
->accel
.x
= (msg
[2]<<2)|((msg
[0]>>5)&3);
232 wm
->accel
.y
= (msg
[3]<<2)|((msg
[1]>>4)&2);
233 wm
->accel
.z
= (msg
[4]<<2)|((msg
[1]>>5)&2);
235 /* calculate the remote orientation */
236 calculate_orientation(&wm
->accel_calib
, &wm
->accel
, &wm
->orient
, WIIMOTE_IS_FLAG_SET(wm
, WIIUSE_SMOOTHING
));
238 /* calculate the gforces on each axis */
239 calculate_gforce(&wm
->accel_calib
, &wm
->accel
, &wm
->gforce
);
242 case WM_RPT_BTN_ACC_IR
:
243 wiiuse_pressed_buttons(wm
,msg
);
245 wm
->accel
.x
= (msg
[2]<<2)|((msg
[0]>>5)&3);
246 wm
->accel
.y
= (msg
[3]<<2)|((msg
[1]>>4)&2);
247 wm
->accel
.z
= (msg
[4]<<2)|((msg
[1]>>5)&2);
249 /* calculate the remote orientation */
250 calculate_orientation(&wm
->accel_calib
, &wm
->accel
, &wm
->orient
, WIIMOTE_IS_FLAG_SET(wm
, WIIUSE_SMOOTHING
));
252 /* calculate the gforces on each axis */
253 calculate_gforce(&wm
->accel_calib
, &wm
->accel
, &wm
->gforce
);
255 calculate_extended_ir(wm
, msg
+5);
258 wiiuse_pressed_buttons(wm
,msg
);
259 handle_expansion(wm
,msg
+2);
261 case WM_RPT_BTN_ACC_EXP
:
262 /* button - motion - expansion */
263 wiiuse_pressed_buttons(wm
, msg
);
265 wm
->accel
.x
= (msg
[2]<<2)|((msg
[0]>>5)&3);
266 wm
->accel
.y
= (msg
[3]<<2)|((msg
[1]>>4)&2);
267 wm
->accel
.z
= (msg
[4]<<2)|((msg
[1]>>5)&2);
269 calculate_orientation(&wm
->accel_calib
, &wm
->accel
, &wm
->orient
, WIIMOTE_IS_FLAG_SET(wm
, WIIUSE_SMOOTHING
));
270 calculate_gforce(&wm
->accel_calib
, &wm
->accel
, &wm
->gforce
);
272 handle_expansion(wm
, msg
+5);
274 case WM_RPT_BTN_IR_EXP
:
275 wiiuse_pressed_buttons(wm
,msg
);
276 calculate_basic_ir(wm
, msg
+2);
277 handle_expansion(wm
,msg
+12);
279 case WM_RPT_BTN_ACC_IR_EXP
:
280 /* button - motion - ir - expansion */
281 wiiuse_pressed_buttons(wm
, msg
);
283 wm
->accel
.x
= (msg
[2]<<2)|((msg
[0]>>5)&3);
284 wm
->accel
.y
= (msg
[3]<<2)|((msg
[1]>>4)&2);
285 wm
->accel
.z
= (msg
[4]<<2)|((msg
[1]>>5)&2);
287 calculate_orientation(&wm
->accel_calib
, &wm
->accel
, &wm
->orient
, WIIMOTE_IS_FLAG_SET(wm
, WIIUSE_SMOOTHING
));
288 calculate_gforce(&wm
->accel_calib
, &wm
->accel
, &wm
->gforce
);
291 calculate_basic_ir(wm
, msg
+5);
293 handle_expansion(wm
, msg
+15);
296 WIIUSE_WARNING("Unknown event, can not handle it [Code 0x%x].", event
);
300 /* was there an event? */
301 wm
->event
= WIIUSE_EVENT
;
305 * @brief Find what buttons are pressed.
307 * @param wm Pointer to a wiimote_t structure.
308 * @param msg The message specified in the event packet.
310 void wiiuse_pressed_buttons(struct wiimote_t
* wm
, ubyte
* msg
) {
313 /* convert to big endian */
314 now
= BIG_ENDIAN_SHORT(*(short*)msg
) & WIIMOTE_BUTTON_ALL
;
316 /* preserve old btns pressed */
317 wm
->btns_last
= wm
->btns
;
319 /* pressed now & were pressed, then held */
320 wm
->btns_held
= (now
& wm
->btns
);
322 /* were pressed or were held & not pressed now, then released */
323 wm
->btns_released
= ((wm
->btns
| wm
->btns_held
) & ~now
);
325 /* buttons pressed now */