/* * Copyright (c) 2017-2019 TOYOTA MOTOR CORPORATION * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "wheel-service.h" #include "js_raw.h" #include "js_signal_event.h" #define JSNAMELEN 128 static int *axis; static char *button; static timer_t tid; static struct sigaction oldact; int js_signal_read(int fd) { ssize_t size; struct js_event jsEvent; int rc = 0; size = read(fd, &jsEvent, sizeof(struct js_event)); if(size != 0) { switch (jsEvent.type) //& ~JS_EVENT_INIT don't deal with init state. { case JS_EVENT_BUTTON | JS_EVENT_INIT: DBG_NOTICE("This is JS_EVENT_BUTTON init state [%d] : %d.", jsEvent.number, button[jsEvent.number]); break; case JS_EVENT_AXIS | JS_EVENT_INIT: DBG_NOTICE("This is JS_EVENT_AXIS init state [%d] : %d.", jsEvent.number, axis[jsEvent.number]); break; case JS_EVENT_BUTTON: button[jsEvent.number] = (char)jsEvent.value; DBG_NOTICE("JS_EVENT_BUTTON [%d] : %d.", jsEvent.number, button[jsEvent.number]); newButtonValue(jsEvent.number, jsEvent.value); break; case JS_EVENT_AXIS: axis[jsEvent.number] = jsEvent.value; DBG_NOTICE("JS_EVENT_AXIS [%d] : %d.", jsEvent.number, axis[jsEvent.number]); newAxisValue(jsEvent.number, jsEvent.value); break; default: break; } rc = 0; } else { rc = -1; } return rc; } int on_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) { if ((revents & EPOLLIN) != 0) { //NOTICEMSG("on_event!\n"); int rc = 0; rc = js_signal_read(fd); if(rc == -1) { DBG_ERROR("JS Frame Read failed"); return -1; } } if ((revents & (EPOLLERR|EPOLLRDHUP|EPOLLHUP)) != 0) { /* T.B.D * if error or hungup */ DBG_ERROR("Error or Hunup: rvent=%08x", revents); } return 0; } int js_open(const char *devname) { unsigned char numAxes = 0; unsigned char numButtons = 0; int version = 0; int fd; char name[JSNAMELEN] = "Unknown"; char steering_name[JSNAMELEN] = "Logitech G29 Driving Force Racing Wheel"; struct js_corr cal[6]; int i, j; unsigned int calData[36] = { 1, 0, 8191, 8192, 65542, 65534, 1, 0, 127, 128, 4227201, 4194176, 1, 0, 127, 128, 4227201, 4194176, 1, 0, 127, 128, 4227201, 4194176, 1, 0, 0, 0, 536854528, 536854528, 1, 0, 0, 0, 536854528, 536854528 }; if ((fd = open(devname, O_RDONLY)) < 0) { return -1; } ioctl(fd, JSIOCGVERSION, &version); ioctl(fd, JSIOCGAXES, &numAxes); ioctl(fd, JSIOCGBUTTONS, &numButtons); ioctl(fd, JSIOCGNAME(JSNAMELEN), name); if (strcmp(name, steering_name) == 0) { setJsType(JS_TYPE_STEERING); DBG_NOTICE("JS_TYPE_STEERING type!"); } else { setJsType(JS_TYPE_GAME_CTL); DBG_NOTICE("JS_TYPE_GAME_CTL type!"); } for (i = 0; i < 6; i++) { int k = 0; cal[i].type = (__u16)calData[(i*6)+k]; k++; cal[i].prec = (__s16)calData[(i*6)+k]; k++; for(j = 0; j < 4; j++) { cal[i].coef[j] = (__s32)calData[(i*6)+k]; k++; } } if (ioctl(fd, JSIOCSCORR, &cal) < 0) { return -1; } axis = (int *)calloc(numAxes, sizeof(int)); button = (char *)calloc(numButtons, sizeof(char)); #if 0 gis = g_unix_input_stream_new(fd, TRUE); if(gis == NULL) { DBG_ERROR("g_unix_input_stream_new() failed!"); } else { NOTICEMSG("g_unix_input_stream_new() succeed!"); } g_input_stream_read_async(gis, &jsEvent, sizeof(struct js_event), G_PRIORITY_DEFAULT, NULL, &readCallback, NULL); #endif return fd; } void js_close(int js) { if (js < 0) { return; } close(js); } int init_timer() { struct sigaction act; struct itimerspec itval; memset(&act, 0, sizeof(struct sigaction)); memset(&oldact, 0, sizeof(struct sigaction)); act.sa_handler = updateTimerHandler; act.sa_flags = SA_RESTART; if(sigaction(SIGALRM, &act, &oldact) < 0) { DBG_ERROR("sigaction failed."); return -1; } itval.it_value.tv_sec = 0; itval.it_value.tv_nsec = 200000000; itval.it_interval.tv_sec = 0; itval.it_interval.tv_nsec = 200000000; if(timer_create(CLOCK_REALTIME, NULL, &tid) < 0) { DBG_ERROR("timer_create failed."); return -1; } if(timer_settime(tid, 0, &itval, NULL) < 0) { DBG_ERROR("timer_settime failed."); return -1; } return 0; } void deinit_timer() { timer_delete(tid); sigaction(SIGALRM, &oldact, NULL); }