root/libcwiid/util.c

Revision 2100f14c612471084434b364501e3818c7f4144e, 4.5 kB (checked in by L. Donnie Smith <donnie.smith@…>, 3 years ago)

Various administrative updates

change email addresses
remove individual file changelogs (that's what version control is for)

  • Property mode set to 100644
Line 
1/* Copyright (C) 2007 L. Donnie Smith <donnie.smith@gatech.edu>
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 */
18
19#include <errno.h>
20#include <stdarg.h>
21#include <stdint.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <fcntl.h>
26#include <unistd.h>
27#include "cwiid_internal.h"
28
29cwiid_err_t cwiid_err_default;
30
31static cwiid_err_t *cwiid_err_func = &cwiid_err_default;
32
33int cwiid_set_err(cwiid_err_t *err)
34{
35        /* TODO: assuming pointer assignment is atomic operation */
36        /* if it is, and the user doesn't care about race conditions, we don't
37         * either */
38        cwiid_err_func = err;
39        return 0;
40}
41
42void cwiid_err_default(struct wiimote *wiimote, const char *str, va_list ap)
43{
44        vfprintf(stderr, str, ap);
45        fprintf(stderr, "\n");
46}
47
48void cwiid_err(struct wiimote *wiimote, const char *str, ...)
49{
50        va_list ap;
51
52        if (cwiid_err_func) {
53                va_start(ap, str);
54                (*cwiid_err_func)(wiimote, str, ap);
55                va_end(ap);
56        }
57}
58
59int verify_handshake(struct wiimote *wiimote)
60{
61        unsigned char handshake;
62        if (read(wiimote->ctl_socket, &handshake, 1) != 1) {
63                cwiid_err(wiimote, "Socket read error (handshake)");
64                return -1;
65        }
66        else if ((handshake & BT_TRANS_MASK) != BT_TRANS_HANDSHAKE) {
67                cwiid_err(wiimote, "Handshake expected, non-handshake received");
68                return -1;
69        }
70        else if ((handshake & BT_PARAM_MASK) != BT_PARAM_SUCCESSFUL) {
71                cwiid_err(wiimote, "Non-successful handshake");
72                return -1;
73        }
74
75        return 0;
76}
77
78int exec_write_seq(struct wiimote *wiimote, unsigned int len,
79                   struct write_seq *seq)
80{
81        unsigned int i;
82
83        for (i=0; i < len; i++) {
84                switch (seq[i].type) {
85                case WRITE_SEQ_RPT:
86                        if (cwiid_send_rpt(wiimote, seq[i].flags, seq[i].report_offset,
87                                           seq[i].len, seq[i].data)) {
88                                return -1;
89                        }
90                        break;
91                case WRITE_SEQ_MEM:
92                        if (cwiid_write(wiimote, seq[i].flags, seq[i].report_offset,
93                                        seq[i].len, seq[i].data)) {
94                                return -1;
95                        }
96                        break;
97                }
98        }
99
100        return 0;
101}
102
103int full_read(int fd, void *buf, size_t len)
104{
105        ssize_t last_len = 0;
106
107        do {
108                if ((last_len = read(fd, buf, len)) == -1) {
109                        return -1;
110                }
111                len -= last_len;
112                buf += last_len;
113        } while (len > 0);
114
115        return 0;
116}
117
118int write_mesg_array(struct wiimote *wiimote, struct mesg_array *ma)
119{
120        ssize_t len = (void *)&ma->array[ma->count] - (void *)ma;
121        int ret = 0;
122
123        /* This must remain a single write operation to ensure atomicity,
124         * which is required to avoid mutexes and cancellation issues */
125        if (write(wiimote->mesg_pipe[1], ma, len) != len) {
126                if (errno == EAGAIN) {
127                        cwiid_err(wiimote, "Mesg pipe overflow");
128                        if (fcntl(wiimote->mesg_pipe[1], F_SETFL, 0)) {
129                                cwiid_err(wiimote, "File control error (mesg pipe)");
130                                ret = -1;
131                        }
132                        else {
133                                if (write(wiimote->mesg_pipe[1], ma, len) != len) {
134                                        cwiid_err(wiimote, "Pipe write error (mesg pipe)");
135                                        ret = -1;
136                                }
137                                if (fcntl(wiimote->mesg_pipe[1], F_SETFL, O_NONBLOCK)) {
138                                        cwiid_err(wiimote, "File control error (mesg pipe");
139                                }
140                        }
141                }
142                else {
143                        cwiid_err(wiimote, "Pipe write error (mesg pipe)");
144                        ret = -1;
145                }
146        }
147
148        return ret;
149}
150
151int read_mesg_array(int fd, struct mesg_array *ma)
152{
153        ssize_t len;
154
155        len = (void *)&ma->array[0] - (void *)ma;
156        if (full_read(fd, ma, len)) {
157                return -1;
158        }
159
160        len = ma->count * sizeof ma->array[0];
161        if (full_read(fd, &ma->array[0], len)) {
162                return -1;
163        }
164
165        return 0;
166}
167
168int cancel_rw(struct wiimote *wiimote)
169{
170        struct rw_mesg rw_mesg;
171
172        rw_mesg.type = RW_CANCEL;
173
174        if (write(wiimote->rw_pipe[1], &rw_mesg, sizeof rw_mesg) !=
175          sizeof rw_mesg) {
176                cwiid_err(wiimote, "Pipe write error (rw)");
177                return -1;
178        }
179
180        return 0;
181}
182
183int cancel_mesg_callback(struct wiimote *wiimote)
184{
185        int ret = 0;
186
187        if (pthread_cancel(wiimote->mesg_callback_thread)) {
188                cwiid_err(wiimote, "Thread cancel error (callback thread)");
189                ret = -1;
190        }
191
192        if (pthread_detach(wiimote->mesg_callback_thread)) {
193                cwiid_err(wiimote, "Thread detach error (callback thread)");
194                ret = -1;
195        }
196
197        return ret;
198}
Note: See TracBrowser for help on using the browser.