From 6e0dd383b3e1e97da99e0aeca0c8b27bf647ae1b Mon Sep 17 00:00:00 2001 From: Raphael Assenat Date: Thu, 20 Aug 2015 23:38:52 -0400 Subject: [PATCH] Generic gamepad structure and USB gamepad --- gamepads.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ usbpad.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++ usbpad.h | 8 +++++ 3 files changed, 170 insertions(+) create mode 100644 gamepads.h create mode 100644 usbpad.c create mode 100644 usbpad.h diff --git a/gamepads.h b/gamepads.h new file mode 100644 index 0000000..5c25459 --- /dev/null +++ b/gamepads.h @@ -0,0 +1,86 @@ +#ifndef _gamepads_h__ +#define _gamepads_h__ + +#define PAD_TYPE_NONE 0 +#define PAD_TYPE_N64 4 +#define PAD_TYPE_GAMECUBE 5 + +#define N64_RAW_SIZE 4 +#define GC_RAW_SIZE 8 + +typedef struct _n64_pad_data { + unsigned char pad_type; // PAD_TYPE_N64 + char x,y; + unsigned short buttons; + unsigned char raw_data[N64_RAW_SIZE]; +} n64_pad_data; + +#define N64_BTN_A 0x0001 +#define N64_BTN_B 0x0002 +#define N64_BTN_Z 0x0004 +#define N64_BTN_START 0x0008 +#define N64_BTN_DPAD_UP 0x0010 +#define N64_BTN_DPAD_DOWN 0x0020 +#define N64_BTN_DPAD_LEFT 0x0040 +#define N64_BTN_DPAD_RIGHT 0x0080 + +#define N64_BTN_RSVD_LOW1 0x0100 +#define N64_BTN_RSVD_LOW2 0x0200 + +#define N64_BTN_L 0x0400 +#define N64_BTN_R 0x0800 +#define N64_BTN_C_UP 0x1000 +#define N64_BTN_C_DOWN 0x2000 +#define N64_BTN_C_LEFT 0x4000 +#define N64_BTN_C_RIGHT 0x8000 + + +typedef struct _gc_pad_data { + unsigned char pad_type; // PAD_TYPE_GAMECUBE + char x,y,cx,cy,lt,rt; + unsigned short buttons; + unsigned char raw_data[GC_RAW_SIZE]; +} gc_pad_data; + +#define GC_BTN_RSVD0 0x0001 +#define GC_BTN_RSVD1 0x0002 +#define GC_BTN_RSVD2 0x0004 + +#define GC_BTN_START 0x0008 +#define GC_BTN_Y 0x0010 +#define GC_BTN_X 0x0020 +#define GC_BTN_B 0x0040 +#define GC_BTN_A 0x0080 + +#define GC_BTN_RSVD3 0x0100 + +#define GC_BTN_L 0x0200 +#define GC_BTN_R 0x0400 +#define GC_BTN_Z 0x0800 +#define GC_BTN_DPAD_UP 0x1000 +#define GC_BTN_DPAD_DOWN 0x2000 +#define GC_BTN_DPAD_RIGHT 0x4000 +#define GC_BTN_DPAD_LEFT 0x8000 + +#define GC_ALL_BUTTONS (GC_BTN_START|GC_BTN_Y|GC_BTN_X|GC_BTN_B|GC_BTN_A|GC_BTN_L|GC_BTN_R|GC_BTN_Z|GC_BTN_DPAD_UP|GC_BTN_DPAD_DOWN|GC_BTN_DPAD_RIGHT|GC_BTN_DPAD_LEFT) + +typedef struct _gamepad_data { + union { + unsigned char pad_type; // PAD_TYPE_* + n64_pad_data n64; + gc_pad_data gc; + }; +} gamepad_data; + +typedef struct { + void (*init)(void); + char (*update)(void); + char (*changed)(void); + void (*getReport)(gamepad_data *dst); + void (*setVibration)(char enable); + char (*probe)(void); /* return true if found */ +} Gamepad; + +#endif // _gamepads_h__ + + diff --git a/usbpad.c b/usbpad.c new file mode 100644 index 0000000..99fb451 --- /dev/null +++ b/usbpad.c @@ -0,0 +1,76 @@ +#include +#include "gamepads.h" +#include "usbpad.h" + +#define REPORT_ID 1 +#define REPORT_SIZE 15 + +void usbpad_init(void) +{ +} + +int usbpad_getReportSize(void) +{ + return REPORT_SIZE; +} + +static void buildReportFromGC(const gc_pad_data *gc_data, unsigned char dstbuf[REPORT_SIZE]) +{ +} + +static void buildReportFromN64(const n64_pad_data *n64_data, unsigned char dstbuf[REPORT_SIZE]) +{ + int16_t xval, yval; + + xval = n64_data->x; + yval = n64_data->y; + + /* Force official range */ + if (xval>80) xval = 80; else if (xval<-80) xval = -80; + if (yval>80) yval = 80; else if (yval<-80) yval = -80; + + /* Scale -80 ... +80 to -16000 ... +16000 */ + xval *= 200; + yval *= 200; + yval = -yval; + + /* Unsign for HID report */ + xval += 16000; + yval += 16000; + + dstbuf[0] = REPORT_ID; + dstbuf[1] = ((uint8_t*)&xval)[0]; + dstbuf[2] = ((uint8_t*)&xval)[1]; + dstbuf[3] = ((uint8_t*)&yval)[0]; + dstbuf[4] = ((uint8_t*)&yval)[1]; + + /* Inactive and centered axis */ + dstbuf[5] = 0x80; + dstbuf[6] = 0x3e; + dstbuf[7] = 0x80; + dstbuf[8] = 0x3e; + dstbuf[9] = 0x80; + dstbuf[10] = 0x3e; + dstbuf[11] = 0x80; + dstbuf[12] = 0x3e; + + /* TODO : Button mapping */ + + dstbuf[13] = n64_data->raw_data[0]; + dstbuf[14] = n64_data->raw_data[1]; +} + +void usbpad_buildReport(const gamepad_data *pad_data, unsigned char dstbuf[REPORT_SIZE]) +{ + switch (pad_data->pad_type) + { + case PAD_TYPE_N64: + buildReportFromN64(&pad_data->n64, dstbuf); + break; + + case PAD_TYPE_GAMECUBE: + buildReportFromGC(&pad_data->gc, dstbuf); + break; + } +} + diff --git a/usbpad.h b/usbpad.h new file mode 100644 index 0000000..3dbd361 --- /dev/null +++ b/usbpad.h @@ -0,0 +1,8 @@ +#ifndef USBPAD_H__ +#define USBPAD_H__ + +void usbpad_init(void); +int usbpad_getReportSize(void); +void usbpad_buildReport(const gamepad_data *pad_data, unsigned char *dstbuf); + +#endif // USBPAD_H__