mirror of
https://github.com/CTCaer/hekate.git
synced 2024-11-22 18:06:40 +00:00
joycon: More robust spi dumping for bd addr/ltk
This commit is contained in:
parent
9619417b07
commit
e2c905e9b2
3 changed files with 159 additions and 50 deletions
|
@ -740,7 +740,18 @@ void first_time_clock_edit(void *param)
|
||||||
static lv_res_t _joycon_info_dump_action(lv_obj_t * btn)
|
static lv_res_t _joycon_info_dump_action(lv_obj_t * btn)
|
||||||
{
|
{
|
||||||
FIL fp;
|
FIL fp;
|
||||||
jc_gamepad_rpt_t *jc_pad = jc_get_bt_pairing_info();
|
bool is_l_hos = false;
|
||||||
|
bool is_r_hos = false;
|
||||||
|
jc_gamepad_rpt_t *jc_pad = jc_get_bt_pairing_info(&is_l_hos, &is_r_hos);
|
||||||
|
|
||||||
|
// Count valid joycon.
|
||||||
|
u32 joycon_found = jc_pad->bt_conn_l.type ? 1 : 0;
|
||||||
|
if (jc_pad->bt_conn_r.type)
|
||||||
|
joycon_found++;
|
||||||
|
|
||||||
|
// Reset PC based for dumping.
|
||||||
|
jc_pad->bt_conn_l.type = is_l_hos ? jc_pad->bt_conn_l.type : 0;
|
||||||
|
jc_pad->bt_conn_r.type = is_r_hos ? jc_pad->bt_conn_r.type : 0;
|
||||||
|
|
||||||
int error = !sd_mount();
|
int error = !sd_mount();
|
||||||
|
|
||||||
|
@ -796,17 +807,50 @@ static lv_res_t _joycon_info_dump_action(lv_obj_t * btn)
|
||||||
lv_mbox_set_recolor_text(mbox, true);
|
lv_mbox_set_recolor_text(mbox, true);
|
||||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5);
|
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5);
|
||||||
|
|
||||||
u32 joycon_found = jc_pad->bt_conn_l.type ? 1 : 0;
|
if (!error)
|
||||||
if (jc_pad->bt_conn_r.type)
|
{
|
||||||
joycon_found++;
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
s_printf(txt_buf, "#FFDD00 Failed to dump to# Joy-Con pairing info#FFDD00 !#\nError: %d", error);
|
|
||||||
else
|
|
||||||
s_printf(txt_buf,
|
s_printf(txt_buf,
|
||||||
"Dumping to SD card finished!\n"
|
"Dumping to SD card finished!\n"
|
||||||
"Found %d Joycon!\n\n"
|
"Saved to: #C7EA46 switchroot/joycon_mac.[bin/ini]#\n\n");
|
||||||
"Saved to: #C7EA46 switchroot/joycon_mac.bin/ini#", joycon_found);
|
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
// Check if pairing info was found.
|
||||||
|
if (joycon_found == 2)
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 Found 2 out of 2 Joy-Con pairing data!#\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# Found #FFDD00 %d out of 2# pairing data!\n", joycon_found);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if pairing was done in HOS.
|
||||||
|
if (is_l_hos && is_r_hos)
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 Both pairing data are HOS based!#");
|
||||||
|
else if (!is_l_hos && is_r_hos)
|
||||||
|
{
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# #FFDD00 Left# pairing data is not HOS based!");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
else if (is_l_hos && !is_r_hos)
|
||||||
|
{
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# #FFDD00 Right# pairing data is not HOS based!");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# #FFDD00 No# pairing data is HOS based!");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
s_printf(txt_buf + strlen(txt_buf),
|
||||||
|
"\n\n#FFDD00 Make sure that both Joy-Con are connected,#\n"
|
||||||
|
"#FFDD00 and that you paired them in HOS!#");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s_printf(txt_buf, "#FFDD00 Failed to dump Joy-Con pairing info!#\n#FFDD00 Error: %d#", error);
|
||||||
|
|
||||||
lv_mbox_set_text(mbox, txt_buf);
|
lv_mbox_set_text(mbox, txt_buf);
|
||||||
|
|
||||||
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
|
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#define HCI_STATE_PAIR 0x02
|
#define HCI_STATE_PAIR 0x02
|
||||||
#define HCI_STATE_HOME 0x04
|
#define HCI_STATE_HOME 0x04
|
||||||
#define JC_HID_SUBCMD_SPI_READ 0x10
|
#define JC_HID_SUBCMD_SPI_READ 0x10
|
||||||
|
#define SPI_READ_OFFSET 0x20
|
||||||
#define JC_HID_SUBCMD_RUMBLE_CTL 0x48
|
#define JC_HID_SUBCMD_RUMBLE_CTL 0x48
|
||||||
#define JC_HID_SUBCMD_SND_RUMBLE 0xFF
|
#define JC_HID_SUBCMD_SND_RUMBLE 0xFF
|
||||||
|
|
||||||
|
@ -309,13 +310,7 @@ void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size)
|
||||||
|
|
||||||
u8 pkt_size = sizeof(jc_hid_out_rpt_t) + size;
|
u8 pkt_size = sizeof(jc_hid_out_rpt_t) + size;
|
||||||
|
|
||||||
if (subcmd != JC_HID_SUBCMD_SPI_READ)
|
jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, pkt_size);
|
||||||
jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, pkt_size);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, pkt_size);
|
|
||||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, pkt_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +375,7 @@ static void jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size)
|
||||||
jc_hid_in_pair_data_t *pair_data = (jc_hid_in_pair_data_t *)spi_info->data;
|
jc_hid_in_pair_data_t *pair_data = (jc_hid_in_pair_data_t *)spi_info->data;
|
||||||
|
|
||||||
// Check if we reply is pairing info.
|
// Check if we reply is pairing info.
|
||||||
if (spi_info->addr == 0x2000 && spi_info->size == 0x1A && pair_data->magic == 0x95)
|
if (spi_info->size == 0x1A && pair_data->magic == 0x95 && pair_data->size == 0x22)
|
||||||
{
|
{
|
||||||
bt_conn->type = jc->type;
|
bt_conn->type = jc->type;
|
||||||
|
|
||||||
|
@ -439,7 +434,7 @@ static void jc_rcv_pkt(joycon_ctxt_t *jc)
|
||||||
if ((uart_irq & 0x8) != 0x8)
|
if ((uart_irq & 0x8) != 0x8)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0);
|
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))
|
if (len > 7 && !memcmp(jc->buf, "\x19\x81\x03", 3))
|
||||||
|
@ -503,7 +498,27 @@ static void jc_req_nx_pad_status(joycon_ctxt_t *jc)
|
||||||
jc->last_status_req_time = get_tmr_ms() + 15;
|
jc->last_status_req_time = get_tmr_ms() + 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
jc_gamepad_rpt_t *jc_get_bt_pairing_info()
|
static bool _jc_validate_pairing_info(u8 *buf, bool *is_hos)
|
||||||
|
{
|
||||||
|
u8 crc = 0;
|
||||||
|
for (u32 i = 0; i < 0x22; i++)
|
||||||
|
crc += buf[4 + i];
|
||||||
|
|
||||||
|
crc += 0x68; // Host is Switch.
|
||||||
|
|
||||||
|
if ((crc ^ 0x55) == buf[2])
|
||||||
|
*is_hos = true;
|
||||||
|
|
||||||
|
crc -= 0x68;
|
||||||
|
crc += 0x08; // Host is PC.
|
||||||
|
|
||||||
|
if (*is_hos || (crc ^ 0x55) == buf[2])
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos)
|
||||||
{
|
{
|
||||||
u8 retries;
|
u8 retries;
|
||||||
jc_bt_conn_t *bt_conn;
|
jc_bt_conn_t *bt_conn;
|
||||||
|
@ -522,9 +537,13 @@ jc_gamepad_rpt_t *jc_get_bt_pairing_info()
|
||||||
jc_rcv_pkt(&jc_l);
|
jc_rcv_pkt(&jc_l);
|
||||||
}
|
}
|
||||||
|
|
||||||
jc_hid_in_spi_read_t subcmd_data;
|
jc_hid_in_spi_read_t subcmd_data_l;
|
||||||
subcmd_data.addr = 0x2000;
|
subcmd_data_l.addr = 0x2000;
|
||||||
subcmd_data.size = 0x1A;
|
subcmd_data_l.size = 0x1A;
|
||||||
|
|
||||||
|
jc_hid_in_spi_read_t subcmd_data_r;
|
||||||
|
subcmd_data_r.addr = 0x2000;
|
||||||
|
subcmd_data_r.size = 0x1A;
|
||||||
|
|
||||||
// Turn off Joy-Con detect.
|
// Turn off Joy-Con detect.
|
||||||
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
|
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
|
||||||
|
@ -533,46 +552,94 @@ jc_gamepad_rpt_t *jc_get_bt_pairing_info()
|
||||||
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;
|
||||||
|
|
||||||
u32 total_retries = 5;
|
u32 total_retries = 10;
|
||||||
retry:
|
retry:
|
||||||
retries = 10;
|
retries = 10;
|
||||||
while (retries)
|
while (retries)
|
||||||
{
|
{
|
||||||
if (jc_l.last_status_req_time < get_tmr_ms())
|
u32 time_now = get_tmr_ms();
|
||||||
|
if ((!jc_l_found && jc_l.last_status_req_time < time_now) || (!jc_r_found && jc_r.last_status_req_time < time_now))
|
||||||
{
|
{
|
||||||
jc_send_hid_cmd(0, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data, 5);
|
if (!jc_l_found)
|
||||||
jc_l.last_status_req_time = get_tmr_ms() + 15;
|
{
|
||||||
jc_r.last_status_req_time = get_tmr_ms() + 15;
|
jc_send_hid_cmd(jc_l.uart, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_l, 5);
|
||||||
retries--;
|
jc_l.last_status_req_time = get_tmr_ms() + 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!jc_r_found)
|
if (!jc_r_found)
|
||||||
{
|
{
|
||||||
memset(jc_r.buf, 0, 0x100);
|
jc_send_hid_cmd(jc_r.uart, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_r, 5);
|
||||||
jc_rcv_pkt(&jc_r);
|
jc_r.last_status_req_time = get_tmr_ms() + 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
retries--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!jc_l_found)
|
if (!jc_l_found)
|
||||||
{
|
{
|
||||||
memset(jc_l.buf, 0, 0x100);
|
memset(jc_l.buf, 0, 0x100);
|
||||||
jc_rcv_pkt(&jc_l);
|
jc_rcv_pkt(&jc_l);
|
||||||
|
|
||||||
|
bool is_hos = false;
|
||||||
|
if (_jc_validate_pairing_info(&jc_l.buf[SPI_READ_OFFSET], &is_hos))
|
||||||
|
{
|
||||||
|
bool is_active = jc_l.buf[SPI_READ_OFFSET] == 0x95;
|
||||||
|
|
||||||
|
if (!is_active)
|
||||||
|
subcmd_data_l.addr += 0x26; // Get next slot.
|
||||||
|
else
|
||||||
|
jc_l_found = true; // Entry is active.
|
||||||
|
|
||||||
|
if (jc_l_found && is_hos)
|
||||||
|
*is_l_hos = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!jc_r_found)
|
||||||
|
{
|
||||||
|
memset(jc_r.buf, 0, 0x100);
|
||||||
|
jc_rcv_pkt(&jc_r);
|
||||||
|
|
||||||
|
bool is_hos = false;
|
||||||
|
if (_jc_validate_pairing_info(&jc_r.buf[SPI_READ_OFFSET], &is_hos))
|
||||||
|
{
|
||||||
|
bool is_active = jc_r.buf[SPI_READ_OFFSET] == 0x95;
|
||||||
|
|
||||||
|
if (!is_active)
|
||||||
|
subcmd_data_r.addr += 0x26; // Get next slot.
|
||||||
|
else
|
||||||
|
jc_r_found = true; // Entry is active.
|
||||||
|
|
||||||
|
if (jc_r_found && is_hos)
|
||||||
|
*is_r_hos = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jc_l_found && jc_r_found)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jc_l.connected &&
|
if (!jc_l_found || !jc_r_found)
|
||||||
memcmp(&jc_gamepad.bt_conn_l.ltk[0], "\x00\x00\x00\x00", 4) &&
|
|
||||||
memcmp(&jc_gamepad.bt_conn_l.ltk[8], "\x00\x00\x00\x00", 4))
|
|
||||||
jc_l_found = true;
|
|
||||||
|
|
||||||
if (jc_r.connected &&
|
|
||||||
memcmp(&jc_gamepad.bt_conn_r.ltk[0], "\x00\x00\x00\x00", 4) &&
|
|
||||||
memcmp(&jc_gamepad.bt_conn_r.ltk[8], "\x00\x00\x00\x00", 4))
|
|
||||||
jc_r_found = true;
|
|
||||||
|
|
||||||
if (total_retries && (!jc_l_found || !jc_r_found))
|
|
||||||
{
|
{
|
||||||
total_retries--;
|
if (total_retries)
|
||||||
goto retry;
|
{
|
||||||
|
total_retries--;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jc_l_found)
|
||||||
|
{
|
||||||
|
bt_conn = &jc_gamepad.bt_conn_l;
|
||||||
|
memset(bt_conn->host_mac, 0, 6);
|
||||||
|
memset(bt_conn->ltk, 0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jc_r_found)
|
||||||
|
{
|
||||||
|
bt_conn = &jc_gamepad.bt_conn_r;
|
||||||
|
memset(bt_conn->host_mac, 0, 6);
|
||||||
|
memset(bt_conn->ltk, 0, 16);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn Joy-Con detect on.
|
// Turn Joy-Con detect on.
|
||||||
|
@ -592,13 +659,11 @@ void jc_deinit()
|
||||||
if (jc_r.connected)
|
if (jc_r.connected)
|
||||||
{
|
{
|
||||||
jc_send_hid_cmd(UART_B, JC_HID_SUBCMD_HCI_STATE, &data, 1);
|
jc_send_hid_cmd(UART_B, JC_HID_SUBCMD_HCI_STATE, &data, 1);
|
||||||
msleep(1);
|
|
||||||
jc_rcv_pkt(&jc_r);
|
jc_rcv_pkt(&jc_r);
|
||||||
}
|
}
|
||||||
if (jc_l.connected)
|
if (jc_l.connected)
|
||||||
{
|
{
|
||||||
jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1);
|
jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1);
|
||||||
msleep(1);
|
|
||||||
jc_rcv_pkt(&jc_l);
|
jc_rcv_pkt(&jc_l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,6 @@ void jc_power_supply(u8 uart, bool enable);
|
||||||
void jc_init_hw();
|
void jc_init_hw();
|
||||||
void jc_deinit();
|
void jc_deinit();
|
||||||
jc_gamepad_rpt_t *joycon_poll();
|
jc_gamepad_rpt_t *joycon_poll();
|
||||||
jc_gamepad_rpt_t *jc_get_bt_pairing_info();
|
jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos);
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in a new issue