mirror of
https://github.com/mist-devel/mist-firmware.git
synced 2026-02-26 08:14:13 +00:00
Started USB joystick support
This commit is contained in:
9
Makefile
9
Makefile
@@ -9,8 +9,9 @@ TODAY = `date +"%m/%d/%y"`
|
||||
|
||||
PRJ = firmware
|
||||
SRC = Cstartup_SAM7.c fat.c fdd.c firmware.c fpga.c hardware.c hdd.c main.c menu.c mmc.c osd.c syscalls.c user_io.c boot_print.c boot_logo.c rafile.c config.c tos.c ikbd.c
|
||||
SRC += usb/max3421e.c usb/usb.c usb/hub.c usb/hid.c usb/timer.c
|
||||
SRC += usb/max3421e.c usb/usb.c usb/hub.c usb/hid.c usb/hidparser.c usb/timer.c
|
||||
SRC += cdc_enumerate.c cdc_control.c
|
||||
|
||||
OBJ = $(SRC:.c=.o)
|
||||
DEP = $(SRC:.c=.d)
|
||||
|
||||
@@ -19,7 +20,7 @@ LIBDIR =
|
||||
|
||||
# Commandline options for each tool.
|
||||
DFLAGS = -I. -Iusb -DMIST
|
||||
CFLAGS = -I. -Iusb -c -fno-common -O3 -DMIST -fsigned-char -DVDATE=\"`date +"%y%m%d"`\"
|
||||
CFLAGS = $(DFLAGS) -c -fno-common -O3 -fsigned-char -DVDATE=\"`date +"%y%m%d"`\"
|
||||
AFLAGS = -ahls -mapcs-32
|
||||
LFLAGS = -nostartfiles -Wl,-Map,$(PRJ).map -T$(LINKMAP) $(LIBDIR)
|
||||
CPFLAGS = --output-target=ihex
|
||||
@@ -36,10 +37,8 @@ clean:
|
||||
rm -f *.d *.o *.hex *.elf *.map *.lst core *~ */*.d */*.o $(MKUPG) *.bin *.upg
|
||||
|
||||
INTERFACE=olimex-arm-usb-tiny-h
|
||||
ADAPTER_KHZ=10000
|
||||
|
||||
#INTERFACE=busblaster
|
||||
#ADAPTER_KHZ=100
|
||||
ADAPTER_KHZ=10000
|
||||
|
||||
reset:
|
||||
openocd -f interface/$(INTERFACE).cfg -f target/at91sam7sx.cfg --command "adapter_khz $(ADAPTER_KHZ); init; reset init; resume; shutdown"
|
||||
|
||||
8
debug.h
8
debug.h
@@ -2,6 +2,14 @@
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
// ------------ usb debugging -----------
|
||||
|
||||
#if 1
|
||||
#define hidp_debugf(...) iprintf(__VA_ARGS__)
|
||||
#else
|
||||
#define hidp_debugf(...)
|
||||
#endif
|
||||
|
||||
// ------------ generic debugging -----------
|
||||
|
||||
#if 0
|
||||
|
||||
83
usb/hid.c
83
usb/hid.c
@@ -3,9 +3,17 @@
|
||||
#include "usb.h"
|
||||
#include "max3421e.h"
|
||||
#include "timer.h"
|
||||
#include "hidparser.h"
|
||||
#include "../user_io.h"
|
||||
|
||||
// joystick todo:
|
||||
// - renumber on unplug
|
||||
// - shift legacy joysticks up
|
||||
// - emulate extra joysticks (at printerport, ...)
|
||||
// - second fire button (no known system uses it, but OSD may have a use ...)
|
||||
|
||||
static unsigned char kbd_led_state = 0; // default: all leds off
|
||||
static unsigned char joysticks = 0; // number of detected usb joysticks
|
||||
|
||||
static void hexdump(void *data, int size) {
|
||||
int i,n = 0, b2c;
|
||||
@@ -42,12 +50,26 @@ static uint8_t hid_get_report_descr(usb_device_t *dev, uint8_t iface, uint16_t s
|
||||
iprintf("%s(%x, if=%d, size=%d)\n", __FUNCTION__, dev->bAddress, iface, size);
|
||||
|
||||
uint8_t buf[size];
|
||||
usb_hid_info_t *info = &(dev->hid_info);
|
||||
uint8_t rcode = usb_ctrl_req( dev, HID_REQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
|
||||
HID_DESCRIPTOR_REPORT, iface, size, size, buf, NULL);
|
||||
|
||||
if(!rcode)
|
||||
if(!rcode) {
|
||||
iprintf("HID report descriptor:\n");
|
||||
hexdump(buf, size);
|
||||
|
||||
|
||||
// we got a report descriptor. Try to parse it
|
||||
if(parse_report_descriptor(buf, size)) {
|
||||
if(hid_conf[0].type == CONFIG_TYPE_JOYSTICK) {
|
||||
iprintf("Detected USB joystick %d\n", joysticks);
|
||||
|
||||
info->iface_info[iface].device_type = HID_DEVICE_JOYSTICK;
|
||||
info->iface_info[iface].conf = hid_conf[0];
|
||||
info->iface_info[iface].jindex = joysticks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rcode;
|
||||
}
|
||||
|
||||
@@ -119,6 +141,7 @@ static uint8_t usb_hid_parse_conf(usb_device_t *dev, uint8_t conf, uint16_t len)
|
||||
info->iface_info[info->bNumIfaces].iface_idx = p->iface_desc.bInterfaceNumber;
|
||||
info->iface_info[info->bNumIfaces].has_boot_mode = false;
|
||||
info->iface_info[info->bNumIfaces].device_type = HID_DEVICE_UNKNOWN;
|
||||
info->iface_info[info->bNumIfaces].conf.type = CONFIG_TYPE_NONE;
|
||||
|
||||
if(p->iface_desc.bInterfaceSubClass == HID_BOOT_INTF_SUBCLASS) {
|
||||
iprintf("Iface %d is Boot sub class\n", info->bNumIfaces);
|
||||
@@ -265,10 +288,13 @@ static uint8_t usb_hid_init(usb_device_t *dev) {
|
||||
|
||||
// process all supported interfaces
|
||||
for(i=0; i<info->bNumIfaces; i++) {
|
||||
rcode = hid_get_report_descr(dev,
|
||||
info->iface_info[i].iface_idx, info->iface_info[i].report_size);
|
||||
if (rcode)
|
||||
return rcode;
|
||||
// no boot mode, try to parse HID report descriptor
|
||||
if(!info->iface_info[info->bNumIfaces].has_boot_mode) {
|
||||
rcode = hid_get_report_descr(dev,
|
||||
info->iface_info[i].iface_idx, info->iface_info[i].report_size);
|
||||
if (rcode)
|
||||
return rcode;
|
||||
}
|
||||
|
||||
rcode = hid_set_idle(dev, info->iface_info[i].iface_idx, 0, 0);
|
||||
if (rcode && rcode != hrSTALL)
|
||||
@@ -291,7 +317,19 @@ static uint8_t usb_hid_init(usb_device_t *dev) {
|
||||
}
|
||||
|
||||
static uint8_t usb_hid_release(usb_device_t *dev) {
|
||||
usb_hid_info_t *info = &(dev->hid_info);
|
||||
|
||||
puts(__FUNCTION__);
|
||||
|
||||
int8_t i;
|
||||
// check if a joystick is released
|
||||
for(i=0;i<info->bNumIfaces;i++) {
|
||||
if(info->iface_info[i].device_type == HID_DEVICE_JOYSTICK) {
|
||||
iprintf("releasing joystick #%d, renumbering\n", info->iface_info[i].jindex);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -337,6 +375,39 @@ static uint8_t usb_hid_poll(usb_device_t *dev) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(info->iface_info[i].device_type == HID_DEVICE_JOYSTICK) {
|
||||
hid_config_t *conf = &info->iface_info[i].conf;
|
||||
uint8_t jmap = 0;
|
||||
uint8_t ax;
|
||||
|
||||
iprintf("Joystick data:\n");
|
||||
hexdump(buf, read);
|
||||
|
||||
// currently only byte sized axes are allowed
|
||||
ax = buf[conf->joystick.axis_byte_offset[0]];
|
||||
if(ax < 64) jmap |= JOY_LEFT;
|
||||
if(ax > 192) jmap |= JOY_RIGHT;
|
||||
ax = buf[conf->joystick.axis_byte_offset[1]];
|
||||
if(ax < 64) jmap |= JOY_UP;
|
||||
if(ax > 192) jmap |= JOY_DOWN;
|
||||
|
||||
// ... and one button
|
||||
if(buf[conf->joystick.button_byte_offset] & conf->joystick.button0_bitmask)
|
||||
jmap |= JOY_BTN1;
|
||||
|
||||
// swap joystick 0 and 1 since 1 is the one used primarily on most systems
|
||||
ax = info->iface_info[i].jindex;
|
||||
if(ax == 0) ax = 1;
|
||||
else if(ax == 1) ax = 0;
|
||||
|
||||
// check if joystick state has changed
|
||||
if(jmap != info->iface_info[i].jmap) {
|
||||
// and feed into joystick input system
|
||||
user_io_joystick(ax, jmap);
|
||||
info->iface_info[i].jmap = jmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#include "hidparser.h"
|
||||
|
||||
#define HID_LED_NUM_LOCK 0x01
|
||||
#define HID_LED_CAPS_LOCK 0x02
|
||||
@@ -40,6 +41,7 @@
|
||||
#define HID_DEVICE_UNKNOWN 0
|
||||
#define HID_DEVICE_MOUSE 1
|
||||
#define HID_DEVICE_KEYBOARD 2
|
||||
#define HID_DEVICE_JOYSTICK 3
|
||||
|
||||
typedef struct {
|
||||
uint8_t iface_idx;
|
||||
@@ -48,6 +50,12 @@ typedef struct {
|
||||
uint8_t device_type;
|
||||
bool has_boot_mode; // device supports boot mode
|
||||
|
||||
// additional info extracted from the report descriptor
|
||||
// (currently only used for joysticks)
|
||||
uint8_t jmap; // last reported joystick state
|
||||
uint8_t jindex; // joystick index
|
||||
hid_config_t conf;
|
||||
|
||||
} usb_hid_iface_info_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
403
usb/hidparser.c
Normal file
403
usb/hidparser.c
Normal file
@@ -0,0 +1,403 @@
|
||||
// http://www.frank-zhao.com/cache/hid_tutorial_1.php
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "hidparser.h"
|
||||
#include "debug.h"
|
||||
|
||||
#if 0
|
||||
#define hidp_extreme_debugf(...) iprintf(__VA_ARGS__)
|
||||
#else
|
||||
#define hidp_extreme_debugf(...)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint8_t bSize: 2;
|
||||
uint8_t bType: 2;
|
||||
uint8_t bTag: 4;
|
||||
} __attribute__((packed)) item_t;
|
||||
|
||||
// flags for joystick components required
|
||||
#define JOYSTICK_REQ_AXIS_X 0x01
|
||||
#define JOYSTICK_REQ_AXIS_Y 0x02
|
||||
#define JOYSTICK_REQ_BTN_0 0x04
|
||||
#define JOYSTICK_COMPLETE (JOYSTICK_REQ_AXIS_X | JOYSTICK_REQ_AXIS_Y | JOYSTICK_REQ_BTN_0)
|
||||
|
||||
hid_config_t hid_conf[MAX_CONF];
|
||||
|
||||
#define USAGE_PAGE_GENERIC_DESKTOP 1
|
||||
#define USAGE_PAGE_SIMULATION 2
|
||||
#define USAGE_PAGE_VR 3
|
||||
#define USAGE_PAGE_SPORT 4
|
||||
#define USAGE_PAGE_GAMING 5
|
||||
#define USAGE_PAGE_GENERIC_DEVICE 6
|
||||
#define USAGE_PAGE_KEYBOARD 7
|
||||
#define USAGE_PAGE_LEDS 8
|
||||
#define USAGE_PAGE_BUTTON 9
|
||||
#define USAGE_PAGE_ORDINAL 10
|
||||
#define USAGE_PAGE_TELEPHONY 11
|
||||
#define USAGE_PAGE_CONSUMER 12
|
||||
|
||||
|
||||
#define USAGE_POINTER 1
|
||||
#define USAGE_MOUSE 2
|
||||
#define USAGE_JOYSTICK 4
|
||||
#define USAGE_GAMEPAD 5
|
||||
#define USAGE_KEYBOARD 6
|
||||
#define USAGE_KEYPAD 7
|
||||
#define USAGE_MULTIAXIS 8
|
||||
|
||||
#define USAGE_X 48
|
||||
#define USAGE_Y 49
|
||||
#define USAGE_Z 50
|
||||
#define USAGE_WHEEL 56
|
||||
|
||||
bool parse_report_descriptor(uint8_t *rep, uint16_t rep_size) {
|
||||
int8_t app_collection = 0;
|
||||
int8_t phys_log_collection = 0;
|
||||
uint8_t skip_collection = 0;
|
||||
int8_t generic_desktop = -1; // depth at which first gen_desk was found
|
||||
uint8_t collection_depth = 0;
|
||||
|
||||
uint8_t i;
|
||||
|
||||
//
|
||||
uint8_t report_size, report_count, config_idx = 0;
|
||||
uint16_t bit_count = 0, usage_count = 0;
|
||||
|
||||
// mask used to check of all required components have been found, so
|
||||
// that e.g. both axes and the button of a joystick are ready to be used
|
||||
uint8_t setup_complete = 0;
|
||||
|
||||
// joystick/mouse components
|
||||
int8_t axis[2] = { -1, -1};
|
||||
uint8_t btns = 0;
|
||||
|
||||
for(i=0;i<MAX_CONF;i++)
|
||||
hid_conf[i].type = CONFIG_TYPE_NONE;
|
||||
|
||||
while(rep_size) {
|
||||
// extract short item
|
||||
uint8_t tag = ((item_t*)rep)->bTag;
|
||||
uint8_t type = ((item_t*)rep)->bType;
|
||||
uint8_t size = ((item_t*)rep)->bSize;
|
||||
|
||||
rep++;
|
||||
rep_size--; // one byte consumed
|
||||
|
||||
uint32_t value = 0;
|
||||
if(size) { // size 1/2/3
|
||||
value = *rep++;
|
||||
rep_size--;
|
||||
}
|
||||
|
||||
if(size > 1) { // size 2/3
|
||||
value = (value & 0xff) + ((uint32_t)(*rep++)<<8);
|
||||
rep_size--;
|
||||
}
|
||||
|
||||
if(size > 2) { // size 3
|
||||
value &= 0xffff;
|
||||
value |= ((uint32_t)(*rep++)<<16);
|
||||
value |= ((uint32_t)(*rep++)<<24);
|
||||
rep_size-=2;
|
||||
}
|
||||
|
||||
// hidp_extreme_debugf("Value = %d (%u)\n", value, value);
|
||||
|
||||
// we are currently skipping an unknown/unsupported collection)
|
||||
if(skip_collection) {
|
||||
if(!type) { // main item
|
||||
// any new collection increases the depth of collections to skip
|
||||
if(tag == 10) {
|
||||
skip_collection++;
|
||||
collection_depth++;
|
||||
}
|
||||
|
||||
// any end collection decreases it
|
||||
if(tag == 12) {
|
||||
skip_collection--;
|
||||
collection_depth--;
|
||||
|
||||
// leaving the depth the generic desktop was valid for
|
||||
if(generic_desktop > collection_depth)
|
||||
generic_desktop = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
// hidp_extreme_debugf("-> Item tag=%d type=%d size=%d\n", tag, type, size);
|
||||
|
||||
switch(type) {
|
||||
case 0:
|
||||
// main item
|
||||
|
||||
switch(tag) {
|
||||
case 8:
|
||||
//
|
||||
if(btns) {
|
||||
hidp_debugf("BUTTON0 @ %d (byte %d, mask %d)\n",
|
||||
bit_count, bit_count/8, 1 << (bit_count%8));
|
||||
if(hid_conf[config_idx].type == CONFIG_TYPE_JOYSTICK) {
|
||||
hid_conf[config_idx].joystick.button_byte_offset = bit_count/8;
|
||||
hid_conf[config_idx].joystick.button0_bitmask = 1 << (bit_count%8);
|
||||
setup_complete |= JOYSTICK_REQ_BTN_0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
char c;
|
||||
for(c=0;c<2;c++) {
|
||||
if(axis[c] >= 0) {
|
||||
uint16_t cnt = bit_count + report_size * axis[c];
|
||||
hidp_debugf("%c-AXIS @ %d (byte %d)\n", 'X'+c,
|
||||
cnt, cnt/8);
|
||||
|
||||
// only 8 bit axes at byte boundaries are supported for
|
||||
// joysticks
|
||||
if((hid_conf[config_idx].type == CONFIG_TYPE_JOYSTICK) &&
|
||||
(report_size == 8) && ((cnt&7) == 0)) {
|
||||
// save in joystick config
|
||||
hid_conf[config_idx].joystick.axis_byte_offset[c] = cnt/8;
|
||||
if(c==0) setup_complete |= JOYSTICK_REQ_AXIS_X;
|
||||
if(c==1) setup_complete |= JOYSTICK_REQ_AXIS_Y;
|
||||
}
|
||||
|
||||
if(report_size != 8)
|
||||
hidp_debugf("Unsupported report size %d\n", report_size);
|
||||
|
||||
if((cnt&7) != 0)
|
||||
hidp_debugf("Unsupported bit offset %d\n", cnt&7);
|
||||
}
|
||||
}
|
||||
|
||||
hidp_extreme_debugf("INPUT(%d)\n", value);
|
||||
|
||||
// reset for next inputs
|
||||
bit_count += report_count * report_size;
|
||||
usage_count = 0;
|
||||
btns = 0;
|
||||
axis[0] = axis[1] = -1;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
hidp_extreme_debugf("OUTPUT(%d)\n", value);
|
||||
break;
|
||||
|
||||
case 11:
|
||||
hidp_extreme_debugf("FEATURE(%d)\n", value);
|
||||
break;
|
||||
|
||||
case 10:
|
||||
hidp_extreme_debugf("COLLECTION(%d)\n", value);
|
||||
collection_depth++;
|
||||
|
||||
if(value == 1) { // app collection
|
||||
hidp_extreme_debugf(" -> application\n");
|
||||
app_collection++;
|
||||
} else if(value == 0) { // physical collection
|
||||
hidp_extreme_debugf(" -> physical\n");
|
||||
phys_log_collection++;
|
||||
} else if(value == 2) { // logical collection
|
||||
hidp_extreme_debugf(" -> logical\n");
|
||||
phys_log_collection++;
|
||||
} else {
|
||||
hidp_extreme_debugf("skipping unsupported collection\n");
|
||||
skip_collection++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 12:
|
||||
hidp_extreme_debugf("END_COLLECTION(%d)\n", value);
|
||||
collection_depth--;
|
||||
|
||||
// leaving the depth the generic desktop was valid for
|
||||
if(generic_desktop > collection_depth)
|
||||
generic_desktop = -1;
|
||||
|
||||
if(phys_log_collection) {
|
||||
hidp_extreme_debugf(" -> phys/log end\n");
|
||||
phys_log_collection--;
|
||||
} else if(app_collection) {
|
||||
hidp_extreme_debugf(" -> app end\n");
|
||||
app_collection--;
|
||||
} else {
|
||||
hidp_debugf(" -> unexpected\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
hidp_debugf("unexpected main item %d\n", tag);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// global item
|
||||
switch(tag) {
|
||||
case 0:
|
||||
hidp_extreme_debugf("USAGE_PAGE(%d/0x%x)\n", value, value);
|
||||
|
||||
if(value == USAGE_PAGE_KEYBOARD) {
|
||||
hidp_extreme_debugf(" -> Keyboard\n");
|
||||
} else if(value == USAGE_PAGE_GAMING) {
|
||||
hidp_extreme_debugf(" -> Game device\n");
|
||||
} else if(value == USAGE_PAGE_LEDS) {
|
||||
hidp_extreme_debugf(" -> LEDs\n");
|
||||
} else if(value == USAGE_PAGE_CONSUMER) {
|
||||
hidp_extreme_debugf(" -> Consumer\n");
|
||||
} else if(value == USAGE_PAGE_BUTTON) {
|
||||
hidp_extreme_debugf(" -> Buttons\n");
|
||||
btns = 1;
|
||||
} else if(value == USAGE_PAGE_GENERIC_DESKTOP) {
|
||||
hidp_extreme_debugf(" -> Generic Desktop\n");
|
||||
|
||||
if(generic_desktop < 0)
|
||||
generic_desktop = collection_depth;
|
||||
} else
|
||||
hidp_extreme_debugf(" -> UNSUPPORTED USAGE_PAGE\n");
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
hidp_extreme_debugf("LOGICAL_MINIMUM(%d/%d)\n", value, (int8_t)value);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
hidp_extreme_debugf("LOGICAL_MAXIMUM(%d)\n", value);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
hidp_extreme_debugf("PHYSICAL_MINIMUM(%d/%d)\n", value, (int8_t)value);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
hidp_extreme_debugf("PHYSICAL_MAXIMUM(%d)\n", value);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
hidp_extreme_debugf("UNIT_EXPONENT(%d)\n", value);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
hidp_extreme_debugf("UNIT(%d)\n", value);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
hidp_extreme_debugf("REPORT_SIZE(%d)\n", value);
|
||||
report_size = value;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
hidp_extreme_debugf("REPORT_ID(%d)\n", value);
|
||||
hid_conf[config_idx].report_id = value;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
hidp_extreme_debugf("REPORT_COUNT(%d)\n", value);
|
||||
report_count = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
hidp_debugf("unexpected global item %d\n", tag);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// local item
|
||||
switch(tag) {
|
||||
case 0:
|
||||
// we only support mice, keyboards and joysticks
|
||||
hidp_extreme_debugf("USAGE(%d/0x%x)\n", value, value);
|
||||
|
||||
if( !collection_depth && (value == USAGE_KEYBOARD)) {
|
||||
// usage(keyboard) is always allowed
|
||||
hidp_debugf(" -> Keyboard\n");
|
||||
hid_conf[config_idx].type = CONFIG_TYPE_KEYBOARD;
|
||||
} else if(!collection_depth && (value == USAGE_MOUSE)) {
|
||||
// usage(mouse) is always allowed
|
||||
hidp_debugf(" -> Mouse\n");
|
||||
hid_conf[config_idx].type = CONFIG_TYPE_MOUSE;
|
||||
} else if(!collection_depth &&
|
||||
((value == USAGE_GAMEPAD) || (value == USAGE_JOYSTICK))) {
|
||||
hidp_extreme_debugf(" -> Gamepad/Joystick\n");
|
||||
hidp_debugf("Gamepad/Joystick usage found\n");
|
||||
hid_conf[config_idx].type = CONFIG_TYPE_JOYSTICK;
|
||||
} else if(value == USAGE_POINTER && app_collection) {
|
||||
// usage(pointer) is allowed within the application collection
|
||||
|
||||
hidp_debugf(" -> Pointer\n");
|
||||
|
||||
} else if((value == USAGE_X || value == USAGE_Y ||
|
||||
value == USAGE_Z || value == USAGE_WHEEL) &&
|
||||
app_collection) {
|
||||
// usage(x) and usage(y) are allowed within the app collection
|
||||
hidp_extreme_debugf(" -> axis usage\n");
|
||||
|
||||
// we support x and y axis on joysticks
|
||||
if(hid_conf[config_idx].type == CONFIG_TYPE_JOYSTICK) {
|
||||
if(value == USAGE_X) {
|
||||
hidp_extreme_debugf("JOYSTICK: found x axis @ %d\n", usage_count);
|
||||
axis[0] = usage_count;
|
||||
}
|
||||
if(value == USAGE_Y) {
|
||||
hidp_extreme_debugf("JOYSTICK: found y axis @ %d\n", usage_count);
|
||||
axis[1] = usage_count;
|
||||
}
|
||||
}
|
||||
usage_count++;
|
||||
} else {
|
||||
hidp_extreme_debugf(" -> UNSUPPORTED USAGE\n");
|
||||
// return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
hidp_extreme_debugf("USAGE_MINIMUM(%d)\n", value);
|
||||
usage_count -= (value-1);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
hidp_extreme_debugf("USAGE_MAXIMUM(%d)\n", value);
|
||||
usage_count += value;
|
||||
break;
|
||||
|
||||
default:
|
||||
hidp_extreme_debugf("unexpected local item %d\n", tag);
|
||||
// return false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// reserved
|
||||
hidp_extreme_debugf("unexpected resreved item %d\n", tag);
|
||||
// return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hidp_debugf("total bit count: %d (%d bytes, %d bits)\n",
|
||||
bit_count, bit_count/8, bit_count%8);
|
||||
|
||||
// check if something useful was detected
|
||||
if(hid_conf[config_idx].type == CONFIG_TYPE_JOYSTICK) {
|
||||
if(setup_complete == JOYSTICK_COMPLETE) {
|
||||
hidp_debugf("Joystick ok\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
hidp_debugf("Ignoring incomplete joystick %x\n", setup_complete);
|
||||
} else
|
||||
hidp_debugf("No joystick %d\n", config_idx);
|
||||
|
||||
return false;
|
||||
}
|
||||
28
usb/hidparser.h
Normal file
28
usb/hidparser.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef HIDPARSER_H
|
||||
#define HIDPARSER_H
|
||||
|
||||
#define CONFIG_TYPE_NONE 0
|
||||
#define CONFIG_TYPE_MOUSE 1
|
||||
#define CONFIG_TYPE_KEYBOARD 2
|
||||
#define CONFIG_TYPE_JOYSTICK 3
|
||||
|
||||
// currently only joysticks are supported
|
||||
typedef struct {
|
||||
uint8_t type: 2; // CONFIG_TYPE_...
|
||||
uint8_t report_id;
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint8_t axis_byte_offset[2]; // x and y axis
|
||||
uint8_t button_byte_offset;
|
||||
uint8_t button0_bitmask;
|
||||
} joystick;
|
||||
};
|
||||
} hid_config_t;
|
||||
|
||||
#define MAX_CONF 2
|
||||
extern hid_config_t hid_conf[MAX_CONF];
|
||||
|
||||
bool parse_report_descriptor(uint8_t *rep, uint16_t rep_size);
|
||||
|
||||
#endif // HIDPARSER_H
|
||||
@@ -137,6 +137,8 @@ void user_io_detect_core_type() {
|
||||
}
|
||||
|
||||
void user_io_joystick(unsigned char joystick, unsigned char map) {
|
||||
iprintf("j%d: %x\n", joystick, map);
|
||||
|
||||
// most cores process joystick events themselves
|
||||
if((core_type == CORE_TYPE_MINIMIG) ||
|
||||
(core_type == CORE_TYPE_PACE) ||
|
||||
@@ -314,7 +316,7 @@ void user_io_poll() {
|
||||
if(status != bit8_status) {
|
||||
char buffer[512];
|
||||
|
||||
bit8_debugf("st %08x", status);
|
||||
// bit8_debugf("st %08x", status);
|
||||
bit8_status = status;
|
||||
|
||||
// sector read testing
|
||||
@@ -322,7 +324,7 @@ void user_io_poll() {
|
||||
|
||||
if((status & 0xff) == 0xa5) {
|
||||
unsigned long sector = (status>>8)&0xffffff;
|
||||
bit8_debugf("sec rd %u", sector);
|
||||
// bit8_debugf("sec rd %u", sector);
|
||||
|
||||
if(MMC_Read(sector, buffer)) {
|
||||
short i;
|
||||
|
||||
Reference in New Issue
Block a user