1 /*
2  * Copyright 2018 Oticon A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "bs_pc_2G4_types.h"
7 #include "bs_pc_2G4.h"
8 #include "bs_pc_2G4_priv.h"
9 #include "bs_tracing.h"
10 
p2G4_dev_initCom_s_nc(p2G4_dev_state_nc_t * p2G4_dev_state,uint d,const char * s,const char * p)11 int p2G4_dev_initCom_s_nc(p2G4_dev_state_nc_t *p2G4_dev_state, uint d,
12                           const char* s, const char* p) {
13   return pb_dev_init_com(&p2G4_dev_state->pb_dev_state, d, s, p);
14 }
15 
p2G4_dev_terminate_s_nc(p2G4_dev_state_nc_t * p2G4_dev_state)16 void p2G4_dev_terminate_s_nc(p2G4_dev_state_nc_t *p2G4_dev_state){
17   pb_dev_terminate(&p2G4_dev_state->pb_dev_state);
18 }
19 
p2G4_dev_disconnect_s_nc(p2G4_dev_state_nc_t * p2G4_dev_state)20 void p2G4_dev_disconnect_s_nc(p2G4_dev_state_nc_t *p2G4_dev_state){
21   pb_dev_disconnect(&p2G4_dev_state->pb_dev_state);
22 }
23 
p2G4_dev_get_tx_resp_nc(p2G4_dev_state_nc_t * c2G4_dev_st)24 static int p2G4_dev_get_tx_resp_nc(p2G4_dev_state_nc_t *c2G4_dev_st) {
25   pc_header_t header;
26   int ret;
27 
28   ret = pb_dev_read(&c2G4_dev_st->pb_dev_state, &header, sizeof(pc_header_t));
29   if (ret == -1)
30     return -1;
31 
32   if (header == P2G4_MSG_ABORTREEVAL) {
33     c2G4_dev_st->ongoing = Tx_Abort_Reeval_2G4;
34     return header;
35   }
36 
37   c2G4_dev_st->ongoing = Nothing_2G4;
38 
39   ret = p2G4_dev_handle_tx_resp_i(&c2G4_dev_st->pb_dev_state, header, c2G4_dev_st->tx_done_s);
40   if (ret == -1)
41     return -1;
42   else
43     return header;
44 }
45 
p2G4_dev_get_cca_resp_nc(p2G4_dev_state_nc_t * c2G4_dev_st)46 static int p2G4_dev_get_cca_resp_nc(p2G4_dev_state_nc_t *c2G4_dev_st) {
47   pc_header_t header;
48   int ret;
49 
50   ret = pb_dev_read(&c2G4_dev_st->pb_dev_state, &header, sizeof(pc_header_t));
51   if (ret == -1)
52     return -1;
53 
54   if (header == P2G4_MSG_ABORTREEVAL) {
55     c2G4_dev_st->ongoing = CCA_Abort_Reeval_2G4;
56     return header;
57   }
58 
59   c2G4_dev_st->ongoing = Nothing_2G4;
60 
61   ret = p2G4_dev_handle_cca_resp_i(&c2G4_dev_st->pb_dev_state, header, c2G4_dev_st->cca_done_s);
62   if (ret == -1)
63     return -1;
64   else
65     return header;
66 }
67 
68 /**
69  * Request a transmissions (v1) to the phy
70  *
71  * tx_done_s needs to point to an allocated structure. Its content will be overwritten
72  *
73  * returns -1 on error, otherwise the response from the phy.
74  * Possible phy responses are:
75  *   * P2G4_MSG_TX_END : (updates the tx_done_s)
76  *        The transaction has terminated, the device may start a new transaction
77  *   * P2G4_MSG_ABORTREEVAL
78  *        The device shall call p2G4_dev_provide_new_tx_abort_s_nc_b() with a new abort structure
79  */
p2G4_dev_req_tx_s_nc_b(p2G4_dev_state_nc_t * c2G4_dev_st,p2G4_tx_t * tx_s,uint8_t * packet,p2G4_tx_done_t * tx_done_s)80 int p2G4_dev_req_tx_s_nc_b(p2G4_dev_state_nc_t *c2G4_dev_st, p2G4_tx_t *tx_s, uint8_t *packet, p2G4_tx_done_t *tx_done_s) {
81 
82   CHECK_CONNECTED(c2G4_dev_st->pb_dev_state.connected);
83   c2G4_dev_st->tx_done_s = tx_done_s;
84 
85   if ( c2G4_dev_st->ongoing != Nothing_2G4 ) {
86     bs_trace_error_time_line("Tried to request a new tx while some other transaction was ongoing\n");
87   }
88 
89   p2G4_dev_req_tx_i(&c2G4_dev_st->pb_dev_state, tx_s, packet);
90 
91   return p2G4_dev_get_tx_resp_nc(c2G4_dev_st);
92 }
93 
94 /**
95  * Request a transmissions (v2) to the phy
96  *
97  * tx_done_s needs to point to an allocated structure. Its content will be overwritten
98  *
99  * returns -1 on error, otherwise the response from the phy.
100  * Possible phy responses are:
101  *   * P2G4_MSG_TX_END : (updates the tx_done_s)
102  *        The transaction has terminated, the device may start a new transaction
103  *   * P2G4_MSG_ABORTREEVAL
104  *        The device shall call p2G4_dev_provide_new_tx_abort_s_nc_b() with a new abort structure
105  */
p2G4_dev_req_txv2_s_nc_b(p2G4_dev_state_nc_t * c2G4_dev_st,p2G4_txv2_t * tx_s,uint8_t * packet,p2G4_tx_done_t * tx_done_s)106 int p2G4_dev_req_txv2_s_nc_b(p2G4_dev_state_nc_t *c2G4_dev_st, p2G4_txv2_t *tx_s, uint8_t *packet, p2G4_tx_done_t *tx_done_s) {
107 
108   CHECK_CONNECTED(c2G4_dev_st->pb_dev_state.connected);
109   c2G4_dev_st->tx_done_s = tx_done_s;
110 
111   if ( c2G4_dev_st->ongoing != Nothing_2G4 ) {
112     bs_trace_error_time_line("Tried to request a new tx while some other transaction was ongoing\n");
113   }
114 
115   p2G4_dev_req_txv2_i(&c2G4_dev_st->pb_dev_state, tx_s, packet);
116 
117   return p2G4_dev_get_tx_resp_nc(c2G4_dev_st);
118 }
119 
120 /**
121  * Provide the phy a new abort struct (during a Tx transaction)
122  *
123  * returns -1 on error, otherwise the response from the phy.
124  * The possible responses depend on the transaction which is ongoing
125  *
126  * Note that the response structures will come thru the pointers
127  * which were provided with the call which initiated the transaction
128  */
p2G4_dev_provide_new_tx_abort_s_nc_b(p2G4_dev_state_nc_t * c2G4_dev_st,p2G4_abort_t * abort)129 int p2G4_dev_provide_new_tx_abort_s_nc_b(p2G4_dev_state_nc_t *c2G4_dev_st, p2G4_abort_t * abort){
130   CHECK_CONNECTED(c2G4_dev_st->pb_dev_state.connected);
131 
132   if ( c2G4_dev_st->ongoing != Tx_Abort_Reeval_2G4 ) {
133     bs_trace_error_time_line("Tried to send a new Tx Abort substruct but we are not in a Tx transaction abort reevaluation!\n");
134   }
135 
136   pb_send_msg(c2G4_dev_st->pb_dev_state.ff_dtp, P2G4_MSG_RERESP_ABORTREEVAL,
137               (void *)abort, sizeof(p2G4_abort_t));
138 
139   return p2G4_dev_get_tx_resp_nc(c2G4_dev_st);
140 }
141 
142 
143 /**
144  * Request a CCA measurement to the phy
145  *
146  * cca_done_s needs to point to an allocated structure. Its content will be overwritten
147  *
148  * returns -1 on error, otherwise the response from the phy.
149  * Possible phy responses are:
150  *   * P2G4_MSG_CCA_END : (updates the cca_done_s)
151  *        The transaction has terminated, the device may start a new transaction
152  *   * P2G4_MSG_ABORTREEVAL
153  *        The device shall call p2G4_dev_provide_new_cca_abort_s_nc_b() with a new abort structure
154  */
p2G4_dev_req_cca_s_nc_b(p2G4_dev_state_nc_t * c2G4_dev_st,p2G4_cca_t * cca_s,p2G4_cca_done_t * cca_done_s)155 int p2G4_dev_req_cca_s_nc_b(p2G4_dev_state_nc_t *c2G4_dev_st, p2G4_cca_t *cca_s, p2G4_cca_done_t *cca_done_s) {
156 
157   CHECK_CONNECTED(c2G4_dev_st->pb_dev_state.connected);
158   c2G4_dev_st->cca_done_s = cca_done_s;
159 
160   if ( c2G4_dev_st->ongoing != Nothing_2G4 ) {
161     bs_trace_error_time_line("Tried to request a new CCA while some other transaction was ongoing\n");
162   }
163 
164   p2G4_dev_req_cca_i(&c2G4_dev_st->pb_dev_state, cca_s);
165 
166   return p2G4_dev_get_cca_resp_nc(c2G4_dev_st);
167 }
168 
169 /**
170  * Provide the phy a new abort struct (during a CCA transaction)
171  *
172  * returns -1 on error, otherwise the response from the phy.
173  * The possible responses depend on the transaction which is ongoing
174  *
175  * Note that the response structures will come thru the pointers
176  * which were provided with the call which initiated the transaction
177  */
p2G4_dev_provide_new_cca_abort_s_nc_b(p2G4_dev_state_nc_t * c2G4_dev_st,p2G4_abort_t * abort)178 int p2G4_dev_provide_new_cca_abort_s_nc_b(p2G4_dev_state_nc_t *c2G4_dev_st, p2G4_abort_t * abort){
179   CHECK_CONNECTED(c2G4_dev_st->pb_dev_state.connected);
180 
181   if ( c2G4_dev_st->ongoing != CCA_Abort_Reeval_2G4 ) {
182     bs_trace_error_time_line("Tried to send a new CCA Abort substruct but we are not in a CCA transaction abort reevaluation!\n");
183   }
184 
185   pb_send_msg(c2G4_dev_st->pb_dev_state.ff_dtp, P2G4_MSG_RERESP_ABORTREEVAL,
186               (void *)abort, sizeof(p2G4_abort_t));
187 
188   return p2G4_dev_get_cca_resp_nc(c2G4_dev_st);
189 }
190 
191 /**
192  * Request a wait to the phy and block until receiving the response
193  * If everything goes ok 0 is returned
194  *
195  * Otherwise, we should disconnect (-1 will be returned)
196  */
p2G4_dev_req_wait_s_nc_b(p2G4_dev_state_nc_t * p2G4_dev_state,pb_wait_t * wait_s)197 int p2G4_dev_req_wait_s_nc_b(p2G4_dev_state_nc_t *p2G4_dev_state, pb_wait_t *wait_s){
198   return pb_dev_request_wait_block(&p2G4_dev_state->pb_dev_state, wait_s);
199 }
200 
c2G4_handle_rx_responses_s_nc(p2G4_dev_state_nc_t * c2G4_dev_st,pc_header_t header)201 static int c2G4_handle_rx_responses_s_nc(p2G4_dev_state_nc_t *c2G4_dev_st, pc_header_t header){
202   int ret;
203   p2G4_rx_done_t *rx_done_s = c2G4_dev_st->rx_done_s;
204 
205   if (header == P2G4_MSG_ABORTREEVAL) {
206     c2G4_dev_st->ongoing = Rx_Abort_Reeval_2G4;
207 
208   } else if ((header == P2G4_MSG_RX_ADDRESSFOUND) && (c2G4_dev_st->WeGotAddress == false )) {
209     ret = pb_dev_read(&c2G4_dev_st->pb_dev_state, rx_done_s, sizeof(p2G4_rx_done_t));
210     if (ret == -1)
211       return -1;
212 
213     ret = p2G4_rx_pick_packet(&c2G4_dev_st->pb_dev_state, rx_done_s->packet_size,
214                               c2G4_dev_st->rxbuf, c2G4_dev_st->bufsize);
215     if (ret == -1)
216       return ret;
217 
218     c2G4_dev_st->WeGotAddress = true;
219     c2G4_dev_st->ongoing = Rx_Header_Eval_2G4;
220 
221   } else if (header == PB_MSG_DISCONNECT) {
222     c2G4_dev_st->ongoing = Nothing_2G4;
223     pb_dev_clean_up(&c2G4_dev_st->pb_dev_state);
224     return -1;
225   } else if (header == P2G4_MSG_RX_END) {
226     c2G4_dev_st->ongoing = Nothing_2G4;
227     ret = pb_dev_read(&c2G4_dev_st->pb_dev_state, rx_done_s, sizeof(p2G4_rx_done_t));
228     if (ret == 1)
229       return -1;
230   } else {
231     INVALID_RESP(header);
232   }
233   return header;
234 }
235 
c2G4_handle_rxv2_responses_s_nc(p2G4_dev_state_nc_t * c2G4_dev_st,pc_header_t header)236 static int c2G4_handle_rxv2_responses_s_nc(p2G4_dev_state_nc_t *c2G4_dev_st, pc_header_t header){
237   int ret;
238   p2G4_rxv2_done_t *rx_done_s = c2G4_dev_st->rxv2_done_s;
239 
240   if (header == P2G4_MSG_ABORTREEVAL) {
241     c2G4_dev_st->ongoing = Rx_Abort_Reeval_2G4;
242 
243   } else if ((header == P2G4_MSG_RXV2_ADDRESSFOUND) && (c2G4_dev_st->WeGotAddress == false )) {
244     ret = pb_dev_read(&c2G4_dev_st->pb_dev_state, rx_done_s, sizeof(p2G4_rxv2_done_t));
245     if (ret == -1)
246       return -1;
247 
248     ret = p2G4_rx_pick_packet(&c2G4_dev_st->pb_dev_state, rx_done_s->packet_size,
249                               c2G4_dev_st->rxbuf, c2G4_dev_st->bufsize);
250     if (ret == -1)
251       return ret;
252 
253     c2G4_dev_st->WeGotAddress = true;
254     c2G4_dev_st->ongoing = Rx_Header_Eval_2G4;
255 
256   } else if (header == PB_MSG_DISCONNECT) {
257     c2G4_dev_st->ongoing = Nothing_2G4;
258     pb_dev_clean_up(&c2G4_dev_st->pb_dev_state);
259     return -1;
260   } else if (header == P2G4_MSG_RXV2_END) {
261     c2G4_dev_st->ongoing = Nothing_2G4;
262     ret = pb_dev_read(&c2G4_dev_st->pb_dev_state, rx_done_s, sizeof(p2G4_rxv2_done_t));
263     if (ret == 1)
264       return -1;
265   } else {
266     INVALID_RESP(header);
267   }
268   return header;
269 }
270 
271 /**
272  * Continue reception after an address evaluation request
273  *  bool dev_accepts defines if the device accepts the packet or not
274  *
275  * if dev_accepts is false, the reception ends and this function returns 0
276  * otherwise, the function will eventually return
277  *  P2G4_MSG_RX_END ( and update rx_done_s )
278  *  or a new P2G4_MSG_ABORTREEVAL
279  *
280  * Note that the response structures will come thru the pointers which
281  * were provided with the call which initiated the transaction
282  */
p2G4_dev_rx_cont_after_addr_s_nc_b(p2G4_dev_state_nc_t * p2G4_dev_state,bool dev_accepts)283 int p2G4_dev_rx_cont_after_addr_s_nc_b(p2G4_dev_state_nc_t *p2G4_dev_state, bool dev_accepts){
284   CHECK_CONNECTED(p2G4_dev_state->pb_dev_state.connected);
285 
286   if ( p2G4_dev_state->ongoing != Rx_Header_Eval_2G4 ) {
287     bs_trace_error_time_line("Tried to continue from an Rx Header eval, but we are not doing that now..\n");
288   }
289   pc_header_t header;
290 
291   if (dev_accepts) {
292     header = P2G4_MSG_RXCONT;
293   } else {
294     header = P2G4_MSG_RXSTOP;
295   }
296   write(p2G4_dev_state->pb_dev_state.ff_dtp, &header, sizeof(header));
297 
298   if (!dev_accepts) {
299     p2G4_dev_state->ongoing = Nothing_2G4;
300     return 0;
301   }
302 
303   if (pb_dev_read(&p2G4_dev_state->pb_dev_state, &header, sizeof(header)) == -1) {
304     return -1;
305   }
306 
307   return c2G4_handle_rx_responses_s_nc(p2G4_dev_state, header);
308 }
309 
310 /**
311  * Continue reception (v2) after an address evaluation request
312  * providing an updated abort substructure
313  *  bool dev_accepts defines if the device accepts the packet or not
314  *  p2G4_abort_t * abort new abort parameters (don't care if dev_accepts == false)
315  *
316  * if dev_accepts is false, the reception ends and this function returns 0
317  * otherwise, the function will eventually return
318  *  P2G4_MSG_RXV2_END ( and update rx_done_s )
319  *  or a new P2G4_MSG_ABORTREEVAL
320  *
321  * Note that the response structures will come thru the pointers which
322  * were provided with the call which initiated the transaction
323  */
p2G4_dev_rxv2_cont_after_addr_s_nc_b(p2G4_dev_state_nc_t * p2G4_dev_state,bool dev_accepts,p2G4_abort_t * abort)324 int p2G4_dev_rxv2_cont_after_addr_s_nc_b(p2G4_dev_state_nc_t *p2G4_dev_state, bool dev_accepts, p2G4_abort_t * abort){
325   CHECK_CONNECTED(p2G4_dev_state->pb_dev_state.connected);
326 
327   if ( p2G4_dev_state->ongoing != Rx_Header_Eval_2G4 ) {
328     bs_trace_error_time_line("Tried to continue from an Rx Header eval, but we are not doing that now..\n");
329   }
330   pc_header_t header;
331 
332   if (dev_accepts) {
333     header = P2G4_MSG_RXV2CONT;
334     write(p2G4_dev_state->pb_dev_state.ff_dtp, &header, sizeof(header));
335     write(p2G4_dev_state->pb_dev_state.ff_dtp, abort, sizeof(p2G4_abort_t));
336   } else {
337     header = P2G4_MSG_RXSTOP;
338     write(p2G4_dev_state->pb_dev_state.ff_dtp, &header, sizeof(header));
339   }
340 
341   if (!dev_accepts) {
342     p2G4_dev_state->ongoing = Nothing_2G4;
343     return 0;
344   }
345 
346   if (pb_dev_read(&p2G4_dev_state->pb_dev_state, &header, sizeof(header)) == -1) {
347     return -1;
348   }
349 
350   return c2G4_handle_rxv2_responses_s_nc(p2G4_dev_state, header);
351 }
352 
353 
354 /**
355  * Provide the phy a new abort struct (during an Rx transaction)
356  *
357  * returns -1 on error, otherwise the response from the phy.
358  * The possible responses depend on the step in the ongoing transaction
359  *
360  * Note that the response structures will come thru the pointers which
361  * were provided with the call which initiated the transaction
362  */
p2G4_dev_provide_new_rx_abort_s_nc_b(p2G4_dev_state_nc_t * p2G4_dev_state,p2G4_abort_t * abort)363 int p2G4_dev_provide_new_rx_abort_s_nc_b(p2G4_dev_state_nc_t *p2G4_dev_state, p2G4_abort_t * abort){
364   CHECK_CONNECTED(p2G4_dev_state->pb_dev_state.connected);
365   if ( p2G4_dev_state->ongoing != Rx_Abort_Reeval_2G4 ) {
366     bs_trace_error_time_line("Tried to send a new Rx Abort substruct but we are not in a Rx transaction abort reevaluation!\n");
367   }
368   pc_header_t header;
369 
370   pb_send_msg(p2G4_dev_state->pb_dev_state.ff_dtp, P2G4_MSG_RERESP_ABORTREEVAL,
371       (void *)abort,  sizeof(p2G4_abort_t));
372 
373   if (pb_dev_read(&p2G4_dev_state->pb_dev_state, &header, sizeof(header)) == -1) {
374     return -1;
375   }
376 
377   return c2G4_handle_rx_responses_s_nc(p2G4_dev_state, header);
378 }
379 
380 /**
381  * Provide the phy a new abort struct (during an Rxv2 transaction)
382  *
383  * returns -1 on error, otherwise the response from the phy.
384  * The possible responses depend on the step in the ongoing transaction
385  *
386  * Note that the response structures will come thru the pointers which
387  * were provided with the call which initiated the transaction
388  */
p2G4_dev_provide_new_rxv2_abort_s_nc_b(p2G4_dev_state_nc_t * p2G4_dev_state,p2G4_abort_t * abort)389 int p2G4_dev_provide_new_rxv2_abort_s_nc_b(p2G4_dev_state_nc_t *p2G4_dev_state, p2G4_abort_t * abort){
390   CHECK_CONNECTED(p2G4_dev_state->pb_dev_state.connected);
391   if ( p2G4_dev_state->ongoing != Rx_Abort_Reeval_2G4 ) {
392     bs_trace_error_time_line("Tried to send a new Rx Abort substruct but we are not in a Rx transaction abort reevaluation!\n");
393   }
394   pc_header_t header;
395 
396   pb_send_msg(p2G4_dev_state->pb_dev_state.ff_dtp, P2G4_MSG_RERESP_ABORTREEVAL,
397       (void *)abort,  sizeof(p2G4_abort_t));
398 
399   if (pb_dev_read(&p2G4_dev_state->pb_dev_state, &header, sizeof(header)) == -1) {
400     return -1;
401   }
402 
403   return c2G4_handle_rxv2_responses_s_nc(p2G4_dev_state, header);
404 }
405 
p2G4_dev_req_RSSI_s_nc_b(p2G4_dev_state_nc_t * p2G4_dev_st,p2G4_rssi_t * RSSI_s,p2G4_rssi_done_t * RSSI_done_s)406 int p2G4_dev_req_RSSI_s_nc_b(p2G4_dev_state_nc_t *p2G4_dev_st, p2G4_rssi_t *RSSI_s, p2G4_rssi_done_t *RSSI_done_s){
407   CHECK_CONNECTED(p2G4_dev_st->pb_dev_state.connected);
408   pb_send_msg(p2G4_dev_st->pb_dev_state.ff_dtp,
409               P2G4_MSG_RSSIMEAS, (void *)RSSI_s, sizeof(p2G4_rssi_t));
410   return p2G4_dev_get_rssi_resp_i(&p2G4_dev_st->pb_dev_state, RSSI_done_s);
411 }
412 
413 /**
414  * Request a reception to the phy
415  *
416  * rx_buf is a pointer to a buffer in which the packet will be copied.
417  * The buffer shall have buf_size bytes.
418  * If buf_size is 0, this function will allocate a new buffer and point
419  *  *RxBuf to it (the application must free it afterwards).
420  * Otherwise this function will fail if the buffer is to small to read the
421  * incoming packet
422  *
423  * returns -1 on error, the received response header >=0 otherwise
424  */
p2G4_dev_req_rx_s_nc_b(p2G4_dev_state_nc_t * p2G4_dev_state,p2G4_rx_t * rx_s,p2G4_rx_done_t * rx_done_s,uint8_t ** rx_buf,size_t buf_size)425 int p2G4_dev_req_rx_s_nc_b(p2G4_dev_state_nc_t *p2G4_dev_state, p2G4_rx_t *rx_s, p2G4_rx_done_t *rx_done_s, uint8_t **rx_buf, size_t buf_size) {
426   CHECK_CONNECTED(p2G4_dev_state->pb_dev_state.connected);
427 
428   if ( p2G4_dev_state->ongoing != Nothing_2G4 ) {
429     bs_trace_error_time_line("Tried to request a new Rx while another transaction was ongoing\n");
430   }
431 
432   pb_send_msg(p2G4_dev_state->pb_dev_state.ff_dtp, P2G4_MSG_RX,
433               (void *)rx_s,  sizeof(p2G4_rx_t));
434 
435   p2G4_dev_state->bufsize = buf_size;
436   p2G4_dev_state->rxbuf   = rx_buf;
437   p2G4_dev_state->rx_done_s = rx_done_s;
438   p2G4_dev_state->WeGotAddress = false;
439 
440   pc_header_t header;
441   int ret;
442 
443   ret = pb_dev_read(&p2G4_dev_state->pb_dev_state, &header, sizeof(header));
444   if (ret==-1)
445     return -1;
446 
447   return c2G4_handle_rx_responses_s_nc(p2G4_dev_state, header);
448 }
449 
450 /**
451  * Request a reception (v2) to the phy
452  *
453  * rx_buf is a pointer to a buffer in which the packet will be copied.
454  * The buffer shall have buf_size bytes.
455  * If buf_size is 0, this function will allocate a new buffer and point
456  *  *RxBuf to it (the application must free it afterwards).
457  * Otherwise this function will fail if the buffer is to small to read the
458  * incoming packet
459  *
460  * returns -1 on error, the received response header >=0 otherwise
461  */
p2G4_dev_req_rxv2_s_nc_b(p2G4_dev_state_nc_t * p2G4_dev_state,p2G4_rxv2_t * rx_s,p2G4_address_t * phy_addr,p2G4_rxv2_done_t * rx_done_s,uint8_t ** rx_buf,size_t buf_size)462 int p2G4_dev_req_rxv2_s_nc_b(p2G4_dev_state_nc_t *p2G4_dev_state, p2G4_rxv2_t *rx_s, p2G4_address_t *phy_addr, p2G4_rxv2_done_t *rx_done_s, uint8_t **rx_buf, size_t buf_size) {
463   CHECK_CONNECTED(p2G4_dev_state->pb_dev_state.connected);
464 
465   if ( p2G4_dev_state->ongoing != Nothing_2G4 ) {
466     bs_trace_error_time_line("Tried to request a new Rx while another transaction was ongoing\n");
467   }
468 
469   pb_send_msg(p2G4_dev_state->pb_dev_state.ff_dtp, P2G4_MSG_RXV2,
470               (void *)rx_s,  sizeof(p2G4_rxv2_t));
471   if (rx_s->n_addr > 0) {
472     write(p2G4_dev_state->pb_dev_state.ff_dtp, phy_addr, sizeof(p2G4_address_t)*rx_s->n_addr);
473   }
474 
475   p2G4_dev_state->bufsize = buf_size;
476   p2G4_dev_state->rxbuf   = rx_buf;
477   p2G4_dev_state->rxv2_done_s = rx_done_s;
478   p2G4_dev_state->WeGotAddress = false;
479 
480   pc_header_t header;
481   int ret;
482 
483   ret = pb_dev_read(&p2G4_dev_state->pb_dev_state, &header, sizeof(header));
484   if (ret==-1)
485     return -1;
486 
487   return c2G4_handle_rxv2_responses_s_nc(p2G4_dev_state, header);
488 }
489