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 ---