Merge "Revert "Fix buffer overflow in GAP_ConnWriteData""
diff --git a/bta/hh/bta_hh_int.h b/bta/hh/bta_hh_int.h
index 74bcffc..70ad6a5 100644
--- a/bta/hh/bta_hh_int.h
+++ b/bta/hh/bta_hh_int.h
@@ -211,7 +211,7 @@
#define BTA_HH_GET_LE_DEV_HDL(x) (uint8_t)(((x) + 1) << 4)
/* check to see if th edevice handle is a LE device handle */
#define BTA_HH_IS_LE_DEV_HDL(x) ((x)&0xf0)
-#define BTA_HH_IS_LE_DEV_HDL_VALID(x) (((x) >> 4) <= BTA_HH_LE_MAX_KNOWN)
+#define BTA_HH_IS_LE_DEV_HDL_VALID(x) (((x) >> 4) <= BTA_HH_MAX_DEVICE)
#endif
/* device control block */
diff --git a/stack/l2cap/l2c_fcr.cc b/stack/l2cap/l2c_fcr.cc
index bcf2ba6..090c55e 100644
--- a/stack/l2cap/l2c_fcr.cc
+++ b/stack/l2cap/l2c_fcr.cc
@@ -1789,77 +1789,45 @@
return (p_xmit);
}
-/*******************************************************************************
- *
- * Function l2c_lcc_get_next_xmit_sdu_seg
- *
- * Description Get the next SDU segment to transmit for LE connection
- * oriented channel
- *
- * Returns pointer to buffer with segment or NULL
- *
- ******************************************************************************/
+/** Get the next PDU to transmit for LE connection oriented channel. Returns
+ * pointer to buffer with PDU. |last_piece_of_sdu| will be set to true, if
+ * returned PDU is last piece from this SDU.*/
BT_HDR* l2c_lcc_get_next_xmit_sdu_seg(tL2C_CCB* p_ccb,
- uint16_t max_packet_length) {
- bool first_seg = false; /* The segment is the first part of data */
- bool last_seg = false; /* The segment is the last part of data */
- uint16_t no_of_bytes_to_send = 0;
- uint16_t sdu_len = 0;
- BT_HDR *p_buf, *p_xmit;
- uint8_t* p;
+ bool* last_piece_of_sdu) {
uint16_t max_pdu = p_ccb->peer_conn_cfg.mps;
- p_buf = (BT_HDR*)fixed_queue_try_peek_first(p_ccb->xmit_hold_q);
+ BT_HDR* p_buf = (BT_HDR*)fixed_queue_try_peek_first(p_ccb->xmit_hold_q);
+ bool first_pdu = (p_buf->event == 0) ? true : false;
- /* We are using the "event" field to tell is if we already started
- * segmentation */
- if (p_buf->event == 0) {
- first_seg = true;
- sdu_len = p_buf->len;
- if (p_buf->len <= (max_pdu - L2CAP_LCC_SDU_LENGTH)) {
- last_seg = true;
- no_of_bytes_to_send = p_buf->len;
- } else
- no_of_bytes_to_send = max_pdu - L2CAP_LCC_SDU_LENGTH;
- } else if (p_buf->len <= max_pdu) {
- last_seg = true;
- no_of_bytes_to_send = p_buf->len;
- } else {
- /* Middle Packet */
- no_of_bytes_to_send = max_pdu;
- }
+ uint16_t no_of_bytes_to_send = std::min(
+ p_buf->len,
+ (uint16_t)(first_pdu ? (max_pdu - L2CAP_LCC_SDU_LENGTH) : max_pdu));
+ bool last_pdu = (no_of_bytes_to_send == p_buf->len);
/* Get a new buffer and copy the data that can be sent in a PDU */
- if (first_seg)
- p_xmit = l2c_fcr_clone_buf(p_buf, L2CAP_LCC_OFFSET, no_of_bytes_to_send);
- else
- p_xmit = l2c_fcr_clone_buf(p_buf, L2CAP_MIN_OFFSET, no_of_bytes_to_send);
+ BT_HDR* p_xmit =
+ l2c_fcr_clone_buf(p_buf, first_pdu ? L2CAP_LCC_OFFSET : L2CAP_MIN_OFFSET,
+ no_of_bytes_to_send);
- if (p_xmit != NULL) {
- p_buf->event = p_ccb->local_cid;
- p_xmit->event = p_ccb->local_cid;
+ p_buf->event = p_ccb->local_cid;
+ p_xmit->event = p_ccb->local_cid;
- if (first_seg) {
- p_xmit->offset -= L2CAP_LCC_SDU_LENGTH; /* for writing the SDU length. */
- p = (uint8_t*)(p_xmit + 1) + p_xmit->offset;
- UINT16_TO_STREAM(p, sdu_len);
- p_xmit->len += L2CAP_LCC_SDU_LENGTH;
- }
-
- p_buf->len -= no_of_bytes_to_send;
- p_buf->offset += no_of_bytes_to_send;
-
- /* copy PBF setting */
- p_xmit->layer_specific = p_buf->layer_specific;
-
- } else /* Should never happen if the application has configured buffers
- correctly */
- {
- L2CAP_TRACE_ERROR("L2CAP - cannot get buffer, for segmentation");
- return (NULL);
+ if (first_pdu) {
+ p_xmit->offset -= L2CAP_LCC_SDU_LENGTH; /* for writing the SDU length. */
+ uint8_t* p = (uint8_t*)(p_xmit + 1) + p_xmit->offset;
+ UINT16_TO_STREAM(p, p_buf->len);
+ p_xmit->len += L2CAP_LCC_SDU_LENGTH;
}
- if (last_seg) {
+ p_buf->len -= no_of_bytes_to_send;
+ p_buf->offset += no_of_bytes_to_send;
+
+ /* copy PBF setting */
+ p_xmit->layer_specific = p_buf->layer_specific;
+
+ if (last_piece_of_sdu) *last_piece_of_sdu = last_pdu;
+
+ if (last_pdu) {
p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
osi_free(p_buf);
}
@@ -1869,7 +1837,7 @@
p_xmit->len += L2CAP_PKT_OVERHEAD;
/* Set the pointer to the beginning of the data */
- p = (uint8_t*)(p_xmit + 1) + p_xmit->offset;
+ uint8_t* p = (uint8_t*)(p_xmit + 1) + p_xmit->offset;
/* Note: if FCS has to be included then the length is recalculated later */
UINT16_TO_STREAM(p, p_xmit->len - L2CAP_PKT_OVERHEAD);
diff --git a/stack/l2cap/l2c_int.h b/stack/l2cap/l2c_int.h
index bf2ec61..a6e111e 100644
--- a/stack/l2cap/l2c_int.h
+++ b/stack/l2cap/l2c_int.h
@@ -739,7 +739,7 @@
extern void l2c_fcr_start_timer(tL2C_CCB* p_ccb);
extern void l2c_lcc_proc_pdu(tL2C_CCB* p_ccb, BT_HDR* p_buf);
extern BT_HDR* l2c_lcc_get_next_xmit_sdu_seg(tL2C_CCB* p_ccb,
- uint16_t max_packet_length);
+ bool* last_piece_of_sdu);
/* Configuration negotiation */
extern uint8_t l2c_fcr_chk_chan_modes(tL2C_CCB* p_ccb);
diff --git a/stack/l2cap/l2c_utils.cc b/stack/l2cap/l2c_utils.cc
index acd87e6..efe2188 100644
--- a/stack/l2cap/l2c_utils.cc
+++ b/stack/l2cap/l2c_utils.cc
@@ -3286,10 +3286,16 @@
L2CAP_TRACE_DEBUG("%s No credits to send packets", __func__);
return NULL;
}
- p_buf = l2c_lcc_get_next_xmit_sdu_seg(p_ccb, 0);
- if (p_buf == NULL) return (NULL);
+ bool last_piece_of_sdu = false;
+ p_buf = l2c_lcc_get_next_xmit_sdu_seg(p_ccb, &last_piece_of_sdu);
p_ccb->peer_conn_cfg.credits--;
+
+ if (last_piece_of_sdu) {
+ // TODO: send callback up the stack. Investigate setting p_cbi->cb to
+ // notify after controller ack send.
+ }
+
} else {
if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);