* Actually implement the relevant parts of BJoystick, i.e. reading the joystick

info and values. Inspired by and in parts based on the patch by caz_haiku in
  ticket #7429 (though rewritten completely due to the other changes). Thanks
  for the pointers!
* Clean up the mixup of internal joystick info and the one from
  joystick_driver.h so that BJoystick and the drivers talk about the same
  structures.
* Extensive coding style cleanup, simplifications, NULL checks, early returns,
  std::nothrow allocations, include sorting, argument naming, ... that kind of
  stuff.
* Added some TODO notes for remaining stuff.
* Automatic (and manual) whitespace cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41849 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2011-05-31 02:05:39 +00:00
parent 331a968c65
commit ef13dbda92
5 changed files with 299 additions and 131 deletions
+2 -2
View File
@@ -87,10 +87,10 @@ friend class _BJoystickTweaker;
bool fBeBoxMode; bool fBeBoxMode;
bool fReservedBool; bool fReservedBool;
int ffd; int fFD;
BList* fDevices; BList* fDevices;
_joystick_info* fJoystickInfo; _joystick_info* fJoystickInfo;
char* fDevName; BList* fExtendedJoystick;
uint32 _reserved_Joystick_[10]; uint32 _reserved_Joystick_[10];
}; };
+12 -18
View File
@@ -6,7 +6,7 @@
* Fredrik Modeen * Fredrik Modeen
*/ */
#include "joystick_driver.h" #include <joystick_driver.h>
#include <List.h> #include <List.h>
#include <Entry.h> #include <Entry.h>
@@ -21,18 +21,12 @@
class BJoystick; class BJoystick;
typedef struct _joystick_info { typedef struct _joystick_info {
char module_name[64]; joystick_module_info module_info;
char controller_name[64]; bool calibration_enable;
int16 num_axes; bigtime_t max_latency;
int16 num_buttons; BList axis_names;
int16 num_hats; BList hat_names;
uint32 num_sticks; BList button_names;
bool calibration_enable;
bigtime_t max_latency;
BList name_axis;
BList name_hat;
BList name_button;
// BList name_
} joystick_info; } joystick_info;
class _BJoystickTweaker { class _BJoystickTweaker {
@@ -43,18 +37,18 @@ public:
virtual ~_BJoystickTweaker(); virtual ~_BJoystickTweaker();
status_t SendIOCT(uint32 op); status_t SendIOCT(uint32 op);
status_t GetInfo(_joystick_info* info, const char * ref); status_t GetInfo(_joystick_info* info, const char * ref);
// BeOS R5's joystick pref need these // BeOS R5's joystick pref need these
status_t save_config(const entry_ref * ref = NULL); status_t save_config(const entry_ref * ref = NULL);
void scan_including_disabled(); void scan_including_disabled();
status_t get_info(); status_t get_info();
private: private:
void _BuildFromJoystickDesc(char *string, _joystick_info* info); void _BuildFromJoystickDesc(char *string, _joystick_info* info);
status_t _ScanIncludingDisabled(const char* rootPath, BList *list, status_t _ScanIncludingDisabled(const char* rootPath, BList *list,
BEntry *rootEntry = NULL); BEntry *rootEntry = NULL);
void _EmpyList(BList *list); void _EmpyList(BList *list);
BJoystick* fJoystick; BJoystick* fJoystick;
#if DEBUG #if DEBUG
public: public:
+1 -1
View File
@@ -79,7 +79,7 @@ typedef struct _joystick_module {
int _reserved_; int _reserved_;
} joystick_module; } joystick_module;
/** Doing force feedback means writing an extended_joystick to the device with force values. /** Doing force feedback means writing an extended_joystick to the device with force values.
The "timestamp" should be the duration of the feedback. Successive writes will be queued The "timestamp" should be the duration of the feedback. Successive writes will be queued
by the device module. */ by the device module. */
enum { /* Joystick driver ioctl() opcodes */ enum { /* Joystick driver ioctl() opcodes */
+276 -104
View File
@@ -5,8 +5,10 @@
*/ */
#include <List.h> #include <Joystick.h>
#include "Joystick.h" #include <JoystickTweaker.h>
#include <new>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@@ -14,10 +16,11 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <Path.h>
#include <Directory.h>
#include <String.h>
#include <Debug.h> #include <Debug.h>
#include <Directory.h>
#include <List.h>
#include <Path.h>
#include <String.h>
#if DEBUG #if DEBUG
@@ -43,34 +46,51 @@ LOG(const char *fmt, ...)
#define CALLED() LOG("%s\n", __PRETTY_FUNCTION__) #define CALLED() LOG("%s\n", __PRETTY_FUNCTION__)
#include "JoystickTweaker.h"
BJoystick::BJoystick() BJoystick::BJoystick()
: :
// legacy members for standard mode
timestamp(0),
horizontal(0),
vertical(0),
button1(0),
button2(0),
fBeBoxMode(false), fBeBoxMode(false),
ffd(-1), fFD(-1),
fDevices(new BList), fDevices(new(std::nothrow) BList),
fJoystickInfo(new _joystick_info()) fJoystickInfo(new(std::nothrow) joystick_info),
fExtendedJoystick(new(std::nothrow) BList)
{ {
#if DEBUG #if DEBUG
sLogFile = fopen("/var/log/libdevice.log", "a"); sLogFile = fopen("/var/log/joystick.log", "a");
#endif #endif
//ScanDevices();
if (fJoystickInfo != NULL)
memset(fJoystickInfo, 0, sizeof(joystick_info));
} }
BJoystick::~BJoystick() BJoystick::~BJoystick()
{ {
if (ffd >= 0) if (fFD >= 0)
close(ffd); close(fFD);
for (int32 count = fDevices->CountItems() - 1; count >= 0; count--) { if (fDevices != NULL) {
free(fDevices->RemoveItem(count)); for (int32 i = 0; i < fDevices->CountItems(); i++)
delete (BString *)fDevices->ItemAt(i);
delete fDevices;
} }
delete fDevices;
delete fJoystickInfo; delete fJoystickInfo;
if (fExtendedJoystick != NULL) {
for (int32 i = 0; i < fExtendedJoystick->CountItems(); i++)
delete (extended_joystick *)fExtendedJoystick->ItemAt(i);
delete fExtendedJoystick;
}
} }
@@ -83,47 +103,70 @@ BJoystick::Open(const char *portName)
status_t status_t
BJoystick::Open(const char *portName, bool enter_enhanced) BJoystick::Open(const char *portName, bool enhanced)
{ {
CALLED(); CALLED();
char buf[64];
if(!enter_enhanced)
fBeBoxMode = !enter_enhanced;
if (portName == NULL) if (portName == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
if (portName[0] != '/') if (fJoystickInfo == NULL || fExtendedJoystick == NULL)
snprintf(buf, 64, DEVICEPATH"/%s", portName); return B_NO_INIT;
else
snprintf(buf, 64, "%s", portName);
if (ffd >= 0) fBeBoxMode = !enhanced;
close(ffd);
char nameBuffer[64];
if (portName[0] != '/')
snprintf(nameBuffer, sizeof(nameBuffer), DEVICEPATH"/%s", portName);
else
snprintf(nameBuffer, sizeof(nameBuffer), "%s", portName);
if (fFD >= 0)
close(fFD);
// TODO: BeOS don't use O_EXCL, and this seems to lead to some issues. I // TODO: BeOS don't use O_EXCL, and this seems to lead to some issues. I
// added this flag having read some comments by Marco Nelissen on the // added this flag having read some comments by Marco Nelissen on the
// annotated BeBook. I think BeOS uses O_RDWR|O_NONBLOCK here. // annotated BeBook. I think BeOS uses O_RDWR|O_NONBLOCK here.
ffd = open(buf, O_RDWR | O_NONBLOCK | O_EXCL); fFD = open(nameBuffer, O_RDWR | O_NONBLOCK | O_EXCL);
if (ffd >= 0) { if (fFD >= 0) {
// we used open() with O_NONBLOCK flag to let it return immediately, // we used open() with O_NONBLOCK flag to let it return immediately,
// but we want read/write operations to block if needed, so we clear // but we want read/write operations to block if needed, so we clear
// that bit here. // that bit here.
int flags = fcntl(ffd, F_GETFL); int flags = fcntl(fFD, F_GETFL);
fcntl(ffd, F_SETFL, flags & ~O_NONBLOCK); fcntl(fFD, F_SETFL, flags & ~O_NONBLOCK);
//Read the Joystick Description file for this port/joystick // read the Joystick Description file for this port/joystick
_BJoystickTweaker jt(*this); _BJoystickTweaker joystickTweaker(*this);
jt.GetInfo(fJoystickInfo, portName); joystickTweaker.GetInfo(fJoystickInfo, portName);
LOG("ioctl - %d\n", fJoystickInfo->num_buttons); LOG("ioctl - %d\n", fJoystickInfo->module_info.num_buttons);
ioctl(ffd, B_JOYSTICK_SET_DEVICE_MODULE, fJoystickInfo); ioctl(fFD, B_JOYSTICK_SET_DEVICE_MODULE, &fJoystickInfo->module_info,
ioctl(ffd, B_JOYSTICK_GET_DEVICE_MODULE, fJoystickInfo); sizeof(joystick_module_info));
LOG("ioctl - %d\n", fJoystickInfo->num_buttons); ioctl(fFD, B_JOYSTICK_GET_DEVICE_MODULE, &fJoystickInfo->module_info,
sizeof(joystick_module_info));
LOG("ioctl - %d\n", fJoystickInfo->module_info.num_buttons);
return ffd; // Allocate the extended_joystick structures to hold the info for each
// "stick". Note that the whole num_sticks thing seems a bit bogus, as
// all sticks would be required to have exactly the same attributes,
// i.e. axis, hat and button counts, since there is only one global
// joystick_info for the whole device. What's implemented here is a
// "best guess", using the read position in Update() to select the
// stick for which an extended_joystick structure shall be returned.
for (uint16 i = 0; i < fJoystickInfo->module_info.num_sticks; i++) {
extended_joystick *extendedJoystick
= new(std::nothrow) extended_joystick;
if (extendedJoystick == NULL)
return B_NO_MEMORY;
if (!fExtendedJoystick->AddItem(extendedJoystick)) {
delete extendedJoystick;
return B_NO_MEMORY;
}
}
return fFD;
} else } else
return errno; return errno;
} }
@@ -133,9 +176,9 @@ void
BJoystick::Close(void) BJoystick::Close(void)
{ {
CALLED(); CALLED();
if (ffd >= 0) { if (fFD >= 0) {
close(ffd); close(fFD);
ffd = -1; fFD = -1;
} }
} }
@@ -145,8 +188,8 @@ BJoystick::ScanDevices(bool useDisabled)
{ {
CALLED(); CALLED();
if (useDisabled) { if (useDisabled) {
_BJoystickTweaker temp(*this); _BJoystickTweaker joystickTweaker(*this);
temp.scan_including_disabled(); joystickTweaker.scan_including_disabled();
} }
} }
@@ -169,24 +212,25 @@ BJoystick::CountDevices()
status_t status_t
BJoystick::GetDeviceName(int32 n, char *name, size_t bufSize) BJoystick::GetDeviceName(int32 index, char *name, size_t bufSize)
{ {
CALLED(); CALLED();
BString *temp = NULL; if (fDevices == NULL)
if (fDevices != NULL && fDevices->CountItems() > n) return B_NO_INIT;
temp = static_cast<BString*>(fDevices->ItemAt(n));
else if (index >= fDevices->CountItems())
return B_BAD_INDEX; return B_BAD_INDEX;
if (temp != NULL && name != NULL) { if (name == NULL)
if(temp->Length() > (int32)bufSize) return B_BAD_VALUE;
return B_NAME_TOO_LONG;
strncpy(name, temp->String(), bufSize); BString *deviceName = (BString *)fDevices->ItemAt(index);
name[bufSize - 1] = '\0'; if (deviceName->Length() > (int32)bufSize)
LOG("Device Name = %s\n", name); return B_NAME_TOO_LONG;
return B_OK;
} strlcpy(name, deviceName->String(), bufSize);
return B_ERROR; LOG("Device Name = %s\n", name);
return B_OK;
} }
@@ -203,7 +247,10 @@ int32
BJoystick::CountSticks() BJoystick::CountSticks()
{ {
CALLED(); CALLED();
return fJoystickInfo->num_sticks; if (fJoystickInfo == NULL)
return 0;
return fJoystickInfo->module_info.num_sticks;
} }
@@ -211,7 +258,10 @@ int32
BJoystick::CountAxes() BJoystick::CountAxes()
{ {
CALLED(); CALLED();
return fJoystickInfo->num_axes; if (fJoystickInfo == NULL)
return 0;
return fJoystickInfo->module_info.num_axes;
} }
@@ -219,7 +269,10 @@ int32
BJoystick::CountHats() BJoystick::CountHats()
{ {
CALLED(); CALLED();
return fJoystickInfo->num_hats; if (fJoystickInfo == NULL)
return 0;
return fJoystickInfo->module_info.num_hats;
} }
@@ -227,32 +280,40 @@ int32
BJoystick::CountButtons() BJoystick::CountButtons()
{ {
CALLED(); CALLED();
return fJoystickInfo->num_buttons; if (fJoystickInfo == NULL)
return 0;
return fJoystickInfo->module_info.num_buttons;
} }
status_t status_t
BJoystick::GetControllerModule(BString *out_name) BJoystick::GetControllerModule(BString *outName)
{ {
CALLED(); CALLED();
if (fJoystickInfo != NULL && ffd >= 0) { if (fJoystickInfo == NULL || fFD < 0)
out_name->SetTo(fJoystickInfo->module_name); return B_NO_INIT;
return B_OK;
} else
return B_ERROR;
if (outName == NULL)
return B_BAD_VALUE;
outName->SetTo(fJoystickInfo->module_info.module_name);
return B_OK;
} }
status_t status_t
BJoystick::GetControllerName(BString *out_name) BJoystick::GetControllerName(BString *outName)
{ {
CALLED(); CALLED();
if (fJoystickInfo != NULL && ffd >= 0) { if (fJoystickInfo == NULL || fFD < 0)
out_name->SetTo(fJoystickInfo->controller_name); return B_NO_INIT;
return B_OK;
} else if (outName == NULL)
return B_ERROR; return B_BAD_VALUE;
outName->SetTo(fJoystickInfo->module_info.device_name);
return B_OK;
} }
@@ -260,6 +321,9 @@ bool
BJoystick::IsCalibrationEnabled() BJoystick::IsCalibrationEnabled()
{ {
CALLED(); CALLED();
if (fJoystickInfo == NULL)
return false;
return fJoystickInfo->calibration_enable; return fJoystickInfo->calibration_enable;
} }
@@ -268,81 +332,189 @@ status_t
BJoystick::EnableCalibration(bool calibrates) BJoystick::EnableCalibration(bool calibrates)
{ {
CALLED(); CALLED();
if (ffd >= 0) { if (fJoystickInfo == NULL || fFD < 0)
fJoystickInfo->calibration_enable = calibrates;
return B_OK;
} else
return B_NO_INIT; return B_NO_INIT;
status_t result = ioctl(fFD, B_JOYSTICK_SET_RAW_MODE, &calibrates,
sizeof(calibrates));
if (result == B_OK)
fJoystickInfo->calibration_enable = calibrates;
return result;
} }
status_t status_t
BJoystick::SetMaxLatency(bigtime_t max_latency) BJoystick::SetMaxLatency(bigtime_t maxLatency)
{ {
CALLED(); CALLED();
fJoystickInfo->max_latency = max_latency; if (fJoystickInfo == NULL || fFD < 0)
//else B_ERROR (when?) return B_NO_INIT;
status_t result = ioctl(fFD, B_JOYSTICK_SET_MAX_LATENCY, &maxLatency,
sizeof(maxLatency));
if (result == B_OK)
fJoystickInfo->max_latency = maxLatency;
return result;
}
status_t
BJoystick::GetAxisNameAt(int32 index, BString *outName)
{
CALLED();
if (index >= CountAxes())
return B_BAD_INDEX;
if (outName == NULL)
return B_BAD_VALUE;
// TODO: actually retrieve the name from the driver (via a new ioctl)
*outName = "Axis ";
*outName << index;
return B_OK; return B_OK;
} }
//--------- not done -------------------
status_t status_t
BJoystick::GetAxisNameAt(int32 index, BString *out_name) BJoystick::GetHatNameAt(int32 index, BString *outName)
{ {
CALLED(); CALLED();
return B_BAD_INDEX;
if (index >= CountHats())
return B_BAD_INDEX;
if (outName == NULL)
return B_BAD_VALUE;
// TODO: actually retrieve the name from the driver (via a new ioctl)
*outName = "Hat ";
*outName << index;
return B_OK;
} }
status_t status_t
BJoystick::GetHatNameAt(int32 index, BString *out_name) BJoystick::GetButtonNameAt(int32 index, BString *outName)
{ {
CALLED(); CALLED();
return B_BAD_INDEX;
if (index >= CountButtons())
return B_BAD_INDEX;
if (outName == NULL)
return B_BAD_VALUE;
// TODO: actually retrieve the name from the driver (via a new ioctl)
*outName = "Button ";
*outName << index;
return B_OK;
} }
status_t status_t
BJoystick::GetButtonNameAt(int32 index, BString *out_name) BJoystick::GetAxisValues(int16 *outValues, int32 forStick)
{ {
CALLED(); CALLED();
return B_BAD_INDEX;
if (fJoystickInfo == NULL || fExtendedJoystick == NULL)
return B_NO_INIT;
if (forStick < 0
|| forStick >= (int32)fJoystickInfo->module_info.num_sticks)
return B_BAD_INDEX;
extended_joystick *extendedJoystick
= (extended_joystick *)fExtendedJoystick->ItemAt(forStick);
if (extendedJoystick == NULL)
return B_NO_INIT;
memcpy(outValues, extendedJoystick->axes,
fJoystickInfo->module_info.num_axes * sizeof(uint16));
return B_OK;
} }
status_t status_t
BJoystick::GetAxisValues(int16 *out_values, int32 for_stick) BJoystick::GetHatValues(uint8 *outHats, int32 forStick)
{ {
CALLED(); CALLED();
return B_BAD_VALUE;
}
if (fJoystickInfo == NULL || fExtendedJoystick == NULL)
return B_NO_INIT;
status_t if (forStick < 0
BJoystick::GetHatValues(uint8 *out_hats, int32 for_stick) || forStick >= (int32)fJoystickInfo->module_info.num_sticks)
{ return B_BAD_INDEX;
CALLED();
return B_BAD_VALUE; extended_joystick *extendedJoystick
= (extended_joystick *)fExtendedJoystick->ItemAt(forStick);
if (extendedJoystick == NULL)
return B_NO_INIT;
memcpy(outHats, extendedJoystick->hats,
fJoystickInfo->module_info.num_hats);
return B_OK;
} }
uint32 uint32
BJoystick::ButtonValues(int32 for_stick) BJoystick::ButtonValues(int32 forStick)
{ {
CALLED(); CALLED();
return 0;
if (fJoystickInfo == NULL || fExtendedJoystick == NULL)
return 0;
if (forStick < 0
|| forStick >= (int32)fJoystickInfo->module_info.num_sticks)
return 0;
extended_joystick *extendedJoystick
= (extended_joystick *)fExtendedJoystick->ItemAt(forStick);
if (extendedJoystick == NULL)
return 0;
return extendedJoystick->buttons;
} }
status_t status_t
BJoystick::Update(void) BJoystick::Update()
{ {
CALLED(); CALLED();
if (ffd >= 0) { if (fJoystickInfo == NULL || fExtendedJoystick == NULL || fFD < 0)
return B_OK; return B_NO_INIT;
} else
return B_ERROR; for (uint16 i = 0; i < fJoystickInfo->module_info.num_sticks; i++) {
extended_joystick *extendedJoystick
= (extended_joystick *)fExtendedJoystick->ItemAt(i);
if (extendedJoystick == NULL)
return B_NO_INIT;
ssize_t result = read_pos(fFD, i, extendedJoystick,
sizeof(extended_joystick));
if (result < 0)
return result;
if (result != sizeof(extended_joystick))
return B_ERROR;
if (i > 0)
continue;
// fill in the legacy values for the first stick
timestamp = extendedJoystick->timestamp;
horizontal = (uint32)((int32)extendedJoystick->axes[0] + 32768);
vertical = (uint32)((int32)extendedJoystick->axes[1] + 32768);
// TODO: if we really want to go that far: scale the value correctly
button1 = (extendedJoystick->buttons & 1) == 0;
button2 = (extendedJoystick->buttons & 2) == 0;
}
return B_OK;
} }
+8 -6
View File
@@ -167,22 +167,24 @@ _BJoystickTweaker::_BuildFromJoystickDesc(char *string, _joystick_info* info)
if (str.IFindFirst("module") != -1) { if (str.IFindFirst("module") != -1) {
str.RemoveFirst("module = "); str.RemoveFirst("module = ");
strlcpy(info->module_name, str.String(), STRINGLENGTHCPY); strlcpy(info->module_info.module_name, str.String(),
STRINGLENGTHCPY);
} else if (str.IFindFirst("gadget") != -1) { } else if (str.IFindFirst("gadget") != -1) {
str.RemoveFirst("gadget = "); str.RemoveFirst("gadget = ");
strlcpy(info->controller_name, str.String(), STRINGLENGTHCPY); strlcpy(info->module_info.device_name, str.String(),
STRINGLENGTHCPY);
} else if (str.IFindFirst("num_axes") != -1) { } else if (str.IFindFirst("num_axes") != -1) {
str.RemoveFirst("num_axes = "); str.RemoveFirst("num_axes = ");
info->num_axes = atoi(str.String()); info->module_info.num_axes = atoi(str.String());
} else if (str.IFindFirst("num_hats") != -1) { } else if (str.IFindFirst("num_hats") != -1) {
str.RemoveFirst("num_hats = "); str.RemoveFirst("num_hats = ");
info->num_hats = atoi(str.String()); info->module_info.num_hats = atoi(str.String());
} else if (str.IFindFirst("num_buttons") != -1) { } else if (str.IFindFirst("num_buttons") != -1) {
str.RemoveFirst("num_buttons = "); str.RemoveFirst("num_buttons = ");
info->num_buttons = atoi(str.String()); info->module_info.num_buttons = atoi(str.String());
} else if (str.IFindFirst("num_sticks") != -1) { } else if (str.IFindFirst("num_sticks") != -1) {
str.RemoveFirst("num_sticks = "); str.RemoveFirst("num_sticks = ");
info->num_sticks = atoi(str.String()); info->module_info.num_sticks = atoi(str.String());
} else { } else {
LOG("Path = %s\n", str.String()); LOG("Path = %s\n", str.String());
} }