root/branches/dev/libcwiid/thread.c

Revision 115, 7.8 kB (checked in by dsmith, 2 years ago)

fixed error message reporting

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  *  2007-05-16 L. Donnie Smith <cwiid@abstrakraft.org>
19  *  * send error_mesg from process_error
20  *
21  *  2007-05-14 L. Donnie Smith <cwiid@abstrakraft.org>
22  *  * added timestamp to message array
23  *
24  *  2007-04-24 L. Donnie Smith <cwiid@abstrakraft.org>
25  *  * rewrite for API overhaul (renamed from event.c)
26  *
27  *  2007-04-09 L. Donnie Smith <cwiid@abstrakraft.org>
28  *  * renamed wiimote to libcwiid, renamed structures accordingly
29  *
30  *  2007-04-08 L. Donnie Smith <cwiid@abstrakraft.org>
31  *  * fixed incompatible pointer warning in process_error
32  *
33  *  2007-04-08 Petter Reinholdtsen <pere@hungry.com>
34  *  * fixed signed/unsigned comparison error in int_listen
35  *
36  *  2007-04-04 L. Donnie Smith <cwiid@abstrakraft.org>
37  *  * implemented process_error to handle socket read errors
38  *  * added rw_status triggers to read and write handlers
39  *
40  *  2007-03-14 L. Donnie Smith <cwiid@abstrakraft.org>
41  *  * audit error checking
42  *  * reorganized file
43  *  * moved int_listen read/write code to process_read and process_write
44  *  * updated (some/a few) comments
45  *
46  *  2007-03-06 L. Donnie Smith <cwiid@abstrakraft.org>
47  *  * added wiimote parameter to cwiid_err calls
48  *
49  *  2007-03-01 L. Donnie Smith <cwiid@abstrakraft.org>
50  *  * Initial ChangeLog
51  *  * type audit (stdint, const, char booleans)
52  */
53
54 #include <stdint.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <pthread.h>
58 #include <time.h>
59 #include <unistd.h>
60 #include "cwiid_internal.h"
61
62 #define READ_BUF_LEN 23
63 void *router_thread(struct wiimote *wiimote)
64 {
65         unsigned char buf[READ_BUF_LEN];
66         ssize_t len;
67         struct mesg_array ma;
68         char err, print_clock_err = 1;
69
70         while (1) {
71                 /* Read packet */
72                 len = read(wiimote->int_socket, buf, READ_BUF_LEN);
73                 ma.count = 0;
74                 if (clock_gettime(CLOCK_REALTIME, &ma.timestamp)) {
75                         if (print_clock_err) {
76                                 cwiid_err(wiimote, "clock_gettime error");
77                                 print_clock_err = 0;
78                         }
79                 }
80                 err = 0;
81                 if ((len == -1) || (len == 0)) {
82                         process_error(wiimote, len, &ma);
83                         write_mesg_array(wiimote, &ma);
84                         /* Quit! */
85                         break;
86                 }
87                 else {
88                         /* Verify first byte (DATA/INPUT) */
89                         if (buf[0] != (BT_TRANS_DATA | BT_PARAM_INPUT)) {
90                                 cwiid_err(wiimote, "Invalid packet type");
91                         }
92
93                         /* Main switch */
94                         switch (buf[1]) {
95                         case RPT_STATUS:
96                                 err = process_status(wiimote, &buf[2], &ma);
97                                 break;
98                         case RPT_BTN:
99                                 err = process_btn(wiimote, &buf[2], &ma);
100                                 break;
101                         case RPT_BTN_ACC:
102                                 err = process_btn(wiimote, &buf[2], &ma) ||
103                                       process_acc(wiimote, &buf[4], &ma);
104                                 break;
105                         case RPT_BTN_EXT8:
106                                 err = process_btn(wiimote, &buf[2], &ma) ||
107                                       process_ext(wiimote, &buf[4], 8, &ma);
108                                 break;
109                         case RPT_BTN_ACC_IR12:
110                                 err = process_btn(wiimote, &buf[2], &ma) ||
111                                       process_acc(wiimote, &buf[4], &ma) ||
112                                       process_ir12(wiimote, &buf[7], &ma);
113                                 break;
114                         case RPT_BTN_EXT19:
115                                 err = process_btn(wiimote, &buf[2], &ma) ||
116                                       process_ext(wiimote, &buf[4], 19, &ma);
117                                 break;
118                         case RPT_BTN_ACC_EXT16:
119                                 err = process_btn(wiimote, &buf[2], &ma) ||
120                                       process_acc(wiimote, &buf[4], &ma) ||
121                                       process_ext(wiimote, &buf[7], 16, &ma);
122                                 break;
123                         case RPT_BTN_IR10_EXT9:
124                                 err = process_btn(wiimote, &buf[2], &ma)  ||
125                                       process_ir10(wiimote, &buf[4], &ma) ||
126                                       process_ext(wiimote, &buf[14], 9, &ma);
127                                 break;
128                         case RPT_BTN_ACC_IR10_EXT6:
129                                 err = process_btn(wiimote, &buf[2], &ma)  ||
130                                       process_acc(wiimote, &buf[4], &ma)  ||
131                                       process_ir10(wiimote, &buf[7], &ma) ||
132                                       process_ext(wiimote, &buf[17], 6, &ma);
133                                 break;
134                         case RPT_EXT21:
135                                 err = process_ext(wiimote, &buf[2], 21, &ma);
136                                 break;
137                         case RPT_BTN_ACC_IR36_1:
138                         case RPT_BTN_ACC_IR36_2:
139                                 cwiid_err(wiimote, "Unsupported report type received "
140                                                    "(interleaved data)");
141                                 err = 1;
142                                 break;
143                         case RPT_READ_DATA:
144                                 err = process_read(wiimote, &buf[4]) ||
145                                       process_btn(wiimote, &buf[2], &ma);
146                                 break;
147                         case RPT_WRITE_ACK:
148                                 err = process_write(wiimote, &buf[2]);
149                                 break;
150                         default:
151                                 cwiid_err(wiimote, "Unknown message type");
152                                 err = 1;
153                                 break;
154                         }
155
156                         if (!err && (ma.count > 0)) {
157                                 if (update_state(wiimote, &ma)) {
158                                         cwiid_err(wiimote, "State update error");
159                                 }
160                                 if (wiimote->flags & CWIID_FLAG_MESG_IFC) {
161                                         /* prints its own errors */
162                                         write_mesg_array(wiimote, &ma);
163                                 }
164                         }
165                 }
166         }
167
168         return NULL;
169 }
170
171 void *status_thread(struct wiimote *wiimote)
172 {
173         struct mesg_array ma;
174         struct cwiid_status_mesg *status_mesg;
175         unsigned char buf;
176
177         ma.count = 1;
178         status_mesg = &ma.array[0].status_mesg;
179
180         while (1) {
181                 if (full_read(wiimote->status_pipe[0], status_mesg,
182                               sizeof *status_mesg)) {
183                         cwiid_err(wiimote, "Pipe read error (status)");
184                         /* Quit! */
185                         break;
186                 }
187
188                 if (status_mesg->type != CWIID_MESG_STATUS) {
189                         cwiid_err(wiimote, "Bad message on status pipe");
190                         continue;
191                 }
192
193                 if (status_mesg->ext_type == CWIID_EXT_UNKNOWN) {
194                         if (wiimote->state.ext_type == CWIID_EXT_NONE) {
195                                 buf = 0x00;
196                                 /* Initialize extension register space */
197                                 if (cwiid_write(wiimote, CWIID_RW_REG, 0xA40040, 1, &buf)) {
198                                         cwiid_err(wiimote, "Extension initialization error");
199                                         status_mesg->ext_type = CWIID_EXT_UNKNOWN;
200                                 }
201                                 /* Read extension ID */
202                                 else if (cwiid_read(wiimote, CWIID_RW_REG | CWIID_RW_DECODE,
203                                                     0xA400FE, 1, &buf)) {
204                                         cwiid_err(wiimote, "Read error (extension error)");
205                                         status_mesg->ext_type = CWIID_EXT_UNKNOWN;
206                                 }
207                                 else {
208                                         switch (buf) {
209                                         case EXT_NONE:
210                                         case EXT_PARTIAL:
211                                                 status_mesg->ext_type = CWIID_EXT_NONE;
212                                                 break;
213                                         case EXT_NUNCHUK:
214                                                 status_mesg->ext_type = CWIID_EXT_NUNCHUK;
215                                                 break;
216                                         case EXT_CLASSIC:
217                                                 status_mesg->ext_type = CWIID_EXT_CLASSIC;
218                                                 break;
219                                         default:
220                                                 status_mesg->ext_type = CWIID_EXT_UNKNOWN;
221                                                 break;
222                                         }
223                                 }
224                         }
225                         else {
226                                 status_mesg->ext_type = wiimote->state.ext_type;
227                         }
228                 }
229
230                 if (update_state(wiimote, &ma)) {
231                         cwiid_err(wiimote, "State update error");
232                 }
233                 if (update_rpt_mode(wiimote, -1)) {
234                         cwiid_err(wiimote, "Error reseting report mode");
235                 }
236                 if ((wiimote->state.rpt_mode & CWIID_RPT_STATUS) &&
237                   (wiimote->flags & CWIID_FLAG_MESG_IFC)) {
238                         if (write_mesg_array(wiimote, &ma)) {
239                                 /* prints its own errors */
240                         }
241                 }
242         }
243
244         return NULL;
245 }
246
247 void *mesg_callback_thread(struct wiimote *wiimote)
248 {
249         int mesg_pipe = wiimote->mesg_pipe[0];
250         cwiid_mesg_callback_t *callback = wiimote->mesg_callback;
251         struct mesg_array ma;
252         int cancelstate;
253
254         while (1) {
255                 if (read_mesg_array(mesg_pipe, &ma)) {
256                         cwiid_err(wiimote, "Mesg pipe read error");
257                         continue;
258                 }
259
260                 /* TODO: The callback can still be called once after disconnect,
261                  * although it's very unlikely.  User must keep track and avoid
262                  * accessing the wiimote struct after disconnect. */
263                 if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelstate)) {
264                         cwiid_err(wiimote, "Cancel state disable error (callback thread)");
265                 }
266                 callback(wiimote, ma.count, ma.array, &ma.timestamp);
267                 if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &cancelstate)) {
268                         cwiid_err(wiimote, "Cancel state restore error (callback thread)");
269                 }
270         }
271
272         return NULL;
273 }
Note: See TracBrowser for help on using the browser.