00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "toolkits/media/joystick.h"
00023
00024 #if PLATAFORMA == i386_WIN32_VC
00025 #include <dinput.h>
00026 #include <assert.h>
00027 #include <malloc.h>
00028 #endif
00029
00030 #include <string.h>
00031 #include <stdlib.h>
00032
00033
00034
00035
00036
00037 #if PLATAFORMA == i386_WIN32_VC
00038
00039 static LONG WINAPI
00040 receptor_eventos_nulo(HWND w, UINT tipo_mensaje, UINT uParam, LONG lParam)
00043 {
00044 return DefWindowProc(w, tipo_mensaje, uParam, lParam);
00045 }
00046
00047 static HWND
00048 crear_ventana_joystick(void)
00049 {
00050 static int lista = 0;
00051 static HWND receptora = NULL;
00052
00053 if ( lista ) return receptora;
00054
00055
00056
00057
00058 WNDCLASS atributos_de_ventana = {
00059 CS_GLOBALCLASS,
00060 (WNDPROC)receptor_eventos_nulo,
00061 0,
00062 0,
00063 0,
00064 NULL,
00065 NULL,
00066 NULL,
00067 "",
00068 "AQUYNZA_JOYSTICK_event_handler"
00069 };
00070
00071 if ( !RegisterClass(&atributos_de_ventana) ) {
00072 fprintf(stderr, "ERROR: No puedo crear la clase!\n");
00073 fflush(stdout);
00074 return NULL;
00075 }
00076
00077
00078 receptora = CreateWindowEx(
00079 WS_EX_NOPARENTNOTIFY | WS_EX_TRANSPARENT,
00080
00081 "AQUYNZA_JOYSTICK_event_handler",
00082 "AQUYNZA JOYSTICK event handler",
00083 WS_ICONIC |
00084 WS_CAPTION | WS_MINIMIZEBOX |WS_MAXIMIZEBOX |
00085 WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
00086 0, 0, 10, 10,
00087 NULL,
00088 NULL,
00089 0,
00090 (LPVOID)NULL
00091 );
00092
00093 if ( !receptora ) {
00094 fprintf(stderr,
00095 "ERROR: No pudo crearse la ventana receptora de eventos!\n");
00096 fflush(stderr);
00097 }
00098
00099 lista = 1;
00100 ShowWindow(receptora, SW_SHOWDEFAULT);
00101 return receptora;
00102 }
00103
00104 #endif
00105
00106
00107
00108
00109
00110 #ifndef JOYSTICK_ENABLED
00111 JOYSTICK::JOYSTICK(char *)
00112 {
00113 fprintf(stderr, "<JOYSTICK> - ERROR: No soportado en esta plataforma!\n");
00114 exit(-1);
00115 }
00116
00117 JOYSTICK::~JOYSTICK()
00118 {
00119 ;
00120 }
00121
00122 BOOLEAN
00123 JOYSTICK::abrir(void)
00124 {
00125 return FALSE;
00126 }
00127
00128 void
00129 JOYSTICK::cerrar(void)
00130 {
00131 ;
00132 }
00133
00134 void
00135 JOYSTICK::consultar(double *, double *, int *)
00136 {
00137 ;
00138 }
00139
00140 void
00141 JOYSTICK::calibrar(void)
00142 {
00143 ;
00144 }
00145
00146 void
00147 JOYSTICK::actualizar(void)
00148 {
00149 ;
00150 }
00151
00152 BOOLEAN
00153 JOYSTICK::consultar_variable(const char *, int &, void **)
00154 {
00155 return FALSE;
00156 }
00157
00158 #endif
00159
00160 #ifdef JOYSTICK_ENABLED
00161
00162 JOYSTICK::JOYSTICK(
00163 #ifdef UNIX_ENABLED
00164 char *filename
00165 #endif
00166 #if PLATAFORMA == i386_WIN32_VC
00167 char *
00168 #endif
00169 )
00170 {
00171 #if PLATAFORMA == i386_LINUX_GCC || PLATAFORMA == SPARC64_LINUX_GCC
00172 archivo = filename;
00173 fd = -1;
00174 #endif
00175
00176 #if PLATAFORMA == i386_WIN32_VC
00177 fd_device = NULL;
00178 direct_input_object = NULL;
00179 gui_valido = FALSE;
00180 #endif
00181
00182 fx = fy = 0;
00183 }
00184
00185 JOYSTICK::~JOYSTICK()
00186 {
00187 cerrar();
00188 }
00189
00190
00191 BOOLEAN
00192 JOYSTICK::abrir(void)
00193 {
00194 #if PLATAFORMA == i386_LINUX_GCC || PLATAFORMA == SPARC64_LINUX_GCC
00195 fd = open (archivo, O_RDONLY);
00196 if ( fd < 0 ) {
00197 fprintf(stderr, "<JOYSTICK> ERROR - Joystick no encontrado.\n");
00198 fflush(stderr);
00199 return FALSE;
00200 }
00201 #endif
00202
00203 #ifndef CBUILDER
00204 #if PLATAFORMA == i386_WIN32_VC
00205 HWND hwndApp = crear_ventana_joystick();
00206 HRESULT hResult;
00207 cerrar();
00208
00209
00210 hResult = DirectInputCreate(i386_WIN32_VC_instancia_actual, DIRECTINPUT_VERSION, &direct_input_object, NULL);
00211 if (FAILED(hResult))
00212 return FALSE;
00213
00214
00215
00216 hResult = direct_input_object->EnumDevices(
00217 DIDEVTYPE_JOYSTICK,
00218 (LPDIENUMDEVICESCALLBACK)device_callback,
00219 this,
00220 DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK
00221 );
00222 if (FAILED(hResult))
00223 return FALSE;
00224
00225 if (!gui_valido) {
00226
00227 hResult = direct_input_object->EnumDevices(
00228 DIDEVTYPE_JOYSTICK,
00229 (LPDIENUMDEVICESCALLBACK)device_callback,
00230 this,
00231 DIEDFL_ATTACHEDONLY
00232 );
00233
00234 if (FAILED(hResult))
00235 return FALSE;
00236 }
00237
00238
00239 if (!gui_valido)
00240 return FALSE;
00241
00242 LPDIRECTINPUTDEVICE lpDIDevice = NULL;
00243
00244
00245 hResult = direct_input_object->CreateDevice(guid, &lpDIDevice, NULL);
00246 if (FAILED(hResult)) {
00247 fd_device = NULL;
00248 return FALSE;
00249 }
00250
00251
00252 hResult = lpDIDevice->QueryInterface(IID_IDirectInputDevice2, (LPVOID *)&fd_device);
00253 if (FAILED(hResult))
00254 return FALSE;
00255
00256
00257 hResult = fd_device->SetDataFormat(&c_dfDIJoystick);
00258 if (FAILED(hResult))
00259 return FALSE;
00260
00261 hResult = fd_device->SetCooperativeLevel(
00262 hwndApp,
00263 DISCL_EXCLUSIVE | DISCL_BACKGROUND);
00264 if (FAILED(hResult))
00265 return FALSE;
00266
00267
00268 hResult = fd_device->Acquire();
00269 if (FAILED(hResult)){
00270 fd_device->Release();
00271 direct_input_object->Release();
00272 return FALSE;
00273 }
00274
00275
00276 DIDEVICEINSTANCE didi;
00277 didi.dwSize = sizeof DIDEVICEINSTANCE;
00278 fd_device->GetDeviceInfo(&didi);
00279
00280 printf("%s encontrado!\n", didi.tszProductName); fflush(stdout);
00281 set_gain(50 );
00282
00283
00284 DIPROPRANGE diprg;
00285 diprg.diph.dwSize = sizeof(diprg);
00286 diprg.diph.dwHeaderSize = sizeof(diprg.diph);
00287 diprg.diph.dwObj = DIJOFS_X;
00288 diprg.diph.dwHow = DIPH_BYOFFSET;
00289 diprg.lMin = -1000;
00290 diprg.lMax = +1000;
00291
00292 fd_device->SetProperty(DIPROP_RANGE, &diprg.diph);
00293
00294
00295 diprg.diph.dwSize = sizeof(diprg);
00296 diprg.diph.dwHeaderSize = sizeof(diprg.diph);
00297 diprg.diph.dwObj = DIJOFS_Y;
00298 diprg.diph.dwHow = DIPH_BYOFFSET;
00299 diprg.lMin = -1000;
00300 diprg.lMax = +1000;
00301
00302 fd_device->SetProperty(DIPROP_RANGE, &diprg.diph);
00303
00304 #endif // i386_WIN32_VC
00305
00306 #endif // CBUILDER
00307
00308 return TRUE;
00309 }
00310
00311 void
00312 JOYSTICK::cerrar(void)
00313 {
00314 #if PLATAFORMA == i386_LINUX_GCC || PLATAFORMA == SPARC64_LINUX_GCC
00315 close(fd);
00316 #endif
00317
00318 #if PLATAFORMA == i386_WIN32_VC
00319 if (fd_device != NULL) {
00320 fd_device->Unacquire();
00321 fd_device->Release();
00322 fd_device = NULL;
00323 }
00324 if (direct_input_object != NULL) {
00325 direct_input_object->Release();
00326 direct_input_object = NULL;
00327 }
00328 #endif
00329 }
00330
00331 void
00332 JOYSTICK::consultar(double *x, double *y, int *botones)
00333 {
00334 actualizar();
00335 (*x) = fx;
00336 (*y) = fy;
00337 (*botones) = fbotones;
00338 }
00339
00340 void
00341 JOYSTICK::actualizar(void)
00342 {
00343 #if PLATAFORMA == i386_LINUX_GCC || PLATAFORMA == SPARC64_LINUX_GCC
00344 if ( fd < 0 ) return;
00345
00346 status = read(fd, &lowlevel_data, JS_RETURN);
00347 if ( status != JS_RETURN ) {
00348 fprintf(stderr, "<JOYSTICK> ERROR leyendo datos.\n");
00349 fflush(stderr);
00350 exit(-1);
00351 }
00352
00353 fx = (((double)(lowlevel_data.x-64))/128) - 0.5;
00354 fy = 0.5 - (((double)(lowlevel_data.y-64))/128);
00355 fbotones = lowlevel_data.buttons;
00356 #endif
00357
00358 #if PLATAFORMA == i386_WIN32_VC
00359 fx = 0;
00360 fy = 0;
00361 fbotones = 0x0;
00362
00363 HRESULT hr ;
00364 DIJOYSTATE diJoyState ;
00365
00366
00367 if( !fd_device ) return;
00368
00369
00370 hr = fd_device->Poll() ;
00371 if( hr== DIERR_INPUTLOST || hr== DIERR_NOTACQUIRED ) {
00372
00373 fd_device->Acquire() ;
00374
00375
00376 hr = fd_device->Poll() ;
00377 }
00378 if( FAILED(hr) ) return;
00379
00380
00381 if( FAILED(fd_device->GetDeviceState( sizeof(DIJOYSTATE),
00382 & diJoyState)) ) {
00383 return;
00384 }
00385
00386 int i;
00387 fbotones = 0x0;
00388 for ( i = 0; i < 8; i++ ) {
00389 if ( diJoyState.rgbButtons[i] ) {
00390 fbotones |= (0x01 << i);
00391 }
00392 }
00393 fx = (double)diJoyState.lX / 1000;
00394 fy = (double)diJoyState.lY / 1000;
00395 fy *= -1;
00396 #endif
00397 }
00398
00399 static double TMP_double;
00400
00401 BOOLEAN
00402 JOYSTICK::consultar_variable(const char *nombre_variable, int &tipo, void **ref)
00403 {
00404 tipo = T_FLOAT;
00405 if ( strcmp(nombre_variable, "x") == 0 ) {
00406 TMP_double = fx;
00407 (*ref) = &TMP_double;
00408 }
00409 else if ( strcmp(nombre_variable, "y") == 0 ) {
00410 TMP_double = fy;
00411 (*ref) = &TMP_double;
00412 }
00413 else if ( strcmp(nombre_variable, "x1") == 0 ) {
00414
00415 if ( !fbotones ) TMP_double = fx; else TMP_double = 0;
00416 (*ref) = &TMP_double;
00417 }
00418 else if ( strcmp(nombre_variable, "y1") == 0 ) {
00419
00420 if ( !fbotones ) TMP_double = fy; else TMP_double = 0;
00421 (*ref) = &TMP_double;
00422 }
00423 else if ( strcmp(nombre_variable, "x2") == 0 ) {
00424
00425 if ( fbotones == 0x01 ) TMP_double = fx; else TMP_double = 0;
00426 (*ref) = &TMP_double;
00427 }
00428 else if ( strcmp(nombre_variable, "y2") == 0 ) {
00429
00430 if ( fbotones == 0x01 ) TMP_double = fy; else TMP_double = 0;
00431 (*ref) = &TMP_double;
00432 }
00433 else if ( strcmp(nombre_variable, "x3") == 0 ) {
00434
00435 if ( fbotones == 0x02 ) TMP_double = fx; else TMP_double = 0;
00436 (*ref) = &TMP_double;
00437 }
00438 else if ( strcmp(nombre_variable, "y3") == 0 ) {
00439
00440 if ( fbotones == 0x02 ) TMP_double = fy; else TMP_double = 0;
00441 (*ref) = &TMP_double;
00442 }
00443 else if ( strcmp(nombre_variable, "x4") == 0 ) {
00444
00445 if ( fbotones == 0x03 ) TMP_double = fx; else TMP_double = 0;
00446 (*ref) = &TMP_double;
00447 }
00448 else if ( strcmp(nombre_variable, "y4") == 0 ) {
00449
00450 if ( fbotones == 0x03 ) TMP_double = fy; else TMP_double = 0;
00451 (*ref) = &TMP_double;
00452 }
00453 else {
00454 return FALSE;
00455 }
00456 ;
00457 return TRUE;
00458 }
00459
00460 #define CHECK() if (status == -1) { perror ("jscal"); exit (1); }
00461
00462 void
00463 JOYSTICK::calibrar(void)
00464 {
00465 #if PLATAFORMA == i386_LINUX_GCC || PLATAFORMA == SPARC64_LINUX_GCC
00466 int tmp;
00467 long tmpl;
00468
00469 printf (
00470 "Mueva el joystick a la esquina superior izquierda y oprima un boton\n");
00471 while ( (read (fd, &lowlevel_data, JS_RETURN) > 0) &&
00472 lowlevel_data.buttons == 0x00 );
00473 while ( (read (fd, &lowlevel_data, JS_RETURN) > 0) &&
00474 lowlevel_data.buttons != 0x00 );
00475
00476 status = ioctl(fd, JS_GET_TIMEOUT, &tmp); CHECK();
00477
00478
00479 status = ioctl(fd, JS_GET_TIMELIMIT, &tmpl); CHECK();
00480
00481
00482
00483 tmpl = 10;
00484 status = ioctl (fd, JS_SET_TIMELIMIT, &tmpl); CHECK();
00485
00486 status = ioctl (fd, JS_GET_CAL, &lowlevel_data); CHECK();
00487
00488
00489 printf (
00490 "Mueva el joystick a la esquina inferior derecha y oprima un boton\n");
00491 while ( (read (fd, &lowlevel_data, JS_RETURN) > 0) &&
00492 lowlevel_data.buttons == 0x00 );
00493
00494 for ( tmp = 0; lowlevel_data.x > 0xff;
00495 tmp++, lowlevel_data.x = lowlevel_data.x >> 1 );
00496 lowlevel_data.x = tmp;
00497 for ( tmp = 0; lowlevel_data.y > 0xff;
00498 tmp++, lowlevel_data.y = lowlevel_data.y >> 1 );
00499 lowlevel_data.y = tmp;
00500
00501
00502 status = ioctl (fd, JS_SET_CAL, &lowlevel_data); CHECK();
00503
00504 status = ioctl (fd, JS_GET_CAL, &lowlevel_data); CHECK();
00505
00506
00507
00508 printf("<JOYSTICK>: Calibracion terminada con exito.\n");
00509 fflush(stdout);
00510 #endif
00511 }
00512
00513 #if PLATAFORMA == i386_WIN32_VC
00514
00515 BOOLEAN
00516 JOYSTICK::set_gain(int gain)
00517 {
00518 if ( ! direct_input_object || ! fd_device )
00519 return FALSE;
00520
00521 if ( (gain < 0) || (gain > 100) )
00522 return FALSE;
00523
00524
00525 DIPROPDWORD propGain;
00526 propGain.diph.dwSize = sizeof propGain;
00527 propGain.diph.dwHeaderSize = sizeof propGain.diph;
00528 propGain.diph.dwHow = DIPH_DEVICE;
00529 propGain.diph.dwObj = 0;
00530 propGain.dwData = 100 * gain;
00531
00532 HRESULT hRes = fd_device->SetProperty(DIPROP_FFGAIN, &propGain.diph);
00533 if (FAILED(hRes))
00534 return FALSE;
00535
00536 return TRUE;
00537 }
00538
00539 #ifndef CBUILDER
00540 BOOLEAN
00541 JOYSTICK::device_callback(LPDIDEVICEINSTANCE pdidi, LPVOID pv)
00542 {
00543
00544
00545
00546
00547
00548 ((JOYSTICK *)pv)->guid = pdidi->guidInstance;
00549 ((JOYSTICK *)pv)->gui_valido = TRUE;
00550
00551 return DIENUM_STOP;
00552 }
00553 #endif
00554
00555 #endif // i386_WIN32_VC
00556
00557 #endif // JOYSTICK_ENABLED
00558
00559
00560
00561
00562