'linux joystick'에 해당되는 글 2건

  1. 2012.02.05 linux/joystick.h 파일
  2. 2012.02.04 리눅스에서 조이스틱 값 읽어오기
Linux API/joystick2012. 2. 5. 11:36
조이스틱 관련 구조체 및 매크로 내용
우분투 기준 /usr/include/linux/joystick.h 에 존재함.

#ifndef _LINUX_JOYSTICK_H
#define _LINUX_JOYSTICK_H

/*
 *  Copyright (C) 1996-2000 Vojtech Pavlik
 *
 *  Sponsored by SuSE
 */

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or 
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 * 
 * Should you need to contact me, the author, you can do so either by
 * e-mail - mail your message to vojtech@suse.cz, or by paper mail:
 * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
 */

#include "linux/types.h"
#include "linux/input.h"

/*
 * Version
 */

#define JS_VERSION		0x020100

/*
 * Types and constants for reading from /dev/js
 */

#define JS_EVENT_BUTTON		0x01	/* button pressed/released */
#define JS_EVENT_AXIS		0x02	/* joystick moved */
#define JS_EVENT_INIT		0x80	/* initial state of device */

struct js_event {
	__u32 time;	/* event timestamp in milliseconds */
	__s16 value;	/* value */
	__u8 type;	/* event type */
	__u8 number;	/* axis/button number */
};

/*
 * IOCTL commands for joystick driver
 */

#define JSIOCGVERSION		_IOR('j', 0x01, __u32)				/* get driver version */

#define JSIOCGAXES		_IOR('j', 0x11, __u8)				/* get number of axes */
#define JSIOCGBUTTONS		_IOR('j', 0x12, __u8)				/* get number of buttons */
#define JSIOCGNAME(len)		_IOC(_IOC_READ, 'j', 0x13, len)			/* get identifier string */

#define JSIOCSCORR		_IOW('j', 0x21, struct js_corr)			/* set correction values */
#define JSIOCGCORR		_IOR('j', 0x22, struct js_corr)			/* get correction values */

#define JSIOCSAXMAP		_IOW('j', 0x31, __u8[ABS_MAX + 1])		/* set axis mapping */
#define JSIOCGAXMAP		_IOR('j', 0x32, __u8[ABS_MAX + 1])		/* get axis mapping */
#define JSIOCSBTNMAP		_IOW('j', 0x33, __u16[KEY_MAX - BTN_MISC + 1])	/* set button mapping */
#define JSIOCGBTNMAP		_IOR('j', 0x34, __u16[KEY_MAX - BTN_MISC + 1])	/* get button mapping */

/*
 * Types and constants for get/set correction
 */

#define JS_CORR_NONE		0x00	/* returns raw values */
#define JS_CORR_BROKEN		0x01	/* broken line */

struct js_corr {
	__s32 coef[8];
	__s16 prec;
	__u16 type;
};

/*
 * v0.x compatibility definitions
 */

#define JS_RETURN		sizeof(struct JS_DATA_TYPE)
#define JS_TRUE			1
#define JS_FALSE		0
#define JS_X_0			0x01
#define JS_Y_0			0x02
#define JS_X_1			0x04
#define JS_Y_1			0x08
#define JS_MAX			2

#define JS_DEF_TIMEOUT		0x1300
#define JS_DEF_CORR		0
#define JS_DEF_TIMELIMIT	10L

#define JS_SET_CAL		1
#define JS_GET_CAL		2
#define JS_SET_TIMEOUT		3
#define JS_GET_TIMEOUT		4
#define JS_SET_TIMELIMIT	5
#define JS_GET_TIMELIMIT	6
#define JS_GET_ALL		7
#define JS_SET_ALL		8

struct JS_DATA_TYPE {
	__s32 buttons;
	__s32 x;
	__s32 y;
};

struct JS_DATA_SAVE_TYPE_32 {
	__s32 JS_TIMEOUT;
	__s32 BUSY;
	__s32 JS_EXPIRETIME;
	__s32 JS_TIMELIMIT;
	struct JS_DATA_TYPE JS_SAVE;
	struct JS_DATA_TYPE JS_CORR;
};

struct JS_DATA_SAVE_TYPE_64 {
	__s32 JS_TIMEOUT;
	__s32 BUSY;
	__s64 JS_EXPIRETIME;
	__s64 JS_TIMELIMIT;
	struct JS_DATA_TYPE JS_SAVE;
	struct JS_DATA_TYPE JS_CORR;
};


#endif /* _LINUX_JOYSTICK_H */


실험적으로 소스를 짜서 해보니
버튼은 type 1
value는 0(눌리지 않음) 1(눌림)
number는 버튼 번호(1번 버튼은 0번 부터 시작)

