bdk: joycon: more refactoring
This commit is contained in:
@@ -302,15 +302,15 @@ typedef struct _jc_uart_hdr_t
|
||||
typedef struct _jc_wired_hdr_t
|
||||
{
|
||||
jc_uart_hdr_t uart_hdr;
|
||||
u8 cmd;
|
||||
u8 subcmd;
|
||||
u8 cmd;
|
||||
u8 subcmd;
|
||||
u16 payload_size;
|
||||
// As out, cmd exists query. For JC_WIRED_CMD_SET_PAIRING: 1-4 pairing step.
|
||||
// As in, 0xF: exists. For JC_WIRED_CMD_SET_HIDRATE: 1 wrong rate.
|
||||
u8 status;
|
||||
u8 crc_payload;
|
||||
u8 crc_hdr;
|
||||
u8 payload[];
|
||||
u8 status;
|
||||
u8 crc_payload;
|
||||
u8 crc_hdr;
|
||||
u8 payload[];
|
||||
} __attribute__((packed)) jc_wired_hdr_t;
|
||||
|
||||
typedef struct _jc_hid_out_rpt_t
|
||||
@@ -324,20 +324,20 @@ typedef struct _jc_hid_out_rpt_t
|
||||
|
||||
typedef struct _jc_hid_in_rpt_t
|
||||
{
|
||||
u8 cmd;
|
||||
u8 pkt_id; // Latency timer. 5 ms lsb (every 4 x 1.25 ms).
|
||||
u8 conn_info:4; // Connection detect.
|
||||
u8 batt_info:4; // Power info.
|
||||
u8 cmd;
|
||||
u8 pkt_id; // Latency timer. 5 ms lsb (every 4 x 1.25 ms).
|
||||
u8 conn_info:4; // Connection detect.
|
||||
u8 batt_info:4; // Power info.
|
||||
u16 btn_right:12;
|
||||
u16 btn_left:12;
|
||||
u16 stick_left_x:12;
|
||||
u16 stick_left_y:12;
|
||||
u16 stick_right_x:12;
|
||||
u16 stick_right_y:12;
|
||||
u8 vib_decider; // right:4, left:4 (bit3 en, bit2-0 buffer avail).
|
||||
u8 submcd_ack;
|
||||
u8 subcmd;
|
||||
u8 subcmd_data[];
|
||||
u8 vib_decider; // right:4, left:4 (bit3 en, bit2-0 buffer avail).
|
||||
u8 submcd_ack;
|
||||
u8 subcmd;
|
||||
u8 subcmd_data[];
|
||||
} __attribute__((packed)) jc_hid_in_rpt_t;
|
||||
|
||||
typedef struct _jc_hid_out_spi_read_t
|
||||
@@ -400,46 +400,46 @@ typedef struct _jc_hid_in_sixaxis_rpt_t
|
||||
|
||||
typedef struct _jc_sio_hid_in_rpt_t
|
||||
{
|
||||
u8 type;
|
||||
u8 pkt_id; // Latency timer.
|
||||
u8 unk;
|
||||
u8 type;
|
||||
u8 pkt_id; // Latency timer.
|
||||
u8 unk;
|
||||
u16 btn_right:12;
|
||||
u16 btn_left:12;
|
||||
u16 stick_left_x:12;
|
||||
u16 stick_left_y:12;
|
||||
u16 stick_right_x:12;
|
||||
u16 stick_right_y:12;
|
||||
u8 sixaxis_rpt; // bit0-3: report num. bit4-7: imu type.
|
||||
u8 sixaxis_rpt; // bit0-3: report num. bit4-7: imu type.
|
||||
// Each report is 800 us?
|
||||
jc_hid_in_sixaxis_rpt_t sixaxis[15];
|
||||
} __attribute__((packed)) jc_sio_hid_in_rpt_t;
|
||||
|
||||
typedef struct _joycon_ctxt_t
|
||||
typedef struct _jc_dev_t
|
||||
{
|
||||
u8 buf[0x100];
|
||||
u8 uart;
|
||||
u8 type;
|
||||
u8 sio_mode;
|
||||
u8 state;
|
||||
u32 last_received_time; // Reset with JC_WIRED_CMD_HID_CONN/JC_WIRED_HID. If exceeded HID mode disconnects.
|
||||
u32 last_status_req_time;
|
||||
u32 last_chrger_chk_time;
|
||||
u8 mac[6];
|
||||
u8 pkt_id;
|
||||
u8 rumble_sent;
|
||||
u8 charger_req;
|
||||
u8 connected;
|
||||
u8 detected;
|
||||
} joycon_ctxt_t;
|
||||
u8 buf[0x100];
|
||||
u8 uart;
|
||||
u8 type;
|
||||
u8 state;
|
||||
u8 pkt_id;
|
||||
bool detected;
|
||||
bool connected;
|
||||
bool sio_mode;
|
||||
bool rumble_sent;
|
||||
bool charger_req;
|
||||
u32 last_received_time; // Reset with JC_WIRED_CMD_HID_CONN/JC_WIRED_HID. If exceeded HID mode disconnects.
|
||||
u32 last_status_req_time;
|
||||
u32 last_chrger_chk_time;
|
||||
u8 mac[6];
|
||||
} jc_dev_t;
|
||||
|
||||
static joycon_ctxt_t jc_l = {0};
|
||||
static joycon_ctxt_t jc_r = {0};
|
||||
static jc_dev_t jc_l = {0};
|
||||
static jc_dev_t jc_r = {0};
|
||||
|
||||
static bool jc_init_done = false;
|
||||
|
||||
static jc_gamepad_rpt_t jc_gamepad;
|
||||
|
||||
static void _jc_rcv_pkt(joycon_ctxt_t *jc);
|
||||
static void _jc_rcv_pkt(jc_dev_t *jc);
|
||||
|
||||
static u8 _jc_crc(const u8 *data, u16 len)
|
||||
{
|
||||
@@ -509,45 +509,42 @@ static void _jc_power_supply(u8 uart, bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
static void _jc_detect()
|
||||
static void _jc_rail_detect()
|
||||
{
|
||||
if (!jc_gamepad.sio_mode)
|
||||
{
|
||||
// Turn on Joy-Con detect. (UARTB/C TX). UART CTS also if HW flow control and irq is enabled.
|
||||
PINMUX_AUX(PINMUX_AUX_UART2_TX) = PINMUX_INPUT_ENABLE;
|
||||
PINMUX_AUX(PINMUX_AUX_UART3_TX) = PINMUX_INPUT_ENABLE;
|
||||
gpio_direction_input(GPIO_PORT_G, GPIO_PIN_0);
|
||||
gpio_direction_input(GPIO_PORT_D, GPIO_PIN_1);
|
||||
usleep(20);
|
||||
// Turn on Joy-Con detect. (UARTB/C TX). UART CTS also if HW flow control and irq is enabled.
|
||||
PINMUX_AUX(PINMUX_AUX_UART2_TX) = PINMUX_INPUT_ENABLE;
|
||||
PINMUX_AUX(PINMUX_AUX_UART3_TX) = PINMUX_INPUT_ENABLE;
|
||||
gpio_direction_input(GPIO_PORT_G, GPIO_PIN_0);
|
||||
gpio_direction_input(GPIO_PORT_D, GPIO_PIN_1);
|
||||
usleep(20);
|
||||
|
||||
//! HW BUG: Unlatch gpio buffer.
|
||||
(void)gpio_read(GPIO_PORT_H, GPIO_PIN_6);
|
||||
(void)gpio_read(GPIO_PORT_E, GPIO_PIN_6);
|
||||
//! HW BUG: Unlatch gpio buffer.
|
||||
(void)gpio_read(GPIO_PORT_H, GPIO_PIN_6);
|
||||
(void)gpio_read(GPIO_PORT_E, GPIO_PIN_6);
|
||||
|
||||
// Read H6/E6 which are shared with UART TX pins.
|
||||
jc_r.detected = !gpio_read(GPIO_PORT_H, GPIO_PIN_6);
|
||||
jc_l.detected = !gpio_read(GPIO_PORT_E, GPIO_PIN_6);
|
||||
// Read H6/E6 which are shared with UART TX pins.
|
||||
jc_r.detected = !gpio_read(GPIO_PORT_H, GPIO_PIN_6);
|
||||
jc_l.detected = !gpio_read(GPIO_PORT_E, GPIO_PIN_6);
|
||||
|
||||
// Turn off Joy-Con detect. (UARTB/C TX).
|
||||
PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0;
|
||||
PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0;
|
||||
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
|
||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||
usleep(20);
|
||||
}
|
||||
else
|
||||
{
|
||||
//! TODO: Is there a way to detect a broken Sio?
|
||||
jc_l.detected = true;
|
||||
}
|
||||
// Turn off Joy-Con detect. (UARTB/C TX).
|
||||
PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0;
|
||||
PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0;
|
||||
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
|
||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||
usleep(20);
|
||||
}
|
||||
|
||||
static void _jc_conn_check()
|
||||
{
|
||||
_jc_detect();
|
||||
|
||||
if (jc_gamepad.sio_mode)
|
||||
{
|
||||
//! TODO: Is there a way to detect a broken Sio?
|
||||
jc_l.detected = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_jc_rail_detect();
|
||||
|
||||
// Check if a Joy-Con was disconnected.
|
||||
if (!jc_l.detected)
|
||||
@@ -618,7 +615,7 @@ static u16 _jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, const u8 *payload, u16
|
||||
return _jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, 0, payload_size, crc);
|
||||
}
|
||||
|
||||
static void _jc_send_hid_output_rpt(joycon_ctxt_t *jc, jc_hid_out_rpt_t *hid_pkt, u16 size, bool crc)
|
||||
static void _jc_send_hid_output_rpt(jc_dev_t *jc, jc_hid_out_rpt_t *hid_pkt, u16 size, bool crc)
|
||||
{
|
||||
u8 rpt[0x50];
|
||||
memset(rpt, 0, sizeof(rpt));
|
||||
@@ -629,7 +626,7 @@ static void _jc_send_hid_output_rpt(joycon_ctxt_t *jc, jc_hid_out_rpt_t *hid_pkt
|
||||
_joycon_send_raw(jc->uart, rpt, rpt_size);
|
||||
}
|
||||
|
||||
static void _jc_send_hid_cmd(joycon_ctxt_t *jc, u8 subcmd, const u8 *data, u16 size)
|
||||
static void _jc_send_hid_cmd(jc_dev_t *jc, u8 subcmd, const u8 *data, u16 size)
|
||||
{
|
||||
static const u8 rumble_mute[8] = { 0x00, 0x01, 0x40, 0x40, 0x00, 0x01, 0x40, 0x40 };
|
||||
static const u8 rumble_init[8] = { 0xc2, 0xc8, 0x03, 0x72, 0xc2, 0xc8, 0x03, 0x72 };
|
||||
@@ -693,7 +690,7 @@ static void _jc_send_hid_cmd(joycon_ctxt_t *jc, u8 subcmd, const u8 *data, u16 s
|
||||
}
|
||||
}
|
||||
|
||||
static void _jc_parse_input(joycon_ctxt_t *jc, const jc_hid_in_rpt_t *hid_pkt)
|
||||
static void _jc_parse_input(jc_dev_t *jc, const jc_hid_in_rpt_t *hid_pkt)
|
||||
{
|
||||
u32 btn_tmp;
|
||||
btn_tmp = hid_pkt->btn_right | hid_pkt->btn_left << 12;
|
||||
@@ -720,7 +717,7 @@ static void _jc_parse_input(joycon_ctxt_t *jc, const jc_hid_in_rpt_t *hid_pkt)
|
||||
}
|
||||
}
|
||||
|
||||
static void _jc_parse_wired_hid(joycon_ctxt_t *jc, const u8 *packet, int size)
|
||||
static void _jc_parse_wired_hid(jc_dev_t *jc, const u8 *packet, int size)
|
||||
{
|
||||
const jc_hid_in_rpt_t *hid_pkt = (jc_hid_in_rpt_t *)packet;
|
||||
|
||||
@@ -777,7 +774,7 @@ static void _jc_parse_wired_hid(joycon_ctxt_t *jc, const u8 *packet, int size)
|
||||
}
|
||||
}
|
||||
|
||||
static void _jc_parse_wired_init(joycon_ctxt_t *jc, const jc_wired_hdr_t *pkt, int size)
|
||||
static void _jc_parse_wired_init(jc_dev_t *jc, const jc_wired_hdr_t *pkt, int size)
|
||||
{
|
||||
// Discard empty packets.
|
||||
if (size <= 0)
|
||||
@@ -810,7 +807,7 @@ static void _jc_parse_wired_init(joycon_ctxt_t *jc, const jc_wired_hdr_t *pkt, i
|
||||
}
|
||||
}
|
||||
|
||||
static void _jc_uart_pkt_parse(joycon_ctxt_t *jc, const jc_wired_hdr_t *pkt, int size)
|
||||
static void _jc_uart_pkt_parse(jc_dev_t *jc, const jc_wired_hdr_t *pkt, int size)
|
||||
{
|
||||
switch (pkt->cmd)
|
||||
{
|
||||
@@ -834,7 +831,7 @@ static void _jc_uart_pkt_parse(joycon_ctxt_t *jc, const jc_wired_hdr_t *pkt, int
|
||||
jc->last_received_time = get_tmr_ms();
|
||||
}
|
||||
|
||||
static void _jc_sio_parse_payload(joycon_ctxt_t *jc, u8 cmd, const u8 *payload, int size)
|
||||
static void _jc_sio_parse_payload(jc_dev_t *jc, u8 cmd, const u8 *payload, int size)
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
@@ -864,7 +861,7 @@ static void _jc_sio_parse_payload(joycon_ctxt_t *jc, u8 cmd, const u8 *payload,
|
||||
}
|
||||
}
|
||||
|
||||
static void _jc_sio_uart_pkt_parse(joycon_ctxt_t *jc, const jc_sio_in_rpt_t *pkt, int size)
|
||||
static void _jc_sio_uart_pkt_parse(jc_dev_t *jc, const jc_sio_in_rpt_t *pkt, int size)
|
||||
{
|
||||
if (pkt->crc_hdr != _jc_crc((u8 *)pkt, sizeof(jc_sio_in_rpt_t) - 1))
|
||||
return;
|
||||
@@ -898,7 +895,7 @@ static void _jc_sio_uart_pkt_parse(joycon_ctxt_t *jc, const jc_sio_in_rpt_t *pkt
|
||||
jc->last_received_time = get_tmr_ms();
|
||||
}
|
||||
|
||||
static void _jc_rcv_pkt(joycon_ctxt_t *jc)
|
||||
static void _jc_rcv_pkt(jc_dev_t *jc)
|
||||
{
|
||||
if (!jc->detected)
|
||||
return;
|
||||
@@ -926,7 +923,7 @@ static void _jc_rcv_pkt(joycon_ctxt_t *jc)
|
||||
}
|
||||
}
|
||||
|
||||
static bool _jc_handle_charging(joycon_ctxt_t *jc)
|
||||
static bool _jc_handle_charging(jc_dev_t *jc)
|
||||
{
|
||||
if (jc->last_chrger_chk_time > get_tmr_ms())
|
||||
return false;
|
||||
@@ -1013,7 +1010,7 @@ set_mode:
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _jc_send_enable_rumble(joycon_ctxt_t *jc)
|
||||
static bool _jc_send_enable_rumble(jc_dev_t *jc)
|
||||
{
|
||||
// Send init rumble or request nx pad status report.
|
||||
if ((jc_r.connected && !jc_r.rumble_sent) ||
|
||||
@@ -1034,7 +1031,7 @@ static bool _jc_send_enable_rumble(joycon_ctxt_t *jc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _jc_req_status(joycon_ctxt_t *jc)
|
||||
static void _jc_req_status(jc_dev_t *jc)
|
||||
{
|
||||
if (!jc->detected)
|
||||
return;
|
||||
@@ -1092,6 +1089,19 @@ jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos)
|
||||
if (!jc_init_done || jc_gamepad.sio_mode)
|
||||
return NULL;
|
||||
|
||||
// Detect and init if needed.
|
||||
for (u32 i = 0; i < 6; i++)
|
||||
{
|
||||
joycon_poll();
|
||||
msleep(15);
|
||||
}
|
||||
|
||||
while ((jc_l.last_status_req_time + 15) > get_tmr_ms())
|
||||
{
|
||||
_jc_rcv_pkt(&jc_r);
|
||||
_jc_rcv_pkt(&jc_l);
|
||||
}
|
||||
|
||||
bt_conn = &jc_gamepad.bt_conn_l;
|
||||
memset(bt_conn->host_mac, 0, 6);
|
||||
memset(bt_conn->ltk, 0, 16);
|
||||
@@ -1100,14 +1110,7 @@ jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos)
|
||||
memset(bt_conn->host_mac, 0, 6);
|
||||
memset(bt_conn->ltk, 0, 16);
|
||||
|
||||
_jc_conn_check();
|
||||
|
||||
while (jc_l.last_status_req_time > get_tmr_ms())
|
||||
{
|
||||
_jc_rcv_pkt(&jc_r);
|
||||
_jc_rcv_pkt(&jc_l);
|
||||
}
|
||||
|
||||
// Setup initial SPI address.
|
||||
jc_hid_out_spi_read_t subcmd_data_l;
|
||||
subcmd_data_l.addr = 0x2000;
|
||||
subcmd_data_l.size = 0x1A;
|
||||
@@ -1223,7 +1226,7 @@ retry:
|
||||
return &jc_gamepad;
|
||||
}
|
||||
|
||||
static void _jc_init_conn(joycon_ctxt_t *jc)
|
||||
static void _jc_conn_init(jc_dev_t *jc)
|
||||
{
|
||||
if (!jc->detected)
|
||||
return;
|
||||
@@ -1480,8 +1483,8 @@ jc_gamepad_rpt_t *joycon_poll()
|
||||
|
||||
_jc_conn_check();
|
||||
|
||||
_jc_init_conn(&jc_r);
|
||||
_jc_init_conn(&jc_l);
|
||||
_jc_conn_init(&jc_r);
|
||||
_jc_conn_init(&jc_l);
|
||||
|
||||
_jc_req_status(&jc_r);
|
||||
_jc_req_status(&jc_l);
|
||||
|
||||
Reference in New Issue
Block a user