Fixed smbClose() for older dkppc versions
[libogc.git] / wiiuse / events.c
blob34855014a7e1da693234f474ad5f7b23c2c0277d
1 #include <stdio.h>
3 #ifndef WIN32
4 #include <sys/time.h>
5 #include <unistd.h>
6 #include <errno.h>
7 #else
8 #include <winsock2.h>
9 #endif
11 #include <sys/types.h>
12 #include <stdlib.h>
13 #include <math.h>
14 #include <string.h>
16 #include "dynamics.h"
17 #include "definitions.h"
18 #include "wiiuse_internal.h"
19 #include "events.h"
20 #include "nunchuk.h"
21 #include "classic.h"
22 #include "guitar_hero_3.h"
23 #include "wiiboard.h"
24 #include "ir.h"
25 #include "io.h"
28 static void event_data_read(struct wiimote_t *wm,ubyte *msg)
30 ubyte err;
31 ubyte len;
32 uword offset;
33 struct op_t *op;
34 struct cmd_blk_t *cmd = wm->cmd_head;
36 wiiuse_pressed_buttons(wm,msg);
38 if(!cmd) return;
39 if(!(cmd->state==CMD_SENT && cmd->data[0]==WM_CMD_READ_DATA)) return;
41 //printf("event_data_read(%p)\n",cmd);
43 err = msg[2]&0x0f;
44 op = (struct op_t*)cmd->data;
45 if(err) {
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);
53 return;
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);
62 op->wait -= len;
63 if(op->wait>=op->readdata.size) op->wait = 0;
65 memcpy((op->buffer+offset-op->readdata.addr),(msg+5),len);
66 if(!op->wait) {
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);
84 if(!cmd) return;
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)
99 int ir = 0;
100 int attachment = 0;
101 int speaker = 0;
102 int led[4]= {0};
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);
122 goto done;
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);
130 goto done;
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);
135 if(attachment) {
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);
138 goto done;
140 } else {
141 WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_EXP_FAILED);
142 if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP)) {
143 wiiuse_disable_expansion(wm);
144 goto done;
147 wiiuse_set_report_type(wm,NULL);
149 done:
150 if(!cmd) return;
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) {
165 case EXP_NUNCHUK:
166 nunchuk_event(&wm->exp.nunchuk, msg);
167 break;
168 case EXP_CLASSIC:
169 classic_ctrl_event(&wm->exp.classic, msg);
170 break;
171 case EXP_GUITAR_HERO_3:
172 guitar_hero_3_event(&wm->exp.gh3, msg);
173 break;
174 case EXP_WII_BOARD:
175 wii_board_event(&wm->exp.wb, msg);
176 break;
177 default:
178 break;
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)
190 * Smooth the angles.
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)
209 ubyte event;
210 ubyte *msg;
212 event = wm->event_buf[0];
213 msg = wm->event_buf+1;
214 //printf("parse_event(%02x,%p)\n",event,msg);
215 switch(event) {
216 case WM_RPT_CTRL_STATUS:
217 event_status(wm,msg);
218 return;
219 case WM_RPT_READ:
220 event_data_read(wm,msg);
221 return;
222 case WM_RPT_WRITE:
223 event_data_write(wm,msg);
224 return;
225 case WM_RPT_BTN:
226 wiiuse_pressed_buttons(wm,msg);
227 break;
228 case WM_RPT_BTN_ACC:
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);
234 #ifndef GEKKO
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);
240 #endif
241 break;
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);
248 #ifndef GEKKO
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);
254 #endif
255 calculate_extended_ir(wm, msg+5);
256 break;
257 case WM_RPT_BTN_EXP:
258 wiiuse_pressed_buttons(wm,msg);
259 handle_expansion(wm,msg+2);
260 break;
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);
268 #ifndef GEKKO
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);
271 #endif
272 handle_expansion(wm, msg+5);
273 break;
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);
278 break;
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);
286 #ifndef GEKKO
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);
289 #endif
290 /* ir */
291 calculate_basic_ir(wm, msg+5);
293 handle_expansion(wm, msg+15);
294 break;
295 default:
296 WIIUSE_WARNING("Unknown event, can not handle it [Code 0x%x].", event);
297 return;
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) {
311 short now;
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 */
326 wm->btns = now;