xref: /btstack/src/l2cap.c (revision a45f1157be420bd87610fc2ab426b71862f626c9)
1 /*
2  *  l2cap.c
3  *
4  *  Logical Link Control and Adaption Protocl (L2CAP)
5  *
6  *  Created by Matthias Ringwald on 5/16/09.
7  */
8 
9 #include "l2cap.h"
10 
11 #include <stdarg.h>
12 #include <string.h>
13 
14 #include <stdio.h>
15 
16 static char *l2cap_signaling_commands_format[] = {
17     "D",    // 0x01 command reject: reason {cmd not understood (0), sig MTU exceeded (2:max sig MTU), invalid CID (4:req CID)}, data len, data
18     "22",   // 0x02 connection request: PSM, Source CID
19     "2222", // 0x03 connection response: Dest CID, Source CID, Result, Status
20     "22D",  // 0x04 config request: Dest CID, Flags, Configuration options
21     "222D", // 0x05 config response: Source CID, Flags, Result, Configuration options
22     "22",   // 0x06 disconection request: Dest CID, Source CID
23     "22",   // 0x07 disconection response: Dest CID, Source CID
24     "D",    // 0x08 echo request: Data
25     "D",    // 0x09 echo response: Data
26     "2",    // 0x0a information request: InfoType {1=Connectionless MTU, 2=Extended features supported}
27     "22D",  // 0x0b information response: InfoType, Result, Data
28 };
29 
30 static uint8_t * sig_buffer;
31 
32 uint8_t   sig_seq_nr;
33 uint16_t  local_cid;
34 
35 int l2cap_send_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){
36 
37     // 0 - Connection handle : PB=10 : BC=00
38      bt_store_16(sig_buffer, 0, handle | (2 << 12) | (0 << 14));
39     // 6 - L2CAP channel = 1
40     bt_store_16(sig_buffer, 6, 1);
41     // 8 - Code
42     sig_buffer[8] = cmd;
43     // 9 - id (!= 0 sequentially)
44     sig_buffer[9] = identifier;
45 
46     // 12 - L2CAP signaling parameters
47     uint16_t pos = 12;
48     va_list argptr;
49     va_start(argptr, identifier);
50     const char *format = l2cap_signaling_commands_format[cmd-1];
51     uint16_t word;
52     uint8_t * ptr;
53     while (*format) {
54         switch(*format) {
55             case '1': //  8 bit value
56             case '2': // 16 bit value
57                 word = va_arg(argptr, int);
58                 // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
59                 sig_buffer[pos++] = word & 0xff;
60                 if (*format == '2') {
61                     sig_buffer[pos++] = word >> 8;
62                 }
63                 break;
64             case 'D': // variable data. passed: len, ptr
65                 word = va_arg(argptr, int);
66                 ptr  = va_arg(argptr, uint8_t *);
67                 memcpy(&sig_buffer[pos], ptr, word);
68                 pos += word;
69                 break;
70             default:
71                 break;
72         }
73         format++;
74     };
75     va_end(argptr);
76 
77     // Fill in various length fields: it's the number of bytes following for ACL lenght and l2cap parameter length
78     // - the l2cap payload length is counted after the following channel id (only payload)
79 
80     // 2 - ACL length
81     bt_store_16(sig_buffer, 2,  pos - 4);
82     // 4 - L2CAP packet length
83     bt_store_16(sig_buffer, 4,  pos - 6 - 2);
84     // 10 - L2CAP signaling parameter length
85     bt_store_16(sig_buffer, 10, pos - 12);
86 
87     return hci_send_acl_packet(sig_buffer, pos);
88 }
89 
90 void l2cap_init(){
91     sig_buffer = malloc( 48 );
92     sig_seq_nr = 1;
93     local_cid = 0x40;
94 }