X/Y/Z 축은 type 2
좌우는 number 0
앞뒤는 number 1
쓰로틀은 number 2
러더는 number 3 
햇좌우 number 5
햇앞뒤 number 6
 
값이 변하기 전에는 새로운 값은 읽히지 않는 듯 하고,
그런 이유로 예제 파일이 멀티쓰레드로 구성이 된 것으로 생각된다. 

'Linux API > joystick' 카테고리의 다른 글

linux force feedback  (0) 2022.06.15
리눅스에서 조이스틱 값 읽어오기  (0) 2012.02.04
Posted by 구차니
Linux API/joystick2012. 2. 4. 14:37
CCTV(PTZ) 업체에 있다 보니 리눅스에서도 조이스틱을 이용해서
컨트롤러를 대체할수 있을까 라는 생각에 조이스틱 관련 API를 찾아보는데
의외로 단순한 구조 같은 느낌..

요즘에는 USB로도 많이 쓰니 USB목록에서 장치명을 찾아서 열거하는 것도 필요할 듯 하고
아무튼 중요한건 js_event 구조체 이녀석인듯.
int fd = open ("/dev/js0", O_RDONLY);
struct js_event e;
read (fd, &e, sizeof(struct js_event));

struct js_event {
__u32 time;     /* event timestamp in milliseconds */
__s16 value;    /* value */
__u8 type;      /* event type */
__u8 number;    /* axis/button number */
}; 

