@@ -107,9 +107,11 @@ enum
107107{
108108 JC_STATE_START = 0 ,
109109 JC_STATE_HANDSHAKED = 1 ,
110- JC_STATE_BRATE_CHANGED = 2 ,
111- JC_STATE_BRATE_OK = 3 ,
112- JC_STATE_INIT_DONE = 4
110+ JC_STATE_INFO_PARSED = 2 ,
111+ JC_STATE_BRATE_CHANGED = 3 ,
112+ JC_STATE_HID_NO_CONN = 4 ,
113+ JC_STATE_HID_CONN = 5 ,
114+ JC_STATE_INIT_DONE = 6
113115};
114116
115117enum
@@ -650,14 +652,12 @@ static void _jc_send_hid_cmd(jc_dev_t *jc, u8 subcmd, const u8 *data, u16 size)
650652 if (send_l_rumble )
651653 _jc_send_hid_output_rpt (& jc_l , hid_pkt , 0x10 , false);
652654
653- if (send_r_rumble || send_l_rumble )
654- {
655- msleep (2 );
656- if (send_r_rumble )
657- _jc_rcv_pkt (& jc_r );
658- if (send_l_rumble )
659- _jc_rcv_pkt (& jc_l );
660- }
655+ msleep (15 );
656+
657+ if (send_r_rumble )
658+ _jc_rcv_pkt (& jc_r );
659+ if (send_l_rumble )
660+ _jc_rcv_pkt (& jc_l );
661661
662662 // Send rumble.
663663 hid_pkt -> cmd = JC_HID_RUMBLE_RPT ;
@@ -785,23 +785,35 @@ static void _jc_parse_wired_init(jc_dev_t *jc, const jc_wired_hdr_t *pkt, int si
785785 switch (pkt -> subcmd )
786786 {
787787 case JC_WIRED_CMD_GET_INFO :
788- for (int i = 6 ; i > 0 ; i -- )
788+ if (!pkt -> status )
789+ {
790+ for (int i = 6 ; i > 0 ; i -- )
789791 jc -> mac [6 - i ] = payload [i ];
790- jc -> type = payload [0 ];
791- jc -> connected = true;
792+ jc -> type = payload [0 ];
793+ jc -> state = JC_STATE_INFO_PARSED ;
794+ }
792795 break ;
793796
794797 case JC_WIRED_CMD_SET_BRATE :
795- jc -> state = JC_STATE_BRATE_CHANGED ;
798+ if (!pkt -> status )
799+ jc -> state = JC_STATE_BRATE_CHANGED ;
796800 break ;
797801
798802 case JC_WIRED_CMD_HID_DISC :
799- jc -> state = JC_STATE_BRATE_OK ;
803+ if (pkt -> status == 0xF )
804+ jc -> state = JC_STATE_HID_NO_CONN ;
800805 break ;
801806
802807 case JC_WIRED_CMD_HID_CONN :
808+ if (!pkt -> status )
809+ jc -> state = JC_STATE_HID_CONN ;
810+ break ;
811+
803812 case JC_WIRED_CMD_SET_HIDRATE :
804- // done.
813+ jc -> state = JC_STATE_INIT_DONE ;
814+ jc -> connected = true;
815+ break ;
816+
805817 default :
806818 break ;
807819 }
@@ -870,12 +882,13 @@ static void _jc_sio_uart_pkt_parse(jc_dev_t *jc, const jc_sio_in_rpt_t *pkt, int
870882 switch (cmd )
871883 {
872884 case JC_SIO_CMD_INIT :
873- jc -> connected = pkt -> status == 0 ;
885+ if (!pkt -> status )
886+ jc -> state = JC_STATE_HANDSHAKED ;
874887 break ;
875888
876889 case JC_SIO_CMD_VER_RPT :
877- if (jc -> connected )
878- jc -> connected = pkt -> status == 0 ;
890+ if (! pkt -> status )
891+ jc -> state = JC_STATE_HID_CONN ;
879892 break ;
880893
881894 case JC_SIO_CMD_IAP_VER :
@@ -1012,9 +1025,16 @@ static bool _jc_handle_charging(jc_dev_t *jc)
10121025
10131026static bool _jc_send_enable_rumble (jc_dev_t * jc )
10141027{
1028+ bool send_r_rumble = jc_r .connected && !jc_r .rumble_sent ;
1029+ bool send_l_rumble = jc_l .connected && !jc_l .rumble_sent ;
1030+
1031+ // Do not sent report yet if second Joy-Con is expected to be initialized.
1032+ if ((send_r_rumble && !jc_l .rumble_sent && jc_l .state == JC_STATE_HID_CONN ) ||
1033+ (send_l_rumble && !jc_r .rumble_sent && jc_r .state == JC_STATE_HID_CONN ))
1034+ return 1 ;
1035+
10151036 // Send init rumble or request nx pad status report.
1016- if ((jc_r .connected && !jc_r .rumble_sent ) ||
1017- (jc_l .connected && !jc_l .rumble_sent ))
1037+ if (send_r_rumble || send_l_rumble )
10181038 {
10191039 _jc_send_hid_cmd (jc , JC_HID_SUBCMD_SND_RUMBLE , NULL , 0 );
10201040
@@ -1033,14 +1053,14 @@ static bool _jc_send_enable_rumble(jc_dev_t *jc)
10331053
10341054static void _jc_req_status (jc_dev_t * jc )
10351055{
1036- if (!jc -> detected )
1056+ if (!jc -> connected )
10371057 return ;
10381058
1039- bool is_nxpad = !(jc -> type & JC_ID_HORI ) && !jc -> sio_mode ;
1040-
1041- if (jc -> last_status_req_time > get_tmr_ms () || !jc -> connected )
1059+ if (jc -> last_status_req_time > get_tmr_ms ())
10421060 return ;
10431061
1062+ bool is_nxpad = !(jc -> type & JC_ID_HORI ) && !jc -> sio_mode ;
1063+
10441064 // Init/maintenance for Joy-Con.
10451065 if (is_nxpad )
10461066 {
@@ -1258,24 +1278,26 @@ static void _jc_conn_init(jc_dev_t *jc)
12581278 // Initialize uart to 1 megabaud and manual RTS.
12591279 uart_init (jc -> uart , 1000000 , UART_AO_TX_MN_RX );
12601280
1281+ jc -> state = JC_STATE_START ;
1282+
12611283 if (!jc -> sio_mode )
12621284 {
12631285 jc_gamepad .buttons = 0 ;
1264- jc -> state = JC_STATE_START ;
12651286
12661287 // Set TX and RTS inversion for Joycon.
12671288 uart_invert (jc -> uart , true, UART_INVERT_TXD | UART_INVERT_RTS );
12681289
1269- // Wake up the controller.
1270- _joycon_send_raw (jc -> uart , _jc_init_wake , sizeof (_jc_init_wake ));
1271- _jc_rcv_pkt (jc ); // Clear RX FIFO.
1272-
1273- // Do a handshake.
1290+ // Initialize.
12741291 u32 retries = 10 ;
12751292 while (retries && jc -> state != JC_STATE_HANDSHAKED )
12761293 {
1294+ // Wake up the controller.
1295+ _joycon_send_raw (jc -> uart , _jc_init_wake , sizeof (_jc_init_wake ));
1296+ _jc_rcv_pkt (jc ); // Clear RX FIFO.
1297+
1298+ // Do a handshake.
12771299 _joycon_send_raw (jc -> uart , _jc_init_handshake , sizeof (_jc_init_handshake ));
1278- msleep (5 );
1300+ msleep (4 );
12791301 _jc_rcv_pkt (jc );
12801302 retries -- ;
12811303 }
@@ -1288,6 +1310,9 @@ static void _jc_conn_init(jc_dev_t *jc)
12881310 msleep (2 );
12891311 _jc_rcv_pkt (jc );
12901312
1313+ if (jc -> state != JC_STATE_INFO_PARSED )
1314+ goto out ;
1315+
12911316 if (!(jc -> type & JC_ID_HORI ))
12921317 {
12931318 // Request 3 megabaud change.
@@ -1301,17 +1326,18 @@ static void _jc_conn_init(jc_dev_t *jc)
13011326 uart_init (jc -> uart , 3000000 , UART_AO_TX_MN_RX );
13021327 uart_invert (jc -> uart , true, UART_INVERT_TXD | UART_INVERT_RTS );
13031328
1304- // Disconnect HID.
1329+ // Make sure HID is disconnected and check connection. Reply expected after 30ms .
13051330 retries = 10 ;
1306- while (retries && jc -> state != JC_STATE_BRATE_OK )
1331+ while (retries && jc -> state != JC_STATE_HID_NO_CONN )
13071332 {
13081333 _joycon_send_raw (jc -> uart , _jc_init_hid_disconnect , sizeof (_jc_init_hid_disconnect ));
13091334 msleep (5 );
13101335 _jc_rcv_pkt (jc );
13111336 retries -- ;
13121337 }
13131338
1314- if (jc -> state != JC_STATE_BRATE_OK )
1339+ // Was connected before or no response. Do a reinit.
1340+ if (jc -> state != JC_STATE_HID_NO_CONN )
13151341 goto out ;
13161342 }
13171343
@@ -1320,10 +1346,15 @@ static void _jc_conn_init(jc_dev_t *jc)
13201346 msleep (2 );
13211347 _jc_rcv_pkt (jc );
13221348
1349+ if (jc -> state != JC_STATE_HID_CONN )
1350+ goto out ;
1351+
13231352 // Set hid packet rate.
13241353 _joycon_send_raw (jc -> uart , _jc_init_set_hid_rate , sizeof (_jc_init_set_hid_rate ));
13251354 msleep (2 );
13261355 _jc_rcv_pkt (jc );
1356+
1357+ goto out ; // Wait for set hid rate reply.
13271358 }
13281359 else // Hori. Unset RTS inversion.
13291360 uart_invert (jc -> uart , false, UART_INVERT_RTS );
@@ -1342,25 +1373,34 @@ static void _jc_conn_init(jc_dev_t *jc)
13421373
13431374 // Initialize the controller.
13441375 u32 retries = 10 ;
1345- while (! jc -> connected && retries )
1376+ while (retries && jc -> state != JC_STATE_HANDSHAKED )
13461377 {
13471378 _joycon_send_raw (jc -> uart , _sio_init , sizeof (_sio_init ));
13481379 msleep (5 );
13491380 _jc_rcv_pkt (jc );
13501381 retries -- ;
13511382 }
13521383
1353- if (! jc -> connected )
1384+ if (jc -> state != JC_STATE_HANDSHAKED )
13541385 goto out ;
13551386
13561387 // Set output report version.
1357- _joycon_send_raw (jc -> uart , _sio_set_rpt_version , sizeof (_sio_set_rpt_version ));
1358- msleep (5 );
1359- _jc_rcv_pkt (jc );
1388+ retries = 10 ;
1389+ while (retries && jc -> state != JC_STATE_HID_CONN )
1390+ {
1391+ _joycon_send_raw (jc -> uart , _sio_set_rpt_version , sizeof (_sio_set_rpt_version ));
1392+ msleep (5 );
1393+ _jc_rcv_pkt (jc );
1394+ retries -- ;
1395+ }
1396+
1397+ if (jc -> state != JC_STATE_HID_CONN )
1398+ goto out ;
13601399 }
13611400
13621401 // Initialization done.
13631402 jc -> state = JC_STATE_INIT_DONE ;
1403+ jc -> connected = true;
13641404
13651405out :
13661406 jc -> last_received_time = get_tmr_ms ();
0 commit comments