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