blob: 0de28b1617c262bbb174a1b1389c91f5c74862de [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 2009-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 * Filename: bte_conf.c
22 *
23 * Description: Contains functions to conduct run-time module configuration
24 * based on entries present in the .conf file
25 *
26 ******************************************************************************/
27
28#define LOG_TAG "bte_conf"
29
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -070030#include <assert.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080031#include <utils/Log.h>
32#include <stdio.h>
33#include <string.h>
34#include <stdlib.h>
35#include <ctype.h>
36
37#include "bt_target.h"
38#include "bta_api.h"
Mike J. Chen5cd8bff2014-01-31 18:16:59 -080039#include "bt_utils.h"
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -070040#include "config.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080041
42/******************************************************************************
43** Externs
44******************************************************************************/
45extern BOOLEAN hci_logging_enabled;
46extern char hci_logfile[256];
47extern BOOLEAN trace_conf_enabled;
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -070048void bte_trace_conf(const char *p_name, const char *p_conf_value);
49void bte_trace_conf_config(const config_t *config);
50int device_name_cfg(const char *p_conf_name, const char *p_conf_value);
51int device_class_cfg(const char *p_conf_name, const char *p_conf_value);
52int logging_cfg_onoff(const char *p_conf_name, const char *p_conf_value);
53int logging_set_filepath(const char *p_conf_name, const char *p_conf_value);
54int trace_cfg_onoff(const char *p_conf_name, const char *p_conf_value);
The Android Open Source Project5738f832012-12-12 16:00:35 -080055
56BD_NAME local_device_default_name = BTM_DEF_LOCAL_NAME;
57DEV_CLASS local_device_default_class = {0x40, 0x02, 0x0C};
58
59/******************************************************************************
60** Local type definitions
61******************************************************************************/
62#define CONF_DBG 0
63#define info(format, ...) ALOGI (format, ## __VA_ARGS__)
64#define debug(format, ...) if (CONF_DBG) ALOGD (format, ## __VA_ARGS__)
65#define error(format, ...) ALOGE (format, ## __VA_ARGS__)
66
67#define CONF_KEY_LEN 32
68#define CONF_VALUE_LEN 96
69
70#define CONF_COMMENT '#'
71#define CONF_DELIMITERS " =\n\r\t"
72#define CONF_VALUES_DELIMITERS "\"=\n\r\t"
73#define CONF_COD_DELIMITERS " {,}\t"
74#define CONF_MAX_LINE_LEN 255
75
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -070076typedef int (conf_action_t)(const char *p_conf_name, const char *p_conf_value);
The Android Open Source Project5738f832012-12-12 16:00:35 -080077
78typedef struct {
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -070079 const char *key_name;
The Android Open Source Project5738f832012-12-12 16:00:35 -080080 conf_action_t *p_action;
81} conf_entry_t;
82
83typedef struct {
84 char key[CONF_KEY_LEN];
85 char value[CONF_VALUE_LEN];
86} tKEY_VALUE_PAIRS;
87
88enum {
89 CONF_DID,
90 CONF_DID_RECORD_NUM,
91 CONF_DID_PRIMARY_RECORD,
92 CONF_DID_VENDOR_ID,
93 CONF_DID_VENDOR_ID_SOURCE,
94 CONF_DID_PRODUCT_ID,
95 CONF_DID_VERSION,
96 CONF_DID_CLIENT_EXECUTABLE_URL,
97 CONF_DID_SERVICE_DESCRIPTION,
98 CONF_DID_DOCUMENTATION_URL,
99 CONF_DID_MAX
100};
101typedef UINT8 tCONF_DID;
102/******************************************************************************
103** Static variables
104******************************************************************************/
105
106/*
107 * Current supported entries and corresponding action functions
108 */
109/* TODO: Name and Class are duplicated with NVRAM adapter_info. Need to be sorted out */
110static const conf_entry_t conf_table[] = {
111 /*{"Name", device_name_cfg},
112 {"Class", device_class_cfg},*/
113 {"BtSnoopLogOutput", logging_cfg_onoff},
114 {"BtSnoopFileName", logging_set_filepath},
115 {"TraceConf", trace_cfg_onoff},
116 {(const char *) NULL, NULL}
117};
118
119static tKEY_VALUE_PAIRS did_conf_pairs[CONF_DID_MAX] = {
120 { "[DID]", "" },
121 { "recordNumber", "" },
122 { "primaryRecord", "" },
123 { "vendorId", "" },
124 { "vendorIdSource", "" },
125 { "productId", "" },
126 { "version", "" },
127 { "clientExecutableURL", "" },
128 { "serviceDescription", "" },
129 { "documentationURL", "" },
130};
131/*****************************************************************************
132** FUNCTIONS
133*****************************************************************************/
134
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -0700135int device_name_cfg(const char *p_conf_name, const char *p_conf_value)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800136{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800137 UNUSED(p_conf_name);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800138 strcpy((char *)local_device_default_name, p_conf_value);
139 return 0;
140}
141
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -0700142int device_class_cfg(const char *p_conf_name, const char *p_conf_value)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800143{
144 char *p_token;
145 unsigned int x;
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -0700146 char tmp[1024] = { 0 };
147 strncpy(tmp, p_conf_value, sizeof(tmp) - 1);
148
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800149 UNUSED(p_conf_name);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800150
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -0700151 p_token = strtok(tmp, CONF_COD_DELIMITERS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800152 sscanf(p_token, "%x", &x);
153 local_device_default_class[0] = (UINT8) x;
154 p_token = strtok(NULL, CONF_COD_DELIMITERS);
155 sscanf(p_token, "%x", &x);
156 local_device_default_class[1] = (UINT8) x;
157 p_token = strtok(NULL, CONF_COD_DELIMITERS);
158 sscanf(p_token, "%x", &x);
159 local_device_default_class[2] = (UINT8) x;
160
161 return 0;
162}
163
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -0700164int logging_cfg_onoff(const char *p_conf_name, const char *p_conf_value)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800165{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800166 UNUSED(p_conf_name);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800167 if (strcmp(p_conf_value, "true") == 0)
168 hci_logging_enabled = TRUE;
169 else
170 hci_logging_enabled = FALSE;
171 return 0;
172}
173
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -0700174int logging_set_filepath(const char *p_conf_name, const char *p_conf_value)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800175{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800176 UNUSED(p_conf_name);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800177 strcpy(hci_logfile, p_conf_value);
178 return 0;
179}
180
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -0700181int trace_cfg_onoff(const char *p_conf_name, const char *p_conf_value)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800182{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800183 UNUSED(p_conf_name);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800184 trace_conf_enabled = (strcmp(p_conf_value, "true") == 0) ? TRUE : FALSE;
185 return 0;
186}
187
188/*****************************************************************************
189** CONF INTERFACE FUNCTIONS
190*****************************************************************************/
191
192/*******************************************************************************
193**
194** Function bte_load_conf
195**
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -0700196** Description Read conf entry from path file one by one and call
The Android Open Source Project5738f832012-12-12 16:00:35 -0800197** the corresponding config function
198**
199** Returns None
200**
201*******************************************************************************/
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -0700202void bte_load_conf(const char *path) {
203 assert(path != NULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800204
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -0700205 ALOGI("%s attempt to load stack conf from %s", __func__, path);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800206
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -0700207 config_t *config = config_new(path);
208 if (!config) {
209 ALOGI("%s file >%s< not found", __func__, path);
210 return;
211 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800212
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -0700213 for (const conf_entry_t *entry = &conf_table[0]; entry->key_name; ++entry) {
214 const char *value = config_get_string(config, CONFIG_DEFAULT_SECTION, entry->key_name, NULL);
215 if (value)
216 entry->p_action(entry->key_name, value);
217 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800218
Sharvil Nanavati9f8a8ae2014-05-04 22:48:09 -0700219 bte_trace_conf_config(config);
220 config_free(config);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800221}
222
223/*******************************************************************************
224**
225** Function bte_parse_did_conf
226**
227** Description Read conf entry from p_path file one by one and get
228** the corresponding config value
229**
230** Returns TRUE if success, else FALSE
231**
232*******************************************************************************/
233static BOOLEAN bte_parse_did_conf (const char *p_path, UINT32 num,
234 tKEY_VALUE_PAIRS *conf_pairs, UINT32 conf_pairs_num)
235{
236 UINT32 i, param_num=0, count=0, start_count=0, end_count=0, conf_num=0;
237 BOOLEAN key=TRUE, conf_found=FALSE;
238
239 FILE *p_file;
240 char *p;
241 char line[CONF_MAX_LINE_LEN+1]; /* add 1 for \0 char */
242
243 ALOGI("Attempt to load did conf from %s", p_path);
244
245 if ((p_file = fopen(p_path, "r")) != NULL)
246 {
247 /* read line by line */
248 while (fgets(line, CONF_MAX_LINE_LEN+1, p_file) != NULL)
249 {
250 count++;
251 if (line[0] == CONF_COMMENT)
252 continue;
253
254 if (conf_found && (conf_num == num) && (*line == '[')) {
255 conf_found = FALSE;
256 end_count = count-1;
257 break;
258 }
259
260 p = strtok(line, CONF_DELIMITERS);
261 while (p != NULL) {
262 if (conf_num <= num) {
263 if (key) {
264 if (!strcmp(p, conf_pairs[0].key)) {
265 if (++conf_num == num) {
266 conf_found = TRUE;
267 start_count = count;
268 strncpy(conf_pairs[0].value, "1", CONF_VALUE_LEN);
269 }
270 } else {
271 if (conf_num == num) {
272 for (i=1; i<conf_pairs_num; i++) {
273 if (!strcmp(p, conf_pairs[i].key)) {
274 param_num = i;
275 break;
276 }
277 }
278 if (i == conf_pairs_num) {
279 error("Attribute %s does not belong to %s configuration",
280 p, conf_pairs[0].key);
281 fclose(p_file);
282 return FALSE;
283 }
284 }
285 key = FALSE;
286 }
287 } else {
288 if ((conf_num == num) && param_num) {
289 strncpy(conf_pairs[param_num].value, p, CONF_VALUE_LEN-1);
290 param_num = 0;
291 }
292 key = TRUE;
293 }
294 }
295 p = strtok(NULL, CONF_DELIMITERS);
296 }
297 }
298
299 fclose(p_file);
300 }
301 else
302 {
303 ALOGI( "bte_parse_did_conf file >%s< not found", p_path);
304 }
305 if (!end_count)
306 end_count = count;
307
308 if (start_count) {
309 debug("Read %s configuration #%u from lines %u to %u in file %s",
310 conf_pairs[0].key, (unsigned int)num, (unsigned int)start_count,
311 (unsigned int)end_count, p_path);
312 return TRUE;
313 }
314
315 error("%s configuration not found in file %s", conf_pairs[0].key, p_path);
316 return FALSE;
317}
318
319/*******************************************************************************
320**
321** Function bte_load_did_conf
322**
323** Description Set local Device ID records, reading from configuration files
324**
325** Returns None
326**
327*******************************************************************************/
328
329void bte_load_did_conf (const char *p_path)
330{
331 tBTA_DI_RECORD rec;
332 UINT32 rec_num, i, j;
333
334 for (i=1; i<=BTA_DI_NUM_MAX; i++) {
335 for (j=0; j<CONF_DID_MAX; j++) {
336 *did_conf_pairs[j].value = 0;
337 }
338
339 if (bte_parse_did_conf(p_path, i, did_conf_pairs, CONF_DID_MAX)) {
340 memset(&rec, 0, sizeof(rec));
341
342 if (*did_conf_pairs[CONF_DID_RECORD_NUM].value) {
343 rec_num = (UINT32)(strtoul(did_conf_pairs[CONF_DID_RECORD_NUM].value, NULL, 0)-1);
344 } else {
345 debug("[%d] Unknown %s", (unsigned int)i, did_conf_pairs[CONF_DID_RECORD_NUM].key);
346 continue;
347 }
348
349 if (*did_conf_pairs[CONF_DID_VENDOR_ID].value) {
350 rec.vendor = (UINT16)strtoul(did_conf_pairs[CONF_DID_VENDOR_ID].value, NULL, 0);
351 } else {
352 rec.vendor = LMP_COMPID_BROADCOM;
353 }
354
355 if (*did_conf_pairs[CONF_DID_VENDOR_ID_SOURCE].value) {
356 rec.vendor_id_source = (UINT16)strtoul(did_conf_pairs[CONF_DID_VENDOR_ID_SOURCE].value, NULL, 0);
357 } else {
358 rec.vendor_id_source = DI_VENDOR_ID_SOURCE_BTSIG;
359 }
360
361 if ((*did_conf_pairs[CONF_DID].value == 0) ||
362 (rec_num >= BTA_DI_NUM_MAX) ||
363 (!((rec.vendor_id_source >= DI_VENDOR_ID_SOURCE_BTSIG) &&
364 (rec.vendor_id_source <= DI_VENDOR_ID_SOURCE_USBIF))) ||
365 (rec.vendor == DI_VENDOR_ID_DEFAULT)) {
366
367 error("DID record #%u not set", (unsigned int)i);
368 for (j=0; j<CONF_DID_MAX; j++) {
369 error("%s:%s", did_conf_pairs[j].key, did_conf_pairs[j].value);
370 }
371 continue;
372 }
373
374 rec.product = (UINT16)strtoul(did_conf_pairs[CONF_DID_PRODUCT_ID].value, NULL, 0);
375 rec.version = (UINT16)strtoul(did_conf_pairs[CONF_DID_VERSION].value, NULL, 0);
376
377 strncpy(rec.client_executable_url,
378 did_conf_pairs[CONF_DID_CLIENT_EXECUTABLE_URL].value,
379 SDP_MAX_ATTR_LEN);
380 strncpy(rec.service_description,
381 did_conf_pairs[CONF_DID_SERVICE_DESCRIPTION].value,
382 SDP_MAX_ATTR_LEN);
383 strncpy(rec.documentation_url,
384 did_conf_pairs[CONF_DID_DOCUMENTATION_URL].value,
385 SDP_MAX_ATTR_LEN);
386
387 for (j=0; j<strlen(did_conf_pairs[CONF_DID_PRIMARY_RECORD].value); j++) {
388 did_conf_pairs[CONF_DID_PRIMARY_RECORD].value[j] =
389 tolower(did_conf_pairs[CONF_DID_PRIMARY_RECORD].value[j]);
390 }
391 if ((!strcmp(did_conf_pairs[CONF_DID_PRIMARY_RECORD].value, "true")) ||
392 (!strcmp(did_conf_pairs[CONF_DID_PRIMARY_RECORD].value, "1"))) {
393 rec.primary_record = TRUE;
394 } else {
395 rec.primary_record = FALSE;
396 }
397
398 info("[%u] primary_record=%d vendor_id=0x%04X vendor_id_source=0x%04X product_id=0x%04X version=0x%04X",
399 (unsigned int)rec_num+1, rec.primary_record, rec.vendor,
400 rec.vendor_id_source, rec.product, rec.version);
401 if (*rec.client_executable_url) {
402 info(" client_executable_url=%s", rec.client_executable_url);
403 }
404 if (*rec.service_description) {
405 info(" service_description=%s", rec.service_description);
406 }
407 if (*rec.documentation_url) {
408 info(" documentation_url=%s", rec.documentation_url);
409 }
410
411 if (BTA_DmSetLocalDiRecord(&rec, &rec_num) != BTA_SUCCESS) {
412 error("SetLocalDiInfo failed for #%u!", (unsigned int)i);
413 }
414 }
415 }
416}