@@ -2061,42 +2061,10 @@ struct notify_data {
20612061 };
20622062};
20632063
2064- #if defined(CONFIG_BT_GATT_NOTIFY_MULTIPLE )
2065-
2066- static struct net_buf * nfy_mult [CONFIG_BT_MAX_CONN ];
2067-
2068- static int gatt_notify_mult_send (struct bt_conn * conn , struct net_buf * * buf )
2069- {
2070- int ret ;
2071-
2072- ret = bt_att_send (conn , * buf );
2073- if (ret < 0 ) {
2074- net_buf_unref (* buf );
2075- }
2076-
2077- * buf = NULL ;
2078-
2079- return ret ;
2080- }
2081-
2082- static void notify_mult_process (struct k_work * work )
2083- {
2084- int i ;
2085-
2086- /* Send to any connection with an allocated buffer */
2087- for (i = 0 ; i < ARRAY_SIZE (nfy_mult ); i ++ ) {
2088- struct net_buf * * buf = & nfy_mult [i ];
2089-
2090- if (* buf ) {
2091- struct bt_conn * conn = bt_conn_lookup_index (i );
2092-
2093- gatt_notify_mult_send (conn , buf );
2094- bt_conn_unref (conn );
2095- }
2096- }
2097- }
2064+ static bool gatt_find_by_uuid (struct notify_data * found ,
2065+ const struct bt_uuid * uuid );
20982066
2099- K_WORK_DEFINE ( nfy_mult_work , notify_mult_process );
2067+ #if defined( CONFIG_BT_GATT_NOTIFY_MULTIPLE )
21002068
21012069static bool gatt_cf_notify_multi (struct bt_conn * conn )
21022070{
@@ -2110,47 +2078,73 @@ static bool gatt_cf_notify_multi(struct bt_conn *conn)
21102078 return CF_NOTIFY_MULTI (cfg );
21112079}
21122080
2113- static int gatt_notify_mult (struct bt_conn * conn , uint16_t handle ,
2114- struct bt_gatt_notify_params * params )
2081+ static int gatt_notify_mult (struct bt_conn * conn , uint16_t num_params ,
2082+ struct bt_gatt_notify_params * params )
21152083{
2116- struct net_buf * * buf = & nfy_mult [ bt_conn_index ( conn )] ;
2084+ struct net_buf * buf ;
21172085 struct bt_att_notify_mult * nfy ;
2118-
2119- /* Check if we can fit more data into it, in case it doesn't fit send
2120- * the existing buffer and proceed to create a new one
2121- */
2122- if (* buf && ((net_buf_tailroom (* buf ) < sizeof (* nfy ) + params -> len ) ||
2123- !bt_att_tx_meta_data_match (* buf , params -> func , params -> user_data ))) {
2124- int ret ;
2125-
2126- ret = gatt_notify_mult_send (conn , buf );
2127- if (ret < 0 ) {
2128- return ret ;
2086+ struct notify_data data ;
2087+ uint16_t pdu_len = 0 ;
2088+
2089+ for (uint16_t i = 0 ; i < num_params ; i ++ ) {
2090+ data .attr = params [i ].attr ;
2091+ data .handle = bt_gatt_attr_get_handle (params [i ].attr );
2092+ /* Lookup UUID if it was given */
2093+ if (params [i ].uuid ) {
2094+ if (!gatt_find_by_uuid (& data , params [i ].uuid )) {
2095+ return - ENOENT ;
2096+ }
2097+ params [i ].attr = data .attr ;
2098+ } else {
2099+ if (!data .handle ) {
2100+ return - ENOENT ;
2101+ }
21292102 }
2130- }
21312103
2132- if (! * buf ) {
2133- * buf = bt_att_create_pdu ( conn , BT_ATT_OP_NOTIFY_MULT ,
2134- sizeof ( * nfy ) + params -> len );
2135- if (! * buf ) {
2136- return - ENOMEM ;
2104+ /* Confirm that the connection has the correct level of security */
2105+ if ( bt_gatt_check_perm ( conn , params [ i ]. attr ,
2106+ BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_READ_AUTHEN )) {
2107+ BT_WARN ( "Link is not encrypted" );
2108+ return - EPERM ;
21372109 }
2110+ /* Calculate the ATT_MULTIPLE_HANDLE_VALUE_NTF pdu length */
2111+ pdu_len += sizeof (* nfy ) + params [i ].len ;
2112+ if (pdu_len > UINT16_MAX ) {
2113+ return - EINVAL ;
2114+ }
2115+ }
21382116
2139- bt_att_set_tx_meta_data (* buf , params -> func , params -> user_data );
2117+ buf = bt_att_create_pdu (conn , BT_ATT_OP_NOTIFY_MULT , pdu_len );
2118+ if (!buf ) {
2119+ return - ENOMEM ;
21402120 }
21412121
2142- BT_DBG ( "handle 0x%04x len %u" , handle , params -> len );
2122+ bt_att_set_tx_meta_data ( buf , params [ 0 ]. func , params [ 0 ]. user_data );
21432123
2144- nfy = net_buf_add (* buf , sizeof (* nfy ));
2145- nfy -> handle = sys_cpu_to_le16 (handle );
2146- nfy -> len = sys_cpu_to_le16 (params -> len );
2124+ for (uint16_t i = 0 ; i < num_params ; i ++ ) {
2125+ data .handle = bt_gatt_attr_get_handle (params [i ].attr );
2126+ /* Check if attribute is a characteristic then adjust the handle */
2127+ if (!bt_uuid_cmp (params [i ].attr -> uuid , BT_UUID_GATT_CHRC )) {
2128+ struct bt_gatt_chrc * chrc = params [i ].attr -> user_data ;
21472129
2148- net_buf_add (* buf , params -> len );
2149- memcpy (nfy -> value , params -> data , params -> len );
2130+ if (!(chrc -> properties & BT_GATT_CHRC_NOTIFY )) {
2131+ return - EINVAL ;
2132+ }
2133+
2134+ data .handle = bt_gatt_attr_value_handle (params [i ].attr );
2135+ }
21502136
2151- k_work_submit ( & nfy_mult_work );
2137+ BT_DBG ( "handle 0x%04x len %u" , data . handle , params [ i ]. len );
21522138
2153- return 0 ;
2139+ nfy = net_buf_add (buf , sizeof (* nfy ));
2140+ nfy -> handle = sys_cpu_to_le16 (data .handle );
2141+ nfy -> len = sys_cpu_to_le16 (params [i ].len );
2142+
2143+ net_buf_add (buf , params [i ].len );
2144+ (void )memcpy (nfy -> value , params [i ].data , params [i ].len );
2145+ }
2146+
2147+ return bt_att_send (conn , buf , params [0 ].func , params [0 ].user_data );
21542148}
21552149#endif /* CONFIG_BT_GATT_NOTIFY_MULTIPLE */
21562150
@@ -2178,12 +2172,6 @@ static int gatt_notify(struct bt_conn *conn, uint16_t handle,
21782172 return - EPERM ;
21792173 }
21802174
2181- #if defined(CONFIG_BT_GATT_NOTIFY_MULTIPLE )
2182- if (gatt_cf_notify_multi (conn )) {
2183- return gatt_notify_mult (conn , handle , params );
2184- }
2185- #endif /* CONFIG_BT_GATT_NOTIFY_MULTIPLE */
2186-
21872175 buf = bt_att_create_pdu (conn , BT_ATT_OP_NOTIFY ,
21882176 sizeof (* nfy ) + params -> len );
21892177 if (!buf ) {
@@ -2539,23 +2527,44 @@ int bt_gatt_notify_cb(struct bt_conn *conn,
25392527}
25402528
25412529#if defined(CONFIG_BT_GATT_NOTIFY_MULTIPLE )
2530+
25422531int bt_gatt_notify_multiple (struct bt_conn * conn , uint16_t num_params ,
25432532 struct bt_gatt_notify_params * params )
25442533{
2545- int i , ret ;
2546-
25472534 __ASSERT (params , "invalid parameters\n" );
2548- __ASSERT (num_params , "invalid parameters\n" );
2549- __ASSERT (params -> attr , "invalid parameters\n" );
2535+ __ASSERT (num_params >= 2 , "invalid parameters\n" );
2536+ __ASSERT (params -> attr || params -> uuid , "invalid parameters\n" );
2537+ for (uint16_t i = 1 ; i < num_params ; i ++ ) {
2538+ __ASSERT (params [0 ].func == params [i ].func , "invalid parameters\n" );
2539+ __ASSERT (memcmp (params [0 ].user_data , params [i ].user_data , 1 ) == 0 ,
2540+ "invalid parameters\n" );
2541+ }
25502542
2551- for (i = 0 ; i < num_params ; i ++ ) {
2552- ret = bt_gatt_notify_cb (conn , & params [i ]);
2553- if (ret < 0 ) {
2554- return ret ;
2555- }
2543+ if (!atomic_test_bit (bt_dev .flags , BT_DEV_READY )) {
2544+ return - EAGAIN ;
25562545 }
25572546
2558- return 0 ;
2547+ if (conn && conn -> state != BT_CONN_CONNECTED ) {
2548+ return - ENOTCONN ;
2549+ }
2550+
2551+ #if defined(CONFIG_BT_GATT_ENFORCE_CHANGE_UNAWARE )
2552+ /* BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part G page 2350:
2553+ * Except for the Handle Value indication, the server shall not send
2554+ * notifications and indications to such a client until it becomes
2555+ * change-aware.
2556+ */
2557+ if (!bt_gatt_change_aware (conn , false)) {
2558+ return - EAGAIN ;
2559+ }
2560+ #endif
2561+
2562+ if (gatt_cf_notify_multi (conn )) {
2563+ return gatt_notify_mult (conn , num_params , params );
2564+ }
2565+
2566+ BT_ERR ("Multiple variable length notifications is not supported" );
2567+ return - EOPNOTSUPP ;
25592568}
25602569#endif /* CONFIG_BT_GATT_NOTIFY_MULTIPLE */
25612570
0 commit comments