Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/wiimote/src/external/wiicpp/wiic/io_nix.c @ 10422

Last change on this file since 10422 was 9830, checked in by smerkli, 11 years ago

Fixed the ugly bluetooth hack into one that's a little less ugly:
now the only place the path has to be specified is FindBluetooth.cmake.
Kudos to reto for pointing me in the right direction.

  • Property svn:executable set to *
File size: 8.5 KB
Line 
1/*
2 *    io_nix.c
3 *
4 *        This file is part of WiiC, written by:
5 *              Gabriele Randelli
6 *              Email: randelli@dis.uniroma1.it
7 *
8 *    Copyright 2010
9 *             
10 *        This file is based on Wiiuse, written By:
11 *              Michael Laforest        < para >
12 *              Email: < thepara (--AT--) g m a i l [--DOT--] com >
13 *
14 *        Copyright 2006-2007
15 *
16 *    This program is free software; you can redistribute it and/or modify
17 *    it under the terms of the GNU General Public License as published by
18 *    the Free Software Foundation; either version 3 of the License, or
19 *    (at your option) any later version.
20 *
21 *    This program is distributed in the hope that it will be useful,
22 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
23 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 *    GNU General Public License for more details.
25 *
26 *    You should have received a copy of the GNU General Public License
27 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
28 *
29 *        $Header$
30 */
31
32/**
33 *      @file
34 *      @brief Handles device I/O for *nix.
35 */
36
37#ifndef __APPLE__
38
39#include <stdio.h>
40#include <stdlib.h>
41#include <unistd.h>
42
43#include <bluetooth/bluetooth.h>
44#include <bluetooth/hci.h>
45#include <bluetooth/hci_lib.h>
46#include <bluetooth/l2cap.h>
47
48#include "definitions.h"
49#include "wiic_internal.h"
50#include "io.h"
51
52/**
53 *      @brief Find a wiimote or wiimotes.
54 *
55 *      @param wm                       An array of wiimote_t structures.
56 *      @param max_wiimotes     The number of wiimote structures in \a wm.
57 *      @param timeout          The number of seconds before the search times out.
58 *
59 *      @return The number of wiimotes found.
60 *
61 *      @see wiimote_connect()
62 *
63 *      This function will only look for wiimote devices.                                               \n
64 *      When a device is found the address in the structures will be set.               \n
65 *      You can then call wiimote_connect() to connect to the found                             \n
66 *      devices.
67 */
68int wiic_find(struct wiimote_t** wm, int max_wiimotes, int timeout) {
69        int device_id;
70        int device_sock;
71        int found_devices;
72        int found_wiimotes;
73
74        /* reset all wiimote bluetooth device addresses */
75        for (found_wiimotes = 0; found_wiimotes < max_wiimotes; ++found_wiimotes)
76                wm[found_wiimotes]->bdaddr = *BDADDR_ANY;
77        found_wiimotes = 0;
78
79        /* get the id of the first bluetooth device. */
80        device_id = hci_get_route(NULL);
81        if (device_id < 0) {
82                perror("hci_get_route");
83                return 0;
84        }
85
86        /* create a socket to the device */
87        device_sock = hci_open_dev(device_id);
88        if (device_sock < 0) {
89                perror("hci_open_dev");
90                return 0;
91        }
92
93        inquiry_info scan_info_arr[128];
94        inquiry_info* scan_info = scan_info_arr;
95        memset(&scan_info_arr, 0, sizeof(scan_info_arr));
96
97        /* scan for bluetooth devices for 'timeout' seconds */
98        if(timeout)
99                found_devices = hci_inquiry(device_id, timeout, 128, NULL, &scan_info, IREQ_CACHE_FLUSH);
100        else {
101                while(!(found_devices = hci_inquiry(device_id, 5, 128, NULL, &scan_info, IREQ_CACHE_FLUSH))) ; // Unlimited inquiry
102        }
103               
104        if (found_devices < 0) {
105                perror("hci_inquiry");
106                return 0;
107        }
108
109        WIIC_INFO("Found %i bluetooth device(s).", found_devices);
110
111        int i = 0;
112
113        /* display discovered devices */
114        for (; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i) {
115                if ((scan_info[i].dev_class[0] == WM_DEV_CLASS_0) &&
116                        (scan_info[i].dev_class[1] == WM_DEV_CLASS_1) &&
117                        (scan_info[i].dev_class[2] == WM_DEV_CLASS_2))
118                {
119                        /* found a device */
120                        ba2str(&scan_info[i].bdaddr, wm[found_wiimotes]->bdaddr_str);
121
122                        WIIC_INFO("Found wiimote (%s) [id %i].", wm[found_wiimotes]->bdaddr_str, wm[found_wiimotes]->unid);
123
124                        wm[found_wiimotes]->bdaddr = scan_info[i].bdaddr;
125                        WIIMOTE_ENABLE_STATE(wm[found_wiimotes], WIIMOTE_STATE_DEV_FOUND);
126                        ++found_wiimotes;
127                }
128        }
129
130        close(device_sock);
131        return found_wiimotes;
132}
133
134
135/**
136 *      @brief Connect to a wiimote or wiimotes once an address is known.
137 *
138 *      @param wm                       An array of wiimote_t structures.
139 *      @param wiimotes         The number of wiimote structures in \a wm.
140 *  @param autoreconnect        Re-connects the device in case of unexpected disconnection.
141 *
142 *      @return The number of wiimotes that successfully connected.
143 *
144 *      @see wiic_find()
145 *      @see wiic_connect_single()
146 *      @see wiic_disconnect()
147 *
148 *      Connect to a number of wiimotes when the address is already set
149 *      in the wiimote_t structures.  These addresses are normally set
150 *      by the wiic_find() function, but can also be set manually.
151 */
152int wiic_connect(struct wiimote_t** wm, int wiimotes, int autoreconnect) 
153{
154        int connected = 0;
155        int i = 0;
156
157        for (; i < wiimotes; ++i) {
158                if (!WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND))
159                        /* if the device address is not set, skip it */
160                        continue;
161               
162                if (wiic_connect_single(wm[i], NULL, autoreconnect)) {
163                        ++connected;
164                }
165        }
166
167        return connected;
168}
169
170/**
171 *      @brief Load Wii devices registered in the wiimotes.config file.
172 *
173 *      @param wm                       An array of wiimote_t structures.
174 *
175 *      @return The number of wiimotes successfully loaded.
176 *
177 *      @see wiic_find()
178 *  @see wiic_connect()
179 *      @see wiic_connect_single()
180 *      @see wiic_disconnect()
181 *
182 *      Up to version 0.53, it is possible to register the MAC address of your
183 *  Wii devices. This allows to automatically load them, without waiting for any
184 *  search timeout. To register a new device, go to: <HOME_DIR>/.wiic/ and
185 *  edit the file wiimotes.config, by adding the MAC address of the device
186 *  you want to register (one line per MAC address).
187 */
188int wiic_load(struct wiimote_t** wm) 
189{
190        int loaded = 0;
191        int i = 0;
192        char str[200];
193        char* str_ptr = 0;
194        char configPath[100];
195        char* tmp = 0;
196       
197        // Retrieve the HOME environment variable
198        tmp = getenv("HOME");
199        strcpy(configPath,tmp);
200        strncat(configPath,"/.wiic/wiimotes.config",22);
201
202        // Open the config file
203        FILE* fd = 0;
204        fd = fopen(configPath,"r");
205        if(!fd) 
206                return loaded;
207
208        // Read line by line
209        while(fgets(str,sizeof(str),fd) != NULL && loaded < 1) {
210                int len = strlen(str)-1;
211        if(str[len] == '\n') 
212                str[len] = 0;
213                loaded++;
214        }
215       
216        // We initialize the device structure
217        for (; i < loaded; ++i) {
218                /* found a device */
219                strncpy(wm[i]->bdaddr_str,str,18);
220                str_ptr = str;
221                str2ba(str_ptr,&(wm[i]->bdaddr));
222                WIIMOTE_ENABLE_STATE(wm[i], WIIMOTE_STATE_DEV_FOUND);
223                WIIC_INFO("Loaded Wiimote (%s) [id %i].",wm[i]->bdaddr_str,wm[i]->unid);
224        }
225
226        return loaded;
227}
228
229/**
230 *      @brief Connect to a wiimote with a known address.
231 *
232 *      @param wm               Pointer to a wiimote_t structure.
233 *      @param address  The address of the device to connect to.
234 *                                      If NULL, use the address in the struct set by wiic_find().
235 *      @param autoreconnect    Re-connect to the device in case of unexpected disconnection.
236 *
237 *      @return 1 on success, 0 on failure
238 */
239int wiic_connect_single(struct wiimote_t* wm, char* address, int autoreconnect) {
240        struct sockaddr_l2 addr;
241        memset(&addr, 0, sizeof(addr));
242
243        if (!wm || WIIMOTE_IS_CONNECTED(wm))
244                return 0;
245
246        addr.l2_family = AF_BLUETOOTH;
247
248        if (address) 
249                /* use provided address */
250                str2ba(address, &addr.l2_bdaddr);
251        else
252                /* use address of device discovered */
253                addr.l2_bdaddr = wm->bdaddr;
254
255        /*
256         *      OUTPUT CHANNEL
257         */
258        wm->out_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
259        if (wm->out_sock == -1)
260                return 0;
261
262        addr.l2_psm = htobs(WM_OUTPUT_CHANNEL);
263
264        /* connect to wiimote */
265        if (connect(wm->out_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
266                perror("connect() output sock");
267                return 0;
268        }
269
270        /*
271         *      INPUT CHANNEL
272         */
273        wm->in_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
274        if (wm->in_sock == -1) {
275                close(wm->out_sock);
276                wm->out_sock = -1;
277                return 0;
278        }
279
280        addr.l2_psm = htobs(WM_INPUT_CHANNEL);
281
282        /* connect to wiimote */
283        if (connect(wm->in_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
284                perror("connect() interrupt sock");
285                close(wm->out_sock);
286                wm->out_sock = -1;
287                return 0;
288        }
289       
290        /* autoreconnect flag */
291        wm->autoreconnect = autoreconnect;
292
293        WIIC_INFO("Connected to wiimote [id %i].", wm->unid);
294
295        /* do the handshake */
296        WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
297        wiic_handshake(wm, NULL, 0);
298
299        wiic_set_report_type(wm);
300
301        return 1;
302}
303
304
305/**
306 *      @brief Disconnect a wiimote.
307 *
308 *      @param wm               Pointer to a wiimote_t structure.
309 *
310 *      @see wiic_connect()
311 *
312 *      Note that this will not free the wiimote structure.
313 */
314void wiic_disconnect(struct wiimote_t* wm) {
315        if (!wm || !WIIMOTE_IS_CONNECTED(wm))
316                return;
317
318        close(wm->out_sock);
319        close(wm->in_sock);
320
321        wm->out_sock = -1;
322        wm->in_sock = -1;
323        wm->event = WIIC_NONE;
324
325        WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
326        WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
327}
328
329
330int wiic_io_read(struct wiimote_t* wm) {
331        /* not used */
332        return 0;
333}
334
335
336int wiic_io_write(struct wiimote_t* wm, byte* buf, int len) {
337        return write(wm->out_sock, buf, len);
338}
339
340
341#endif /* ifndef __APPLE__ */
Note: See TracBrowser for help on using the repository browser.