[android源码解析]bluetoothd默认初始化中main.conf的解析

本文深入剖析了Bluetoothd启动过程中的关键步骤,包括默认配置初始化、命令行参数解析及main.conf配置文件的具体处理方式。

上文我们从总体上把握了bluetoothd启动的流程,下面我们就具体的细节来详细分析一下,首先要看到的就是init_defaults,在它里面最重要也是最有意义的就是main.conf的解析了。我们通常需要修改某个配置就去修改main.conf中的内容,那么这些内容又是如何真正被配置呢?本文就来和你一一说来。

2.2.1 默认的初始化简介

这个函数会初始化一些默认的配置,在main.conf中没有修改的参数,将会使用这里定义的,当然,若是修改过了,那就只能使用这里的参数了

static void init_defaults(void)
{
	/* Default HCId settings */
	//默认的配置
	//这里的main_opts是一个全局变量
	memset(&main_opts, 0, sizeof(main_opts));
	main_opts.mode	= MODE_CONNECTABLE; //可连接的
	main_opts.name	= g_strdup("BlueZ");//名字是bluez
	main_opts.discovto	= DEFAULT_DISCOVERABLE_TIMEOUT;//默认的可发现timeout是3分钟
	main_opts.remember_powered = TRUE;
	main_opts.reverse_sdp = TRUE;
	main_opts.name_resolv = TRUE; //需要remote name request
	main_opts.link_mode = HCI_LM_ACCEPT;
	//支持role swtich以sniff,hold和park状态了
	main_opts.link_policy = HCI_LP_RSWITCH | HCI_LP_SNIFF |
						HCI_LP_HOLD | HCI_LP_PARK;
	//这里就是获取主机的名字来作为host_name
	if (gethostname(main_opts.host_name, sizeof(main_opts.host_name) - 1) < 0)
		strcpy(main_opts.host_name, "noname");
}

2.2.2glib命令行解析库的简单使用

这个方法使用的目的就是避免一个一个参数进行switch的解析,就像hciattach中写的那样,大家会发现那样去解析要写很大一段代码。glib库提供了一个库函数进行解析,他会根据一个GoptionEntry结构体进行自动地解析,先来看一下GoptionEntry结构体:

	typedef struct {  
	  const gchar *long_name;  // 完整命令 如:--name  
	  gchar        short_name;    // 简写命令 如:-n  
	  gint         flags;           // GOptionFlags枚举的值  
	  GOptionArg   arg;    // GOptionArg枚举的值  
	  gpointer     arg_data; // 解析出来的数据,所要存储的位置  
	    
	  const gchar *description;  // 参数描述,--help可以查看到  
	  const gchar *arg_description;   
	} GOptionEntry;  

这样一看就感觉到很清晰了吧,就是说我们解析命令行中的参数最终把它保存到arg_data中,我们只要事先实现这个结构体就万事大吉了。

回到我们的分析中来,我们这个结构体是实现在options中的,我们看一下它的定义:

static GOptionEntry options[] = {
	{ "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
				G_OPTION_ARG_CALLBACK, parse_debug,
				"Specify debug options to enable", "DEBUG" },
	{ "plugin", 'p', 0, G_OPTION_ARG_STRING, &option_plugin,
				"Specify plugins to load", "NAME,..," },
	{ "noplugin", 'P', 0, G_OPTION_ARG_STRING, &option_noplugin,
				"Specify plugins not to load", "NAME,..." },
	{ "nodetach", 'n', G_OPTION_FLAG_REVERSE,
				G_OPTION_ARG_NONE, &option_detach,
				"Don't run as daemon in background" },
	{ "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
				"Show version information and exit" },
	{ "udev", 'u', 0, G_OPTION_ARG_NONE, &option_udev,
				"Run from udev mode of operation" },
	{ NULL },
};


所以,很清晰把,就是我们定义了一系列的参数比如-n,后面的参数就会被保存在parse_debug中,简单吧。

