root/wiimote/connect.c @ d2323a579f283ed7393c20b762697766d2d01e1f

Revision d2323a579f283ed7393c20b762697766d2d01e1f, 7.5 KB (checked in by dsmith <dsmith@…>, 6 years ago)

Added struct wiimote info and info retrieval functions

git-svn-id: http://abstrakraft.org/cwiid/svn/trunk@47 918edb2d-ff29-0410-9de2-eb38e7f22bc7

  • Property mode set to 100644
Line 
1/* Copyright (C) 2007 L. Donnie Smith <cwiid@abstrakraft.org>
2 *
3 *  This program is free software; you can redistribute it and/or modify
4 *  it under the terms of the GNU General Public License as published by
5 *  the Free Software Foundation; either version 2 of the License, or
6 *  (at your option) any later version.
7 *
8 *  This program is distributed in the hope that it will be useful,
9 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 *  GNU General Public License for more details.
12 *
13 *  You should have received a copy of the GNU General Public License
14 *  along with this program; if not, write to the Free Software
15 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
16 *
17 *  ChangeLog:
18 *  04/01/2007: L. Donnie Smith <cwiid@abstrakraft.org>
19 *  * changed wiimote_findfirst to wiimote_find_wiimote
20 *
21 *  03/14/2007: L. Donnie Smith <cwiid@abstrakraft.org>
22 *  * changed memcpy to bacmp
23 *  * audited error checking (coda and error handler sections)
24 *  * updated comments
25 *
26 *  03/06/2007: L. Donnie Smith <cwiid@abstrakraft.org>
27 *  * added wiimote parameter to wiimote_err calls
28 *
29 *  03/01/2007: L. Donnie Smith <cwiid@abstrakraft.org>
30 *  * Initial ChangeLog
31 */
32
33#include <pthread.h>
34#include <stdlib.h>
35#include <string.h>
36#include <sys/types.h>
37#include <sys/socket.h>
38#include <unistd.h>
39#include <bluetooth/bluetooth.h>
40#include <bluetooth/l2cap.h>
41#include "wiimote_internal.h"
42#include "queue.h"
43
44pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
45static int wiimote_id = 0;
46
47wiimote_t *wiimote_connect(bdaddr_t bdaddr,
48                           wiimote_mesg_callback_t *mesg_callback, int *id)
49{
50        struct wiimote *wiimote = NULL;
51        struct sockaddr_l2 ctl_remote_addr, int_remote_addr;
52
53        /* Allocate wiimote */
54        if ((wiimote = malloc(sizeof *wiimote)) == NULL) {
55                wiimote_err(NULL, "Error allocating wiimote");
56                goto ERR_HND;
57        }
58
59        /* Set wiimote members for proper error detection */
60        wiimote->ctl_socket = -1;
61        wiimote->int_socket = -1;
62        wiimote->dispatch_queue = NULL;
63
64        /* Global Lock, Store and Increment wiimote_id */
65        if (pthread_mutex_lock(&global_mutex)) {
66                wiimote_err(NULL, "Error locking global lock");
67                goto ERR_HND;
68        }
69        wiimote->id = wiimote_id++;
70        if (pthread_mutex_unlock(&global_mutex)) {
71                wiimote_err(wiimote, "Error unlocking global lock");
72                goto ERR_HND;
73        }
74        /* Return the id in a pointer, if desired */
75        if (id) {
76                *id = wiimote->id;
77        }
78
79        /* Store mesg callback */
80        wiimote->mesg_callback = mesg_callback;
81
82        /* If BDADDR_ANY is given, find available wiimote */
83        if (bacmp(&bdaddr, BDADDR_ANY) == 0) {
84                if (wiimote_find_wiimote(&bdaddr, 2)) {
85                        /* TODO: wiimote functions should print their own errors */
86                        wiimote_err(wiimote, "Unable to find wiimote");
87                        goto ERR_HND;
88                }
89        }
90
91        /* Clear address structs, fill address family, address, and ports */
92        memset(&ctl_remote_addr, 0, sizeof(ctl_remote_addr));
93        ctl_remote_addr.l2_family = AF_BLUETOOTH;
94        ctl_remote_addr.l2_bdaddr = bdaddr;
95        ctl_remote_addr.l2_psm = htobs(CTL_PSM);
96
97        memset(&int_remote_addr, 0, sizeof(int_remote_addr));
98        int_remote_addr.l2_family = AF_BLUETOOTH;
99        int_remote_addr.l2_bdaddr = bdaddr;
100        int_remote_addr.l2_psm = htobs(INT_PSM);
101
102        /* Get Bluetooth Sockets */
103        if ((wiimote->ctl_socket =
104          socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1) {
105                wiimote_err(wiimote, "Error opening control socket");
106                goto ERR_HND;
107        }
108        if ((wiimote->int_socket =
109          socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1) {
110                wiimote_err(wiimote, "Error opening interrupt socket");
111                goto ERR_HND;
112        }
113
114        /* Connect to Wiimote */
115        if (connect(wiimote->ctl_socket, (struct sockaddr *)&ctl_remote_addr,
116                        sizeof(ctl_remote_addr))) {
117                wiimote_err(wiimote, "Error opening control channel");
118                goto ERR_HND;
119        }
120        if (connect(wiimote->int_socket, (struct sockaddr *)&int_remote_addr,
121                        sizeof(int_remote_addr))) {
122                wiimote_err(wiimote, "Error opening interrupt channel");
123                goto ERR_HND;
124        }
125
126        /* Create Dispatch Queue */
127        if ((wiimote->dispatch_queue = queue_new()) == NULL) {
128                wiimote_err(wiimote, "Error creating dispatch queue");
129                goto ERR_HND;
130        }
131
132        /* TODO: backout logic (pthread_*_destroy) */
133        /* Mutex and cond init */
134        if (pthread_mutex_init(&wiimote->wiimote_mutex, NULL) ||
135          pthread_mutex_init(&wiimote->rw_mutex, NULL) ||
136          pthread_cond_init(&wiimote->rw_cond, NULL) ||
137          pthread_mutex_init(&wiimote->rw_cond_mutex, NULL)) {
138                wiimote_err(wiimote,
139                            "Error initializing synchronization variables");
140                goto ERR_HND;
141        }
142
143        /* Set rw_status before interrupt thread */
144        wiimote->rw_status = RW_NONE;
145
146        /* Launch interrupt channel listener and dispatch threads */
147        if (pthread_create(&wiimote->int_listen_thread, NULL,
148                           (void *(*)(void *))&int_listen, wiimote)) {
149                wiimote_err(wiimote,
150                            "Error creating interrupt channel listener thread");
151                goto ERR_HND;
152        }
153        if (pthread_create(&wiimote->dispatch_thread, NULL,
154                           (void *(*)(void *))&dispatch, wiimote)) {
155                pthread_cancel(wiimote->int_listen_thread);
156                pthread_join(wiimote->int_listen_thread, NULL);
157                wiimote_err(wiimote, "Error creating dispatch thread");
158                goto ERR_HND;
159        }
160
161        /* Success!  Update state */
162        wiimote->buttons = 0;
163        wiimote->rpt_mode_flags = 0;
164        wiimote->extension = WIIMOTE_EXT_NONE;
165        wiimote->led_rumble_state = 0;
166        wiimote_command(wiimote, WIIMOTE_CMD_LED, 0);
167        wiimote_command(wiimote, WIIMOTE_CMD_STATUS, 0);
168
169        return wiimote;
170
171ERR_HND:
172        if (wiimote) {
173                if (wiimote->dispatch_queue) {
174                        queue_free(wiimote->dispatch_queue,
175                                   (free_func_t *)free_mesg_array);
176                }
177                if (wiimote->int_socket != -1) {
178                        if (close(wiimote->int_socket)) {
179                                wiimote_err(wiimote, "Error closing interrupt channel");
180                        }
181                }
182                if (wiimote->ctl_socket != -1) {
183                        if (close(wiimote->ctl_socket)) {
184                                wiimote_err(wiimote, "Error closing control channel");
185                        }
186                }
187                free(wiimote);
188        }
189        return NULL;
190}
191
192int wiimote_disconnect(struct wiimote *wiimote)
193{
194        void *pthread_ret;
195
196        /* Cancel and join int_thread */
197        if (pthread_cancel(wiimote->int_listen_thread)) {
198                wiimote_err(wiimote, "Error canceling int_listen_thread");
199        }
200        else {
201                if (pthread_join(wiimote->int_listen_thread, &pthread_ret)) {
202                        wiimote_err(wiimote, "Error joining int_listen_thread");
203                }
204                else if (pthread_ret != PTHREAD_CANCELED) {
205                        wiimote_err(wiimote,
206                                    "Invalid return value from int_listen_thread");
207                }
208        }
209        /* TODO: cancel RW operations if they are in progress */
210        /* Cancel and detach dispatch_thread */
211        /* We detach to decouple dispatch (which runs the callback) from wiimote
212         * code - specifically, a race condition exists for gtk apps */
213        if (pthread_cancel(wiimote->dispatch_thread)) {
214                wiimote_err(wiimote, "Error canceling dispatch_thread");
215        }
216        if (pthread_detach(wiimote->dispatch_thread)) {
217                wiimote_err(wiimote, "Error detaching dispatch_thread");
218        }
219
220        /* Close sockets */
221        if (close(wiimote->int_socket)) {
222                wiimote_err(wiimote, "Error closing interrupt channel");
223        }
224        if (close(wiimote->ctl_socket)) {
225                wiimote_err(wiimote, "Error closing control channel");
226        }
227
228        /* Destroy sync variables */
229        if (pthread_mutex_destroy(&wiimote->wiimote_mutex)) {
230                wiimote_err(wiimote, "Error destroying wiimote_mutex");
231        }
232        if (pthread_mutex_destroy(&wiimote->rw_mutex)) {
233                wiimote_err(wiimote, "Error destroying rw_mutex");
234        }
235        if (pthread_cond_destroy(&wiimote->rw_cond)) {
236                wiimote_err(wiimote, "Error destroying rw_cond");
237        }
238        if (pthread_mutex_destroy(&wiimote->rw_cond_mutex)) {
239                wiimote_err(wiimote, "Error destroying rw_cond_mutex");
240        }
241
242        free(wiimote);
243
244        return 0;
245}
246
Note: See TracBrowser for help on using the browser.