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 <List.h> 9 #include "Joystick.h" 10 11 #include <errno.h> 12 #include <fcntl.h> 13 #include <stdio.h> 14 15 #include <sys/ioctl.h> 16 17 #include <Path.h> 18 #include <Directory.h> 19 #include <String.h> 20 #include <Debug.h> 21 22 23 #if DEBUG 24 static FILE *sLogFile = NULL; 25 26 inline void 27 LOG(const char *fmt, ...) 28 { 29 char buf[1024]; 30 va_list ap; 31 va_start(ap, fmt); 32 vsprintf(buf, fmt, ap); 33 va_end(ap); 34 fputs(buf, sLogFile); fflush(sLogFile); 35 } 36 37 # define LOG_ERR(text...) LOG(text) 38 39 #else 40 # define LOG(text...) 41 # define LOG_ERR(text...) fprintf(stderr, text) 42 #endif 43 44 #define CALLED() LOG("%s\n", __PRETTY_FUNCTION__) 45 46 #include "JoystickTweaker.h" 47 48 49 BJoystick::BJoystick() 50 : 51 fBeBoxMode(false), 52 ffd(-1), 53 fDevices(new BList), 54 fJoystickInfo(new _joystick_info()) 55 { 56 #if DEBUG 57 sLogFile = fopen("/var/log/libdevice.log", "a"); 58 #endif 59 //ScanDevices(); 60 } 61 62 63 BJoystick::~BJoystick() 64 { 65 if (ffd >= 0) 66 close(ffd); 67 68 for (int32 count = fDevices->CountItems() - 1; count >= 0; count--) { 69 free(fDevices->RemoveItem(count)); 70 } 71 72 delete fDevices; 73 delete fJoystickInfo; 74 } 75 76 77 status_t 78 BJoystick::Open(const char *portName) 79 { 80 CALLED(); 81 return Open(portName, true); 82 } 83 84 85 status_t 86 BJoystick::Open(const char *portName, bool enter_enhanced) 87 { 88 CALLED(); 89 char buf[64]; 90 91 if(!enter_enhanced) 92 fBeBoxMode = !enter_enhanced; 93 94 if (portName == NULL) 95 return B_BAD_VALUE; 96 97 if (portName[0] != '/') 98 snprintf(buf, 64, DEVICEPATH"/%s", portName); 99 else 100 snprintf(buf, 64, "%s", portName); 101 102 if (ffd >= 0) 103 close(ffd); 104 105 // TODO: BeOS don't use O_EXCL, and this seems to lead to some issues. I 106 // added this flag having read some comments by Marco Nelissen on the 107 // annotated BeBook. I think BeOS uses O_RDWR|O_NONBLOCK here. 108 ffd = open(buf, O_RDWR | O_NONBLOCK | O_EXCL); 109 110 if (ffd >= 0) { 111 // we used open() with O_NONBLOCK flag to let it return immediately, 112 // but we want read/write operations to block if needed, so we clear 113 // that bit here. 114 int flags = fcntl(ffd, F_GETFL); 115 fcntl(ffd, F_SETFL, flags & ~O_NONBLOCK); 116 117 //Read the Joystick Description file for this port/joystick 118 _BJoystickTweaker jt(*this); 119 jt.GetInfo(fJoystickInfo, portName); 120 121 LOG("ioctl - %d\n", fJoystickInfo->num_buttons); 122 ioctl(ffd, B_JOYSTICK_SET_DEVICE_MODULE, fJoystickInfo); 123 ioctl(ffd, B_JOYSTICK_GET_DEVICE_MODULE, fJoystickInfo); 124 LOG("ioctl - %d\n", fJoystickInfo->num_buttons); 125 126 return ffd; 127 } else 128 return errno; 129 } 130 131 132 void 133 BJoystick::Close(void) 134 { 135 CALLED(); 136 if (ffd >= 0) { 137 close(ffd); 138 ffd = -1; 139 } 140 } 141 142 143 void 144 BJoystick::ScanDevices(bool useDisabled) 145 { 146 CALLED(); 147 if (useDisabled) { 148 _BJoystickTweaker temp(*this); 149 temp.scan_including_disabled(); 150 } 151 } 152 153 154 int32 155 BJoystick::CountDevices() 156 { 157 CALLED(); 158 159 // Refresh devices list 160 ScanDevices(true); 161 162 int32 count = 0; 163 if (fDevices != NULL) 164 count = fDevices->CountItems(); 165 166 LOG("Count = %d\n", count); 167 return count; 168 } 169 170 171 status_t 172 BJoystick::GetDeviceName(int32 n, char *name, size_t bufSize) 173 { 174 CALLED(); 175 BString *temp = NULL; 176 if (fDevices != NULL && fDevices->CountItems() > n) 177 temp = static_cast<BString*>(fDevices->ItemAt(n)); 178 else 179 return B_BAD_INDEX; 180 181 if (temp != NULL && name != NULL) { 182 if(temp->Length() > (int32)bufSize) 183 return B_NAME_TOO_LONG; 184 strncpy(name, temp->String(), bufSize); 185 name[bufSize - 1] = '\0'; 186 LOG("Device Name = %s\n", name); 187 return B_OK; 188 } 189 return B_ERROR; 190 } 191 192 193 bool 194 BJoystick::EnterEnhancedMode(const entry_ref *ref) 195 { 196 CALLED(); 197 fBeBoxMode = false; 198 return !fBeBoxMode; 199 } 200 201 202 int32 203 BJoystick::CountSticks() 204 { 205 CALLED(); 206 return fJoystickInfo->num_sticks; 207 } 208 209 210 int32 211 BJoystick::CountAxes() 212 { 213 CALLED(); 214 return fJoystickInfo->num_axes; 215 } 216 217 218 int32 219 BJoystick::CountHats() 220 { 221 CALLED(); 222 return fJoystickInfo->num_hats; 223 } 224 225 226 int32 227 BJoystick::CountButtons() 228 { 229 CALLED(); 230 return fJoystickInfo->num_buttons; 231 } 232 233 234 status_t 235 BJoystick::GetControllerModule(BString *out_name) 236 { 237 CALLED(); 238 if (fJoystickInfo != NULL && ffd >= 0) { 239 out_name->SetTo(fJoystickInfo->module_name); 240 return B_OK; 241 } else 242 return B_ERROR; 243 244 } 245 246 247 status_t 248 BJoystick::GetControllerName(BString *out_name) 249 { 250 CALLED(); 251 if (fJoystickInfo != NULL && ffd >= 0) { 252 out_name->SetTo(fJoystickInfo->controller_name); 253 return B_OK; 254 } else 255 return B_ERROR; 256 } 257 258 259 bool 260 BJoystick::IsCalibrationEnabled() 261 { 262 CALLED(); 263 return fJoystickInfo->calibration_enable; 264 } 265 266 267 status_t 268 BJoystick::EnableCalibration(bool calibrates) 269 { 270 CALLED(); 271 if (ffd >= 0) { 272 fJoystickInfo->calibration_enable = calibrates; 273 return B_OK; 274 } else 275 return B_NO_INIT; 276 } 277 278 279 status_t 280 BJoystick::SetMaxLatency(bigtime_t max_latency) 281 { 282 CALLED(); 283 fJoystickInfo->max_latency = max_latency; 284 //else B_ERROR (when?) 285 return B_OK; 286 } 287 288 //--------- not done ------------------- 289 290 status_t 291 BJoystick::GetAxisNameAt(int32 index, BString *out_name) 292 { 293 CALLED(); 294 return B_BAD_INDEX; 295 } 296 297 298 status_t 299 BJoystick::GetHatNameAt(int32 index, BString *out_name) 300 { 301 CALLED(); 302 return B_BAD_INDEX; 303 } 304 305 306 status_t 307 BJoystick::GetButtonNameAt(int32 index, BString *out_name) 308 { 309 CALLED(); 310 return B_BAD_INDEX; 311 } 312 313 314 status_t 315 BJoystick::GetAxisValues(int16 *out_values, int32 for_stick) 316 { 317 CALLED(); 318 return B_BAD_VALUE; 319 } 320 321 322 status_t 323 BJoystick::GetHatValues(uint8 *out_hats, int32 for_stick) 324 { 325 CALLED(); 326 return B_BAD_VALUE; 327 } 328 329 330 uint32 331 BJoystick::ButtonValues(int32 for_stick) 332 { 333 CALLED(); 334 return 0; 335 } 336 337 338 status_t 339 BJoystick::Update(void) 340 { 341 CALLED(); 342 if (ffd >= 0) { 343 return B_OK; 344 } else 345 return B_ERROR; 346 } 347 348 349 void 350 BJoystick::Calibrate(struct _extended_joystick *reading) 351 { 352 CALLED(); 353 } 354 355 356 status_t 357 BJoystick::GatherEnhanced_info(const entry_ref *ref) 358 { 359 CALLED(); 360 return B_ERROR; 361 } 362 363 364 status_t 365 BJoystick::SaveConfig(const entry_ref *ref) 366 { 367 CALLED(); 368 return B_ERROR; 369 } 370 371 372 // #pragma mark - FBC protection 373 374 375 void BJoystick::_ReservedJoystick1() {} 376 void BJoystick::_ReservedJoystick2() {} 377 void BJoystick::_ReservedJoystick3() {} 378 status_t BJoystick::_Reserved_Joystick_4(void*, ...) { return B_ERROR; } 379 status_t BJoystick::_Reserved_Joystick_5(void*, ...) { return B_ERROR; } 380 status_t BJoystick::_Reserved_Joystick_6(void*, ...) { return B_ERROR; } 381