Skip to content

Commit

Permalink
Merge pull request #118 from UzixLS/master
Browse files Browse the repository at this point in the history
Several improvements for USB joysticks support
  • Loading branch information
gyurco authored Sep 21, 2024
2 parents 494f448 + ac42d36 commit c1560a4
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 76 deletions.
3 changes: 2 additions & 1 deletion osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ This is the Minimig OSD (on-screen-display) handler.
#include "spi.h"

#include "logo.h"
#include "state.h"
#include "user_io.h"

extern unsigned char charfont[128][8];
Expand Down Expand Up @@ -590,7 +591,7 @@ unsigned char OsdGetCtrl(void)
if(!c) {
static unsigned char last_but = 0;
if(!disable_menu) {
unsigned char but = CheckButton();
unsigned char but = CheckButton() || StateJoyGetMenuAny();
if(!but && last_but) c = KEY_MENU;
last_but = but;
} else {
Expand Down
24 changes: 21 additions & 3 deletions state.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ static mist_joystick_t mist_joystick_temp;
.right=0, \
.usb_state=0, \
.usb_state_extra=0, \
.analogue={0,0,0,0} \
.analogue={0,0,0,0}, \
.menu_button=0, \
}

/* latest joystick state */
Expand All @@ -53,7 +54,7 @@ static mist_joystick_t mist_joysticks[7] = { // 7th one is dummy, used to store
joy_init,
joy_init
};



// De-init all joysticks, useful when changing core
void StateReset() {
Expand All @@ -64,6 +65,7 @@ void StateReset() {
StateJoySetExtra(0, idx);
StateJoySetRight(0, idx);
StateJoySetAnalogue(0, 0, 0, 0, idx);
StateJoySetMenu(0, idx);
StateUsbIdSet(0, 0, 0, idx);
StateUsbJoySet(0, 0, idx);
}
Expand Down Expand Up @@ -91,6 +93,11 @@ void StateJoySetAnalogue(uint8_t lx, uint8_t ly, uint8_t rx, uint8_t ry, uint8_t
mist_joysticks[joy_num].analogue[2] = rx;
mist_joysticks[joy_num].analogue[3] = ry;
}
static uint8_t mist_joystick_menu;
void StateJoySetMenu(uint8_t c, uint8_t joy_num) {
if (joy_num > 5) return;
mist_joysticks[joy_num].menu_button = c;
}

uint8_t StateJoyGet(uint8_t joy_num) {
return (joy_num < 6) ? mist_joysticks[joy_num].state : 0;
Expand All @@ -104,6 +111,18 @@ uint8_t StateJoyGetRight(uint8_t joy_num) {
uint8_t StateJoyGetAnalogue(uint8_t idx, uint8_t joy_num) {
return (joy_num < 6 && idx < 4) ? mist_joysticks[joy_num].analogue[idx] : 0;
}
uint8_t StateJoyGetMenu(uint8_t joy_num) {
return (joy_num < 6) ? mist_joysticks[joy_num].menu_button : 0;
}
uint8_t StateJoyGetMenuAny() {
uint8_t joy_num;
for(joy_num=0; joy_num<6; joy_num++) {
if (mist_joysticks[joy_num].menu_button)
return mist_joysticks[joy_num].menu_button;
}
return 0;
}



void StateUsbJoySet(uint8_t usbjoy, uint8_t usbextra, uint8_t joy_num) {
Expand Down Expand Up @@ -191,4 +210,3 @@ void StateKeyboardPressed(uint8_t *keycodes) {
for(i=0; i<6; i++)
keycodes[i]=key_pressed[i];
}

13 changes: 9 additions & 4 deletions state.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@
void StateReset();

//// type definitions ////


typedef struct {
uint16_t vid; // USB vendor ID
uint16_t pid; // USB product ID
uint8_t num_buttons; // number of physical buttons reported by HID parsing
uint8_t state; // virtual joystick: current state of 4 direction + 4 first buttons
uint8_t state_extra; // current state of 8 more buttons
uint8_t right; // right stick state
uint8_t right; // right stick state
uint8_t usb_state; // raw USB state of direction and buttons
uint8_t usb_state_extra; // raw USB state of 8 more buttons
uint8_t analogue[4];
uint8_t analogue[4];
uint8_t menu_button;

} mist_joystick_t;

Expand Down Expand Up @@ -52,11 +53,15 @@ uint8_t StateJoyGetAnalogue(uint8_t idx, uint8_t joy_num);
uint8_t StateNumJoysticks();
void StateNumJoysticksSet(uint8_t num);

void StateJoySetMenu(uint8_t c, uint8_t joy_num);
uint8_t StateJoyGetMenu(uint8_t joy_num);
uint8_t StateJoyGetMenuAny();


// keyboard status
void StateKeyboardSet( uint8_t modifier, uint8_t* pressed, uint16_t* pressed_ps2); //get usb and ps2 codes
uint8_t StateKeyboardModifiers();
void StateKeyboardPressed(uint8_t *pressed);
void StateKeyboardPressedPS2(uint16_t *keycodes);

#endif

14 changes: 12 additions & 2 deletions usb/hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,8 +423,15 @@ static uint8_t usb_hid_init(usb_device_t *dev, usb_device_descriptor_t *dev_desc
}
}
rcode = hid_set_idle(dev, info->iface[i].iface_idx, 0, 0);
if (rcode && rcode != hrSTALL)
if (rcode && rcode != hrSTALL) {
hid_debugf("set idle error %d", rcode);
if(info->iface[i].device_type == HID_DEVICE_JOYSTICK) {
uint8_t c_jindex = joystick_index(info->iface[i].jindex);
hid_debugf("releasing joystick #%d, renumbering", c_jindex);
joystick_release(c_jindex);
}
return rcode;
}

// enable boot mode if its not diabled
if(info->iface[i].has_boot_mode && !info->iface[i].ignore_boot_mode) {
Expand Down Expand Up @@ -893,7 +900,10 @@ static uint8_t usb_hid_poll(usb_device_t *dev) {
if (timer_check(iface->qLastPollTime, iface->interval)) { // poll at requested rate
// hid_debugf("poll %d...", iface->ep.epAddr);
uint16_t read = iface->ep.maxPktSize;
uint8_t buf[iface->ep.maxPktSize];
// report may not fit into one packet
if (iface->conf.report_size > read)
read = iface->conf.report_size;
uint8_t buf[read];
// clear buffer
memset(buf, 0, iface->ep.maxPktSize);
uint8_t rcode = usb_in_transfer(dev, &(iface->ep), &read, buf);
Expand Down
14 changes: 14 additions & 0 deletions usb/hidparser.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ bool parse_report_descriptor(uint8_t *rep, uint16_t rep_size, hid_report_t *conf
return true;
else {
// retry with next report
memset(conf, 0, sizeof(*conf));
bit_count = 0;
report_complete = 0;
}
Expand Down Expand Up @@ -362,6 +363,19 @@ bool parse_report_descriptor(uint8_t *rep, uint16_t rep_size, hid_report_t *conf
break;

case 8:
// Next report is beginning from this point
// If we're already got report descriptor and it's satisfies us - stop further parsing
if (conf->report_id) {
if(report_is_usable(bit_count, report_complete, conf)) {
return true;
}
else {
// reset report items and try with next report
memset(conf, 0, sizeof(*conf));
bit_count = 0;
report_complete = 0;
}
}
hidp_extreme_debugf("REPORT_ID(%d)", value);
conf->report_id = value;
break;
Expand Down
39 changes: 36 additions & 3 deletions usb/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "usb.h"
#include "timer.h"
#include "max3421e.h"

static uint8_t usb_hub_clear_hub_feature(usb_device_t *dev, uint8_t fid ) {
return( usb_ctrl_req( dev, USB_HUB_REQ_CLEAR_HUB_FEATURE,
Expand Down Expand Up @@ -210,6 +211,9 @@ static uint8_t usb_hub_port_status_change(usb_device_t *dev, uint8_t port, hub_e
return 0;
}

// Some peripherals may perform a quick reconnection, which causes the disconnect event to be missed.
usb_release_device(dev->bAddress, port);

// timer_delay_msec(100);

iprintf("resetting port %d\n", port);
Expand Down Expand Up @@ -239,12 +243,42 @@ static uint8_t usb_hub_port_status_change(usb_device_t *dev, uint8_t port, hub_e
usb_hub_clear_port_feature(dev, HUB_FEATURE_C_PORT_RESET, port, 0);
usb_hub_clear_port_feature(dev, HUB_FEATURE_C_PORT_CONNECTION, port, 0);

rcode = usb_configure(dev->bAddress, port,
for(unsigned retries = 0; retries < 3; retries++) {
rcode = usb_configure(dev->bAddress, port,
(evt.bmStatus & USB_HUB_PORT_STATUS_PORT_LOW_SPEED)!=0 );
if (rcode) iprintf("USB configure error: %d\n", rcode);
if (!rcode)
break;
iprintf("USB configure error: %d\n", rcode);
if (rcode == hrJERR) {
// Some devices returns this when plugged in - trying to initialize the device again usually works
timer_delay_msec(100);
continue;
}
else {
break;
}
}

bResetInitiated = false;
break;

// Unhandled event, this shouldn't happen under normal conditions
default:
iprintf("unexpected status on port %d\n", port);
if ((evt.bmChange & USB_HUB_PORT_STATUS_PORT_RESET) && (evt.bmChange & USB_HUB_PORT_STATUS_PORT_CONNECTION)) {
// Reconnection happens during reset
usb_hub_clear_port_feature(dev, HUB_FEATURE_C_PORT_RESET, port, 0);
bResetInitiated = false;
}
if (evt.bmChange & USB_HUB_PORT_STATUS_PORT_SUSPEND)
usb_hub_clear_port_feature(dev, HUB_FEATURE_C_PORT_SUSPEND, port, 0);
if (evt.bmChange & USB_HUB_PORT_STATUS_PORT_OVER_CURRENT)
usb_hub_clear_port_feature(dev, HUB_FEATURE_C_PORT_OVER_CURRENT, port, 0);
if (evt.bmStatus & USB_HUB_PORT_STATUS_PORT_SUSPEND)
usb_hub_clear_port_feature(dev, HUB_FEATURE_PORT_SUSPEND, port, 0);
if (!(evt.bmStatus & USB_HUB_PORT_STATUS_PORT_POWER))
usb_hub_set_port_feature(dev, HUB_FEATURE_PORT_POWER, port, 0);
break;
}

return 0;
Expand Down Expand Up @@ -325,4 +359,3 @@ static uint8_t usb_hub_poll(usb_device_t *dev) {

const usb_device_class_config_t usb_hub_class = {
usb_hub_init, usb_hub_release, usb_hub_poll };

9 changes: 3 additions & 6 deletions usb/usb.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <stdio.h>
#include <string.h>

#include "timer.h"
#include "usb.h"
Expand Down Expand Up @@ -52,20 +53,16 @@ uint8_t usb_configure(uint8_t parent, uint8_t port, bool lowspeed) {
if(i < USB_NUMDEVICES) {
iprintf("using free entry at %d\n", i);

usb_device_t *d = dev+i;
usb_device_t *d = &dev[i];
memset(d, 0, sizeof(*d));

// setup generic info
d->bAddress = 0;
d->parent = parent;
d->lowspeed = lowspeed;
d->port = port;
d->class = NULL;
d->vid = d->pid = 0;

// setup endpoint 0
d->ep0.epAddr = 0;
d->ep0.maxPktSize = 8;
d->ep0.epAttribs = 0;
d->ep0.bmNakPower = USB_NAK_MAX_POWER;

if(rcode = usb_get_dev_descr( d, 8, &dev_desc ))
Expand Down
Loading

0 comments on commit c1560a4

Please sign in to comment.