
#ifndef USBJOYSTICK_H_INCLUDED
#define USBJOYSTICK_H_INCLUDED



#include "usb.h"
#include "usbhid.h"
#include "usbrdesc.h"


// silence compiler warnings about unused parameters
#define IGNORE(x) do { (void)(x); } while(0)

// Vector readability
#define VECTOR_PASSON 1
#define VECTOR_CLAIM 0



#define NOT_MAPPED      -1000
#define NONE_AVAILABLE  -1



// from xmame - /unix/devices.h
#define JOY_MAX               8
#define JOY_BUTTONS          32
#define JOY_USAGE_AXES       16
#define JOY_AXES             20
#define JOY_NAME_LEN         20
#define JOY_MAX_DATA_LENGTH  64


// our axes types: note that we must not use 0
#define AXIS_START    1

#define AXIS_HATX     1
#define AXIS_HATY     2
#define AXIS_DPADX    3
#define AXIS_DPADY    4
#define AXIS_X        5
#define AXIS_Y        6
#define AXIS_Z        7
#define AXIS_RX       8
#define AXIS_RY       9
#define AXIS_RZ       10
#define AXIS_SLIDER   11

#define AXIS_END      11



// xmame: /src/unix/devices.h
struct axisdata_struct
{
  int32_t    val;
  int32_t    min;
  int32_t    mid;
  int32_t    max;
  // risc os additions:
  uint32_t   acorn_slope_8;
  osbool     acorn_slope_div_8;
  uint32_t   acorn_slope_16;
  osbool     acorn_slope_div_16;
  uint32_t   pc_slope;
  osbool     pc_slope_div;
  int32_t    serial_port_upper_bound;
  int32_t    serial_port_lower_bound;
  osbool     is_digital;
  char       *name;
  osbool     flip;
  uint32_t   type;          // todo: make a type/enum for this?
  uint32_t   mouse_factor;
  uint32_t   mouse_sensitivity;
};



struct joydata_struct
{
  // xmame: joy_usb.c
  uint32_t                 report_length;
  osbool                   has_report_id;  // indicates if first data byte is the reportid
  char                     *data_buf;      // only for the report id+data
  struct hid_item          *axes_items[JOY_USAGE_AXES];  // only analogue axes
  struct hid_item          *button_items[JOY_BUTTONS];
  struct hid_item          *hat_item;
  struct hid_item          *dpad_up_item;
  struct hid_item          *dpad_down_item;
  struct hid_item          *dpad_left_item;
  struct hid_item          *dpad_right_item;
  osbool                   has_dpad;
  osbool                   has_hat;
  uint32_t                 hat_axis;   // if we have one, this is the x (y will be next)
  uint32_t                 dpad_axis;  // if we have one, this is the x (y will be next)
  // from xmame core:
  uint32_t                 num_axes;
  uint32_t                 num_buttons;
  struct axisdata_struct   axes[JOY_AXES];
  uint32_t                 buttons[JOY_BUTTONS];
  // risc os additions follow:
  struct joy_device_struct *device;
  osbool                   in_use;
  osbool                   open;
  char                     device_name[USB_DEVICE_NAME_LENGTH];
  uint8_t                  interface;
  uint8_t                  endpoint;
  char                     usb_path[USB_DEVICEFS_PATH_MAX_LENGTH];
  os_fw                    fp;
  buffer_b                 buffer_handle;
  buffer_internal_id       buffer_internal_id;
  asm_routine              buffer_service_routine;
  void                     *buffer_workspace;
  uint32_t                 devicefs_handle;
  uint32_t                 upcalls;
  uint32_t                 upcalls_delta;
  char                     manufacturer[USB_MAX_STRING_LEN];
  char                     product[USB_MAX_STRING_LEN];
  char                     serial[USB_MAX_STRING_LEN];
  uint32_t                 vendor_id;
  uint32_t                 product_id;
  uint32_t                 device_id;
  uint32_t                 good_reads;
  uint32_t                 good_reads_delta;
  uint32_t                 bad_reads;
  uint32_t                 bad_reads_delta;
  int32_t                  mapped_number;
  int32_t                  mapped_x_8;
  int32_t                  mapped_y_8;
  int32_t                  mapped_x_16;
  int32_t                  mapped_y_16;
  uint32_t                 mapped_buttons[JOY_BUTTONS];
  int32_t                  mapped_mouse_x;
  int32_t                  mapped_mouse_y;
  int32_t                  mapped_mouse_select;
  int32_t                  mapped_mouse_menu;
  int32_t                  mapped_mouse_adjust;
  int32_t                  key_up;
  int32_t                  key_previousup;
  int32_t                  key_down;
  int32_t                  key_left;
  int32_t                  key_right;
  int32_t                  key_buttons[JOY_BUTTONS];
};



struct joystick_read_dev_info_struct {
  uint8_t              joystick_id;
  char                 *device_path;
  char                 *manufacturer;
  char                 *product;
  char                 *serial;
  uint8_t              number_axes;
  uint8_t              number_buttons;
};



struct joystick_read_axes_info_struct {
  uint32_t             type;
  char                 *name;
  int32_t              min;
  int32_t              mid;
  int32_t              max;
  int32_t              val;
};



// the following will be initialised elsewhere

extern uint32_t joy_index;
extern uint32_t axis_max;
extern struct joydata_struct joy_data[];
extern struct joystick_read_dev_info_struct joy_read_dev_info[JOY_MAX];
extern struct joystick_read_axes_info_struct joy_read_axes_info[JOY_AXES];
extern int32_t joy_read_axes_values[JOY_AXES];

extern osbool emulate_acorn_on;
extern osbool emulate_serial_port_on;
extern osbool emulate_joy_on;

extern osbool bytev_claimed;
extern osbool upcall_claimed;
extern osbool ukswiv_claimed;

extern void* g_module_pw;



// Errors
//
// kernel.h defines: ErrorBase_Joystick as &43F40  (Acorn's error?)

extern _kernel_oserror err_syntax;
extern _kernel_oserror err_badnoparms;
extern _kernel_oserror err_toomanyparms;

extern _kernel_oserror err_nosuchswi;
extern _kernel_oserror err_modulebadswi;

extern _kernel_oserror err_badjoy;
extern _kernel_oserror err_nousb;
extern _kernel_oserror err_joynotactive;
extern _kernel_oserror err_joynotopen;



_kernel_oserror *module_initialise(const char *cmd_tail, int32_t podule_base, void *pw);
_kernel_oserror *module_finalise(int32_t fatal, int32_t podule, void *pw);
_kernel_oserror *module_swi(int32_t swi_offset, _kernel_swi_regs *r, void *pw);

#endif
