[Bluez HAL] Adapt GATT Server 14/124914/1
authorAnupam Roy <anupam.r@samsung.com>
Tue, 11 Apr 2017 14:07:53 +0000 (19:37 +0530)
committerAnupam Roy <anupam.r@samsung.com>
Thu, 13 Apr 2017 04:39:23 +0000 (10:09 +0530)
This patch adds support of GATT server
operations in Bluez HAL

Change-Id: I358867fc83f35c9a37a60191fa8e649a8ed7e966
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
13 files changed:
bt-oal/bluez_hal/hardware/bt_gatt_server.h
bt-oal/bluez_hal/inc/bt-hal-msg.h
bt-oal/bluez_hal/inc/bt-hal-utils.h
bt-oal/bluez_hal/src/bt-hal-adapter-dbus-handler.c
bt-oal/bluez_hal/src/bt-hal-adapter-le.c
bt-oal/bluez_hal/src/bt-hal-adapter-le.h
bt-oal/bluez_hal/src/bt-hal-dbus-common-utils.c
bt-oal/bluez_hal/src/bt-hal-dbus-common-utils.h
bt-oal/bluez_hal/src/bt-hal-event-receiver.c
bt-oal/bluez_hal/src/bt-hal-gatt-server.c
bt-oal/bluez_hal/src/bt-hal-gatt-server.h
bt-oal/bluez_hal/src/bt-hal-gatt.c
bt-oal/bluez_hal/src/bt-hal-utils.c

