diff --git a/ble/att.h b/ble/att.h
index 6c283681f..00f36fe0b 100644
--- a/ble/att.h
+++ b/ble/att.h
@@ -73,8 +73,8 @@ extern "C" {
 #define ATT_EXECUTE_WRITE_RESPONSE      0x19
 
 #define ATT_HANDLE_VALUE_NOTIFICATION   0x1b
-#define ATT_HANDLE_VALUE_CONFIRMATION   0x1c
 #define ATT_HANDLE_VALUE_INDICATION     0x1d
+#define ATT_HANDLE_VALUE_CONFIRMATION   0x1e
 
 
 #define ATT_WRITE_COMMAND               0x52
@@ -120,6 +120,14 @@ extern "C" {
 #define ATT_PROPERTY_AUTHORIZATION_REQUIRED  0x800
 // Encryption key size stored in upper 4 bits, 0 == no encryption, encryption key size - 1 otherwise
 
+// ATT Transaxtion Timeout of 30 seconds for Command/Response or Incidationc/Confirmation
+#define ATT_TRANSACTION_TIMEOUT_MS     30000
+
+#define ATT_TRANSACTION_MODE_NONE      0x0
+#define ATT_TRANSACTION_MODE_ACTIVE    0x1
+#define ATT_TRANSACTION_MODE_EXECUTE   0x2
+#define ATT_TRANSACTION_MODE_CANCEL    0x3
+
 // MARK: GATT UUIDs
 #define GATT_PRIMARY_SERVICE_UUID      0x2800
 #define GATT_SECONDARY_SERVICE_UUID    0x2801
@@ -129,10 +137,6 @@ extern "C" {
 #define GAP_SERVICE_UUID               0x1800
 #define GAP_DEVICE_NAME_UUID           0x2a00
 
-#define ATT_TRANSACTION_MODE_NONE      0x0
-#define ATT_TRANSACTION_MODE_ACTIVE    0x1
-#define ATT_TRANSACTION_MODE_EXECUTE   0x2
-#define ATT_TRANSACTION_MODE_CANCEL    0x3
 
 typedef struct att_connection {
     uint16_t mtu;
diff --git a/ble/att_server.c b/ble/att_server.c
index b1972f7a0..053d93195 100644
--- a/ble/att_server.c
+++ b/ble/att_server.c
@@ -81,8 +81,31 @@ static uint8_t   att_request_buffer[28];
 static int       att_ir_central_device_db_index = -1;
 static int       att_ir_lookup_active = 0;
 
+static int       att_handle_value_indication_handle = 0;    
+static timer_source_t att_handle_value_indication_timer;
+
 static btstack_packet_handler_t att_client_packet_handler = NULL;
 
+
+static int att_handle_value_indication_notify_client(uint8_t status, uint16_t client_handle, uint16_t attribute_handle){
+    uint8_t event[7];
+    int pos = 0;
+    event[pos++] = ATT_HANDLE_VALUE_INDICATION_COMPLETE;
+    event[pos++] = sizeof(event) - 2;
+    event[pos++] = status;
+    bt_store_16(event, pos, client_handle);
+    pos += 2;
+    bt_store_16(event, pos, attribute_handle);
+    pos += 2;
+    (*att_client_packet_handler)(HCI_EVENT_PACKET, 0, &event[0], sizeof(event));
+}
+
+static void att_handle_value_indication_timeout(timer_source_t *ts){
+    uint16_t att_handle = att_handle_value_indication_handle;
+    att_handle_value_indication_handle = 0;    
+    att_handle_value_indication_notify_client(ATT_HANDLE_VALUE_INDICATION_TIMEOUT, att_request_handle, att_handle);
+}
+
 static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
     
     switch (packet_type) {
@@ -255,6 +278,15 @@ static void att_run(void){
 static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){
     if (packet_type != ATT_DATA_PACKET) return;
 
+    // handle value indication confirms
+    if (packet[0] == ATT_HANDLE_VALUE_CONFIRMATION && att_handle_value_indication_handle){
+        run_loop_remove_timer(&att_handle_value_indication_timer);
+        uint16_t att_handle = att_handle_value_indication_handle;
+        att_handle_value_indication_handle = 0;    
+        att_handle_value_indication_notify_client(0, att_request_handle, att_handle);
+        return;
+    }
+
     // check size
     if (size > sizeof(att_request_buffer)) return;
 
@@ -292,14 +324,24 @@ int  att_server_can_send(){
 	return hci_can_send_packet_now(HCI_ACL_DATA_PACKET);
 }
 
-void att_server_notify(uint16_t handle, uint8_t *value, uint16_t value_len){
+int att_server_notify(uint16_t handle, uint8_t *value, uint16_t value_len){
     uint8_t packet_buffer[att_connection.mtu];
     uint16_t size = att_prepare_handle_value_notification(&att_connection, handle, value, value_len, packet_buffer);
-	l2cap_send_connectionless(att_request_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, packet_buffer, size);
+	return l2cap_send_connectionless(att_request_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, packet_buffer, size);
 }
 
-void att_server_indicate(uint16_t handle, uint8_t *value, uint16_t value_len){
+int att_server_indicate(uint16_t handle, uint8_t *value, uint16_t value_len){
+    if (att_handle_value_indication_handle) return ATT_HANDLE_VALUE_INDICATION_IN_PORGRESS;
+    if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)) return BTSTACK_ACL_BUFFERS_FULL;
+
+    // track indication
+    att_handle_value_indication_handle = handle;
+    run_loop_set_timer_handler(&att_handle_value_indication_timer, att_handle_value_indication_timeout);
+    run_loop_set_timer(&att_handle_value_indication_timer, ATT_TRANSACTION_TIMEOUT_MS);
+    run_loop_add_timer(&att_handle_value_indication_timer);
+
     uint8_t packet_buffer[att_connection.mtu];
     uint16_t size = att_prepare_handle_value_indication(&att_connection, handle, value, value_len, packet_buffer);
 	l2cap_send_connectionless(att_request_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, packet_buffer, size);
+    return 0;
 }
diff --git a/ble/att_server.h b/ble/att_server.h
index b9ae9acac..bd971d316 100644
--- a/ble/att_server.h
+++ b/ble/att_server.h
@@ -65,13 +65,15 @@ int  att_server_can_send();
 
 /*
  * @brief notify client about attribute value change
+ * @ereturns 0 if ok, error otherwise
  */
-void att_server_notify(uint16_t handle, uint8_t *value, uint16_t value_len);
+int att_server_notify(uint16_t handle, uint8_t *value, uint16_t value_len);
 
 /*
  * @brief indicate value change to client. client is supposed to reply with an indication_response
+ * @ereturns 0 if ok, error otherwise
  */
-void att_server_indicate(uint16_t handle, uint8_t *value, uint16_t value_len);
+int att_server_indicate(uint16_t handle, uint8_t *value, uint16_t value_len);
 
 #if defined __cplusplus
 }
diff --git a/example/libusb/ble_peripheral.c b/example/libusb/ble_peripheral.c
index 851a32ad2..481889286 100644
--- a/example/libusb/ble_peripheral.c
+++ b/example/libusb/ble_peripheral.c
@@ -83,11 +83,27 @@ static void  heartbeat_handler(struct timer *ts){
 } 
 
 static void app_run(){
-    if (!client_configuration || !update_client) return;
+    if (!update_client) return;
     if (!att_server_can_send()) return;
-    printf("Notify value %u\n", counter);
+
+    int result = -1;
+    switch (client_configuration){
+        case 0x01:
+            printf("Notify value %u\n", counter);
+            result = att_server_notify(0x0f, &counter, 1);
+            break;
+        case 0x02:
+            printf("Indicate value %u\n", counter);
+            result = att_server_indicate(0x0f, &counter, 1);
+            break;
+        default:
+            return;
+    }        
+    if (result){
+        printf("Error 0x%02x\n", result);
+        return;        
+    }
     update_client = 0;
-    att_server_notify(0x0f, &counter, 1);
 }
 
 // write requests
@@ -177,6 +193,10 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
                     sm_authorization_grant(event->addr_type, event->address);
                     break;
                 }
+                case ATT_HANDLE_VALUE_INDICATION_COMPLETE:
+                    printf("ATT_HANDLE_VALUE_INDICATION_COMPLETE status %u\n", packet[2]);
+                    break;
+
                 default:
                     break;
             }
diff --git a/include/btstack/hci_cmds.h b/include/btstack/hci_cmds.h
index 66f124d88..c0a1fb8e8 100644
--- a/include/btstack/hci_cmds.h
+++ b/include/btstack/hci_cmds.h
@@ -228,6 +228,9 @@ extern "C" {
 #define GATT_CHARACTERISTIC_QUERY_RESULT				   0xA4
 #define GATT_CHARACTERISTIC_QUERY_COMPLETE    			   0xA5
 
+// data: event(8), len(8), status (8), hci_handle (16), attribute_handle (16)
+#define ATT_HANDLE_VALUE_INDICATION_COMPLETE        	   0xAF
+
 // data: event(8), address_type(8), address (48), [number(32)]
 #define SM_JUST_WORKS_REQUEST							   0xb0
 #define SM_JUST_WORKS_CANCEL							   0xb1 
@@ -241,6 +244,8 @@ extern "C" {
 #define SM_AUTHORIZATION_REQUEST						   0xb9
 #define SM_AUTHORIZATION_RESULT							   0xba
 
+// ATT 
+
 // last error code in 2.1 is 0x38 - we start with 0x50 for BTstack errors
 
 #define BTSTACK_CONNECTION_TO_BTDAEMON_FAILED              0x50
@@ -278,6 +283,9 @@ extern "C" {
 #define SDP_HANDLE_ALREADY_REGISTERED                      0x80
 #define SDP_QUERY_INCOMPLETE                               0x81
  
+#define ATT_HANDLE_VALUE_INDICATION_IN_PORGRESS 		   0x90 
+#define ATT_HANDLE_VALUE_INDICATION_TIMEOUT				   0x91
+
 /**
  * Default INQ Mode
  */