Changeset 101
- Timestamp:
- 04/24/07 19:41:13 (2 years ago)
- Files:
-
- trunk/ChangeLog (modified) (1 diff)
- trunk/NEWS (modified) (1 diff)
- trunk/libcwiid/Makefile.in (modified) (1 diff)
- trunk/libcwiid/bluetooth.c (modified) (6 diffs)
- trunk/libcwiid/command.c (modified) (5 diffs)
- trunk/libcwiid/connect.c (modified) (7 diffs)
- trunk/libcwiid/cwiid.h (modified) (15 diffs)
- trunk/libcwiid/cwiid_internal.h (modified) (6 diffs)
- trunk/libcwiid/event.c (deleted)
- trunk/libcwiid/interface.c (copied) (copied from branches/api_overhaul/libcwiid/interface.c)
- trunk/libcwiid/process.c (copied) (copied from branches/api_overhaul/libcwiid/process.c)
- trunk/libcwiid/queue.c (deleted)
- trunk/libcwiid/queue.h (deleted)
- trunk/libcwiid/rw.c (deleted)
- trunk/libcwiid/state.c (copied) (copied from branches/api_overhaul/libcwiid/state.c)
- trunk/libcwiid/thread.c (copied) (copied from branches/api_overhaul/libcwiid/thread.c)
- trunk/libcwiid/util.c (modified) (9 diffs)
- trunk/wmdemo/wmdemo.c (modified) (10 diffs)
- trunk/wmgui/main.c (modified) (10 diffs)
- trunk/wminput/main.c (modified) (14 diffs)
- trunk/wminput/plugins/acc/acc.c (modified) (2 diffs)
- trunk/wminput/plugins/ir_ptr/ir_ptr.c (modified) (11 diffs)
- trunk/wminput/plugins/nunchuk_acc/nunchuk_acc.c (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/ChangeLog
r91 r101 1 2007-04-24 L. Donnie Smith <cwiid@abstrakraft.org> 2 libcwiid 3 * rewrite (API overhaul) 4 5 wmdemo 6 * updated for API overhaul 7 8 wmgui 9 * updated for API overhaul 10 11 wminput 12 * updated for API overhaul 13 1 14 2007-04-15 <work.eric@gmail.com> 2 15 wminput trunk/NEWS
r37 r101 1 0.5.03 2 - Bugfixes, lswm utility, disconnect messages, wminput infinite wait 3 1 4 0.5.02 2 5 - Bugfixes, configure --disable-ldconfig trunk/libcwiid/Makefile.in
r83 r101 6 6 MAJOR_VER = 0 7 7 MINOR_VER = 1 8 SOURCES = connect.c command.c event.c rw.c bluetooth.c util.c queue.c 8 SOURCES = bluetooth.c command.c connect.c interface.c process.c state.c \ 9 thread.c util.c 9 10 LDLIBS += -lbluetooth -lpthread -lrt 10 11 LIB_INST_DIR = @libdir@ trunk/libcwiid/bluetooth.c
r88 r101 16 16 * 17 17 * ChangeLog: 18 * 2007-04-24 L. Donnie Smith (cwiid@abstrakraft.org> 19 * * revised error messages 20 * 18 21 * 2007-04-12 L. Donnie Smith <cwiid@abstrakraft.org> 19 22 * * streamlined wiimote filter … … 81 84 if ((dev_count = hci_inquiry(dev_id, timeout, max_inquiry, NULL, 82 85 &dev_list, IREQ_CACHE_FLUSH)) == -1) { 83 cwiid_err(NULL, " Error on bluetooth device inquiry");86 cwiid_err(NULL, "Bluetooth device inquiry error"); 84 87 err = 1; 85 88 goto CODA; … … 93 96 /* Open connection to Bluetooth Interface */ 94 97 if ((sock = hci_open_dev(dev_id)) == -1) { 95 cwiid_err(NULL, " Error opening Bluetooth interface");98 cwiid_err(NULL, "Bluetooth interface open error"); 96 99 err = 1; 97 100 goto CODA; … … 103 106 } 104 107 if ((*bdinfo = malloc(max_bdinfo * sizeof **bdinfo)) == NULL) { 105 cwiid_err(NULL, " Error mallocing bdinfo array");108 cwiid_err(NULL, "Memory allocation error (bdinfo array)"); 106 109 err = 1; 107 110 goto CODA; … … 122 125 if (hci_remote_name(sock, &dev_list[i].bdaddr, BT_NAME_LEN, 123 126 (*bdinfo)[bdinfo_count].name, 10000)) { 124 cwiid_err(NULL, " Error reading Bluetooth device name");127 cwiid_err(NULL, "Bluetooth name read error"); 125 128 err = 1; 126 129 goto CODA; … … 148 151 if ((*bdinfo = realloc(*bdinfo, bdinfo_count * sizeof **bdinfo)) 149 152 == NULL) { 150 cwiid_err(NULL, " Error reallocing bdinfo array");153 cwiid_err(NULL, "Memory reallocation error (bdinfo array)"); 151 154 err = 1; 152 155 goto CODA; trunk/libcwiid/command.c
r83 r101 16 16 * 17 17 * ChangeLog: 18 * 2007-04-24 L. Donnie Smith <cwiid@abstrakraft.org> 19 * * rewrite for API overhaul 20 * * added rw and beep functions from rw.c 21 * 18 22 * 2007-04-09 L. Donnie Smith <cwiid@abstrakraft.org> 19 23 * * renamed wiimote to libcwiid, renamed structures accordingly 24 * 25 * 2007-04-04 L. Donnie Smith <cwiid@abstrakraft.org> 26 * * updated cwiid_read and cwiid_write to trigger and detect rw_error 20 27 * 21 28 * 2007-03-14 L. Donnie Smith <cwiid@abstrakraft.org> 22 29 * * audited error checking (coda and error handler sections) 23 30 * * updated comments 31 * * cwiid_read - changed to obey decode flag only for register read 24 32 * 25 33 * 2007-03-06 L. Donnie Smith <cwiid@abstrakraft.org> … … 32 40 33 41 #include <stdint.h> 42 #include <time.h> 43 #include <pthread.h> 34 44 #include <unistd.h> 35 45 #include "cwiid_internal.h" 36 46 37 /* IR Sensitivity Block */38 unsigned char ir_block1[] = CLIFF_IR_BLOCK_1;39 unsigned char ir_block2[] = CLIFF_IR_BLOCK_2;40 41 struct write_seq ir_enable10_seq[] = {42 {WRITE_SEQ_RPT, RPT_IR_ENABLE1, (const void *)"\x04", 1, 0},43 {WRITE_SEQ_RPT, RPT_IR_ENABLE2, (const void *)"\x04", 1, 0},44 {WRITE_SEQ_MEM, 0xB00030, (const void *)"\x08", 1, CWIID_RW_REG},45 {WRITE_SEQ_MEM, 0xB00000, ir_block1, sizeof(ir_block1)-1, CWIID_RW_REG},46 {WRITE_SEQ_MEM, 0xB0001A, ir_block2, sizeof(ir_block2)-1, CWIID_RW_REG},47 {WRITE_SEQ_MEM, 0xB00033, (const void *)"\x01", 1, CWIID_RW_REG}48 };49 50 struct write_seq ir_enable12_seq[] = {51 {WRITE_SEQ_RPT, RPT_IR_ENABLE1, (const void *)"\x04", 1, 0},52 {WRITE_SEQ_RPT, RPT_IR_ENABLE2, (const void *)"\x04", 1, 0},53 {WRITE_SEQ_MEM, 0xB00030, (const void *)"\x08", 1, CWIID_RW_REG},54 {WRITE_SEQ_MEM, 0xB00000, ir_block1, sizeof(ir_block1)-1, CWIID_RW_REG},55 {WRITE_SEQ_MEM, 0xB0001A, ir_block2, sizeof(ir_block2)-1, CWIID_RW_REG},56 {WRITE_SEQ_MEM, 0xB00033, (const void *)"\x03", 1, CWIID_RW_REG}57 };58 59 struct write_seq ir_disable_seq[] = {60 {WRITE_SEQ_RPT, RPT_IR_ENABLE1, (const void *)"\x00", 1, 0},61 {WRITE_SEQ_RPT, RPT_IR_ENABLE2, (const void *)"\x00", 1, 0}62 };63 64 47 #define CMD_BUF_LEN 21 65 48 int cwiid_command(struct wiimote *wiimote, enum cwiid_command command, 66 uint8_t flags) {49 int flags) { 67 50 int ret = 0; 68 51 unsigned char buf[CMD_BUF_LEN]; 69 52 53 /* TODO: assumption: char assignments are atomic, no mutex lock needed */ 70 54 switch (command) { 71 55 case CWIID_CMD_STATUS: 72 56 buf[0] = 0; 73 57 if (send_report(wiimote, 0, RPT_STATUS_REQ, 1, buf)) { 74 cwiid_err(wiimote, " Error requesting status");58 cwiid_err(wiimote, "Status request error"); 75 59 ret = -1; 76 60 } 77 61 break; 78 62 case CWIID_CMD_LED: 79 wiimote->led_rumble_state = ((flags & 0x0F)<<4) | 80 (wiimote->led_rumble_state & 0x01); 81 buf[0]=wiimote->led_rumble_state; 63 wiimote->state.led = flags & 0x0F; 64 buf[0] = wiimote->state.led<<4 | wiimote->state.rumble; 82 65 if (send_report(wiimote, SEND_RPT_NO_RUMBLE, RPT_LED_RUMBLE, 1, buf)) { 83 cwiid_err(wiimote, " Error setting LEDs");66 cwiid_err(wiimote, "Report send error (led)"); 84 67 ret = -1; 85 68 } 86 69 break; 87 70 case CWIID_CMD_RUMBLE: 88 wiimote->led_rumble_state = (wiimote->led_rumble_state & 0xFE) | 89 (flags ? 1 : 0); 90 buf[0]=wiimote->led_rumble_state; 71 wiimote->state.rumble = flags ? 1 : 0; 72 buf[0] = wiimote->state.led<<4 | wiimote->state.rumble; 91 73 if (send_report(wiimote, SEND_RPT_NO_RUMBLE, RPT_LED_RUMBLE, 1, buf)) { 92 cwiid_err(wiimote, " Error setting rumble");74 cwiid_err(wiimote, "Report send error (rumble)"); 93 75 ret = -1; 94 76 } … … 98 80 break; 99 81 default: 100 cwiid_err(wiimote, "Unknown command");101 82 ret = -1; 102 83 break; … … 106 87 } 107 88 108 #define RPT_MODE_BUF_LEN 2 109 int update_rpt_mode(struct wiimote *wiimote, int8_t flags) 89 #define RPT_READ_REQ_LEN 6 90 int cwiid_read(struct wiimote *wiimote, uint8_t flags, uint32_t offset, 91 uint16_t len, void *data) 110 92 { 111 unsigned char buf[RPT_MODE_BUF_LEN]; 112 uint8_t rpt_mode; 113 struct write_seq *ir_enable_seq; 114 int seq_len; 93 unsigned char buf[RPT_READ_REQ_LEN]; 94 struct rw_mesg mesg; 95 unsigned char *cursor; 115 96 int ret = 0; 116 117 /* Lock wiimote access */ 118 if (pthread_mutex_lock(&wiimote->wiimote_mutex)) { 119 cwiid_err(wiimote, "Error locking wiimote_mutex"); 97 int i; 98 99 /* Compose read request packet */ 100 buf[0]=flags & (CWIID_RW_EEPROM | CWIID_RW_REG); 101 buf[1]=(unsigned char)((offset>>16) & 0xFF); 102 buf[2]=(unsigned char)((offset>>8) & 0xFF); 103 buf[3]=(unsigned char)(offset & 0xFF); 104 buf[4]=(unsigned char)((len>>8) & 0xFF); 105 buf[5]=(unsigned char)(len & 0xFF); 106 107 /* Lock wiimote rw access */ 108 if (pthread_mutex_lock(&wiimote->rw_mutex)) { 109 cwiid_err(wiimote, "Mutex lock error (rw_mutex)"); 110 return -1; 111 } 112 113 /* Setup read info */ 114 wiimote->rw_status = RW_READ; 115 116 /* TODO: Document: user is responsible for ensuring that read/write 117 * operations are not in flight while disconnecting. Nothing serious, 118 * just accesses to freed memory */ 119 /* Send read request packet */ 120 if (send_report(wiimote, 0, RPT_READ_REQ, RPT_READ_REQ_LEN, buf)) { 121 cwiid_err(wiimote, "Report send error (read)"); 120 122 ret = -1; 121 123 goto CODA; 122 124 } 123 125 124 /* Use -1 to update the reporting mode without changing flags */ 125 if (flags == -1) { 126 flags = wiimote->rpt_mode_flags; 127 } 128 129 /* Pick a report mode based on report flags */ 130 if ((flags & CWIID_RPT_EXT) && 131 ((wiimote->extension == CWIID_EXT_NUNCHUK) || 132 (wiimote->extension == CWIID_EXT_CLASSIC))) { 133 if ((flags & CWIID_RPT_IR) && 134 (flags & CWIID_RPT_ACC)) { 135 rpt_mode = RPT_BTN_ACC_IR10_EXT6; 136 ir_enable_seq = ir_enable10_seq; 137 seq_len = SEQ_LEN(ir_enable10_seq); 138 } 139 else if (flags & CWIID_RPT_IR) { 140 rpt_mode = RPT_BTN_IR10_EXT9; 141 ir_enable_seq = ir_enable10_seq; 142 seq_len = SEQ_LEN(ir_enable10_seq); 143 } 144 else if (flags & CWIID_RPT_ACC) { 145 rpt_mode = RPT_BTN_ACC_EXT16; 146 } 147 else if (flags & CWIID_RPT_BTN) { 148 rpt_mode = RPT_BTN_EXT8; 149 } 150 else { 151 rpt_mode = RPT_EXT21; 152 } 153 } 154 else { 155 if (flags & CWIID_RPT_IR) { 156 rpt_mode = RPT_BTN_ACC_IR12; 157 ir_enable_seq = ir_enable12_seq; 158 seq_len = SEQ_LEN(ir_enable12_seq); 159 } 160 else if (flags & CWIID_RPT_ACC) { 161 rpt_mode = RPT_BTN_ACC; 162 } 163 else { 164 rpt_mode = RPT_BTN; 165 } 166 } 167 168 /* Enable IR */ 169 /* TODO: only do this when necessary (record old IR mode) */ 170 if ((flags & CWIID_RPT_IR)) { 171 if (exec_write_seq(wiimote, seq_len, ir_enable_seq)) { 172 cwiid_err(wiimote, "Error on IR enable"); 173 ret = -1; 174 goto CODA; 175 } 176 } 177 /* Disable IR */ 178 else if ((wiimote->rpt_mode_flags & CWIID_RPT_IR) & 179 !(flags & CWIID_RPT_IR)) { 180 if (exec_write_seq(wiimote, SEQ_LEN(ir_disable_seq), 181 ir_disable_seq)) { 182 cwiid_err(wiimote, "Error on IR enable"); 183 ret = -1; 184 goto CODA; 185 } 186 } 187 188 /* Send SET_REPORT */ 189 buf[0]=0; 190 buf[1]=rpt_mode; 191 if (send_report(wiimote, 0, RPT_RPT_MODE, RPT_MODE_BUF_LEN, buf)) { 192 cwiid_err(wiimote, "Error setting report state"); 193 ret = -1; 194 goto CODA; 195 } 196 197 wiimote->rpt_mode_flags = flags; 126 /* TODO:Better sanity checks (offset) */ 127 /* Read packets */ 128 for (cursor = data; cursor - (unsigned char *)data < len; 129 cursor += mesg.len) { 130 if (full_read(wiimote->rw_pipe[0], &mesg, sizeof mesg)) { 131 cwiid_err(wiimote, "Pipe read error (rw pipe)"); 132 ret = -1; 133 goto CODA; 134 } 135 136 if (mesg.type == RW_CANCEL) { 137 ret = -1; 138 goto CODA; 139 } 140 else if (mesg.type != RW_READ) { 141 cwiid_err(wiimote, "Unexpected write message"); 142 ret = -1; 143 goto CODA; 144 } 145 146 if (mesg.error) { 147 cwiid_err(wiimote, "Wiimote read error"); 148 ret = -1; 149 goto CODA; 150 } 151 152 memcpy(cursor, &mesg.data, mesg.len); 153 } 198 154 199 155 CODA: 200 /* Unlock cwiid_mutex */ 201 if (pthread_mutex_unlock(&wiimote->wiimote_mutex)) { 202 cwiid_err(wiimote, "Error unlocking wiimote_mutex: deadlock warning"); 156 /* Clear rw_status */ 157 wiimote->rw_status = RW_IDLE; 158 159 /* Unlock rw_mutex */ 160 if (pthread_mutex_unlock(&wiimote->rw_mutex)) { 161 cwiid_err(wiimote, "Mutex unlock error (rw_mutex) - deadlock warning"); 162 } 163 164 /* Decode (only for register reads) */ 165 if ((ret == 0) && (flags & CWIID_RW_DECODE) && (flags & CWIID_RW_REG)) { 166 for (i=0; i < len; i++) { 167 ((unsigned char *)data)[i] = DECODE(((unsigned char *)data)[i]); 168 } 203 169 } 204 170 … … 206 172 } 207 173 174 #define RPT_WRITE_LEN 21 175 int cwiid_write(struct wiimote *wiimote, uint8_t flags, uint32_t offset, 176 uint16_t len, const void *data) 177 { 178 unsigned char buf[RPT_WRITE_LEN]; 179 uint16_t sent=0; 180 struct rw_mesg mesg; 181 int ret = 0; 182 183 /* Compose write packet header */ 184 buf[0]=flags; 185 186 /* Lock wiimote rw access */ 187 if (pthread_mutex_lock(&wiimote->rw_mutex)) { 188 cwiid_err(wiimote, "Mutex lock error (rw mutex)"); 189 return -1; 190 } 191 192 /* Send packets */ 193 wiimote->rw_status = RW_WRITE; 194 while (sent<len) { 195 /* Compose write packet */ 196 buf[1]=(unsigned char)(((offset+sent)>>16) & 0xFF); 197 buf[2]=(unsigned char)(((offset+sent)>>8) & 0xFF); 198 buf[3]=(unsigned char)((offset+sent) & 0xFF); 199 if (len-sent >= 0x10) { 200 buf[4]=(unsigned char)0x10; 201 } 202 else { 203 buf[4]=(unsigned char)(len-sent); 204 } 205 memcpy(buf+5, data+sent, buf[4]); 206 207 if (send_report(wiimote, 0, RPT_WRITE, RPT_WRITE_LEN, buf)) { 208 cwiid_err(wiimote, "Report send error (write)"); 209 ret = -1; 210 goto CODA; 211 } 212 213 /* Read packets from pipe */ 214 if (read(wiimote->rw_pipe[0], &mesg, sizeof mesg) != sizeof mesg) { 215 cwiid_err(wiimote, "Pipe read error (rw pipe)"); 216 ret = -1; 217 goto CODA; 218 } 219 220 if (mesg.type == RW_CANCEL) { 221 ret = -1; 222 goto CODA; 223 } 224 else if (mesg.type != RW_WRITE) { 225 cwiid_err(wiimote, "Unexpected read message"); 226 ret = -1; 227 goto CODA; 228 } 229 230 if (mesg.error) { 231 cwiid_err(wiimote, "Wiimote write error"); 232 ret = -1; 233 goto CODA; 234 }; 235 236 sent+=buf[4]; 237 } 238 239 CODA: 240 /* Clear rw_status */ 241 wiimote->rw_status = RW_IDLE; 242 243 /* Unlock rw_mutex */ 244 if (pthread_mutex_unlock(&wiimote->rw_mutex)) { 245 cwiid_err(wiimote, "Mutex unlock error (rw_mutex) - deadlock warning"); 246 } 247 248 return ret; 249 } 250 251 252 struct write_seq speaker_enable_seq[] = { 253 {WRITE_SEQ_RPT, RPT_SPEAKER_ENABLE, (const void *)"\x04", 1, 0}, 254 {WRITE_SEQ_RPT, RPT_SPEAKER_MUTE, (const void *)"\x04", 1, 0}, 255 {WRITE_SEQ_MEM, 0xA20009, (const void *)"\x01", 1, CWIID_RW_REG}, 256 {WRITE_SEQ_MEM, 0xA20001, (const void *)"\x08", 1, CWIID_RW_REG}, 257 {WRITE_SEQ_MEM, 0xA20001, (const void *)"\x00\x00\x00\x0C\x40\x00\x00", 258 7, CWIID_RW_REG}, 259 {WRITE_SEQ_MEM, 0xA20008, (const void *)"\x01", 1, CWIID_RW_REG}, 260 {WRITE_SEQ_RPT, RPT_SPEAKER_MUTE, (const void *)"\x00", 1, 0} 261 }; 262 263 struct write_seq speaker_disable_seq[] = { 264 {WRITE_SEQ_RPT, RPT_SPEAKER_MUTE, (const void *)"\x04", 1, 0}, 265 {WRITE_SEQ_RPT, RPT_SPEAKER_ENABLE, (const void *)"\x00", 1, 0} 266 }; 267 268 #define SOUND_BUF_LEN 21 269 int cwiid_beep(cwiid_wiimote_t *wiimote) 270 { 271 /* unsigned char buf[SOUND_BUF_LEN] = { 0xA0, 0xCC, 0x33, 0xCC, 0x33, 272 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 273 0xCC, 0x33, 0xCC, 0x33}; */ 274 unsigned char buf[SOUND_BUF_LEN] = { 0xA0, 0xC3, 0xC3, 0xC3, 0xC3, 275 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 276 0xC3, 0xC3, 0xC3, 0xC3}; 277 int i; 278 int ret = 0; 279 pthread_mutex_t timer_mutex = PTHREAD_MUTEX_INITIALIZER; 280 pthread_cond_t timer_cond = PTHREAD_COND_INITIALIZER; 281 struct timespec t; 282 283 if (exec_write_seq(wiimote, SEQ_LEN(speaker_enable_seq), 284 speaker_enable_seq)) { 285 cwiid_err(wiimote, "Speaker enable error"); 286 ret = -1; 287 } 288 289 pthread_mutex_lock(&timer_mutex); 290 291 for (i=0; i<100; i++) { 292 clock_gettime(CLOCK_REALTIME, &t); 293 t.tv_nsec += 10204081; 294 /* t.tv_nsec += 7000000; */ 295 if (send_report(wiimote, 0, RPT_SPEAKER_DATA, SOUND_BUF_LEN, buf)) { 296 printf("%d\n", i); 297 cwiid_err(wiimote, "Report send error (speaker data)"); 298 ret = -1; 299 break; 300 } 301 /* TODO: I should be shot for this, but hey, it works. 302 * longterm - find a better wait */ 303 pthread_cond_timedwait(&timer_cond, &timer_mutex, &t); 304 } 305 306 pthread_mutex_unlock(&timer_mutex); 307 308 if (exec_write_seq(wiimote, SEQ_LEN(speaker_disable_seq), 309 speaker_disable_seq)) { 310 cwiid_err(wiimote, "Speaker disable error"); 311 ret = -1; 312 } 313 314 return ret; 315 } trunk/libcwiid/connect.c
r83 r101 16 16 * 17 17 * ChangeLog: 18 * 2007-04-24 L. Donnie Smith <cwiid@abstrakraft.org> 19 * * rewrite for API overhaul 20 * 18 21 * 2007-04-09 L. Donnie Smith <cwiid@abstrakraft.org> 19 22 * * renamed wiimote to libcwiid, renamed structures accordingly … … 38 41 */ 39 42 40 #include <pthread.h>41 43 #include <stdlib.h> 42 44 #include <string.h> 45 #include <fcntl.h> 46 #include <pthread.h> 43 47 #include <sys/types.h> 44 48 #include <sys/socket.h> … … 47 51 #include <bluetooth/l2cap.h> 48 52 #include "cwiid_internal.h" 49 #include "queue.h"50 53 51 54 pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER; 52 55 static int wiimote_id = 0; 53 56 54 cwiid_wiimote_t *cwiid_connect(bdaddr_t *bdaddr, 55 cwiid_mesg_callback_t *mesg_callback, int *id) 57 cwiid_wiimote_t *cwiid_connect(bdaddr_t *bdaddr, int flags) 56 58 { 57 59 struct wiimote *wiimote = NULL; 58 struct sockaddr_l2 ctl_remote_addr, int_remote_addr; 60 struct sockaddr_l2 remote_addr; 61 char mesg_pipe_init = 0, status_pipe_init = 0, error_pipe_init = 0, 62 rw_pipe_init = 0, state_mutex_init = 0, rw_mutex_init = 0, 63 rpt_mutex_init = 0, router_thread_init = 0, status_thread_init = 0; 64 void *pthread_ret; 59 65 60 66 /* Allocate wiimote */ 61 67 if ((wiimote = malloc(sizeof *wiimote)) == NULL) { 62 cwiid_err(NULL, "Error allocating cwiid_wiimote"); 63 goto ERR_HND; 64 } 65 66 /* Set wiimote members for proper error detection */ 67 wiimote->ctl_socket = -1; 68 wiimote->int_socket = -1; 69 wiimote->dispatch_queue = NULL; 68 cwiid_err(NULL, "Memory allocation error (cwiid_wiimote_t)"); 69 goto ERR_HND; 70 } 71 72 /* set flags */ 73 wiimote->flags = flags; 74 75 /* For error detection */ 76 wiimote->ctl_socket = wiimote->int_socket = -1; 70 77 71 78 /* Global Lock, Store and Increment wiimote_id */ 72 79 if (pthread_mutex_lock(&global_mutex)) { 73 cwiid_err(NULL, " Error locking global lock");80 cwiid_err(NULL, "Mutex lock error (global mutex)"); 74 81 goto ERR_HND; 75 82 } 76 83 wiimote->id = wiimote_id++; 77 84 if (pthread_mutex_unlock(&global_mutex)) { 78 cwiid_err(wiimote, "Error unlocking global lock"); 79 goto ERR_HND; 80 } 81 /* Return the id in a pointer, if desired */ 82 if (id) { 83 *id = wiimote->id; 84 } 85 86 /* Store mesg callback */ 87 wiimote->mesg_callback = mesg_callback; 85 cwiid_err(wiimote, "Mutex unlock error (global mutex) - " 86 "deadlock warning"); 87 goto ERR_HND; 88 } 88 89 89 90 /* If BDADDR_ANY is given, find available wiimote */ … … 94 95 } 95 96 96 /* Clear address structs, fill address family, address, and ports */ 97 memset(&ctl_remote_addr, 0, sizeof(ctl_remote_addr)); 98 ctl_remote_addr.l2_family = AF_BLUETOOTH; 99 ctl_remote_addr.l2_bdaddr = *bdaddr; 100 ctl_remote_addr.l2_psm = htobs(CTL_PSM); 101 102 memset(&int_remote_addr, 0, sizeof(int_remote_addr)); 103 int_remote_addr.l2_family = AF_BLUETOOTH; 104 int_remote_addr.l2_bdaddr = *bdaddr; 105 int_remote_addr.l2_psm = htobs(INT_PSM); 106 107 /* Get Bluetooth Sockets */ 97 /* Connect to Wiimote */ 98 /* Control Channel */ 99 memset(&remote_addr, 0, sizeof remote_addr); 100 remote_addr.l2_family = AF_BLUETOOTH; 101 remote_addr.l2_bdaddr = *bdaddr; 102 remote_addr.l2_psm = htobs(CTL_PSM); 108 103 if ((wiimote->ctl_socket = 109 104 socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1) { 110 cwiid_err(wiimote, "Error opening control socket"); 111 goto ERR_HND; 112 } 105 cwiid_err(wiimote, "Socket creation error (control socket)"); 106 goto ERR_HND; 107 } 108 if (connect(wiimote->ctl_socket, (struct sockaddr *)&remote_addr, 109 sizeof remote_addr)) { 110 cwiid_err(wiimote, "Socket connect error (control channel)"); 111 goto ERR_HND; 112 } 113 114 /* Interrupt Channel */ 115 remote_addr.l2_psm = htobs(INT_PSM); 113 116 if ((wiimote->int_socket = 114 117 socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1) { 115 cwiid_err(wiimote, "Error opening interrupt socket"); 116 goto ERR_HND; 117 } 118 119 /* Connect to Wiimote */ 120 if (connect(wiimote->ctl_socket, (struct sockaddr *)&ctl_remote_addr, 121 sizeof(ctl_remote_addr))) { 122 cwiid_err(wiimote, "Error opening control channel"); 123 goto ERR_HND; 124 } 125 if (connect(wiimote->int_socket, (struct sockaddr *)&int_remote_addr, 126 sizeof(int_remote_addr))) { 127 cwiid_err(wiimote, "Error opening interrupt channel"); 128 goto ERR_HND; 129 } 130 131 /* Create Dispatch Queue */ 132 if ((wiimote->dispatch_queue = queue_new()) == NULL) { 133 cwiid_err(wiimote, "Error creating dispatch queue"); 134 goto ERR_HND; 135 } 136 137 /* TODO: backout logic (pthread_*_destroy) */ 138 /* Mutex and cond init */ 139 if (pthread_mutex_init(&wiimote->wiimote_mutex, NULL) || 140 pthread_mutex_init(&wiimote->rw_mutex, NULL) || 141 pthread_cond_init(&wiimote->rw_cond, NULL) || 142 pthread_mutex_init(&wiimote->rw_cond_mutex, NULL)) { 143 cwiid_err(wiimote, "Error initializing synchronization variables"); 144 goto ERR_HND; 145 } 146 147 /* Set rw_status before interrupt thread */ 148 wiimote->rw_status = RW_NONE; 149 wiimote->rw_error = 0; 118 cwiid_err(wiimote, "Socket creation error (interrupt socket)"); 119 goto ERR_HND; 120 } 121 if (connect(wiimote->int_socket, (struct sockaddr *)&remote_addr, 122 sizeof remote_addr)) { 123 cwiid_err(wiimote, "Socket connect error (interrupt channel)"); 124 goto ERR_HND; 125 } 126 127 /* Create pipes */ 128 if (pipe(wiimote->mesg_pipe)) { 129 cwiid_err(wiimote, "Pipe creation error (mesg pipe)"); 130 goto ERR_HND; 131 } 132 mesg_pipe_init = 1; 133 if (pipe(wiimote->status_pipe)) { 134 cwiid_err(wiimote, "Pipe creation error (status pipe)"); 135 goto ERR_HND; 136 } 137 status_pipe_init = 1; 138 if (pipe(wiimote->error_pipe)) { 139 cwiid_err(wiimote, "Pipe creation error (error pipe)"); 140 goto ERR_HND; 141 } 142 error_pipe_init = 1; 143 if (pipe(wiimote->rw_pipe)) { 144 cwiid_err(wiimote, "Pipe creation error (rw pipe)"); 145 goto ERR_HND; 146 } 147 rw_pipe_init = 1; 148 149 /* Setup blocking */ 150 if (fcntl(wiimote->mesg_pipe[1], F_SETFL, O_NONBLOCK)) { 151 cwiid_err(wiimote, "File control error (mesg write pipe)"); 152 goto ERR_HND; 153 } 154 if (wiimote->flags & CWIID_FLAG_NONBLOCK) { 155 if (fcntl(wiimote->mesg_pipe[0], F_SETFL, O_NONBLOCK)) { 156 cwiid_err(wiimote, "File control error (mesg read pipe)"); 157 goto ERR_HND; 158 } 159 } 160 161 /* Init mutexes */ 162 if (pthread_mutex_init(&wiimote->state_mutex, NULL)) { 163 cwiid_err(wiimote, "Mutex initialization error (state mutex)"); 164 goto ERR_HND; 165 } 166 state_mutex_init = 1; 167 if (pthread_mutex_init(&wiimote->rw_mutex, NULL)) { 168 cwiid_err(wiimote, "Mutex initialization error (rw mutex)"); 169 goto ERR_HND; 170 } 171 rw_mutex_init = 1; 172 if (pthread_mutex_init(&wiimote->rpt_mutex, NULL)) { 173 cwiid_err(wiimote, "Mutex initialization error (rpt mutex)"); 174 goto ERR_HND; 175 } 176 rpt_mutex_init = 1; 177 178 /* Set rw_status before starting router thread */ 179 wiimote->rw_status = RW_IDLE; 150 180 151 181 /* Launch interrupt channel listener and dispatch threads */ 152 if (pthread_create(&wiimote-> int_listen_thread, NULL,153 (void *(*)(void *))& int_listen, wiimote)) {154 cwiid_err(wiimote, " Error creating interrupt channel listener thread");155 goto ERR_HND; 156 } 157 if (pthread_create(&wiimote->dispatch_thread, NULL,158 (void *(*)(void *))&dispatch, wiimote)) {159 pthread_cancel(wiimote->int_listen_thread);160 pthread_join(wiimote->int_listen_thread, NULL);161 cwiid_err(wiimote, "Error creating dispatch thread");162 goto ERR_HND;163 }182 if (pthread_create(&wiimote->router_thread, NULL, 183 (void *(*)(void *))&router_thread, wiimote)) { 184 cwiid_err(wiimote, "Thread creation error (router thread)"); 185 goto ERR_HND; 186 } 187 router_thread_init = 1; 188 if (pthread_create(&wiimote->status_thread, NULL, 189 (void *(*)(void *))&status_thread, wiimote)) { 190 cwiid_err(wiimote, "Thread creation error (status thread)"); 191 goto ERR_HND; 192 } 193 status_thread_init = 1; 164 194 165 195 /* Success! Update state */ 166 wiimote->buttons = 0; 167 wiimote->rpt_mode_flags = 0; 168 wiimote->extension = CWIID_EXT_NONE; 169 wiimote->led_rumble_state = 0; 196 memset(&wiimote->state, 0, sizeof wiimote->state); 197 wiimote->mesg_callback = NULL; 170 198 cwiid_command(wiimote, CWIID_CMD_LED, 0); 171 199 cwiid_command(wiimote, CWIID_CMD_STATUS, 0); … … 175 203 ERR_HND: 176 204 if (wiimote) { 177 if (wiimote->dispatch_queue) { 178 queue_free(wiimote->dispatch_queue, 179 (free_func_t *)free_mesg_array); 180 } 205 /* Close threads */ 206 if (router_thread_init) { 207 pthread_cancel(wiimote->router_thread); 208 if (pthread_join(wiimote->router_thread, &pthread_ret)) { 209 cwiid_err(wiimote, "Thread join error (router thread)"); 210 } 211 else if (!((pthread_ret == PTHREAD_CANCELED) && 212 (pthread_ret == NULL))) { 213 cwiid_err(wiimote, "Bad return value from router thread"); 214 } 215 } 216 217 if (status_thread_init) { 218 pthread_cancel(wiimote->status_thread); 219 if (pthread_join(wiimote->status_thread, &pthread_ret)) { 220 cwiid_err(wiimote, "Thread join error (status thread)"); 221 } 222 else if (!((pthread_ret == PTHREAD_CANCELED) && (pthread_ret == NULL))) { 223 cwiid_err(wiimote, "Bad return value from status thread"); 224 } 225 } 226 227 /* Close Sockets */ 181 228 if (wiimote->int_socket != -1) { 182 229 if (close(wiimote->int_socket)) { 183 cwiid_err(wiimote, " Error closing interrupt channel");230 cwiid_err(wiimote, "Socket close error (interrupt channel)"); 184 231 } 185 232 } 186 233 if (wiimote->ctl_socket != -1) { 187 234 if (close(wiimote->ctl_socket)) { 188 cwiid_err(wiimote, "Error closing control channel"); 235 cwiid_err(wiimote, "Socket close error (control channel)"); 236 } 237 } 238 /* Close Pipes */ 239 if (mesg_pipe_init) { 240 if (close(wiimote->mesg_pipe[0]) || close(wiimote->mesg_pipe[1])) { 241 cwiid_err(wiimote, "Pipe close error (mesg pipe)"); 242 } 243 } 244 if (status_pipe_init) { 245 if (close(wiimote->status_pipe[0]) || 246 close(wiimote->status_pipe[1])) { 247 cwiid_err(wiimote, "Pipe close error (status pipe)"); 248 } 249 } 250 if (error_pipe_init) { 251 if (close(wiimote->error_pipe[0]) || 252 close(wiimote->error_pipe[1])) { 253 cwiid_err(wiimote, "Pipe close error (error pipe)"); 254 } 255 } 256 if (rw_pipe_init) { 257 if (close(wiimote->rw_pipe[0]) || close(wiimote->rw_pipe[1])) { 258 cwiid_err(wiimote, "Pipe close error (rw pipe)"); 259 } 260 } 261 /* Destroy Mutexes */ 262 if (state_mutex_init) { 263 if (pthread_mutex_destroy(&wiimote->state_mutex)) { 264 cwiid_err(wiimote, "Mutex destroy error (state mutex)"); 265 } 266 } 267 if (rw_mutex_init) { 268 if (pthread_mutex_destroy(&wiimote->rw_mutex)) { 269 cwiid_err(wiimote, "Mutex destroy error (rw mutex)"); 270 } 271 } 272 if (rpt_mutex_init) { 273 if (pthread_mutex_destroy(&wiimote->rpt_mutex)) { 274 cwiid_err(wiimote, "Mutex destroy error (rpt mutex)"); 189 275 } 190 276 } … … 198 284 void *pthread_ret; 199 285 200 /* Cancel and join int_thread */ 201 if (pthread_cancel(wiimote->int_listen_thread)) { 202 /* int could exit on it's own, so we don't care */ 203 /* cwiid_err(wiimote, "Error canceling int_listen_thread"); */ 204 } 205 else { 206 if (pthread_join(wiimote->int_listen_thread, &pthread_ret)) { 207 cwiid_err(wiimote, "Error joining int_listen_thread"); 208 } 209 else if (pthread_ret != PTHREAD_CANCELED) { 210 &
