3535struct ble_eatt {
3636 SLIST_ENTRY (ble_eatt ) next ;
3737 uint16_t conn_handle ;
38- struct ble_l2cap_chan * chan ;
38+ struct ble_l2cap_chan * chan [ MYNEWT_VAL ( BLE_EATT_CHAN_PER_CONN )] ;
3939 uint8_t client_op ;
40+ uint8_t channels_to_connect ;
4041
4142 /* Packet transmit queue */
4243 STAILQ_HEAD (, os_mbuf_pkthdr ) eatt_tx_q ;
@@ -122,16 +123,78 @@ ble_eatt_find_by_conn_handle_and_busy_op(uint16_t conn_handle, uint8_t op)
122123static struct ble_eatt *
123124ble_eatt_find (uint16_t conn_handle , uint16_t cid )
124125{
126+ int i ;
125127 struct ble_eatt * eatt ;
126128
127129 SLIST_FOREACH (eatt , & g_ble_eatt_list , next ) {
128- if (( eatt -> conn_handle == conn_handle ) &&
129- ( eatt -> chan ) &&
130- (eatt -> chan -> scid == cid ) ) {
130+ if (eatt -> conn_handle == conn_handle ) {
131+ for ( i = 0 ; i < MYNEWT_VAL ( BLE_EATT_CHAN_PER_CONN ); i ++ ) {
132+ if (eatt -> chan [ i ] && eatt -> chan [ i ] -> scid == cid ) {
131133 return eatt ;
132134 }
133135 }
136+ }
137+ }
138+ return NULL ;
139+ }
140+
141+ static size_t
142+ ble_eatt_used_channels (uint16_t conn_handle )
143+ {
144+ int i ;
145+ size_t used_chans = 0 ;
146+ struct ble_eatt * eatt ;
147+
148+ eatt = ble_eatt_find_by_conn_handle (conn_handle );
149+ if (!eatt ) {
150+ BLE_EATT_LOG_ERROR ("ble_eatt_used_channels: No eatt for given conn handle\n" );
151+ }
152+
153+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
154+ if (eatt -> chan [i ] != NULL ) {
155+ used_chans ++ ;
156+ }
157+ }
158+
159+ return used_chans ;
160+ }
161+
162+ static int
163+ ble_eatt_free_channel_idx (struct ble_eatt * eatt )
164+ {
165+ int i ;
166+
167+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
168+ if (eatt -> chan [i ] == NULL )
169+ return i ;
170+ }
171+
172+ return -1 ;
173+ }
174+
175+ static struct ble_l2cap_chan *
176+ ble_eatt_find_chan (struct ble_eatt * eatt , struct ble_l2cap_chan * chan )
177+ {
178+ int i ;
179+
180+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
181+ if (eatt -> chan [i ] == chan ) {
182+ return eatt -> chan [i ];
183+ }
184+ }
185+ return NULL ;
186+ }
134187
188+ static struct ble_l2cap_chan *
189+ ble_eatt_channel_find_by_cid (struct ble_eatt * eatt , uint16_t cid )
190+ {
191+ int i ;
192+
193+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
194+ if (eatt -> chan [i ] && eatt -> chan [i ]-> scid == cid ) {
195+ return eatt -> chan [i ];
196+ }
197+ }
135198 return NULL ;
136199}
137200
@@ -160,6 +223,7 @@ ble_eatt_prepare_rx_sdu(struct ble_l2cap_chan *chan)
160223static void
161224ble_eatt_wakeup_cb (struct ble_npl_event * ev )
162225{
226+ int i ;
163227 struct ble_eatt * eatt ;
164228 struct os_mbuf * txom ;
165229 struct os_mbuf_pkthdr * omp ;
@@ -173,14 +237,24 @@ ble_eatt_wakeup_cb(struct ble_npl_event *ev)
173237 STAILQ_REMOVE_HEAD (& eatt -> eatt_tx_q , omp_next );
174238
175239 txom = OS_MBUF_PKTHDR_TO_MBUF (omp );
176- ble_l2cap_get_chan_info (eatt -> chan , & info );
240+
241+ /* Look for the already established channel.
242+ * Send necessary data, then break.
243+ */
244+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
245+ if (eatt -> chan [i ] != NULL ) {
246+ ble_l2cap_get_chan_info (eatt -> chan [i ], & info );
177247 ble_eatt_tx (eatt -> conn_handle , info .dcid , txom );
248+ break ;
249+ }
250+ }
178251 }
179252}
180253
181254static struct ble_eatt *
182255ble_eatt_alloc (void )
183256{
257+ int i ;
184258 struct ble_eatt * eatt ;
185259
186260 eatt = os_memblock_get (& ble_eatt_conn_pool );
@@ -192,7 +266,9 @@ ble_eatt_alloc(void)
192266 SLIST_INSERT_HEAD (& g_ble_eatt_list , eatt , next );
193267
194268 eatt -> conn_handle = BLE_HS_CONN_HANDLE_NONE ;
195- eatt -> chan = NULL ;
269+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
270+ eatt -> chan [i ] = NULL ;
271+ }
196272 eatt -> client_op = 0 ;
197273
198274 STAILQ_INIT (& eatt -> eatt_tx_q );
@@ -221,7 +297,9 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
221297{
222298 struct ble_eatt * eatt = arg ;
223299 struct ble_gap_conn_desc desc ;
300+ struct ble_l2cap_chan * channel ;
224301 uint8_t opcode ;
302+ int chan_idx ;
225303 int rc ;
226304
227305 switch (event -> type ) {
@@ -231,7 +309,15 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
231309 ble_eatt_free (eatt );
232310 return 0 ;
233311 }
234- eatt -> chan = event -> connect .chan ;
312+ chan_idx = ble_eatt_free_channel_idx (eatt );
313+ if (chan_idx > 0 ) {
314+ eatt -> chan [chan_idx ] = event -> connect .chan ;
315+ } else {
316+ BLE_EATT_LOG_ERROR ("eatt: Connect event: No free channels\n" );
317+ ble_eatt_free (eatt );
318+ return 0 ;
319+ }
320+
235321 break ;
236322 case BLE_L2CAP_EVENT_COC_DISCONNECTED :
237323 BLE_EATT_LOG_DEBUG ("eatt: Disconnected \n" );
@@ -266,7 +352,11 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
266352 ble_npl_eventq_put (ble_hs_evq_get (), & eatt -> wakeup_ev );
267353 break ;
268354 case BLE_L2CAP_EVENT_COC_DATA_RECEIVED :
269- assert (eatt -> chan == event -> receive .chan );
355+ channel = ble_eatt_find_chan (eatt , event -> receive .chan );
356+ if (channel == NULL ) {
357+ BLE_EATT_LOG_ERROR ("eatt: receive: Invalid channel\n" );
358+ ble_eatt_free (eatt );
359+ }
270360 opcode = event -> receive .sdu_rx -> om_data [0 ];
271361 if (ble_eatt_supported_rsp (opcode )) {
272362 ble_npl_eventq_put (ble_hs_evq_get (), & eatt -> wakeup_ev );
@@ -279,7 +369,7 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
279369 * • The Signed Write Without Response sub-procedure shall only be
280370 * supported on the LE Fixed Channel Unenhanced ATT bearer.
281371 */
282- ble_l2cap_disconnect (eatt -> chan );
372+ ble_l2cap_disconnect (channel );
283373 return BLE_HS_EREJECT ;
284374 }
285375
@@ -293,11 +383,11 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
293383 * encryption.
294384 */
295385 if (!desc .sec_state .encrypted ) {
296- ble_l2cap_disconnect (eatt -> chan );
386+ ble_l2cap_disconnect (channel );
297387 return BLE_HS_EREJECT ;
298388 }
299389
300- ble_eatt_att_rx_cb (event -> receive .conn_handle , eatt -> chan -> scid , & event -> receive .sdu_rx );
390+ ble_eatt_att_rx_cb (event -> receive .conn_handle , channel -> scid , & event -> receive .sdu_rx );
301391 if (event -> receive .sdu_rx ) {
302392 os_mbuf_free_chain (event -> receive .sdu_rx );
303393 event -> receive .sdu_rx = NULL ;
@@ -306,7 +396,7 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
306396 /* Receiving L2CAP data is no longer possible, terminate connection */
307397 rc = ble_eatt_prepare_rx_sdu (event -> receive .chan );
308398 if (rc ) {
309- ble_l2cap_disconnect (eatt -> chan );
399+ ble_l2cap_disconnect (channel );
310400 return BLE_HS_ENOMEM ;
311401 }
312402 break ;
@@ -337,8 +427,8 @@ ble_eatt_setup_cb(struct ble_npl_event *ev)
337427 BLE_EATT_LOG_DEBUG ("eatt: connecting eatt on conn_handle 0x%04x\n" , eatt -> conn_handle );
338428
339429 rc = ble_l2cap_enhanced_connect (eatt -> conn_handle , BLE_EATT_PSM ,
340- MYNEWT_VAL (BLE_EATT_MTU ), 1 , & om ,
341- ble_eatt_l2cap_event_fn , eatt );
430+ MYNEWT_VAL (BLE_EATT_MTU ), eatt -> channels_to_connect ,
431+ & om , ble_eatt_l2cap_event_fn , eatt );
342432 if (rc ) {
343433 BLE_EATT_LOG_ERROR ("eatt: Failed to connect EATT on conn_handle 0x%04x (status=%d)\n" ,
344434 eatt -> conn_handle , rc );
@@ -441,6 +531,7 @@ ble_eatt_gap_event(struct ble_gap_event *event, void *arg)
441531uint16_t
442532ble_eatt_get_available_chan_cid (uint16_t conn_handle , uint8_t op )
443533{
534+ int i ;
444535 struct ble_eatt * eatt ;
445536
446537 eatt = ble_eatt_find_not_busy (conn_handle );
@@ -450,7 +541,13 @@ ble_eatt_get_available_chan_cid(uint16_t conn_handle, uint8_t op)
450541
451542 eatt -> client_op = op ;
452543
453- return eatt -> chan -> scid ;
544+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
545+ if (eatt -> chan [i ] != NULL ) {
546+ return eatt -> chan [i ]-> scid ;
547+ }
548+ }
549+
550+ return BLE_L2CAP_CID_ATT ;
454551}
455552
456553void
@@ -472,17 +569,25 @@ int
472569ble_eatt_tx (uint16_t conn_handle , uint16_t cid , struct os_mbuf * txom )
473570{
474571 struct ble_eatt * eatt ;
572+ static struct ble_l2cap_chan * channel ;
475573 int rc ;
476574
477575 BLE_EATT_LOG_DEBUG ("eatt: %s, size %d " , __func__ , OS_MBUF_PKTLEN (txom ));
478576 eatt = ble_eatt_find (conn_handle , cid );
479- if (!eatt || !eatt -> chan ) {
577+ if (!eatt ) {
578+ BLE_EATT_LOG_ERROR ("Eatt not available" );
579+ rc = BLE_HS_ENOENT ;
580+ goto error ;
581+ }
582+
583+ channel = ble_eatt_channel_find_by_cid (eatt , cid );
584+ if (!channel ) {
480585 BLE_EATT_LOG_ERROR ("Eatt not available" );
481586 rc = BLE_HS_ENOENT ;
482587 goto error ;
483588 }
484589
485- rc = ble_l2cap_send (eatt -> chan , txom );
590+ rc = ble_l2cap_send (channel , txom );
486591 if (rc == 0 ) {
487592 goto done ;
488593 }
0 commit comments