[haiku-development] Re: Joysticks in Haiku

  • From: "Carwyn" <cdj1000@xxxxxxx>
  • To: "Haiku-dev" <haiku-development@xxxxxxxxxxxxx>
  • Date: Tue, 08 Mar 2011 01:51:44 +0000

Here is some code that works on the original BeOS,  the testjoy app 
from usb_0.50 joystick driver works with this code, when this code is 
compiled with the testjoy.cpp.  Ignore the hack nature of the code as 
it's been created by using the debugger and seeing how the original 
BJoystick worked.

#include "joystick_driver.h"
#include "joystick_tweaker.h"

#include <Joystick.h>
#include <List.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <String.h>
#include <Entry.h>
#include <Path.h>
#include <FindDirectory.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>

const struct port_names {
        char *name;
        char *path;
} names[] = {
        { "joystick1", "/dev/joystick/joystick_1" },
        { "joystick2", "/dev/joystick/joystick_2" },
        { "joystick3", "/dev/joystick/joystick_3" },
        { "joystick4", "/dev/joystick/joystick_4" },
        { "/dev/"    , "/dev/joystick/" }
};

static bool determined = true, isit = false;

class _BJoystickTweaker {
public:
        _BJoystickTweaker(BJoystick &stick);
        ~_BJoystickTweaker();
        status_t save_config(const entry_ref *ref);
        void scan_including_disabled();
        _joystick_info *get_info();
private:
        BJoystick *joystick;
};


_BJoystickTweaker::_BJoystickTweaker(BJoystick &stick)
{
        puts("CALLING Tweaker");
        joystick = &stick;
}

status_t _BJoystickTweaker::save_config(const entry_ref *ref)
{
        puts(__PRETTY_FUNCTION__);
        return B_ERROR;
}

void _BJoystickTweaker::scan_including_disabled()
{
        //puts(__PRETTY_FUNCTION__);
        if(!joystick->_fDevices) joystick->ScanDevices(true);
}

_joystick_info *_BJoystickTweaker::get_info()
{
        //return B_ERROR;
        return joystick->m_info;
}

_BJoystickTweaker::~_BJoystickTweaker()
{
}

BJoystick::BJoystick()
{
        //puts("Constructor");
        timestamp = 0;
        horizontal = 0;
        vertical = 0;
        button1 = 0;
        button2 = 0;
        ffd = -1;
        _fDevices = 0;
        m_info = 0;
        m_dev_name = 0;
        _mBeBoxMode = 0;
}

BJoystick::~BJoystick()
{
        //puts("DESTROY");
}

status_t BJoystick::EnableCalibration(bool calibrates)
{
        if(!m_info) return B_NO_INIT;
        
        m_info->calibration_enabled = calibrates;
        return B_OK;
}

bool BJoystick::IsCalibrationEnabled()
{
        bool iscalibration_enabled = false;
        if(m_info) {
                if(m_info->calibration_enabled) iscalibration_enabled = true;
        }
        return iscalibration_enabled;
}

void BJoystick::Close(void)
{
        if(ffd >= 0) {
                close(ffd);
                ffd = -1;
        }
        
        if(m_info) {
                for(int i = 0; i < m_info->module_info.num_axes; i++)
                        free((void *)m_info->axis_name[i].name);
                        
                for(int i = 0; i < m_info->module_info.num_buttons; i++)
                        free((void *)m_info->button_name[i].name);
                
                delete m_info;
        }
        
        free(m_dev_name);
        m_info = 0;
        m_dev_name = 0;
}

