/*
    Raydium - CQFD Corp.
    http://raydium.org/
    Released under both BSD license and Lesser GPL library license.
    See "license.txt" file.
*/

#ifndef DONT_INCLUDE_HEADERS
#include "index.h"
#else
#include "headers/joy.h"
#endif
#ifdef WIN32
// Need to add winmm lib to windows dll build
#include <mmsystem.h>
#endif
#ifdef MACOSX
#include <unistd.h>
#include <ctype.h>
#include <sysexits.h>
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>
#include <IOKit/hid/IOHIDLib.h>
#include <IOKit/hid/IOHIDKeys.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h>
#include <ForceFeedback/ForceFeedback.h>
#include <ForceFeedback/ForceFeedbackConstants.h>
#endif

// proto
int raydium_init_cli_option_default(char *option, char *value, char *default_value);

// This file needs a lot of work, again ...
// (will use Glut for windows joy support soon ...)

//#define joy_debug 1                   //do we display debug infos ?

#define JS_EVENT_BUTTON         0x01    /* button pressed/released */
#define JS_EVENT_AXIS           0x02    /* joystick moved */
#define JS_EVENT_INIT           0x80    /* initial state of device */
/*
                        // function                     3rd arg
#define JSIOCGAXES      // get number of axes           char
#define JSIOCGBUTTONS   // get number of buttons        char
#define JSIOCGVERSION   // get driver version           int
#define JSIOCGNAME(len) // get identifier string        char
#define JSIOCSCORR      // set correction values        &js_corr
#define JSIOCGCORR      // get correction values        &js_corr
*/

//int joy;                              //file handle

//struct input_event play;
//struct input_event stop;
//struct ff_effect effect;
int raydium_joy_event_handle;
#ifndef APPLE
#ifndef WIN32
struct ff_effect effect_tremble;
#else
int raydium_joy_win_id;
#endif
#else
#ifdef MACOSX
struct recElement
{
    // Unique value which identifies element.
    IOHIDElementCookie cookie;

    // Reported min value possible.
    long min;

    // Reported max value possible.
    long max;

    // Runtime variables used for auto-calibration.
    long minReport;
    long maxReport;

    // Next element in list.
    struct recElement *pNext;
};
typedef struct recElement recElement;

struct joystick_hwdata
{
    // Interface for force feedback, 0 = no ff.
    io_service_t ffservice;

    // Interface to device, NULL = no interface.
    IOHIDDeviceInterface **interface;

    // Name of product.
    char product[256];

    // Usage page from IOUSBHID Parser.h which defines general usage.
    long usage;

    // Usage within above page from IOUSBHID Parser.h which defines specific usage.
    long usagePage;

    // Number of axis (calculated, not reported by device).
    long axes;

    // Number of buttons (calculated, not reported by device).
    long buttons;

    // Number of hat switches (calculated, not reported by device).
    long hats;

    // Number of total elements (shouldbe total of above) (calculated, not reported by device).
    long elements;

    recElement *firstAxis;
    recElement *firstButton;
    recElement *firstHat;

    int removed;
    int uncentered;

    // Next device.
    struct joystick_hwdata *pNext;
};
typedef struct joystick_hwdata recDevice;

struct IOKit_Joystick
{
    // Device index.
    uint8_t index;

    // Joystick name.
    const char *name;

    // Number of axis controls on the joystick.
    int naxes;

    // Current axis states.
    int16_t *axes;

    // Number of hats on the joystick.
    int nhats;

    // Current hat states.
    uint8_t *hats;

    // Number of trackballs on the joystick
    int nballs;

    // Current ball motion deltas.
    struct balldelta
    {
        int dx;
        int dy;
    } *balls;

    // Number of buttons on the joystick.
    int nbuttons;

    // Current button states.
    uint8_t *buttons;

    // Driver dependent information.
    struct joystick_hwdata *hwdata;

    // Reference cou