index 8bb0ac6..c05272c 100644 (file)
@@ -107,6 +107,13 @@ typedef void (*service_deleted_callback)(int status, int server_if,
  */
 typedef void (*indication_confirmation_callback) ( int conn_id, int trans_id, int attr_handle, bt_bdaddr_t *bda);
 
+#ifdef TIZEN_BT_HAL
+/**
+ * Callback invoked when indication confirmation
+ */
+typedef void (*notification_enabled_callback) (int conn_id, int trans_id, int attr_handle, bool notify, bt_bdaddr_t *bda);
+#endif
+
 /**
  * Callback invoked when a remote device has requested to read a characteristic
  * or descriptor. The application must respond by calling send_response
@@ -173,6 +180,9 @@ typedef struct {
        multi_adv_data_callback         multi_adv_data_cb;
        multi_adv_disable_callback      multi_adv_disable_cb;
        mtu_changed_callback            mtu_changed_cb;
+#ifdef TIZEN_BT_HAL
+       notification_enabled_callback   notif_enabled_cb;
+#endif
 } btgatt_server_callbacks_t;
 
 /** Represents the standard BT-GATT server interface. */
@@ -224,6 +234,10 @@ typedef struct {
        bt_status_t (*send_response)(int conn_id, int trans_id,
                        int status, btgatt_response_t *response);
 
+       /** Update GATT server attribute value */
+       bt_status_t (*update_att_value)(int server_if, int attribute_handle,
+                int value_length, char* att_value);
+
        /** Start or stop advertisements to listen for incoming connections */
        bt_status_t (*listen)(int server_if, bool start);
 
index b0ac5ee..3fe509f 100644 (file)
@@ -493,4 +493,94 @@ struct hal_ev_gatt_client_scan_result {
        uint8_t  adv_data[0];
 } __attribute__((packed));
 
+#define HAL_EV_GATT_SERVICE_ADDED              0xAD
+struct hal_ev_gatt_service_added {
+        uint32_t status;
+        uint32_t server_instance;
+       uint8_t  is_primary;
+       uint8_t svc_uuid[16];
+        uint32_t service_handle;
+} __attribute__((packed));
+
+#define HAL_EV_GATT_CHAR_ADDED                 0xAE
+struct hal_ev_gatt_char_added {
+        uint32_t status;
+        uint32_t server_instance;
+        uint32_t service_handle;
+        uint32_t char_handle;
+       uint8_t char_uuid[16];
+} __attribute__((packed));
+
+#define HAL_EV_GATT_DESC_ADDED                 0xAF
+struct hal_ev_gatt_desc_added {
+        uint32_t status;
+        uint32_t server_instance;
+        uint32_t service_handle;
+        uint32_t desc_handle;
+       uint8_t desc_uuid[16];
+} __attribute__((packed));
+
+#define HAL_EV_GATT_SERVICE_STARTED            0xB0
+struct hal_ev_gatt_service_started {
+        uint32_t status;
+        uint32_t server_instance;
+        uint32_t service_handle;
+} __attribute__((packed));
+
+#define HAL_EV_GATT_SERVICE_DELETED            0xB1
+struct hal_ev_gatt_service_deleted {
+        uint32_t status;
+        uint32_t server_instance;
+        uint32_t service_handle;
+} __attribute__((packed));
+
+#define HAL_EV_GATT_SERVER_CONNECTED           0xB2
+struct hal_ev_gatt_server_connected {
+        uint32_t conn_id;
+        uint32_t server_instance;
+        uint8_t connected;
+       uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_EV_GATT_READ_REQUESTED             0xB3
+struct hal_ev_gatt_server_read_req {
+        uint32_t conn_id;
+        uint32_t trans_id;
+       uint8_t bdaddr[6];
+        uint32_t att_handle;
+        uint32_t offset;
+        uint8_t is_long;
+} __attribute__((packed));
+
+#define HAL_EV_GATT_WRITE_REQUESTED            0xB4
+struct hal_ev_gatt_server_write_req {
+        uint32_t conn_id;
+        uint32_t trans_id;
+       uint8_t bdaddr[6];
+        uint32_t att_handle;
+        uint32_t offset;
+        uint32_t length;
+        uint8_t need_rsp;
+        uint8_t is_prep;
+        uint8_t value[0];
+} __attribute__((packed));
+
+#define HAL_EV_GATT_INDICATE_CFM               0xB5
+struct hal_ev_gatt_server_indicate_cfm {
+        uint32_t conn_id;
+        uint32_t trans_id;
+        uint32_t att_handle;
+       uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#ifdef TIZEN_BT_HAL
+#define HAL_EV_GATT_NOTIFICATION_CHANGE                0xB6
+struct hal_ev_gatt_server_notifcation_change {
+        uint32_t conn_id;
+        uint32_t trans_id;
+        uint32_t att_handle;
+       uint8_t notify;
+       uint8_t bdaddr[6];
+} __attribute__((packed));
+#endif
 #endif //_BT_HAL_MSG_H_
index 1408187..1a04061 100644 (file)
@@ -30,6 +30,8 @@
 #define BT_HAL_UUID_32     4
 #define BT_HAL_UUID_128    16
 
+#define CASE_RETURN_STR(const) case const: return #const;
+
 static const char BT_BASE_UUID[BT_HAL_UUID_128] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
        0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
@@ -60,6 +62,352 @@ static const char BASE_UUID_CONVERTED[BT_HAL_UUID_128] = {
 #define BT_HAL_HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
 #define BT_HAL_SAP_UUID_OLD "a49eb41e-cb06-495c-9f4f-bb80a90cdf00"
 #define BT_HAL_SAP_UUID_NEW "a49eb41e-cb06-495c-9f4f-aa80a90cdf4a"
+// List of Protocols
+#define BASE                                    0x0000          //Base
+#define SDP                                     0x0001          //Bluetooth Core Specification
+#define UDP                                     0x0002          //[NO USE BY PROFILES]
+#define RFCOMM                                  0x0003          //RFCOMM with TS 07.10
+#define TCP                                     0x0004          //[NO USE BY PROFILES]
+#define TCS_BIN                                 0x0005          //Telephony Control Specification / TCS Binary [DEPRECATED]
+#define TCS_AT                                  0x0006          //[NO USE BY PROFILES]
+#define ATT                                     0x0007          //Attribute Protocol
+#define OBEX                                    0x0008          //IrDA Interoperability
+#define IP                                      0x0009          //[NO USE BY PROFILES]
+#define FTP                                     0x000A          //[NO USE BY PROFILES]
+#define HTTP                                    0x000C          //[NO USE BY PROFILES]
+#define WSP                                     0x000E          //[NO USE BY PROFILES]
+#define BNEP                                    0x000F          //Bluetooth Network Encapsulation Protocol (BNEP)
+#define UPNP                                    0x0010          //Extended Service Discovery Profile (ESDP) [DEPRECATED]
+#define HIDP                                    0x0011          //Human Interface Device Profile (HID)
+#define HardcopyControlChannel                  0x0012          //Hardcopy Cable Replacement Profile (HCRP)
+#define HardcopyDataChannel                     0x0014          //See Hardcopy Cable Replacement Profile (HCRP)
+#define HardcopyNotification                    0x0016          //Hardcopy Cable Replacement Profile (HCRP)
+#define AVCTP                                   0x0017          //Audio/Video Control Transport Protocol (AVCTP)
+#define AVDTP                                   0x0019          //Audio/Video Distribution Transport Protocol (AVDTP)
+#define CMTP                                    0x001B          //Common ISDN Access Profile (CIP) [DEPRECATED]
+#define MCAPControlChannel                      0x001E          //Multi-Channel Adaptation Protocol (MCAP)
+#define MCAPDataChannel                         0x001F          //Multi-Channel Adaptation Protocol (MCAP)
+#define L2CAP                                   0x0100          //Bluetooth Core Specification
+
+//List of Services
+#define ServiceDiscoveryServerServiceClassID    0x1000          //Bluetooth Core Specification Service Class
+#define BrowseGroupDescriptorServiceClassID     0x1001          //Bluetooth Core Specification Service Class
+#define SerialPort                              0x1101          //Serial Port Profile (SPP)
+#define LANAccessUsingPPP                       0x1102          //LAN Access Profile
+#define DialupNetworking                        0x1103          //Dial-up Networking Profile (DUN)
+#define IrMCSync                                0x1104          //Synchronization Profile (SYNC)
+#define OBEXObjectPush                          0x1105          //Object Push Profile (OPP)
+#define OBEXFileTransfer                        0x1106          //File Transfer Profile (FTP)
+#define IrMCSyncCommand                         0x1107          //Synchronization Profile (SYNC)
+#define Headset                                 0x1108          //Headset Profile (HSP)
+#define CordlessTelephony                       0x1109          //Cordless Telephony Profile (CTP)
+#define AudioSource                             0x110A          //Advanced Audio Distribution Profile (A2DP) Service Class
+#define AudioSink                               0x110B          //Advanced Audio Distribution Profile (A2DP) Service Class
+#define AV_RemoteControlTarget                  0x110C          //Audio/Video Remote Control Profile (AVRCP) Service Class
+#define AdvancedAudioDistribution               0x110D          //Advanced Audio Distribution Profile (A2DP) Profile
+#define AV_RemoteControl                        0x110E          //Audio/Video Remote Control Profile (AVRCP)
+#define AV_RemoteControlController              0x110F          //Audio/Video Remote Control Profile (AVRCP)
+#define Intercom                                0x1110          //Intercom Profile (ICP)
+#define Fax                                     0x1111          //Fax Profile (FAX)
+#define Headset_Audio_Gateway                   0x1112          //Headset Profile (HSP) Service Class
+#define WAP                                     0x1113          //Interoperability Requirements for Bluetooth technology as a WAP, Bluetooth SIG [DEPRECATED] Service Class
+#define WAP_CLIENT                              0x1114          //Interoperability Requirements for Bluetooth technology as a WAP, Bluetooth SIG [DEPRECATED] Service Class
+#define PANU                                    0x1115          //Personal Area Networking Profile (PAN)
+#define NAP                                     0x1116          //Personal Area Networking Profile (PAN)
+#define GN                                      0x1117          //Personal Area Networking Profile (PAN)
+#define DirectPrinting                          0x1118          //Basic Printing Profile (BPP) Service Class
+#define ReferencePrinting                       0x1119          //See Basic Printing Profile (BPP) Service Class
+#define Basic_Imaging_Profile                   0x111A          //Basic Imaging Profile (BIP) Profile
+#define ImagingResponder                        0x111B          //Basic Imaging Profile (BIP) Service Class
+#define ImagingAutomaticArchive                 0x111C          //Basic Imaging Profile (BIP) Service Class
+#define ImagingReferencedObjects                0x111D          //Basic Imaging Profile (BIP) Service Class
+#define Handsfree                               0x111E          //Hands-Free Profile (HFP)
+#define HandsfreeAudioGateway                   0x111F          //Hands-free Profile (HFP) Service Class
+#define DirectPrintingReferenceObjectsService   0x1120          //Basic Printing Profile (BPP) Service Class
+#define ReflectedUI                             0x1121          //Basic Printing Profile (BPP) Service Class
+#define BasicPrinting                           0x1122          //Basic Printing Profile (BPP) Profile
+#define PrintingStatus                          0x1123          //Basic Printing Profile (BPP) Service Class
+#define HumanInterfaceDeviceService             0x1124          //Human Interface Device (HID)
+#define HardcopyCableReplacement                0x1125          //Hardcopy Cable Replacement Profile (HCRP) Profile
+#define HCR_Print                               0x1126          //Hardcopy Cable Replacement Profile (HCRP) Service Class
+#define HCR_Scan                                0x1127          //Hardcopy Cable Replacement Profile (HCRP) Service Class
+#define Common_ISDN_Access                      0x1128          //Common ISDN Access Profile (CIP)
+#define SIM_Access                              0x112D          //SIM Access Profile (SAP)
+#define Phonebook_Access_PCE                    0x112E          //Phonebook Access Profile (PBAP) Service Class
+#define Phonebook_Access_PSE                    0x112F          //Phonebook Access Profile (PBAP) Service Class
+#define Phonebook_Access                        0x1130          //Phonebook Access Profile (PBAP) Profile
+#define Headset_HS                              0x1131          //Headset Profile (HSP)
+#define Message_Access_Server                   0x1132          //Message Access Profile (MAP) Service Class
+#define Message_Notification_Server             0x1133          //Message Access Profile (MAP) Service Class
+#define Message_Access_Profile                  0x1134          //Message Access Profile (MAP) Profile
+#define GNSS                                    0x1135          //Global Navigation Satellite System Profile (GNSS) Profile
+#define GNSS_Server                             0x1136          // Global Navigation Satellite System Profile (GNSS) Service Class
+#define ThreeD_Display                          0x1137          //3D Synchronization Profile (3DSP) Service Class?
+#define ThreeD_Glasses                          0x1138          //3D Synchronization Profile (3DSP) ?Service Class
+#define ThreeD_Synchronization                  0x1139          //3D Synchronization Profile (3DSP) ?Profile
+#define MPS_Profile                             0x113A          //Multi-Profile Specification (MPS) ?Profile
+#define MPS_SC                                  0x113B          //Multi-Profile Specification (MPS) ?Service Class
+#define CTN_Access_Service                      0x113C          //Calendar, Task, and Notes (CTN) Profile ?Service Class
+#define CTN_Notification_Service                0x113D          //Calendar Tasks and Notes (CTN) Profile ?Service Class
+#define CTN_Profile                             0x113E          //Calendar Tasks and Notes (CTN) Profile ?Profile
+#define PnPInformation                          0x1200          //Device Identification (DID)
+#define GenericNetworking                       0x1201          //N/A Service Class
+#define GenericFileTransfer                     0x1202          //N/A Service Class
+#define GenericAudio                            0x1203          //N/A Service Class
+#define GenericTelephony                        0x1204          //N/A Service Class
+#define UPNP_Service                            0x1205          //Enhanced Service Discovery Profile (ESDP) [DEPRECATED] Service Class
+#define UPNP_IP_Service                         0x1206          //Enhanced Service Discovery Profile (ESDP) [DEPRECATED] Service Class
+#define ESDP_UPNP_IP_PAN                        0x1300          //Enhanced Service Discovery Profile (ESDP) [DEPRECATED] Service Class
+#define ESDP_UPNP_IP_LAP                        0x1301          //Enhanced Service Discovery Profile (ESDP)[DEPRECATED] Service Class
+#define ESDP_UPNP_L2CAP                         0x1302          //Enhanced Service Discovery Profile (ESDP)[DEPRECATED] Service Class
+#define VideoSource                             0x1303          //Video Distribution Profile (VDP) Service Class
+#define VideoSink                               0x1304          //Video Distribution Profile (VDP) Service Class
+#define VideoDistribution                       0x1305          //Video Distribution Profile (VDP) Profile
+#define HDP                                     0x1400          //Health Device Profile Profile
+#define HDP_Source                              0x1401          //Health Device Profile (HDP) Service Class
+#define HDP_Sink                                0x1402          //Health Device Profile (HDP) Service Class
+
+/* List of GATT Services UUID */
+#define Generic_Access                                                 0x1800                  //Generic Access Service
+#define Generic_Attribute                                              0x1801                  //Generic Attribute Service
+#define Immediate_Alert                                                        0x1802                  //Immediate Alert Service
+#define Link_Loss                                                              0x1803                  //Link Loss Service
+#define Tx_Power                                                               0x1804                  //Tx Power Service
+#define Current_Time                                                   0x1805                  //Current Time Service
+#define Reference_Time_Update                                  0x1806                  //Reference Time Update Service
+#define Next_Dst_Change                                                        0x1807                  //Next Destination Change Service
+#define Glucose                                                                        0x1808                  //Glucose Service
+#define Health_Thermometer                                             0x1809                  //Health Thermometer Service
+#define Device_Information                                             0x180A                  //Device Information Service
+#define Heart_Rate                                                             0x180D                  //Heart Rate Service
+#define Phone_Alert_Status                                             0x180E                  //Phone Alert Status Service
+#define Battery_Service                                                        0x180F                  //Battery Service
+#define Blood_Pressure                                                 0x1810                  //Blood Pressure Service
+#define Alert_Notification                                             0x1811                  //Alert Notification Service
+#define Human_Interface_Device                                 0x1812                  //HID Service
+#define Scan_Parameters                                                        0x1813                  //Scan Parameters Service
+#define Running_Speed_And_Cadence                              0x1814                  //Running Speed and Cadence Service
+#define Automation_IO                                                  0x1815                  //Automation IO Service
+#define Cycling_Speed_And_Cadence                              0x1816                  //Cycling Speed and Cadence Service
+#define Cycling_Power                                                  0x1818                  //Cycling Power Service
+#define Location_And_Navigation                                        0x1819                  //Location and Navigation Service
+#define Environmental_Sensing                                  0x181A                  //Environment Sensing Service
+#define Body_Composition                                               0x181B                  //Body Composition Service
+#define User_Data                                                              0x181C                  //User Data Service
+#define Weight_Scale                                                   0x181D                  //Weight Scale Service
+#define Bond_Management                                                        0x181E                  //Bond Management Service
+#define Continuous_Glucose_Monitoring                  0x181F                  //Continuous Glucose Monitoring Service
+#define Internet_Protocol_Support                              0x1820                  //Internet Protocol Support Service
+#define Indoor_Positioning                                             0x1821                  //Indoor Positioning Service
+#define Pulse_Oximeter                                                 0x1822                  //Pulse Oximeter Service
+#define Http_Proxy                                                             0x1823                  //Http Proxy Service
+#define Transport_Discovery                                            0x1824                  //Transport Discovery Service
+#define Object_Transfer                                                        0x1825                  //Object Transfer Service
+
+/* List of GATT Characteristics UUID */
+#define Gap_Device_Name                                                                                0x2A00
+#define Gap_Appearance                                                                         0x2A01
+#define Gap_Peripheral_Privacy_Flag                                                    0x2A02
+#define Gap_Reconnection_Address                                                       0x2A03
+#define Gap_Peripheral_Preferred_Connection_Parameters         0x2A04
+#define Gatt_Service_Changed                                                           0x2A05
+#define Alert_Level                                                                                    0x2A06
+#define Tx_Power_Level                                                                         0x2A07
+#define Date_Time                                                                                      0x2A08
+#define Day_Of_Week                                                                                    0x2A09
+#define Day_Date_Time                                                                          0x2A0A
+#define Exact_Time_256                                                                         0x2A0C
+#define Dst_Offset                                                                                     0x2A0D
+#define Time_Zone                                                                                      0x2A0E
+#define Local_Time_Information                                                         0x2A0F
+#define Time_With_Dst                                                                          0x2A11
+#define Time_Accuracy                                                                          0x2A12
+#define Time_Source                                                                                    0x2A13
+#define Reference_Time_Information                                                     0x2A14
+#define Time_Update_Control_Point                                                      0x2A16
+#define Time_Update_State                                                                      0x2A17
+#define Glucose_Measurement                                                                    0x2A18
+#define Battery_Level                                                                          0x2A19
+#define Temperature_Measurement                                                                0x2A1C
+#define Temperature_Type                                                                       0x2A1D
+#define Intermediate_Temperature                                                       0x2A1E
+#define Measurement_Interval                                                           0x2A21
+#define Boot_Keyboard_Input_Report                                                     0x2A22
+#define System_Id                                                                                      0x2A23
+#define Model_Number_String                                                                    0x2A24
+#define Serial_Number_String                                                           0x2A25
+#define Firmware_Revision_String                                                       0x2A26
+#define Hardware_Revision_String                                                       0x2A27
+#define Software_Revision_String                                                       0x2A28
+#define Manufacturer_Name_String                                                       0x2A29
+#define Regulatory_Certification_Data_List                                     0x2A2A
+#define Current_Time_Charac                                                                    0x2A2B
+#define Magnetic_Declination                                                           0x2A2C
+#define Scan_Refresh                                                                           0x2A31
+#define Boot_Keyboard_Output_Report                                                    0x2A32
+#define Boot_Mouse_Input_Report                                                                0x2A33
+#define Glucose_Measurement_Context                                                    0x2A34
+#define Blood_Pressure_Measurement                                                     0x2A35
+#define Intermediate_Cuff_Pressure                                                     0x2A36
+#define Heart_Rate_Measurement                                                         0x2A37
+#define Body_Sensor_Location                                                           0x2A38
+#define Heart_Rate_Control_Point                                                       0x2A39
+#define Alert_Status                                                                           0x2A3F
+#define Ringer_Control_Point                                                           0x2A40
+#define Ringer_Setting                                                                         0x2A41
+#define Alert_Category_Id_Bit_Mask                                                     0x2A42
+#define Alert_Category_Id                                                                      0x2A43
+#define Alert_Notification_Control_Point                                       0x2A44
+#define Unread_Alert_Status                                                                    0x2A45
+#define New_Alert                                                                                      0x2A46
+#define Supported_New_Alert_Category                                           0x2A47
+#define Supported_Unread_Alert_Category                                                0x2A48
+#define Blood_Pressure_Feature                                                         0x2A49
+#define Hid_Information                                                                                0x2A4A
+#define Report_Map                                                                                     0x2A4B
+#define Hid_Control_Point                                                                      0x2A4C
+#define Report                                                                                         0x2A4D
+#define Protocol_Mode                                                                          0x2A4E
+#define Scan_Interval_Window                                                           0x2A4F
+#define Pnp_Id                                                                                         0x2A50
+#define Glucose_Feature                                                                                0x2A51
+#define Record_Access_Control_Point                                                    0x2A52
+#define Rsc_Measurement                                                                                0x2A53
+#define Rsc_Feature                                                                                    0x2A54
+#define Sc_Control_Point                                                                       0x2A55
+#define Digital                                                                                                0x2A56
+#define Analog                                                                                         0x2A58
+#define Aggregate                                                                                      0x2A5A
+#define Csc_Measurement                                                                                0x2A5B
+#define Csc_Feature                                                                                    0x2A5C
+#define Sensor_Location                                                                                0x2A5D
+#define Plx_Spot_Check_Measurement                                                     0x2A5E
+#define Plx_Continuous_Measurement                                                     0x2A5F
+#define Plx_Features                                                                           0x2A60
+#define Cycling_Power_Measurement                                                      0x2A63
+#define Cycling_Power_Vector                                                           0x2A64
+#define Cycling_Power_Feature                                                          0x2A65
+#define Cycling_Power_Control_Point                                                    0x2A66
+#define Location_And_Speed                                                                     0x2A67
+#define Navigation                                                                                     0x2A68
+#define Position_Quality                                                                       0x2A69
+#define Ln_Feature                                                                                     0x2A6A
+#define Ln_Control_Point                                                                       0x2A6B
+#define Elevation                                                                                      0x2A6C
+#define Pressure                                                                                       0x2A6D
+#define Temperature                                                                                    0x2A6E
+#define Humidity                                                                                       0x2A6F
+#define True_Wind_Speed                                                                                0x2A70
+#define True_Wind_Direction                                                                    0x2A71
+#define Apparent_Wind_Speed                                                                    0x2A72
+#define Apparent_Wind_Direction                                                                0x2A73
+#define Gust_Factor                                                                                    0x2A74
+#define Pollen_Concentration                                                           0x2A75
+#define Uv_Index                                                                                       0x2A76
+#define Irradiance                                                                                     0x2A77
+#define Rainfall                                                                                       0x2A78
+#define Wind_Chill                                                                                     0x2A79
+#define Heat_Index                                                                                     0x2A7A
+#define Dew_Point                                                                                      0x2A7B
+#define Descriptor_Value_Changed                                                       0x2A7D
+#define Aerobic_Threshold                                                                      0x2A7F
+#define Age                                                                                                    0x2A80
+#define Anaerobic_Heart_Rate_Lower_Limit                                       0x2A81
+#define Anaerobic_Heart_Rate_Upper_Limit                                       0x2A82
+#define Anaerobic_Threshold                                                                    0x2A83
+#define Aerobic_Heart_Rate_Upper_Limit                                         0x2A84
+#define Date_Of_Birth                                                                          0x2A85
+#define Date_Of_Threshold_Assessment                                           0x2A86
+#define Email_Address                                                                          0x2A87
+#define Fat_Burn_Heart_Rate_Lower_Limit                                                0x2A88
+#define Fat_Burn_Heart_Rate_Upper_Limit                                                0x2A89
+#define First_Name                                                                                     0x2A8A
+#define Five_Zone_Heart_Rate_Limits                                                    0x2A8B
+#define Gender                                                                                         0x2A8C
+#define Heart_Rate_Max                                                                         0x2A8D
+#define Height                                                                                         0x2A8E
+#define Hip_Circumference                                                                      0x2A8F
+#define Last_Name                                                                                      0x2A90
+#define Maximum_Recommended_Heart_Rate                                         0x2A91
+#define Resting_Heart_Rate                                                                     0x2A92
+#define Sport_Type_For_Aerobic_And_Anaerobic_Thresholds                0x2A93
+#define Three_Zone_Heart_Rate_Limits                                           0x2A94
+#define Two_Zone_Heart_Rate_Limit                                                      0x2A95
+#define Vo2_Max                                                                                                0x2A96
+#define Waist_Circumference                                                                    0x2A97
+#define Weight                                                                                         0x2A98
+#define Database_Change_Increment                                                      0x2A99
+#define User_Index                                                                                     0x2A9A
+#define Body_Composition_Feature                                                       0x2A9B
+#define Body_Composition_Measurement                                           0x2A9C
+#define Weight_Measurement                                                                     0x2A9D
+#define Weight_Scale_Feature                                                           0x2A9E
+#define User_Control_Point                                                                     0x2A9F
+#define Magnetic_Flux_Density_2D                                                       0x2AA0
+#define Magnetic_Flux_Density_3D                                                       0x2AA1
+#define Language                                                                                       0x2AA2
+#define Barometric_Pressure_Trend                                                      0x2AA3
+#define Bond_Management_Control_Point                                          0x2AA4
+#define Bond_Management_Feature                                                                0x2AA5
+#define Gap_Central_Address_Resolution_Support                         0x2AA6
+#define Cgm_Measurement                                                                                0x2AA7
+#define Cgm_Feature                                                                                    0x2AA8
+#define Cgm_Status                                                                                     0x2AA9
+#define Cgm_Session_Start_Time                                                         0x2AAA
+#define Cgm_Session_Run_Time                                                           0x2AAB
+#define Cgm_Specific_Ops_Control_Point                                         0x2AAC
+#define Indoor_Positioning_Configuration                                       0x2AAD
+#define Latitude                                                                                       0x2AAE
+#define Longitude                                                                                      0x2AAF
+#define Local_North_Coordinate                                                         0x2AB0
+#define Local_East_Coordinate                                                          0x2AB1
+#define Floor_Number                                                                           0x2AB2
+#define Altitude                                                                                       0x2AB3
+#define Uncertainty                                                                                    0x2AB4
+#define Location_Name                                                                          0x2AB5
+#define Uri                                                                                                    0x2AB6
+#define Http_Headers                                                                           0x2AB7
+#define Http_Status_Code                                                                       0x2AB8
+#define Http_Entity_Body                                                                       0x2AB9
+#define Http_Control_Point                                                                     0x2ABA
+#define Https_Security                                                                         0x2ABB
+#define Tds_Control_Point                                                                      0x2ABC
+#define Ots_Feature                                                                                    0x2ABD
+#define Object_Name                                                                                    0x2ABE
+#define Object_Type                                                                                    0x2ABF
+#define Object_Size                                                                                    0x2AC0
+#define Object_First_Created                                                           0x2AC1
+#define Object_Last_Modified                                                           0x2AC2
+#define Object_Id                                                                                      0x2AC3
+#define Object_Properties                                                                      0x2AC4
+#define Object_Action_Control_Point                                                    0x2AC5
+#define Object_List_Control_Point                                                      0x2AC6
+#define Object_List_Filter                                                                     0x2AC7
+#define Object_Changed                                                                         0x2AC8
+#define Fitness_Machine_Control_Point                                          0xEE1D
+
+/* List of GATT Descriptors UUID */
+#define Gatt_Characteristic_Extended_Properties                        0x2900
+#define Gatt_Characteristic_User_Description                   0x2901
+#define Gatt_Client_Characteristic_Configuration               0x2902
+#define Gatt_Server_Characteristic_Configuration               0x2903
+#define Gatt_Characteristic_Presentation_Format                        0x2904
+#define Gatt_Characteristic_Aggregate_Format                   0x2905
+#define Valid_Range                                                                            0x2906
+#define External_Report_Reference                                              0x2907
+#define Report_Reference                                                               0x2908
+#define Number_Of_Digitals                                                             0x2909
+#define Value_Trigger_Setting                                                  0x290A
+#define Es_Configuration                                                               0x290B
+#define Es_Measurement                                                                 0x290C
+#define Es_Trigger_Setting                                                             0x290D
+#define Time_Trigger_Setting                                                   0x290E
+
+/* List of GATT Declarations UUID */
+#define Gatt_Primary_Service_Declaration                               0x2800
+#define Gatt_Secondary_Service_Declaration                             0x2801
+#define Gatt_Include_Declaration                                               0x2802
+#define Gatt_Characteristic_Declaration                                        0x2803
 
 const char *bt_uuid_t2str(const uint8_t *uuid, char *buf);
 const char *btuuid2str(const uint8_t *uuid);
@@ -84,4 +432,6 @@ const char *enum_strings(void *v, int i);
 const char *enum_one_string(void *v, int i);
 bt_service_id_t _bt_convert_uuid_string_to_service_id(const char *uuid);
 char *_bt_convert_service_id_to_uuid_string(bt_service_id_t service_id);
+const char *_bt_hal_dump_uuid_name(int uuid_no);
+
 #endif //_BT_HAL_UTILS_H_
index ee862ce..bc87058 100644 (file)
@@ -333,7 +333,7 @@ static gboolean __bt_adapter_all_properties_cb(gpointer user_data)
                        g_free(address);
                } else if (!g_strcmp0(key, "Alias")) {
                        name = (gchar *) g_variant_get_string(value, NULL);
-                       DBG("Alias [%s]@@@", name);
+                       DBG("Alias [%s]", name);
                        size += __bt_insert_hal_properties(buf + size,
                                        HAL_PROP_ADAPTER_NAME, strlen(name) + 1, name);
                        ev->num_props++;
index c5cad7e..e947371 100644 (file)
@@ -36,6 +36,7 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <string.h>
+#include <fcntl.h>
 
 #include "bt-hal.h"
 #include "bt-hal-log.h"
@@ -118,6 +119,14 @@ static void __bt_hal_free_le_adv_slot(void)
        le_adv_slot = NULL;
 }
 
+void _bt_hal_unregister_adv_slot_owner(int slot_id)
+{
+       if (le_adv_slot == NULL)
+               return;
+       INFO("Unregister Adv Slot [%d]", slot_id);
+       memset(&le_adv_slot[slot_id], 0x00, sizeof(bt_adapter_le_adv_slot_t));
+}
+
 int _bt_hal_get_adv_slot_adv_handle(int slot_id)
 {
        if (le_adv_slot == NULL)
@@ -126,6 +135,11 @@ int _bt_hal_get_adv_slot_adv_handle(int slot_id)
        return le_adv_slot[slot_id].adv_handle;
 }
 
+gboolean _bt_hal_is_advertising_in_slot(int slot)
+{
+       return le_adv_slot[slot].is_advertising;
+}
+
 void _bt_hal_set_advertising_status(int slot_id, gboolean mode)
 {
 
@@ -236,6 +250,25 @@ int _bt_hal_get_available_adv_slot_id(bt_uuid_t *uuid)
        return -1;
 }
 
+void _bt_hal_get_gatt_server_instance_initialized(int *instance)
+{
+       int i;
+       if (le_adv_slot == NULL) {
+               ERR("le_adv_slot is NULL");
+               return;
+       }
+
+       DBG("adv_inst_max : %d", le_feature_info.adv_inst_max);
+
+       for (i = 0; i < le_feature_info.adv_inst_max; i++) {
+               if (le_adv_slot[i].initialized == 0)
+                       continue;
+               DBG("Initialized Slot found: UUID [%s] slot [%d]", le_adv_slot[i].app_uuid.uu, i);
+               *instance = i;
+               break;
+       }
+}
+
 gboolean _bt_is_advertising(void)
 {
        return FALSE;
@@ -393,21 +426,21 @@ static gboolean __bt_hal_adv_event_cb(gpointer param)
 
        switch(event->event) {
        case BT_HAL_MULTI_ADV_ENB_EVT: {
+               INFO("BLE Advertising enabled slot [%d]", event->server_if);
                struct hal_ev_multi_adv_enable ev;
                memset(&ev, 0, sizeof(struct hal_ev_multi_adv_enable));
                ev.status = event->status;
                ev.server_instance = event->server_if;
                gatt_le_event_cb(HAL_EV_MULTI_ADV_ENABLE, (void *)&ev, sizeof(ev));
-               INFO("BLE Advertising enabled slot [%d]", event->server_if);
                break;
        }
        case BT_HAL_MULTI_ADV_DISABLE_EVT: {
+               INFO("BLE Advertising disabled slot [%d]", event->server_if);
                struct hal_ev_multi_adv_disable ev;
                memset(&ev, 0, sizeof(struct hal_ev_multi_adv_disable));
                ev.status = event->status;
                ev.server_instance = event->server_if;
                gatt_le_event_cb(HAL_EV_MULTI_ADV_DISABLE, (void *)&ev, sizeof(ev));
-               INFO("BLE Advertising disabled slot [%d]", event->server_if);
                break;
        }
        case BT_HAL_MULTI_ADV_PARAM_EVT: {
@@ -415,12 +448,12 @@ static gboolean __bt_hal_adv_event_cb(gpointer param)
                break;
        }
        case BT_HAL_MULTI_ADV_UPDATE_EVT: {
+               INFO("BLE Advertising Param update slot [%d]", event->server_if);
                struct hal_ev_multi_adv_update ev;
                memset(&ev, 0, sizeof(struct hal_ev_multi_adv_update));
                ev.status = event->status;
                ev.server_instance = event->server_if;
                gatt_le_event_cb(HAL_EV_MULTI_ADV_UPDATE, (void *)&ev, sizeof(ev));
-               INFO("BLE Advertising Param update slot [%d]", event->server_if);
                break;
        }
        case BT_HAL_MULTI_ADV_DATA_EVT: {
@@ -496,6 +529,7 @@ int _bt_hal_enable_advertising(int server_if, bool enable, bool is_multi_adv)
                g_variant_unref(ret);
 
        le_adv_slot[server_if].is_multi_adv = is_multi_adv;
+       le_adv_slot[server_if].is_advertising = enable;
        return BT_STATUS_SUCCESS;
 }
 
@@ -551,7 +585,7 @@ int _bt_hal_set_advertising_params(int server_if, int min_interval,
          * callback method which will carry actual result
          */
        event = g_malloc0(sizeof(bt_hal_adv_event_data_t));
-       event->event  = BT_HAL_MULTI_ADV_DATA_EVT;
+       event->event  = BT_HAL_MULTI_ADV_UPDATE_EVT;
        event->server_if = server_if;
        event->status = BT_STATUS_SUCCESS;
         g_idle_add(__bt_hal_adv_event_cb, (gpointer)event);
index 697bd64..c1c8460 100644 (file)
@@ -43,6 +43,10 @@ int _bt_hal_get_available_adv_slot_id(bt_uuid_t *uuid);
 
 int _bt_hal_get_adv_slot_adv_handle(int slot_id);
 
+void _bt_hal_unregister_adv_slot_owner(int slot_id);
+
+gboolean _bt_hal_is_advertising_in_slot(int slot);
+
 void _bt_hal_set_advertising_status(int slot_id, gboolean mode);
 
 gboolean _bt_hal_is_advertising(void);
@@ -64,6 +68,8 @@ int _bt_hal_adapter_le_stop_scan(void);
 int _bt_hal_adapter_le_set_scan_parameters(
                int scan_type, int scan_interval, int scan_window);
 
+void _bt_hal_get_gatt_server_instance_initialized(int *instance);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index f92bcaf..9377417 100644 (file)
@@ -47,6 +47,8 @@
 #include "bt-hal-utils.h"
 #include "bt-hal-internal.h"
 
+#define CASE_RETURN_STR(const) case const: return #const;
+
 /**
  * This is RFCOMM default Channel Value
  */
@@ -571,6 +573,33 @@ void _bt_convert_device_path_to_address(const char *device_path,
        }
 }
 
+gboolean _bt_hal_uuid_is_standard(bt_uuid_t *p_uuid)
+{
+       uint32_t uuid0, uuid4;
+       uint16_t uuid1, uuid2, uuid3, uuid5;
+       const char *uuid_name;
+       const char *uuid_name1;
+
+       memcpy(&uuid0, &(p_uuid->uu[0]), 4);
+       memcpy(&uuid1, &(p_uuid->uu[4]), 2);
+       memcpy(&uuid2, &(p_uuid->uu[6]), 2);
+       memcpy(&uuid3, &(p_uuid->uu[8]), 2);
+       memcpy(&uuid4, &(p_uuid->uu[10]), 4);
+       memcpy(&uuid5, &(p_uuid->uu[14]), 2);
+
+       uuid_name = _bt_hal_dump_uuid_name(ntohl(uuid0));
+       uuid_name1 = _bt_hal_dump_uuid_name((ntohl(uuid4) >> 16));
+
+       DBG("UUID Name [%s]", uuid_name);
+       DBG("UUID Name Shifted [%s]", uuid_name1);
+
+       if (!g_strcmp0(uuid_name, "--"))
+               return FALSE;
+       else
+               return TRUE;
+
+}
+
 void _bt_convert_uuid_string_to_type(unsigned char *uuid,
                 const char *device_uuid)
 {
@@ -1519,3 +1548,109 @@ done:
        DBG("-");
        return result;
 }
+
+int bt_hal_gatt_convert_prop2string(
+                        bt_hal_gatt_characteristic_property_t properties,
+                        char *char_properties[])
+{
+       int flag_count = 0;
+
+       if (properties & BT_HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
+               char_properties[flag_count] = g_strdup("broadcast");
+               flag_count++;
+       }
+       if (properties & BT_HAL_GATT_CHARACTERISTIC_PROPERTY_READ) {
+               char_properties[flag_count] = g_strdup("read");
+               flag_count++;
+       }
+       if (properties & BT_HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
+               char_properties[flag_count] = g_strdup("write-without-response");
+               flag_count++;
+       }
+       if (properties & BT_HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
+               char_properties[flag_count] = g_strdup("write");
+               flag_count++;
+       }
+       if (properties & BT_HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
+               char_properties[flag_count] = g_strdup("notify");
+               flag_count++;
+       }
+       if (properties & BT_HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
+               char_properties[flag_count] = g_strdup("indicate");
+               flag_count++;
+       }
+       if (properties & BT_HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
+               char_properties[flag_count] = g_strdup("authenticated-signed-writes");
+               flag_count++;
+       }
+       if (properties & BT_HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE) {
+               char_properties[flag_count] = g_strdup("reliable-write");
+               flag_count++;
+       }
+       if (properties & BT_HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES) {
+               char_properties[flag_count] = g_strdup("writable-auxiliaries");
+               flag_count++;
+       }
+       if (properties & BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ) {
+               char_properties[flag_count] = g_strdup("encrypt-read");
+               flag_count++;
+       }
+       if (properties & BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE) {
+               char_properties[flag_count] = g_strdup("encrypt-write");
+               flag_count++;
+       }
+       if (properties & BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ) {
+               char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
+               flag_count++;
+       }
+       if (properties & BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE) {
+               char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
+               flag_count++;
+       }
+
+       if (flag_count == 0) {
+               char_properties[flag_count] = g_strdup("read");
+               flag_count++;
+       }
+
+       return flag_count;
+}
+
+int bt_hal_gatt_convert_perm2string(
+                        bt_hal_gatt_permission_t properties,
+                        char *char_properties[])
+{
+        int flag_count = 0;
+
+        if (properties & BT_HAL_GATT_PERMISSION_READ) {
+                char_properties[flag_count] = g_strdup("read");
+                flag_count++;
+        }
+        if (properties & BT_HAL_GATT_PERMISSION_WRITE) {
+                char_properties[flag_count] = g_strdup("write");
+                flag_count++;
+        }
+        if (properties & BT_HAL_GATT_PERMISSION_ENCRYPT_READ) {
+                char_properties[flag_count] = g_strdup("encrypt-read");
+                flag_count++;
+        }
+        if (properties & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE) {
+                char_properties[flag_count] = g_strdup("encrypt-write");
+                flag_count++;
+        }
+        if (properties & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ) {
+                char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
+                flag_count++;
+        }
+        if (properties & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE) {
+                char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
+                flag_count++;
+        }
+
+        if (flag_count == 0) {
+                char_properties[flag_count] = g_strdup("read");
+                flag_count++;
+        }
+
+        return flag_count;
+}
index 14276c2..06d0eb0 100644 (file)
@@ -365,6 +365,32 @@ typedef enum {
        BT_HAL_DEVICE_MINOR_CLASS_ANKLE_PROSTHESIS = 0x34,   /**< Ankle prosthesis minor class */
 } bt_hal_device_minor_class_t;
 
+typedef enum {
+        BT_HAL_GATT_PERMISSION_READ = 0x01,
+        BT_HAL_GATT_PERMISSION_WRITE = 0x02,
+        BT_HAL_GATT_PERMISSION_ENCRYPT_READ = 0x04,
+        BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE = 0x08,
+        BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ = 0x10,
+        BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE = 0x20,
+} bt_hal_gatt_permission_t;
+
+typedef enum {
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST = 0x01,
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_READ = 0x02,
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE = 0x04,
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE = 0x08,
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY = 0x10,
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE = 0x20,
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE = 0x40,
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE = 0x80,
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES = 0x100,
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ = 0x200,
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE = 0x400,
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ = 0x800,
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE = 0x1000,
+        BT_HAL_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS = 0xffff,
+} bt_hal_gatt_characteristic_property_t;
+
 /**
  * This is Bluetooth device address type, fixed to 6 bytes ##:##:##:##:##:##
  */
@@ -435,6 +461,16 @@ void _bt_unregister_gdbus_object(int object_id);
 
 char *_bt_get_control_device_path(bt_bdaddr_t *bd_addr);
 
+int bt_hal_gatt_convert_prop2string(
+                        bt_hal_gatt_characteristic_property_t properties,
+                        char *char_properties[]);
+
+int bt_hal_gatt_convert_perm2string(
+                        bt_hal_gatt_permission_t properties,
+                        char *char_properties[]);
+
+gboolean _bt_hal_uuid_is_standard(bt_uuid_t *p_uuid);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index 10b28ec..de6ab41 100644 (file)
@@ -39,6 +39,7 @@
 #include "bt-hal-dbus-common-utils.h"
 #include "bt-hal-agent.h"
 #include "bt-hal-adapter-le.h"
+#include "bt-hal-gatt-server.h"
 
 #define BASELEN_PROP_CHANGED (sizeof(struct hal_ev_adapter_props_changed) \
                + sizeof(struct hal_property))
@@ -1277,6 +1278,14 @@ static void __bt_hal_device_property_changed_event(GVariant *msg, const char *pa
                        __bt_hal_dbus_device_found_properties(path);
                } else if (!g_strcmp0(key, "GattConnected")) {
                        DBG("Device property changed : GattConnected");
+                       gboolean gatt_connected = FALSE;
+                       g_variant_get(value, "b", &gatt_connected);
+                       char *address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE);
+                       _bt_convert_device_path_to_address(path, address);
+                       DBG("@@gatt_connected: %d", gatt_connected);
+                       DBG("@@address: %s", address);
+                       _bt_hal_gatt_connected_state_event(gatt_connected, address);
+                       g_free(address);
                } else if (!g_strcmp0(key, "Paired")) {
                        DBG("Device property changed : Paired");
                } else if (!g_strcmp0(key, "LegacyPaired")) {
@@ -1598,7 +1607,15 @@ static void __bt_hal_handle_device_specific_events(GVariant *msg, const char *me
                if (property == NULL)
                        return;
                if (strcasecmp(property, "GattConnected") == 0) {
-                       /* TODO */
+                       INFO("GATT Connected");
+                       gboolean connected = FALSE;
+                        char *address;
+                        address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE);
+
+                        _bt_convert_device_path_to_address(path, address);
+                        g_variant_get(msg, "(b)", &connected);
+
+                       INFO("Connected device address[%s] connnected[%d]", address, connected);
                } else if (strcasecmp(property, "Paired") == 0) {
                        /* TODO */
                } else if (strcasecmp(property, "UUIDs") == 0) {
index 077d1ba..b8d6c78 100644 (file)
 #include <stdbool.h>
 #include <stddef.h>
 #include <string.h>
+#include <fcntl.h>
 
 #include "bt-hal.h"
 #include "bt-hal-log.h"
 #include "bt-hal-msg.h"
 #include "bt-hal-utils.h"
+#include "bt-hal-dbus-common-utils.h"
 
 #include "bt-hal-adapter-le.h"
 #include "bt-hal-event-receiver.h"
 
+#define NUMBER_OF_FLAGS 10
+
+#define GATT_SERV_INTERFACE             "org.bluez.GattService1"
+#define GATT_CHAR_INTERFACE             "org.bluez.GattCharacteristic1"
+#define GATT_DESC_INTERFACE             "org.bluez.GattDescriptor1"
+
+#define BT_GATT_SERVICE_NAME    "org.frwk.gatt_service"
+#define GATT_SERV_OBJECT_PATH   "/service"
+
+static GDBusProxy *manager_gproxy = NULL;
+
 /************************************************************************************
  **  Static variables
  ************************************************************************************/
 extern const btgatt_callbacks_t *bt_gatt_callbacks;
+guint owner_id;
+GDBusConnection *g_conn = NULL;
+//GDBusConnection *conn = NULL;
+GDBusNodeInfo *manager_node_info = NULL;
+guint manager_id;
+
+/* Global handles which needs to be incremented during each addition */
+static int gatt_service_handle = 10;
+static int gatt_char_handle = 20;
+static int gatt_desc_handle = 30;
+
+struct gatt_service_info {
+        gchar *serv_path;
+        guint serv_id;
+        gchar *service_uuid;
+        guint manager_id;
+        guint prop_id;
+        GSList *char_data;
+        gboolean is_svc_registered;
+        gboolean is_svc_primary;
+       int service_handle;
+};
+
+struct gatt_char_info {
+        gchar *char_path;
+        guint char_id;
+        gchar *char_uuid;
+        gchar *char_value;
+        gchar *char_flags[NUMBER_OF_FLAGS];
+        int value_length;
+        int flags_length;
+       int char_handle;
+        GSList *desc_data;
+};
+
+struct gatt_desc_info {
+        gchar *desc_path;
+        guint desc_id;
+        gchar *desc_uuid;
+        gchar *desc_value;
+        gchar *desc_flags[NUMBER_OF_FLAGS];
+        int value_length;
+        int flags_length;
+       int desc_handle;
+};
+
+/**
+ * GATT Server Request type
+ */
+typedef enum {
+        BT_HAL_GATT_REQUEST_TYPE_READ = 0x00,       /* Read Requested */
+        BT_HAL_GATT_REQUEST_TYPE_WRITE = 0x01,      /* Write Requested */
+        BT_HAL_GATT_REQUEST_TYPE_EXEC_WRITE = 0x02, /* Exec Write Requested */
+} bt_gatt_request_type_e;
+
+struct gatt_req_info {
+        gchar *attr_path;
+        gchar *svc_path;
+        guint  request_id;
+        guint  offset;
+        bt_gatt_request_type_e request_type;  /* Read or Write request */
+        GDBusMethodInvocation *context;
+};
+
+struct gatt_server_app {
+       int slot;
+       char *app_path;
+       GSList *services;
+};
+
+/* Linked List of gatt server app's */
+static GSList *gatt_server_apps = NULL;
+
+static GSList *gatt_services = NULL;
+
+static int conn_id = 0;
+
+/* Linked List of connected Remote GATT clients */
+static GSList *gatt_client_info_list = NULL;
+
+/* GATT Client Info List Structure */
+struct gatt_client_info_t {
+        int connection_id;                               /* This value will uniquely identify a GATT client-server connection */
+        int instance_id;                                 /* This value unique identifies a GATT server instance */
+        char *addr;                                      /* Remote GATT client address */
+       GSList *gatt_req_info_list;                              /* List of transactions per Connection*/
+};
+
+static handle_stack_msg event_cb = NULL;
+
+typedef struct {
+       uint32_t instance_data;
+       bt_uuid_t uuid;
+} hal_register_server_data;
+
+typedef struct {
+       uint32_t instance_data;
+       uint32_t srvc_hdl;
+       bt_uuid_t uuid;
+       uint8_t is_primary;
+} hal_gatt_service_added;
+
+typedef struct {
+       uint32_t instance_data;
+       uint32_t srvc_hdl;
+} hal_gatt_service_started;
+
+typedef struct {
+       uint32_t instance_data;
+       uint32_t srvc_hdl;
+} hal_gatt_service_deleted;
+
+typedef struct {
+       uint32_t instance_data;
+       uint32_t srvc_hdl;
+       uint32_t char_hdl;
+       bt_uuid_t uuid;
+} hal_gatt_char_added;
+
+typedef struct {
+       uint32_t instance_data;
+       uint32_t srvc_hdl;
+       uint32_t desc_hdl;
+       bt_uuid_t uuid;
+} hal_gatt_desc_added;
+
+#define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
+{\
+       ERR("%s: BTGATT not initialized", __FUNCTION__);\
+       return BT_STATUS_NOT_READY;\
+} else {\
+       DBG("%s", __FUNCTION__);\
+}
+
+static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data);
+
+static void __bt_hal_gatt_deinit(char *app_path);
+
+static void __bt_hal_register_application_cb(GObject *object,
+                               GAsyncResult *res, gpointer user_data);
+
+static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
+                gpointer user_data);
+
+static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
+                                const gchar *path, const gchar *interface);
+
+/* Introspection data for the service we are exporting */
+static const gchar service_introspection_xml[] =
+"<node name='/'>"
+"  <interface name='org.freedesktop.DBus.Properties'>"
+"    <property type='s' name='UUID' access='read'>"
+"    </property>"
+"        <property type='b' name='primary' access='read'>"
+"        </property>"
+"        <property type='o' name='Device' access='read'>"
+"        </property>"
+"        <property type='ao' name='Characteristics' access='read'>"
+"        </property>"
+"        <property type='s' name='Includes' access='read'>"
+"        </property>"
+"  </interface>"
+"</node>";
+
+/* Introspection data for the characteristics we are exporting */
+static const gchar characteristics_introspection_xml[] =
+"<node name='/'>"
+"  <interface name='org.bluez.GattCharacteristic1'>"
+"        <method name='ReadValue'>"
+"               <arg type='s' name='address' direction='in'/>"
+"               <arg type='y' name='id' direction='in'/>"
+"               <arg type='q' name='offset' direction='in'/>"
+"               <arg type='ay' name='Value' direction='out'/>"
+"        </method>"
+"        <method name='WriteValue'>"
+"               <arg type='s' name='address' direction='in'/>"
+"               <arg type='y' name='id' direction='in'/>"
+"               <arg type='q' name='offset' direction='in'/>"
+"               <arg type='ay' name='value' direction='in'/>"
+"        </method>"
+"        <method name='StartNotify'>"
+"        </method>"
+"        <method name='StopNotify'>"
+"        </method>"
+"        <method name='IndicateConfirm'>"
+"               <arg type='s' name='address' direction='in'/>"
+"               <arg type='b' name='complete' direction='in'/>"
+"        </method>"
+"  </interface>"
+"  <interface name='org.freedesktop.DBus.Properties'>"
+"    <property type='s' name='UUID' access='read'>"
+"    </property>"
+"    <property type='o' name='Service' access='read'>"
+"    </property>"
+"    <property type='ay' name='Value' access='readwrite'>"
+"    </property>"
+"        <property type='b' name='Notifying' access='read'>"
+"        </property>"
+"    <property type='as' name='Flags' access='read'>"
+"    </property>"
+"    <property type='s' name='Unicast' access='read'>"
+"    </property>"
+"        <property type='ao' name='Descriptors' access='read'>"
+"        </property>"
+"  </interface>"
+"</node>";
+
+/* Introspection data for the descriptor we are exporting */
+static const gchar descriptor_introspection_xml[] =
+"<node name='/'>"
+"  <interface name='org.bluez.GattDescriptor1'>"
+"        <method name='ReadValue'>"
+"               <arg type='s' name='address' direction='in'/>"
+"               <arg type='u' name='id' direction='in'/>"
+"               <arg type='q' name='offset' direction='in'/>"
+"               <arg type='ay' name='Value' direction='out'/>"
+"        </method>"
+"        <method name='WriteValue'>"
+"               <arg type='s' name='address' direction='in'/>"
+"               <arg type='u' name='id' direction='in'/>"
+"               <arg type='q' name='offset' direction='in'/>"
+"               <arg type='b' name='response_needed' direction='in'/>"
+"               <arg type='ay' name='value' direction='in'/>"
+"        </method>"
+"  </interface>"
+"  <interface name='org.freedesktop.DBus.Properties'>"
+"    <property type='s' name='UUID' access='read'>"
+"    </property>"
+"    <property type='o' name='Characteristic' access='read'>"
+"    </property>"
+"    <property type='ay' name='Value' access='read'>"
+"    </property>"
+"    <property type='as' name='Flags' access='read'>"
+"    </property>"
+"  </interface>"
+"</node>";
+
+
+static const gchar manager_introspection_xml[] =
+"<node name='/'>"
+"  <interface name='org.freedesktop.DBus.ObjectManager'>"
+"    <method name='GetManagedObjects'>"
+"     <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
+"        </method>"
+"  </interface>"
+"</node>";
+
+GSList *_bt_get_service_list_from_server(int instance)
+{
+       GSList *l;
+       INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
+       INFO("Find App with slot [%d]", instance);
+
+       for (l = gatt_server_apps; l; l = g_slist_next(l)) {
+               struct gatt_server_app *app = (struct gatt_server_app *)l->data;
+
+               if (app->slot == instance) {
+                       INFO("App slot [%d] Found, Number of services registered [%d]",
+                                       app->slot, g_slist_length(app->services));
+                       return app->services;
+               }
+       }
+       return NULL;
+}
+
+void _bt_remote_service_from_gatt_server(int instance, int service_handle)
+{
+       GSList *l;
+       GSList *l1;
+
+       for (l = gatt_server_apps; l; l = g_slist_next(l)) {
+               struct gatt_server_app *app = (struct gatt_server_app *)l->data;
+
+               if (app->slot == instance) {
+                       for (l1 = app->services; l1; l1 = g_slist_next(l1)) {
+                               struct gatt_service_info *srv = (struct gatt_service_info *)l1->data;
+                               if (srv->service_handle == service_handle) {
+                                       app->services = g_slist_remove(app->services, srv);
+                                       return;
+                               }
+                       }
+               }
+       }
+}
+
+void _bt_hal_update_gatt_service_in_gatt_server(int slot, struct gatt_service_info *serv_info)
+{
+       GSList *l;
+       for (l = gatt_server_apps; l; l = g_slist_next(l)) {
+               struct gatt_server_app *app = (struct gatt_server_app *)l->data;
+
+               if (app->slot == slot) {
+                       INFO("Updating service in GATT server's service list service handle [%d] slot [%d]",
+                               serv_info->service_handle, slot);
+                       app->services = g_slist_append(app->services, serv_info);
+               }
+       }
+}
+
+static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
+{
+       GSList *l;
+       struct gatt_client_info_t *info = NULL;
+
+       for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
+               info = (struct gatt_client_info_t*)l->data;
+               if (info == NULL)
+                       continue;
+
+               if (!g_strcmp0(info->addr, address)) {
+                       INFO("Remote GATT client found addr[%s]", info->addr);
+                       return info;
+               }
+       }
+       return NULL;
+}
+
+static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
+{
+       GSList *l;
+       struct gatt_client_info_t *info = NULL;
+
+       for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
+               info = (struct gatt_client_info_t*)l->data;
+               if (info == NULL)
+                       continue;
+
+               if (info->connection_id == conn_id) {
+                       INFO("Remote GATT client found addr[%s]", info->addr);
+                       return info;
+               }
+       }
+       return NULL;
+}
+
+static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
+{
+       GSList *l;
+       GSList *l1;
+
+       struct gatt_client_info_t *info = NULL;
+       struct gatt_req_info *info1 = NULL;
+
+       for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
+               info = (struct gatt_client_info_t*)l->data;
+
+               if (info == NULL)
+                       continue;
+               if (info->connection_id == conn_id) {
+
+                       for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
+
+                               info1 = (struct gatt_req_info*)l1->data;
+                               if (info1 == NULL)
+                                       continue;
+
+                               if (info1->request_id == trans_id) {
+                                       INFO("Remote GATT client found addr[%s]", info->addr);
+                                       return info1;
+                               }
+                       }
+               }
+       }
+       return NULL;
+}
+
+void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
+{
+       struct hal_ev_gatt_server_connected ev;
+       struct gatt_client_info_t *conn_info = NULL;
+       int instance = -1;
+       memset(&ev, 0, sizeof(ev));
+
+       /* Find Server Instance */
+       _bt_hal_get_gatt_server_instance_initialized(&instance);
+       if (instance == -1) {
+               ERR("Not even a single GATT server is registered");
+               return;
+       }
+
+       /* Convert address to hex */
+       _bt_convert_addr_string_to_type(ev.bdaddr, address);
+
+       /* Create Connection ID */
+       /* Check if device is already in connected list */
+       conn_info = __bt_find_remote_gatt_client_info(address);
+
+
+       /* If disconnected, and conn info found, then remove conn info */
+       if (is_connected == FALSE) {
+               DBG("GATT Disconnected");
+               if (conn_info) {
+                       INFO("Remove GATT client info from List..");
+                       /* Remove info from List */
+                       gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
+                       INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
+
+                       if (!event_cb)
+                               ERR("GATT callback not registered");
+                       else {
+                               DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
+                                               conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
+                               ev.conn_id = conn_info->connection_id;
+                               ev.server_instance = conn_info->instance_id;
+                               ev.connected = is_connected;
+
+                               event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
+                       }
+                       g_free(conn_info->addr);
+                       g_free(conn_info);
+               }
+               /* If connected, and conn info NOT found, then add conn info */
+       } else {
+               if (!conn_info) {
+                       /* Save Connection info */
+                       conn_info = g_new0(struct gatt_client_info_t, 1);
+                       conn_info->addr = g_strdup(address);
+                       INFO("Added GATT client addr[%s]", conn_info->addr);
+                       conn_info->connection_id = ++conn_id;
+                       conn_info->instance_id = instance;
+                       gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
+                       INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
+
+                       if (!event_cb)
+                               ERR("GATT callback not registered");
+                       else {
+                               DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
+                                               conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
+                               ev.conn_id = conn_info->connection_id;
+                               ev.server_instance = conn_info->instance_id;
+                               ev.connected = is_connected;
+
+                               event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
+                       }
+               }
+       }
+       /* Send GATT connected or disconnected event */
+}
+
+static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
+{
+       GSList *l1, *l2;
+
+       for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
+               struct gatt_service_info *serv_info = l1->data;
+
+               for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
+                       struct gatt_char_info *char_info = l2->data;
+
+                       if (g_strcmp0(char_info->char_path, char_path)
+                                       == 0) {
+                               *char_hdl = char_info->char_handle;
+                               return serv_info;
+                       }
+               }
+       }
+       ERR("Gatt service not found");
+       return NULL;
+}
+
+char *__bt_gatt_find_char_path_from_handle(int char_hdl)
+{
+       GSList *l1, *l2;
+
+       for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
+               struct gatt_service_info *serv_info = l1->data;
+
+               for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
+                       struct gatt_char_info *char_info = l2->data;
+
+                       if (char_info->char_handle == char_hdl) {
+                               return char_info->char_path;
+                       }
+               }
+       }
+       ERR("Not found");
+       return NULL;
+}
+
+struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
+{
+       GSList *l1, *l2;
+
+       for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
+               struct gatt_service_info *serv_info = l1->data;
+
+               for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
+                       struct gatt_char_info *char_info = l2->data;
+
+                       if (char_info->char_handle == char_hdl) {
+                               return char_info;
+                       }
+               }
+       }
+       ERR("Not found");
+       return NULL;
+}
+
+static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
+{
+       GSList *l1, *l2, *l3;
+
+       for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
+               struct gatt_service_info *serv_info = l1->data;
+
+               for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
+                       struct gatt_char_info *char_info = l2->data;
+
+                       for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
+                               struct gatt_desc_info *desc_info = l3->data;
+
+                               if (g_strcmp0(desc_info->desc_path, desc_path)
+                                               == 0) {
+                                       *desc_hdl = desc_info->desc_handle;
+                                       return serv_info;
+                               }
+                       }
+               }
+       }
+       ERR("Gatt service not found");
+       return NULL;
+}
+
+static void __bt_gatt_manager_method_call(GDBusConnection *connection,
+                                        const gchar *sender,
+                                        const gchar *object_path,
+                                        const gchar *interface_name,
+                                        const gchar *method_name,
+                                        GVariant *parameters,
+                                        GDBusMethodInvocation *invocation,
+                                        gpointer user_data)
+{
+       GSList *l = NULL;
+
+       if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
+               GVariantBuilder *builder;
+               GVariantBuilder *inner_builder1 = NULL;
+               GVariant *svc_char = NULL;
+               GSList *l4;
+               GSList *gatt_services = NULL;
+               int *instance;
+               instance = (int*)user_data;
+
+               DBG("Getting values for service, chars and descriptors");
+               DBG("GATT Server App for which services are requested [%d]", *instance);
+
+               /*Main Builder */
+               builder = g_variant_builder_new(
+                               G_VARIANT_TYPE("a{oa{sa{sv}}}"));
+
+
+               gatt_services = _bt_get_service_list_from_server(*instance);
+
+               if (g_slist_length(gatt_services) == 0) {
+                       ERR("No registered GATT services!!!!");
+                       g_dbus_method_invocation_return_value(invocation, NULL);
+                       return;
+               }
+
+               for (l = gatt_services; l != NULL; l = l->next) {
+                       GVariantBuilder *svc_builder = NULL;
+                        GVariantBuilder *inner_builder = NULL;
+                       struct gatt_service_info *serv_info = l->data;
+                       INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
+
+                       /* Prepare inner builder for GattService1 interface */
+                       DBG("Creating builder for service");
+                       svc_builder = g_variant_builder_new(
+                                       G_VARIANT_TYPE("a{sa{sv}}"));
+                       inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+
+                       g_variant_builder_add(inner_builder, "{sv}", "UUID",
+                                       g_variant_new_string(serv_info->service_uuid));
+
+                       g_variant_builder_add(inner_builder, "{sv}", "Primary",
+                                       g_variant_new_boolean(serv_info->is_svc_primary));
+
+                       /*Characteristics*/
+                       inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
+                       DBG("Adding Charatarisitcs list");
+                       for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
+                               struct gatt_char_info *char_info = l4->data;
+                               INFO("GATT Char handle [%d] found in GATT service handle [%d]",
+                                               char_info->char_handle, serv_info->service_handle);
+                               g_variant_builder_add(inner_builder1, "o",
+                                               char_info->char_path);
+                               DBG("%s", char_info->char_path);
+                       }
+
+                       svc_char = g_variant_new("ao", inner_builder1);
+                       g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
+                                       svc_char);
+
+                       g_variant_builder_add(svc_builder, "{sa{sv}}",
+                                       GATT_SERV_INTERFACE,
+                                       inner_builder);
+
+                       g_variant_builder_add(builder, "{oa{sa{sv}}}",
+                                       serv_info->serv_path,
+                                       svc_builder);
+
+                       g_variant_builder_unref(inner_builder1);
+
+                       /* Prepare inner builder for GattCharacteristic1 interface */
+
+                       GSList *l2 = serv_info->char_data;
+                       DBG("Creating builder for characteristics \n");
+
+                       if (l2 == NULL)
+                               DBG("characteristic data is NULL");
+
+                       for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
+
+                               GVariantBuilder *char_builder = NULL;
+                               GVariantBuilder *inner_builder = NULL;
+                               GVariantBuilder *builder1 = NULL;
+                               GVariantBuilder *builder2 = NULL;
+                               GVariantBuilder *builder3 = NULL;
+                               GVariant *char_val = NULL;
+                               GVariant *flags_val = NULL;
+                               GVariant *char_desc = NULL;
+                               char *unicast = NULL;
+                               gboolean notify = FALSE;
+                               int i = 0;
+
+                               char_builder = g_variant_builder_new(
+                                               G_VARIANT_TYPE(
+                                                       "a{sa{sv}}"));
+                               inner_builder = g_variant_builder_new(
+                                               G_VARIANT_TYPE(
+                                                       "a{sv}"));
+
+                               struct gatt_char_info *char_info = l2->data;
+                               if (char_info == NULL) {
+                                       ERR("char_info is NULL");
+                                       continue;
+                               }
+
+                               /*Uuid*/
+                               g_variant_builder_add(inner_builder, "{sv}", "UUID",
+                                               g_variant_new_string(char_info->char_uuid));
+                               /*Service*/
+                               g_variant_builder_add(inner_builder, "{sv}", "Service",
+                                               g_variant_new("o", serv_info->serv_path));
+                               /*Value*/
+                               builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
+
+                               if (char_info->char_value != NULL) {
+                                       for (i = 0; i < char_info->value_length; i++) {
+                                               g_variant_builder_add(builder1, "y",
+                                                               char_info->char_value[i]);
+                                       }
+                                       char_val = g_variant_new("ay", builder1);
+                                       g_variant_builder_add(inner_builder, "{sv}",
+                                                       "Value", char_val);
+                               }
+                               /*Flags*/
+                               builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
+                               for (i = 0; i < char_info->flags_length; i++) {
+                                       g_variant_builder_add(builder2, "s",
+                                                       char_info->char_flags[i]);
+                               }
+
+                               flags_val = g_variant_new("as", builder2);
+                               g_variant_builder_add(inner_builder, "{sv}", "Flags",
+                                               flags_val);
+
+                               /* Notifying */
+                               g_variant_builder_add(inner_builder, "{sv}", "Notifying",
+                                               g_variant_new("b", notify));
+
+                               /* Unicast */
+                               unicast = g_strdup("00:00:00:00:00:00");
+                               g_variant_builder_add(inner_builder, "{sv}", "Unicast",
+                                               g_variant_new("s", unicast));
+
+                               /*Descriptors*/
+                               builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
+                               DBG("Adding Descriptors list");
+
+                               for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
+                                       struct gatt_desc_info *desc_info = l4->data;
+                                       INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
+                                                       desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
+                                       g_variant_builder_add(builder3, "o",
+                                                       desc_info->desc_path);
+                                       DBG("%s", desc_info->desc_path);
+                               }
+
+                               char_desc = g_variant_new("ao", builder3);
+                               g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
+                                               char_desc);
+
+                               g_variant_builder_add(char_builder, "{sa{sv}}",
+                                               GATT_CHAR_INTERFACE , inner_builder);
+                               g_variant_builder_add(builder, "{oa{sa{sv}}}",
+                                               char_info->char_path, char_builder);
+
+                               /*Prepare inner builder for GattDescriptor1 interface*/
+
+                               GSList *l3 = char_info->desc_data;
+
+                               if (l3 == NULL)
+                                       DBG("descriptor data is NULL");
+
+                               for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
+
+                                       DBG("Creating builder for descriptor \n");
+
+                                       GVariantBuilder *desc_builder = NULL;
+                                       GVariantBuilder *inner_builder = NULL;
+                                       GVariantBuilder *builder1 = NULL;
+                                       GVariantBuilder *builder2 = NULL;
+                                       GVariant *desc_val = NULL;
+
+                                       desc_builder = g_variant_builder_new(
+                                                       G_VARIANT_TYPE(
+                                                               "a{sa{sv}}"));
+                                       inner_builder = g_variant_builder_new(
+                                                       G_VARIANT_TYPE(
+                                                               "a{sv}"));
+
+                                       struct gatt_desc_info *desc_info = l3->data;
+                                       if (desc_info == NULL) {
+                                               ERR("desc_info is NULL");
+                                               continue;
+                                       }
+
+                                       /*Uuid*/
+                                       g_variant_builder_add(inner_builder,
+                                                       "{sv}", "UUID",
+                                                       g_variant_new_string(
+                                                               desc_info->desc_uuid));
+
+                                       /*Characteristic*/
+                                       g_variant_builder_add(inner_builder, "{sv}",
+                                                       "Characteristic",
+                                                       g_variant_new("o",
+                                                               char_info->char_path));
+
+                                       /*Value*/
+                                       builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
+
+                                       if (desc_info->desc_value != NULL) {
+                                               for (i = 0; i < desc_info->value_length; i++) {
+                                                       g_variant_builder_add(builder1, "y",
+                                                                       desc_info->desc_value[i]);
+                                               }
+                                               desc_val = g_variant_new("ay", builder1);
+                                               g_variant_builder_add(inner_builder, "{sv}",
+                                                               "Value", desc_val);
+                                       }
+
+                                       /*Flags*/
+                                       builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
+
+                                       for (i = 0; i < desc_info->flags_length; i++) {
+                                               g_variant_builder_add(builder2, "s",
+                                                               desc_info->desc_flags[i]);
+                                       }
+
+                                       flags_val = g_variant_new("as", builder2);
+                                       g_variant_builder_add(inner_builder, "{sv}", "Flags",
+                                                       flags_val);
+
+                                       g_variant_builder_add(desc_builder, "{sa{sv}}",
+                                                       GATT_DESC_INTERFACE,
+                                                       inner_builder);
+
+                                       g_variant_builder_add(builder, "{oa{sa{sv}}}",
+                                                       desc_info->desc_path,
+                                                       desc_builder);
+
+                                       /*unref descriptor builder pointers*/
+                                       g_variant_builder_unref(builder1);
+                                       g_variant_builder_unref(builder2);
+                                       g_variant_builder_unref(inner_builder);
+                                       g_variant_builder_unref(desc_builder);
+                               }
+
+                               if (unicast)
+                                       g_free(unicast);
+                               /*unref char builder pointers*/
+                               g_variant_builder_unref(builder1);
+                               g_variant_builder_unref(builder2);
+                               g_variant_builder_unref(builder3);
+                               g_variant_builder_unref(inner_builder);
+                               g_variant_builder_unref(char_builder);
+                       }
+
+                       /*unref service builder pointers*/
+                       g_variant_builder_unref(inner_builder);
+                       g_variant_builder_unref(svc_builder);
+
+               }
+               /* Return builder as method reply */
+               DBG("Sending gatt service builder values to Bluez");
+               g_dbus_method_invocation_return_value(invocation,
+                               g_variant_new(
+                                       "(a{oa{sa{sv}}})",
+                                       builder));
+       }
+
+       /* Free User Data */
+       g_free(user_data);
+}
+
+static void __bt_gatt_desc_method_call(GDBusConnection *connection,
+                                        const gchar *sender,
+                                        const gchar *object_path,
+                                        const gchar *interface_name,
+                                        const gchar *method_name,
+                                        GVariant *parameters,
+                                        GDBusMethodInvocation *invocation,
+                                        gpointer user_data)
+{
+
+       if (g_strcmp0(method_name, "ReadValue") == 0) {
+               struct hal_ev_gatt_server_read_req ev;
+
+               gchar *addr = NULL;
+               guint req_id = 0;
+               guint16 offset = 0;
+               struct gatt_client_info_t *conn_info = NULL;
+               struct gatt_req_info *req_info = NULL;
+               struct gatt_service_info *svc_info = NULL;
+               int desc_hdl = -1;
+
+               DBG("ReadValue");
+               DBG("Application path = %s", object_path);
+               DBG("Sender = %s", sender);
+
+               svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
+               if (svc_info == NULL) {
+                       ERR("Coudn't find service for %s", object_path);
+                       g_dbus_method_invocation_return_value(invocation, NULL);
+                       return;
+               }
+
+               g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
+               DBG("Request id = %u, Offset = %u", req_id, offset);
+
+               /* Check if device is already in connected list */
+               conn_info = __bt_find_remote_gatt_client_info(addr);
+
+               if (conn_info == NULL) {
+                       ERR("Coudn't find Connection info for %s", addr);
+                       g_dbus_method_invocation_return_value(invocation, NULL);
+                       return;
+               }
+
+               if (!event_cb) {
+                       ERR("GATT callback NOT registered");
+                       g_dbus_method_invocation_return_value(invocation, NULL);
+                       return;
+               }
+
+               /* Store requests information */
+               req_info = g_new0(struct gatt_req_info, 1);
+               req_info->attr_path = g_strdup(object_path);
+               req_info->svc_path = g_strdup(svc_info->serv_path);
+               req_info->request_id = req_id;
+               req_info->offset = offset;
+               req_info->context = invocation;
+
+               /* Append request info in list of requests for the particular connection */
+               conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
+
+               /* Send HAL event */
+               memset(&ev, 0, sizeof(ev));
+               ev.conn_id = conn_info->connection_id;
+               ev.trans_id = req_id;
+               ev.att_handle = desc_hdl;
+               ev.offset = offset;
+               ev.is_long = false; /* TODO*/
+
+               /* Convert address to hex */
+               _bt_convert_addr_string_to_type(ev.bdaddr, addr);
+
+               event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
+               return;
+       } else if (g_strcmp0(method_name, "WriteValue") == 0) {
+
+               GVariant *var = NULL;
+               gchar *addr = NULL;
+               guint req_id = 0;
+               guint16 offset = 0;
+               gboolean response_needed = FALSE;
+               struct hal_ev_gatt_server_write_req ev;
+               int desc_hdl = -1;
+               int len;
+
+               struct gatt_service_info *svc_info = NULL;
+               struct gatt_client_info_t *conn_info = NULL;
+               struct gatt_req_info *req_info = NULL;
+
+               DBG("WriteValue");
+               DBG("Application path = %s", object_path);
+               DBG("Sender = %s", sender);
+
+               g_variant_get(parameters, "(&suqb@ay)",
+                               &addr, &req_id, &offset, &response_needed, &var);
+               DBG("Request id = %u, Offset = %u", req_id, offset);
+
+               /* Check if device is already in connected list */
+               conn_info = __bt_find_remote_gatt_client_info(addr);
+
+               svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
+
+               if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
+                       g_variant_unref(var);
+                       if (response_needed)
+                               g_dbus_method_invocation_return_value(invocation, NULL);
+                       else
+                               g_object_unref(invocation);
+                       return;
+               }
+
+               len = g_variant_get_size(var);
+                if (len > 0) {
+                        char *data;
+                       data = (char *)g_variant_get_data(var);
+                       memcpy(ev.value, data, len);
+                       ev.length = len;
+               }
+               if (response_needed) {
+                       /* Store request information */
+                       req_info = g_new0(struct gatt_req_info, 1);
+                       req_info->attr_path = g_strdup(object_path);
+                       req_info->svc_path = g_strdup(svc_info->serv_path);
+                       req_info->request_id = req_id;
+                       req_info->offset = offset;
+                       req_info->context = invocation;
+
+                       /* Append request info in list of requests for the particular connection */
+                       conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
+               } else {
+                       g_object_unref(invocation);
+               }
+
+               /* Send HAL event */
+               memset(&ev, 0, sizeof(ev));
+               ev.conn_id = conn_info->connection_id;
+               ev.trans_id = req_id;
+               ev.att_handle = desc_hdl;
+               ev.offset = offset;
+               ev.need_rsp = response_needed;
+               ev.is_prep = 0;
+
+               /* Convert address to hex */
+               _bt_convert_addr_string_to_type(ev.bdaddr, addr);
+
+               event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
+
+               g_variant_unref(var);
+               return;
+       }
+}
+
+static void __bt_gatt_char_method_call(GDBusConnection *connection,
+                                        const gchar *sender,
+                                        const gchar *object_path,
+                                        const gchar *interface_name,
+                                        const gchar *method_name,
+                                        GVariant *parameters,
+                                        GDBusMethodInvocation *invocation,
+                                        gpointer user_data)
+{
+       if (g_strcmp0(method_name, "ReadValue") == 0) {
+               gchar *addr = NULL;
+               guint req_id = 0;
+               guint16 offset = 0;
+               struct hal_ev_gatt_server_read_req ev;
+               int char_hdl = -1;
+
+               struct gatt_req_info *req_info = NULL;
+               struct gatt_client_info_t *conn_info = NULL;
+               struct gatt_service_info *svc_info = NULL;
+
+               DBG("Application path = %s", object_path);
+               DBG("Sender = %s", sender);
+
+               /* Check if device is already in connected list */
+               conn_info = __bt_find_remote_gatt_client_info(addr);
+
+               svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
+
+               if (svc_info == NULL || conn_info == NULL) {
+                       g_dbus_method_invocation_return_value(invocation, NULL);
+                       return;
+               }
+
+               if (!event_cb) {
+                        ERR("GATT callback NOT registered");
+                        g_dbus_method_invocation_return_value(invocation, NULL);
+                        return;
+                }
+
+               g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
+               DBG("Request id = %u, Offset = %u", req_id, offset);
+
+               /* Store requets information */
+               req_info = g_new0(struct gatt_req_info, 1);
+               req_info->attr_path = g_strdup(object_path);
+               req_info->svc_path = g_strdup(svc_info->serv_path);
+               req_info->request_id = req_id;
+               req_info->offset = offset;
+               req_info->context = invocation;
+
+               /* Append request info in list of requests for the particular connection */
+               conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
+
+               /* Send HAL event */
+               memset(&ev, 0, sizeof(ev));
+               ev.conn_id = conn_info->connection_id;
+               ev.trans_id = req_id;
+               ev.att_handle = char_hdl;
+               ev.offset = offset;
+               ev.is_long = false; /* TODO*/
+
+               /* Convert address to hex */
+               _bt_convert_addr_string_to_type(ev.bdaddr, addr);
+
+               event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
+               return;
+       } else if (g_strcmp0(method_name, "WriteValue") == 0) {
+               GVariant *var = NULL;
+               gchar *addr = NULL;
+               guint req_id = 0;
+               guint16 offset = 0;
+               gboolean response_needed = FALSE;
+               struct hal_ev_gatt_server_write_req ev;
+               int char_hdl = -1;
+
+               struct gatt_service_info *svc_info = NULL;
+               struct gatt_req_info *req_info = NULL;
+               struct gatt_client_info_t *conn_info = NULL;
+
+               DBG("WriteValue");
+               DBG("Application path = %s", object_path);
+               DBG("Sender = %s", sender);
+
+               g_variant_get(parameters, "(&suqb@ay)",
+                               &addr, &req_id, &offset, &response_needed, &var);
+               DBG("Request id = %u, Offset = %u", req_id, offset);
+
+               svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
+
+               /* Check if device is already in connected list */
+               conn_info = __bt_find_remote_gatt_client_info(addr);
+
+               if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
+                       g_variant_unref(var);
+                       if (response_needed)
+                               g_dbus_method_invocation_return_value(invocation, NULL);
+                       else
+                               g_object_unref(invocation);
+                       return;
+               }
+
+               if (response_needed) {
+                       /* Store requets information */
+                       req_info = g_new0(struct gatt_req_info, 1);
+                       req_info->attr_path = g_strdup(object_path);
+                       req_info->svc_path = g_strdup(svc_info->serv_path);
+                       req_info->request_id = req_id;
+                       req_info->offset = offset;
+                       req_info->context = invocation;
+
+                       /* Append request info in list of requests for the particular connection */
+                       conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
+
+               } else {
+                       g_object_unref(invocation);
+               }
+
+               /* Send HAL event */
+               memset(&ev, 0, sizeof(ev));
+               ev.conn_id = conn_info->connection_id;
+               ev.trans_id = req_id;
+               ev.att_handle = char_hdl;
+               ev.offset = offset;
+               ev.need_rsp = response_needed;
+               ev.is_prep = 0;
+
+               /* Convert address to hex */
+               _bt_convert_addr_string_to_type(ev.bdaddr, addr);
+
+               event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
+
+               g_variant_unref(var);
+               return;
+
+       } else if (g_strcmp0(method_name, "StartNotify") == 0) {
+               DBG("StartNotify");
+#ifdef TIZEN_BT_HAL
+               struct gatt_service_info *svc_info = NULL;
+               struct hal_ev_gatt_server_notifcation_change ev;
+               int char_hdl = -1;
+
+               svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
+               if (svc_info == NULL || event_cb == NULL) {
+                       return;
+               }
+
+               /* Send HAL event */
+                memset(&ev, 0, sizeof(ev));
+                ev.conn_id = -1;  /*TODO Bluez does not provide remote GATT client address, so no conn_id */
+                ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
+                ev.att_handle = char_hdl;
+               ev.notify = true;
+
+                /* Convert address to hex */
+                _bt_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
+
+                event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
+#endif
+
+       } else if (g_strcmp0(method_name, "StopNotify") == 0) {
+               DBG("StopNotify");
+#ifdef TIZEN_BT_HAL
+               struct gatt_service_info *svc_info = NULL;
+               struct hal_ev_gatt_server_notifcation_change ev;
+               int char_hdl = -1;
+
+               svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
+               if (svc_info == NULL || event_cb == NULL) {
+                       return;
+               }
+
+               /* Send HAL event */
+                memset(&ev, 0, sizeof(ev));
+                ev.conn_id = -1;  /*TODO Bluez does not provide remote GATT client address, so no conn_id */
+                ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
+                ev.att_handle = char_hdl;
+               ev.notify = false;
+
+                /* Convert address to hex */
+                _bt_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
+
+                event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
+#endif
+
+       } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
+               gchar *addr = NULL;
+               gboolean complete = FALSE;
+               int char_hdl = -1;
+
+               struct gatt_service_info *svc_info = NULL;
+               struct gatt_client_info_t *conn_info = NULL;
+
+               struct hal_ev_gatt_server_indicate_cfm ev;
+
+               DBG("IndicateConfirm");
+               DBG("Application path = %s", object_path);
+               DBG("Sender = %s", sender);
+
+               g_variant_get(parameters, "(&sb)", &addr, &complete);
+               DBG("Remote Device address number = %s", addr);
+               DBG("Is Indicate confirmation for last device [%d]", complete);
+
+               /* Check if device is already in connected list */
+               conn_info = __bt_find_remote_gatt_client_info(addr);
+
+               svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
+
+               if (svc_info == NULL || conn_info == NULL
+                       || event_cb == NULL) {
+                       return;
+               }
+
+               /* Send HAL event */
+                memset(&ev, 0, sizeof(ev));
+                ev.conn_id = conn_info->connection_id;
+                ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
+                ev.att_handle = char_hdl;
+
+                /* Convert address to hex */
+                _bt_convert_addr_string_to_type(ev.bdaddr, addr);
+
+                event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
+       }
+
+       g_dbus_method_invocation_return_value(invocation, NULL);
+}
+
+gboolean __bt_hal_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
+{
+       gboolean ret;
+       GError *error = NULL;
+       GVariantBuilder *array_builder;
+
+       array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
+       g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
+       g_variant_builder_add(array_builder, "s", interface);
+
+       ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
+                       "org.freedesktop.Dbus.Objectmanager",
+                       "InterfacesRemoved",
+                       g_variant_new("(oas)",
+                               object_path, array_builder),
+                       &error);
+
+       if (!ret) {
+               if (error != NULL) {
+                       /* dbus gives error cause */
+                       ERR("d-bus api failure: errcode[%x], message[%s]",
+                                       error->code, error->message);
+                       g_clear_error(&error);
+               }
+       }
+       g_variant_builder_unref(array_builder);
+
+       return ret;
+}
+
+static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
+{
+       int i;
+
+       if (!desc_info)
+               return;
+
+       g_free(desc_info->desc_path);
+       g_free(desc_info->desc_uuid);
+       g_free(desc_info->desc_value);
+
+       for (i = 0; i < desc_info->flags_length; i++)
+               g_free(desc_info->desc_flags[i]);
+
+       g_free(desc_info);
+}
+
+static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
+{
+       int i;
+
+       if (!char_info)
+               return;
+
+       g_free(char_info->char_path);
+       g_free(char_info->char_uuid);
+       g_free(char_info->char_value);
+
+       for (i = 0; i < char_info->flags_length; i++)
+               g_free(char_info->char_flags[i]);
+
+       g_free(char_info);
+}
+
+
+static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
+{
+       if (!svc_info)
+               return;
+
+       g_free(svc_info->serv_path);
+       g_free(svc_info->service_uuid);
+       g_free(svc_info);
+}
+
+static const GDBusInterfaceVTable desc_interface_vtable = {
+        __bt_gatt_desc_method_call,
+        NULL,
+        NULL,
+};
+
+static const GDBusInterfaceVTable char_interface_vtable = {
+        __bt_gatt_char_method_call,
+        NULL,
+        NULL,
+};
+
+static const GDBusInterfaceVTable serv_interface_vtable = {
+        NULL,
+        NULL,
+        NULL,
+};
+
+static const GDBusInterfaceVTable manager_interface_vtable = {
+        __bt_gatt_manager_method_call,
+        NULL,
+        NULL
+};
+
+
+static GDBusNodeInfo *__bt_gatt_create_method_node_info(
+                                const gchar *introspection_data)
+{
+       GError *err = NULL;
+       GDBusNodeInfo *node_info = NULL;
+
+       if (introspection_data == NULL)
+               return NULL;
+
+
+       DBG("Create new node info");
+       node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
+
+       if (err) {
+               ERR("Unable to create node: %s", err->message);
+               g_clear_error(&err);
+               return NULL;
+       }
+
+       return node_info;
+}
+
+/* To send stack event to hal-av handler */
+void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
+{
+       event_cb = cb;
+}
+
+void _bt_hal_unregister_gatt_server_handler_cb(void)
+{
+       event_cb = NULL;
+}
+
+static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
+{
+       struct hal_ev_gatt_desc_added ev;
+       hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
+
+       /* Prepare to GATT characteristic added event */
+       memset(&ev, 0, sizeof(ev));
+       ev.status = BT_STATUS_SUCCESS;
+       ev.server_instance = data->instance_data;
+       memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
+       ev.service_handle = data->srvc_hdl;
+       ev.desc_handle = data->desc_hdl;
+
+       if (!event_cb)
+               ERR("GATT Descriptor Added callback registered");
+       else {
+               DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
+                               data->instance_data, data->srvc_hdl, data->desc_hdl);
+
+               event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
+       }
+
+       g_free(data);
+       return FALSE;
+}
+
+static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
+{
+       struct hal_ev_gatt_char_added ev;
+       hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
+
+       /* Prepare to GATT characteristic added event */
+       memset(&ev, 0, sizeof(ev));
+       ev.status = BT_STATUS_SUCCESS;
+       ev.server_instance = data->instance_data;
+       memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
+       ev.service_handle = data->srvc_hdl;
+       ev.char_handle = data->char_hdl;
+
+       if (!event_cb)
+               ERR("GATT Characteristic Added callback registered");
+       else {
+               DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
+                               data->instance_data, data->srvc_hdl, data->char_hdl);
+
+               event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
+       }
+
+       g_free(data);
+       return FALSE;
+}
+
+static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
+{
+       struct hal_ev_gatt_service_added ev;
+       hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
+
+       /* Prepare to GATT Service added event */
+       memset(&ev, 0, sizeof(ev));
+       ev.status = BT_STATUS_SUCCESS;
+       ev.server_instance = data->instance_data;
+       memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
+       ev.service_handle = data->srvc_hdl;
+       ev.is_primary = data->is_primary;
+
+       if (!event_cb)
+               ERR("GATT Service Added callback registered");
+       else {
+               DBG("GATT Service Added: server if [%d] Service handle [%d]",
+                               data->instance_data,  data->srvc_hdl);
+               event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
+       }
+
+       g_free(data);
+       return FALSE;
+}
+
+static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
+{
+       struct hal_ev_gatt_service_started ev;
+       hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
+
+       /* Prepare to GATT Service added event */
+       memset(&ev, 0, sizeof(ev));
+       ev.status = BT_STATUS_SUCCESS;
+       ev.server_instance = data->instance_data;
+       ev.service_handle = data->srvc_hdl;
+
+       if (!event_cb)
+               ERR("GATT Service Started callback registered");
+       else {
+               DBG("GATT Service Started: server if [%d] Service handle [%d]",
+                               data->instance_data,  data->srvc_hdl);
+               event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
+       }
+
+       g_free(data);
+       return FALSE;
+}
+
+static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
+{
+       struct hal_ev_gatt_service_deleted ev;
+       hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
+
+       /* Prepare to GATT Service added event */
+       memset(&ev, 0, sizeof(ev));
+       ev.status = BT_STATUS_SUCCESS;
+       ev.server_instance = data->instance_data;
+       ev.service_handle = data->srvc_hdl;
+
+       if (!event_cb)
+               ERR("GATT Service Deleted callback registered");
+       else {
+               DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
+                               data->instance_data,  data->srvc_hdl);
+               event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
+       }
+
+       g_free(data);
+       return FALSE;
+}
+
+static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
+{
+       struct hal_ev_server_instance_registered ev;
+       hal_register_server_data *data = (hal_register_server_data*) user_data;
+
+       /* Prepare to send AV connecting event */
+       memset(&ev, 0, sizeof(ev));
+       ev.status = BT_STATUS_SUCCESS;
+       ev.server_instance = data->instance_data;
+       memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
+
+       if (!event_cb)
+               ERR("GATT Register Server Instance Callback not registered");
+       else {
+               DBG("Server Instance is registered!! server if [%d]", data->instance_data);
+               event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
+       }
+
+       g_free(data);
+       return FALSE;
+}
+
+static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
+{
+       CHECK_BTGATT_INIT();
+       int status = BT_STATUS_FAIL;
+       int server_if;
+       DBG("Register server instance request");
+       hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
+
+       /* Check if slot available */
+       server_if = _bt_hal_get_available_adv_slot_id(uuid);
+
+       if (server_if == -1) {
+               ERR("Allocation of server instance failed");
+               g_free(user_data);
+               return status;
+       } else {
+               user_data->instance_data = server_if;
+               DBG("Allocated new Advertising slot with Stack [%d]", user_data->instance_data);
+       }
+
+       /*
+        * As we need to provide async callback to user from HAL, simply schedule a
+        * callback method which will carry actual result
+        */
+       memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
+       g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
+
+       /* If available, then return success, else return error */
+       return BT_STATUS_SUCCESS;
+}
+
+void _bt_hal_remove_gatt_server_from_list(int server_if)
+{
+       GSList *l;
+       struct gatt_server_app *info = NULL;
+
+       for (l = gatt_server_apps; l != NULL;) {
+               info = (struct gatt_server_app*)l->data;
+               l = g_slist_next(l);
+               if (info == NULL)
+                       continue;
+               if (info->slot == server_if) {
+                       INFO("Found Matching GATT Server in List path[%s] slot [%d]",
+                               info->app_path, info->slot);
+
+                       /* Only if all services are deleted from the GATT Server, then only Unregister it.
+                          Reason: it is possible, GATT Server app oly wants to disable multi advertising
+                           In above case, only advertising block will be deallocated, Gatt Server will remain
+                           unaffected */
+                       if (info->services == NULL) {
+                               gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
+                               INFO("Total gatt server apps still existing after removing above is [%d]",
+                                               g_slist_length(gatt_server_apps));
+
+                               /* DBUS Unregister only for current app */
+                               __bt_hal_gatt_deinit(info->app_path);
+
+                               g_free(info->app_path);
+                               g_free(info);
+                               return;
+                       } else {
+                               INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
+                                       g_slist_length(info->services));
+                       }
+               }
+       }
+}
+
+static bt_status_t gatt_server_unregister_app(int server_if)
+{
+       CHECK_BTGATT_INIT();
+       DBG("Un-Register server instance request [%d]", server_if);
+
+       if (_bt_hal_is_advertising_in_slot(server_if) == FALSE)
+               _bt_hal_free_server_slot(server_if);
+
+       /* If server_if belongs to a GATT Server, then delete the GATT server from List */
+       _bt_hal_remove_gatt_server_from_list(server_if);
+       return BT_STATUS_SUCCESS;
+}
+
+static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_SUCCESS;
+}
+
+static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_SUCCESS;
+}
+
+static void __bt_gatt_close_gdbus_connection(void)
+{
+        GError *err = NULL;
+        DBG("+");
+
+        if (g_conn == NULL)
+               return;
+
+        if (!g_dbus_connection_flush_sync(g_conn, NULL, &err)) {
+                ERR("Fail to flush the connection: %s", err->message);
+                g_error_free(err);
+                err = NULL;
+        }
+
+        if (!g_dbus_connection_close_sync(g_conn, NULL, &err)) {
+                if (err) {
+                        ERR("Fail to close the dbus connection: %s", err->message);
+                        g_error_free(err);
+                }
+        }
+
+        g_object_unref(g_conn);
+        g_conn = NULL;
+        DBG("-");
+}
+
+static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
+{
+       GDBusConnection *local_system_gconn = NULL;
+       char *address;
+       GError *err = NULL;
+
+       if (g_conn == NULL) {
+               address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+               if (address == NULL) {
+                       if (err) {
+                               ERR("Failed to get bus address: %s", err->message);
+                               g_clear_error(&err);
+                       }
+                       return NULL;
+               }
+
+               g_conn = g_dbus_connection_new_for_address_sync(address,
+                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
+                               G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
+                               NULL, /* GDBusAuthObserver */
+                               NULL,
+                               &err);
+               if (!g_conn) {
+                       if (err) {
+                               ERR("Unable to connect to dbus: %s", err->message);
+                               g_clear_error(&err);
+                       }
+                       return NULL;
+               }
+       } else if (g_dbus_connection_is_closed(g_conn)) {
+               address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+               if (address == NULL) {
+                       if (err) {
+                               ERR("Failed to get bus address: %s", err->message);
+                               g_clear_error(&err);
+                       }
+                       return NULL;
+               }
+
+               local_system_gconn = g_dbus_connection_new_for_address_sync(address,
+                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
+                               G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
+                               NULL, /* GDBusAuthObserver */
+                               NULL,
+                               &err);
+
+               if (!local_system_gconn) {
+                       ERR("Unable to connect to dbus: %s", err->message);
+                       g_clear_error(&err);
+               }
+
+               g_conn = local_system_gconn;
+       }
+
+       return g_conn;
+}
+
+static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
+{
+       char uuid_buf[5];
+       const char *uuid;
+
+       uuid = btuuid2str(srvc_id->uu);
+       DBG("Original UUID [%s]", uuid);
+
+       if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
+               /* Extract Standard UUID string */
+               memcpy(uuid_buf, &uuid[4], 4);
+               uuid_buf[4] = '\0';
+               DBG("Converted string [%s]", uuid_buf);
+               return g_strdup(uuid_buf);
+       } else
+               return strdup(uuid);
+}
+
+int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
+{
+       /* For GATT service specific */
+       GDBusNodeInfo *node_info;
+       guint object_id;
+       gchar *path = NULL;
+       struct gatt_service_info *serv_info = NULL;
+       GVariantBuilder *builder = NULL;
+       GVariantBuilder *builder1 = NULL;
+       GVariantBuilder *inner_builder = NULL;
+       gboolean svc_primary = TRUE;
+       GError *error = NULL;
+       hal_gatt_service_added *user_data = NULL;
+       DBG("Service add to DBUS slot [%d]", slot);
+
+       node_info = __bt_gatt_create_method_node_info(
+                       service_introspection_xml);
+
+       if (node_info == NULL)
+               return BT_STATUS_FAIL;
+
+       DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
+       path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
+       DBG("gatt service path is [%s]", path);
+
+       object_id = g_dbus_connection_register_object(g_conn, path,
+                       node_info->interfaces[0],
+                       &serv_interface_vtable,
+                       NULL, NULL, &error);
+
+       if (object_id == 0) {
+               ERR("failed to register: %s", error->message);
+               g_error_free(error);
+               g_free(path);
+               return BT_STATUS_FAIL;
+       }
+       /* Add object_id/gatt service information; it's required at the time of
+        *  service unregister and Getmanagedobjects
+        */
+       serv_info = g_new0(struct gatt_service_info, 1);
+
+       serv_info->serv_path = g_strdup(path);
+       serv_info->serv_id = object_id;
+       serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
+       serv_info->is_svc_registered = FALSE;
+       serv_info->is_svc_primary = svc_primary;
+       DBG("Service Handle to be added is [%d]", gatt_service_handle);
+       serv_info->service_handle = gatt_service_handle;
+
+       /* Update service in GATT Server service List */
+       gatt_services = g_slist_append(gatt_services, serv_info);
+
+       /* emit interfacesadded signal here for service path */
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
+       inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+
+       g_variant_builder_add(inner_builder, "{sv}",
+                       "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
+
+       g_variant_builder_add(inner_builder, "{sv}",
+                       "Primary", g_variant_new_boolean(svc_primary));
+
+       builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
+
+       g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
+                       g_variant_new("ao", builder1));
+
+       g_variant_builder_add(builder, "{sa{sv}}",
+                       GATT_SERV_INTERFACE, inner_builder);
+
+       g_dbus_connection_emit_signal(g_conn, NULL, "/",
+                       "org.freedesktop.Dbus.ObjectManager",
+                       "InterfacesAdded",
+                       g_variant_new("(oa{sa{sv}})",
+                               path, builder),
+                       &error);
+
+       /* Send Service handle to application */
+       user_data = g_malloc0(sizeof(hal_gatt_service_added));
+       user_data->srvc_hdl = serv_info->service_handle;
+       user_data->instance_data = slot;
+       memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
+       g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
+
+       /* Save newly created service in GATT Server's service list */
+       _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
+
+       /* Free data */
+       g_free(path);
+       g_variant_builder_unref(inner_builder);
+       g_variant_builder_unref(builder);
+       g_variant_builder_unref(builder1);
+       return BT_STATUS_SUCCESS;
+}
+
+static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
+                gpointer user_data)
+{
+       char *app_path = (char*)user_data;
+        INFO("UnregisterApplication is completed app [%s]", app_path);
+        GError *error = NULL;
+        GVariant *result;
+
+        result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
+
+        if (result == NULL) {
+                /* dBUS-RPC is failed */
+                ERR("Dbus-RPC is failed\n");
+
+                if (error != NULL) {
+                        /* dBUS gives error cause */
+                        ERR("D-Bus API failure: errCode[%x], message[%s]\n",
+                                        error->code, error->message);
+                        g_clear_error(&error);
+                }
+        } else {
+                g_variant_unref(result);
+        }
+       g_free(app_path);
+}
+
+static void __bt_hal_gatt_deinit(char *app_path)
+{
+       GDBusProxy *proxy = NULL;
+       char *data;
+       INFO("+");
+
+       /* Step1: Remove requested App */
+       proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
+                       "/org/bluez/hci0", "org.bluez.GattManager1");
+
+       if (proxy == NULL)
+               return;
+
+       INFO("UnregisterApplication : path [%s]", app_path);
+
+       /* Async Call to Unregister Service */
+       data = g_strdup(app_path);
+       g_dbus_proxy_call(proxy,
+                       "UnregisterApplication",
+                       g_variant_new("(o)",
+                               app_path),
+                       G_DBUS_CALL_FLAGS_NONE, -1,
+                       NULL,
+                       (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
+                       (gpointer)data);
+
+       /* If requested app is last GATT Server app, then clean all resources */
+       if (gatt_server_apps == NULL) {
+               INFO("All GATT servers are removed, clean all DBUS resources");
+               if (owner_id) {
+                       /* unregister the exported interface for object manager
+                          g_conn and manager_id are common for all GATT servers */
+                       g_dbus_connection_unregister_object(g_conn,
+                                       manager_id);
+                       manager_id = 0;
+                       g_bus_unown_name(owner_id);
+                       owner_id = 0;
+
+                       g_object_unref(manager_gproxy);
+                       manager_gproxy = NULL;
+
+                       /* Close the GDBUS connection */
+                       __bt_gatt_close_gdbus_connection();
+               }
+       }
+       INFO("-");
+}
+
+int __bt_hal_gatt_init(void)
+{
+       GDBusConnection *conn = NULL;
+       DBG("+");
+       /* Only once for ALL GATT Servers */
+       if (owner_id == 0) {
+               owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
+                               BT_GATT_SERVICE_NAME,
+                               G_BUS_NAME_OWNER_FLAGS_NONE,
+                               NULL, NULL, NULL, NULL, NULL);
+       }
+       INFO("Owner ID [%d]", owner_id);
+
+       /* Only once for ALL GATT Servers conn = g_conn(global)*/
+       conn = __bt_gatt_get_gdbus_connection();
+       if (!conn) {
+               ERR("Unable to get connection");
+               return BT_STATUS_FAIL;
+       }
+
+       /* Only once for ALL GATT Servers */
+       if (manager_node_info == NULL) {
+               /* Register ObjectManager interface */
+               manager_node_info = __bt_gatt_create_method_node_info(
+                               manager_introspection_xml);
+
+               if (manager_node_info == NULL) {
+                       ERR("failed to get node info");
+                       return BT_STATUS_FAIL;
+               }
+       }
+
+       INFO("-");
+       return BT_STATUS_SUCCESS;
+}
+
+void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
+{
+       GSList *l;
+
+       for (l = gatt_server_apps; l; l = g_slist_next(l)) {
+               struct gatt_server_app *app = (struct gatt_server_app *)l->data;
+               if (app->slot == slot) {
+                       INFO("GATT Server app found app path [%s] instance [%d]",
+                                       app->app_path, app->slot);
+                       *app_path = app->app_path;
+                       return;
+               }
+       }
+       /* GATT Server not found */
+       *app_path = NULL;
+}
+
+void _bt_hal_update_gatt_server_path(int slot, char *app_path)
+{
+       if (app_path == NULL)
+               return;
+
+       struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
+       app->app_path = g_strdup(app_path);
+       app->slot = slot;
+       gatt_server_apps = g_slist_append(gatt_server_apps, app);
+       INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
+
+}
+
+
+static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
+               int num_handles)
+{
+       CHECK_BTGATT_INIT();
+       char *app_path = NULL;
+       GError *error = NULL;
+       int *app_id = NULL;
+       guint manager_id;
+
+       int result = BT_STATUS_SUCCESS;
+
+       DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
+                       server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
+
+       /* Check if this GATT server Application is already registered with DBUS */
+       _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
+
+       if (app_path != NULL) {
+               DBG("GATT server path is already defined [%s]", app_path);
+               return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
+       } else {
+               DBG("GATT server application path for instance [%d] is not defined yet", server_if);
+               result = __bt_hal_gatt_init();
+               if (result != BT_STATUS_SUCCESS)
+                       return result;
+
+               /* Only once for each GATT Server */
+               app_path = g_strdup_printf("/com/%d", server_if);
+
+               app_id = g_malloc0(sizeof(int));
+               *app_id = server_if;
+
+               manager_id = g_dbus_connection_register_object(g_conn, app_path,
+                               manager_node_info->interfaces[0],
+                               &manager_interface_vtable,
+                               (gpointer)app_id, NULL, &error);
+
+               if (manager_id == 0) {
+                       ERR("failed to register: %s", error->message);
+                       g_error_free(error);
+                       goto failed;
+               }
+
+               /* For current GATT Server, app_path is created, save it in Table */
+               _bt_hal_update_gatt_server_path(server_if, app_path);
+
+               /* Add GATT Service to DBUS */
+               if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
+                       goto failed;
+       }
+
+       INFO("Successfully added service");
+       return BT_STATUS_SUCCESS;
+failed:
+       if (app_id)
+               g_free(app_id);
+       if (app_path)
+               g_free(app_path);
+       INFO("Service addition failed!!");
+       return BT_STATUS_FAIL;
+}
+
+static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
+               int included_handle)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_SUCCESS;
+}
+
+
+static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
+{
+       GSList *l;
+       GSList *gatt_services = NULL;
+       int len;
+       struct gatt_service_info *info = NULL;
+
+       gatt_services =  _bt_get_service_list_from_server(instance);
+
+       len = g_slist_length(gatt_services);
+       l = g_slist_nth(gatt_services, len -1);
+
+       info = l->data;
+
+       if (info->service_handle == service_handle)
+               return TRUE;
+       return FALSE;
+}
+
+static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
+                        int service_handle)
+{
+       GSList *l;
+       GSList *gatt_services = NULL;
+       INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
+
+       gatt_services = _bt_get_service_list_from_server(instance);
+
+       for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
+               struct gatt_service_info *info = l->data;
+               INFO("Got one service with handle [%d]", info->service_handle);
+               if (info->service_handle == service_handle) {
+                       return info;
+               }
+       }
+       ERR("Gatt service with handle [%d] not found", service_handle);
+       return NULL;
+}
+
+static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
+               bt_uuid_t *uuid, int properties,
+               int permissions)
+{
+        GError *error = NULL;
+        guint object_id;
+        GDBusNodeInfo *node_info;
+        gchar *path = NULL;
+        GVariantBuilder *builder = NULL;
+        GVariantBuilder *inner_builder = NULL;
+        struct gatt_service_info *serv_info = NULL;
+        struct gatt_char_info *char_info = NULL;
+        GVariantBuilder *builder2 = NULL;
+        GVariantBuilder *builder3 = NULL;
+        GVariant *flags_val = NULL;
+        int i = 0;
+        char *char_flags[NUMBER_OF_FLAGS];
+        int flag_count = 0;
+       hal_gatt_char_added *user_data = NULL;
+       int *app_id;
+
+       CHECK_BTGATT_INIT();
+       DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
+       DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
+
+       serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
+       if (serv_info == NULL)
+               return BT_STATUS_FAIL;
+
+       node_info = __bt_gatt_create_method_node_info(
+                       characteristics_introspection_xml);
+
+       if (node_info == NULL)
+               return BT_STATUS_FAIL;
+
+       DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
+       path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
+       DBG("gatt characteristic path is [%s]", path);
+
+       app_id = g_malloc0(sizeof(int));
+       *app_id = slot;
+
+       object_id = g_dbus_connection_register_object(g_conn, path,
+                       node_info->interfaces[0],
+                       &char_interface_vtable,
+                       (gpointer)app_id, NULL, &error);
+
+       if (object_id == 0) {
+               ERR("failed to register: %s", error->message);
+               g_error_free(error);
+               g_free(path);
+
+               return BT_STATUS_FAIL;
+       }
+
+       if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
+               properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
+       if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
+               properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
+       if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
+               properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
+       if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
+               properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
+
+       flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
+
+       char_info = g_new0(struct gatt_char_info, 1);
+
+       char_info->char_path = g_strdup(path);
+       char_info->char_id = object_id;
+       char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
+       for (i = 0; i < flag_count; i++)
+               char_info->char_flags[i] = char_flags[i];
+
+
+       char_info->flags_length = flag_count;
+       char_info->char_handle = gatt_char_handle;
+
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
+       inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+
+       g_variant_builder_add(inner_builder, "{sv}", "UUID",
+                       g_variant_new("s", char_info->char_uuid));
+       g_variant_builder_add(inner_builder, "{sv}", "Service",
+                       g_variant_new("o", serv_info->serv_path));
+
+       builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
+
+       for (i = 0; i < flag_count; i++)
+               g_variant_builder_add(builder2, "s", char_flags[i]);
+
+       flags_val = g_variant_new("as", builder2);
+       g_variant_builder_add(inner_builder, "{sv}", "Flags",
+                       flags_val);
+
+       builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
+
+       g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
+                       g_variant_new("ao", builder3));
+
+       g_variant_builder_add(builder, "{sa{sv}}",
+                       GATT_CHAR_INTERFACE,
+                       inner_builder);
+
+       g_dbus_connection_emit_signal(g_conn, NULL, "/",
+                       "org.freedesktop.Dbus.ObjectManager",
+                       "InterfacesAdded",
+                       g_variant_new("(oa{sa{sv}})",
+                               path, builder),
+                       &error);
+
+       //*char_path = g_strdup(path);
+
+       //new_char = TRUE;
+
+
+       /* Send Service handle to application */
+       user_data = g_malloc0(sizeof(hal_gatt_char_added));
+       user_data->srvc_hdl = serv_info->service_handle;
+       user_data->char_hdl = gatt_char_handle;
+       user_data->instance_data = slot;
+       memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
+       g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
+
+       /* Save newly created charatcristic to GATT Server's service's characteristic  list */
+       serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
+
+       /* Free data */
+       g_free(path);
+
+       g_variant_builder_unref(inner_builder);
+       g_variant_builder_unref(builder);
+       g_variant_builder_unref(builder2);
+       g_variant_builder_unref(builder3);
+
+       return BT_STATUS_SUCCESS;
+}
+
+static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
+               int permissions)
+{
+       CHECK_BTGATT_INIT();
+
+//     static int desc_id = 1;
+       GError *error = NULL;
+       guint object_id;
+       GDBusNodeInfo *node_info;
+       gchar *path = NULL;
+       GVariantBuilder *builder = NULL;
+       GVariantBuilder *inner_builder = NULL;
+
+       struct gatt_char_info *char_info = NULL;
+       struct gatt_desc_info *desc_info = NULL;
+       struct gatt_service_info *serv_info = NULL;
+
+       gchar **line_argv = NULL;
+       char *serv_path;
+       char *char_path = NULL;
+       GSList *l;
+
+       GVariantBuilder *builder2 = NULL;
+       GVariant *flags_val = NULL;
+       int i = 0;
+       char *desc_flags[NUMBER_OF_FLAGS];
+       int flag_count = 0;
+       int *app_id;
+
+       hal_gatt_desc_added *user_data = NULL;
+#if 0
+       if (new_char) {
+               desc_id = 1;
+               new_char = FALSE;
+       }
+#endif
+       /* Fetch service data for the GATT server */
+       serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
+        if (serv_info == NULL)
+                return BT_STATUS_FAIL;
+
+       /* Fetch list of characteristics from the service info */
+       l = serv_info->char_data;
+
+       /* Fetch last char info from the characteristic list */
+       char_info = g_slist_last(l)->data;
+       if (char_info == NULL) {
+               return BT_STATUS_FAIL;
+       }
+
+       /* Fetch characteristic path from char info */
+       char_path = char_info->char_path;
+
+       line_argv = g_strsplit_set(char_path, "/", 0);
+       serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
+
+
+       node_info = __bt_gatt_create_method_node_info(
+                       descriptor_introspection_xml);
+
+       if (node_info == NULL) {
+               g_strfreev(line_argv);
+               g_free(serv_path);
+               return BT_STATUS_FAIL;
+       }
+
+       DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
+
+       path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
+       DBG("gatt descriptor path is [%s]", path);
+
+       app_id = g_malloc0(sizeof(int));
+        *app_id = slot;
+
+       object_id = g_dbus_connection_register_object(g_conn, path,
+                       node_info->interfaces[0],
+                       &desc_interface_vtable,
+                       (gpointer)app_id, NULL, &error);
+
+       if (object_id == 0) {
+               ERR("failed to register: %s", error->message);
+               g_error_free(error);
+               g_free(path);
+               g_strfreev(line_argv);
+               g_free(serv_path);
+
+               return BT_STATUS_FAIL;
+       }
+
+       flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
 
-static handle_stack_msg event_cb = NULL;
+       desc_info = g_new0(struct gatt_desc_info, 1);
 
-typedef struct {
-       uint32_t instance_data;
-       bt_uuid_t uuid;
-} hal_register_server_data;
+       desc_info->desc_path = g_strdup(path);
+       desc_info->desc_id = object_id;
+       desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
 
-#define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
-{\
-       ERR("%s: BTGATT not initialized", __FUNCTION__);\
-       return BT_STATUS_NOT_READY;\
-} else {\
-       DBG("%s", __FUNCTION__);\
-}
+       for (i = 0; i < flag_count; i++)
+               desc_info->desc_flags[i] = desc_flags[i];
 
-/* To send stack event to hal-av handler */
-void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
-{
-       event_cb = cb;
-}
+       desc_info->flags_length = flag_count;
+       desc_info->desc_handle = gatt_desc_handle;
 
-void _bt_hal_unregister_gatt_server_handler_cb(void)
-{
-       event_cb = NULL;
-}
 
-static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
-{
-       struct hal_ev_server_instance_registered ev;
-       hal_register_server_data *data = (hal_register_server_data*) user_data;
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
+       inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
 
-       /* Prepare to send AV connecting event */
-       memset(&ev, 0, sizeof(ev));
-       ev.status = BT_STATUS_SUCCESS;
-       ev.server_instance = data->instance_data;
-       memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
+       g_variant_builder_add(inner_builder, "{sv}", "UUID",
+                       g_variant_new("s", btuuid2str(uuid->uu)));
+       g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
+                       g_variant_new("o", char_path));
 
-       if (!event_cb)
-               ERR("GATT Register Server Instance Callback not registered");
-       else {
-               DBG("Server Instance is registered!! server if [%d]", data->instance_data);
-               event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
+       builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
 
-       }
+       for (i = 0; i < flag_count; i++)
+               g_variant_builder_add(builder2, "s", desc_flags[i]);
 
-       g_free(data);
-       return FALSE;
-}
+       flags_val = g_variant_new("as", builder2);
+       g_variant_builder_add(inner_builder, "{sv}", "Flags",
+                       flags_val);
 