//void get_module_name(FILE *f
status_t BJoystick::gather_enhanced_info(const entry_ref * ref)
{

char jbuffer[256];
char module[256];
char gadget[256];

#ifdef WORKING
        if(!m_info) m_info = new _joystick_info;
        
        memset(m_info, 0, sizeof(_joystick_info));
        
        m_info->num_sticks = 1;
        strcpy(m_info->device_name, "Generic USB Joystick");
#endif

        //puts("GATHERING");
//#if 0
        BPath path(ref); // XXX
        
        if(ref != NULL) {
                BEntry entry(ref);
                entry.GetPath(&path);
                
                //if(entry.GetPath(&path) == B_OK) {
                //      if(!determined) {
                        
                        //}
                //}
        } else {
        
                if(strncmp(m_dev_name, "/dev/", 5) == 0) {
                        if(strncmp(m_dev_name + 5, "joystick/", 9) == 0) {
                                find_directory(B_COMMON_SETTINGS_DIRECTORY, 
&path);
                        
                                printf("FOUND SETTINGS: %s\n", path.Path());
                        // XXX
                                path.Append("joysticks");
                                path.Append(m_dev_name + 14);
                        }
                
                }
        }
                        //path.Append(
                        
                        FILE *f = fopen(path.Path(), "r");
                        //FILE *f = fopen("myfile1.txt", "wb");
                        //fputs(path.Path(), f);
                        //fputs(m_dev_name + 14, f);
                        //fclose(f);
                        
                        //char *p = new char[0x428];
                        m_info = new _joystick_info();
                        
                        memset(&m_info->module_info, 0, sizeof(m_info-
>module_info));
                        memset(m_info->sticks, 0, sizeof(m_info->sticks));
                        memset(m_info->file_name, 0, sizeof(m_info->file_name));
                        memset(m_info->axis_name, 0, sizeof(m_info->axis_name));
                        memset(m_info->hat_name, 0, sizeof(m_info->hat_name));
                        memset(m_info->button_name, 0, sizeof(m_info-
>button_name));
                        
                        #if 0
                        m_info->sticks.timestamp = 0;
                        m_info->sticks.buttons = 0;
                        m_info->sticks.axes[0] = 0;
                        m_info->sticks.hats[0] = 0;
                        #endif
                        m_info->calibration_enabled = 1;
                        
                        m_info->module_info.num_sticks = 1;
                        
                        BEntry entry(path.Path(), true);
                        
                        BPath newpath(&entry);
                        
                        entry.GetPath(&newpath);
                        
                        printf("FOUND SETTINGS NOW: %s\n", newpath.Path());
                        const char *currentpath = newpath.Leaf();
                        
                        // m_info->leaf is at 1b0
                        strncpy(m_info->file_name, currentpath, 256);
                        
                        while(!feof(f)) {
                                if(fgets(jbuffer, 256, f)) {
                                        if(jbuffer[0] != '#' && jbuffer[1] != ' 
') {
                                                if(jbuffer[0] == 'm') {
                                                        sscanf(jbuffer, "module 
= \"%255[^\"\n]", 
module);
                                                        
strncpy(m_info->module_info.module_name, 
module, 64);
                                                        
m_info->module_info.module_name[64-1] = 
'\0';
                                                }
                                                
                                                if(jbuffer[0] == 'g') {
                                                        sscanf(jbuffer, "gadget 
= \"%255[^\"\n]", 
gadget);
                                                        
strncpy(m_info->module_info.device_name, 
gadget, 64);
                                                        
m_info->module_info.device_name[64-1] = 
'\0'; 
                                                }
                                                if(jbuffer[0] == 'f') {
                                                        //sscanf(jbuffer, 
"gadget = \"%255[^\"\n]", 
gadget);
                                                        
//strncpy(m_info->file_name, "myname", 
256);
                                                        
//m_info->file_name[256-1] = '\0'; 
                                                }
                                        }
                                }
                        }
                        
                        m_info->module_info.num_axes = 2;
                        m_info->axis_name[0].name = strdup("Left-Right");
                        m_info->axis_name[1].name = strdup("Front-Back");
                        
                        for(int c = 0; c < 10; c++) m_info->button_name[c].name 
= 
strdup("Button");
                        fclose(f);
                
                
                if(m_info->module_info.module_name != NULL && m_info-
>module_info.device_name != NULL) {
                        //test button_names etc
                        //if(m_info->module_info.num_axes > 0 && 
                }
        
        
//#endif

// gather_enhanced is at 463c

        //breakpoint gather_enhanced_info__9BJoystickPC9entry_ref+0xc68
        return true;
}

