* 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];
}; };
+7 -13
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 {
+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());
} }