-static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
-{
-       CHECK_BTGATT_INIT();
-       int status = BT_STATUS_FAIL;
-       int server_if;
-       DBG("Register server instance request");
-       hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
+       g_variant_builder_add(builder, "{sa{sv}}",
+                       GATT_DESC_INTERFACE,
+                       inner_builder);
 
-       /* Check if slot available */
-       server_if = _bt_hal_get_available_adv_slot_id(uuid);
+       g_dbus_connection_emit_signal(g_conn, NULL, "/",
+                       "org.freedesktop.Dbus.ObjectManager",
+                       "InterfacesAdded",
+                       g_variant_new("(oa{sa{sv}})",
+                               path, builder),
+                       &error);
 
-       if (server_if == -1) {
-               ERR("Allocation of server instance failed");
-               g_free(user_data);
-               return status;
-       } else {
-               user_data->instance_data = server_if;
-               DBG("Allocated new Advertising slot with Stack [%d]", user_data->instance_data);
-       }
+       //*desc_path = g_strdup(path);
 
-       /*
-        * As we need to provide async callback to user from HAL, simply schedule a
-        * callback method which will carry actual result
-        */
-       memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
-       g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
+       /* Save newly created descriptor to GATT server's service's characteristic */
+       char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
 
-       /* If available, then return success, else return error */
-       return BT_STATUS_SUCCESS;
-}
+       /* Send descriptor handle to application */
+       user_data = g_malloc0(sizeof(hal_gatt_desc_added));
+       user_data->srvc_hdl = serv_info->service_handle;
+       user_data->desc_hdl = gatt_desc_handle;
+       user_data->instance_data = slot;
+       memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
+       g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
 
