@@ -2126,6 +2126,142 @@ TEST_CASE_SELF(ble_att_svr_test_unsupported_req)
21262126 ble_att_svr_test_assert_mbufs_freed ();
21272127}
21282128
2129+ /**
2130+ * Tests that Read By Type and Find By Type Value work correctly with attribute
2131+ * values larger than the old hardcoded buffer limits (19 and 16 bytes
2132+ * respectively). Verifies proper truncation per Core Spec 3.4.4.2:
2133+ * max value length = min(ATT_MTU - 4, 253).
2134+ */
2135+ TEST_CASE_SELF (ble_att_svr_test_large_value )
2136+ {
2137+ static uint8_t large_val [128 ];
2138+ uint16_t conn_handle ;
2139+ uint16_t mtu ;
2140+ uint16_t expected_len ;
2141+ int rc ;
2142+ int i ;
2143+
2144+ /* Fill test buffer with a recognizable pattern. */
2145+ for (i = 0 ; i < (int )sizeof (large_val ); i ++ ) {
2146+ large_val [i ] = i ;
2147+ }
2148+
2149+ /***
2150+ * Read By Type with large attribute value (MTU = 260).
2151+ * max value = min(260 - 4, 253) = 253, but our value is 128 bytes so
2152+ * the full value should be returned without truncation.
2153+ */
2154+ mtu = 260 ;
2155+ conn_handle = ble_att_svr_test_misc_init (mtu );
2156+
2157+ ble_att_svr_test_attr_r_1 = large_val ;
2158+ ble_att_svr_test_attr_r_1_len = sizeof (large_val );
2159+
2160+ /* Register a primary service attribute with the r_1 access callback. */
2161+ ble_att_svr_test_misc_register_uuid (
2162+ BLE_UUID16_DECLARE (BLE_ATT_UUID_PRIMARY_SERVICE ),
2163+ HA_FLAG_PERM_RW , 1 , ble_att_svr_test_misc_attr_fn_r_1 );
2164+
2165+ /* Read by type: value is 128 bytes, fits within min(256, 253) = 253. */
2166+ rc = ble_hs_test_util_rx_att_read_type_req16 (conn_handle , 1 , 0xffff ,
2167+ BLE_ATT_UUID_PRIMARY_SERVICE );
2168+ TEST_ASSERT (rc == 0 );
2169+ ble_att_svr_test_misc_verify_tx_read_type_rsp (
2170+ ((struct ble_att_svr_test_type_entry []) { {
2171+ .handle = 1 ,
2172+ .value = large_val ,
2173+ .value_len = sizeof (large_val ),
2174+ }, {
2175+ .handle = 0 ,
2176+ } }));
2177+
2178+ /***
2179+ * Read By Type with value truncated by MTU.
2180+ * MTU = 64, max value = min(64 - 4, 253) = 60. Value is 128 bytes,
2181+ * so response should contain only the first 60 bytes.
2182+ */
2183+ mtu = 64 ;
2184+ conn_handle = ble_att_svr_test_misc_init (mtu );
2185+
2186+ ble_att_svr_test_attr_r_1 = large_val ;
2187+ ble_att_svr_test_attr_r_1_len = sizeof (large_val );
2188+
2189+ ble_att_svr_test_misc_register_uuid (
2190+ BLE_UUID16_DECLARE (BLE_ATT_UUID_PRIMARY_SERVICE ),
2191+ HA_FLAG_PERM_RW , 1 , ble_att_svr_test_misc_attr_fn_r_1 );
2192+
2193+ expected_len = mtu - 4 ; /* 60 */
2194+
2195+ rc = ble_hs_test_util_rx_att_read_type_req16 (conn_handle , 1 , 0xffff ,
2196+ BLE_ATT_UUID_PRIMARY_SERVICE );
2197+ TEST_ASSERT (rc == 0 );
2198+ ble_att_svr_test_misc_verify_tx_read_type_rsp (
2199+ ((struct ble_att_svr_test_type_entry []) { {
2200+ .handle = 1 ,
2201+ .value = large_val ,
2202+ .value_len = expected_len ,
2203+ }, {
2204+ .handle = 0 ,
2205+ } }));
2206+
2207+ /***
2208+ * Find By Type Value with large attribute value (> 16 bytes).
2209+ * The request value must match the full attribute value for a hit.
2210+ */
2211+ mtu = 260 ;
2212+ conn_handle = ble_att_svr_test_misc_init (mtu );
2213+
2214+ ble_att_svr_test_attr_r_1 = large_val ;
2215+ ble_att_svr_test_attr_r_1_len = sizeof (large_val );
2216+
2217+ ble_att_svr_test_misc_register_uuid (
2218+ BLE_UUID16_DECLARE (BLE_ATT_UUID_PRIMARY_SERVICE ),
2219+ HA_FLAG_PERM_RW , 1 , ble_att_svr_test_misc_attr_fn_r_1 );
2220+
2221+ /* Search with the correct 128-byte value: should match. */
2222+ rc = ble_hs_test_util_rx_att_find_type_value_req (
2223+ conn_handle , 1 , 0xffff , BLE_ATT_UUID_PRIMARY_SERVICE ,
2224+ large_val , sizeof (large_val ));
2225+ TEST_ASSERT (rc == 0 );
2226+ ble_att_svr_test_misc_verify_tx_find_type_value_rsp (
2227+ ((struct ble_att_svr_test_type_value_entry []) { {
2228+ .first = 1 ,
2229+ .last = 1 ,
2230+ }, {
2231+ .first = 0 ,
2232+ } }));
2233+
2234+ /***
2235+ * Find By Type Value with wrong large value: should not match.
2236+ */
2237+ {
2238+ uint8_t wrong_val [128 ];
2239+ memcpy (wrong_val , large_val , sizeof (wrong_val ));
2240+ wrong_val [64 ] ^= 0xff ; /* Flip one byte in the middle. */
2241+
2242+ rc = ble_hs_test_util_rx_att_find_type_value_req (
2243+ conn_handle , 1 , 0xffff , BLE_ATT_UUID_PRIMARY_SERVICE ,
2244+ wrong_val , sizeof (wrong_val ));
2245+ TEST_ASSERT (rc != 0 );
2246+ ble_hs_test_util_verify_tx_err_rsp (
2247+ BLE_ATT_OP_FIND_TYPE_VALUE_REQ , 1 ,
2248+ BLE_ATT_ERR_ATTR_NOT_FOUND );
2249+ }
2250+
2251+ /***
2252+ * Find By Type Value with length mismatch: should not match.
2253+ */
2254+ rc = ble_hs_test_util_rx_att_find_type_value_req (
2255+ conn_handle , 1 , 0xffff , BLE_ATT_UUID_PRIMARY_SERVICE ,
2256+ large_val , 64 );
2257+ TEST_ASSERT (rc != 0 );
2258+ ble_hs_test_util_verify_tx_err_rsp (
2259+ BLE_ATT_OP_FIND_TYPE_VALUE_REQ , 1 ,
2260+ BLE_ATT_ERR_ATTR_NOT_FOUND );
2261+
2262+ ble_att_svr_test_assert_mbufs_freed ();
2263+ }
2264+
21292265TEST_SUITE (ble_att_svr_suite )
21302266{
21312267 ble_att_svr_test_mtu ();
@@ -2143,4 +2279,5 @@ TEST_SUITE(ble_att_svr_suite)
21432279 ble_att_svr_test_indicate ();
21442280 ble_att_svr_test_oom ();
21452281 ble_att_svr_test_unsupported_req ();
2282+ ble_att_svr_test_large_value ();
21462283}
0 commit comments