143625864Smatthias.ringwald /* 243625864Smatthias.ringwald * l2cap.c 343625864Smatthias.ringwald * 443625864Smatthias.ringwald * Logical Link Control and Adaption Protocl (L2CAP) 543625864Smatthias.ringwald * 643625864Smatthias.ringwald * Created by Matthias Ringwald on 5/16/09. 743625864Smatthias.ringwald */ 843625864Smatthias.ringwald 943625864Smatthias.ringwald #include "l2cap.h" 1043625864Smatthias.ringwald 1143625864Smatthias.ringwald #include <stdarg.h> 1243625864Smatthias.ringwald #include <string.h> 1343625864Smatthias.ringwald 1443625864Smatthias.ringwald #include <stdio.h> 1543625864Smatthias.ringwald 1643625864Smatthias.ringwald static char *l2cap_signaling_commands_format[] = { 1743625864Smatthias.ringwald "D", // 0x01 command reject: reason {cmd not understood (0), sig MTU exceeded (2:max sig MTU), invalid CID (4:req CID)}, data len, data 1843625864Smatthias.ringwald "22", // 0x02 connection request: PSM, Source CID 1943625864Smatthias.ringwald "2222", // 0x03 connection response: Dest CID, Source CID, Result, Status 2043625864Smatthias.ringwald "22D", // 0x04 config request: Dest CID, Flags, Configuration options 2143625864Smatthias.ringwald "222D", // 0x05 config response: Source CID, Flags, Result, Configuration options 2243625864Smatthias.ringwald "22", // 0x06 disconection request: Dest CID, Source CID 2343625864Smatthias.ringwald "22", // 0x07 disconection response: Dest CID, Source CID 2443625864Smatthias.ringwald "D", // 0x08 echo request: Data 2543625864Smatthias.ringwald "D", // 0x09 echo response: Data 2643625864Smatthias.ringwald "2", // 0x0a information request: InfoType {1=Connectionless MTU, 2=Extended features supported} 2743625864Smatthias.ringwald "22D", // 0x0b information response: InfoType, Result, Data 2843625864Smatthias.ringwald }; 2943625864Smatthias.ringwald 3043625864Smatthias.ringwald static uint8_t * sig_buffer; 3143625864Smatthias.ringwald 32*0af41d30Smatthias.ringwald uint8_t sig_seq_nr = 1; 33*0af41d30Smatthias.ringwald uint16_t local_cid = 0x40; 3443625864Smatthias.ringwald 35*0af41d30Smatthias.ringwald uint16_t l2cap_create_signaling_internal(uint8_t * acl_buffer,hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, va_list argptr){ 3643625864Smatthias.ringwald 3743625864Smatthias.ringwald // 0 - Connection handle : PB=10 : BC=00 38*0af41d30Smatthias.ringwald bt_store_16(acl_buffer, 0, handle | (2 << 12) | (0 << 14)); 3943625864Smatthias.ringwald // 6 - L2CAP channel = 1 40*0af41d30Smatthias.ringwald bt_store_16(acl_buffer, 6, 1); 4143625864Smatthias.ringwald // 8 - Code 42*0af41d30Smatthias.ringwald acl_buffer[8] = cmd; 4343625864Smatthias.ringwald // 9 - id (!= 0 sequentially) 44*0af41d30Smatthias.ringwald acl_buffer[9] = identifier; 4543625864Smatthias.ringwald 4643625864Smatthias.ringwald // 12 - L2CAP signaling parameters 4743625864Smatthias.ringwald uint16_t pos = 12; 4843625864Smatthias.ringwald const char *format = l2cap_signaling_commands_format[cmd-1]; 4943625864Smatthias.ringwald uint16_t word; 5043625864Smatthias.ringwald uint8_t * ptr; 5143625864Smatthias.ringwald while (*format) { 5243625864Smatthias.ringwald switch(*format) { 5343625864Smatthias.ringwald case '1': // 8 bit value 5443625864Smatthias.ringwald case '2': // 16 bit value 5543625864Smatthias.ringwald word = va_arg(argptr, int); 5643625864Smatthias.ringwald // minimal va_arg is int: 2 bytes on 8+16 bit CPUs 57*0af41d30Smatthias.ringwald acl_buffer[pos++] = word & 0xff; 5843625864Smatthias.ringwald if (*format == '2') { 59*0af41d30Smatthias.ringwald acl_buffer[pos++] = word >> 8; 6043625864Smatthias.ringwald } 6143625864Smatthias.ringwald break; 6243625864Smatthias.ringwald case 'D': // variable data. passed: len, ptr 6343625864Smatthias.ringwald word = va_arg(argptr, int); 6443625864Smatthias.ringwald ptr = va_arg(argptr, uint8_t *); 65*0af41d30Smatthias.ringwald memcpy(&acl_buffer[pos], ptr, word); 6643625864Smatthias.ringwald pos += word; 6743625864Smatthias.ringwald break; 6843625864Smatthias.ringwald default: 6943625864Smatthias.ringwald break; 7043625864Smatthias.ringwald } 7143625864Smatthias.ringwald format++; 7243625864Smatthias.ringwald }; 7343625864Smatthias.ringwald va_end(argptr); 7443625864Smatthias.ringwald 7543625864Smatthias.ringwald // Fill in various length fields: it's the number of bytes following for ACL lenght and l2cap parameter length 7643625864Smatthias.ringwald // - the l2cap payload length is counted after the following channel id (only payload) 7743625864Smatthias.ringwald 7843625864Smatthias.ringwald // 2 - ACL length 79*0af41d30Smatthias.ringwald bt_store_16(acl_buffer, 2, pos - 4); 8043625864Smatthias.ringwald // 4 - L2CAP packet length 81*0af41d30Smatthias.ringwald bt_store_16(acl_buffer, 4, pos - 6 - 2); 8243625864Smatthias.ringwald // 10 - L2CAP signaling parameter length 83*0af41d30Smatthias.ringwald bt_store_16(acl_buffer, 10, pos - 12); 8443625864Smatthias.ringwald 85*0af41d30Smatthias.ringwald return pos; 86*0af41d30Smatthias.ringwald } 87*0af41d30Smatthias.ringwald int l2cap_send_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){ 88*0af41d30Smatthias.ringwald va_list argptr; 89*0af41d30Smatthias.ringwald va_start(argptr, identifier); 90*0af41d30Smatthias.ringwald uint16_t len = l2cap_create_signaling_internal(sig_buffer, handle, cmd, identifier, argptr); 91*0af41d30Smatthias.ringwald return hci_send_acl_packet(sig_buffer, len); 92*0af41d30Smatthias.ringwald } 93*0af41d30Smatthias.ringwald 94*0af41d30Smatthias.ringwald uint16_t l2cap_create_signaling_packet(uint8_t *acl_buffer, hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){ 95*0af41d30Smatthias.ringwald va_list argptr; 96*0af41d30Smatthias.ringwald va_start(argptr, identifier); 97*0af41d30Smatthias.ringwald uint16_t len = l2cap_create_signaling_internal(acl_buffer, handle, cmd, identifier, argptr); 98*0af41d30Smatthias.ringwald va_end(argptr); 99*0af41d30Smatthias.ringwald return len; 10043625864Smatthias.ringwald } 10143625864Smatthias.ringwald 10243625864Smatthias.ringwald void l2cap_init(){ 10343625864Smatthias.ringwald sig_buffer = malloc( 48 ); 10443625864Smatthias.ringwald }