-static bt_status_t gatt_server_unregister_app(int server_if)
-{
-       CHECK_BTGATT_INIT();
-       DBG("Un-Register server instance request [%d]", server_if);
-       _bt_hal_free_server_slot(server_if);
+       /* Free data */
+       g_free(path);
+       g_free(serv_path);
+       g_strfreev(line_argv);
+       g_variant_builder_unref(inner_builder);
+       g_variant_builder_unref(builder);
        return BT_STATUS_SUCCESS;
 }
 
-static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
+static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
 {
-       CHECK_BTGATT_INIT();
-       return BT_STATUS_SUCCESS;
-}
+       GError *error = NULL;
+       GVariant *result;
+       char *data = (char*) user_data;
+       INFO("RegisterApplication is completed path [%s]", data);
 
-static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
-{
-       CHECK_BTGATT_INIT();
-       return BT_STATUS_SUCCESS;
-}
+       result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
 
-static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
-               int num_handles)
-{
-       CHECK_BTGATT_INIT();
-       return BT_STATUS_SUCCESS;
+       if (result == NULL) {
+               /* dBUS-RPC is failed */
+               ERR("Dbus-RPC is failed\n");
+
+               if (error != NULL) {
+                       /* dBUS gives error cause */
+                       ERR("D-Bus API failure: errCode[%x], message[%s]\n",
+                                       error->code, error->message);
+                       g_clear_error(&error);
+               }
+       } else {
+               g_variant_unref(result);
+       }
+       g_free(data);
 }
 