那么在我们想解析的时候该如何使用,并调用哪些函数呢?

首先你需要调用context =g_option_context_new(NULL);来创建一个goptioncontext,然后

调用g_option_context_add_main_entries(context,options, NULL);关联对应的GoptionEntry,下面就可以调用_option_context_parse(context, &argc, &argv, &err)来解析传入的参数了,需要注意的是,在最后不要忘了调用g_option_context_free来释放对应的goptioncontext,否则就会出现内存泄露的情况了。

2.2.3main.conf的解析

这个函数就是根据main.conf中的配置进行不同的设置。需要注意的是bluez中有一个main.conf的文件,然而android最终并没有使用这个文件,而是使用了system/bluetooth/data目录下的main.conf文件。

初略地去看一下,这个文件的内容其实蛮简单的,去除掉注释就是这样的:

[General]
Name = %m
Class = 0x40020C
DiscoverableTimeout = 120
PairableTimeout = 0
PageTimeout = 8192
DiscoverSchedulerInterval = 30
InitiallyPowered = true
RememberPowered = false
DeviceID = android:generic:1.5
ReverseServiceDiscovery = true
NameResolving = true
DebugKeys = false
EnableLE = false
AttributeServer = false
DefaultLinkPolicy = 7

下面我们就根据源码解析的代码来看一下这些参数都是什么意思

static void parse_config(GKeyFile *config)
{
	GError *err = NULL;
	char *str;
	int val;
	gboolean boolean;
	//首先肯定是文件要是存在的
	if (!config)
		return;

	DBG("parsing main.conf");
	//找到General下面的DiscoverableTimeout
	val = g_key_file_get_integer(config, "General",
						"DiscoverableTimeout", &err);
	if (err) {
		DBG("%s", err->message);
		g_clear_error(&err);
	} else {
		//设置main_opts中的discovto参数
		//同时把flags中的HCID_SET_DISCOVTO置位
		DBG("discovto=%d", val);
		main_opts.discovto = val;
		main_opts.flags |= 1 << HCID_SET_DISCOVTO;
	}
……
	//下面的代码就全部是类似的,不再相信分析
	//所以,都只是根据main.conf然后设置一些值,这些值将在后面才会真正用到,我们在用到的时候再来具体分析
}


这样main.conf中的内容就被我们解析出来了,后面只要根据具体的内容做具体的配置就可以了。这些配置的值如何被使用的,我们在后面的文章中将一一介绍。

若您觉得该文章对您有帮助,请在下面用鼠标轻轻按一下“顶”,哈哈~~·