[링크 : http://www.mjmwired.net/kernel/Documentation/input/joystick-api.txt] 3.2 kernel
[링크 :  http://archives.seul.org/linuxgames/Aug-1999/msg00107.html] 2.2 kernel

----
curse.h가 없다고 에러날 경우는 아래와 같이 설치해주고
$ sudo apt-get install libncurses5-dev  

소스는 이런식으로 수정하고 컴파일을 하면된다.
#define JOY_DEV "/dev/input/js0"  

#include "pthread.h"
#include "sys/timeb.h"
#include "curses.h"
#include "fcntl.h"
#include "linux/joystick.h"

#define NUM_THREADS	3
#define JOY_DEV		"/dev/input/js0"
#define HZ				12

const char FILENAME[] = "./joystickLog.out";
char axisDesc[15][5] = {"X", "Y", "Z", "R", "A", "B", "C", "D", "E", "F", "G", "H", "I" };
char numAxis[20], numButtons[20], value[20][20], timeSec[20], timeMilli[20];
int num_of_axis;

void write_to_log(){
	sleep(1);
	int cnt;
	FILE * daFile;
	daFile = fopen(FILENAME, "w+");

//	WRITE A HEADER ON THE OUPUT FILE
	fprintf(daFile, "#,");
	for(cnt = 0; cnt < num_of_axis; cnt++)
		if(cnt < num_of_axis -1)	fprintf(daFile, "%s,", axisDesc[cnt]);
		else								fprintf(daFile, "%s", axisDesc[cnt]);
	fprintf(daFile, "\r\n");

	while(1){
		fprintf(daFile, "%s.%s, ", timeSec, timeMilli);
		for(cnt = 0; cnt < num_of_axis; cnt++){
			if(cnt < num_of_axis -1)	fprintf(daFile, "%s, ", value[cnt]);
			else								fprintf(daFile, "%s ", value[cnt]);
		}
		fprintf(daFile, "\r\n");
		usleep(83333);
	}
	
	fprintf(daFile, "%s.%s Len = %d ", timeSec, timeMilli,strlen(timeMilli));

	fprintf(daFile, "\r\n");
	fflush(daFile);
}

void write_to_screen(){
	struct timeb seconds;
	int cnt, joy_fd, *axis=NULL, num_of_buttons=0, x;
	char *button=NULL, name_of_joystick[80];
	struct js_event js;
	time_t theTime;

	wmove(stdscr, 8, 0);
	addstr("Type \"q\" to quit.\n");

	if( ( joy_fd = open( JOY_DEV , O_RDONLY)) == -1 ){
		wmove(stdscr, 3,0);
		addstr( "Couldn't open joystick " );
		addstr( JOY_DEV );
		wmove(stdscr, 10,0);
		while(1)usleep(16666);
	}

	ioctl( joy_fd, JSIOCGAXES, &num_of_axis );				//	GET THE NUMBER OF AXIS ON JS
	ioctl( joy_fd, JSIOCGBUTTONS, &num_of_buttons );		//	GET THE NUMBER OF BUTTONS ON THE JS
	ioctl( joy_fd, JSIOCGNAME(80), &name_of_joystick );	//	GET THE NAME OF THE JS

	axis = (int *) calloc( num_of_axis, sizeof( int ) );
	button = (char *) calloc( num_of_buttons, sizeof( char ) );

	sprintf(numAxis, "%d", num_of_axis);
	sprintf(numButtons, "%d", num_of_buttons);

	wmove(stdscr, 0,0);
	addstr("Joystick detected: ");

	wmove(stdscr, 0, 19);
	addstr(name_of_joystick);

	wmove(stdscr, 1, 0);
	addstr("Number of axis   :");

	wmove(stdscr, 1, 19);
	addstr(numAxis);
	
	wmove(stdscr, 2, 0);
	addstr("Number of buttons:");

	wmove (stdscr, 2, 19);
	addstr(numButtons);

//	CHANGE THE STATUS FLAG OF THE FILE DESCRIPTOR TO NON-BLOCKING MODE
	fcntl( joy_fd, F_SETFL, O_NONBLOCK );   

	while( 1 ){
		usleep(16666);
	
	//	READ THE JOYSTICK STATE, IT WILL BE RETURNED IN THE JS_EVENT STRUCT
		read(joy_fd, &js, sizeof(struct js_event));

	//	GET THE NUMBER OF SECONDS SINCE EPOCH
		ftime(&seconds);
		theTime = time(NULL);
		sprintf(timeSec, "%d", seconds.time);						
		sprintf(timeMilli, "%d", seconds.millitm);
               
	//	CHECK THE EVENT
		switch (js.type & ~JS_EVENT_INIT){
			case JS_EVENT_AXIS:
				axis   [ js.number ] = js.value;
				break;
			case JS_EVENT_BUTTON:
				button [ js.number ] = js.value;
				break;
		}
		//	ADD LEADING 0'S TO THE MILLISECOND STRING (IF NECESSARY)
			char temp[10] = "";
			while(strlen(temp) < (3 - strlen(timeMilli)))
				strcat(temp, "0");
			strcat(temp,timeMilli);
			strcpy(timeMilli, temp);

		//	PRINT THE RESULTS
			wmove(stdscr, 4, 0);
			for(cnt = 0; cnt < num_of_axis; cnt++)
				addstr("            ");
			for(cnt = 0; cnt < num_of_axis && cnt < 13; cnt++){
				sprintf(value[cnt], "%d", axis[cnt]);
				wmove(stdscr, 4, cnt * 10);
				addstr(axisDesc[cnt]);
				addstr(": ");
				wmove(stdscr, 4, (cnt * 10) + 2);
				addstr(value[cnt]);
			}
			
			wmove(stdscr, 6, 0);
			addstr(timeSec);
			wmove(stdscr, 6,10);
			addstr(".");
			wmove(stdscr, 6, 11);
			addstr(timeMilli);
			wmove(stdscr, 6, 15);
			addstr("=");
			wmove(stdscr, 6, 17);
			addstr(ctime(&theTime));
                       
			wmove(stdscr, 10, 0);
			refresh();
	}
}

void *ThreadProcs(void *threadid){
	int thread_id = (int)threadid;
	
	if(thread_id == 0){
		write_to_screen();
	}
	
	if(thread_id == 1){
	//	THIS THREAD WILL MAKE THE PROGRAM EXIT
		int ch;
		nodelay(stdscr, TRUE);				//	SETUP NON BLOCKING INPUT
		while(1) {
			if ((ch = getch()) == ERR) usleep(16666);		//	USER HASN'T RESPONDED
			else if( ch == 'q'){			
				endwin();
				exit(0);			//	QUIT ALL THREADS
			}
		}
	}
	if(thread_id == 2){
		write_to_log();
	}
}

int main(int argc, char *argv[]){
	initscr(); 									//	INIT THE SCREEN FOR CURSES
	pthread_t threads[NUM_THREADS];
	int rc, t;
	for(t = 0; t < NUM_THREADS; t++){	//	MAKE 2 NEW THREADS
		rc = pthread_create(&threads[t], NULL, ThreadProcs, (void *)t);
		if (rc){
			printf("ERROR; return code from pthread_create() is %d\n", rc);
			exit(-1);pthread_exit(NULL);
		}
	}
	
	for(t = 0; t < NUM_THREADS; t++)
		pthread_join(threads[t], NULL);		//	WAIT FOR THREADS TO EXIT OR IT WILL RACE TO HERE.

	endwin();
	return 0;
}


[링크 : http://www.linuxquestions.org/questions/programming-9/joystick-347292/]
 + [링크 : http://sukwoo.blogspot.com/2008/07/ubuntu-804-ncurses.html]
---
[링크 : http://msdn.microsoft.com/en-us/library/windows/desktop/dd743596(v=vs.85).aspx] << 윈도우용

'Linux API > joystick' 카테고리의 다른 글

linux force feedback  (0) 2022.06.15
linux/joystick.h 파일  (0) 2012.02.05
Posted by 구차니