-static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
-               int included_handle)
+static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
+                                const gchar *path, const gchar *interface)
 {
-       CHECK_BTGATT_INIT();
-       return BT_STATUS_SUCCESS;
+       GDBusProxy *proxy;
+       GError *err = NULL;
+
+       if (g_conn == NULL)
+               g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
+                               NULL, &err);
+
+       if (!g_conn) {
+               if (err) {
+                       ERR("Unable to connect to gdbus: %s", err->message);
+                       g_clear_error(&err);
+               }
+               return NULL;
+       }
+
+       proxy =  g_dbus_proxy_new_sync(g_conn,
+                       G_DBUS_PROXY_FLAGS_NONE, NULL,
+                       service, path,
+                       interface, NULL, &err);
+
+       if (!proxy) {
+               if (err) {
+                       ERR("Unable to create proxy: %s", err->message);
+                       g_clear_error(&err);
+               }
+               return NULL;
+       }
+       manager_gproxy = proxy;
+
+       return proxy;
 }
 
-static bt_status_t gatt_server_add_characteristic(int server_if, int service_handle,
-               bt_uuid_t *uuid, int properties,
-               int permissions)
+static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
+                                const gchar *path, const gchar *interface)
 {
-       CHECK_BTGATT_INIT();
-       return BT_STATUS_SUCCESS;
+        return (manager_gproxy) ? manager_gproxy :
+                        __bt_hal_gatt_gdbus_init_manager_proxy(service,
+                                path, interface);
 }
 
