1 /*
2  * Copyright 2018 Oticon A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "bs_pc_base.h"
7 #include "bs_pc_2G4_types.h"
8 #include "bs_pc_2G4.h"
9 #include "bs_tracing.h"
10 #include <unistd.h>
11 
12 static pb_phy_state_t cb_med_state = {0};
13 
14 #pragma GCC diagnostic ignored "-Wunused-result"
15 
p2G4_phy_initcom(const char * s,const char * p,uint n)16 void p2G4_phy_initcom(const char* s, const char* p, uint n){
17   if (pb_phy_initcom(&cb_med_state, s, p, n)) {
18     bs_trace_error_line("Cannot establish communication with devices\n");
19   }
20 }
21 
p2G4_phy_disconnect_all_devices()22 void p2G4_phy_disconnect_all_devices(){
23   pb_phy_disconnect_devices(&cb_med_state);
24 }
25 
p2G4_phy_resp_wait(uint d)26 void p2G4_phy_resp_wait(uint d) {
27   pb_phy_resp_wait(&cb_med_state, d);
28 }
29 
30 /**
31  *  Respond to the device with P2G4_MSG_TX_END and the tx done structure
32  */
p2G4_phy_resp_tx(uint d,p2G4_tx_done_t * tx_done_s)33 void p2G4_phy_resp_tx(uint d, p2G4_tx_done_t *tx_done_s) {
34   if (pb_phy_is_connected_to_device(&cb_med_state, d)) {
35     pb_send_msg(cb_med_state.ff_ptd[d], P2G4_MSG_TX_END,
36                 (void *)tx_done_s, sizeof(p2G4_tx_done_t));
37   }
38 }
39 
40 /**
41  * Respond to the device with P2G4_MSG_RX_ADDRESSFOUND a
42  * p2G4_rx_done_t and a possible packet of p2G4_rx_done_t->packet_size bytes
43  */
p2G4_phy_resp_rx_addr_found(uint d,p2G4_rx_done_t * rx_done_s,uint8_t * packet)44 void p2G4_phy_resp_rx_addr_found(uint d, p2G4_rx_done_t* rx_done_s, uint8_t *packet) {
45   if (pb_phy_is_connected_to_device(&cb_med_state, d)) {
46     pb_send_msg(cb_med_state.ff_ptd[d], P2G4_MSG_RX_ADDRESSFOUND,
47                 (void *)rx_done_s, sizeof(p2G4_rx_done_t));
48     pb_send_payload(cb_med_state.ff_ptd[d], packet, rx_done_s->packet_size);
49   }
50 }
51 
52 /**
53  * Respond to the device with P2G4_MSG_RXV2_ADDRESSFOUND a
54  * p2G4_rx_done_t and a possible packet of p2G4_rxv2_done_t->packet_size bytes
55  */
p2G4_phy_resp_rxv2_addr_found(uint d,p2G4_rxv2_done_t * rx_done_s,uint8_t * packet)56 void p2G4_phy_resp_rxv2_addr_found(uint d, p2G4_rxv2_done_t* rx_done_s, uint8_t *packet) {
57   if (pb_phy_is_connected_to_device(&cb_med_state, d)) {
58     pb_send_msg(cb_med_state.ff_ptd[d], P2G4_MSG_RXV2_ADDRESSFOUND,
59                 (void *)rx_done_s, sizeof(p2G4_rxv2_done_t));
60     pb_send_payload(cb_med_state.ff_ptd[d], packet, rx_done_s->packet_size);
61   }
62 }
63 
64 /**
65  * Respond to the device with P2G4_MSG_RX_END and a p2G4_rx_done_t
66  * (note that the packet was already sent out in the address found)
67  */
p2G4_phy_resp_rx(uint d,p2G4_rx_done_t * rx_done_s)68 void p2G4_phy_resp_rx(uint d, p2G4_rx_done_t* rx_done_s) {
69   if (pb_phy_is_connected_to_device(&cb_med_state, d)) {
70     pb_send_msg(cb_med_state.ff_ptd[d], P2G4_MSG_RX_END,
71                 (void *)rx_done_s, sizeof(p2G4_rx_done_t));
72   }
73 }
74 
75 /**
76  * Respond to the device with P2G4_MSG_RX_ENDV2 and a p2G4_rx_donev2_t
77  * (note that the packet was already sent out in the address found)
78  */
p2G4_phy_resp_rxv2(uint d,p2G4_rxv2_done_t * rx_done_s)79 void p2G4_phy_resp_rxv2(uint d, p2G4_rxv2_done_t* rx_done_s) {
80   if (pb_phy_is_connected_to_device(&cb_med_state, d)) {
81     pb_send_msg(cb_med_state.ff_ptd[d], P2G4_MSG_RXV2_END,
82                 (void *)rx_done_s, sizeof(p2G4_rxv2_done_t));
83   }
84 }
85 
86 /**
87  * Respond to the device with P2G4_MSG_CCA_END and a p2G4_cca_done_t
88  */
p2G4_phy_resp_cca(uint d,p2G4_cca_done_t * sc_done_s)89 void p2G4_phy_resp_cca(uint d, p2G4_cca_done_t *sc_done_s) {
90   if (pb_phy_is_connected_to_device(&cb_med_state, d)) {
91     pb_send_msg(cb_med_state.ff_ptd[d], P2G4_MSG_CCA_END,
92                 (void *)sc_done_s, sizeof(p2G4_cca_done_t));
93   }
94 }
95 
96 /**
97  * Respond to the device with P2G4_MSG_RSSI_END and a p2G4_rssi_done_t
98  */
p2G4_phy_resp_RSSI(uint d,p2G4_rssi_done_t * RSSI_done_s)99 void p2G4_phy_resp_RSSI(uint d, p2G4_rssi_done_t* RSSI_done_s) {
100   if (pb_phy_is_connected_to_device(&cb_med_state, d)) {
101     pb_send_msg(cb_med_state.ff_ptd[d], P2G4_MSG_RSSI_END,
102                 (void *)RSSI_done_s, sizeof(p2G4_rssi_done_t));
103   }
104 }
105 
106 /**
107  * Respond to the device with P2G4_MSG_ABORTREVAL_RRSI and a p2G4_rssi_done_t
108  * (during an abort reeval procedure, as a result of the device asking for
109  * an immediate RSSI measurement)
110  */
p2G4_phy_resp_IMRSSI(uint d,p2G4_rssi_done_t * RSSI_done_s)111 void p2G4_phy_resp_IMRSSI(uint d, p2G4_rssi_done_t* RSSI_done_s) {
112   if (pb_phy_is_connected_to_device(&cb_med_state, d)) {
113     pb_send_msg(cb_med_state.ff_ptd[d], P2G4_MSG_IMMRSSI_RRSI_DONE,
114                 (void *)RSSI_done_s, sizeof(p2G4_rssi_done_t));
115   }
116 }
117 
p2G4_get_next_request(uint d)118 pc_header_t p2G4_get_next_request(uint d){
119   return pb_phy_get_next_request(&cb_med_state, d);
120 }
121 
p2G4_phy_get(uint d,void * b,size_t size)122 void p2G4_phy_get(uint d, void* b, size_t size) {
123   if (pb_phy_is_connected_to_device(&cb_med_state, d)) {
124     read(cb_med_state.ff_dtp[d], b, size);
125   }
126 }
127 
128 
129 /**
130  * Get abort structure from device
131  */
p2G4_phy_get_abort_struct(uint d,p2G4_abort_t * abort_s)132 void p2G4_phy_get_abort_struct(uint d, p2G4_abort_t* abort_s) {
133   ssize_t read_size = 0;
134   read_size = read(cb_med_state.ff_dtp[d], abort_s, sizeof(p2G4_abort_t));
135 
136   if (read_size != sizeof(p2G4_abort_t)) {
137     //There is some likelihood that a device will crash badly during abort
138     //reevaluation, therefore we try to handle it
139     bs_trace_warning_line(
140         "Low level communication with device %i broken during Abort reevaluation (tried to get %i got %i bytes) (most likely the device was terminated)\n",
141         d, sizeof(p2G4_abort_t), read_size);
142     pb_phy_disconnect_devices(&cb_med_state);
143     bs_trace_error_line("Exiting\n");
144   }
145 }
146 
147 /**
148  * Ask the device for a new abort struct for the ongoing Tx or Rx
149  */
p2G4_phy_get_new_abort(uint d,p2G4_abort_t * abort_s)150 int p2G4_phy_get_new_abort(uint d, p2G4_abort_t* abort_s) {
151   if (pb_phy_is_connected_to_device(&cb_med_state, d)) {
152     pc_header_t r_header = P2G4_MSG_ABORTREEVAL;
153     write(cb_med_state.ff_ptd[d], &r_header, sizeof(r_header));
154 
155     pc_header_t header = PB_MSG_DISCONNECT;
156     read(cb_med_state.ff_dtp[d], &header, sizeof(header));
157 
158     if (header == PB_MSG_TERMINATE) {
159       return PB_MSG_TERMINATE;
160     } else if (header == P2G4_MSG_RERESP_IMMRSSI) {
161       return P2G4_MSG_RERESP_IMMRSSI;
162     } else if (header != P2G4_MSG_RERESP_ABORTREEVAL) {
163       //if the read failed or the device really wants to disconnect in the
164       //middle of an abort (which is not really supported) we try to
165       //handle it gracefully
166       pb_phy_free_one_device(&cb_med_state ,d);
167     } else {
168       p2G4_phy_get_abort_struct(d, abort_s);
169     }
170   }
171   return 0;
172 }
173