/* Copyright 1999, Be Incorporated. All Rights Reserved. This file may be used under the terms of the Be Sample Code License. */ #ifndef _JOYSTICK_DRIVER_H #define _JOYSTICK_DRIVER_H #include #include #include #include typedef struct _joystick { bigtime_t timestamp; uint32 horizontal; uint32 vertical; bool button1; bool button2; } joystick; /* maximum number of axes on one controller (pads count as 2 axes each) */ #define MAX_AXES 12 /* maximum number of hats on one controller -- PADS SHOULD BE RETURNED AS AXES! */ #define MAX_HATS 8 /* maximum number of buttons on one controller */ #define MAX_BUTTONS 32 /* maximum number of controllers on one port */ #define MAX_STICKS 4 typedef struct _extended_joystick { bigtime_t timestamp; /* system_time when it was read */ uint32 buttons; /* lsb to msb, 1 == on */ int16 axes[MAX_AXES]; /* -32768 to 32767, X, Y, Z, U, V, W */ uint8 hats[MAX_HATS]; /* 0 through 8 (1 == N, 3 == E, 5 == S, 7 == W) */ } _PACKED extended_joystick; // This is a helper structure to manage variably sized data. It is here to // make storing and accessing the flat data in the "data" member easier. When // transferring data via read/write/ioctl only the flat data in "data" is ever // transmitted, not the whole structure. typedef struct _variable_joystick { #ifdef __cplusplus status_t initialize(uint32 axisCount, uint32 hatCount, uint32 buttonCount) { axis_count = axisCount; hat_count = hatCount; button_blocks = (buttonCount + 31) / 32; data_size = sizeof(bigtime_t) // timestamp + button_blocks * sizeof(uint32) // bitmaps + axis_count * sizeof(int16) // axis values + hat_count * sizeof(uint8); // hat values data = (uint8 *)malloc(data_size); if (data == NULL) return B_NO_MEMORY; // fill in the convenience pointers timestamp = (bigtime_t *)data; buttons = (uint32 *)×tamp[1]; axes = (int16 *)&buttons[button_blocks]; hats = (uint8 *)&axes[axis_count]; return B_OK; } status_t initialize_to_extended_joystick() { return initialize(MAX_AXES, MAX_HATS, MAX_BUTTONS); } #endif uint32 axis_count; uint32 hat_count; uint32 button_blocks; // count of 32 bit button bitmap blocks == (button_count + 31) / 32 // These pointers all point into the data section and are here for // convenience. They need to be set up manually by the one who creates this // structure or by using the initialize() method. bigtime_t * timestamp; uint32 * buttons; int16 * axes; uint8 * hats; // The data is always structured in the following way (see extended_joystick // for data interpretation): // bigtime_t timestamp; // uint32 button_bitmap_blocks[button_blocks]; // int16 axes[axis_count]; // uint8 hats[hat_count]; size_t data_size; uint8 * data; } variable_joystick; #define MAX_CONFIG_SIZE 100 enum { /* flags for joystick module info */ js_flag_force_feedback = 0x1, js_flag_force_feedback_directional = 0x2, js_flag_variable_size_reads = 0x4 }; typedef struct _joystick_module_info { char module_name[64]; char device_name[64]; int16 num_axes; int16 num_buttons; int16 num_hats; uint16 _reserved[7]; uint32 flags; uint16 num_sticks; int16 config_size; char device_config[MAX_CONFIG_SIZE]; /* device specific */ } joystick_module_info; /* Note that joystick_module is something used by the game port driver */ /* to talk to digital joysticks; if you're writing a sound card driver */ /* and want to add support for a /dev/joystick device, use the generic_gameport */ /* module. */ typedef struct _joystick_module { module_info minfo; /** "configure" might change the "info" if it auto-detects a device */ int (*configure)(int port, joystick_module_info * info, size_t size, void ** out_cookie); /** "read" actual data from device into "data" */ int (*read)(void * cookie, int port, extended_joystick * data, size_t size); /** "crumble" the cookie (deallocate) when done */ int (*crumble)(void * cookie, int port); /** "force" tells the joystick to exert force on the same axes as input for the specified duration */ int (*force)(void * cookie, int port, bigtime_t duration, extended_joystick * force, size_t size); int _reserved_; } joystick_module; /** 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 by the device module. */ enum { /* Joystick driver ioctl() opcodes */ B_JOYSTICK_GET_SPEED_COMPENSATION = B_JOYSTICK_DRIVER_BASE, /* arg -> ptr to int32 */ B_JOYSTICK_SET_SPEED_COMPENSATION, /* arg -> ptr to int32 */ B_JOYSTICK_GET_MAX_LATENCY, /* arg -> ptr to long long */ B_JOYSTICK_SET_MAX_LATENCY, /* arg -> ptr to long long */ B_JOYSTICK_SET_DEVICE_MODULE, /* arg -> ptr to joystick_module; also enters enhanced mode */ B_JOYSTICK_GET_DEVICE_MODULE, /* arg -> ptr to joystick_module */ B_JOYSTICK_SET_RAW_MODE /* arg -> ptr to bool (true or false) */ }; /* Speed compensation is not generally necessary, because the joystick */ /* driver is measuring using real time, not just # cycles. "0" means the */ /* default, center value. + typically returns higher values; - returns lower */ /* A typical range might be from -10 to +10, but it varies by driver */ /* Lower latency will make for more overhead in reading the joystick */ /* ideally, you set this value to just short of how long it takes you */ /* to calculate and render a frame. 30 fps -> latency 33000 */ typedef struct _generic_gameport_module { module_info minfo; status_t (*create_device)(int port, void ** out_storage); status_t (*delete_device)(void * storage); status_t (*open_hook)(void * storage, uint32 flags, void ** out_cookie); status_t (*close_hook)(void * cookie); status_t (*free_hook)(void * cookie); status_t (*control_hook)(void * cookie, uint32 op, void * data, size_t len); status_t (*read_hook)(void * cookie, off_t pos, void * data, size_t * len); status_t (*write_hook)(void * cookie, off_t pos, const void * data, size_t * len); int _reserved_; } generic_gameport_module; #endif