-static bt_status_t gatt_server_add_descriptor(int server_if, int service_handle, bt_uuid_t *uuid,
-               int permissions)
+static void __bt_register_application_to_dbus(int slot)
 {
-       CHECK_BTGATT_INIT();
-       return BT_STATUS_SUCCESS;
+       GDBusProxy *proxy = NULL;
+       char *app_path = NULL;
+       char *data;
+       DBG("RegisterApplication slot [%d]", slot);
+
+       /* It is impossible that app path is still not initialized */
+       _bt_hal_is_gatt_server_initialzed(slot, &app_path);
+
+       proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
+                       "/org/bluez/hci0", "org.bluez.GattManager1");
+
+       data = g_strdup(app_path);
+       g_dbus_proxy_call(proxy,
+                       "RegisterApplication",
+                       g_variant_new("(oa{sv})",
+                               app_path, NULL),
+                       G_DBUS_CALL_FLAGS_NONE, -1,
+                       NULL,
+                       (GAsyncReadyCallback)__bt_hal_register_application_cb,
+                       (gpointer)data);
+       INFO("GATT server started");
 }
 
 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
 {
        CHECK_BTGATT_INIT();
+       struct gatt_service_info *serv_info = NULL;
+       hal_gatt_service_started *user_data = NULL;
+       DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
+
+       /* Fetch service data for the GATT server */
+       serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
+       if (serv_info == NULL)
+               return BT_STATUS_FAIL;
+
+       if (serv_info->is_svc_registered) {
+               DBG("service already registered \n");
+       }
+
+       serv_info->is_svc_registered = TRUE;
+
+       /* Send Service handle to application */
+        user_data = g_malloc0(sizeof(hal_gatt_service_started));
+        user_data->srvc_hdl = serv_info->service_handle;
+        user_data->instance_data = server_if;
+        g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
+
+       /* If this is nth Service that is started, then register application at this point */
+       if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
+               DBG("This is the last service started from the GATT Server's list of services handle [%d]",
+                       service_handle);
+               __bt_register_application_to_dbus(server_if);
+       }
+
        return BT_STATUS_SUCCESS;
 }
 
 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
 {
        CHECK_BTGATT_INIT();
+       INFO("Stop service successful");
        return BT_STATUS_SUCCESS;
 }
 
 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
 {
        CHECK_BTGATT_INIT();
-       return BT_STATUS_SUCCESS;
+       struct gatt_service_info *serv_info = NULL;
+       hal_gatt_service_deleted *user_data = NULL;
+       GSList *l = NULL;
+       GSList *l1 = NULL;
+       int err = BT_STATUS_SUCCESS;
+       int ret = BT_STATUS_SUCCESS;
+       INFO("Slot [%d] service handle [%d]", server_if, service_handle);
+
+       /* Fetch service data for the GATT server */
+       serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
+       if (serv_info == NULL) {
+               ERR("Could not find service info svc handle [%d] server slot [%d]",
+                               service_handle, server_if);
+               return BT_STATUS_FAIL;
+       }
+
+       if (serv_info->is_svc_registered == FALSE) {
+               ERR("service Not registered path [%s] handle [%d]",
+                       serv_info->serv_path, service_handle);
+       }
+
+       for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
+               struct gatt_char_info *char_info = l->data;
+
+               if (char_info == NULL)
+                       break;
+
+               for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
+                       struct gatt_desc_info *desc_info = l1->data;
+
+                       if (desc_info == NULL)
+                               break;
+
+                       ret = g_dbus_connection_unregister_object(g_conn,
+                                       desc_info->desc_id);
+                       if (ret) {
+                               __bt_hal_gatt_emit_interface_removed(
+                                               desc_info->desc_path,
+                                               GATT_DESC_INTERFACE);
+                       } else {
+                               err = BT_STATUS_FAIL;
+                       }
+
+                       /* list remove & free */
+                       char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
+                       __bt_hal_gatt_free_descriptor_info(desc_info);
+               }
+
+               g_slist_free(char_info->desc_data);
+               char_info->desc_data = NULL;
+
+               ret = g_dbus_connection_unregister_object(g_conn,
+                               char_info->char_id);
+               if (ret) {
+                       __bt_hal_gatt_emit_interface_removed(char_info->char_path,
+                                       GATT_CHAR_INTERFACE);
+               } else {
+                       INFO("Err");
+                       err = BT_STATUS_FAIL;
+               }
+
+               /* list remove & free */
+               serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
+               __bt_hal_gatt_free_characteristic_info(char_info);
+       }
+
+       g_slist_free(serv_info->char_data);
+       serv_info->char_data = NULL;
+
+       ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
+       if (ret) {
+               __bt_hal_gatt_emit_interface_removed(serv_info->serv_path,
+                               GATT_SERV_INTERFACE);
+       } else {
+               INFO("Failed!!");
+               err = BT_STATUS_FAIL;
+       }
+
+       ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
+       if (ret)
+               DBG("Unregistered the service on properties interface");
+
+       /* Remove from global list */
+       gatt_services = g_slist_remove(gatt_services, serv_info);
+       INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
+
+       /* Remove from GATT Server's list of services */
+       _bt_remote_service_from_gatt_server(server_if, service_handle);
+
+       if (gatt_services == NULL) {
+               INFO("All GATT Services of all GATT Servers are unregistered");
+       }
+
+       if (err == BT_STATUS_SUCCESS) {
+               INFO("Send GATT Service deleted Event");
+               /* Send Service handle to application */
+               user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
+               user_data->srvc_hdl = serv_info->service_handle;
+               user_data->instance_data = server_if;
+               g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
+       }
+
+       /* Free the service */
+       __bt_hal_gatt_free_service_info(serv_info);
+       return err;
+}
+
+static gboolean __bt_gatt_get_service_state(const char *service_path)
+{
+        struct gatt_service_info *svc_info = NULL;
+        GSList *l = NULL;
+
+        for (l= gatt_services; l; l = g_slist_next(l)) {
+
+                svc_info = (struct gatt_service_info *)l->data;
+                if (svc_info->serv_path == service_path) {
+                        DBG("Return the state of the gatt service %d",
+                                        svc_info->is_svc_registered);
+                        return svc_info->is_svc_registered;
+                }
+        }
+
+        DBG("gatt service info is NULL");
+        return FALSE;
 }
 
 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
                int len, int confirm, char* p_value)
 {
        CHECK_BTGATT_INIT();
-       return BT_STATUS_SUCCESS;
+
+       /* For Notifying */
+       GVariantBuilder *outer_builder;
+        GVariantBuilder *invalidated_builder;
+
+       /* For Value update via PropertyChange */
+       GVariantBuilder *outer_builder1;
+       GVariantBuilder *inner_builder1;
+       GVariantBuilder *invalidated_builder1;
+       GVariant *update_value = NULL;
+
+       /* Other variables */
+       struct gatt_client_info_t *conn_info = NULL;
+       gchar *serv_path = NULL;
+       char *char_path = NULL;
+       gchar **line_argv = NULL;
+       gboolean notify = TRUE;
+       gboolean ret = TRUE;
+       int err = BT_STATUS_SUCCESS;
+       char addr[20];
+       GError *error = NULL;
+       int i;
+
+       memset(addr, 0x00, sizeof(addr));
+
+       conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
+       if (conn_info == NULL) {
+               ERR("No Connection Inforamtion!!!");
+               return BT_STATUS_FAIL;
+       }
+
+       DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
+
+       char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
+       if (char_path == NULL)
+               return BT_STATUS_FAIL;
+
+       line_argv = g_strsplit_set(char_path, "/", 0);
+       serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
+
+       if (!__bt_gatt_get_service_state(serv_path)) {
+               DBG("service not registered for this characteristic \n");
+               g_free(serv_path);
+               g_strfreev(line_argv);
+               return BT_STATUS_FAIL;
+       }
+
+       outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+
+       g_variant_builder_add(outer_builder, "{sv}", "Notifying",
+                       g_variant_new("b", notify));
+
+       _bt_convert_addr_type_to_string(addr, (unsigned char *)conn_info->addr);
+
+       g_variant_builder_add(outer_builder, "{sv}", "Unicast",
+                       g_variant_new("s", addr));
+
+       DBG("Set characteristic Notification \n");
+       ret = g_dbus_connection_emit_signal(g_conn, NULL,
+                       char_path,
+                       "org.freedesktop.DBus.Properties",
+                       "PropertiesChanged",
+                       g_variant_new("(sa{sv}as)",
+                               "org.bluez.GattCharacteristic1",
+                               outer_builder, invalidated_builder),
+                       &error);
+
+       if (!ret) {
+               if (error != NULL) {
+                       ERR("D-Bus API failure: errCode[%x], \
+                                       message[%s]",
+                                       error->code, error->message);
+                       g_clear_error(&error);
+               }
+               err = BT_STATUS_FAIL;
+       }
+
+       g_variant_builder_unref(outer_builder);
+       g_variant_builder_unref(invalidated_builder);
+
+
+       /* Notifying Done, now update Value to Bluez via PropertyChanged */
+       invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
+
+       inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
+       for (i = 0; i < len; i++)
+               g_variant_builder_add(inner_builder1, "y", p_value[i]);
+
+       update_value = g_variant_new("ay", inner_builder1);
+
+
+       outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
+       g_variant_builder_add(outer_builder1, "{sv}", "Value",
+                       update_value);
+
+       DBG("Updating characteristic value \n");
+       ret = g_dbus_connection_emit_signal(g_conn, NULL,
+                       char_path,
+                       "org.freedesktop.DBus.Properties",
+                       "PropertiesChanged",
+                       g_variant_new("(sa{sv}as)",
+                               "org.bluez.GattCharacteristic1",
+                               outer_builder1, invalidated_builder1),
+                       &error);
+
+       if (!ret) {
+               if (error != NULL) {
+                       ERR("D-Bus API failure: errCode[%x], \
+                                       message[%s]",
+                                       error->code, error->message);
+                       g_clear_error(&error);
+               }
+               err = BT_STATUS_FAIL;
+       } else {
+               struct gatt_char_info *char_info = NULL;
+
+               char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
+               if (char_info == NULL) {
+                       g_free(serv_path);
+                       g_strfreev(line_argv);
+                       g_variant_builder_unref(inner_builder1);
+                       g_variant_builder_unref(outer_builder1);
+                       g_variant_builder_unref(invalidated_builder1);
+
+                       return BT_STATUS_FAIL;
+               }
+
+               char_info->value_length = len;
+
+               char_info->char_value = (char *)realloc(char_info->char_value, len);
+               if (char_info->char_value) {
+                       for (i = 0; i < len; i++)
+                               char_info->char_value[i] = p_value[i];
+               }
+       }
+
+       g_free(serv_path);
+       g_strfreev(line_argv);
+       g_variant_builder_unref(inner_builder1);
+       g_variant_builder_unref(outer_builder1);
+       g_variant_builder_unref(invalidated_builder1);
+
+       return err;
 }
 
 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
                int status, btgatt_response_t *response)
 {
        CHECK_BTGATT_INIT();
+
+       struct gatt_req_info *req_info = NULL;
+       struct gatt_client_info_t *conn_info = NULL;
+       int i;
+
+       DBG("GATT Server Send Response Conn ID [%d]", conn_id);
+
+       conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
+       if (conn_info == NULL) {
+               ERR("No Connection Inforamtion!!!");
+               return BT_STATUS_FAIL;
+       }
+
+       req_info =  __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
+       if (req_info == NULL) {
+               ERR("No Request Inforamtion!!!");
+               return BT_STATUS_FAIL;
+       }
+
+       if (status != BT_STATUS_SUCCESS) {
+               ERR("resp_state is 0x%X", status);
+
+               g_dbus_method_invocation_return_dbus_error(req_info->context,
+                               "org.bluez.Error.Failed", "Application Error");
+
+               conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
+
+               req_info->context = NULL;
+               if (req_info->attr_path)
+                       g_free(req_info->attr_path);
+               if (req_info->svc_path)
+                       g_free(req_info->svc_path);
+               g_free(req_info);
+
+               return BT_STATUS_SUCCESS;
+       }
+
+       DBG("Reponse Value length [%d]", response->attr_value.len);
+       /* DEBUG */
+       for(i=0; i < response->attr_value.len; i++) {
+               DBG("Resonse [%d] = [0x%x]", response->attr_value.value[i]);
+
+       }
+
+       if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
+               GVariantBuilder *inner_builder = NULL;
+               inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
+
+               if (response->attr_value.len > 0) {
+                       for (i = 0; i < response->attr_value.len; i++)
+                               g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
+               }
+               g_dbus_method_invocation_return_value(req_info->context,
+                               g_variant_new("(ay)", inner_builder));
+
+               g_variant_builder_unref(inner_builder);
+       } else {
+               g_dbus_method_invocation_return_value(req_info->context, NULL);
+       }
+       conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
+
+       req_info->context = NULL;
+       if (req_info->attr_path)
+               g_free(req_info->attr_path);
+       if (req_info->svc_path)
+               g_free(req_info->svc_path);
+       g_free(req_info);
+
        return BT_STATUS_SUCCESS;
 }
 
+static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
+                int value_length, char* att_value)
+{
+       CHECK_BTGATT_INIT();
+
+       /* Other variables */
+       char *char_path = NULL;
+       gboolean ret = TRUE;
+       GError *error = NULL;
+
+       GVariantBuilder *outer_builder;
+       GVariantBuilder *inner_builder;
+       GVariantBuilder *invalidated_builder;
+       GVariant *update_value = NULL;
+       int err = BT_STATUS_SUCCESS;
+       int i = 0;
+       gchar **line_argv = NULL;
+       gchar *serv_path = NULL;
+
+       char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
+       if (char_path == NULL)
+               return BT_STATUS_FAIL;
+
+       line_argv = g_strsplit_set(char_path, "/", 0);
+       serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
+
+       if (!__bt_gatt_get_service_state(serv_path)) {
+               DBG("service not registered for this characteristic \n");
+               g_free(serv_path);
+               g_strfreev(line_argv);
+               return BT_STATUS_FAIL;
+       }
+
+       line_argv = g_strsplit_set(char_path, "/", 0);
+       serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
+
+       if (!__bt_gatt_get_service_state(serv_path)) {
+               DBG("service not registered for this characteristic \n");
+               g_free(serv_path);
+               g_strfreev(line_argv);
+               return BT_STATUS_FAIL;
+       }
+
+       outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+
+       inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
+       for (i = 0; i < value_length; i++)
+               g_variant_builder_add(inner_builder, "y", att_value[i]);
+
+       update_value = g_variant_new("ay", inner_builder);
+
+       outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
+       g_variant_builder_add(outer_builder, "{sv}", "Value",
+                       update_value);
+
+       DBG("Updating characteristic value \n");
+       ret = g_dbus_connection_emit_signal(g_conn, NULL,
+                       char_path,
+                       "org.freedesktop.DBus.Properties",
+                       "PropertiesChanged",
+                       g_variant_new("(sa{sv}as)",
+                               "org.bluez.GattCharacteristic1",
+                               outer_builder, invalidated_builder),
+                       &error);
+
+       if (!ret) {
+               if (error != NULL) {
+                       ERR("D-Bus API failure: errCode[%x], \
+                                       message[%s]",
+                                       error->code, error->message);
+                       g_clear_error(&error);
+               }
+               err = BT_STATUS_FAIL;
+       } else {
+               struct gatt_char_info *char_info = NULL;
+
+               char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
+               if (char_info == NULL) {
+                       g_free(serv_path);
+                       g_strfreev(line_argv);
+                       g_variant_builder_unref(inner_builder);
+                       g_variant_builder_unref(outer_builder);
+                       g_variant_builder_unref(invalidated_builder);
+
+                       return BT_STATUS_FAIL;
+               }
+
+               char_info->value_length = value_length;
+
+               char_info->char_value = (char *)realloc(char_info->char_value, value_length);
+               if (char_info->char_value) {
+                       for (i = 0; i < value_length; i++)
+                               char_info->char_value[i] = att_value[i];
+               }
+       }
+
+       /* Free data */
+       g_free(serv_path);
+       g_strfreev(line_argv);
+       g_variant_builder_unref(inner_builder);
+       g_variant_builder_unref(outer_builder);
+       g_variant_builder_unref(invalidated_builder);
+
+       return err;
+}
+
 static bt_status_t gatt_server_listen(int server_if, bool start)
 {
        CHECK_BTGATT_INIT();
@@ -227,9 +2969,8 @@ static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bo
 static bt_status_t gatt_server_multi_adv_enable(int server_if)
 {
        CHECK_BTGATT_INIT();
-       /* Send Data to LE Module */
+       /* Send Enable Advertising request to LE Module */
        return _bt_hal_enable_advertising(server_if, TRUE, TRUE);
-       return BT_STATUS_SUCCESS;
 }
 
 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval,int max_interval,int adv_type,
@@ -260,7 +3001,84 @@ static bt_status_t gatt_server_multi_adv_disable(int server_if)
 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
 {
        CHECK_BTGATT_INIT();
-       return BT_STATUS_SUCCESS;
+       char *object_path = NULL;
+
+       GDBusProxy *device_proxy;
+       GError *error = NULL;
+       GVariant *value;
+       GVariant *tmp_value;
+       GDBusConnection *conn;
+       GVariant *result = NULL;
+       int ret = BT_STATUS_SUCCESS;
+       struct gatt_client_info_t *conn_info = NULL;
+       unsigned int mtu;
+
+       if (mtu_size == NULL)
+               return BT_STATUS_PARM_INVALID;
+
+       /* GDBUS Connection Info validate */
+       conn = _bt_get_system_gconn();
+        if (conn == NULL) {
+                ERR("Could not get System DBUS Connection");
+                return  BT_STATUS_FAIL;
+        }
+
+       /* Connection Info validate */
+       conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
+        if (conn_info == NULL) {
+                ERR("No Connection Inforamtion!!!");
+                return BT_STATUS_FAIL;
+        }
+
+
+       object_path = _bt_get_device_object_path(conn_info->addr);
+       if (object_path == NULL)
+               return BT_STATUS_FAIL;
+
+       device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
+                       NULL, BT_HAL_BLUEZ_NAME, object_path,
+                       BT_HAL_PROPERTIES_INTERFACE,  NULL, NULL);
+
+       g_free(object_path);
+       if (device_proxy == NULL)
+               return BT_STATUS_FAIL;
+
+       result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
+                       g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
+                       G_DBUS_CALL_FLAGS_NONE,
+                       -1,
+                       NULL,
+                       &error);
+       if (result == NULL) {
+               if (error != NULL) {
+                       ERR("Error occured in Proxy call [%s]\n", error->message);
+                       g_error_free(error);
+               }
+               g_object_unref(device_proxy);
+               return BT_STATUS_FAIL;
+       }
+
+       g_variant_get(result , "(@a{sv})", &value);
+       g_variant_unref(result);
+
+       tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
+       if (tmp_value == NULL) {
+               g_object_unref(device_proxy);
+               g_variant_unref(value);
+               return BT_STATUS_FAIL;
+       }
+
+       mtu = g_variant_get_uint16(tmp_value);
+
+       DBG("ATT MTU : [%d]", mtu);
+
+       g_variant_unref(tmp_value);
+       g_variant_unref(value);
+       g_object_unref(device_proxy);
+
+       *mtu_size = (int) mtu;
+
+       return ret;
 }
 
 const btgatt_server_interface_t btgatt_server_interface = {
@@ -277,6 +3095,7 @@ const btgatt_server_interface_t btgatt_server_interface = {
        gatt_server_delete_service,
        gatt_server_send_indication,
        gatt_server_send_response,
+       gatt_server_update_att_value,
        gatt_server_listen,
        gatt_server_set_adv_data,
        gatt_server_multi_adv_enable,
index dc6f526..97f48e8 100644 (file)
@@ -39,6 +39,10 @@ void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb);
 
 void _bt_hal_unregister_gatt_server_handler_cb(void);
 
+void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address);
+
+handle_stack_msg _bt_hal_get_gatt_event(void);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index f0cba77..a64859b 100644 (file)
@@ -22,8 +22,6 @@
 
 /*******************************************************************************
  *
- * Filename:   btif_gatt.c
- *
  * Description:        GATT Profile Bluetooth Interface
  *
  *******************************************************************************/
@@ -77,7 +75,7 @@ static void __bt_hal_handle_gatt_client_scan_result(void *buf, uint16_t len);
 
 static bool interface_ready(void)
 {
-       return bt_gatt_callbacks != NULL;
+        return bt_gatt_callbacks != NULL;
 }
 
 static void __bt_hal_handle_server_instance_initialized(void *buf, uint16_t len)
@@ -129,6 +127,115 @@ static void __bt_hal_handle_legacy_adv_status(void *buf, uint16_t len)
                bt_gatt_callbacks->server->listen_cb(ev->status, ev->server_instance);
 }
 
+static void __bt_hal_handle_service_added(void *buf, uint16_t len)
+{
+       struct hal_ev_gatt_service_added *ev = buf;
+       btgatt_srvc_id_t srvc_id;
+
+       memset(&srvc_id, 0x00, sizeof(btgatt_srvc_id_t));
+       srvc_id.is_primary = ev->is_primary;
+       srvc_id.id.inst_id = ev->server_instance;
+       memcpy(srvc_id.id.uuid.uu, ev->svc_uuid, sizeof(ev->svc_uuid));
+
+       if (bt_gatt_callbacks->server->service_added_cb)
+               bt_gatt_callbacks->server->service_added_cb(ev->status, ev->server_instance,
+                               &srvc_id, ev->service_handle);
+}
+
+static void __bt_hal_handle_char_added(void *buf, uint16_t len)
+{
+       struct hal_ev_gatt_char_added *ev = buf;
+       bt_uuid_t uuid;
+
+       memcpy(uuid.uu, ev->char_uuid, sizeof(ev->char_uuid));
+
+       if (bt_gatt_callbacks->server->characteristic_added_cb)
+               bt_gatt_callbacks->server->characteristic_added_cb(ev->status, ev->server_instance,
+                               &uuid, ev->service_handle, ev->char_handle);
+}
+
+static void __bt_hal_handle_desc_added(void *buf, uint16_t len)
+{
+       struct hal_ev_gatt_desc_added *ev = buf;
+       bt_uuid_t uuid;
+
+       memcpy(uuid.uu, ev->desc_uuid, sizeof(ev->desc_uuid));
+
+       if (bt_gatt_callbacks->server->descriptor_added_cb)
+               bt_gatt_callbacks->server->descriptor_added_cb(ev->status, ev->server_instance,
+                               &uuid, ev->service_handle, ev->desc_handle);
+}
+
+static void __bt_hal_handle_service_started(void *buf, uint16_t len)
+{
+       struct hal_ev_gatt_service_started *ev = buf;
+
+       if (bt_gatt_callbacks->server->service_started_cb)
+               bt_gatt_callbacks->server->service_started_cb(ev->status, ev->server_instance,
+                               ev->service_handle);
+}
+
+static void __bt_hal_handle_service_deleted(void *buf, uint16_t len)
+{
+       struct hal_ev_gatt_service_deleted *ev = buf;
+
+       if (bt_gatt_callbacks->server->service_deleted_cb)
+               bt_gatt_callbacks->server->service_deleted_cb(ev->status, ev->server_instance,
+                               ev->service_handle);
+}
+
+static void __bt_hal_handle_gatt_server_connected(void *buf, uint16_t len)
+{
+       struct hal_ev_gatt_server_connected *ev = buf;
+       bt_bdaddr_t bd_addr;
+
+       memcpy(bd_addr.address, ev->bdaddr, 6);
+
+       if (bt_gatt_callbacks->server->connection_cb)
+               bt_gatt_callbacks->server->connection_cb(ev->conn_id, ev->server_instance,
+                               ev->connected, &bd_addr);
+}
+
+static void __bt_hal_handle_gatt_server_read_requested(void *buf, uint16_t len)
+{
+       struct hal_ev_gatt_server_read_req *ev = buf;
+       bt_bdaddr_t bd_addr;
+
+       memcpy(bd_addr.address, ev->bdaddr, 6);
+
+       if (bt_gatt_callbacks->server->request_read_cb)
+               bt_gatt_callbacks->server->request_read_cb(ev->conn_id, ev->trans_id, &bd_addr,
+                                       ev->att_handle, ev->offset, ev->is_long);
+}
+
+static void __bt_hal_handle_gatt_server_write_requested(void *buf, uint16_t len)
+{
+        struct hal_ev_gatt_server_write_req *ev = buf;
+
+        if (len != sizeof(*ev) + ev->length) {
+                ERR("gatt: invalid request write event, aborting");
+               return;
+        }
+
+       if (bt_gatt_callbacks->server->request_write_cb)
+                bt_gatt_callbacks->server->request_write_cb(ev->conn_id, ev->trans_id,
+                                                (bt_bdaddr_t *) ev->bdaddr,
+                                                ev->att_handle, ev->offset,
+                                                ev->length, ev->need_rsp,
+                                                ev->is_prep, ev->value);
+}
+
+static void __bt_hal_handle_gatt_server_indicate_confirmed(void *buf, uint16_t len)
+{
+       struct hal_ev_gatt_server_indicate_cfm *ev = buf;
+
+
+       if (bt_gatt_callbacks->server->indication_confirmation_cb)
+               bt_gatt_callbacks->server->indication_confirmation_cb(ev->conn_id, ev->trans_id,
+                               ev->att_handle, (bt_bdaddr_t *) ev->bdaddr);
+
+}
+
 static void __bt_hal_gatt_events(int message, void *buf, uint16_t len)
 {
        DBG("+");
@@ -169,6 +276,42 @@ static void __bt_hal_gatt_events(int message, void *buf, uint16_t len)
                __bt_hal_handle_gatt_client_scan_result(buf, len);
                break;
        }
+       case HAL_EV_GATT_SERVICE_ADDED: {
+               __bt_hal_handle_service_added(buf, len);
+               break;
+       }
+       case HAL_EV_GATT_CHAR_ADDED: {
+               __bt_hal_handle_char_added(buf, len);
+               break;
+       }
+       case HAL_EV_GATT_DESC_ADDED: {
+               __bt_hal_handle_desc_added(buf, len);
+               break;
+       }
+       case HAL_EV_GATT_SERVICE_STARTED: {
+               __bt_hal_handle_service_started(buf, len);
+               break;
+       }
+       case HAL_EV_GATT_SERVICE_DELETED: {
+               __bt_hal_handle_service_deleted(buf, len);
+               break;
+       }
+       case HAL_EV_GATT_SERVER_CONNECTED: {
+               __bt_hal_handle_gatt_server_connected(buf, len);
+               break;
+       }
+       case HAL_EV_GATT_READ_REQUESTED: {
+               __bt_hal_handle_gatt_server_read_requested(buf, len);
+               break;
+       }
+       case HAL_EV_GATT_WRITE_REQUESTED: {
+               __bt_hal_handle_gatt_server_write_requested(buf, len);
+               break;
+       }
+       case HAL_EV_GATT_INDICATE_CFM: {
+               __bt_hal_handle_gatt_server_indicate_confirmed(buf, len);
+               break;
+       }
        default:
                DBG("Event Currently not handled!!");
                break;
