2
* Fake joystick driver for Linux
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
#include <linux/input.h>
30
#define STACK_SIZE 1024
34
//#define debug printf
36
static int installed=0;
38
static int timestamp=0;
39
static int executing=0;
41
//controller variables
42
static __s16 code_analog[64];
43
//controller variables
44
static __u8 code_bit[128];
45
//controller variables
46
static __s16 js_analog[16][64];
47
//controller variables
48
static __u8 js_bit[16][128];
49
static __s16 currentmode=0;
50
static __s16 firstscan=1;
51
static __s16 clocktick=1;
55
static __u8 code[MAX_CODE_SIZE];
56
//registers inaccessible to user
57
//allocated by compiler
58
static int status=0; //0 = no valid program 1=valid program
59
static struct code_context {
61
int registers[256]; //general purpose registers
63
int stack[STACK_SIZE];
64
int active; //is this thread active
65
} code_threads[MAX_THREADS];
67
//for each instruction, does it have an operand
68
static char has_operand[]={
92
1, /* THREAD handles its own arguments */
102
struct code_context *code_thread;
104
void code_button(int code, int value);
105
void code_axis(int axis, int value);
106
void execute_script(void);
108
void code_notify_button(int js, int key, int value) {
109
if ((js>=0)&&(js<16))
110
if ((key-BTN_JOYSTICK>=0)&&(key-BTN_JOYSTICK<128)) {
111
if (js_bit[js][key-BTN_JOYSTICK]!=value) {
112
js_bit[js][key-BTN_JOYSTICK]=value;
118
void code_notify_axis(int js, int axis, int value) {
119
if ((js>=0)&&(js<16))
120
if ((axis>=0)&&(axis<64)) {
121
if (js_analog[js][axis]!=value) {
122
js_analog[js][axis]=value;
128
void code_set_program(struct program_code *program) {
133
if (program->program!=PROGRAM_CODE) return;
134
memcpy(code, program->code, MAX_CODE_SIZE);
141
void code_reset(void) {
143
for (i=0; i<MAX_THREADS; i++) {
144
for (j=0; j<256; j++) {
145
code_threads[i].registers[j]=0;
147
code_threads[i].active=0;
149
code_threads[0].active=1;
150
for (i=0; i<64; i++) {
153
for (i=0; i<128; i++) {
161
static void push(int x) {
162
if (code_thread->sp<STACK_SIZE) code_thread->stack[code_thread->sp++]=x;
165
static int pop(void) {
166
if (code_thread->sp<=0) return 0;
167
else return code_thread->stack[--code_thread->sp];
170
static int get_value(int address, int type, int array) {
174
ofs=code_thread->registers[OFSREG];
177
if (address+ofs==FIRSTSCAN) return firstscan;
178
if (address+ofs==CLOCKTICK) return clocktick;
179
if (address+ofs==XREL) return xrel;
180
if (address+ofs==YREL) return yrel;
181
if (address+ofs==ZREL) return zrel;
182
if (address+ofs==TIMESTAMP) return timestamp;//jiffies_to_msecs(jiffies);
183
if (address+ofs==CURRENTMODE) return currentmode;
184
if ((address+ofs>=0)&&(address+ofs<256))
185
return code_thread->registers[address+ofs];
189
if ((address+ofs>=0)&&(address+ofs<64))
190
return code_analog[address+ofs];
194
if ((address+ofs>=0)&&(address+ofs<128))
195
return code_bit[address+ofs];
199
js=(address&0x0F00)>>8;
201
address=address&0x00FF;
203
if ((address+ofs>=0)&&(address+ofs<128))
204
return js_bit[js][address+ofs];
208
if ((address+ofs>=0)&&(address+ofs<64))
209
return js_analog[js][address+ofs];
220
static void set_value(int address, int type, int value, int array) {
223
ofs=code_thread->registers[OFSREG];
226
if (address==XREL) xrel=value;
227
if (address==YREL) yrel=value;
228
if (address==ZREL) zrel=value;
229
if (address==CURRENTMODE) currentmode=value;
230
if ((address+ofs>=0)&&(address+ofs<256))
231
code_thread->registers[address+ofs]=value;
234
if ((address+ofs>=0)&&(address+ofs<64))
235
code_axis(address+ofs, value);
238
if ((address+ofs>=0)&&(address+ofs<128))
239
code_button(address+ofs, value);
249
static int instr_exec=0;
251
static void execute_script_thread(struct code_context *new_thread, unsigned int new_ip, unsigned int retip);
252
void execute_script(void) {
253
if (executing) return;
255
code_thread=&code_threads[0];
258
code_thread->active=1;
260
debug("\n\nstart thread\n");
261
debug("timestamp %d\n", timestamp);
262
execute_script_thread(code_thread,0,MAX_CODE_SIZE);
268
static void execute_script_thread(struct code_context *new_thread, unsigned int new_ip, unsigned int retip) {
269
int address=0, array=0;
275
unsigned int thread_start;
276
unsigned int thread_exit;
277
if (status!=1) return;
278
if (!new_thread->active) {
279
debug("Activating thread\n");
280
*new_thread=*code_thread;
281
new_thread->ip=new_ip;
282
//code_thread->ip=retip;
283
code_thread=new_thread;
284
new_thread->active=1;
286
code_thread=new_thread;
288
while ((code_thread->ip<MAX_CODE_SIZE)&&(instr_exec<100000)) {
289
task=code[code_thread->ip++];
290
if (task>=PUSHA) array=1;
294
if ((task>=0)&&(task<=INCA))
295
if (has_operand[task]) {
296
address=*((unsigned short *)(code+code_thread->ip));
297
value=get_value(address, type, array);
299
debug("Got operand %d address=%d type=%d\n",value, address, type);
305
code_thread->ip=MAX_CODE_SIZE+1;
306
code_thread->active=0;
311
if (st==0) code_thread->ip=value;
315
code_thread->ip=value;
319
code_thread->ip+=value;
404
debug("PUSH %d\n", value);
409
debug("POP %d\n", value);
410
set_value(address, type, value, 0);
414
set_value(address, type, value-1, 0);
418
set_value(address, type, value+1, 0);
421
debug("PUSHA %d\n", value);
426
debug("POPA %d\n", value);
427
set_value(address, type, value, 1);
431
set_value(address, type, value-1, 1);
435
set_value(address, type, value+1, 1);
440
debug("KEY %d %d\n", p1, p2);
448
case THREAD: //context switch, value is new thread, two constant jump targets
449
//thread_start=*((unsigned short *)(code+code_thread->ip));
450
//code_thread->ip+=2;
451
debug("THREAD %d\n", value);
452
thread_exit=*((unsigned short *)(code+code_thread->ip));
454
thread_start=code_thread->ip;
455
if ((value>0)&&(value<MAX_THREADS)) {
456
execute_script_thread(&code_threads[value], thread_start, thread_exit);
457
code_thread=new_thread;
458
code_thread->ip=thread_exit;
460
debug("Not a valid thread\n");
461
code_thread=new_thread;
462
code_thread->ip=thread_exit;
469
case JOIN: //stop thread
470
debug("JOIN %d\n", value);
471
if ((value>0)&&(value<MAX_THREADS)) {
472
code_thread[value].active=0;
479
int mapper_code_install(void) {
481
if (installed) return 0;
483
for (j=0; j<16; j++) {
484
for (i=0; i<64; i++) {
487
for (i=0; i<128; i++) {
497
int mapper_code_uninstall(void) {
504
void code_button(int code, int value) {
505
if (!installed) return;
506
if (value!=code_bit[code]) {
507
press_joy_button(255, BTN_JOYSTICK+code, value);
508
code_bit[code]=value;
512
void code_axis(int axis, int value) {
513
if (!installed) return;
514
if (value!=code_analog[axis]) {
515
set_joy_axis(255, axis, value);
516
code_analog[axis]=value;
525
debug("timertick %d\n", timestamp);