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 #include <Joystick.h> 8 #include <List.h> 9 #include <Entry.h> 10 #include <Path.h> 11 #include <Directory.h> 12 13 #include <String.h> 14 #include <Debug.h> 15 16 #include <errno.h> 17 #include <fcntl.h> 18 #include <stdio.h> 19 20 #define DEVICEPATH "/dev/joystick/" 21 22 typedef struct _joystick_info { 23 char module_name[64]; 24 char device_name[64]; 25 int16 num_axes; 26 int16 num_buttons; 27 int16 num_hats; 28 uint16 num_sticks; 29 } joystick_info; 30 31 //Scans a directory and adds the entries it founds as strings to the given list 32 static status_t 33 scan_directory(const char* rootPath, BList *list, BEntry *rootEntry = NULL) 34 { 35 BDirectory root; 36 37 if (rootEntry != NULL) 38 root.SetTo( rootEntry); 39 else if (rootPath != NULL) 40 root.SetTo(rootPath); 41 else 42 return B_ERROR; 43 44 BEntry entry; 45 46 ASSERT(list != NULL); 47 while ((root.GetNextEntry(&entry)) > B_ERROR ) { 48 if (entry.IsDirectory()) { 49 scan_directory(rootPath, list, &entry); 50 } else { 51 BPath path; 52 entry.GetPath(&path); 53 BString str(path.Path()); 54 str.RemoveFirst(rootPath); 55 list->AddItem(strdup(str.String())); 56 } 57 } 58 return B_OK; 59 } 60 61 class _BJoystickTweaker { 62 63 public: 64 _BJoystickTweaker(); 65 _BJoystickTweaker(BJoystick &stick); 66 virtual ~_BJoystickTweaker(); 67 68 protected: 69 private: 70 status_t scan_including_disabled(); 71 status_t save_config(const entry_ref * ref = NULL); 72 status_t get_info(); 73 BJoystick* fJoystick; 74 }; 75 //-------------------------------------------------------------------// 76 77 78 BJoystick::BJoystick() 79 : _mBeBoxMode(false) 80 , _fDevices(new BList) 81 { 82 ScanDevices(); 83 } 84 85 86 BJoystick::~BJoystick() 87 { 88 if (ffd >= 0) 89 close(ffd); 90 91 for (int32 count = _fDevices->CountItems() - 1; count >= 0; count--) 92 free(_fDevices->RemoveItem(count)); 93 94 delete _fDevices; 95 } 96 97 98 status_t 99 BJoystick::Open(const char *portName) 100 { 101 return Open(portName, true); 102 } 103 104 105 status_t 106 BJoystick::Open(const char *portName, 107 bool enter_enhanced) 108 { 109 char buf[64]; 110 111 //We don't want to use enhanced mode but _mBeBoxMode sugest if we use 112 //BeBoxMode 113 if(!enter_enhanced) 114 _mBeBoxMode = !enter_enhanced; 115 116 if (portName == NULL) 117 return B_BAD_VALUE; // Heheee, we won't crash 118 119 if (portName[0] != '/') 120 snprintf(buf, 64, DEVICEPATH"/%s", portName); 121 else 122 // A name like "/dev/joystick/usb/0" was passed 123 snprintf(buf, 64, "%s", portName); 124 125 if (ffd >= 0) //If this port is already open, close it 126 close(ffd); 127 128 // TODO: BeOS don't use O_EXCL, and this seems to lead to some issues. I 129 // added this flag having read some comments by Marco Nelissen on the 130 // annotated BeBook. I think BeOS uses O_RDWR|O_NONBLOCK here. 131 ffd = open(buf, O_RDWR | O_NONBLOCK | O_EXCL); 132 133 if (ffd >= 0) { 134 // we used open() with O_NONBLOCK flag to let it return immediately, 135 // but we want read/write operations to block if needed, so we clear 136 // that bit here. 137 int flags = fcntl(ffd, F_GETFL); 138 fcntl(ffd, F_SETFL, flags & ~O_NONBLOCK); 139 140 //DriverControl(); 141 } 142 // TODO: I wonder why the return type is a status_t, 143 // since we (as BeOS does) return the descriptor number for the device... 144 return (ffd >= 0) ? ffd : errno; 145 } 146 147 148 void 149 BJoystick::Close(void) 150 { 151 if (ffd >= 0) 152 close(ffd); 153 ffd = -1; 154 } 155 156 157 void 158 BJoystick::ScanDevices(bool use_disabled = false) 159 { 160 // First, we empty the list 161 for (int32 count = _fDevices->CountItems() - 1; count >= 0; count--) 162 free(_fDevices->RemoveItem(count)); 163 164 // Add devices to the list 165 scan_directory(DEVICEPATH, _fDevices); 166 } 167 168 169 int32 170 BJoystick::CountDevices() 171 { 172 int32 count = 0; 173 174 // Refresh devices list 175 ScanDevices(); 176 177 if (_fDevices != NULL) 178 count = _fDevices->CountItems(); 179 180 return count; 181 } 182 183 184 status_t 185 BJoystick::GetDeviceName(int32 n, char *name, size_t bufSize) 186 { 187 status_t result = B_ERROR; 188 const char *dev = NULL; 189 if (_fDevices != NULL) 190 dev = static_cast<char*>(_fDevices->ItemAt(n)); 191 192 if (dev != NULL && name != NULL) { 193 strncpy(name, dev, bufSize); 194 name[bufSize - 1] = '\0'; 195 result = B_OK; 196 } 197 return result; 198 } 199 200 201 status_t 202 BJoystick::Update(void) 203 { 204 return B_ERROR; 205 } 206 207 208 status_t 209 BJoystick::SetMaxLatency(bigtime_t max_latency) 210 { 211 return B_ERROR; 212 } 213 214 215 bool 216 BJoystick::EnterEnhancedMode(const entry_ref *ref) 217 { 218 _mBeBoxMode = false; 219 return !_mBeBoxMode; 220 } 221 222 223 int32 224 BJoystick::CountSticks() 225 { 226 return 0; 227 } 228 229 230 int32 231 BJoystick::CountAxes() 232 { 233 return 0; 234 } 235 236 237 int32 238 BJoystick::CountHats() 239 { 240 return 0; 241 } 242 243 244 int32 245 BJoystick::CountButtons() 246 { 247 return 0; 248 } 249 250 251 status_t 252 BJoystick::GetAxisValues(int16 *out_values, 253 int32 for_stick) 254 { 255 return B_ERROR; 256 } 257 258 259 status_t 260 BJoystick::GetHatValues(uint8 *out_hats, 261 int32 for_stick) 262 { 263 return B_ERROR; 264 } 265 266 267 uint32 268 BJoystick::ButtonValues(int32 for_stick) 269 { 270 return 0; 271 } 272 273 274 status_t 275 BJoystick::GetAxisNameAt(int32 index, 276 BString *out_name) 277 { 278 return B_ERROR; 279 } 280 281 282 status_t 283 BJoystick::GetHatNameAt(int32 index, 284 BString *out_name) 285 { 286 return B_ERROR; 287 } 288 289 290 status_t 291 BJoystick::GetButtonNameAt(int32 index, 292 BString *out_name) 293 { 294 return B_ERROR; 295 } 296 297 298 status_t 299 BJoystick::GetControllerModule(BString *out_name) 300 { 301 return B_ERROR; 302 } 303 304 305 status_t 306 BJoystick::GetControllerName(BString *out_name) 307 { 308 return B_ERROR; 309 } 310 311 312 bool 313 BJoystick::IsCalibrationEnabled() 314 { 315 return false; 316 } 317 318 319 status_t 320 BJoystick::EnableCalibration(bool calibrates) 321 { 322 return false; 323 } 324 325 326 void 327 BJoystick::Calibrate(struct _extended_joystick *reading) 328 { 329 } 330 331 332 status_t 333 BJoystick::gather_enhanced_info(const entry_ref *ref) 334 { 335 return B_ERROR; 336 } 337 338 339 status_t 340 BJoystick::save_config(const entry_ref *ref) 341 { 342 return B_ERROR; 343 } 344 345 346 /* These functions are here to maintain Binary Compatibility */ 347 void BJoystick::_ReservedJoystick1() {} 348 void BJoystick::_ReservedJoystick2() {} 349 void BJoystick::_ReservedJoystick3() {} 350 status_t BJoystick::_Reserved_Joystick_4(void *, ...) {return B_ERROR;} 351 status_t BJoystick::_Reserved_Joystick_5(void *, ...) {return B_ERROR;} 352 status_t BJoystick::_Reserved_Joystick_6(void *, ...) {return B_ERROR;} 353 354 355 //-------------------------------------------------------------------// 356 357 358 _BJoystickTweaker::_BJoystickTweaker() 359 { 360 } 361 362 363 _BJoystickTweaker::_BJoystickTweaker(BJoystick &stick) 364 { 365 fJoystick = &stick; 366 } 367 368 369 _BJoystickTweaker::~_BJoystickTweaker() 370 { 371 } 372 373 374 status_t 375 _BJoystickTweaker::save_config(const entry_ref *ref) 376 { 377 return B_ERROR; 378 } 379 380 381 status_t 382 _BJoystickTweaker::scan_including_disabled() 383 { 384 return B_ERROR; 385 } 386 387 388 status_t 389 _BJoystickTweaker::get_info() 390 { 391 return B_ERROR; 392 } 393