bool BJoystick::EnterEnhancedMode(const entry_ref * ref)
{
        
        
        
        if(ref != NULL) printf("EnterEnhancedMode: %s\n", ref->name);
        //if(determined) return false;
        
        //if(ref->name) determined = true;
        //if(getenv("JOYSTICK_DEBUG") == 0) return false;
        
        determined = true;
        
        //if(m_info) return true;
        
        gather_enhanced_info(ref);
        
        if(ioctl(ffd, B_JOYSTICK_SET_DEVICE_MODULE, m_info) != B_OK) return 
false;
        
        ioctl(ffd, B_JOYSTICK_GET_DEVICE_MODULE, m_info);
        
        timestamp = 0;
        Update();
        return true;
}
                                                
status_t BJoystick::Open(const char *portName)
{
        //puts(portName);
        puts(__PRETTY_FUNCTION__);
        return Open(portName, 1);
}

status_t BJoystick::Open(const char *portName, bool enter_enhanced)
{
        puts(__PRETTY_FUNCTION__);
        char my_dev[B_OS_NAME_LENGTH];
        struct stat buf;
        //char *path = NULL;
        //_joystick_info *info = 0;
        
        puts(portName);
        if(portName == NULL) return B_ERROR;
        
#if 0
        _joystick_info info;
        for(int i = 0; i < 4; i++) {
                if(strcmp(portName, names[i].name) == 0) {
                        //ffd = open(names[i].path, 0, &info);
                        path = names[i].path;
                        break;
                }
        }
        
        
#endif

        //if(strncmp(portName, "/dev/", 5) == 0) {
        if(strncmp(portName, "/dev/", 5) != 0) {
                strcpy(my_dev, "/dev/joystick/");
                strcat(my_dev, portName);
        } else
                strcpy(my_dev, portName);
                
                
                if(stat(my_dev, &buf) == 0) {
                        if(ffd < 0) {
                                _mBeBoxMode = false;
                                ffd = open(my_dev, 0);
                                free(m_dev_name);
                                
                                if(!m_info) {
                                        m_info = 0;
                                        if(ffd > 0) {
                                                m_dev_name = strdup(my_dev);
                                                if(enter_enhanced) 
EnterEnhancedMode(NULL);
//return ffd;
                                        }
                                }
                        }
                }
        //}
        
        //m_dev_name = strdup(portName);
        return ffd;
}

uint32 BJoystick::ButtonValues(int32 for_stick)
{
        uint32 ret = 0;
        if(!m_info) {
                if(!button1) ret = 1;
                if(!button2) ret |= 2;
                return ret;
        }
        
        if(for_stick < 0) return B_BAD_VALUE;
                                
        if(for_stick < m_info->module_info.num_sticks)
                return m_info->sticks[for_stick].buttons;
        
        //printf("BUTTONS: %ld\n", m_info->sticks.buttons);
        return B_BAD_VALUE;
}

status_t BJoystick::GetHatValues(uint8 * out_hats, int32 for_stick)
{
        return B_BAD_VALUE;
}
                                                
status_t BJoystick::GetAxisValues(int16 * out_values, int32 for_stick)
{
        memcpy(out_values, m_info->sticks[for_stick].axes,
                m_info->module_info.num_axes * sizeof(int16));
        return B_OK;
}

int32 BJoystick::CountButtons()
{
        if(!m_info) return 2;
        return m_info->module_info.num_buttons;
}

int32 BJoystick::CountAxes()
{
        if(!m_info) return 2;
        return m_info->module_info.num_axes;
}

int32 BJoystick::CountHats()
{
        if(!m_info) return 0;
        return m_info->module_info.num_hats;
}

int32 BJoystick::CountSticks()
{
        if(!m_info) return 1;
        return m_info->module_info.num_sticks;
}

status_t BJoystick::GetDeviceName(int32 n, char * name, size_t bufSize)
{
        puts(__PRETTY_FUNCTION__);
        if(!_fDevices) ScanDevices();
        
        
        if(n >= _fDevices->CountItems()) return B_ERROR;
        const char *device_name = (const char *)_fDevices->ItemAt(n);
        strncpy(name, device_name, bufSize);
        
        printf("DEV_NAME: %s\n", device_name);
        return 0;//_fDevices->CountItems();
        
        //return 0;
}