<think>好的,用户之前已经问过如何在嵌入式代码中修改蓝牙广播名,现在他们的问题是询问蓝牙广播名通常在哪个文件中进行修改。我需要理解用户的需求,他们可能正在开发嵌入式蓝牙设备,或者是在某个特定的平台上进行开发,比如Nordic、ESP32或者ST的芯片。 用户之前的提问是关于代码层面的修改,现在转向具体文件的位置。这可能意味着他们现在在项目结构中寻找需要修改的地方,而不仅仅是代码逻辑。他们可能在寻找配置文件或特定的源文件,比如在ESP-IDF中的某个组件,或者Nordic SDK中的示例代码里的main.c。 我需要考虑不同平台的情况,因为不同的芯片厂商和SDK会有不同的文件结构。例如,Nordic的示例项目可能在main.c里设置设备名称,而ESP32可能在主程序或专门的配置文件中。另外,像Arduino这样的开发环境可能会有更简化的结构,用户可能只需要修改一个头文件或主ino文件。 用户可能的真实需求是快速找到需要修改的位置,而不需要深入理解整个项目结构。他们可能对嵌入式开发有一定的了解,但不太熟悉特定平台的文件组织方式。因此,我应该分平台说明常见的文件位置,并给出示例路径,同时提醒他们注意事项,比如重新编译和广播数据格式。 另外,用户可能遇到的问题包括修改了文件但名称未生效,这可能是因为没有重新初始化广播或者广播数据包过长。需要强调检查名称长度和重新启动广播的重要性。同时,建议用户使用工具验证广播数据,确保名称正确包含在内。 总结回答结构:首先按不同平台(如Nordic、ESP32、Arduino、Linux等)说明常见的文件位置,然后给出注意事项和调试建议。需要保持回答清晰有条理,帮助用户快速定位到需要修改的地方。</think>在嵌入式开发中,蓝牙广播名的修改通常与 **代码实现** 和 **SDK配置** 相关,具体文件位置取决于芯片平台和开发框架。以下是常见平台中可能涉及的文件及修改方法: --- ### **1. 芯片原厂SDK(如Nordic、ESP32、ST等)** #### **常见文件位置** - **主程序文件**(如 `main.c` / `app_main.c`): 设备名称可能直接在初始化蓝牙的代码中设置,例如: ```c // 示例:Nordic nRF SDK中的 main.c void ble_init() { ble_gap_conn_sec_mode_t sec_mode; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); sd_ble_gap_device_name_set(&sec_mode, "MyDevice", strlen("MyDevice")); } ``` - **蓝牙配置文件**: 某些SDK会将名称定义在头文件或配置文件中,例如: - ESP32 的 `menuconfig`(通过 `idf.py menuconfig` 配置): ```text Component config → Bluetooth → Bluetooth controller → Bluetooth device name ``` - Nordic 的 `sdk_config.h`(通过Kconfig或直接修改宏定义)。 - **广播数据构造文件**: 若广播数据是手动组包的(例如自定义广播内容),设备名可能在广播初始化函数中设置: ```c // 示例:在 ble_advertising.c 中定义广播数据 static uint8_t adv_data[] = { 0x02, 0x01, 0x06, // Flags 0x0A, 0x09, 'M','y','D','e','v' // 设备名(AD Type 0x09) }; ``` --- ### **2. 基于Arduino或第三方库** - **主程序文件(.ino 或 .cpp)**: 名称可能在 `setup()` 函数中通过库API设置。例如ESP32 Arduino库: ```cpp #include <BLEDevice.h> void setup() { BLEDevice::init("MyDevice"); // 直接在此处修改名称 } ``` - **库的配置文件(.h / .cpp)**: 某些第三方蓝牙库可能将默认名称定义在头文件中,例如: ```cpp // 示例:某BLE库的 BLEConfig.h #define DEFAULT_DEVICE_NAME "MyDevice" ``` --- ### **3. 基于Linux系统(如树莓派、BlueZ协议栈)** - **BlueZ配置文件**: 在Linux系统中,蓝牙名称通常通过 `bluetoothd` 服务和配置文件控制: - 修改 `/etc/bluetooth/main.conf`: ```ini [General] Name = MyDevice # 修改此项 ``` - 重启服务生效: ```bash sudo systemctl restart bluetooth ``` --- ### **4. 注意事项** 1. **名称长度限制**: 蓝牙广播名通常不超过 **31字节**(受广播数据包长度限制)。 2. **代码逻辑依赖**: 某些SDK可能需要在修改名称后 **重启广播** 或 **重新初始化蓝牙协议栈**。 3. **广播数据包格式**: 若名称未生效,需检查广播数据包是否包含 `AD Type 0x09`(Complete Local Name)。 --- ### **5. 调试建议** - **使用工具验证**: 通过手机蓝牙扫描(如nRF Connect、LightBlue)或抓包工具(Wireshark)确认广播名是否更新。 - **检查代码路径**: 确保修改的代码文件被编译到最终固件中(避免多文件重复定义导致未生效)。 --- 如果需要针对具体平台(如ESP-IDF、nRF Connect SDK、Zephyr等)进一步定位文件,可以提供芯片型号或开发环境,我会补充更详细的说明!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值