📄 joystick.c
字号:
/* Joystick interface modeled after svgalibs keyboard and mouse interfaces * Copyright 1998 Daniel Engstr鰉 <daniel.engstrom@riksnett.no> * Partly based on code from * joystick-0.7.3 Copyright (C) 1992, 1993 Author C. Smith * and * joystick-1.0.6 Copyright (C) 1997 Vojtech Pavlik */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include "joydev.h"#include "vgajoystick.h"#include <driver.h>#undef DEBUG#ifndef SVGA_AOUT/* forward declarations */static void joystick_defaulthandler(int event, int num, char val, int joydev);static void joystick_initdefhandler(int joydev, int buttons, int axes);/* global variables *//* Do not just change the sizes, check vga.c too, 4 is a minimum */#define NUM_JOYSTICKS 4char *__joystick_devicenames[NUM_JOYSTICKS] = { NULL, NULL, NULL, NULL };static char *defnames[NUM_JOYSTICKS] = { "/dev/js0", "/dev/js1", "/dev/js2", "/dev/js3"};typedef struct { int (*update)(int); void (*handler)(int, int, char, int); int (*flip_vc)(int, int); char *dh_buttons; char *dh_axes; char axes, buttons; union t{ struct { int b, x, y; int xdif, ydif; struct JS_DATA_TYPE caldata; } prot0; struct { struct js_corr corrdata[4]; } prot1; } p;} joydat_t;static struct { int fd; joydat_t *joydata;} joydesc[NUM_JOYSTICKS] = { {-1, NULL}, {-1, NULL}, {-1, NULL}, {-1, NULL},};#define PROT0_TIMELIMIT 5/* NULL func to be used before we know which one to use *//* Update functions return bit 1 set if further events might be pending, bit 0 set if status changed... */static int joystick_updx(int joydev){ return 0;}/* For old version 0.x joystick drivers */static int joystick_upd0(int joydev){ int retval = 0; struct JS_DATA_TYPE js; if (read(joydesc[joydev].fd, &js, sizeof(struct JS_DATA_TYPE)) != sizeof(struct JS_DATA_TYPE)) return retval; if (js.buttons != joydesc[joydev].joydata->p.prot0.b) { int bmask=1, but; for (but=0; but<4; but++) { if ((js.buttons & bmask) != (joydesc[joydev].joydata->p.prot0.b & bmask)) { joydesc[joydev].joydata->handler((js.buttons & bmask)? JOY_EVENTBUTTONDOWN: JOY_EVENTBUTTONUP, but, 0, joydev); } bmask=bmask<<1; } joydesc[joydev].joydata->p.prot0.b=js.buttons; retval = 1; } if (js.x != joydesc[joydev].joydata->p.prot0.x) { joydesc[joydev].joydata->p.prot0.x = js.x; js.x -= joydesc[joydev].joydata->p.prot0.xdif; if (js.x < -128) js.x = -128; else if (js.x > 127) js.x = 127; joydesc[joydev].joydata->handler(JOY_EVENTAXIS, 0, (char)js.x, joydev); retval = 1; } if (js.y != joydesc[joydev].joydata->p.prot0.y) { joydesc[joydev].joydata->p.prot0.y = js.y; js.y -= joydesc[joydev].joydata->p.prot0.ydif; if (js.y < -128) js.y = -128; else if (js.y > 127) js.y = 127; joydesc[joydev].joydata->handler(JOY_EVENTAXIS, 1, (char)js.y, joydev); retval = 1; } return retval;}static int joystick_flp0(int joydev, int acquire) { unsigned long tmpl;#ifdef DEBUG printf("joyflp: %d, %d\n", joydev, acquire);#endif if (!acquire) { /* close joystick device */ if (joydesc[joydev].fd >= 0) { close(joydesc[joydev].fd); joydesc[joydev].fd = -1; } } else if (joydesc[joydev].fd < 0) {#ifdef DEBUG puts("trying to reopen");#endif /* (re)open joystick device */ if ((joydesc[joydev].fd = open(__joystick_devicenames[joydev] ? __joystick_devicenames[joydev] : defnames[joydev], O_RDONLY|O_NONBLOCK)) < 0) return 1; tmpl = PROT0_TIMELIMIT; if (-1 == ioctl(joydesc[joydev].fd, JS_SET_TIMELIMIT, &tmpl)) return 1; if (-1 == ioctl(joydesc[joydev].fd, JS_SET_CAL, &joydesc[joydev].joydata->p.prot0.caldata)) return 1; } return 0;}/* For new, version 1.x+ joystick drivers */static int joystick_upd1(int joydev){ int retval = 0; struct js_event js; if (read(joydesc[joydev].fd, &js, sizeof(struct js_event)) != sizeof(struct js_event)) return retval; retval = 2; /* further events might be pending */ if ((js.type & JS_EVENT_AXIS) == JS_EVENT_AXIS) { joydesc[joydev].joydata->handler(JOY_EVENTAXIS, js.number, js.value>>8, joydev); retval = 3; } if ((js.type & JS_EVENT_BUTTON) == JS_EVENT_BUTTON) { if (js.value) joydesc[joydev].joydata->handler(JOY_EVENTBUTTONDOWN, js.number, 0, joydev); else joydesc[joydev].joydata->handler(JOY_EVENTBUTTONUP, js.number, 0, joydev); retval = 3; } return retval;}static int joystick_flp1(int joydev, int acquire) { if (!acquire) { /* close joystick device */ if (joydesc[joydev].fd >= 0) { close(joydesc[joydev].fd); joydesc[joydev].fd = -1; } } else if (joydesc[joydev].fd < 0) { /* (re)open joystick device */ if ((joydesc[joydev].fd = open(__joystick_devicenames[joydev] ? __joystick_devicenames[joydev] : defnames[joydev], O_RDONLY|O_NONBLOCK)) < 0) return 1; if (-1 == ioctl(joydesc[joydev].fd, JSIOCSCORR, &joydesc[joydev].joydata->p.prot1.corrdata)) return 1; } return 0;}/* calibration routine for version 0.x protocol */static int jscal0(int joydev, __joystick_output jo){ char msg[100]; int tmp; long tmpl; struct JS_DATA_TYPE js_data; tmpl = PROT0_TIMELIMIT; if (-1 == ioctl(joydesc[joydev].fd, JS_SET_TIMELIMIT, &tmpl)) { if (__svgalib_driver_report) printf("svgalib, joystick%d: Failed to set timelimit\n", joydev); return -1; } if (-1 == ioctl(joydesc[joydev].fd, JS_GET_CAL, &js_data)) { if (__svgalib_driver_report) printf("svgalib, joystick%d: Failed to read calibration data\n", joydev); return -1; } if (__svgalib_driver_report) printf("svgalib, joystick%d: Current correction: %d , %d\n", joydev, js_data.x, js_data.y); sprintf(msg, "Move Joystick %d to lower right corner and press either button...\n", joydev); jo(msg); while ((read (joydesc[joydev].fd, &js_data, JS_RETURN) > 0) && js_data.buttons == 0x00) usleep(100); for (tmp = 0; js_data.x > 0xff; tmp++, js_data.x = js_data.x >> 1); js_data.x = tmp; for (tmp = 0; js_data.y > 0xff; tmp++, js_data.y = js_data.y >> 1); js_data.y = tmp; if (__svgalib_driver_report) printf("svgalib, joystick%d: Setting correction: %d , %d\n", joydev, js_data.x, js_data.y); if (-1 == ioctl(joydesc[joydev].fd, JS_SET_CAL, &js_data)) { if (__svgalib_driver_report) printf("svgalib, joystick%d: Failed to set calibration data\n", joydev); return -1; } sprintf(msg, "Center Joystick %d and press either button...\n", joydev); jo(msg); while ((read (joydesc[joydev].fd, &js_data, JS_RETURN) > 0) && js_data.buttons) usleep(100); while ((read (joydesc[joydev].fd, &js_data, JS_RETURN) > 0) && !js_data.buttons) usleep(100); if (__svgalib_driver_report) printf("svgalib, joystick%d: Setting center offset: %d , %d\n", joydev, js_data.x, js_data.y); joydesc[joydev].joydata->p.prot0.xdif = js_data.x; joydesc[joydev].joydata->p.prot0.ydif = js_data.y; sprintf(msg, "Joystick %d recalibrated.\n", joydev); jo(msg); return joydesc[joydev].fd;}/* Definitions and data types for jscal1() and friends */#define NUM_POS 3struct js_info { int time; int buttons; int axis[4];};struct correction_data { int cmin[NUM_POS]; int cmax[NUM_POS];}; /* support routine for jscal1() * Waits for a joystick event to happen * and updates struct js_info *s accordingly */static int wait_for_event(int fd, struct js_info *s){ struct js_event ev; if (read(fd, &ev, sizeof(struct js_event)) != sizeof(struct js_event)) return 0; s->time = ev.time; switch (ev.type & ~JS_EVENT_INIT) { case JS_EVENT_AXIS: s->axis[ev.number]=ev.value; break; case JS_EVENT_BUTTON: s->buttons = (s->buttons & ~(1 << ev.number)) | ev.value << ev.number; } return sizeof(struct js_event);}/* calibration routine for 1.x protcol */static int jscal1(int joydev, __joystick_output jo){ int i, j, t; struct correction_data corda[4]; struct js_corr corr[4]; struct js_info js; const char corr_coef_num[] = {0,6}; char msg[200]; static const char *pos_name[] = {"minimum", "center", "maximum"}; static const char *corr_name[] = {"none (raw)", "broken line"}; js.buttons=0; if (-1 == ioctl(joydesc[joydev].fd, JSIOCGCORR, &corr)) { if (__svgalib_driver_report) printf("svgalib, joystick %d: error getting correction\n", joydev); return -1; } for (i=0; i<3; i++) { corr[i].type = JS_CORR_NONE; corr[i].prec = 0; } for(i=0; i < joydesc[joydev].joydata->axes; i++) js.axis[i]=0; for(i=0; i < joydesc[joydev].joydata->axes; i++) while(0==js.axis[i]) wait_for_event(joydesc[joydev].fd, &js);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -