patch to make enabling 64B L2 cache optional (tueidj)
[libogc.git] / lwbt / l2cap.c
blob573037976e494f34ca4e2571e566847520fcbeb2
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <malloc.h>
5 #include <ogcsys.h>
6 #include <gccore.h>
8 #include "hci.h"
9 #include "l2cap.h"
10 #include "btmemb.h"
11 #include "btpbuf.h"
13 /* Next Identifier to be sent */
14 u8_t sigid_nxt;
16 /* The L2CAP PCB lists. */
17 struct l2cap_pcb_listen *l2cap_listen_pcbs = NULL; /* List of all L2CAP PCBs in CLOSED state
18 but awaiting an incoming conn req */
19 struct l2cap_pcb *l2cap_active_pcbs; /* List of all L2CAP PCBs that are in a
20 state in which they accept or send
21 data */
22 struct l2cap_pcb *l2cap_tmp_pcb = NULL;
24 /* Temp signal */
25 struct l2cap_sig *l2cap_tmp_sig = NULL;
27 /* Global variable involved in input processing of l2cap data segements */
28 struct l2cap_seg *l2cap_insegs = NULL;
29 struct l2cap_seg *l2cap_tmp_inseg = NULL;
31 /* Global Baseband disconnect callback. */
32 static void (*l2cap_disconnect_bb_cb)(struct bd_addr *bdaddr,u8_t reason) = NULL;
34 /* Forward declarations */
35 static u16_t l2cap_cid_alloc(void);
37 MEMB(l2cap_pcbs,sizeof(struct l2cap_pcb),MEMB_NUM_L2CAP_PCB);
38 MEMB(l2cap_listenpcbs,sizeof(struct l2cap_pcb_listen),MEMB_NUM_L2CAP_PCB_LISTEN);
39 MEMB(l2cap_sigs,sizeof(struct l2cap_sig),MEMB_NUM_L2CAP_SIG);
40 MEMB(l2cap_segs,sizeof(struct l2cap_seg),MEMB_NUM_L2CAP_SEG);
42 /*-----------------------------------------------------------------------------------*/
43 /*
44 * l2cap_init():
46 * Initializes the L2CAP layer.
48 /*-----------------------------------------------------------------------------------*/
49 void l2cap_init()
51 btmemb_init(&l2cap_pcbs);
52 btmemb_init(&l2cap_listenpcbs);
53 btmemb_init(&l2cap_sigs);
54 btmemb_init(&l2cap_segs);
56 /* Clear globals */
57 l2cap_listen_pcbs = NULL;
58 l2cap_active_pcbs = NULL;
59 l2cap_tmp_pcb = NULL;
60 l2cap_tmp_sig = NULL;
61 l2cap_insegs = NULL;
62 l2cap_tmp_inseg = NULL;
63 l2cap_disconnect_bb_cb = NULL;
65 /* Initialize the signal identifier (0x00 shall never be used) */
66 sigid_nxt = 0x00;
69 /*-----------------------------------------------------------------------------------*/
71 * l2cap_tmr():
73 * Called every 1s and implements the retransmission timer that
74 * removes a channel if it has been waiting for a request enough
75 * time. It also includes a configuration timer.
77 /*-----------------------------------------------------------------------------------*/
78 void l2cap_tmr()
80 struct l2cap_sig *sig;
81 struct l2cap_pcb *pcb;
82 err_t ret;
84 /* Step through all of the active pcbs */
85 for(pcb = l2cap_active_pcbs; pcb != NULL; pcb = pcb->next) {
86 /* Step through any unresponded signals */
87 for(sig = pcb->unrsp_sigs; sig != NULL; sig = sig->next) {
88 /* Check if channel is not reliable */
89 if(pcb->cfg.outflushto < 0xFFFF) {
90 /* Check if rtx is active. Otherwise ertx is active */
91 if(sig->rtx > 0) {
92 /* Adjust rtx timer */
93 --sig->rtx;
94 /* Check if rtx has expired */
95 if(sig->rtx == 0) {
96 if(sig->nrtx == 0) {
97 /* Move pcb to closed state */
98 pcb->state = L2CAP_CLOSED;
99 /* Indicate disconnect to upper layer */
100 LOG("l2cap_tmr: Max number of retransmissions (rtx) has expired\n");
101 L2CA_ACTION_DISCONN_IND(pcb,ERR_OK,ret);
102 } else {
103 --sig->nrtx;
104 /* Indicate timeout to upper layer */
105 L2CA_ACTION_TO_IND(pcb,ERR_OK,ret);
106 /* Retransmitt signal w timeout doubled */
107 sig->rtx += sig->rtx;
108 ret = l2cap_rexmit_signal(pcb, sig);
110 } /* if */
111 } else {
112 /* Adjust ertx timer */
113 --sig->ertx;
114 /* Check if ertx has expired */
115 if(sig->ertx == 0) {
116 if(sig->nrtx == 0) {
117 /* Move pcb to closed state */
118 pcb->state = L2CAP_CLOSED;
119 /* Indicate disconnect to upper layer */
120 LOG("l2cap_tmr: Max number of retransmissions (ertx) has expired\n");
121 L2CA_ACTION_DISCONN_IND(pcb,ERR_OK,ret);
122 } else {
123 --sig->nrtx;
124 /* Indicate timeout to upper layer */
125 L2CA_ACTION_TO_IND(pcb,ERR_OK,ret);
126 /* Disable ertx, activate rtx and retransmitt signal */
127 sig->ertx = 0;
128 sig->rtx = L2CAP_RTX;
129 ret = l2cap_rexmit_signal(pcb, sig);
131 } /* if */
132 } /* else */
133 } /* if */
134 } /* for */
136 /* Check configuration timer */
137 if(pcb->state == L2CAP_CONFIG) {
138 /* Check if configuration timer is active */
139 if(pcb->cfg.cfgto > 0) {
140 --pcb->cfg.cfgto;
141 //LOG("l2cap_tmr: Configuration timer = %d\n", pcb->cfg.cfgto);
142 /* Check if config timer has expired */
143 if(pcb->cfg.cfgto == 0) {
144 /* Connection attempt failed. Disconnect */
145 l2ca_disconnect_req(pcb, NULL);
146 /* Notify the application that the connection attempt failed */
147 if(pcb->cfg.l2capcfg & L2CAP_CFG_IR) {
148 L2CA_ACTION_CONN_CFM(pcb, L2CAP_CONN_CFG_TO, 0x0000, ret);
149 } else {
150 L2CA_ACTION_CONN_IND(pcb, ERR_OK, ret);
152 pcb->cfg.cfgto = L2CAP_CFG_TO; /* Reset timer */
156 } /* for */
159 /*-----------------------------------------------------------------------------------*/
161 * l2cap_write():
163 * Output L2CAP data to the lower layers. Segments the packet in to PDUs.
165 /*-----------------------------------------------------------------------------------*/
166 err_t l2cap_write(struct bd_addr *bdaddr, struct pbuf *p, u16_t len)
168 u8_t pb = L2CAP_ACL_START;
169 u16_t maxsize;
170 u16_t outsize;
171 err_t ret = ERR_OK;
172 struct pbuf *q;
173 u16_t i = 0;
175 /*u16_t i;
176 struct pbuf *q;
177 for(q = p; q != NULL; q = q->next) {
178 for(i = 0; i < q->len; ++i) {
179 LWIP_DEBUGF(L2CAP_DEBUG, ("l2cap_write: 0x%x\n", ((u8_t *)q->payload)[i]));
181 LWIP_DEBUGF(L2CAP_DEBUG, ("l2cap_write: *\n"));
185 maxsize = lp_pdu_maxsize();
186 q = p;
188 while(len && ret == ERR_OK) {
189 //LOG("l2cap_write: len %d maxsize %d p->len %d\n", len, maxsize, p->len);
190 if(len > maxsize) {
191 ret = lp_acl_write(bdaddr, q, maxsize, pb);
192 len -= maxsize;
193 outsize = maxsize;
194 //LOG("l2cap_write: Outsize before %d\n", outsize);
195 while(q->len < outsize) {
196 outsize -= q->len;
197 q = q->next;
199 //LOG("l2cap_write: Outsize after %d\n", outsize);
200 if(outsize) {
201 btpbuf_header(q, -outsize);
202 i += outsize;
204 pb = L2CAP_ACL_CONT;
205 LOG("l2cap_write: FRAG\n");
206 } else {
207 ret = lp_acl_write(bdaddr, q, len, pb);
208 len = 0;
211 btpbuf_header(q, i);
212 LOG("l2cap_write: DONE\n");
213 return ret;
216 /*-----------------------------------------------------------------------------------*/
218 * l2cap_process_sig():
220 * Parses the received message handles it.
222 /*-----------------------------------------------------------------------------------*/
223 void l2cap_process_sig(struct pbuf *q, struct l2cap_hdr *l2caphdr, struct bd_addr *bdaddr)
225 struct l2cap_sig_hdr *sighdr;
226 struct l2cap_sig *sig = NULL;
227 struct l2cap_pcb *pcb = NULL;
228 struct l2cap_pcb_listen *lpcb;
229 struct l2cap_cfgopt_hdr *opthdr;
230 u16_t result, status, flags, psm, dcid, scid;
231 u16_t len;
232 u16_t siglen;
233 struct pbuf *p, *r = NULL, *s = NULL, *data;
234 err_t ret;
235 u8_t i;
236 u16_t rspstate = L2CAP_CFG_SUCCESS;
238 if(q->len != q->tot_len) {
239 LOG("l2cap_process_sig: Fragmented packet received. Reassemble into one buffer\n");
240 if((p = btpbuf_alloc(PBUF_RAW, q->tot_len, PBUF_RAM)) != NULL) {
241 i = 0;
242 for(r = q; r != NULL; r = r->next) {
243 memcpy(((u8_t *)p->payload) + i, r->payload, r->len);
244 i += r->len;
246 } else {
247 ERROR("l2cap_process_sig: Could not allocate buffer for fragmented packet\n");
248 return;
250 } else {
251 p = q;
254 len = l2caphdr->len;
256 while(len > 0) {
257 /* Set up signal header */
258 sighdr = p->payload;
259 btpbuf_header(p, -L2CAP_SIGHDR_LEN);
261 /* Check if this is a response/reject signal, and if so, find the matching request */
262 if(sighdr->code % 2) { /* if odd this is a resp/rej signal */
263 LOG("l2cap_process_sig: Response/reject signal received id = %d code = %d\n", sighdr->id, sighdr->code);
264 for(pcb = l2cap_active_pcbs; pcb != NULL; pcb = pcb->next) {
265 for(sig = pcb->unrsp_sigs; sig != NULL; sig = sig->next) {
266 if(sig->sigid == sighdr->id) {
267 break; /* found */
270 if(sig != NULL) {
271 break;
274 } else {
275 LOG("l2cap_process_sig: Request signal received id = %d code = %d\n", sighdr->id, sighdr->code);
278 /* Reject packet if length exceeds MTU */
279 if(l2caphdr->len > L2CAP_MTU) {
280 /* Alloc size of reason in cmd rej + MTU */
281 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_CMD_REJ_SIZE+2, PBUF_RAM)) != NULL) {
282 ((u16_t *)data->payload)[0] = htole16(L2CAP_MTU_EXCEEDED);
283 ((u16_t *)data->payload)[1] = htole16(L2CAP_MTU);
285 l2cap_signal(NULL, L2CAP_CMD_REJ, sighdr->id, bdaddr, data);
287 break;
290 switch(sighdr->code) {
291 case L2CAP_CMD_REJ:
292 /* Remove signal from unresponded list and deallocate it */
293 L2CAP_SIG_RMV(&(pcb->unrsp_sigs), sig);
294 btpbuf_free(sig->p);
295 btmemb_free(&l2cap_sigs, sig);
296 LOG("l2cap_process_sig: Our command was rejected so we disconnect\n");
297 l2ca_disconnect_req(pcb, NULL);
298 break;
299 case L2CAP_CONN_REQ:
300 psm = le16toh(((u16_t *)p->payload)[0]);
301 /* Search for a listening pcb */
302 for(lpcb = l2cap_listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
303 if(bd_addr_cmp(&(lpcb->bdaddr),bdaddr) && lpcb->psm == psm) {
304 /* Found a listening pcb with the correct PSM & BD Address */
305 break;
309 //printf("l2cap_process_sig(L2CAP_CONN_REQ): psm = %04x, lpcb = %p\n",psm,lpcb);
310 /* If no matching pcb was found, send a connection rsp neg (PSM) */
311 if(lpcb == NULL) {
312 /* Alloc size of data in conn rsp signal */
313 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_CONN_RSP_SIZE, PBUF_RAM)) != NULL) {
314 ((u16_t *)data->payload)[0] = htole16(L2CAP_CONN_REF_PSM);
315 ((u16_t *)data->payload)[1] = 0; /* No further info available */
316 ret = l2cap_signal(NULL, L2CAP_CONN_RSP, sighdr->id, bdaddr, data);
318 } else {
319 /* Initiate a new active pcb */
320 pcb = l2cap_new();
321 if(pcb == NULL) {
322 LOG("l2cap_process_sig: could not allocate PCB\n");
323 /* Send a connection rsp neg (no resources available) and alloc size of data in conn rsp
324 signal */
325 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_CONN_RSP_SIZE, PBUF_RAM)) != NULL) {
326 ((u16_t *)data->payload)[0] = htole16(L2CAP_CONN_REF_RES);
327 ((u16_t *)data->payload)[1] = 0; /* No further info available */
328 ret = l2cap_signal(NULL, L2CAP_CONN_RSP, sighdr->id, bdaddr, data);
331 bd_addr_set(&(pcb->remote_bdaddr),bdaddr);
333 pcb->scid = l2cap_cid_alloc();
334 pcb->dcid = le16toh(((u16_t *)p->payload)[1]);
335 pcb->psm = psm;
336 pcb->callback_arg = lpcb->callback_arg;
337 pcb->l2ca_connect_ind = lpcb->l2ca_connect_ind;
339 pcb->state = L2CAP_CONFIG;
340 L2CAP_REG(&l2cap_active_pcbs, pcb);
342 LOG("l2cap_process_sig: A connection request was received. Send a response\n");
343 data = btpbuf_alloc(PBUF_RAW, L2CAP_CONN_RSP_SIZE, PBUF_RAM);
344 if(data == NULL) {
345 ERROR("l2cap_connect_rsp: Could not allocate memory for pbuf\n");
346 break;
348 ((u16_t *)data->payload)[0] = htole16(pcb->scid);
349 ((u16_t *)data->payload)[1] = htole16(pcb->dcid);
350 ((u16_t *)data->payload)[2] = htole16(L2CAP_CONN_SUCCESS);
351 ((u16_t *)data->payload)[3] = 0x0000; /* No further information available */
353 /* Send the response */
354 ret = l2cap_signal(pcb, L2CAP_CONN_RSP, sighdr->id, &(pcb->remote_bdaddr), data);
356 break;
357 case L2CAP_CONN_RSP:
358 if(pcb == NULL) {
359 /* A response without a matching request is silently discarded */
360 break;
362 LOG("l2cap_process_sig: conn rsp, active pcb->state == W4_L2CAP_CONNECT_RSP\n");
363 result = le16toh(((u16_t *)p->payload)[2]);
364 status = le16toh(((u16_t *)p->payload)[3]);
365 switch(result) {
366 case L2CAP_CONN_SUCCESS:
367 LOG("l2cap_process_sig: Conn_rsp_sucess, status %d\n", status);
368 LOG("l2cap_process_sig: conn rsp success, pcb->scid == %04x\n", ((u16_t *)p->payload)[1]);
370 /* Set destination connection id */
371 pcb->dcid = le16toh(((u16_t *)p->payload)[0]);
373 /* Remove signal from unresponded list and deallocate it */
374 L2CAP_SIG_RMV(&(pcb->unrsp_sigs), sig);
375 btpbuf_free(sig->p);
376 btmemb_free(&l2cap_sigs, sig);
378 /* Configure connection */
379 pcb->state = L2CAP_CONFIG;
381 /* If initiator send a configuration request */
382 if(pcb->cfg.l2capcfg & L2CAP_CFG_IR) {
383 l2ca_config_req(pcb);
384 pcb->cfg.l2capcfg |= L2CAP_CFG_OUT_REQ;
386 break;
387 case L2CAP_CONN_PND:
388 LOG("l2cap_process_sig: Conn_rsp_pnd, status %d\n", status);
390 /* Disable rtx and enable ertx */
391 sig->rtx = 0;
392 sig->ertx = L2CAP_ERTX;
393 break;
394 default:
395 LOG("l2cap_process_sig: Conn_rsp_neg, result %d\n", result);
396 /* Remove signal from unresponded list and deallocate it */
397 L2CAP_SIG_RMV(&(pcb->unrsp_sigs), sig);
398 btpbuf_free(sig->p);
399 btmemb_free(&l2cap_sigs, sig);
401 L2CA_ACTION_CONN_CFM(pcb,result,status,ret);
402 break;
404 break;
405 case L2CAP_CFG_REQ:
406 siglen = le16toh(sighdr->len);
407 dcid = le16toh(((u16_t *)p->payload)[0]);
408 flags = le16toh(((u16_t *)p->payload)[1]);
409 siglen -= 4;
410 btpbuf_header(p, -4);
413 LOG("l2cap_process_sig: Congfiguration request, flags = %d\n", flags);
415 /* Find PCB with matching cid */
416 for(pcb = l2cap_active_pcbs; pcb != NULL; pcb = pcb->next) {
417 //LOG("l2cap_process_sig: dcid = 0x%x, pcb->scid = 0x%x, pcb->dcid = 0x%x\n\n", dcid, pcb->scid, pcb->dcid);
418 if(pcb->scid == dcid) {
419 /* Matching cid found */
420 break;
423 /* If no matching cid was found, send a cmd reject (Invalid cid) */
424 if(pcb == NULL) {
425 LOG("l2cap_process_sig: Cfg req: no matching cid was found\n");
426 /* Alloc size of reason in cmd rej + data (dcid + scid) */
427 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_CMD_REJ_SIZE+4, PBUF_RAM)) != NULL) {
428 ((u16_t *)data->payload)[0] = htole16(L2CAP_INVALID_CID);
429 ((u16_t *)data->payload)[1] = htole16(dcid); /* Requested local cid */
430 ((u16_t *)data->payload)[2] = htole16(L2CAP_NULL_CID); /* Remote cid not known */
432 ret = l2cap_signal(NULL, L2CAP_CMD_REJ, sighdr->id, bdaddr, data);
434 } else { /* Handle config request */
435 LOG("l2cap_process_sig: Handle configuration request\n");
436 pcb->ursp_id = sighdr->id; /* Set id of request to respond to */
438 /* Parse options and add to pcb */
439 while(siglen > 0) {
440 LOG("l2cap_process_sig: Siglen = %d\n", siglen);
441 opthdr = p->payload;
442 /* Check if type of action bit indicates a non-hint. Hints are ignored */
443 LOG("l2cap_process_sig: Type of action bit = %d\n", L2CAP_OPTH_TOA(opthdr));
444 if(L2CAP_OPTH_TOA(opthdr) == 0) {
445 LOG("l2cap_process_sig: Type = %d\n", L2CAP_OPTH_TYPE(opthdr));
446 LOG("l2cap_process_sig: Length = %d\n", opthdr->len);
447 switch(L2CAP_OPTH_TYPE(opthdr)) {
448 case L2CAP_CFG_MTU:
449 LOG("l2cap_process_sig: Out MTU = %d\n", le16toh(((u16_t *)p->payload)[1]));
450 pcb->cfg.outmtu = le16toh(((u16_t *)p->payload)[1]);
451 break;
452 case L2CAP_FLUSHTO:
453 LOG("l2cap_process_sig: In flush timeout = %d\n", ((u16_t *)p->payload)[1]);
454 pcb->cfg.influshto = le16toh(((u16_t *)p->payload)[1]);
455 break;
456 case L2CAP_QOS:
457 /* If service type is Best Effort or No Traffic the remainder fields will be ignored */
458 if(((u8_t *)p->payload)[3] == L2CAP_QOS_GUARANTEED) {
459 LOG("l2cap_process_sig: This implementation does not support the guaranteed QOS service type");
460 if(rspstate == L2CAP_CFG_SUCCESS) {
461 rspstate = L2CAP_CFG_UNACCEPT;
462 if(pcb->cfg.opt != NULL) {
463 btpbuf_free(pcb->cfg.opt);
464 pcb->cfg.opt = NULL;
467 s = btpbuf_alloc(PBUF_RAW, L2CAP_CFGOPTHDR_LEN + opthdr->len, PBUF_RAM);
468 memcpy((u8_t *)s->payload, (u8_t *)p->payload, L2CAP_CFGOPTHDR_LEN + opthdr->len);
469 if(pcb->cfg.opt == NULL) {
470 pcb->cfg.opt = s;
471 } else {
472 btpbuf_chain(pcb->cfg.opt, s);
473 btpbuf_free(s);
476 break;
477 default:
478 if(rspstate != L2CAP_CFG_REJ) {
479 /* Unknown option. Add to unknown option type buffer */
480 if(rspstate != L2CAP_CFG_UNKNOWN) {
481 rspstate = L2CAP_CFG_UNKNOWN;
482 if(pcb->cfg.opt != NULL) {
483 btpbuf_free(pcb->cfg.opt);
484 pcb->cfg.opt = NULL;
487 s = btpbuf_alloc(PBUF_RAW, L2CAP_CFGOPTHDR_LEN + opthdr->len, PBUF_RAM);
488 memcpy((u8_t *)s->payload, (u8_t *)p->payload, L2CAP_CFGOPTHDR_LEN + opthdr->len);
489 if(pcb->cfg.opt == NULL) {
490 pcb->cfg.opt = s;
491 } else {
492 btpbuf_chain(pcb->cfg.opt, s);
493 btpbuf_free(s);
496 break;
497 } /* switch */
498 } /* if(L2CAP_OPTH_TOA(opthdr) == 0) */
499 btpbuf_header(p, -(L2CAP_CFGOPTHDR_LEN + opthdr->len));
500 siglen -= L2CAP_CFGOPTHDR_LEN + opthdr->len;
501 } /* while */
503 /* If continuation flag is set we don't send the final response just yet */
504 if((flags & 0x0001) == 1) {
505 /* Send success result with no options until the full request has been received */
506 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_CFG_RSP_SIZE, PBUF_RAM)) == NULL) {
507 ERROR("l2cap_process_sig: Could not allocate memory for pbuf\n");
508 break;
510 ((u16_t *)data->payload)[0] = htole16(pcb->dcid);
511 ((u16_t *)data->payload)[1] = 0;
512 ((u16_t *)data->payload)[2] = htole16(L2CAP_CFG_SUCCESS);
513 ret = l2cap_signal(pcb, L2CAP_CFG_RSP, pcb->ursp_id, &(pcb->remote_bdaddr), data);
514 break;
517 /* Send a configure request for outgoing link if it hasnt been configured */
518 if(!(pcb->cfg.l2capcfg & L2CAP_CFG_IR) && !(pcb->cfg.l2capcfg & L2CAP_CFG_OUT_REQ)) {
519 l2ca_config_req(pcb);
520 pcb->cfg.l2capcfg |= L2CAP_CFG_OUT_REQ;
523 /* Send response to configuration request */
524 LOG("l2cap_process_sig: Send response to configuration request\n");
525 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_CFG_RSP_SIZE, PBUF_RAM)) != NULL) {
526 ((u16_t *)data->payload)[0] = htole16(pcb->dcid);
527 ((u16_t *)data->payload)[1] = 0; /* Flags (No continuation) */
528 ((u16_t *)data->payload)[2] = htole16(rspstate); /* Result */
529 if(pcb->cfg.opt != NULL) {
530 LOG("l2cap_process_sig: pcb->cfg.opt->len = %d\n", pcb->cfg.opt->len);
531 btpbuf_chain(data, pcb->cfg.opt); /* Add option type buffer to data buffer */
532 btpbuf_free(pcb->cfg.opt);
533 pcb->cfg.opt = NULL;
535 ret = l2cap_signal(pcb, L2CAP_CFG_RSP, pcb->ursp_id, &(pcb->remote_bdaddr), data);
538 if(rspstate == L2CAP_CFG_SUCCESS) {
539 pcb->cfg.l2capcfg |= L2CAP_CFG_OUT_SUCCESS;
540 /* L2CAP connection established if a successful configuration response has been sent */
541 if(pcb->cfg.l2capcfg & L2CAP_CFG_IN_SUCCESS) {
542 /* IPCP connection established, notify upper layer that connection is open */
543 pcb->state = L2CAP_OPEN;
544 if(pcb->cfg.l2capcfg & L2CAP_CFG_IR) {
545 L2CA_ACTION_CONN_CFM(pcb, L2CAP_CONN_SUCCESS, 0x0000, ret);
546 } else {
547 L2CA_ACTION_CONN_IND(pcb, ERR_OK, ret);
551 } /* else */
552 break;
553 case L2CAP_CFG_RSP:
554 if(pcb == NULL) {
555 /* A response without a matching request is silently discarded */
556 LOG("l2cap_process_sig: discarded response without matching request\n");
557 break;
560 /* Remove signal from unresponded list and deallocate it */
561 L2CAP_SIG_RMV(&(pcb->unrsp_sigs), sig);
562 btpbuf_free(sig->p);
563 btmemb_free(&l2cap_sigs, sig);
565 siglen = le16toh(sighdr->len);
566 scid = le16toh(((u16_t *)p->payload)[0]);
567 flags = le16toh(((u16_t *)p->payload)[1]);
568 result = le16toh(((u16_t *)p->payload)[2]);
569 siglen -= 6;
570 btpbuf_header(p, -6);
572 LOG("l2cap_process_sig: Outgoing configuration result == %d continuation flag == %d\n", result, flags);
574 /* Handle config request */
575 switch(result) {
576 case L2CAP_CFG_SUCCESS:
577 LOG("l2cap_process_sig: Successfull outgoing configuration\n");
578 pcb->cfg.l2capcfg |= L2CAP_CFG_IN_SUCCESS; /* Local side of the connection
579 has been configured for outgoing data */
580 pcb->cfg.cfgto = L2CAP_CFG_TO; /* Reset configuration timeout */
582 if(pcb->cfg.outflushto != L2CAP_CFG_DEFAULT_OUTFLUSHTO) {
583 lp_write_flush_timeout(&pcb->remote_bdaddr, pcb->cfg.outflushto);
586 /* L2CAP connection established if a successful configuration response has been sent */
587 if(pcb->cfg.l2capcfg & L2CAP_CFG_OUT_SUCCESS) {
588 pcb->state = L2CAP_OPEN;
589 if(pcb->cfg.l2capcfg & L2CAP_CFG_IR) {
590 L2CA_ACTION_CONN_CFM(pcb, L2CAP_CONN_SUCCESS, 0x0000, ret);
591 } else {
592 L2CA_ACTION_CONN_IND(pcb, ERR_OK, ret);
595 break;
596 case L2CAP_CFG_UNACCEPT:
597 /* Parse and add options to pcb */
598 while(siglen > 0) {
599 opthdr = p->payload;
600 /* Check if type of action bit indicates a non-hint. Hints are ignored */
601 if(L2CAP_OPTH_TOA(opthdr) == 0) {
602 switch(L2CAP_OPTH_TYPE(opthdr)) {
603 case L2CAP_CFG_MTU:
604 if(L2CAP_MTU > le16toh(((u16_t *)p->payload)[1])) {
605 pcb->cfg.outmtu = le16toh(((u16_t *)p->payload)[1]);
606 } else {
607 ERROR("l2cap_process_sig: Configuration of MTU failed\n");
608 l2ca_disconnect_req(pcb, NULL);
609 return;
611 break;
612 case L2CAP_FLUSHTO:
613 pcb->cfg.influshto = le16toh(((u16_t *)p->payload)[1]);
614 break;
615 case L2CAP_QOS:
616 /* If service type Best Effort is not accepted we will close the connection */
617 if(((u8_t *)p->payload)[3] != L2CAP_QOS_BEST_EFFORT) {
618 ERROR("l2cap_process_sig: Unsupported service type\n");
619 l2ca_disconnect_req(pcb, NULL);
620 return;
622 break;
623 default:
624 /* Should not happen, skip option */
625 break;
626 } /* switch */
627 } /* if(L2CAP_OPTH_TOA(opthdr) == 0) */
628 btpbuf_header(p, -(L2CAP_CFGOPTHDR_LEN + opthdr->len));
629 siglen -= L2CAP_CFGOPTHDR_LEN + opthdr->len;
630 } /* while */
632 /* Send out a new configuration request if the continuation flag isn't set */
633 if((flags & 0x0001) == 0) {
634 l2ca_config_req(pcb);
636 break;
637 case L2CAP_CFG_REJ:
638 /* Fallthrough */
639 case L2CAP_CFG_UNKNOWN:
640 /* Fallthrough */
641 default:
642 if((flags & 0x0001) == 0) {
643 LOG("l2cap_process_sig: Configuration failed\n");
644 l2ca_disconnect_req(pcb, NULL);
645 return;
647 break;
648 } /* switch(result) */
650 /* If continuation flag is set we must send a NULL configuration request */
651 if((flags & 0x0001) == 1) {
652 LOG("l2cap_process_sig: Continuation flag is set. Send empty (default) config request signal\n");
653 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_CFG_REQ_SIZE, PBUF_RAM)) == NULL) {
654 ERROR("l2cap_process_sig: Could not allocate memory for pbuf\n");
655 return;
657 /* Assemble config request packet */
658 ((u16_t *)data->payload)[0] = htole16(pcb->scid);
659 ((u16_t *)data->payload)[2] = 0;
660 l2cap_signal(pcb, L2CAP_CFG_REQ, 0, &(pcb->remote_bdaddr), data);
662 break;
663 case L2CAP_DISCONN_REQ:
664 siglen = le16toh(sighdr->len);
665 dcid = le16toh(((u16_t *)p->payload)[0]);
666 siglen = siglen - 2;
667 flags = le16toh(((u16_t *)p->payload)[1]);
668 siglen = siglen - 2;
669 btpbuf_header(p, -4);
671 /* Find PCB with matching cid */
672 for(pcb = l2cap_active_pcbs; pcb != NULL; pcb = pcb->next) {
673 if(pcb->scid == dcid) {
674 /* Matching cid found */
675 break;
678 /* If no matching cid was found, send a cmd reject (Invalid cid) */
679 if(pcb == NULL) {
680 /* Alloc size of reason in cmd rej + data (dcid + scid) */
681 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_CMD_REJ_SIZE+4, PBUF_RAM)) != NULL) {
682 ((u16_t *)data->payload)[0] = htole16(L2CAP_INVALID_CID);
683 ((u16_t *)data->payload)[1] = htole16(dcid); /* Requested local cid */
684 ((u16_t *)data->payload)[2] = htole16(L2CAP_NULL_CID); /* Remote cid not known */
686 ret = l2cap_signal(NULL, L2CAP_CMD_REJ, sighdr->id, bdaddr, data);
688 } else { /* Handle disconnection request */
689 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_DISCONN_RSP_SIZE, PBUF_RAM)) != NULL) {
690 ((u16_t *)data->payload)[0] = htole16(pcb->scid);
691 ((u16_t *)data->payload)[1] = htole16(pcb->dcid);
692 ret = l2cap_signal(pcb, L2CAP_DISCONN_RSP, sighdr->id, &(pcb->remote_bdaddr), data);
694 /* Give upper layer indication */
695 pcb->state = L2CAP_CLOSED;
696 LOG("l2cap_process_sig: Disconnection request\n");
697 L2CA_ACTION_DISCONN_IND(pcb,ERR_OK,ret);
700 break;
701 case L2CAP_DISCONN_RSP:
702 if(pcb == NULL) {
703 /* A response without a matching request is silently discarded */
704 break;
706 /* Remove signal from unresponded list and deallocate it */
707 L2CAP_SIG_RMV(&(pcb->unrsp_sigs), sig);
708 btpbuf_free(sig->p);
709 btmemb_free(&l2cap_sigs, sig);
711 L2CA_ACTION_DISCONN_CFM(pcb,ret); /* NOTE: Application should
712 now close the connection */
713 break;
714 case L2CAP_ECHO_REQ:
715 pcb->ursp_id = sighdr->id;
716 ret = l2cap_signal(pcb, L2CAP_ECHO_RSP, sighdr->id, &(pcb->remote_bdaddr), NULL);
717 break;
718 case L2CAP_ECHO_RSP:
719 if(pcb == NULL) {
720 /* A response without a matching request is silently discarded */
721 break;
723 /* Remove signal from unresponded list and deallocate it */
724 L2CAP_SIG_RMV(&(pcb->unrsp_sigs), sig);
725 btpbuf_free(sig->p);
726 btmemb_free(&l2cap_sigs, sig);
728 /* Remove temporary pcb from active list */
729 L2CAP_RMV(&l2cap_active_pcbs, pcb);
730 L2CA_ACTION_PING_CFM(pcb,L2CAP_ECHO_RCVD,ret);
731 break;
732 default:
733 /* Alloc size of reason in cmd rej */
734 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_CMD_REJ_SIZE, PBUF_RAM)) != NULL) {
735 ((u16_t *)data->payload)[0] = htole16(L2CAP_CMD_NOT_UNDERSTOOD);
737 ret = l2cap_signal(NULL, L2CAP_CMD_REJ, sighdr->id, bdaddr, data);
739 break;
740 } /* switch */
741 len = len - (le16toh(sighdr->len) + L2CAP_SIGHDR_LEN);
742 btpbuf_header(p, -(le16toh(sighdr->len)));
743 } /* while */
746 /*-----------------------------------------------------------------------------------*/
748 * l2cap_input():
750 * Called by the lower layer. Reassembles the packet, parses the header and forward
751 * it to the upper layer or the signal handler.
753 /*-----------------------------------------------------------------------------------*/
754 void l2cap_input(struct pbuf *p, struct bd_addr *bdaddr)
756 struct l2cap_seg *inseg;
757 struct hci_acl_hdr *aclhdr;
758 struct pbuf *data;
759 err_t ret;
761 btpbuf_header(p, HCI_ACL_HDR_LEN);
762 aclhdr = p->payload;
763 btpbuf_header(p, -HCI_ACL_HDR_LEN);
765 btpbuf_realloc(p, aclhdr->len);
767 for(inseg = l2cap_insegs; inseg != NULL; inseg = inseg->next) {
768 if(bd_addr_cmp(bdaddr, &(inseg->bdaddr))) {
769 break;
773 aclhdr->connhdl_pb_bc = le16toh(aclhdr->connhdl_pb_bc);
774 aclhdr->len = le16toh(aclhdr->len);
775 /* Reassembly procedures */
776 /* Check if continuing fragment or start of L2CAP packet */
777 if(((aclhdr->connhdl_pb_bc >> 12) & 0x03)== L2CAP_ACL_CONT) { /* Continuing fragment */
778 if(inseg == NULL) {
779 /* Discard packet */
780 LOG("l2cap_input: Continuing fragment. Discard packet\n");
781 btpbuf_free(p);
782 return;
783 } else if(inseg->p->tot_len + p->tot_len > inseg->len) { /* Check if length of
784 segment exceeds
785 l2cap header length */
786 /* Discard packet */
787 LOG("l2cap_input: Continuing fragment. Length exceeds L2CAP hdr length. Discard packet\n");
788 btpbuf_free(inseg->p);
789 L2CAP_SEG_RMV(&(l2cap_insegs), inseg);
790 btmemb_free(&l2cap_segs, inseg);
792 btpbuf_free(p);
793 return;
795 /* Add pbuf to segement */
796 btpbuf_chain(inseg->p, p);
797 btpbuf_free(p);
799 } else if(((aclhdr->connhdl_pb_bc >> 12) & 0x03) == L2CAP_ACL_START) { /* Start of L2CAP packet */
800 //LOG("l2cap_input: Start of L2CAP packet p->len = %d, p->tot_len = %d\n", p->len, p->tot_len);
801 if(inseg != NULL) { /* Check if there are segments missing in a previous packet */
802 /* Discard previous packet */
803 LOG("l2cap_input: Start of L2CAP packet. Discard previous packet\n");
804 btpbuf_free(inseg->p);
805 } else {
806 inseg = btmemb_alloc(&l2cap_segs);
807 bd_addr_set(&(inseg->bdaddr), bdaddr);
808 L2CAP_SEG_REG(&(l2cap_insegs), inseg);
810 inseg->p = p;
811 inseg->l2caphdr = p->payload;
812 inseg->l2caphdr->cid = le16toh(inseg->l2caphdr->cid);
813 inseg->l2caphdr->len = le16toh(inseg->l2caphdr->len);
815 inseg->len = inseg->l2caphdr->len + L2CAP_HDR_LEN;
816 for(inseg->pcb = l2cap_active_pcbs; inseg->pcb != NULL; inseg->pcb = inseg->pcb->next) {
817 if(inseg->pcb->scid == inseg->l2caphdr->cid) {
818 break; /* found */
821 } else {
822 /* Discard packet */
823 LOG("l2cap_input: Discard packet\n");
824 btpbuf_free(inseg->p);
825 L2CAP_SEG_RMV(&(l2cap_insegs), inseg);
826 btmemb_free(&l2cap_segs, inseg);
828 btpbuf_free(p);
829 return;
831 if(inseg->p->tot_len < inseg->len) {
832 LOG("l2cap_input: Get continuing segments\n");
833 return; /* Get continuing segments */
836 /* Handle packet */
837 switch(inseg->l2caphdr->cid) {
838 case L2CAP_NULL_CID:
839 /* Illegal */
840 LOG("l2cap_input: Illegal null cid\n");
841 btpbuf_free(inseg->p);
842 break;
843 case L2CAP_SIG_CID:
844 btpbuf_header(inseg->p, -L2CAP_HDR_LEN);
845 l2cap_process_sig(inseg->p, inseg->l2caphdr, bdaddr);
846 btpbuf_free(inseg->p);
847 break;
848 case L2CAP_CONNLESS_CID:
849 /* Not needed by PAN, LAN access or DUN profiles */
850 btpbuf_free(inseg->p);
851 break;
852 default:
853 if(inseg->l2caphdr->cid < 0x0040 || inseg->pcb == NULL) {
854 /* Reserved for specific L2CAP functions or channel does not exist */
855 /* Alloc size of reason in cmd rej */
856 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_CMD_REJ_SIZE+4, PBUF_RAM)) != NULL) {
857 ((u16_t *)data->payload)[0] = htole16(L2CAP_INVALID_CID);
858 ((u16_t *)data->payload)[1] = htole16(inseg->l2caphdr->cid);
859 ((u16_t *)data->payload)[2] = htole16(L2CAP_NULL_CID);
861 ret = l2cap_signal(NULL, L2CAP_CMD_REJ, l2cap_next_sigid(), bdaddr, data);
863 btpbuf_free(inseg->p);
864 break;
867 btpbuf_header(inseg->p, -L2CAP_HDR_LEN);
869 /* Forward packet to higher layer */
870 LOG("l2cap_input: Forward packet to higher layer\n");
872 LOG("l2cap_input: Remote BD address: 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
873 inseg->pcb->remote_bdaddr.addr[5],
874 inseg->pcb->remote_bdaddr.addr[4],
875 inseg->pcb->remote_bdaddr.addr[3],
876 inseg->pcb->remote_bdaddr.addr[2],
877 inseg->pcb->remote_bdaddr.addr[1],
878 inseg->pcb->remote_bdaddr.addr[0]));
880 L2CA_ACTION_RECV(inseg->pcb,inseg->p,ERR_OK,ret);
881 break;
884 /* Remove input segment */
885 L2CAP_SEG_RMV(&(l2cap_insegs), inseg);
886 btmemb_free(&l2cap_segs, inseg);
889 /*-----------------------------------------------------------------------------------*/
891 * l2cap_cid_alloc():
893 * Allocates a channel identifier (CID). They are local names representing a logical
894 * channel endpoint on the device.
896 /*-----------------------------------------------------------------------------------*/
897 static u16_t l2cap_cid_alloc(void)
899 u16_t cid;
900 struct l2cap_pcb *pcb;
902 for (cid = L2CAP_MIN_CID; cid < L2CAP_MAX_CID; ++cid) {
903 for(pcb = l2cap_active_pcbs; pcb != NULL; pcb = pcb->next) {
904 if(pcb->scid == cid) {
905 break;
908 if(pcb == NULL) {
909 return cid;
912 return 0;
915 /*-----------------------------------------------------------------------------------*/
917 * l2cap_new():
919 * Creates a new L2CAP protocol control block but doesn't place it on
920 * any of the L2CAP PCB lists.
922 /*-----------------------------------------------------------------------------------*/
923 struct l2cap_pcb* l2cap_new(void)
925 struct l2cap_pcb *pcb;
927 pcb = btmemb_alloc(&l2cap_pcbs);
928 if(pcb != NULL) {
929 memset(pcb, 0, sizeof(struct l2cap_pcb));
930 pcb->state = L2CAP_CLOSED;
932 /* Initialize configuration parameter options with default values */
934 /* Maximum Transmission Unit */
935 pcb->cfg.inmtu = L2CAP_MTU; /* The MTU that this implementation support */
936 pcb->cfg.outmtu = 672; /* Default MTU. Two Baseband DH5 packets minus the Baseband ACL headers and
937 L2CAP header. This can be set here since we will never send any signals
938 larger than the L2CAP sig MTU (48 bytes) before L2CAP has been configured
941 /* Flush Timeout */
942 pcb->cfg.influshto = 0xFFFF;
943 pcb->cfg.outflushto = 0xFFFF;
945 pcb->cfg.cfgto = L2CAP_CFG_TO; /* Maximum time before terminating a negotiation.
946 Cfg shall not last more than 120s */
947 pcb->cfg.opt = NULL;
948 return pcb;
950 ERROR("l2cap_new: Could not allocate memory for pcb\n");
951 return NULL;
954 /*-----------------------------------------------------------------------------------*/
956 * l2cap_close():
958 * Closes the L2CAP protocol control block.
960 /*-----------------------------------------------------------------------------------*/
961 err_t l2cap_close(struct l2cap_pcb *pcb)
963 struct l2cap_sig *tmpsig;
965 if(pcb->state == L2CAP_LISTEN) {
966 L2CAP_RMV((struct l2cap_pcb**)((void*)&(l2cap_listen_pcbs)), pcb);
967 btmemb_free(&l2cap_listenpcbs, pcb);
968 } else {
969 L2CAP_RMV(&(l2cap_active_pcbs), pcb);
970 /* Free any unresponded signals */
971 while(pcb->unrsp_sigs != NULL) {
972 tmpsig = pcb->unrsp_sigs;
973 pcb->unrsp_sigs = pcb->unrsp_sigs->next;
974 btmemb_free(&l2cap_sigs, tmpsig);
977 btmemb_free(&l2cap_pcbs, pcb);
979 pcb = NULL;
980 return ERR_OK;
982 /*-----------------------------------------------------------------------------------*/
984 * l2cap_reset_all():
986 * Closes all active and listening L2CAP protocol control blocks.
988 /*-----------------------------------------------------------------------------------*/
989 void l2cap_reset_all(void)
991 struct l2cap_pcb *pcb, *tpcb;
992 struct l2cap_pcb_listen *lpcb, *tlpcb;
993 struct l2cap_seg *seg, *tseg;
995 for(pcb = l2cap_active_pcbs; pcb != NULL;) {
996 tpcb = pcb->next;
997 l2cap_close(pcb);
998 pcb = tpcb;
1001 for(lpcb = l2cap_listen_pcbs; lpcb != NULL;) {
1002 tlpcb = lpcb->next;
1003 l2cap_close((struct l2cap_pcb *)lpcb);
1004 lpcb = tlpcb;
1007 for(seg = l2cap_insegs; seg != NULL;) {
1008 tseg = seg->next;
1009 L2CAP_SEG_RMV(&(l2cap_insegs), seg);
1010 btmemb_free(&l2cap_segs, seg);
1011 seg = tseg;
1014 l2cap_init();
1017 /*-----------------------------------------------------------------------------------*/
1018 /* L2CAP to L2CAP signalling events
1020 /*-----------------------------------------------------------------------------------*/
1021 /*-----------------------------------------------------------------------------------*/
1023 * l2cap_signal():
1025 * Assembles the signalling packet and passes it to the lower layer.
1027 /*-----------------------------------------------------------------------------------*/
1028 err_t l2cap_signal(struct l2cap_pcb *pcb, u8_t code, u16_t ursp_id, struct bd_addr *remote_bdaddr, struct pbuf *data)
1030 struct l2cap_sig *sig;
1031 struct l2cap_sig_hdr *sighdr;
1032 struct l2cap_hdr *hdr;
1033 err_t ret;
1035 /* Alloc a new signal */
1036 LOG("l2cap_signal: Allocate memory for l2cap_sig. Code = 0x%x\n", code);
1037 if((sig = btmemb_alloc(&l2cap_sigs)) == NULL) {
1038 ERROR("l2cap_signal: could not allocate memory for l2cap_sig\n");
1039 return ERR_MEM;
1042 /* Alloc a pbuf for signal */
1043 if((sig->p = btpbuf_alloc(PBUF_RAW, L2CAP_HDR_LEN+L2CAP_SIGHDR_LEN, PBUF_RAM)) == NULL) {
1044 ERROR("l2cap_signal: could not allocate memory for pbuf\n");
1045 return ERR_MEM;
1048 /* Setup signal header and leave room for l2cap hdr */
1049 sighdr = (struct l2cap_sig_hdr *)(((u8_t *)sig->p->payload)+L2CAP_HDR_LEN);
1051 /* Chain data to signal and set length of signal data */
1052 if(data == NULL) {
1053 sighdr->len = 0;
1054 } else {
1055 btpbuf_chain(sig->p, data);
1056 btpbuf_free(data);
1057 sighdr->len = htole16(data->tot_len);
1060 sighdr->code = code;
1062 if(sighdr->code % 2) { /* If odd this is a resp/rej signal */
1063 sig->sigid = ursp_id; /* Get id */
1064 LOG("l2cap_signal: Sending response/reject signal with id = %d code = %d\n", sig->sigid, sighdr->code);
1065 } else {
1066 sig->sigid = l2cap_next_sigid(); /* Alloc id */
1067 sig->rtx = L2CAP_RTX; /* Set Response Timeout Expired timer (in seconds)
1068 should be at least as large as the BB flush timeout */
1069 sig->nrtx = L2CAP_MAXRTX; /* Set max number of retransmissions */
1070 LOG("l2cap_signal: Sending request signal with id = %d code = %d\n", sig->sigid, sighdr->code);
1072 sighdr->id = sig->sigid; /* Set id */
1074 /* Set up L2CAP hdr */
1075 hdr = sig->p->payload;
1076 hdr->len = htole16((sig->p->tot_len - L2CAP_HDR_LEN));
1077 hdr->cid = htole16(L2CAP_SIG_CID); /* 0x0001 */
1079 ret = l2cap_write(remote_bdaddr, sig->p, sig->p->tot_len); /* Send peer L2CAP signal */
1081 /* Put signal on unresponded list if it's a request signal, else deallocate it */
1082 if(ret == ERR_OK && (sighdr->code % 2) == 0) {
1083 LOG("l2cap_signal: Registering sent request signal with id = %d code = %d\n", sig->sigid, sighdr->code);
1084 L2CAP_SIG_REG(&(pcb->unrsp_sigs), sig);
1085 } else {
1086 LOG("l2cap_signal: Deallocating sent response/reject signal with id = %d code = %d\n", sig->sigid, sighdr->code);
1087 btpbuf_free(sig->p);
1088 sig->p = NULL;
1089 btmemb_free(&l2cap_sigs, sig);
1092 return ret;
1095 /*-----------------------------------------------------------------------------------*/
1097 * l2cap_rexmit_signal():
1099 * Called by the l2cap timer. Retransmitts a signal.
1101 /*-----------------------------------------------------------------------------------*/
1102 err_t l2cap_rexmit_signal(struct l2cap_pcb *pcb, struct l2cap_sig *sig)
1104 err_t ret;
1106 /* Set up L2CAP hdr */
1107 ret = l2cap_write(&(pcb->remote_bdaddr), sig->p, sig->p->tot_len); /* Send peer L2CAP signal */
1109 return ret;
1111 /*-----------------------------------------------------------------------------------*/
1112 /* Upper-Layer to L2CAP signaling events
1114 /*-----------------------------------------------------------------------------------*/
1115 /*-----------------------------------------------------------------------------------*/
1117 * l2ca_connect_req():
1119 * Initiates the sending of a connect request message. Requests the creation of a
1120 * channel representing a logicalconnection to a physical address. Input parameters
1121 * are the target protocol(PSM) and remote devices 48-bit address (BD_ADDR). Also
1122 * specify the function to be called when a confirm has been received.
1124 /*-----------------------------------------------------------------------------------*/
1125 err_t l2ca_connect_req(struct l2cap_pcb *pcb, struct bd_addr *bdaddr, u16_t psm,
1126 u8_t role_switch, err_t (* l2ca_connect_cfm)(void *arg, struct l2cap_pcb *lpcb,
1127 u16_t result, u16_t status))
1129 err_t ret;
1130 struct pbuf *data;
1132 if(bdaddr != NULL) {
1133 bd_addr_set(&(pcb->remote_bdaddr),bdaddr);
1134 } else {
1135 return ERR_VAL;
1138 pcb->psm = psm;
1139 pcb->l2ca_connect_cfm = l2ca_connect_cfm;
1140 pcb->scid = l2cap_cid_alloc();
1142 pcb->cfg.l2capcfg |= L2CAP_CFG_IR; /* We are the initiator of this connection */
1144 if(!lp_is_connected(bdaddr)) {
1145 ret = lp_connect_req(bdaddr, role_switch); /* Create ACL link w pcb state == CLOSED */
1146 } else {
1147 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_CONN_REQ_SIZE, PBUF_RAM)) == NULL) {
1148 ERROR("l2cap_connect_req: Could not allocate memory for pbuf\n");
1149 return ERR_MEM;
1151 ((u16_t *)data->payload)[0] = htole16(psm);
1152 ((u16_t *)data->payload)[1] = htole16(pcb->scid);
1153 ret = l2cap_signal(pcb, L2CAP_CONN_REQ, 0, &(pcb->remote_bdaddr), data); /* Send l2cap_conn_req signal */
1155 pcb->state = W4_L2CAP_CONNECT_RSP;
1158 L2CAP_REG(&(l2cap_active_pcbs), pcb);
1160 return ret;
1163 /*-----------------------------------------------------------------------------------*/
1165 * l2ca_config_req():
1167 * Requests the initial configuration (or reconfiguration) of a channel to a new set
1168 * of channel parameters. Input parameters are the local CID endpoint, new incoming
1169 * receivable MTU (InMTU), new outgoing flow specification, and flush and link
1170 * timeouts. Also specify the function to be called when a confirm has been received.
1172 /*-----------------------------------------------------------------------------------*/
1173 err_t l2ca_config_req(struct l2cap_pcb *pcb)
1175 struct pbuf *p, *q;
1176 struct l2cap_cfgopt_hdr *opthdr;
1177 err_t ret;
1179 switch(pcb->state) {
1180 case L2CAP_OPEN:
1181 LOG("l2cap_config_req: state = L2CAP_OPEN. Suspend transmission\n");
1182 /* Note: Application should have suspended data transmission, otherwise outgoing data will be
1183 dropped */
1184 pcb->state = L2CAP_CONFIG;
1185 /* Fallthrough */
1186 case L2CAP_CONFIG:
1187 LOG("l2cap_config_req: state = L2CAP_CONFIG\n");
1189 if((p = btpbuf_alloc(PBUF_RAW, L2CAP_CFG_REQ_SIZE, PBUF_RAM)) == NULL) {
1190 ERROR("l2cap_config_req: Could not allocate memory for pbuf\n");
1191 return ERR_MEM;
1194 /* Assemble config request packet. Only options that has to be changed will be
1195 sent */
1196 ((u16_t *)p->payload)[0] = htole16(pcb->dcid);
1197 /* In this implementation we do not send multiple cmds in one
1198 signal packet. Therefore we will never send a config_req packet
1199 that will cause the signal to be larger than the minimum L2CAP MTU
1200 48 bytes. Hence, this flag will always be cleared */
1201 ((u16_t *)p->payload)[1] = 0;
1203 /* Add MTU and out flush timeout to cfg packet if not default value. QoS (Best effort) is always
1204 set to default and can be skipped */
1205 if(pcb->cfg.inmtu != L2CAP_CFG_DEFAULT_INMTU) {
1206 if((q = btpbuf_alloc(PBUF_RAW, L2CAP_CFGOPTHDR_LEN + L2CAP_MTU_LEN, PBUF_RAM)) == NULL) {
1207 ERROR("l2cap_config_req: Could not allocate memory for pbuf\n");
1208 btpbuf_free(p);
1209 return ERR_MEM;
1211 opthdr = q->payload;
1212 opthdr->type = L2CAP_CFG_MTU;
1213 opthdr->len = L2CAP_MTU_LEN;
1214 ((u16_t *)q->payload)[1] = htole16(pcb->cfg.inmtu);
1215 btpbuf_chain(p, q);
1216 btpbuf_free(q);
1219 if(L2CAP_OUT_FLUSHTO != L2CAP_CFG_DEFAULT_OUTFLUSHTO) {
1220 if((q = btpbuf_alloc(PBUF_RAW, L2CAP_CFGOPTHDR_LEN + L2CAP_FLUSHTO_LEN, PBUF_RAM)) == NULL) {
1221 ERROR("l2cap_config_req: Could not allocate memory for pbuf\n");
1222 btpbuf_free(p);
1223 return ERR_MEM;
1225 opthdr = q->payload;
1226 opthdr->type = L2CAP_FLUSHTO;
1227 opthdr->len = L2CAP_FLUSHTO_LEN;
1228 pcb->cfg.outflushto = L2CAP_OUT_FLUSHTO;
1229 ((u16_t *)q->payload)[1] = htole16(pcb->cfg.outflushto);
1230 btpbuf_chain(p, q);
1231 btpbuf_free(q);
1234 /* Send config request signal */
1235 ret = l2cap_signal(pcb, L2CAP_CFG_REQ, 0, &(pcb->remote_bdaddr), p);
1236 break;
1237 default:
1238 ERROR("l2cap_config_req: state = L2CAP_?. Invalid state\n");
1239 return ERR_CONN; /* Invalid state. Connection is not in OPEN or CONFIG state */
1241 return ret;
1243 /*-----------------------------------------------------------------------------------*/
1245 * l2ca_disconnect_req():
1247 * Requests the disconnection of the channel. Also specify the function to be called
1248 * when a confirm is received
1250 /*-----------------------------------------------------------------------------------*/
1251 err_t l2ca_disconnect_req(struct l2cap_pcb *pcb, err_t (* l2ca_disconnect_cfm)(void *arg, struct l2cap_pcb *pcb))
1253 struct pbuf *data;
1254 err_t ret;
1256 if(pcb->state == L2CAP_OPEN || pcb->state == L2CAP_CONFIG) {
1257 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_DISCONN_REQ_SIZE, PBUF_RAM)) == NULL) {
1258 ERROR("l2cap_disconnect_req: Could not allocate memory for pbuf\n");
1259 return ERR_MEM;
1261 pcb->l2ca_disconnect_cfm = l2ca_disconnect_cfm;
1263 ((u16_t *)data->payload)[0] = htole16(pcb->dcid);
1264 ((u16_t *)data->payload)[1] = htole16(pcb->scid);
1266 ret = l2cap_signal(pcb, L2CAP_DISCONN_REQ, 0, &(pcb->remote_bdaddr), data);
1268 if(ret == ERR_OK) {
1269 pcb->state = W4_L2CAP_DISCONNECT_RSP;
1271 } else {
1272 return ERR_CONN; /* Signal not supported in this state */
1275 return ret;
1277 /*-----------------------------------------------------------------------------------*/
1279 * l2ca_datawrite():
1281 * Transfers data across the channel.
1283 /*-----------------------------------------------------------------------------------*/
1284 err_t l2ca_datawrite(struct l2cap_pcb *pcb, struct pbuf *p)
1286 err_t ret;
1287 struct l2cap_hdr *l2caphdr;
1288 struct pbuf *q;
1290 if(pcb->state != L2CAP_OPEN) {
1291 ERROR("l2cap_datawrite: State != L2CAP_OPEN. Dropping data\n");
1292 return ERR_CONN;
1295 /* Build L2CAP header */
1296 if((q = btpbuf_alloc(PBUF_RAW, L2CAP_HDR_LEN, PBUF_RAM)) == NULL) {
1297 ERROR("l2cap_datawrite: Could not allocate memory for pbuf\n");
1298 return ERR_MEM;
1300 btpbuf_chain(q, p);
1302 l2caphdr = q->payload;
1303 l2caphdr->cid = htole16(pcb->dcid);
1305 /* If length of the data exceeds the OutMTU then only the first OutMTU bytes are sent */
1306 if(p->tot_len > pcb->cfg.outmtu) {
1307 /* Send peer L2CAP data */
1308 l2caphdr->len = htole16(pcb->cfg.outmtu);
1309 if((ret = l2cap_write(&(pcb->remote_bdaddr), q, pcb->cfg.outmtu + L2CAP_HDR_LEN)) == ERR_OK) {
1310 //LOG("l2cap_datawrite: Length of data exceeds the OutMTU p->tot_len = %d\n", p->tot_len);
1311 ret = ERR_BUF; /* Length of data exceeds the OutMTU */
1313 } else {
1314 /* Send peer L2CAP data */
1315 l2caphdr->len = htole16(p->tot_len);
1316 //LOG("l2cap_datawrite: q->tot_len = %d\n", q->tot_len);
1317 ret = l2cap_write(&(pcb->remote_bdaddr), q, q->tot_len);
1320 /* Free L2CAP header. Higher layers will handle rest of packet */
1321 p = btpbuf_dechain(q);
1322 btpbuf_free(q);
1324 return ret;
1326 /*-----------------------------------------------------------------------------------*/
1328 * l2ca_ping():
1330 * Sends an empty L2CAP echo request message. Also specify the function that should
1331 * be called when a L2CAP echo reply has been received.
1333 /*-----------------------------------------------------------------------------------*/
1334 err_t l2ca_ping(struct bd_addr *bdaddr, struct l2cap_pcb *tpcb,
1335 err_t (* l2ca_pong)(void *arg, struct l2cap_pcb *pcb, u8_t result))
1337 err_t ret;
1339 if(!lp_is_connected(bdaddr)) {
1340 return ERR_CONN;
1343 bd_addr_set(&(tpcb->remote_bdaddr), bdaddr);
1344 tpcb->l2ca_pong = l2ca_pong;
1346 L2CAP_REG(&(l2cap_active_pcbs), tpcb);
1348 ret = l2cap_signal(tpcb, L2CAP_ECHO_REQ, 0, &(tpcb->remote_bdaddr), NULL); /* Send l2cap_echo_req signal */
1350 return ret;
1352 /*-----------------------------------------------------------------------------------*/
1353 /* Lower-Layer to L2CAP signaling events
1355 /*-----------------------------------------------------------------------------------*/
1356 /*-----------------------------------------------------------------------------------*/
1358 * lp_connect_cfm():
1360 * Confirms the request to establish a lower layer (Baseband) connection.
1362 /*-----------------------------------------------------------------------------------*/
1363 void lp_connect_cfm(struct bd_addr *bdaddr, u8_t encrypt_mode, err_t err)
1365 struct l2cap_pcb *pcb;
1366 struct pbuf *data;
1367 err_t ret;
1369 for(pcb = l2cap_active_pcbs; pcb != NULL; pcb = pcb->next) {
1370 if(bd_addr_cmp(&(pcb->remote_bdaddr), bdaddr)) {
1371 break;
1374 if(pcb == NULL) {
1375 /* Silently discard */
1376 LOG("lp_connect_cfm: Silently discard\n");
1377 } else {
1378 if(err == ERR_OK) {
1379 pcb->encrypt = encrypt_mode;
1380 /* Send l2cap_conn_req signal if no error */
1381 if((data = btpbuf_alloc(PBUF_RAW, L2CAP_CONN_REQ_SIZE, PBUF_RAM)) != NULL) {
1382 ((u16_t *)data->payload)[0] = htole16(pcb->psm);
1383 ((u16_t *)data->payload)[1] = htole16(pcb->scid);
1384 if((ret = l2cap_signal(pcb, L2CAP_CONN_REQ, 0, &(pcb->remote_bdaddr), data)) == ERR_OK) {
1385 pcb->state = W4_L2CAP_CONNECT_RSP;
1386 } else {
1387 L2CA_ACTION_CONN_CFM(pcb,L2CAP_CONN_REF_RES,0x0000,ret); /* No resources available? */
1389 //LOG("lp_connect_cfm: l2cap_conn_req signal sent. err = %d\nPSM = 0x%x\nscid = 0x%x\nencrypt mode = 0x%x\n", err, pcb->psm, pcb->scid, pcb->encrypt);
1390 } else {
1391 ERROR("lp_connect_cfm: No resources available\n");
1392 L2CA_ACTION_CONN_CFM(pcb,L2CAP_CONN_REF_RES,0x0000,ret); /* No resources available */
1394 } else {
1395 ERROR("lp_connect_cfm: Connection falied\n");
1396 L2CA_ACTION_CONN_CFM(pcb,L2CAP_CONN_REF_RES,0x0000,ret); /* No resources available */
1400 /*-----------------------------------------------------------------------------------*/
1402 * lp_connect_ind():
1404 * Indicates the lower protocol has successfully established a connection.
1406 /*-----------------------------------------------------------------------------------*/
1407 void lp_connect_ind(struct bd_addr *bdaddr)
1409 LOG("lp_connect_ind\n");
1411 /*-----------------------------------------------------------------------------------*/
1413 * lp_disconnect_ind():
1415 * Indicates the lower protocol (Baseband) has been shut down by LMP commands or a
1416 * timeout event..
1418 /*-----------------------------------------------------------------------------------*/
1419 void lp_disconnect_ind(struct bd_addr *bdaddr,u8_t reason)
1421 struct l2cap_pcb *pcb, *tpcb;
1422 err_t ret;
1424 for(pcb = l2cap_active_pcbs; pcb != NULL;) {
1425 tpcb = pcb->next;
1426 LOG("lp_disconnect_ind: Find a pcb with a matching Bluetooth address\n");
1427 /* All PCBs with matching Bluetooth address have been disconnected */
1428 if(bd_addr_cmp(&(pcb->remote_bdaddr), bdaddr)) {// && pcb->state != L2CAP_CLOSED) {
1429 pcb->state = L2CAP_CLOSED;
1430 LOG("lp_disconnect_ind: Notify application\n");
1431 L2CA_ACTION_DISCONN_IND(pcb,ERR_OK,ret);
1433 pcb = tpcb;
1435 if(l2cap_disconnect_bb_cb) l2cap_disconnect_bb_cb(bdaddr,reason);
1438 /*-----------------------------------------------------------------------------------*/
1440 * l2cap_disconnect_bb():
1442 * Register a callback to obtain the disconnection reason from the baseband
1444 /*-----------------------------------------------------------------------------------*/
1445 void (*l2cap_disconnect_bb(void (*l2ca_disconnect_bb)(struct bd_addr *bdaddr,u8_t reason)))(struct bd_addr *bdaddr,u8_t reason)
1447 void (*oldcb)(struct bd_addr *bdaddr,u8_t reason) = NULL;
1448 oldcb = l2cap_disconnect_bb_cb;
1449 l2cap_disconnect_bb_cb = l2ca_disconnect_bb;
1450 return oldcb;
1453 /*-----------------------------------------------------------------------------------*/
1455 * l2cap_next_sigid():
1457 * Issues a signal identifier that helps matching a request with the reply.
1459 /*-----------------------------------------------------------------------------------*/
1460 u8_t l2cap_next_sigid(void)
1462 ++sigid_nxt;
1463 if(sigid_nxt == 0) {
1464 sigid_nxt = 1;
1466 return sigid_nxt;
1468 /*-----------------------------------------------------------------------------------*/
1470 * l2cap_arg():
1472 * Used to specify the argument that should be passed callback functions.
1474 /*-----------------------------------------------------------------------------------*/
1475 void l2cap_arg(struct l2cap_pcb *pcb, void *arg)
1477 pcb->callback_arg = arg;
1480 /*-----------------------------------------------------------------------------------*/
1482 * l2cap_connect_ind():
1484 * Set the state of the connection to be LISTEN, which means that it is able to accept
1485 * incoming connections. The protocol control block is reallocated in order to consume
1486 * less memory. Setting the connection to LISTEN is an irreversible process. Also
1487 * specify the function that should be called when the channel has received a
1488 * connection request.
1490 /*-----------------------------------------------------------------------------------*/
1491 err_t l2cap_connect_ind(struct l2cap_pcb *npcb, struct bd_addr *bdaddr, u16_t psm,err_t (* l2ca_connect_ind)(void *arg, struct l2cap_pcb *pcb, err_t err))
1493 struct l2cap_pcb_listen *lpcb;
1495 lpcb = btmemb_alloc(&l2cap_listenpcbs);
1496 if(lpcb == NULL) {
1497 ERROR("l2cap_connect_ind: Could not allocate memory for lpcb\n");
1498 return ERR_MEM;
1501 bd_addr_set(&(lpcb->bdaddr),bdaddr);
1502 lpcb->psm = psm;
1503 lpcb->l2ca_connect_ind = l2ca_connect_ind;
1504 lpcb->state = L2CAP_LISTEN;
1505 lpcb->callback_arg = npcb->callback_arg;
1506 btmemb_free(&l2cap_pcbs, npcb);
1507 L2CAP_REG(&(l2cap_listen_pcbs), lpcb);
1508 return ERR_OK;
1511 /*-----------------------------------------------------------------------------------*/
1513 * l2cap_disconnect_ind():
1515 * Used to specify the a function to be called when a disconnection request has been
1516 * received from a remote device or the remote device has been disconnected because it
1517 * has failed to respond to a signalling request.
1519 /*-----------------------------------------------------------------------------------*/
1520 void l2cap_disconnect_ind(struct l2cap_pcb *pcb, err_t (* l2ca_disconnect_ind)(void *arg, struct l2cap_pcb *newpcb, err_t err))
1522 pcb->l2ca_disconnect_ind = l2ca_disconnect_ind;
1524 /*-----------------------------------------------------------------------------------*/
1526 * l2cap_timeout_ind():
1528 * Used to specify the function to be called when RTX or ERTX timer has expired.
1530 /*-----------------------------------------------------------------------------------*/
1531 void l2cap_timeout_ind(struct l2cap_pcb *pcb,err_t (* l2ca_timeout_ind)(void *arg, struct l2cap_pcb *newpcb, err_t err))
1533 pcb->l2ca_timeout_ind = l2ca_timeout_ind;
1535 /*-----------------------------------------------------------------------------------*/
1537 * l2cap_recv():
1539 * Used to specify the function that should be called when a L2CAP connection receives
1540 * data.
1542 /*-----------------------------------------------------------------------------------*/
1543 void l2cap_recv(struct l2cap_pcb *pcb, err_t (* l2ca_recv)(void *arg, struct l2cap_pcb *pcb, struct pbuf *p, err_t err))
1545 pcb->l2ca_recv = l2ca_recv;
1547 /*-----------------------------------------------------------------------------------*/