l2cap.c (d84e866fb87b02372d5534d4932cd5fa66d5315b) | l2cap.c (f0fb4cd727a7cb54eb1a1c2b1dc9efdf67d42fde) |
---|---|
1/* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright --- 546 unchanged lines hidden (view full) --- 555 return (((uint16_t) sar) << 14) | (req_seq << 8) | (final << 7) | (tx_seq << 1) | 0; 556} 557static inline uint16_t l2cap_encanced_control_field_for_supevisor_frame(l2cap_supervisory_function_t supervisory_function, int poll, int final, uint8_t req_seq){ 558 return (req_seq << 8) | (final << 7) | (poll << 4) | (((int) supervisory_function) << 2) | 1; 559} 560static int l2cap_next_ertm_seq_nr(int seq_nr){ 561 return (seq_nr + 1) & 0x3f; 562} | 1/* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright --- 546 unchanged lines hidden (view full) --- 555 return (((uint16_t) sar) << 14) | (req_seq << 8) | (final << 7) | (tx_seq << 1) | 0; 556} 557static inline uint16_t l2cap_encanced_control_field_for_supevisor_frame(l2cap_supervisory_function_t supervisory_function, int poll, int final, uint8_t req_seq){ 558 return (req_seq << 8) | (final << 7) | (poll << 4) | (((int) supervisory_function) << 2) | 1; 559} 560static int l2cap_next_ertm_seq_nr(int seq_nr){ 561 return (seq_nr + 1) & 0x3f; 562} |
563static void l2cap_ertm_next_tx_write_index(l2cap_channel_t * channel){ 564 channel->tx_write_index++; 565 if (channel->tx_write_index < channel->num_tx_buffers) return; 566 channel->tx_write_index = 0; 567} 568static int l2cap_ertm_send_information_frame(l2cap_channel_t * channel, int index){ 569 l2cap_ertm_tx_packet_state_t * tx_state = &channel->tx_packets_state[index]; 570 hci_reserve_packet_buffer(); 571 uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 572 uint16_t control = l2cap_encanced_control_field_for_information_frame(tx_state->tx_seq, 0, 0, L2CAP_SEGMENTATION_AND_REASSEMBLY_UNSEGMENTED_L2CAP_SDU); 573 log_info("I-Frame: control 0x%04x", control); 574 little_endian_store_16(acl_buffer, 8, control); 575 memcpy(&acl_buffer[8+2], &channel->tx_packets_data[index * channel->local_mtu], tx_state->len); 576 // send 577 return l2cap_send_prepared(channel->local_cid, 2 + tx_state->len); 578} 579static int l2cap_ertm_send(l2cap_channel_t * channel, uint8_t * data, uint16_t len){ 580 if (len > channel->remote_mtu){ 581 log_error("l2cap_send cid 0x%02x, data length exceeds remote MTU.", channel->local_cid); 582 return L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU; 583 } 584 // TODO: check tx_transmit 585 // store int tx packet buffer 586 int index = channel->tx_write_index; 587 l2cap_ertm_tx_packet_state_t * tx_state = &channel->tx_packets_state[index]; 588 tx_state->tx_seq = channel->next_tx_seq; 589 tx_state->len = len; 590 memcpy(&channel->tx_packets_data[index * channel->local_mtu], data, len); 591 // update 592 channel->next_tx_seq = l2cap_next_ertm_seq_nr(channel->next_tx_seq); 593 l2cap_ertm_next_tx_write_index(channel); 594 // test sendiging it right away 595 l2cap_ertm_send_information_frame(channel, index); 596 return 0; 597} |
|
563#endif 564 565// assumption - only on Classic connections 566int l2cap_send(uint16_t local_cid, uint8_t *data, uint16_t len){ | 598#endif 599 600// assumption - only on Classic connections 601int l2cap_send(uint16_t local_cid, uint8_t *data, uint16_t len){ |
567 | |
568 l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 569 if (!channel) { 570 log_error("l2cap_send no channel for cid 0x%02x", local_cid); 571 return -1; // TODO: define error 572 } 573 | 602 l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 603 if (!channel) { 604 log_error("l2cap_send no channel for cid 0x%02x", local_cid); 605 return -1; // TODO: define error 606 } 607 |
608#ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 609 // send in ERTM 610 if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 611 return l2cap_ertm_send(channel, data, len); 612 } 613#endif 614 |
|
574 if (len > channel->remote_mtu){ 575 log_error("l2cap_send cid 0x%02x, data length exceeds remote MTU.", local_cid); 576 return L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU; 577 } 578 579 if (!hci_can_send_acl_packet_now(channel->con_handle)){ 580 log_info("l2cap_send cid 0x%02x, cannot send", local_cid); 581 return BTSTACK_ACL_BUFFERS_FULL; 582 } 583 584 hci_reserve_packet_buffer(); 585 uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); | 615 if (len > channel->remote_mtu){ 616 log_error("l2cap_send cid 0x%02x, data length exceeds remote MTU.", local_cid); 617 return L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU; 618 } 619 620 if (!hci_can_send_acl_packet_now(channel->con_handle)){ 621 log_info("l2cap_send cid 0x%02x, cannot send", local_cid); 622 return BTSTACK_ACL_BUFFERS_FULL; 623 } 624 625 hci_reserve_packet_buffer(); 626 uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); |
586 587 int control_size = 0; 588#ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 589 // hack to send i-frames 590 if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 591 uint16_t control = l2cap_encanced_control_field_for_information_frame(channel->next_tx_seq, 0, 0, L2CAP_SEGMENTATION_AND_REASSEMBLY_UNSEGMENTED_L2CAP_SDU); 592 log_info("I-Frame: control 0x%04x", control); 593 little_endian_store_16(acl_buffer, 8, control); 594 channel->next_tx_seq = l2cap_next_ertm_seq_nr(channel->next_tx_seq); 595 control_size = 2; 596 } 597#endif 598 599 memcpy(&acl_buffer[8+control_size], data, len); 600 601 return l2cap_send_prepared(local_cid, len+control_size); | 627 memcpy(&acl_buffer[8], data, len); 628 return l2cap_send_prepared(local_cid, len); |
602} 603 604int l2cap_send_echo_request(hci_con_handle_t con_handle, uint8_t *data, uint16_t len){ 605 return l2cap_send_signaling_packet(con_handle, ECHO_REQUEST, 0x77, len, data); 606} 607 608static inline void channelStateVarSetFlag(l2cap_channel_t *channel, L2CAP_CHANNEL_STATE_VAR flag){ 609 channel->state_var = (L2CAP_CHANNEL_STATE_VAR) (channel->state_var | flag); --- 2327 unchanged lines hidden --- | 629} 630 631int l2cap_send_echo_request(hci_con_handle_t con_handle, uint8_t *data, uint16_t len){ 632 return l2cap_send_signaling_packet(con_handle, ECHO_REQUEST, 0x77, len, data); 633} 634 635static inline void channelStateVarSetFlag(l2cap_channel_t *channel, L2CAP_CHANNEL_STATE_VAR flag){ 636 channel->state_var = (L2CAP_CHANNEL_STATE_VAR) (channel->state_var | flag); --- 2327 unchanged lines hidden --- |