bdk: joycon: use flow control to improve packet integrity

This commit is contained in:
CTCaer 2022-05-09 05:55:06 +03:00
parent 2aed1b3b83
commit 47d06d0e8a

View file

@ -586,9 +586,8 @@ static void _jc_parse_wired_init(joycon_ctxt_t *jc, const u8* data, u32 size)
} }
} }
static void jc_uart_pkt_parse(joycon_ctxt_t *jc, const u8* packet, size_t size) static void _jc_uart_pkt_parse(joycon_ctxt_t *jc, const jc_wired_hdr_t *pkt, size_t size)
{ {
jc_wired_hdr_t *pkt = (jc_wired_hdr_t *)packet;
switch (pkt->cmd) switch (pkt->cmd)
{ {
case JC_HORI_INPUT_RPT_CMD: case JC_HORI_INPUT_RPT_CMD:
@ -613,20 +612,14 @@ static void _jc_rcv_pkt(joycon_ctxt_t *jc)
if (!jc->detected) if (!jc->detected)
return; return;
// Check if device stopped sending data. u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100);
u32 uart_irq = uart_get_IIR(jc->uart); if (len < 8)
if (uart_irq != UART_IIR_REDI)
return; return;
u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100);
// Check valid size and uart reply magic. // Check valid size and uart reply magic.
if (len > 7 && !memcmp(jc->buf, "\x19\x81\x03", 3)) jc_wired_hdr_t *jc_pkt = (jc_wired_hdr_t *)jc->buf;
{ if (!memcmp(jc_pkt->uart_hdr.magic, "\x19\x81\x03", 3))
jc_wired_hdr_t *pkt = (jc_wired_hdr_t *)(jc->buf); _jc_uart_pkt_parse(jc, jc_pkt, jc_pkt->uart_hdr.total_size_lsb + sizeof(jc_uart_hdr_t));
jc_uart_pkt_parse(jc, jc->buf, pkt->uart_hdr.total_size_lsb + sizeof(jc_uart_hdr_t));
}
} }
static bool _jc_send_init_rumble(joycon_ctxt_t *jc) static bool _jc_send_init_rumble(joycon_ctxt_t *jc)
@ -728,6 +721,10 @@ jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos)
bool jc_r_found = jc_r.connected ? false : true; bool jc_r_found = jc_r.connected ? false : true;
bool jc_l_found = jc_l.connected ? false : true; bool jc_l_found = jc_l.connected ? false : true;
// Set mode to HW controlled RTS.
uart_set_mode(jc_l.uart, UART_AO_TX_HW_RX);
uart_set_mode(jc_r.uart, UART_AO_TX_HW_RX);
u32 total_retries = 10; u32 total_retries = 10;
retry: retry:
retries = 10; retries = 10;
@ -751,6 +748,9 @@ retry:
retries--; retries--;
} }
// Wait for the first 36 bytes to arrive.
msleep(5);
if (!jc_l_found) if (!jc_l_found)
{ {
memset(jc_l.buf, 0, 0x100); memset(jc_l.buf, 0, 0x100);
@ -818,9 +818,9 @@ retry:
} }
} }
// Turn Joy-Con detect on. // Restore mode to manual RTS.
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO); uart_set_mode(jc_l.uart, UART_AO_TX_MN_RX);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO); uart_set_mode(jc_r.uart, UART_AO_TX_MN_RX);
return &jc_gamepad; return &jc_gamepad;
} }
@ -850,8 +850,8 @@ static void _jc_init_conn(joycon_ctxt_t *jc)
uart_init(jc->uart, 1000000, UART_AO_TX_MN_RX); uart_init(jc->uart, 1000000, UART_AO_TX_MN_RX);
jc->state = JC_STATE_START; jc->state = JC_STATE_START;
uart_invert(jc->uart, true, UART_INVERT_TXD); // Set TX and RTS inversion for Joycon.
uart_set_IIR(jc->uart); uart_invert(jc->uart, true, UART_INVERT_TXD | UART_INVERT_RTS);
// Wake up the controller. // Wake up the controller.
_joycon_send_raw(jc->uart, init_wake, sizeof(init_wake)); _joycon_send_raw(jc->uart, init_wake, sizeof(init_wake));