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,79 @@ 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 (
151+ "ble_eatt_used_channels: No eatt for given conn handle\n" );
152+ }
153+
154+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
155+ if (eatt -> chan [i ] != NULL ) {
156+ used_chans ++ ;
157+ }
158+ }
159+
160+ return used_chans ;
161+ }
162+
163+ static int
164+ ble_eatt_free_channel_idx (struct ble_eatt * eatt )
165+ {
166+ int i ;
167+
168+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
169+ if (eatt -> chan [i ] == NULL )
170+ return i ;
171+ }
172+
173+ return -1 ;
174+ }
175+
176+ static struct ble_l2cap_chan *
177+ ble_eatt_find_chan (struct ble_eatt * eatt , struct ble_l2cap_chan * chan )
178+ {
179+ int i ;
180+
181+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
182+ if (eatt -> chan [i ] == chan ) {
183+ return eatt -> chan [i ];
184+ }
185+ }
186+ return NULL ;
187+ }
134188
189+ static struct ble_l2cap_chan *
190+ ble_eatt_channel_find_by_cid (struct ble_eatt * eatt , uint16_t cid )
191+ {
192+ int i ;
193+
194+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
195+ if (eatt -> chan [i ] && eatt -> chan [i ]-> scid == cid ) {
196+ return eatt -> chan [i ];
197+ }
198+ }
135199 return NULL ;
136200}
137201
@@ -160,6 +224,7 @@ ble_eatt_prepare_rx_sdu(struct ble_l2cap_chan *chan)
160224static void
161225ble_eatt_wakeup_cb (struct ble_npl_event * ev )
162226{
227+ int i ;
163228 struct ble_eatt * eatt ;
164229 struct os_mbuf * txom ;
165230 struct os_mbuf_pkthdr * omp ;
@@ -173,14 +238,24 @@ ble_eatt_wakeup_cb(struct ble_npl_event *ev)
173238 STAILQ_REMOVE_HEAD (& eatt -> eatt_tx_q , omp_next );
174239
175240 txom = OS_MBUF_PKTHDR_TO_MBUF (omp );
176- ble_l2cap_get_chan_info (eatt -> chan , & info );
241+
242+ /* Look for the already established channel.
243+ * Send necessary data, then break.
244+ */
245+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
246+ if (eatt -> chan [i ] != NULL ) {
247+ ble_l2cap_get_chan_info (eatt -> chan [i ], & info );
177248 ble_eatt_tx (eatt -> conn_handle , info .dcid , txom );
249+ break ;
250+ }
251+ }
178252 }
179253}
180254
181255static struct ble_eatt *
182256ble_eatt_alloc (void )
183257{
258+ int i ;
184259 struct ble_eatt * eatt ;
185260
186261 eatt = os_memblock_get (& ble_eatt_conn_pool );
@@ -192,7 +267,9 @@ ble_eatt_alloc(void)
192267 SLIST_INSERT_HEAD (& g_ble_eatt_list , eatt , next );
193268
194269 eatt -> conn_handle = BLE_HS_CONN_HANDLE_NONE ;
195- eatt -> chan = NULL ;
270+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
271+ eatt -> chan [i ] = NULL ;
272+ }
196273 eatt -> client_op = 0 ;
197274
198275 STAILQ_INIT (& eatt -> eatt_tx_q );
@@ -221,7 +298,9 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
221298{
222299 struct ble_eatt * eatt = arg ;
223300 struct ble_gap_conn_desc desc ;
301+ struct ble_l2cap_chan * channel ;
224302 uint8_t opcode ;
303+ int chan_idx ;
225304 int rc ;
226305
227306 switch (event -> type ) {
@@ -231,7 +310,15 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
231310 ble_eatt_free (eatt );
232311 return 0 ;
233312 }
234- eatt -> chan = event -> connect .chan ;
313+ chan_idx = ble_eatt_free_channel_idx (eatt );
314+ if (chan_idx > 0 ) {
315+ eatt -> chan [chan_idx ] = event -> connect .chan ;
316+ } else {
317+ BLE_EATT_LOG_ERROR ("eatt: Connect event: No free channels\n" );
318+ ble_eatt_free (eatt );
319+ return 0 ;
320+ }
321+
235322 break ;
236323 case BLE_L2CAP_EVENT_COC_DISCONNECTED :
237324 BLE_EATT_LOG_DEBUG ("eatt: Disconnected \n" );
@@ -266,7 +353,11 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
266353 ble_npl_eventq_put (ble_hs_evq_get (), & eatt -> wakeup_ev );
267354 break ;
268355 case BLE_L2CAP_EVENT_COC_DATA_RECEIVED :
269- assert (eatt -> chan == event -> receive .chan );
356+ channel = ble_eatt_find_chan (eatt , event -> receive .chan );
357+ if (channel == NULL ) {
358+ BLE_EATT_LOG_ERROR ("eatt: receive: Invalid channel\n" );
359+ ble_eatt_free (eatt );
360+ }
270361 opcode = event -> receive .sdu_rx -> om_data [0 ];
271362 if (ble_eatt_supported_rsp (opcode )) {
272363 ble_npl_eventq_put (ble_hs_evq_get (), & eatt -> wakeup_ev );
@@ -279,7 +370,7 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
279370 * • The Signed Write Without Response sub-procedure shall only be
280371 * supported on the LE Fixed Channel Unenhanced ATT bearer.
281372 */
282- ble_l2cap_disconnect (eatt -> chan );
373+ ble_l2cap_disconnect (channel );
283374 return BLE_HS_EREJECT ;
284375 }
285376
@@ -293,11 +384,12 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
293384 * encryption.
294385 */
295386 if (!desc .sec_state .encrypted ) {
296- ble_l2cap_disconnect (eatt -> chan );
387+ ble_l2cap_disconnect (channel );
297388 return BLE_HS_EREJECT ;
298389 }
299390
300- ble_eatt_att_rx_cb (event -> receive .conn_handle , eatt -> chan -> scid , & event -> receive .sdu_rx );
391+ ble_eatt_att_rx_cb (event -> receive .conn_handle , channel -> scid ,
392+ & event -> receive .sdu_rx );
301393 if (event -> receive .sdu_rx ) {
302394 os_mbuf_free_chain (event -> receive .sdu_rx );
303395 event -> receive .sdu_rx = NULL ;
@@ -306,7 +398,7 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
306398 /* Receiving L2CAP data is no longer possible, terminate connection */
307399 rc = ble_eatt_prepare_rx_sdu (event -> receive .chan );
308400 if (rc ) {
309- ble_l2cap_disconnect (eatt -> chan );
401+ ble_l2cap_disconnect (channel );
310402 return BLE_HS_ENOMEM ;
311403 }
312404 break ;
@@ -336,9 +428,10 @@ ble_eatt_setup_cb(struct ble_npl_event *ev)
336428
337429 BLE_EATT_LOG_DEBUG ("eatt: connecting eatt on conn_handle 0x%04x\n" , eatt -> conn_handle );
338430
339- 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 );
431+ rc = ble_l2cap_enhanced_connect (
432+ eatt -> conn_handle , BLE_EATT_PSM , MYNEWT_VAL (BLE_EATT_MTU ),
433+ eatt -> channels_to_connect , & om , ble_eatt_l2cap_event_fn , eatt );
434+
342435 if (rc ) {
343436 BLE_EATT_LOG_ERROR ("eatt: Failed to connect EATT on conn_handle 0x%04x (status=%d)\n" ,
344437 eatt -> conn_handle , rc );
@@ -441,6 +534,7 @@ ble_eatt_gap_event(struct ble_gap_event *event, void *arg)
441534uint16_t
442535ble_eatt_get_available_chan_cid (uint16_t conn_handle , uint8_t op )
443536{
537+ int i ;
444538 struct ble_eatt * eatt ;
445539
446540 eatt = ble_eatt_find_not_busy (conn_handle );
@@ -450,7 +544,13 @@ ble_eatt_get_available_chan_cid(uint16_t conn_handle, uint8_t op)
450544
451545 eatt -> client_op = op ;
452546
453- return eatt -> chan -> scid ;
547+ for (i = 0 ; i < MYNEWT_VAL (BLE_EATT_CHAN_PER_CONN ); i ++ ) {
548+ if (eatt -> chan [i ] != NULL ) {
549+ return eatt -> chan [i ]-> scid ;
550+ }
551+ }
552+
553+ return BLE_L2CAP_CID_ATT ;
454554}
455555
456556void
@@ -472,17 +572,25 @@ int
472572ble_eatt_tx (uint16_t conn_handle , uint16_t cid , struct os_mbuf * txom )
473573{
474574 struct ble_eatt * eatt ;
575+ static struct ble_l2cap_chan * channel ;
475576 int rc ;
476577
477578 BLE_EATT_LOG_DEBUG ("eatt: %s, size %d " , __func__ , OS_MBUF_PKTLEN (txom ));
478579 eatt = ble_eatt_find (conn_handle , cid );
479- if (!eatt || !eatt -> chan ) {
580+ if (!eatt ) {
581+ BLE_EATT_LOG_ERROR ("Eatt not available" );
582+ rc = BLE_HS_ENOENT ;
583+ goto error ;
584+ }
585+
586+ channel = ble_eatt_channel_find_by_cid (eatt , cid );
587+ if (!channel ) {
480588 BLE_EATT_LOG_ERROR ("Eatt not available" );
481589 rc = BLE_HS_ENOENT ;
482590 goto error ;
483591 }
484592
485- rc = ble_l2cap_send (eatt -> chan , txom );
593+ rc = ble_l2cap_send (channel , txom );
486594 if (rc == 0 ) {
487595 goto done ;
488596 }
0 commit comments