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