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