1 /* 2 * Copyright 2002-2008, Marcus Overhagen, Stefano Ceccherini, Fredrik Modéen. 3 * All rights reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <Joystick.h> 9 #include <JoystickTweaker.h> 10 11 #include <new> 12 13 #include <errno.h> 14 #include <fcntl.h> 15 #include <stdio.h> 16 17 #include <sys/ioctl.h> 18 19 #include <Debug.h> 20 #include <Directory.h> 21 #include <List.h> 22 #include <Path.h> 23 #include <String.h> 24 25 26 #if DEBUG 27 static FILE *sLogFile = NULL; 28 29 inline void 30 LOG(const char *fmt, ...) 31 { 32 char buf[1024]; 33 va_list ap; 34 va_start(ap, fmt); 35 vsprintf(buf, fmt, ap); 36 va_end(ap); 37 fputs(buf, sLogFile); fflush(sLogFile); 38 } 39 40 # define LOG_ERR(text...) LOG(text) 41 42 #else 43 # define LOG(text...) 44 # define LOG_ERR(text...) fprintf(stderr, text) 45 #endif 46 47 #define CALLED() LOG("%s\n", __PRETTY_FUNCTION__) 48 49 50 BJoystick::BJoystick() 51 : 52 // legacy members for standard mode 53 timestamp(0), 54 horizontal(0), 55 vertical(0), 56 button1(0), 57 button2(0), 58 59 fBeBoxMode(false), 60 fFD(-1), 61 fDevices(new(std::nothrow) BList), 62 fJoystickInfo(new(std::nothrow) joystick_info), 63 fExtendedJoystick(new(std::nothrow) BList) 64 { 65 #if DEBUG 66 sLogFile = fopen("/var/log/joystick.log", "a"); 67 #endif 68 69 if (fJoystickInfo != NULL) 70 memset(fJoystickInfo, 0, sizeof(joystick_info)); 71 72 RescanDevices(); 73 } 74 75 76 BJoystick::~BJoystick() 77 { 78 if (fFD >= 0) 79 close(fFD); 80 81 if (fDevices != NULL) { 82 for (int32 i = 0; i < fDevices->CountItems(); i++) 83 delete (BString *)fDevices->ItemAt(i); 84 85 delete fDevices; 86 } 87 88 delete fJoystickInfo; 89 90 if (fExtendedJoystick != NULL) { 91 for (int32 i = 0; i < fExtendedJoystick->CountItems(); i++) 92 delete (extended_joystick *)fExtendedJoystick->ItemAt(i); 93 94 delete fExtendedJoystick; 95 } 96 } 97 98 99 status_t 100 BJoystick::Open(const char *portName) 101 { 102 CALLED(); 103 return Open(portName, true); 104 } 105 106 107 status_t 108 BJoystick::Open(const char *portName, bool enhanced) 109 { 110 CALLED(); 111 112 if (portName == NULL) 113 return B_BAD_VALUE; 114 115 if (fJoystickInfo == NULL || fExtendedJoystick == NULL) 116 return B_NO_INIT; 117 118 fBeBoxMode = !enhanced; 119 120 char nameBuffer[64]; 121 if (portName[0] != '/') { 122 snprintf(nameBuffer, sizeof(nameBuffer), DEVICE_BASE_PATH"/%s", 123 portName); 124 } else 125 snprintf(nameBuffer, sizeof(nameBuffer), "%s", portName); 126 127 if (fFD >= 0) 128 close(fFD); 129 130 // TODO: BeOS don't use O_EXCL, and this seems to lead to some issues. I 131 // added this flag having read some comments by Marco Nelissen on the 132 // annotated BeBook. I think BeOS uses O_RDWR|O_NONBLOCK here. 133 fFD = open(nameBuffer, O_RDWR | O_NONBLOCK | O_EXCL); 134 135 if (fFD >= 0) { 136 // we used open() with O_NONBLOCK flag to let it return immediately, 137 // but we want read/write operations to block if needed, so we clear 138 // that bit here. 139 int flags = fcntl(fFD, F_GETFL); 140 fcntl(fFD, F_SETFL, flags & ~O_NONBLOCK); 141 142 // read the Joystick Description file for this port/joystick 143 _BJoystickTweaker joystickTweaker(*this); 144 joystickTweaker.GetInfo(fJoystickInfo, portName); 145 146 LOG("ioctl - %d\n", fJoystickInfo->module_info.num_buttons); 147 ioctl(fFD, B_JOYSTICK_SET_DEVICE_MODULE, &fJoystickInfo->module_info, 148 sizeof(joystick_module_info)); 149 ioctl(fFD, B_JOYSTICK_GET_DEVICE_MODULE, &fJoystickInfo->module_info, 150 sizeof(joystick_module_info)); 151 LOG("ioctl - %d\n", fJoystickInfo->module_info.num_buttons); 152 153 // Allocate the extended_joystick structures to hold the info for each 154 // "stick". Note that the whole num_sticks thing seems a bit bogus, as 155 // all sticks would be required to have exactly the same attributes, 156 // i.e. axis, hat and button counts, since there is only one global 157 // joystick_info for the whole device. What's implemented here is a 158 // "best guess", using the read position in Update() to select the 159 // stick for which an extended_joystick structure shall be returned. 160 for (uint16 i = 0; i < fJoystickInfo->module_info.num_sticks; i++) { 161 extended_joystick *extendedJoystick 162 = new(std::nothrow) extended_joystick; 163 if (extendedJoystick == NULL) 164 return B_NO_MEMORY; 165 166 if (!fExtendedJoystick->AddItem(extendedJoystick)) { 167 delete extendedJoystick; 168 return B_NO_MEMORY; 169 } 170 } 171 172 return fFD; 173 } else 174 return errno; 175 } 176 177 178 void 179 BJoystick::Close(void) 180 { 181 CALLED(); 182 if (fFD >= 0) { 183 close(fFD); 184 fFD = -1; 185 } 186 } 187 188 189 void 190 BJoystick::ScanDevices(bool useDisabled) 191 { 192 CALLED(); 193 if (useDisabled) { 194 _BJoystickTweaker joystickTweaker(*this); 195 joystickTweaker.scan_including_disabled(); 196 } 197 } 198 199 200 int32 201 BJoystick::CountDevices() 202 { 203 CALLED(); 204 205 if (fDevices == NULL) 206 return 0; 207 208 int32 count = fDevices->CountItems(); 209 210 LOG("Count = %d\n", count); 211 return count; 212 } 213 214 215 status_t 216 BJoystick::GetDeviceName(int32 index, char *name, size_t bufSize) 217 { 218 CALLED(); 219 if (fDevices == NULL) 220 return B_NO_INIT; 221 222 if (index >= fDevices->CountItems()) 223 return B_BAD_INDEX; 224 225 if (name == NULL) 226 return B_BAD_VALUE; 227 228 BString *deviceName = (BString *)fDevices->ItemAt(index); 229 if (deviceName->Length() > (int32)bufSize) 230 return B_NAME_TOO_LONG; 231 232 strlcpy(name, deviceName->String(), bufSize); 233 LOG("Device Name = %s\n", name); 234 return B_OK; 235 } 236 237 238 status_t 239 BJoystick::RescanDevices() 240 { 241 CALLED(); 242 243 if (fDevices == NULL) 244 return B_NO_INIT; 245 246 ScanDevices(true); 247 return B_OK; 248 } 249 250 251 bool 252 BJoystick::EnterEnhancedMode(const entry_ref *ref) 253 { 254 CALLED(); 255 fBeBoxMode = false; 256 return !fBeBoxMode; 257 } 258 259 260 int32 261 BJoystick::CountSticks() 262 { 263 CALLED(); 264 if (fJoystickInfo == NULL) 265 return 0; 266 267 return fJoystickInfo->module_info.num_sticks; 268 } 269 270 271 int32 272 BJoystick::CountAxes() 273 { 274 CALLED(); 275 if (fJoystickInfo == NULL) 276 return 0; 277 278 return fJoystickInfo->module_info.num_axes; 279 } 280 281 282 int32 283 BJoystick::CountHats() 284 { 285 CALLED(); 286 if (fJoystickInfo == NULL) 287 return 0; 288 289 return fJoystickInfo->module_info.num_hats; 290 } 291 292 293 int32 294 BJoystick::CountButtons() 295 { 296 CALLED(); 297 if (fJoystickInfo == NULL) 298 return 0; 299 300 return fJoystickInfo->module_info.num_buttons; 301 } 302 303 304 status_t 305 BJoystick::GetControllerModule(BString *outName) 306 { 307 CALLED(); 308 if (fJoystickInfo == NULL || fFD < 0) 309 return B_NO_INIT; 310 311 if (outName == NULL) 312 return B_BAD_VALUE; 313 314 outName->SetTo(fJoystickInfo->module_info.module_name); 315 return B_OK; 316 } 317 318 319 status_t 320 BJoystick::GetControllerName(BString *outName) 321 { 322 CALLED(); 323 if (fJoystickInfo == NULL || fFD < 0) 324 return B_NO_INIT; 325 326 if (outName == NULL) 327 return B_BAD_VALUE; 328 329 outName->SetTo(fJoystickInfo->module_info.device_name); 330 return B_OK; 331 } 332 333 334 bool 335 BJoystick::IsCalibrationEnabled() 336 { 337 CALLED(); 338 if (fJoystickInfo == NULL) 339 return false; 340 341 return fJoystickInfo->calibration_enable; 342 } 343 344 345 status_t 346 BJoystick::EnableCalibration(bool calibrates) 347 { 348 CALLED(); 349 if (fJoystickInfo == NULL || fFD < 0) 350 return B_NO_INIT; 351 352 status_t result = ioctl(fFD, B_JOYSTICK_SET_RAW_MODE, &calibrates, 353 sizeof(calibrates)); 354 if (result == B_OK) 355 fJoystickInfo->calibration_enable = calibrates; 356 357 return result; 358 } 359 360 361 status_t 362 BJoystick::SetMaxLatency(bigtime_t maxLatency) 363 { 364 CALLED(); 365 if (fJoystickInfo == NULL || fFD < 0) 366 return B_NO_INIT; 367 368 status_t result = ioctl(fFD, B_JOYSTICK_SET_MAX_LATENCY, &maxLatency, 369 sizeof(maxLatency)); 370 if (result == B_OK) 371 fJoystickInfo->max_latency = maxLatency; 372 373 return result; 374 } 375 376 377 status_t 378 BJoystick::GetAxisNameAt(int32 index, BString *outName) 379 { 380 CALLED(); 381 382 if (index >= CountAxes()) 383 return B_BAD_INDEX; 384 385 if (outName == NULL) 386 return B_BAD_VALUE; 387 388 // TODO: actually retrieve the name from the driver (via a new ioctl) 389 *outName = "Axis "; 390 *outName << index; 391 return B_OK; 392 } 393 394 395 status_t 396 BJoystick::GetHatNameAt(int32 index, BString *outName) 397 { 398 CALLED(); 399 400 if (index >= CountHats()) 401 return B_BAD_INDEX; 402 403 if (outName == NULL) 404 return B_BAD_VALUE; 405 406 // TODO: actually retrieve the name from the driver (via a new ioctl) 407 *outName = "Hat "; 408 *outName << index; 409 return B_OK; 410 } 411 412 413 status_t 414 BJoystick::GetButtonNameAt(int32 index, BString *outName) 415 { 416 CALLED(); 417 418 if (index >= CountButtons()) 419 return B_BAD_INDEX; 420 421 if (outName == NULL) 422 return B_BAD_VALUE; 423 424 // TODO: actually retrieve the name from the driver (via a new ioctl) 425 *outName = "Button "; 426 *outName << index; 427 return B_OK; 428 } 429 430 431 status_t 432 BJoystick::GetAxisValues(int16 *outValues, int32 forStick) 433 { 434 CALLED(); 435 436 if (fJoystickInfo == NULL || fExtendedJoystick == NULL) 437 return B_NO_INIT; 438 439 if (forStick < 0 440 || forStick >= (int32)fJoystickInfo->module_info.num_sticks) 441 return B_BAD_INDEX; 442 443 extended_joystick *extendedJoystick 444 = (extended_joystick *)fExtendedJoystick->ItemAt(forStick); 445 if (extendedJoystick == NULL) 446 return B_NO_INIT; 447 448 memcpy(outValues, extendedJoystick->axes, 449 fJoystickInfo->module_info.num_axes * sizeof(uint16)); 450 return B_OK; 451 } 452 453 454 status_t 455 BJoystick::GetHatValues(uint8 *outHats, int32 forStick) 456 { 457 CALLED(); 458 459 if (fJoystickInfo == NULL || fExtendedJoystick == NULL) 460 return B_NO_INIT; 461 462 if (forStick < 0 463 || forStick >= (int32)fJoystickInfo->module_info.num_sticks) 464 return B_BAD_INDEX; 465 466 extended_joystick *extendedJoystick 467 = (extended_joystick *)fExtendedJoystick->ItemAt(forStick); 468 if (extendedJoystick == NULL) 469 return B_NO_INIT; 470 471 memcpy(outHats, extendedJoystick->hats, 472 fJoystickInfo->module_info.num_hats); 473 return B_OK; 474 } 475 476 477 uint32 478 BJoystick::ButtonValues(int32 forStick) 479 { 480 CALLED(); 481 482 if (fJoystickInfo == NULL || fExtendedJoystick == NULL) 483 return 0; 484 485 if (forStick < 0 486 || forStick >= (int32)fJoystickInfo->module_info.num_sticks) 487 return 0; 488 489 extended_joystick *extendedJoystick 490 = (extended_joystick *)fExtendedJoystick->ItemAt(forStick); 491 if (extendedJoystick == NULL) 492 return 0; 493 494 return extendedJoystick->buttons; 495 } 496 497 498 status_t 499 BJoystick::Update() 500 { 501 CALLED(); 502 if (fJoystickInfo == NULL || fExtendedJoystick == NULL || fFD < 0) 503 return B_NO_INIT; 504 505 for (uint16 i = 0; i < fJoystickInfo->module_info.num_sticks; i++) { 506 extended_joystick *extendedJoystick 507 = (extended_joystick *)fExtendedJoystick->ItemAt(i); 508 if (extendedJoystick == NULL) 509 return B_NO_INIT; 510 511 ssize_t result = read_pos(fFD, i, extendedJoystick, 512 sizeof(extended_joystick)); 513 if (result < 0) 514 return result; 515 516 if (result != sizeof(extended_joystick)) 517 return B_ERROR; 518 519 if (i > 0) 520 continue; 521 522 // fill in the legacy values for the first stick 523 timestamp = extendedJoystick->timestamp; 524 horizontal = extendedJoystick->axes[0]; 525 vertical = extendedJoystick->axes[1]; 526 button1 = (extendedJoystick->buttons & 1) == 0; 527 button2 = (extendedJoystick->buttons & 2) == 0; 528 } 529 530 return B_OK; 531 } 532 533 534 void 535 BJoystick::Calibrate(struct _extended_joystick *reading) 536 { 537 CALLED(); 538 } 539 540 541 status_t 542 BJoystick::GatherEnhanced_info(const entry_ref *ref) 543 { 544 CALLED(); 545 return B_ERROR; 546 } 547 548 549 status_t 550 BJoystick::SaveConfig(const entry_ref *ref) 551 { 552 CALLED(); 553 return B_ERROR; 554 } 555 556 557 // #pragma mark - FBC protection 558 559 560 void BJoystick::_ReservedJoystick1() {} 561 void BJoystick::_ReservedJoystick2() {} 562 void BJoystick::_ReservedJoystick3() {} 563 status_t BJoystick::_Reserved_Joystick_4(void*, ...) { return B_ERROR; } 564 status_t BJoystick::_Reserved_Joystick_5(void*, ...) { return B_ERROR; } 565 status_t BJoystick::_Reserved_Joystick_6(void*, ...) { return B_ERROR; } 566