device: Set disconnect timer to zero for fast disconnection
[platform/upstream/bluez.git] / profile.h
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  */
19
20 #ifndef __TIZEN_PROFILE_H__
21 #define __TIZEN_PROFILE_H__
22
23 #include <stdlib.h>
24
25 #include <iniparser.h>
26 #include <libxml/xmlmemory.h>
27 #include <libxml/parser.h>
28 #include <libxml/tree.h>
29
30 #define MODEL_CONFIG_FILE "/etc/config/model-config.xml"
31 #define TYPE_FIELD "string"
32 #define FEATURE_TAG "platform"
33 #define MODEL_CONFIG_TAG "model-config"
34 #define CERTI_STACK_FILE "/var/lib/bluetooth/stack_test"
35 #define CERTI_PROFILE_FILE "/var/lib/bluetooth/profile_test"
36
37
38 typedef enum {
39         TIZEN_PROFILE_UNKNOWN = 0,
40         TIZEN_PROFILE_MOBILE = 0x1,
41         TIZEN_PROFILE_WEARABLE = 0x2,
42         TIZEN_PROFILE_TV = 0x4,
43         TIZEN_PROFILE_IVI = 0x8,
44         TIZEN_PROFILE_IOT = 0x10,
45         TIZEN_PROFILE_COMMON = 0x20,
46 } tizen_profile_t;
47
48 typedef enum {
49         TIZEN_MODEL_UNKNOWN = 0,
50         TIZEN_MODEL_COMMON = 0x1,
51         TIZEN_MODEL_TM1 = 0x2,
52         TIZEN_MODEL_TM2 = 0x4,
53         TIZEN_MODEL_TW1 = 0x8,
54         TIZEN_MODEL_TW2 = 0x10,
55         TIZEN_MODEL_TW3 = 0x20,
56         TIZEN_MODEL_RPI3 = 0x40,
57         TIZEN_MODEL_ROBOT = 0x80,
58         TIZEN_MODEL_FHUB = 0x100,
59         TIZEN_MODEL_DA = 0x200,
60 } tizen_model_t;
61
62 typedef enum {
63         TIZEN_CERTI_MODE_UNKNOWN = 0,
64         TIZEN_CERTI_MODE_DISABLE = 0x1,
65         TIZEN_CERTI_MODE_STACK = 0x2,
66         TIZEN_CERTI_MODE_PROFILE = 0x4,
67 } tizen_certifcation_mode_t;
68
69 static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
70 static tizen_model_t model = TIZEN_MODEL_UNKNOWN;
71 static tizen_certifcation_mode_t certification_mode = TIZEN_CERTI_MODE_UNKNOWN;
72
73 static inline int __get_profile_from_model_config_xml(const char *field, char **value)
74 {
75         char *node_name = NULL;
76         char *node_value = NULL;
77         xmlNode *cur_node = NULL;
78         xmlNodePtr cur_ptr = NULL;
79         xmlNodePtr model_ptr = NULL;
80         xmlDocPtr xml_doc = NULL;
81
82         xml_doc = xmlParseFile(MODEL_CONFIG_FILE);
83         if (xml_doc == NULL)
84                 return -1;
85
86         cur_ptr = xmlDocGetRootElement(xml_doc);
87         if (cur_ptr == NULL) {
88                 xmlFreeDoc(xml_doc);
89                 return -1;
90         }
91
92         for (cur_node = cur_ptr; cur_node; cur_node = cur_node->next) {
93                 if (!xmlStrcmp(cur_ptr->name, (const xmlChar*)MODEL_CONFIG_TAG))
94                         break;
95         }
96
97         if (cur_ptr == NULL) {
98                 xmlFreeDoc(xml_doc);
99                 return -1;
100         }
101
102         cur_ptr = cur_ptr->xmlChildrenNode;
103         for (cur_node = cur_ptr; cur_node; cur_node = cur_node->next) {
104                 if (!xmlStrcmp(cur_node->name, (const xmlChar*)FEATURE_TAG)) {
105                         model_ptr = cur_node;
106                         break;
107                 }
108         }
109
110         if (model_ptr == NULL) {
111                 xmlFreeDoc(xml_doc);
112                 return -1;
113         }
114
115         if (model_ptr) {
116                 cur_ptr = model_ptr->xmlChildrenNode;
117
118                 for (cur_node = cur_ptr; cur_node; cur_node = cur_node->next) {
119                         if (cur_node->type == XML_ELEMENT_NODE) {
120                                 node_name = (char *)xmlGetProp(cur_node, (const xmlChar*)"name");
121
122                                 if (!strncmp(node_name, field, strlen(node_name))) {
123                                         node_value = (char *)xmlNodeListGetString(xml_doc, cur_node->xmlChildrenNode, 1);
124                                         if (node_value) {
125                                                 *value = strdup(node_value);
126                                                 xmlFree(node_name);
127                                                 xmlFree(node_value);
128                                                 break;
129                                         }
130                                 }
131                                 xmlFree(node_name);
132                         }
133                 }
134         }
135
136         xmlFreeDoc(xml_doc);
137         return 0;
138 }
139
140 static inline tizen_profile_t _get_tizen_profile(void)
141 {
142         char *profile_name = NULL;
143
144         if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
145                 return profile;
146
147         if (__get_profile_from_model_config_xml("tizen.org/feature/profile",
148                                                                         &profile_name) < 0) {
149                 profile = TIZEN_PROFILE_MOBILE;
150                 return profile;
151         }
152
153         if (profile_name == NULL) {
154                 profile = TIZEN_PROFILE_MOBILE;
155                 return profile;
156         }
157
158         switch (*profile_name) {
159                 case 'm':
160                 case 'M':
161                         profile = TIZEN_PROFILE_MOBILE;
162                         break;
163                 case 'w':
164                 case 'W':
165                         profile = TIZEN_PROFILE_WEARABLE;
166                         break;
167                 case 't':
168                 case 'T':
169                         profile = TIZEN_PROFILE_TV;
170                         break;
171                 case 'i':
172                 case 'I':
173                         if (!strncasecmp(profile_name, "ivi", 3))
174                                 profile = TIZEN_PROFILE_IVI;
175                         else if (!strncasecmp(profile_name, "iot", 3))
176                                 profile = TIZEN_PROFILE_IOT;
177                         else
178                                 profile = TIZEN_PROFILE_COMMON;
179                         break;
180                 default: /* common or unknown ==> ALL ARE COMMON */
181                         profile = TIZEN_PROFILE_COMMON;
182         }
183         free(profile_name);
184
185         return profile;
186 }
187
188 static inline tizen_model_t _get_tizen_model(void)
189 {
190         char *model_name = NULL;
191
192         if (__builtin_expect(model != TIZEN_MODEL_UNKNOWN, 1))
193                 return model;
194
195         if (__get_profile_from_model_config_xml("tizen.org/system/model_name",
196                                                                         &model_name) < 0) {
197                 model = TIZEN_MODEL_COMMON;
198                 return model;
199         }
200
201         if (model_name == NULL) {
202                 model = TIZEN_MODEL_COMMON;
203                 return model;
204         }
205
206         if (!strcasecmp(model_name, "TM1"))
207                 model = TIZEN_MODEL_TM1;
208         else if (!strcasecmp(model_name, "TM2"))
209                 model = TIZEN_MODEL_TM2;
210         else if (!strcasecmp(model_name, "TW1"))
211                 model = TIZEN_MODEL_TW1;
212         else if (!strcasecmp(model_name, "TW2"))
213                 model = TIZEN_MODEL_TW2;
214         else if (!strcasecmp(model_name, "TW3"))
215                 model = TIZEN_MODEL_TW3;
216         else if (!strcasecmp(model_name, "rpi3"))
217                 model = TIZEN_MODEL_RPI3;
218         else if (!strcasecmp(model_name, "gems") || !strncasecmp(model_name, "ServingBot", 10))
219                 model = TIZEN_MODEL_ROBOT;
220         else if (!strncasecmp(model_name, "Family Hub", 10))
221                 model = TIZEN_MODEL_FHUB;
222         else if (!strcasecmp(model_name, "Robot Vacuum Cleaner") ||
223                         !strcasecmp(model_name, "Smart Dryer") ||
224                         !strcasecmp(model_name, "Smart Washer") ||
225                         !strcasecmp(model_name, "DDMS") ||
226                         !strcasecmp(model_name, "Smart Cooktop") ||
227                         !strcasecmp(model_name, "Smart Range") ||
228                         !strcasecmp(model_name, "Refrigerator") ||
229                         !strcasecmp(model_name, "Echo Heating System Controller") ||
230                         !strcasecmp(model_name, "Bespoke Washer") ||
231                         !strcasecmp(model_name, "Bespoke Dryer") ||
232                         !strcasecmp(model_name, "Appliance Emulator") ||
233                         !strcasecmp(model_name, "AI Hub Smart EHS"))
234                 model = TIZEN_MODEL_DA;
235         else
236                 model = TIZEN_MODEL_COMMON;
237
238         free(model_name);
239
240         return model;
241 }
242
243 static inline tizen_certifcation_mode_t _get_tizen_certification_mode(void)
244 {
245         if (__builtin_expect(certification_mode != TIZEN_CERTI_MODE_UNKNOWN, 1))
246                 return certification_mode;
247
248         if (access(CERTI_STACK_FILE, F_OK) == 0)
249                 certification_mode |= TIZEN_CERTI_MODE_STACK;
250
251         if (access(CERTI_PROFILE_FILE, F_OK) == 0)
252                 certification_mode |= TIZEN_CERTI_MODE_PROFILE;
253
254         if (certification_mode == TIZEN_CERTI_MODE_UNKNOWN)
255                 certification_mode = TIZEN_CERTI_MODE_DISABLE;
256
257         return certification_mode;
258 }
259
260 #define TIZEN_FEATURE_BLUEZ_BRCM_CHIP ((_get_tizen_profile()) == TIZEN_PROFILE_IVI)
261 #define TIZEN_FEATURE_BLUEZ_WEARABLE ((_get_tizen_profile()) == TIZEN_PROFILE_WEARABLE)
262 #define TIZEN_FEATURE_BLUEZ_SMS_ONLY ((_get_tizen_profile()) == TIZEN_PROFILE_WEARABLE)
263 #define TIZEN_FEATURE_BLUEZ_BRCM_QOS ((_get_tizen_profile()) == TIZEN_PROFILE_WEARABLE)
264 #define TIZEN_FEATURE_BLUEZ_ROLE_CHANGE ((_get_tizen_profile()) == TIZEN_PROFILE_WEARABLE)
265 #define TIZEN_FEATURE_BLUEZ_CONFIRM_ONLY ((_get_tizen_profile()) == TIZEN_PROFILE_WEARABLE)
266 #define TIZEN_FEATURE_BLUEZ_SPRD_QOS ((_get_tizen_model()) == TIZEN_MODEL_TM1)
267 #define TIZEN_FEATURE_BLUEZ_SPRD_PAGE_SCAN ((_get_tizen_model()) == TIZEN_MODEL_TM1)
268 #define TIZEN_FEATURE_BLUEZ_SPEAKER_REFERENCE ((_get_tizen_model()) == TIZEN_MODEL_RPI3 && (_get_tizen_profile()) == TIZEN_PROFILE_COMMON)
269 #define TIZEN_FEATURE_ROBOT_REFERENCE ((_get_tizen_model()) == TIZEN_MODEL_ROBOT)
270 #define TIZEN_FEATURE_BLUEZ_FHUB ((_get_tizen_model()) == TIZEN_MODEL_FHUB)
271 #define TIZEN_FEATURE_BLUEZ_DA ((_get_tizen_model()) == TIZEN_MODEL_FHUB || (_get_tizen_model()) == TIZEN_MODEL_DA)
272 #define TIZEN_FEATURE_BLUEZ_STACK_CERTIFICATION (((_get_tizen_certification_mode()) & TIZEN_CERTI_MODE_STACK) != 0)
273 #define TIZEN_FEATURE_BLUEZ_PROFILE_CERTIFICATION (((_get_tizen_certification_mode()) & TIZEN_CERTI_MODE_PROFILE) != 0)
274
275 #endif /* __TIZEN_PROFILE_H__ */
276