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