@@ -175,10 +175,25 @@ static void pu_reset_timing_restrict(struct ll_conn *conn)
175175}
176176
177177#if  defined(CONFIG_BT_PERIPHERAL )
178+ static  inline  bool  phy_valid (uint8_t  phy )
179+ {
180+ 	/* This is equivalent to: 
181+ 	 * maximum one bit set, and no bit set is rfu's 
182+ 	 */ 
183+ 	return  (phy  <  5  &&  phy  !=  3 );
184+ }
185+ 
178186static  uint8_t  pu_check_update_ind (struct  ll_conn  * conn , struct  proc_ctx  * ctx )
179187{
180188	uint8_t  ret  =  0 ;
181189
190+ 	/* Check if either phy selected is invalid */ 
191+ 	if  (!phy_valid (ctx -> data .pu .c_to_p_phy ) ||  !phy_valid (ctx -> data .pu .p_to_c_phy )) {
192+ 		/* more than one or any rfu bit selected in either phy */ 
193+ 		ctx -> data .pu .error  =  BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL ;
194+ 		ret  =  1 ;
195+ 	}
196+ 
182197	/* Both tx and rx PHY unchanged */ 
183198	if  (!((ctx -> data .pu .c_to_p_phy  | ctx -> data .pu .p_to_c_phy ) &  0x07 )) {
184199		/* if no phy changes, quit procedure, and possibly signal host */ 
@@ -199,29 +214,41 @@ static uint8_t pu_check_update_ind(struct ll_conn *conn, struct proc_ctx *ctx)
199214static  uint8_t  pu_apply_phy_update (struct  ll_conn  * conn , struct  proc_ctx  * ctx )
200215{
201216	struct  lll_conn  * lll  =  & conn -> lll ;
217+ 	uint8_t  phy_bitmask  =  PHY_1M ;
218+ 	const  uint8_t  old_tx  =  lll -> phy_tx ;
219+ 	const  uint8_t  old_rx  =  lll -> phy_rx ;
220+ 
221+ #if  defined(CONFIG_BT_CTLR_PHY_2M )
222+ 	phy_bitmask  |= PHY_2M ;
223+ #endif 
224+ #if  defined(CONFIG_BT_CTLR_PHY_CODED )
225+ 	phy_bitmask  |= PHY_CODED ;
226+ #endif 
227+ 	const  uint8_t  p_to_c_phy  =  ctx -> data .pu .p_to_c_phy  &  phy_bitmask ;
228+ 	const  uint8_t  c_to_p_phy  =  ctx -> data .pu .c_to_p_phy  &  phy_bitmask ;
202229
203230	if  (0 ) {
204231#if  defined(CONFIG_BT_PERIPHERAL )
205232 	} else  if  (lll -> role  ==  BT_HCI_ROLE_PERIPHERAL ) {
206- 		if  (ctx -> data . pu . p_to_c_phy ) {
207- 			lll -> phy_tx  =  ctx -> data . pu . p_to_c_phy ;
233+ 		if  (p_to_c_phy ) {
234+ 			lll -> phy_tx  =  p_to_c_phy ;
208235		}
209- 		if  (ctx -> data . pu . c_to_p_phy ) {
210- 			lll -> phy_rx  =  ctx -> data . pu . c_to_p_phy ;
236+ 		if  (c_to_p_phy ) {
237+ 			lll -> phy_rx  =  c_to_p_phy ;
211238		}
212239#endif  /* CONFIG_BT_PERIPHERAL */ 
213240#if  defined(CONFIG_BT_CENTRAL )
214241 	} else  if  (lll -> role  ==  BT_HCI_ROLE_CENTRAL ) {
215- 		if  (ctx -> data . pu . p_to_c_phy ) {
216- 			lll -> phy_rx  =  ctx -> data . pu . p_to_c_phy ;
242+ 		if  (p_to_c_phy ) {
243+ 			lll -> phy_rx  =  p_to_c_phy ;
217244		}
218- 		if  (ctx -> data . pu . c_to_p_phy ) {
219- 			lll -> phy_tx  =  ctx -> data . pu . c_to_p_phy ;
245+ 		if  (c_to_p_phy ) {
246+ 			lll -> phy_tx  =  c_to_p_phy ;
220247		}
221248#endif  /* CONFIG_BT_CENTRAL */ 
222249	}
223250
224- 	return  (ctx -> data . pu . c_to_p_phy  ||  ctx -> data . pu . p_to_c_phy );
251+ 	return  (( old_tx   !=   lll -> phy_tx )  ||  ( old_rx   !=   lll -> phy_rx ) );
225252}
226253
227254#if  defined(CONFIG_BT_CTLR_DATA_LENGTH )
@@ -313,8 +340,9 @@ static void pu_prepare_instant(struct ll_conn *conn, struct proc_ctx *ctx)
313340	/* Set instance only in case there is actual PHY change. Otherwise the instant should be 
314341	 * set to 0. 
315342	 */ 
316- 	if  (ctx -> data .pu .c_to_p_phy   !=  0  ||  ctx -> data .pu .p_to_c_phy  !=  0 ) {
317- 		ctx -> data .pu .instant  =  ull_conn_event_counter (conn ) +  PHY_UPDATE_INSTANT_DELTA ;
343+ 	if  (ctx -> data .pu .c_to_p_phy  !=  0  ||  ctx -> data .pu .p_to_c_phy  !=  0 ) {
344+ 		ctx -> data .pu .instant  =  ull_conn_event_counter (conn ) +  conn -> lll .latency  + 
345+ 			PHY_UPDATE_INSTANT_DELTA ;
318346	} else  {
319347		ctx -> data .pu .instant  =  0 ;
320348	}
@@ -650,6 +678,10 @@ static void lp_pu_st_wait_rx_phy_update_ind(struct ll_conn *conn, struct proc_ct
650678			ctx -> state  =  LP_PU_STATE_WAIT_INSTANT ;
651679		} else  {
652680			llcp_rr_set_incompat (conn , INCOMPAT_NO_COLLISION );
681+ 			if  (ctx -> data .pu .error  !=  BT_HCI_ERR_SUCCESS ) {
682+ 				/* Mark the connection for termination */ 
683+ 				conn -> llcp_terminate .reason_final  =  ctx -> data .pu .error ;
684+ 			}
653685			ctx -> data .pu .ntf_pu  =  ctx -> data .pu .host_initiated ;
654686			lp_pu_complete (conn , ctx , evt , param );
655687		}
@@ -1045,8 +1077,12 @@ static void rp_pu_st_wait_rx_phy_update_ind(struct ll_conn *conn, struct proc_ct
10451077			 */ 
10461078			llcp_rr_prt_stop (conn );
10471079
1048- 			ctx -> state  =  LP_PU_STATE_WAIT_INSTANT ;
1080+ 			ctx -> state  =  RP_PU_STATE_WAIT_INSTANT ;
10491081		} else  {
1082+ 			if  (ctx -> data .pu .error  ==  BT_HCI_ERR_INSTANT_PASSED ) {
1083+ 				/* Mark the connection for termination */ 
1084+ 				conn -> llcp_terminate .reason_final  =  BT_HCI_ERR_INSTANT_PASSED ;
1085+ 			}
10501086			rp_pu_complete (conn , ctx , evt , param );
10511087		}
10521088		break ;
0 commit comments