@@ -1089,8 +1089,9 @@ ble_att_svr_fill_type_value(uint16_t conn_handle,
10891089 uint16_t mtu , uint8_t * out_att_err )
10901090{
10911091 struct ble_att_svr_entry * ha ;
1092- uint8_t buf [ 16 ] ;
1092+ struct os_mbuf * attr_om ;
10931093 uint16_t attr_len ;
1094+ uint16_t req_val_len ;
10941095 uint16_t first ;
10951096 uint16_t prev ;
10961097 int any_entries ;
@@ -1100,6 +1101,17 @@ ble_att_svr_fill_type_value(uint16_t conn_handle,
11001101 prev = 0 ;
11011102 rc = 0 ;
11021103
1104+ /* Length of the attribute value in the request. */
1105+ req_val_len = OS_MBUF_PKTLEN (rxom ) -
1106+ sizeof (struct ble_att_find_type_value_req );
1107+
1108+ /* Allocate a temporary mbuf for reading attribute values. */
1109+ attr_om = ble_hs_mbuf_l2cap_pkt ();
1110+ if (attr_om == NULL ) {
1111+ * out_att_err = BLE_ATT_ERR_INSUFFICIENT_RES ;
1112+ return BLE_HS_ENOMEM ;
1113+ }
1114+
11031115 /* Iterate through the attribute list, keeping track of the current
11041116 * matching group. For each attribute entry, determine if data needs to be
11051117 * written to the response.
@@ -1141,15 +1153,20 @@ ble_att_svr_fill_type_value(uint16_t conn_handle,
11411153 * determine if this attribute matches.
11421154 */
11431155 if (ble_uuid_cmp (ha -> ha_uuid , & attr_type .u ) == 0 ) {
1144- rc = ble_att_svr_read_flat (conn_handle , ha , 0 , sizeof buf , buf ,
1145- & attr_len , out_att_err );
1156+ /* Read attribute value into temporary mbuf. */
1157+ os_mbuf_adj (attr_om , OS_MBUF_PKTLEN (attr_om ));
1158+ rc = ble_att_svr_read (conn_handle , ha , 0 , attr_om , out_att_err );
11461159 if (rc != 0 ) {
11471160 goto done ;
11481161 }
1149- /* value is at the end of req */
1150- rc = os_mbuf_cmpf (rxom , sizeof (struct ble_att_find_type_value_req ),
1151- buf , attr_len );
1152- if (rc == 0 ) {
1162+
1163+ attr_len = OS_MBUF_PKTLEN (attr_om );
1164+
1165+ /* Compare attribute value with the value from the request. */
1166+ if (attr_len == req_val_len &&
1167+ os_mbuf_cmpm (rxom ,
1168+ sizeof (struct ble_att_find_type_value_req ),
1169+ attr_om , 0 , attr_len ) == 0 ) {
11531170 first = ha -> ha_handle_id ;
11541171 prev = ha -> ha_handle_id ;
11551172 }
@@ -1170,6 +1187,8 @@ ble_att_svr_fill_type_value(uint16_t conn_handle,
11701187 }
11711188
11721189done :
1190+ os_mbuf_free_chain (attr_om );
1191+
11731192 any_entries = OS_MBUF_PKTHDR (txom )-> omp_len >
11741193 BLE_ATT_FIND_TYPE_VALUE_RSP_BASE_SZ ;
11751194 if (rc == 0 && !any_entries ) {
@@ -1293,9 +1312,10 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, uint16_t cid,
12931312 struct ble_att_read_type_rsp * rsp ;
12941313 struct ble_att_svr_entry * entry ;
12951314 struct os_mbuf * txom ;
1315+ struct os_mbuf * attr_om ;
12961316 uint16_t attr_len ;
1317+ uint16_t max_attr_len ;
12971318 uint16_t mtu ;
1298- uint8_t buf [19 ];
12991319 int entry_written ;
13001320 int txomlen ;
13011321 int prev_attr_len ;
@@ -1306,6 +1326,7 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, uint16_t cid,
13061326 * err_handle = start_handle ;
13071327 entry_written = 0 ;
13081328 prev_attr_len = 0 ;
1329+ attr_om = NULL ;
13091330
13101331 /* Just reuse the request buffer for the response. */
13111332 txom = * rxom ;
@@ -1326,6 +1347,21 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, uint16_t cid,
13261347
13271348 mtu = ble_att_mtu_by_cid (conn_handle , cid );
13281349
1350+ /* Per Core Spec: max attribute value length is min(ATT_MTU - 4, 253). */
1351+ max_attr_len = mtu - 4 ;
1352+ if (max_attr_len > 253 ) {
1353+ max_attr_len = 253 ;
1354+ }
1355+
1356+ /* Allocate a temporary mbuf for reading attribute values. */
1357+ attr_om = ble_hs_mbuf_l2cap_pkt ();
1358+ if (attr_om == NULL ) {
1359+ * att_err = BLE_ATT_ERR_INSUFFICIENT_RES ;
1360+ * err_handle = 0 ;
1361+ rc = BLE_HS_ENOMEM ;
1362+ goto done ;
1363+ }
1364+
13291365 /* Find all matching attributes, writing a record for each. */
13301366 entry = NULL ;
13311367 while (1 ) {
@@ -1336,15 +1372,17 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, uint16_t cid,
13361372 }
13371373
13381374 if (entry -> ha_handle_id >= start_handle ) {
1339- rc = ble_att_svr_read_flat (conn_handle , entry , 0 , sizeof buf , buf ,
1340- & attr_len , att_err );
1375+ /* Read attribute value into temporary mbuf. */
1376+ os_mbuf_adj (attr_om , OS_MBUF_PKTLEN (attr_om ));
1377+ rc = ble_att_svr_read (conn_handle , entry , 0 , attr_om , att_err );
13411378 if (rc != 0 ) {
13421379 * err_handle = entry -> ha_handle_id ;
13431380 goto done ;
13441381 }
13451382
1346- if (attr_len > mtu - 4 ) {
1347- attr_len = mtu - 4 ;
1383+ attr_len = OS_MBUF_PKTLEN (attr_om );
1384+ if (attr_len > max_attr_len ) {
1385+ attr_len = max_attr_len ;
13481386 }
13491387
13501388 if (prev_attr_len == 0 ) {
@@ -1367,12 +1405,14 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, uint16_t cid,
13671405 }
13681406
13691407 data -> handle = htole16 (entry -> ha_handle_id );
1370- memcpy ( data -> value , buf , attr_len );
1408+ os_mbuf_copydata ( attr_om , 0 , attr_len , data -> value );
13711409 entry_written = 1 ;
13721410 }
13731411 }
13741412
13751413done :
1414+ os_mbuf_free_chain (attr_om );
1415+
13761416 if (!entry_written ) {
13771417 /* No matching attributes. */
13781418 if (* att_err == 0 ) {
0 commit comments