@@ -333,6 +476,7 @@ static void gatt_cleanup(void)
 {
        _bt_hal_unregister_gatt_le_dbus_handler_cb();
        _bt_hal_unregister_gatt_client_handler_cb();
+       _bt_hal_unregister_gatt_server_handler_cb();
        _bt_hal_unregister_event_handler_cb(HAL_GATT);
 
        if (bt_gatt_callbacks)
index 6db3726..b1eefc6 100644 (file)
@@ -142,6 +142,350 @@ void str2bt_uuid_t(const char *str, bt_uuid_t *uuid)
        }
 }
 
+const char *_bt_hal_dump_uuid_name(int uuid_no)
+{
+    switch(uuid_no)
+    {
+        CASE_RETURN_STR(BASE)
+        CASE_RETURN_STR(SDP)
+        CASE_RETURN_STR(UDP)
+        CASE_RETURN_STR(RFCOMM)
+        CASE_RETURN_STR(TCP)
+        CASE_RETURN_STR(TCS_BIN)
+        CASE_RETURN_STR(TCS_AT)
+        CASE_RETURN_STR(ATT)
+        CASE_RETURN_STR(OBEX)
+        CASE_RETURN_STR(IP)
+        CASE_RETURN_STR(FTP)
+        CASE_RETURN_STR(HTTP)
+        CASE_RETURN_STR(WSP)
+        CASE_RETURN_STR(BNEP)
+        CASE_RETURN_STR(UPNP)
+        CASE_RETURN_STR(HIDP)
+        CASE_RETURN_STR(HardcopyControlChannel)
+        CASE_RETURN_STR(HardcopyDataChannel)
+        CASE_RETURN_STR(HardcopyNotification)
+        CASE_RETURN_STR(AVCTP)
+        CASE_RETURN_STR(AVDTP)
+        CASE_RETURN_STR(CMTP)
+        CASE_RETURN_STR(MCAPControlChannel)
+        CASE_RETURN_STR(MCAPDataChannel)
+        CASE_RETURN_STR(L2CAP)
+        CASE_RETURN_STR(ServiceDiscoveryServerServiceClassID)
+        CASE_RETURN_STR(BrowseGroupDescriptorServiceClassID)
+        CASE_RETURN_STR(SerialPort)
+        CASE_RETURN_STR(LANAccessUsingPPP)
+        CASE_RETURN_STR(DialupNetworking)
+        CASE_RETURN_STR(IrMCSync)
+        CASE_RETURN_STR(OBEXObjectPush)
+        CASE_RETURN_STR(OBEXFileTransfer)
+        CASE_RETURN_STR(IrMCSyncCommand)
+        CASE_RETURN_STR(Headset)
+        CASE_RETURN_STR(CordlessTelephony)
+        CASE_RETURN_STR(AudioSource)
+        CASE_RETURN_STR(AudioSink)
+        CASE_RETURN_STR(AV_RemoteControlTarget)
+        CASE_RETURN_STR(AdvancedAudioDistribution)
+        CASE_RETURN_STR(AV_RemoteControl)
+        CASE_RETURN_STR(AV_RemoteControlController)
+        CASE_RETURN_STR(Intercom)
+        CASE_RETURN_STR(Fax)
+        CASE_RETURN_STR(Headset_Audio_Gateway)
+        CASE_RETURN_STR(WAP)
+        CASE_RETURN_STR(WAP_CLIENT)
+        CASE_RETURN_STR(PANU)
+        CASE_RETURN_STR(NAP)
+        CASE_RETURN_STR(GN)
+       CASE_RETURN_STR(DirectPrinting)
+        CASE_RETURN_STR(ReferencePrinting)
+        CASE_RETURN_STR(Basic_Imaging_Profile)
+        CASE_RETURN_STR(ImagingResponder)
+        CASE_RETURN_STR(ImagingAutomaticArchive)
+        CASE_RETURN_STR(ImagingReferencedObjects)
+        CASE_RETURN_STR(Handsfree)
+        CASE_RETURN_STR(HandsfreeAudioGateway)
+        CASE_RETURN_STR(DirectPrintingReferenceObjectsService)
+        CASE_RETURN_STR(ReflectedUI)
+        CASE_RETURN_STR(BasicPrinting)
+        CASE_RETURN_STR(PrintingStatus)
+        CASE_RETURN_STR(HumanInterfaceDeviceService)
+        CASE_RETURN_STR(HardcopyCableReplacement)
+        CASE_RETURN_STR(HCR_Print)
+        CASE_RETURN_STR(HCR_Scan)
+        CASE_RETURN_STR(Common_ISDN_Access)
+        CASE_RETURN_STR(SIM_Access)
+        CASE_RETURN_STR(Phonebook_Access_PCE)
+        CASE_RETURN_STR(Phonebook_Access_PSE)
+        CASE_RETURN_STR(Phonebook_Access)
+        CASE_RETURN_STR(Headset_HS)
+        CASE_RETURN_STR(Message_Access_Server)
+        CASE_RETURN_STR(Message_Notification_Server)
+        CASE_RETURN_STR(Message_Access_Profile)
+        CASE_RETURN_STR(GNSS)
+        CASE_RETURN_STR(GNSS_Server)
+        CASE_RETURN_STR(ThreeD_Display)
+        CASE_RETURN_STR(ThreeD_Glasses)
+        CASE_RETURN_STR(ThreeD_Synchronization)
+        CASE_RETURN_STR(MPS_Profile)
+        CASE_RETURN_STR(MPS_SC)
+        CASE_RETURN_STR(CTN_Access_Service)
+        CASE_RETURN_STR(CTN_Notification_Service)
+        CASE_RETURN_STR(CTN_Profile)
+        CASE_RETURN_STR(PnPInformation)
+        CASE_RETURN_STR(GenericNetworking)
+        CASE_RETURN_STR(GenericFileTransfer)
+        CASE_RETURN_STR(GenericAudio)
+        CASE_RETURN_STR(GenericTelephony)
+        CASE_RETURN_STR(UPNP_Service)
+        CASE_RETURN_STR(UPNP_IP_Service)
+        CASE_RETURN_STR(ESDP_UPNP_IP_PAN)
+        CASE_RETURN_STR(ESDP_UPNP_IP_LAP)
+        CASE_RETURN_STR(ESDP_UPNP_L2CAP)
+        CASE_RETURN_STR(VideoSource)
+        CASE_RETURN_STR(VideoSink)
+        CASE_RETURN_STR(VideoDistribution)
+        CASE_RETURN_STR(HDP)
+       CASE_RETURN_STR(HDP_Source)
+        CASE_RETURN_STR(HDP_Sink)
+                CASE_RETURN_STR(Generic_Access)
+                CASE_RETURN_STR(Generic_Attribute)
+                CASE_RETURN_STR(Immediate_Alert)
+                CASE_RETURN_STR(Link_Loss)
+                CASE_RETURN_STR(Tx_Power)
+                CASE_RETURN_STR(Current_Time)
+                CASE_RETURN_STR(Reference_Time_Update)
+                CASE_RETURN_STR(Next_Dst_Change)
+                CASE_RETURN_STR(Glucose)
+                CASE_RETURN_STR(Health_Thermometer)
+                CASE_RETURN_STR(Device_Information)
+                CASE_RETURN_STR(Heart_Rate)
+                CASE_RETURN_STR(Phone_Alert_Status)
+                CASE_RETURN_STR(Battery_Service)
+                CASE_RETURN_STR(Blood_Pressure)
+                CASE_RETURN_STR(Alert_Notification)
+                CASE_RETURN_STR(Human_Interface_Device)
+                CASE_RETURN_STR(Scan_Parameters)
+                CASE_RETURN_STR(Running_Speed_And_Cadence)
+                CASE_RETURN_STR(Automation_IO)
+                CASE_RETURN_STR(Cycling_Speed_And_Cadence)
+                CASE_RETURN_STR(Cycling_Power)
+                CASE_RETURN_STR(Location_And_Navigation)
+                CASE_RETURN_STR(Environmental_Sensing)
+                CASE_RETURN_STR(Body_Composition)
+                CASE_RETURN_STR(User_Data)
+                CASE_RETURN_STR(Weight_Scale)
+                CASE_RETURN_STR(Bond_Management)
+                CASE_RETURN_STR(Continuous_Glucose_Monitoring)
+                CASE_RETURN_STR(Internet_Protocol_Support)
+                CASE_RETURN_STR(Indoor_Positioning)
+                CASE_RETURN_STR(Pulse_Oximeter)
+                CASE_RETURN_STR(Http_Proxy)
+                CASE_RETURN_STR(Transport_Discovery)
+                CASE_RETURN_STR(Object_Transfer)
+                CASE_RETURN_STR(Gap_Device_Name)
+                CASE_RETURN_STR(Gap_Appearance)
+                CASE_RETURN_STR(Gap_Peripheral_Privacy_Flag)
+                CASE_RETURN_STR(Gap_Reconnection_Address)
+                CASE_RETURN_STR(Gap_Peripheral_Preferred_Connection_Parameters)
+                CASE_RETURN_STR(Gatt_Service_Changed)
+                CASE_RETURN_STR(Alert_Level)
+                CASE_RETURN_STR(Tx_Power_Level)
+                CASE_RETURN_STR(Date_Time)
+                CASE_RETURN_STR(Day_Of_Week)
+                CASE_RETURN_STR(Day_Date_Time)
+               CASE_RETURN_STR(Exact_Time_256)
+                CASE_RETURN_STR(Dst_Offset)
+                CASE_RETURN_STR(Time_Zone)
+                CASE_RETURN_STR(Local_Time_Information)
+                CASE_RETURN_STR(Time_With_Dst)
+                CASE_RETURN_STR(Time_Accuracy)
+                CASE_RETURN_STR(Time_Source)
+                CASE_RETURN_STR(Reference_Time_Information)
+                CASE_RETURN_STR(Time_Update_Control_Point)
+                CASE_RETURN_STR(Time_Update_State)
+                CASE_RETURN_STR(Glucose_Measurement)
+                CASE_RETURN_STR(Battery_Level)
+                CASE_RETURN_STR(Temperature_Measurement)
+                CASE_RETURN_STR(Temperature_Type)
+                CASE_RETURN_STR(Intermediate_Temperature)
+                CASE_RETURN_STR(Measurement_Interval)
+                CASE_RETURN_STR(Boot_Keyboard_Input_Report)
+                CASE_RETURN_STR(System_Id)
+                CASE_RETURN_STR(Model_Number_String)
+                CASE_RETURN_STR(Serial_Number_String)
+                CASE_RETURN_STR(Firmware_Revision_String)
+                CASE_RETURN_STR(Hardware_Revision_String)
+                CASE_RETURN_STR(Software_Revision_String)
+                CASE_RETURN_STR(Manufacturer_Name_String)
+                CASE_RETURN_STR(Regulatory_Certification_Data_List)
+                CASE_RETURN_STR(Current_Time_Charac)
+                CASE_RETURN_STR(Magnetic_Declination)
+                CASE_RETURN_STR(Scan_Refresh)
+                CASE_RETURN_STR(Boot_Keyboard_Output_Report)
+                CASE_RETURN_STR(Boot_Mouse_Input_Report)
+                CASE_RETURN_STR(Glucose_Measurement_Context)
+                CASE_RETURN_STR(Blood_Pressure_Measurement)
+                CASE_RETURN_STR(Intermediate_Cuff_Pressure)
+                CASE_RETURN_STR(Heart_Rate_Measurement)
+                CASE_RETURN_STR(Body_Sensor_Location)
+                CASE_RETURN_STR(Heart_Rate_Control_Point)
+                CASE_RETURN_STR(Alert_Status)
+                CASE_RETURN_STR(Ringer_Control_Point)
+                CASE_RETURN_STR(Ringer_Setting)
+                CASE_RETURN_STR(Alert_Category_Id_Bit_Mask)
+                CASE_RETURN_STR(Alert_Category_Id)
+                CASE_RETURN_STR(Alert_Notification_Control_Point)
+                CASE_RETURN_STR(Unread_Alert_Status)
+                CASE_RETURN_STR(New_Alert)
+                CASE_RETURN_STR(Supported_New_Alert_Category)
+                CASE_RETURN_STR(Supported_Unread_Alert_Category)
+                CASE_RETURN_STR(Blood_Pressure_Feature)
+                CASE_RETURN_STR(Hid_Information)
+                CASE_RETURN_STR(Report_Map)
+                CASE_RETURN_STR(Hid_Control_Point)
+                CASE_RETURN_STR(Report)
+                CASE_RETURN_STR(Protocol_Mode)
+                CASE_RETURN_STR(Scan_Interval_Window)
+                CASE_RETURN_STR(Pnp_Id)
+               CASE_RETURN_STR(Glucose_Feature)
+                CASE_RETURN_STR(Record_Access_Control_Point)
+                CASE_RETURN_STR(Rsc_Measurement)
+                CASE_RETURN_STR(Rsc_Feature)
+                CASE_RETURN_STR(Sc_Control_Point)
+                CASE_RETURN_STR(Digital)
+                CASE_RETURN_STR(Analog)
+                CASE_RETURN_STR(Aggregate)
+                CASE_RETURN_STR(Csc_Measurement)
+                CASE_RETURN_STR(Csc_Feature)
+                CASE_RETURN_STR(Sensor_Location)
+                CASE_RETURN_STR(Plx_Spot_Check_Measurement)
+                CASE_RETURN_STR(Plx_Continuous_Measurement)
+                CASE_RETURN_STR(Plx_Features)
+                CASE_RETURN_STR(Cycling_Power_Measurement)
+                CASE_RETURN_STR(Cycling_Power_Vector)
+                CASE_RETURN_STR(Cycling_Power_Feature)
+                CASE_RETURN_STR(Cycling_Power_Control_Point)
+                CASE_RETURN_STR(Location_And_Speed)
+                CASE_RETURN_STR(Navigation)
+                CASE_RETURN_STR(Position_Quality)
+                CASE_RETURN_STR(Ln_Feature)
+                CASE_RETURN_STR(Ln_Control_Point)
+                CASE_RETURN_STR(Elevation)
+                CASE_RETURN_STR(Pressure)
+                CASE_RETURN_STR(Temperature)
+                CASE_RETURN_STR(Humidity)
+                CASE_RETURN_STR(True_Wind_Speed)
+                CASE_RETURN_STR(True_Wind_Direction)
+                CASE_RETURN_STR(Apparent_Wind_Speed)
+                CASE_RETURN_STR(Apparent_Wind_Direction)
+                CASE_RETURN_STR(Gust_Factor)
+                CASE_RETURN_STR(Pollen_Concentration)
+                CASE_RETURN_STR(Uv_Index)
+                CASE_RETURN_STR(Irradiance)
+                CASE_RETURN_STR(Rainfall)
+                CASE_RETURN_STR(Wind_Chill)
+                CASE_RETURN_STR(Heat_Index)
+                CASE_RETURN_STR(Dew_Point)
+                CASE_RETURN_STR(Descriptor_Value_Changed)
+                CASE_RETURN_STR(Aerobic_Threshold)
+                CASE_RETURN_STR(Age)
+                CASE_RETURN_STR(Anaerobic_Heart_Rate_Lower_Limit)
+                CASE_RETURN_STR(Anaerobic_Heart_Rate_Upper_Limit)
+                CASE_RETURN_STR(Anaerobic_Threshold)
+                CASE_RETURN_STR(Aerobic_Heart_Rate_Upper_Limit)
+                CASE_RETURN_STR(Date_Of_Birth)
+                CASE_RETURN_STR(Date_Of_Threshold_Assessment)
+                CASE_RETURN_STR(Email_Address)
+                CASE_RETURN_STR(Fat_Burn_Heart_Rate_Lower_Limit)
+                CASE_RETURN_STR(Fat_Burn_Heart_Rate_Upper_Limit)
+                CASE_RETURN_STR(First_Name)
+                CASE_RETURN_STR(Five_Zone_Heart_Rate_Limits)
+                CASE_RETURN_STR(Gender)
+                CASE_RETURN_STR(Heart_Rate_Max)
+               CASE_RETURN_STR(Height)
+                CASE_RETURN_STR(Hip_Circumference)
+                CASE_RETURN_STR(Last_Name)
+                CASE_RETURN_STR(Maximum_Recommended_Heart_Rate)
+                CASE_RETURN_STR(Resting_Heart_Rate)
+                CASE_RETURN_STR(Sport_Type_For_Aerobic_And_Anaerobic_Thresholds)
+                CASE_RETURN_STR(Three_Zone_Heart_Rate_Limits)
+                CASE_RETURN_STR(Two_Zone_Heart_Rate_Limit)
+                CASE_RETURN_STR(Vo2_Max)
+                CASE_RETURN_STR(Waist_Circumference)
+                CASE_RETURN_STR(Weight)
+                CASE_RETURN_STR(Database_Change_Increment)
+                CASE_RETURN_STR(User_Index)
+                CASE_RETURN_STR(Body_Composition_Feature)
+                CASE_RETURN_STR(Body_Composition_Measurement)
+                CASE_RETURN_STR(Weight_Measurement)
+                CASE_RETURN_STR(Weight_Scale_Feature)
+                CASE_RETURN_STR(User_Control_Point)
+                CASE_RETURN_STR(Magnetic_Flux_Density_2D)
+                CASE_RETURN_STR(Magnetic_Flux_Density_3D)
+                CASE_RETURN_STR(Language)
+                CASE_RETURN_STR(Barometric_Pressure_Trend)
+                CASE_RETURN_STR(Bond_Management_Control_Point)
+                CASE_RETURN_STR(Bond_Management_Feature)
+                CASE_RETURN_STR(Gap_Central_Address_Resolution_Support)
+                CASE_RETURN_STR(Cgm_Measurement)
+                CASE_RETURN_STR(Cgm_Feature)
+                CASE_RETURN_STR(Cgm_Status)
+                CASE_RETURN_STR(Cgm_Session_Start_Time)
+                CASE_RETURN_STR(Cgm_Session_Run_Time)
+                CASE_RETURN_STR(Cgm_Specific_Ops_Control_Point)
+                CASE_RETURN_STR(Indoor_Positioning_Configuration)
+                CASE_RETURN_STR(Latitude)
+                CASE_RETURN_STR(Longitude)
+                CASE_RETURN_STR(Local_North_Coordinate)
+                CASE_RETURN_STR(Local_East_Coordinate)
+                CASE_RETURN_STR(Floor_Number)
+                CASE_RETURN_STR(Altitude)
+                CASE_RETURN_STR(Uncertainty)
+                CASE_RETURN_STR(Location_Name)
+                CASE_RETURN_STR(Uri)
+                CASE_RETURN_STR(Http_Headers)
+                CASE_RETURN_STR(Http_Status_Code)
+                CASE_RETURN_STR(Http_Entity_Body)
+                CASE_RETURN_STR(Http_Control_Point)
+                CASE_RETURN_STR(Https_Security)
+                CASE_RETURN_STR(Tds_Control_Point)
+                CASE_RETURN_STR(Ots_Feature)
+                CASE_RETURN_STR(Object_Name)
+                CASE_RETURN_STR(Object_Type)
+                CASE_RETURN_STR(Object_Size)
+                CASE_RETURN_STR(Object_First_Created)
+                CASE_RETURN_STR(Object_Last_Modified)
+                CASE_RETURN_STR(Object_Id)
+                CASE_RETURN_STR(Object_Properties)
+                CASE_RETURN_STR(Object_Action_Control_Point)
+                CASE_RETURN_STR(Object_List_Control_Point)
+                CASE_RETURN_STR(Object_List_Filter)
+                CASE_RETURN_STR(Object_Changed)
+                CASE_RETURN_STR(Fitness_Machine_Control_Point)
+                CASE_RETURN_STR(Gatt_Characteristic_Extended_Properties)
+                CASE_RETURN_STR(Gatt_Characteristic_User_Description)
+                CASE_RETURN_STR(Gatt_Client_Characteristic_Configuration)
+                CASE_RETURN_STR(Gatt_Server_Characteristic_Configuration)
+                CASE_RETURN_STR(Gatt_Characteristic_Presentation_Format)
+                CASE_RETURN_STR(Gatt_Characteristic_Aggregate_Format)
+                CASE_RETURN_STR(Valid_Range)
+                CASE_RETURN_STR(External_Report_Reference)
+                CASE_RETURN_STR(Report_Reference)
+                CASE_RETURN_STR(Number_Of_Digitals)
+                CASE_RETURN_STR(Value_Trigger_Setting)
+                CASE_RETURN_STR(Es_Configuration)
+                CASE_RETURN_STR(Es_Measurement)
+                CASE_RETURN_STR(Es_Trigger_Setting)
+                CASE_RETURN_STR(Time_Trigger_Setting)
+                CASE_RETURN_STR(Gatt_Primary_Service_Declaration)
+                CASE_RETURN_STR(Gatt_Secondary_Service_Declaration)
+                CASE_RETURN_STR(Gatt_Include_Declaration)
+                CASE_RETURN_STR(Gatt_Characteristic_Declaration)
+        default:
+            return "--";
+    }
+}
+
 const char *enum_defines(void *v, int i)
 {
        const struct int2str *m = v;