ubuntu bluetooth 配对过程

bluetoothd运行时(main函数启动时),加载plugin(调用plugin_init函数):

  1. gboolean plugin_init(GKeyFile *config)  
  2. {  
  3.     GSList *list;  
  4.     GDir *dir;  
  5.     const gchar *file;  
  6.     gchar **disabled;  
  7.     unsigned int i;  
  8.   
  9.     /* Make a call to BtIO API so its symbols got resolved before the 
  10.      * plugins are loaded. */  
  11.     bt_io_error_quark();  
  12.   
  13.     if (config)  
  14.         disabled = g_key_file_get_string_list(config, "General",  
  15.                             "DisablePlugins",  
  16.                             NULL, NULL);  
  17.     else  
  18.         disabled = NULL;  
  19.   
  20.     info("Loading builtin plugins");  
  21.   
  22.     //add default plugins, those plugins always need for bluetoothd runing  
  23.     //those plugins will add to the global link named plugins  
  24.     for (i = 0; __bluetooth_builtin[i]; i++) {  
  25.         if (is_disabled(__bluetooth_builtin[i]->name, disabled))  
  26.             continue;  
  27.   
  28.         add_plugin(NULL,  __bluetooth_builtin[i]);  
  29.     }  
  30.   
  31.     if (strlen(PLUGINDIR) == 0) {  
  32.         g_strfreev(disabled);  
  33.         goto start;  
  34.     }  
  35.   
  36.     info("Loading plugins %s\n", PLUGINDIR);  
  37.   
  38.     dir = g_dir_open(PLUGINDIR, 0, NULL);  
  39.     if (!dir) {  
  40.         g_strfreev(disabled);  
  41.         goto start;  
  42.     }  
  43.   
  44.     //add user plugins, those plugins stored in PLUGINDIR path, and the   
  45.     //PLUGINDIR = /usr/local/lib/bluetooth/plugins. The bluetoothd will  
  46.     //find all those plugins which name *.so, and open them, get the method  
  47.     //named bluetooth_plugin_desc, it will also add those plugins to the  
  48.     //plugins links.  
  49.     while ((file = g_dir_read_name(dir)) != NULL) {  
  50.         struct bluetooth_plugin_desc *desc;  
  51.         void *handle;  
  52.         gchar *filename;  
  53.   
  54.         if (g_str_has_prefix(file, "lib") == TRUE ||  
  55.                 g_str_has_suffix(file, ".so") == FALSE)  
  56.             continue;  
  57.   
  58.         if (is_disabled(file, disabled))  
  59.             continue;  
  60.   
  61.         filename = g_build_filename(PLUGINDIR, file, NULL);  
  62.   
  63.         handle = dlopen(filename, RTLD_NOW);  
  64.         if (handle == NULL) {  
  65.             error("Can't load plugin %s: %s", filename,  
  66.                                 dlerror());  
  67.             g_free(filename);  
  68.             continue;  
  69.         }  
  70.   
  71.         g_free(filename);  
  72.   
  73.         desc = dlsym(handle, "bluetooth_plugin_desc");  
  74.         if (desc == NULL) {  
  75.             error("Can't load plugin description: %s", dlerror());  
  76.             dlclose(handle);  
  77.             continue;  
  78.         }  
  79.   
  80.         if (add_plugin(handle, desc) == FALSE)  
  81.             dlclose(handle);  
  82.     }  
  83.   
  84.     g_dir_close(dir);  
  85.   
  86.     g_strfreev(disabled);  
  87.   
  88. start:  
  89.     //init all of the plugins by calling the plugins init function  
  90.     for (list = plugins; list; list = list->next) {  
  91.         struct bluetooth_plugin *plugin = list->data;  
  92.   
  93.         if (plugin->desc->init() < 0) {  
  94.             error("Failed to init %s plugin", plugin->desc->name);  
  95.             continue;  
  96.         }  
  97.         info("plugins active\n");  
  98.         plugin->active = TRUE;  
  99.     }  
  100.   
  101.     return TRUE;  
  102. }  
gboolean plugin_init(GKeyFile *config)
{
	GSList *list;
	GDir *dir;
	const gchar *file;
	gchar **disabled;
	unsigned int i;

	/* Make a call to BtIO API so its symbols got resolved before the
	 * plugins are loaded. */
	bt_io_error_quark();

	if (config)
		disabled = g_key_file_get_string_list(config, "General",
							"DisablePlugins",
							NULL, NULL);
	else
		disabled = NULL;

	info("Loading builtin plugins");

	//add default plugins, those plugins always need for bluetoothd runing
	//those plugins will add to the global link named plugins
	for (i = 0; __bluetooth_builtin[i]; i++) {
		if (is_disabled(__bluetooth_builtin[i]->name, disabled))
			continue;

		add_plugin(NULL,  __bluetooth_builtin[i]);
	}

	if (strlen(PLUGINDIR) == 0) {
		g_strfreev(disabled);
		goto start;
	}

	info("Loading plugins %s\n", PLUGINDIR);

	dir = g_dir_open(PLUGINDIR, 0, NULL);
	if (!dir) {
		g_strfreev(disabled);
		goto start;
	}

	//add user plugins, those plugins stored in PLUGINDIR path, and the 
	//PLUGINDIR = /usr/local/lib/bluetooth/plugins. The bluetoothd will
	//find all those plugins which name *.so, and open them, get the method
	//named bluetooth_plugin_desc, it will also add those plugins to the
	//plugins links.
	while ((file = g_dir_read_name(dir)) != NULL) {
		struct bluetooth_plugin_desc *desc;
		void *handle;
		gchar *filename;

		if (g_str_has_prefix(file, "lib") == TRUE ||
				g_str_has_suffix(file, ".so") == FALSE)
			continue;

		if (is_disabled(file, disabled))
			continue;

		filename = g_build_filename(PLUGINDIR, file, NULL);

		handle = dlopen(filename, RTLD_NOW);
		if (handle == NULL) {
			error("Can't load plugin %s: %s", filename,
								dlerror());
			g_free(filename);
			continue;
		}

		g_free(filename);

		desc = dlsym(handle, "bluetooth_plugin_desc");
		if (desc == NULL) {
			error("Can't load plugin description: %s", dlerror());
			dlclose(handle);
			continue;
		}

		if (add_plugin(handle, desc) == FALSE)
			dlclose(handle);
	}

	g_dir_close(dir);

	g_strfreev(disabled);

start:
	//init all of the plugins by calling the plugins init function
	for (list = plugins; list; list = list->next) {
		struct bluetooth_plugin *plugin = list->data;

		if (plugin->desc->init() < 0) {
			error("Failed to init %s plugin", plugin->desc->name);
			continue;
		}
		info("plugins active\n");
		plugin->active = TRUE;
	}

	return TRUE;
}
函数中__bluetooth_builtin结构体为存储加载的plugin的入口地址,这些地址是通过连接宏##连接的,其中包含hciops模块的加载。此函数将结构体中的地址加载成plugins链表,然后循环调用每个模块的初始化init函数。对应于hciops模块,调用初始化函数为hciops_init。__bluetooth_builtin结构体和连接宏定义如下:
  1. static struct bluetooth_plugin_desc *__bluetooth_builtin[] = {  
  2.   &__bluetooth_builtin_audio,  
  3.   &__bluetooth_builtin_input,  
  4.   &__bluetooth_builtin_serial,  
  5.   &__bluetooth_builtin_network,  
  6.   &__bluetooth_builtin_service,  
  7.   &__bluetooth_builtin_hciops,  
  8.   &__bluetooth_builtin_hal,  
  9.   &__bluetooth_builtin_storage,  
  10.   NULL  
  11. };  
static struct bluetooth_plugin_desc *__bluetooth_builtin[] = {
  &__bluetooth_builtin_audio,
  &__bluetooth_builtin_input,
  &__bluetooth_builtin_serial,
  &__bluetooth_builtin_network,
  &__bluetooth_builtin_service,
  &__bluetooth_builtin_hciops,
  &__bluetooth_builtin_hal,
  &__bluetooth_builtin_storage,
  NULL
};
  1. #define BLUETOOTH_PLUGIN_DEFINE(name, version, priority, init, exit) \  
  2.         struct bluetooth_plugin_desc __bluetooth_builtin_ ## name = { \  
  3.             #name, version, priority, init, exit \  
  4.         };  
#define BLUETOOTH_PLUGIN_DEFINE(name, version, priority, init, exit) \
		struct bluetooth_plugin_desc __bluetooth_builtin_ ## name = { \
			#name, version, priority, init, exit \
		};
hciops模块初始化:
  1. static int hciops_init(void)  
  2. {  
  3.     info("hciops_init\n");  
  4.     return btd_register_adapter_ops(&hci_ops);  
  5. }  
static int hciops_init(void)
{
	info("hciops_init\n");
	return btd_register_adapter_ops(&hci_ops);
}
  1. int btd_register_adapter_ops(struct btd_adapter_ops *btd_adapter_ops)  
  2. {  
  3.     /* Already registered */  
  4.     if (adapter_ops)  
  5.         return -EALREADY;  
  6.   
  7.     if (btd_adapter_ops->setup == NULL)  
  8.         return -EINVAL;  
  9.   
  10.     adapter_ops = btd_adapter_ops;  
  11.   
  12.     return 0;  
  13. }  
int btd_register_adapter_ops(struct btd_adapter_ops *btd_adapter_ops)
{
	/* Already registered */
	if (adapter_ops)
		return -EALREADY;

	if (btd_adapter_ops->setup == NULL)
		return -EINVAL;

	adapter_ops = btd_adapter_ops;

	return 0;
}
这个初始化函数将静态hci_ops结构体变量赋值给了全局变量adapter_ops。hci_ops结构定义:
  1. static struct btd_adapter_ops hci_ops = {  
  2.     .setup = hciops_setup,  
  3.     .cleanup = hciops_cleanup,  
  4.     .start = hciops_start,  
  5.     .stop = hciops_stop,  
  6.     .set_powered = hciops_powered,  
  7.     .set_connectable = hciops_connectable,  
  8.     .set_discoverable = hciops_discoverable,  
  9.     .set_limited_discoverable = hciops_set_limited_discoverable,  
  10.     .start_discovery = hciops_start_discovery,  
  11.     .stop_discovery = hciops_stop_discovery,  
  12.     .resolve_name = hciops_resolve_name,  
  13.     .cancel_resolve_name = hciops_cancel_resolve_name,  
  14.     .set_name = hciops_set_name,  
  15.     .read_name = hciops_read_name,  
  16.     .set_class = hciops_set_class,  
  17. };  
static struct btd_adapter_ops hci_ops = {
	.setup = hciops_setup,
	.cleanup = hciops_cleanup,
	.start = hciops_start,
	.stop = hciops_stop,
	.set_powered = hciops_powered,
	.set_connectable = hciops_connectable,
	.set_discoverable = hciops_discoverable,
	.set_limited_discoverable = hciops_set_limited_discoverable,
	.start_discovery = hciops_start_discovery,
	.stop_discovery = hciops_stop_discovery,
	.resolve_name = hciops_resolve_name,
	.cancel_resolve_name = hciops_cancel_resolve_name,
	.set_name = hciops_set_name,
	.read_name = hciops_read_name,
	.set_class = hciops_set_class,
};
在plugin_init加载完plugins后,调用了adapter_ops_setup函数来启动HCI适配层:
  1. int adapter_ops_setup(void)  
  2. {  
  3.     if (!adapter_ops)  
  4.         return -EINVAL;  
  5.   
  6.     return adapter_ops->setup();  
  7. }  
int adapter_ops_setup(void)
{
	if (!adapter_ops)
		return -EINVAL;

	return adapter_ops->setup();
}
这个函数即调用里 hci_ops静态全局变量的setup函数,看hci_ops全局变量的定义,.setup指向hciops_setup函数:
  1. static int hciops_setup(void)  
  2. {  
  3.     struct sockaddr_hci addr;  
  4.     struct hci_filter flt;  
  5.     GIOChannel *ctl_io, *child_io;  
  6.     int sock, err;  
  7.   
  8.     info("hciops_setup\n");  
  9.   
  10.     if (child_pipe[0] != -1)  
  11.         return -EALREADY;  
  12.   
  13.     if (pipe(child_pipe) < 0) {  
  14.         err = errno;  
  15.         error("pipe(): %s (%d)", strerror(err), err);  
  16.         return -err;  
  17.     }  
  18.   
  19.     child_io = g_io_channel_unix_new(child_pipe[0]);  
  20.     g_io_channel_set_close_on_unref(child_io, TRUE);  
  21.     child_io_id = g_io_add_watch(child_io,  
  22.                 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,  
  23.                 child_exit, NULL);  
  24.     g_io_channel_unref(child_io);  
  25.   
  26.     /* Create and bind HCI socket */  
  27.     sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);  
  28.     if (sock < 0) {  
  29.         err = errno;  
  30.         error("Can't open HCI socket: %s (%d)", strerror(err),  
  31.                                 err);  
  32.         return -err;  
  33.     }  
  34.   
  35.     /* Set filter */  
  36.     hci_filter_clear(&flt);  
  37.     hci_filter_set_ptype(HCI_EVENT_PKT, &flt);  
  38.     hci_filter_set_event(EVT_STACK_INTERNAL, &flt);  
  39.     if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt,  
  40.                             sizeof(flt)) < 0) {  
  41.         err = errno;  
  42.         error("Can't set filter: %s (%d)", strerror(err), err);  
  43.         return -err;  
  44.     }  
  45.   
  46.     memset(&addr, 0, sizeof(addr));  
  47.     addr.hci_family = AF_BLUETOOTH;  
  48.     addr.hci_dev = HCI_DEV_NONE;  
  49.     if (bind(sock, (struct sockaddr *) &addr,  
  50.                             sizeof(addr)) < 0) {  
  51.         err = errno;  
  52.         error("Can't bind HCI socket: %s (%d)",  
  53.                             strerror(err), err);  
  54.         return -err;  
  55.     }  
  56.   
  57.     ctl_io = g_io_channel_unix_new(sock);  
  58.     g_io_channel_set_close_on_unref(ctl_io, TRUE);  
  59.   
  60.     ctl_io_id = g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL);  
  61.   
  62.     g_io_channel_unref(ctl_io);  
  63.   
  64.     /* Initialize already connected devices */  
  65.     return init_known_adapters(sock);  
  66. }  
static int hciops_setup(void)
{
	struct sockaddr_hci addr;
	struct hci_filter flt;
	GIOChannel *ctl_io, *child_io;
	int sock, err;

	info("hciops_setup\n");

	if (child_pipe[0] != -1)
		return -EALREADY;

	if (pipe(child_pipe) < 0) {
		err = errno;
		error("pipe(): %s (%d)", strerror(err), err);
		return -err;
	}

	child_io = g_io_channel_unix_new(child_pipe[0]);
	g_io_channel_set_close_on_unref(child_io, TRUE);
	child_io_id = g_io_add_watch(child_io,
				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
				child_exit, NULL);
	g_io_channel_unref(child_io);

	/* Create and bind HCI socket */
	sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
	if (sock < 0) {
		err = errno;
		error("Can't open HCI socket: %s (%d)", strerror(err),
								err);
		return -err;
	}

	/* Set filter */
	hci_filter_clear(&flt);
	hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
	hci_filter_set_event(EVT_STACK_INTERNAL, &flt);
	if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt,
							sizeof(flt)) < 0) {
		err = errno;
		error("Can't set filter: %s (%d)", strerror(err), err);
		return -err;
	}

	memset(&addr, 0, sizeof(addr));
	addr.hci_family = AF_BLUETOOTH;
	addr.hci_dev = HCI_DEV_NONE;
	if (bind(sock, (struct sockaddr *) &addr,
							sizeof(addr)) < 0) {
		err = errno;
		error("Can't bind HCI socket: %s (%d)",
							strerror(err), err);
		return -err;
	}

	ctl_io = g_io_channel_unix_new(sock);
	g_io_channel_set_close_on_unref(ctl_io, TRUE);

	ctl_io_id = g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL);

	g_io_channel_unref(ctl_io);

	/* Initialize already connected devices */
	return init_known_adapters(sock);
}
在函数的最后,调用里init_known_adapters启动里已知的hci设备,初始化HCI适配器:
  1. static int init_known_adapters(int ctl)  
  2. {  
  3.     struct hci_dev_list_req *dl;  
  4.     struct hci_dev_req *dr;  
  5.     int i, err;  
  6.   
  7.     info("init_known_adapters\n");  
  8.   
  9.     dl = g_try_malloc0(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t));  
  10.     if (!dl) {  
  11.         err = errno;  
  12.         error("Can't allocate devlist buffer: %s (%d)",  
  13.                             strerror(err), err);  
  14.         return -err;  
  15.     }  
  16.   
  17.     dl->dev_num = HCI_MAX_DEV;  
  18.     dr = dl->dev_req;  
  19.   
  20.     if (ioctl(ctl, HCIGETDEVLIST, (void *) dl) < 0) {  
  21.         err = errno;  
  22.         error("Can't get device list: %s (%d)",  
  23.                             strerror(err), err);  
  24.         g_free(dl);  
  25.         return -err;  
  26.     }  
  27.   
  28.     for (i = 0; i < dl->dev_num; i++, dr++) {  
  29.         device_event(HCI_DEV_REG, dr->dev_id);  
  30.   
  31.         if (hci_test_bit(HCI_UP, &dr->dev_opt)){  
  32.             info("here start the hci device\n");  
  33.             <span style="color: rgb(0, 0, 0);">device_event(HCI_DEV_UP, dr->dev_id);</span>  
  34.         }  
  35.     }  
  36.   
  37.     g_free(dl);  
  38.     return 0;  
  39. }  
static int init_known_adapters(int ctl)
{
	struct hci_dev_list_req *dl;
	struct hci_dev_req *dr;
	int i, err;

	info("init_known_adapters\n");

	dl = g_try_malloc0(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t));
	if (!dl) {
		err = errno;
		error("Can't allocate devlist buffer: %s (%d)",
							strerror(err), err);
		return -err;
	}

	dl->dev_num = HCI_MAX_DEV;
	dr = dl->dev_req;

	if (ioctl(ctl, HCIGETDEVLIST, (void *) dl) < 0) {
		err = errno;
		error("Can't get device list: %s (%d)",
							strerror(err), err);
		g_free(dl);
		return -err;
	}

	for (i = 0; i < dl->dev_num; i++, dr++) {
		device_event(HCI_DEV_REG, dr->dev_id);

		if (hci_test_bit(HCI_UP, &dr->dev_opt)){
			info("here start the hci device\n");
			device_event(HCI_DEV_UP, dr->dev_id);
		}
	}

	g_free(dl);
	return 0;
}
这个函数通过ioctl获取系统的hci设备列表,然后用device_event(HCI_DEV_UP..)启动HCI设备。device_event接收HCI_DEV_UP消息,调用HCI设备启动函数:
  1. static void device_event(int event, int index)  
  2. {  
  3.     switch (event) {  
  4.     case HCI_DEV_REG:  
  5.         info("HCI dev %d registered", index);  
  6.         device_devreg_setup(index);  
  7.         break;  
  8.   
  9.     case HCI_DEV_UNREG:  
  10.         info("HCI dev %d unregistered", index);  
  11.         manager_unregister_adapter(index);  
  12.         break;  
  13.   
  14. <span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">   case HCI_DEV_UP:  
  15.         info("HCI dev %d up", index);  
  16.         device_devup_setup(index);  
  17.         break;</span>  
  18.   
  19.     case HCI_DEV_DOWN:  
  20.         info("HCI dev %d down", index);  
  21.         manager_stop_adapter(index);  
  22.         stop_security_manager(index);  
  23.         break;  
  24.     }  
  25. }  
static void device_event(int event, int index)
{
	switch (event) {
	case HCI_DEV_REG:
		info("HCI dev %d registered", index);
		device_devreg_setup(index);
		break;

	case HCI_DEV_UNREG:
		info("HCI dev %d unregistered", index);
		manager_unregister_adapter(index);
		break;

	case HCI_DEV_UP:
		info("HCI dev %d up", index);
		device_devup_setup(index);
		break;

	case HCI_DEV_DOWN:
		info("HCI dev %d down", index);
		manager_stop_adapter(index);
		stop_security_manager(index);
		break;
	}
}

启动HCI DEV设备:

  1. static void device_devup_setup(int index)  
  2. {  
  3.     configure_device(index);  
  4.   
  5.     <span style="color: rgb(0, 0, 0);">start_security_manager</span>(index);  
  6.   
  7.     /* Return value 1 means ioctl(DEVDOWN) was performed */  
  8.     if (manager_start_adapter(index) == 1)  
  9.         stop_security_manager(index);  
  10. }  
static void device_devup_setup(int index)
{
	configure_device(index);

	start_security_manager(index);

	/* Return value 1 means ioctl(DEVDOWN) was performed */
	if (manager_start_adapter(index) == 1)
		stop_security_manager(index);
}
开始安全管理:
  1. void start_security_manager(int hdev)  
  2. {  
  3.     GIOChannel *chan = io_data[hdev].channel;  
  4.     struct hci_dev_info *di;  
  5.     struct hci_filter flt;  
  6.     read_stored_link_key_cp cp;  
  7.     int dev;  
  8.   
  9.     if (chan)  
  10.         return;  
  11.   
  12.     info("Starting security manager %d", hdev);  
  13.   
  14.     if ((dev = hci_open_dev(hdev)) < 0) {  
  15.         error("Can't open device hci%d: %s (%d)",  
  16.                         hdev, strerror(errno), errno);  
  17.         return;  
  18.     }  
  19.   
  20.     /* Set filter */  
  21.     hci_filter_clear(&flt);  
  22.     hci_filter_set_ptype(HCI_EVENT_PKT, &flt);  
  23.     hci_filter_set_event(EVT_CMD_STATUS, &flt);  
  24.     hci_filter_set_event(EVT_CMD_COMPLETE, &flt);  
  25.     hci_filter_set_event(EVT_PIN_CODE_REQ, &flt);  
  26.     hci_filter_set_event(EVT_LINK_KEY_REQ, &flt);  
  27.     hci_filter_set_event(EVT_LINK_KEY_NOTIFY, &flt);  
  28.     hci_filter_set_event(EVT_RETURN_LINK_KEYS, &flt);  
  29.     hci_filter_set_event(EVT_IO_CAPABILITY_REQUEST, &flt);  
  30.     hci_filter_set_event(EVT_IO_CAPABILITY_RESPONSE, &flt);  
  31.     hci_filter_set_event(EVT_USER_CONFIRM_REQUEST, &flt);  
  32.     hci_filter_set_event(EVT_USER_PASSKEY_REQUEST, &flt);  
  33.     hci_filter_set_event(EVT_REMOTE_OOB_DATA_REQUEST, &flt);  
  34.     hci_filter_set_event(EVT_USER_PASSKEY_NOTIFY, &flt);  
  35.     hci_filter_set_event(EVT_KEYPRESS_NOTIFY, &flt);  
  36.     hci_filter_set_event(EVT_SIMPLE_PAIRING_COMPLETE, &flt);  
  37.     hci_filter_set_event(EVT_AUTH_COMPLETE, &flt);  
  38.     hci_filter_set_event(EVT_REMOTE_NAME_REQ_COMPLETE, &flt);  
  39.     hci_filter_set_event(EVT_READ_REMOTE_VERSION_COMPLETE, &flt);  
  40.     hci_filter_set_event(EVT_READ_REMOTE_FEATURES_COMPLETE, &flt);  
  41.     hci_filter_set_event(EVT_REMOTE_HOST_FEATURES_NOTIFY, &flt);  
  42.     hci_filter_set_event(EVT_INQUIRY_COMPLETE, &flt);  
  43.     hci_filter_set_event(EVT_INQUIRY_RESULT, &flt);  
  44.     hci_filter_set_event(EVT_INQUIRY_RESULT_WITH_RSSI, &flt);  
  45.     hci_filter_set_event(EVT_EXTENDED_INQUIRY_RESULT, &flt);  
  46.     hci_filter_set_event(EVT_CONN_REQUEST, &flt);  
  47.     hci_filter_set_event(EVT_CONN_COMPLETE, &flt);  
  48.     hci_filter_set_event(EVT_DISCONN_COMPLETE, &flt);  
  49.     if (setsockopt(dev, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {  
  50.         error("Can't set filter on hci%d: %s (%d)",  
  51.                         hdev, strerror(errno), errno);  
  52.         close(dev);  
  53.         return;  
  54.     }  
  55.   
  56.     di = g_new(struct hci_dev_info, 1);  
  57.     if (hci_devinfo(hdev, di) < 0) {  
  58.         error("Can't get device info: %s (%d)",  
  59.                             strerror(errno), errno);  
  60.         close(dev);  
  61.         g_free(di);  
  62.         return;  
  63.     }  
  64.   
  65.     chan = g_io_channel_unix_new(dev);  
  66.     g_io_channel_set_close_on_unref(chan, TRUE);  
  67.     io_data[hdev].watch_id = g_io_add_watch_full(chan, G_PRIORITY_LOW,  
  68.                         G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,  
  69.                         <span style="color: rgb(0, 0, 0);">io_security_event</span>, di, (GDestroyNotify) g_free);//注册消息处理函数  
  70.     io_data[hdev].channel = chan;  
  71.     io_data[hdev].pin_length = -1;  
  72.   
  73.     if (hci_test_bit(HCI_RAW, &di->flags))  
  74.         return;  
  75.   
  76.     bacpy(&cp.bdaddr, BDADDR_ANY);  
  77.     cp.read_all = 1;  
  78.   
  79.     hci_send_cmd(dev, OGF_HOST_CTL, OCF_READ_STORED_LINK_KEY,  
  80.             READ_STORED_LINK_KEY_CP_SIZE, (void *) &cp);  
  81. }  
void start_security_manager(int hdev)
{
	GIOChannel *chan = io_data[hdev].channel;
	struct hci_dev_info *di;
	struct hci_filter flt;
	read_stored_link_key_cp cp;
	int dev;

	if (chan)
		return;

	info("Starting security manager %d", hdev);

	if ((dev = hci_open_dev(hdev)) < 0) {
		error("Can't open device hci%d: %s (%d)",
						hdev, strerror(errno), errno);
		return;
	}

	/* Set filter */
	hci_filter_clear(&flt);
	hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
	hci_filter_set_event(EVT_CMD_STATUS, &flt);
	hci_filter_set_event(EVT_CMD_COMPLETE, &flt);
	hci_filter_set_event(EVT_PIN_CODE_REQ, &flt);
	hci_filter_set_event(EVT_LINK_KEY_REQ, &flt);
	hci_filter_set_event(EVT_LINK_KEY_NOTIFY, &flt);
	hci_filter_set_event(EVT_RETURN_LINK_KEYS, &flt);
	hci_filter_set_event(EVT_IO_CAPABILITY_REQUEST, &flt);
	hci_filter_set_event(EVT_IO_CAPABILITY_RESPONSE, &flt);
	hci_filter_set_event(EVT_USER_CONFIRM_REQUEST, &flt);
	hci_filter_set_event(EVT_USER_PASSKEY_REQUEST, &flt);
	hci_filter_set_event(EVT_REMOTE_OOB_DATA_REQUEST, &flt);
	hci_filter_set_event(EVT_USER_PASSKEY_NOTIFY, &flt);
	hci_filter_set_event(EVT_KEYPRESS_NOTIFY, &flt);
	hci_filter_set_event(EVT_SIMPLE_PAIRING_COMPLETE, &flt);
	hci_filter_set_event(EVT_AUTH_COMPLETE, &flt);
	hci_filter_set_event(EVT_REMOTE_NAME_REQ_COMPLETE, &flt);
	hci_filter_set_event(EVT_READ_REMOTE_VERSION_COMPLETE, &flt);
	hci_filter_set_event(EVT_READ_REMOTE_FEATURES_COMPLETE, &flt);
	hci_filter_set_event(EVT_REMOTE_HOST_FEATURES_NOTIFY, &flt);
	hci_filter_set_event(EVT_INQUIRY_COMPLETE, &flt);
	hci_filter_set_event(EVT_INQUIRY_RESULT, &flt);
	hci_filter_set_event(EVT_INQUIRY_RESULT_WITH_RSSI, &flt);
	hci_filter_set_event(EVT_EXTENDED_INQUIRY_RESULT, &flt);
	hci_filter_set_event(EVT_CONN_REQUEST, &flt);
	hci_filter_set_event(EVT_CONN_COMPLETE, &flt);
	hci_filter_set_event(EVT_DISCONN_COMPLETE, &flt);
	if (setsockopt(dev, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
		error("Can't set filter on hci%d: %s (%d)",
						hdev, strerror(errno), errno);
		close(dev);
		return;
	}

	di = g_new(struct hci_dev_info, 1);
	if (hci_devinfo(hdev, di) < 0) {
		error("Can't get device info: %s (%d)",
							strerror(errno), errno);
		close(dev);
		g_free(di);
		return;
	}

	chan = g_io_channel_unix_new(dev);
	g_io_channel_set_close_on_unref(chan, TRUE);
	io_data[hdev].watch_id = g_io_add_watch_full(chan, G_PRIORITY_LOW,
						G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
						io_security_event, di, (GDestroyNotify) g_free);//注册消息处理函数
	io_data[hdev].channel = chan;
	io_data[hdev].pin_length = -1;

	if (hci_test_bit(HCI_RAW, &di->flags))
		return;

	bacpy(&cp.bdaddr, BDADDR_ANY);
	cp.read_all = 1;

	hci_send_cmd(dev, OGF_HOST_CTL, OCF_READ_STORED_LINK_KEY,
			READ_STORED_LINK_KEY_CP_SIZE, (void *) &cp);
}

这个函数打开里hci dev设备(实际上就是一个socket),设置处理消息类型,然后创建channel,最后用io_security_event函数侦听远程设备发送过来的消息(socket数据)。接收消息函数:

  1. static gboolean io_security_event(GIOChannel *chan, GIOCondition cond,  
  2.                                 gpointer data)  
  3. {  
  4.     unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr = buf;  
  5.     struct hci_dev_info *di = data;  
  6.     int type, dev;  
  7.     size_t len;  
  8.     hci_event_hdr *eh;  
  9.     GIOError err;  
  10.     evt_cmd_status *evt;  
  11.   
  12.     if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {  
  13.         delete_channel(chan);  
  14.         return FALSE;  
  15.     }  
  16.   
  17.     if ((err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len))) {  
  18.         if (err == G_IO_ERROR_AGAIN)  
  19.             return TRUE;  
  20.         delete_channel(chan);  
  21.         return FALSE;  
  22.     }  
  23.   
  24.     type = *ptr++;  
  25.   
  26.     if (type != HCI_EVENT_PKT)  
  27.         return TRUE;  
  28.   
  29.     eh = (hci_event_hdr *) ptr;  
  30.     ptr += HCI_EVENT_HDR_SIZE;  
  31.   
  32.     dev = g_io_channel_unix_get_fd(chan);  
  33.   
  34.     ioctl(dev, HCIGETDEVINFO, (void *) di);  
  35.   
  36.     if (hci_test_bit(HCI_RAW, &di->flags))  
  37.         return TRUE;  
  38.   
  39.     hci_cmd_print(eh->evt);  
  40.   
  41.     switch (eh->evt) {  
  42.     case EVT_CMD_STATUS://命令状态  
  43.         cmd_status(dev, &di->bdaddr, ptr);  
  44.         break;  
  45.   
  46.     case EVT_CMD_COMPLETE://命令完成  
  47.         cmd_complete(dev, &di->bdaddr, ptr);  
  48.         break;  
  49.   
  50.     case EVT_REMOTE_NAME_REQ_COMPLETE://获取远程设备名  
  51.         remote_name_information(dev, &di->bdaddr, ptr);  
  52.         break;  
  53.   
  54.     case EVT_READ_REMOTE_VERSION_COMPLETE:  
  55.         remote_version_information(dev, &di->bdaddr, ptr);  
  56.         break;  
  57.   
  58.     case EVT_READ_REMOTE_FEATURES_COMPLETE://读取远程设备属性  
  59.         remote_features_information(dev, &di->bdaddr, ptr);  
  60.         break;  
  61.   
  62.     case EVT_REMOTE_HOST_FEATURES_NOTIFY:  
  63.         remote_features_notify(dev, &di->bdaddr, ptr);  
  64.         break;  
  65.   
  66.     case EVT_INQUIRY_COMPLETE:  
  67.         evt = (evt_cmd_status *) ptr;  
  68.         inquiry_complete(&di->bdaddr, evt->status, FALSE);  
  69.         break;  
  70.   
  71.     case EVT_INQUIRY_RESULT:  
  72.         inquiry_result(dev, &di->bdaddr, eh->plen, ptr);  
  73.         break;  
  74.   
  75.     case EVT_INQUIRY_RESULT_WITH_RSSI:  
  76.         inquiry_result_with_rssi(dev, &di->bdaddr, eh->plen, ptr);  
  77.         break;  
  78.   
  79.     case EVT_EXTENDED_INQUIRY_RESULT:  
  80.         extended_inquiry_result(dev, &di->bdaddr, eh->plen, ptr);  
  81.         break;  
  82.   
  83.     case EVT_CONN_COMPLETE://连接完成  
  84.         conn_complete(dev, di->dev_id, &di->bdaddr, ptr);  
  85.         break;  
  86.   
  87.     case EVT_DISCONN_COMPLETE://断开连接  
  88.         disconn_complete(dev, &di->bdaddr, ptr);  
  89.         break;  
  90.   
  91.     case EVT_AUTH_COMPLETE:  
  92.         auth_complete(dev, &di->bdaddr, ptr);  
  93.         break;  
  94.   
  95.     case EVT_SIMPLE_PAIRING_COMPLETE:  
  96.         simple_pairing_complete(dev, &di->bdaddr, ptr);  
  97.         break;  
  98.   
  99.     case EVT_CONN_REQUEST://配对请求  
  100.         conn_request(dev, &di->bdaddr, ptr);  
  101.         break;  
  102.     }  
  103.   
  104.     /* Check for pending command request */  
  105.     check_pending_hci_req(di->dev_id, eh->evt);  
  106.     switch (eh->evt) {  
  107.     case EVT_PIN_CODE_REQ://PIN码请求  
  108.         pin_code_request(dev, &di->bdaddr, (bdaddr_t *) ptr);  
  109.         break;  
  110.   
  111.     case EVT_LINK_KEY_REQ:  
  112.         link_key_request(dev, &di->bdaddr, (bdaddr_t *) ptr);  
  113.         break;  
  114.   
  115.     case EVT_LINK_KEY_NOTIFY://linkkey通知  
  116.         link_key_notify(dev, &di->bdaddr, ptr);  
  117.         break;  
  118.   
  119.     case EVT_RETURN_LINK_KEYS:  
  120.         return_link_keys(dev, &di->bdaddr, ptr);  
  121.         break;  
  122.   
  123.     case EVT_IO_CAPABILITY_REQUEST:  
  124.         io_capa_request(dev, &di->bdaddr, (bdaddr_t *) ptr);  
  125.         break;  
  126.   
  127.     case EVT_IO_CAPABILITY_RESPONSE:  
  128.         io_capa_response(dev, &di->bdaddr, ptr);  
  129.         break;  
  130.   
  131.     case EVT_USER_CONFIRM_REQUEST:  
  132.         user_confirm_request(dev, &di->bdaddr, ptr);  
  133.         break;  
  134.   
  135.     case EVT_USER_PASSKEY_REQUEST:  
  136.         user_passkey_request(dev, &di->bdaddr, ptr);  
  137.         break;  
  138.   
  139.     case EVT_USER_PASSKEY_NOTIFY:  
  140.         user_passkey_notify(dev, &di->bdaddr, ptr);  
  141.         break;  
  142.   
  143.     case EVT_REMOTE_OOB_DATA_REQUEST:  
  144.         remote_oob_data_request(dev, &di->bdaddr, ptr);  
  145.         break;  
  146.     }  
  147.   
  148.     return TRUE;  
  149. }  
static gboolean io_security_event(GIOChannel *chan, GIOCondition cond,
								gpointer data)
{
	unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr = buf;
	struct hci_dev_info *di = data;
	int type, dev;
	size_t len;
	hci_event_hdr *eh;
	GIOError err;
	evt_cmd_status *evt;

	if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
		delete_channel(chan);
		return FALSE;
	}

	if ((err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len))) {
		if (err == G_IO_ERROR_AGAIN)
			return TRUE;
		delete_channel(chan);
		return FALSE;
	}

	type = *ptr++;

	if (type != HCI_EVENT_PKT)
		return TRUE;

	eh = (hci_event_hdr *) ptr;
	ptr += HCI_EVENT_HDR_SIZE;

	dev = g_io_channel_unix_get_fd(chan);

	ioctl(dev, HCIGETDEVINFO, (void *) di);

	if (hci_test_bit(HCI_RAW, &di->flags))
		return TRUE;

	hci_cmd_print(eh->evt);

	switch (eh->evt) {
	case EVT_CMD_STATUS://命令状态
		cmd_status(dev, &di->bdaddr, ptr);
		break;

	case EVT_CMD_COMPLETE://命令完成
		cmd_complete(dev, &di->bdaddr, ptr);
		break;

	case EVT_REMOTE_NAME_REQ_COMPLETE://获取远程设备名
		remote_name_information(dev, &di->bdaddr, ptr);
		break;

	case EVT_READ_REMOTE_VERSION_COMPLETE:
		remote_version_information(dev, &di->bdaddr, ptr);
		break;

	case EVT_READ_REMOTE_FEATURES_COMPLETE://读取远程设备属性
		remote_features_information(dev, &di->bdaddr, ptr);
		break;

	case EVT_REMOTE_HOST_FEATURES_NOTIFY:
		remote_features_notify(dev, &di->bdaddr, ptr);
		break;

	case EVT_INQUIRY_COMPLETE:
		evt = (evt_cmd_status *) ptr;
		inquiry_complete(&di->bdaddr, evt->status, FALSE);
		break;

	case EVT_INQUIRY_RESULT:
		inquiry_result(dev, &di->bdaddr, eh->plen, ptr);
		break;

	case EVT_INQUIRY_RESULT_WITH_RSSI:
		inquiry_result_with_rssi(dev, &di->bdaddr, eh->plen, ptr);
		break;

	case EVT_EXTENDED_INQUIRY_RESULT:
		extended_inquiry_result(dev, &di->bdaddr, eh->plen, ptr);
		break;

	case EVT_CONN_COMPLETE://连接完成
		conn_complete(dev, di->dev_id, &di->bdaddr, ptr);
		break;

	case EVT_DISCONN_COMPLETE://断开连接
		disconn_complete(dev, &di->bdaddr, ptr);
		break;

	case EVT_AUTH_COMPLETE:
		auth_complete(dev, &di->bdaddr, ptr);
		break;

	case EVT_SIMPLE_PAIRING_COMPLETE:
		simple_pairing_complete(dev, &di->bdaddr, ptr);
		break;

	case EVT_CONN_REQUEST://配对请求
		conn_request(dev, &di->bdaddr, ptr);
		break;
	}

	/* Check for pending command request */
	check_pending_hci_req(di->dev_id, eh->evt);
	switch (eh->evt) {
	case EVT_PIN_CODE_REQ://PIN码请求
		pin_code_request(dev, &di->bdaddr, (bdaddr_t *) ptr);
		break;

	case EVT_LINK_KEY_REQ:
		link_key_request(dev, &di->bdaddr, (bdaddr_t *) ptr);
		break;

	case EVT_LINK_KEY_NOTIFY://linkkey通知
		link_key_notify(dev, &di->bdaddr, ptr);
		break;

	case EVT_RETURN_LINK_KEYS:
		return_link_keys(dev, &di->bdaddr, ptr);
		break;

	case EVT_IO_CAPABILITY_REQUEST:
		io_capa_request(dev, &di->bdaddr, (bdaddr_t *) ptr);
		break;

	case EVT_IO_CAPABILITY_RESPONSE:
		io_capa_response(dev, &di->bdaddr, ptr);
		break;

	case EVT_USER_CONFIRM_REQUEST:
		user_confirm_request(dev, &di->bdaddr, ptr);
		break;

	case EVT_USER_PASSKEY_REQUEST:
		user_passkey_request(dev, &di->bdaddr, ptr);
		break;

	case EVT_USER_PASSKEY_NOTIFY:
		user_passkey_notify(dev, &di->bdaddr, ptr);
		break;

	case EVT_REMOTE_OOB_DATA_REQUEST:
		remote_oob_data_request(dev, &di->bdaddr, ptr);
		break;
	}

	return TRUE;
}

这个函数接收到远程设备发送过来的socket数据,然后解析出cmd,并执行对应的操作。在这里,用9510和PC配对,PC收到如下消息:

手机端输入PIN码前:

EVT_CONN_REQUEST
EVT_CMD_STATUS
EVT_PIN_CODE_REQ
bluetoothd[2395]: pin_code_request (sba=00:1C:26:FB:26:DC, dba=36:15:00:EF:80:6E)
手机端输入PIN码后:
EVT_CMD_COMPLETE
EVT_LINK_KEY_NOTIFY
bluetoothd[2395]: link_key_notify (sba=00:1C:26:FB:26:DC, dba=36:15:00:EF:80:6E, type=0)
EVT_CONN_COMPLETE
EVT_CMD_STATUS
EVT_READ_REMOTE_FEATURES_COMPLETE
EVT_CMD_STATUS
EVT_REMOTE_NAME_REQ_COMPLETE
EVT_CMD_STATUS
EVT_REMOTE_NAME_REQ_COMPLETE
EVT_CMD_STATUS
EVT_DISCONN_COMPLETE

下面看以下各个CMD是啥意思。


EVT_CONN_REQUEST:

  1. static inline void conn_request(int dev, bdaddr_t *sba, void *ptr)  
  2. {  
  3.     evt_conn_request *evt = ptr;  
  4.     uint32_t class = evt->dev_class[0] | (evt->dev_class[1] << 8)  
  5.                 | (evt->dev_class[2] << 16);  
  6.   
  7.     hcid_dbus_remote_class(sba, &evt->bdaddr, class);//从本地/var/lib/buetooth/bdaddr/classes文件中读取来配对地址的class值,如果有变化,dbus通知  
  8.   
  9.     write_remote_class(sba, &evt->bdaddr, class);//将class写入/var/lib/buetooth/bdaddr/classes文件  
  10. }  
static inline void conn_request(int dev, bdaddr_t *sba, void *ptr)
{
	evt_conn_request *evt = ptr;
	uint32_t class = evt->dev_class[0] | (evt->dev_class[1] << 8)
				| (evt->dev_class[2] << 16);

	hcid_dbus_remote_class(sba, &evt->bdaddr, class);//从本地/var/lib/buetooth/bdaddr/classes文件中读取来配对地址的class值,如果有变化,dbus通知

	write_remote_class(sba, &evt->bdaddr, class);//将class写入/var/lib/buetooth/bdaddr/classes文件
}



EVT_CMD_STATUS:

  1. static inline void cmd_status(int dev, bdaddr_t *sba, void *ptr)  
  2. {  
  3.     evt_cmd_status *evt = ptr;  
  4.     uint16_t opcode = btohs(evt->opcode);  
  5.   
  6.     if (opcode == cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY))  
  7.         start_inquiry(sba, evt->status, FALSE);  
  8. }  
static inline void cmd_status(int dev, bdaddr_t *sba, void *ptr)
{
	evt_cmd_status *evt = ptr;
	uint16_t opcode = btohs(evt->opcode);

	if (opcode == cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY))
		start_inquiry(sba, evt->status, FALSE);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值