usb 2.0 support through ios 58, and other usb improvements/corrections. patch by...
[libogc.git] / wiiuse / wiiuse.c
blobaa8ecb08f35fa782a6eda5777b5e1666a22786ef
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 void wiiuse_send_next_command(struct wiimote_t *wm)
17 struct cmd_blk_t *cmd = wm->cmd_head;
19 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return;
21 if(!cmd) return;
22 if(cmd->state!=CMD_READY) return;
24 cmd->state = CMD_SENT;
25 if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) cmd->data[1] |= 0x01;
27 wiiuse_io_write(wm,cmd->data,cmd->len);
30 static __inline__ void __wiiuse_push_command(struct wiimote_t *wm,struct cmd_blk_t *cmd)
32 uint level;
34 if(!wm || !cmd) return;
36 cmd->next = NULL;
37 cmd->state = CMD_READY;
39 _CPU_ISR_Disable(level);
40 if(wm->cmd_head==NULL) {
41 wm->cmd_head = wm->cmd_tail = cmd;
42 wiiuse_send_next_command(wm);
43 } else {
44 wm->cmd_tail->next = cmd;
45 wm->cmd_tail = cmd;
47 _CPU_ISR_Restore(level);
50 #ifndef GEKKO
51 struct wiimote_t** wiiuse_init(int wiimotes) {
52 #else
53 extern void __wiiuse_sensorbar_enable(int enable);
54 struct wiimote_t** wiiuse_init(int wiimotes, wii_event_cb event_cb) {
55 #endif
56 int i = 0;
57 struct wiimote_t** wm = NULL;
59 if (!wiimotes)
60 return NULL;
62 wm = __lwp_wkspace_allocate(sizeof(struct wiimote_t*) * wiimotes);
63 if(!wm) return NULL;
65 for (i = 0; i < wiimotes; ++i) {
66 wm[i] = __lwp_wkspace_allocate(sizeof(struct wiimote_t));
67 memset(wm[i], 0, sizeof(struct wiimote_t));
69 wm[i]->unid = i;
71 #if defined(WIN32)
72 wm[i]->dev_handle = 0;
73 wm[i]->stack = WIIUSE_STACK_UNKNOWN;
74 wm[i]->normal_timeout = WIIMOTE_DEFAULT_TIMEOUT;
75 wm[i]->exp_timeout = WIIMOTE_EXP_TIMEOUT;
76 wm[i]->timeout = wm[i]->normal_timeout;
77 #elif defined(GEKKO)
78 wm[i]->sock = NULL;
79 wm[i]->bdaddr = *BD_ADDR_ANY;
80 wm[i]->event_cb = event_cb;
81 wiiuse_init_cmd_queue(wm[i]);
82 #elif defined(unix)
83 wm[i]->bdaddr = *BDADDR_ANY;
84 wm[i]->out_sock = -1;
85 wm[i]->in_sock = -1;
86 #endif
88 wm[i]->state = WIIMOTE_INIT_STATES;
89 wm[i]->flags = WIIUSE_INIT_FLAGS;
91 wm[i]->event = WIIUSE_NONE;
93 wm[i]->exp.type = EXP_NONE;
95 wiiuse_set_aspect_ratio(wm[i], WIIUSE_ASPECT_4_3);
96 wiiuse_set_ir_position(wm[i], WIIUSE_IR_ABOVE);
98 wm[i]->accel_calib.st_alpha = WIIUSE_DEFAULT_SMOOTH_ALPHA;
101 return wm;
105 * @brief Set flags for the specified wiimote.
107 * @param wm Pointer to a wiimote_t structure.
108 * @param enable Flags to enable.
109 * @param disable Flags to disable.
111 * @return The flags set after 'enable' and 'disable' have been applied.
113 * The values 'enable' and 'disable' may be any flags OR'ed together.
114 * Flags are defined in wiiuse.h.
116 int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable) {
117 if (!wm) return 0;
119 /* remove mutually exclusive flags */
120 enable &= ~disable;
121 disable &= ~enable;
123 wm->flags |= enable;
124 wm->flags &= ~disable;
126 return wm->flags;
130 * @brief Set if the wiimote should report motion sensing.
132 * @param wm Pointer to a wiimote_t structure.
133 * @param status 1 to enable, 0 to disable.
135 * Since reporting motion sensing sends a lot of data,
136 * the wiimote saves power by not transmitting it
137 * by default.
139 void wiiuse_motion_sensing(struct wiimote_t* wm, int status)
141 if (status) {
142 if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_ACC)) return;
143 WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_ACC);
144 } else {
145 if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_ACC)) return;
146 WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC);
149 if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) return;
151 wiiuse_status(wm,NULL);
155 * @brief Toggle the state of the rumble.
157 * @param wm Pointer to a wiimote_t structure.
159 void wiiuse_toggle_rumble(struct wiimote_t* wm)
161 if (!wm) return;
163 WIIMOTE_TOGGLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
164 if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) return;
166 wiiuse_set_leds(wm,wm->leds,NULL);
170 * @brief Enable or disable the rumble.
172 * @param wm Pointer to a wiimote_t structure.
173 * @param status 1 to enable, 0 to disable.
175 void wiiuse_rumble(struct wiimote_t* wm, int status)
177 if (status && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) return;
178 else if(!status && !WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) return;
179 wiiuse_toggle_rumble(wm);
182 void wiiuse_set_leds(struct wiimote_t *wm,int leds,cmd_blk_cb cb)
184 ubyte buf;
186 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return;
188 wm->leds = (leds&0xf0);
190 buf = wm->leds;
191 wiiuse_sendcmd(wm,WM_CMD_LED,&buf,1,cb);
194 int wiiuse_set_report_type(struct wiimote_t *wm,cmd_blk_cb cb)
196 ubyte buf[2];
197 int motion,ir,exp;
199 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
201 buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00); /* set to 0x04 for continuous reporting */
202 buf[1] = 0x00;
204 motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC) || WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
205 exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP);
206 ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
208 if (motion && ir && exp) buf[1] = WM_RPT_BTN_ACC_IR_EXP;
209 else if (motion && exp) buf[1] = WM_RPT_BTN_ACC_EXP;
210 else if (motion && ir) buf[1] = WM_RPT_BTN_ACC_IR;
211 else if (ir && exp) buf[1] = WM_RPT_BTN_IR_EXP;
212 else if (ir) buf[1] = WM_RPT_BTN_ACC_IR;
213 else if (exp) buf[1] = WM_RPT_BTN_EXP;
214 else if (motion) buf[1] = WM_RPT_BTN_ACC;
215 else buf[1] = WM_RPT_BTN;
217 WIIUSE_DEBUG("Setting report type: 0x%x", buf[1]);
219 wiiuse_sendcmd(wm,WM_CMD_REPORT_TYPE,buf,2,cb);
220 return buf[1];
223 void wiiuse_status(struct wiimote_t *wm,cmd_blk_cb cb)
225 ubyte buf;
227 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return;
229 buf = 0x00;
230 wiiuse_sendcmd(wm,WM_CMD_CTRL_STATUS,&buf,1,cb);
233 int wiiuse_read_data(struct wiimote_t *wm,ubyte *buffer,uint addr,uword len,cmd_blk_cb cb)
235 struct op_t *op;
236 struct cmd_blk_t *cmd;
238 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
239 if(!buffer || !len) return 0;
241 cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
242 if(!cmd) return 0;
244 cmd->cb = cb;
245 cmd->len = 7;
247 op = (struct op_t*)cmd->data;
248 op->cmd = WM_CMD_READ_DATA;
249 op->buffer = buffer;
250 op->wait = len;
251 op->readdata.addr = BIG_ENDIAN_LONG(addr);
252 op->readdata.size = BIG_ENDIAN_SHORT(len);
253 __wiiuse_push_command(wm,cmd);
255 return 1;
258 int wiiuse_write_data(struct wiimote_t *wm,uint addr,ubyte *data,ubyte len,cmd_blk_cb cb)
260 struct op_t *op;
261 struct cmd_blk_t *cmd;
263 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
264 if(!data || !len) return 0;
266 cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
267 if(!cmd) return 0;
269 cmd->cb = cb;
270 cmd->len = 22;
272 op = (struct op_t*)cmd->data;
273 op->cmd = WM_CMD_WRITE_DATA;
274 op->buffer = NULL;
275 op->wait = 0;
276 op->writedata.addr = BIG_ENDIAN_LONG(addr);
277 op->writedata.size = (len&0x0f);
278 memcpy(op->writedata.data,data,len);
279 memset(op->writedata.data+len,0,(16 - len));
280 __wiiuse_push_command(wm,cmd);
282 return 1;
285 int wiiuse_write_streamdata(struct wiimote_t *wm,ubyte *data,ubyte len,cmd_blk_cb cb)
287 struct cmd_blk_t *cmd;
289 if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
290 if(!data || !len || len>20) return 0;
292 cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
293 if(!cmd) return 0;
295 cmd->cb = cb;
296 cmd->len = 22;
297 cmd->data[0] = WM_CMD_STREAM_DATA;
298 cmd->data[1] = (len<<3);
299 memcpy(cmd->data+2,data,len);
300 __wiiuse_push_command(wm,cmd);
302 return 1;
305 int wiiuse_sendcmd(struct wiimote_t *wm,ubyte report_type,ubyte *msg,int len,cmd_blk_cb cb)
307 struct cmd_blk_t *cmd;
309 cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
310 if(!cmd) return 0;
312 cmd->cb = cb;
313 cmd->len = (1+len);
315 cmd->data[0] = report_type;
316 memcpy(cmd->data+1,msg,len);
317 __wiiuse_push_command(wm,cmd);
319 return 1;