root/trunk/libcwiid/state.c

Revision 101, 7.5 kB (checked in by dsmith, 2 years ago)

merge api_overhaul into head (#22, #24, #29)

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-04-24 L. Donnie Smith <cwiid@abstrakraft.org>
19  *  * created for API overhaul (update_rpt_mode moved from command.c)
20  */
21
22 #include <string.h>
23 #include <pthread.h>
24 #include "cwiid_internal.h"
25
26 int update_state(struct wiimote *wiimote, struct mesg_array *ma)
27 {
28         int i;
29         union cwiid_mesg *mesg;
30
31         if (pthread_mutex_lock(&wiimote->state_mutex)) {
32                 cwiid_err(wiimote, "Mutex lock error (state mutex)");
33                 return -1;
34         }
35
36         for (i=0; i < ma->count; i++) {
37                 mesg = &ma->array[i];
38
39                 switch (mesg->type) {
40                 case CWIID_MESG_STATUS:
41                         wiimote->state.battery = mesg->status_mesg.battery;
42                         if (wiimote->state.ext_type != mesg->status_mesg.ext_type) {
43                                 memset(&wiimote->state.ext, 0, sizeof wiimote->state.ext);
44                                 wiimote->state.ext_type = mesg->status_mesg.ext_type;
45                         }
46                         break;
47                 case CWIID_MESG_BTN:
48                         wiimote->state.buttons = mesg->btn_mesg.buttons;
49                         break;
50                 case CWIID_MESG_ACC:
51                         memcpy(wiimote->state.acc, mesg->acc_mesg.acc,
52                                sizeof wiimote->state.acc);
53                         break;
54                 case CWIID_MESG_IR:
55                         memcpy(wiimote->state.ir_src, mesg->ir_mesg.src,
56                                sizeof wiimote->state.ir_src);
57                         break;
58                 case CWIID_MESG_NUNCHUK:
59                         memcpy(wiimote->state.ext.nunchuk.stick,
60                                mesg->nunchuk_mesg.stick,
61                                sizeof wiimote->state.ext.nunchuk.stick);
62                         memcpy(wiimote->state.ext.nunchuk.acc,
63                                mesg->nunchuk_mesg.acc,
64                                sizeof wiimote->state.ext.nunchuk.acc);
65                         wiimote->state.ext.nunchuk.buttons = mesg->nunchuk_mesg.buttons;
66                         break;
67                 case CWIID_MESG_CLASSIC:
68                         memcpy(wiimote->state.ext.classic.l_stick,
69                                mesg->classic_mesg.l_stick,
70                                sizeof wiimote->state.ext.classic.l_stick);
71                         memcpy(wiimote->state.ext.classic.r_stick,
72                                mesg->classic_mesg.r_stick,
73                                sizeof wiimote->state.ext.classic.r_stick);
74                         wiimote->state.ext.classic.l = mesg->classic_mesg.l;
75                         wiimote->state.ext.classic.r = mesg->classic_mesg.r;
76                         wiimote->state.ext.classic.buttons = mesg->classic_mesg.buttons;
77                         break;
78                 case CWIID_MESG_ERROR:
79                         wiimote->state.error = mesg->error_mesg.error;
80                         break;
81                 case CWIID_MESG_UNKNOWN:
82                         /* do nothing, error has already been printed */
83                         break;
84                 }
85         }
86
87         if (pthread_mutex_unlock(&wiimote->state_mutex)) {
88                 cwiid_err(wiimote, "Mutex unlock error (state mutex) - "
89                                    "deadlock warning");
90                 return -1;
91         }
92
93         return 0;
94 }
95
96 /* IR Sensitivity Block */
97 unsigned char ir_block1[] = CLIFF_IR_BLOCK_1;
98 unsigned char ir_block2[] = CLIFF_IR_BLOCK_2;
99
100 struct write_seq ir_enable10_seq[] = {
101         {WRITE_SEQ_RPT, RPT_IR_ENABLE1, (const void *)"\x04", 1, 0},
102         {WRITE_SEQ_RPT, RPT_IR_ENABLE2, (const void *)"\x04", 1, 0},
103         {WRITE_SEQ_MEM, 0xB00030, (const void *)"\x08", 1,     CWIID_RW_REG},
104         {WRITE_SEQ_MEM, 0xB00000, ir_block1, sizeof(ir_block1)-1, CWIID_RW_REG},
105         {WRITE_SEQ_MEM, 0xB0001A, ir_block2, sizeof(ir_block2)-1, CWIID_RW_REG},
106         {WRITE_SEQ_MEM, 0xB00033, (const void *)"\x01", 1,     CWIID_RW_REG}
107 };
108
109 struct write_seq ir_enable12_seq[] = {
110         {WRITE_SEQ_RPT, RPT_IR_ENABLE1, (const void *)"\x04", 1, 0},
111         {WRITE_SEQ_RPT, RPT_IR_ENABLE2, (const void *)"\x04", 1, 0},
112         {WRITE_SEQ_MEM, 0xB00030, (const void *)"\x08", 1,     CWIID_RW_REG},
113         {WRITE_SEQ_MEM, 0xB00000, ir_block1, sizeof(ir_block1)-1, CWIID_RW_REG},
114         {WRITE_SEQ_MEM, 0xB0001A, ir_block2, sizeof(ir_block2)-1, CWIID_RW_REG},
115         {WRITE_SEQ_MEM, 0xB00033, (const void *)"\x03", 1,     CWIID_RW_REG}
116 };
117
118 struct write_seq ir_disable_seq[] = {
119         {WRITE_SEQ_RPT, RPT_IR_ENABLE1, (const void *)"\x00", 1, 0},
120         {WRITE_SEQ_RPT, RPT_IR_ENABLE2, (const void *)"\x00", 1, 0}
121 };
122
123 #define RPT_MODE_BUF_LEN 2
124 int update_rpt_mode(struct wiimote *wiimote, int8_t rpt_mode)
125 {
126         unsigned char buf[RPT_MODE_BUF_LEN];
127         uint8_t rpt_type;
128         struct write_seq *ir_enable_seq;
129         int seq_len;
130
131         /* rpt_mode = bitmask of requested report types */
132         /* rpt_type = report id sent to the wiimote */
133         if (pthread_mutex_lock(&wiimote->rpt_mutex)) {
134                 cwiid_err(wiimote, "Mutex lock error (rpt mutex)");
135                 return -1;
136         }
137
138         /* -1 updates the reporting mode using old rpt_mode
139          * (reporting type may change if extensions are
140          * plugged in/unplugged */
141         if (rpt_mode == -1) {
142                 rpt_mode = wiimote->state.rpt_mode;
143         }
144
145         /* Pick a report mode based on report flags */
146         if ((rpt_mode & CWIID_RPT_EXT) &&
147           ((wiimote->state.ext_type == CWIID_EXT_NUNCHUK) ||
148            (wiimote->state.ext_type == CWIID_EXT_CLASSIC))) {
149                 if ((rpt_mode & CWIID_RPT_IR) && (rpt_mode & CWIID_RPT_ACC)) {
150                         rpt_type = RPT_BTN_ACC_IR10_EXT6;
151                         ir_enable_seq = ir_enable10_seq;
152                         seq_len = SEQ_LEN(ir_enable10_seq);
153                 }
154                 else if (rpt_mode & CWIID_RPT_IR) {
155                         rpt_type = RPT_BTN_IR10_EXT9;
156                         ir_enable_seq = ir_enable10_seq;
157                         seq_len = SEQ_LEN(ir_enable10_seq);
158                 }
159                 else if (rpt_mode & CWIID_RPT_ACC) {
160                         rpt_type = RPT_BTN_ACC_EXT16;
161                 }
162                 else if (rpt_mode & CWIID_RPT_BTN) {
163                         rpt_type = RPT_BTN_EXT8;
164                 }
165                 else {
166                         rpt_type = RPT_EXT21;
167                 }       
168         }
169         else {
170                 if (rpt_mode & CWIID_RPT_IR) {
171                         rpt_type = RPT_BTN_ACC_IR12;
172                         ir_enable_seq = ir_enable12_seq;
173                         seq_len = SEQ_LEN(ir_enable12_seq);
174                 }
175                 else if (rpt_mode & CWIID_RPT_ACC) {
176                         rpt_type = RPT_BTN_ACC;
177                 }
178                 else {
179                         rpt_type = RPT_BTN;
180                 }
181         }
182
183         /* Enable IR */
184         /* TODO: only do this when necessary (record old IR mode) */
185         if ((rpt_mode & CWIID_RPT_IR)) {
186                 if (exec_write_seq(wiimote, seq_len, ir_enable_seq)) {
187                         cwiid_err(wiimote, "IR enable error");
188                         return -1;
189                 }
190         }
191         /* Disable IR */
192         else if ((wiimote->state.rpt_mode & CWIID_RPT_IR) &&
193                  !(rpt_mode & CWIID_RPT_IR)) {
194                 if (exec_write_seq(wiimote, SEQ_LEN(ir_disable_seq), ir_disable_seq)) {
195                         cwiid_err(wiimote, "IR disable error");
196                         return -1;
197                 }
198         }
199
200         /* Send SET_REPORT */
201         buf[0] = (wiimote->flags & CWIID_FLAG_CONTINUOUS) ? 0x04 : 0;
202         buf[1] = rpt_type;
203         if (send_report(wiimote, 0, RPT_RPT_MODE, RPT_MODE_BUF_LEN, buf)) {
204                 cwiid_err(wiimote, "Send report error (report mode)");
205                 return -1;
206         }
207
208         /* clear state for unreported data */
209         if (CWIID_RPT_BTN & ~rpt_mode & wiimote->state.rpt_mode) {
210                 wiimote->state.buttons = 0;
211         }
212         if (CWIID_RPT_ACC & ~rpt_mode & wiimote->state.rpt_mode) {
213                 memset(wiimote->state.acc, 0, sizeof wiimote->state.acc);
214         }
215         if (CWIID_RPT_IR & ~rpt_mode & wiimote->state.rpt_mode) {
216                 memset(wiimote->state.ir_src, 0, sizeof wiimote->state.ir_src);
217         }
218         if ((wiimote->state.ext_type == CWIID_EXT_NUNCHUK) &&
219           (CWIID_RPT_NUNCHUK & ~rpt_mode & wiimote->state.rpt_mode)) {
220                 memset(&wiimote->state.ext, 0, sizeof wiimote->state.ext);
221         }
222         else if ((wiimote->state.ext_type == CWIID_EXT_CLASSIC) &&
223           (CWIID_RPT_CLASSIC & ~rpt_mode & wiimote->state.rpt_mode)) {
224                 memset(&wiimote->state.ext, 0, sizeof wiimote->state.ext);
225         }
226
227         wiimote->state.rpt_mode = rpt_mode;
228
229         if (pthread_mutex_unlock(&wiimote->rpt_mutex)) {
230                 cwiid_err(wiimote, "Mutex unlock error (rpt mutex) - "
231                           "deadlock warning");
232                 return -1;
233         }
234
235         return 0;
236 }
Note: See TracBrowser for help on using the browser.