status_t BJoystick::SetMaxLatency(bigtime_t max_latency)
{
        //status_t ret = 0;
        if(ffd >= 0) {
                return ioctl(ffd, B_JOYSTICK_SET_MAX_LATENCY, &max_latency, 
sizeof(bigtime_t));
        }
        return B_ERROR;
}

void recursive_scan(const char *path, BList *devices, BList &returnlist)
{
        // malloc 0x400 probably char
        char *joy_path = (char *)malloc(0x400);
        struct stat buf;
        DIR *dir = opendir(path);
        
        dirent *d;
        if(dir) {
                while((d = readdir(dir)) != 0) {
                        //if(d->d_reclen > 2) {
                        if(memcmp(d->d_name, ".", 1)) {
                                strcpy(joy_path, path);
                                strcat(joy_path, "/");
                                strcat(joy_path, d->d_name);
                                if(stat(joy_path, &buf) == 0) {
                                        puts(joy_path);
                                        if(S_ISDIR(buf.st_mode)) {
                                                recursive_scan(joy_path, 
devices, returnlist);
                                        } else {
                                                const char *cpath = 
strdup(joy_path + 14);
                                                devices->AddItem((void *)cpath);
                                        }
                                }
                        }
                //cout << d->d_name << endl;
                }
                closedir(dir);
                free(joy_path);
        }
}

void BJoystick::ScanDevices(bool use_disabled)
{
        if(!_fDevices) _fDevices = new BList();
        _fDevices->MakeEmpty();
        
        BList returnlist;
        BPath path;
        
        recursive_scan("/dev/joystick", _fDevices, returnlist);
}

status_t BJoystick::Update(void)
{
        joystick joy;
        
        if(ffd < 0) return B_ERROR;
        //if(ffd > 0) {
                //read(ffd, &joy, sizeof(joy));
                //button1 = joy.button1;
                //return B_ERROR;
        if(!m_info) {
                read(ffd, &joy, sizeof(joy));
                timestamp = joy.timestamp;
                horizontal = joy.horizontal;
                vertical = joy.vertical;
                button1 = joy.button1;
                button2 = joy.button2;
        } else {
                int result = read(ffd, m_info->sticks,
                        sizeof(extended_joystick) * 
m_info->module_info.num_sticks);
                
                //printf("UPDATE: %d\n", m_info->num_buttons);
                Calibrate(m_info->sticks);
                
                //horizontal = m_info->sticks[0].axes[0];
                return result;
                //return m_info->num_sticks;
        }
        return B_ERROR;
}

status_t BJoystick::GetControllerName(BString *out_name)
{
        const char *str = "2-axis";
        
        if(m_info) str = m_info->module_info.device_name;
        *out_name = str;
        
        return B_OK;
}

status_t BJoystick::GetControllerModule(BString *out_name)
{
        const char *str = "Legacy";

        if(m_info) str = m_info->module_info.module_name;
        *out_name = str;
        
        return B_OK;
}

status_t BJoystick::GetAxisNameAt(int32 index, BString *out_name)
{
        if(m_info) {
                if(index > 1) return B_BAD_INDEX;
                if(index > m_info->module_info.num_axes) return B_BAD_INDEX;
                
                *out_name = m_info->axis_name[index].name;
        }

        return B_OK;
}

status_t BJoystick::GetHatNameAt(int32 index, BString * out_name)
{
        if(m_info) {
                *out_name = m_info->hat_name[index].name;
        }
        return B_BAD_INDEX;
}

status_t BJoystick::GetButtonNameAt(int32 index, BString *out_name)
{
        if(m_info) {
                *out_name = m_info->button_name[index].name;
        }
        return B_OK;
}

void BJoystick::Calibrate(struct _extended_joystick * reading)
{
        puts(__PRETTY_FUNCTION__);
}

void BJoystick::_ReservedJoystick1() {}

void BJoystick::_ReservedJoystick2() {}

void BJoystick::_ReservedJoystick3() {}

status_t BJoystick::_Reserved_Joystick_4(void *, ...)
{
        return B_ERROR;
}

status_t BJoystick::_Reserved_Joystick_5(void *, ...)
{
        return B_ERROR;
}

status_t BJoystick::_Reserved_Joystick_6(void *, ...)
{
        return B_ERROR;
}

Carwyn

Other related posts: