bluetoothd运行时(main函数启动时),加载plugin(调用plugin_init函数):
- 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;
- }
- 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
- };
- #define BLUETOOTH_PLUGIN_DEFINE(name, version, priority, init, exit) \
- struct bluetooth_plugin_desc __bluetooth_builtin_ ## name = { \
- #name, version, priority, init, exit \
- };
- static int hciops_init(void)
- {
- info("hciops_init\n");
- return btd_register_adapter_ops(&hci_ops);
- }
- 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;
- }
- 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,
- };
- int adapter_ops_setup(void)
- {
- if (!adapter_ops)
- return -EINVAL;
- return adapter_ops->setup();
- }
- 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);
- }
- 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");
- <span style="color:#000000;">device_event(HCI_DEV_UP, dr->dev_id);</span>
- }
- }
- g_free(dl);
- return 0;
- }
- 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;
- <span style="color:#000000;background-color: rgb(255, 255, 255);"> case HCI_DEV_UP:
- info("HCI dev %d up", index);
- device_devup_setup(index);
- break;</span>
- case HCI_DEV_DOWN:
- info("HCI dev %d down", index);
- manager_stop_adapter(index);
- stop_security_manager(index);
- break;
- }
- }
启动HCI DEV设备:
- static void device_devup_setup(int index)
- {
- configure_device(index);
- <span style="color:#000000;">start_security_manager</span>(index);
- /* Return value 1 means ioctl(DEVDOWN) was performed */
- if (manager_start_adapter(index) == 1)
- stop_security_manager(index);
- }
- 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,
- <span style="color:#000000;">io_security_event</span>, 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数据)。接收消息函数:
- 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:
- 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:
- 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);
- }