Android源码分析–hciops的初始化

凡是真正分析过bluez代码或者debug过相关bug的童鞋,一定对hciops非常熟悉吧,是的,它是各个event的处理中心,承接着controller到上层host的各个方面的交互,本文就来详细分析一下它的初始化过程。

2.3.5.2 add_plugin分析

add_plugin只是单纯地把plugin加入到系统里面,或者就是plugin的初始化,来看看吧

[cpp][/cpp] view plaincopy

  1. static gboolean add_plugin(void *handle, struct bluetooth_plugin_desc *desc)
  2. {
  3.     struct bluetooth_plugin *plugin;
  4.     //检查是否有init函数,没有直接返回
  5.     if (desc->init == NULL)
  6.         return FALSE;
  7.     //检查一下version是不是匹配,那边初始化的时候就是用的VERSION,所以,没有问题
  8.     if (g_str_equal(desc->version, VERSION) == FALSE) {
  9.         error(“Version mismatch for %s”, desc->name);
  10.         return FALSE;
  11.     }
  12.     DBG(“Loading %s plugin”, desc->name);
  13.     //初始化bluetooth_plugin结构体
  14.     plugin = g_try_new0(struct bluetooth_plugin, 1);
  15.     if (plugin == NULL)
  16.         return FALSE;
  17.     plugin->handle = handle;
  18.     plugin->active = FALSE;
  19.     plugin->desc = desc;
  20.     //按照priority来加入到plugins list中
  21.     plugins = g_slist_insert_sorted(plugins, plugin, compare_priority);
  22.     return TRUE;
  23. }

2.3.5.3  hciops的init函数分析

初略一看,hciops的init函数还是蛮简单的,就是一句话:

[cpp][/cpp] view plaincopy

  1. static int hciops_init(void)
  2. {
  3.     DBG(“”);
  4.     //这个我们比较熟悉,就是把hci_ops注册进来呗
  5.     //这里我们详细分析一下,究竟做了些什么
  6.     return btd_register_adapter_ops(&hci_ops, FALSE);
  7. }
[cpp][/cpp] view plaincopy

  1. int btd_register_adapter_ops(struct btd_adapter_ops *ops, gboolean priority)
  2. {
  3.     //其实就是判断setup函数是否存在,具体的带用会在后面的adapter_ops_setup中
  4.     if (ops->setup == NULL)
  5.         return -EINVAL;
  6.     //根据priority,决定吧ops加入到ops_candidates的头还是尾中,这个还是蛮简单的吧
  7.     if (priority)
  8.         ops_candidates = g_slist_prepend(ops_candidates, ops);
  9.     else
  10.         ops_candidates = g_slist_append(ops_candidates, ops);
  11.     return 0;
  12. }

2.3.6 adapter_ops_setup的分析

其实这个函数很简单,就是setuphciops,我们来分析一下

[cpp][/cpp] view plaincopy

  1. int adapter_ops_setup(void)
  2. {
  3.     GSList *l;
  4.     int ret;
  5.     //ops_candidates是在hciops的init函数中加入的
  6.     if (!ops_candidates)
  7.         return -EINVAL;
  8.     //这里也没有别的,就只有hciops,调用他的setup即可
  9.     for (l = ops_candidates; l != NULL; l = g_slist_next(l)) {
  10.         struct btd_adapter_ops *ops = l->data;
  11.         //Setup见下面的分析
  12.         ret = ops->setup();
  13.         if (ret < 0)
  14.             continue;
  15.         //同时需要把这个ops和adapter_ops相关联
  16.         adapter_ops = ops;
  17.         break;
  18.     }
  19.     return ret;
  20. }

hciops的setup函数也是在对应的ops中定义的,我们去看一下:

[cpp][/cpp] view plaincopy

  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.     DBG(“”);
  8.     //先判断一下有没有pipe过
  9.     if (child_pipe[0] != -1)
  10.         return -EALREADY;
  11.     //创建一个管道,child_pipe[0]为读入端,child_pipe[1]为写入端
  12.     if (pipe(child_pipe) < 0) {
  13.         err = -errno;
  14.         error(“pipe(): %s (%d)”, strerror(-err), -err);
  15.         return err;
  16.     }
  17. //一个io channel进行监听,若是有数据,就会去读了
  18.     child_io = g_io_channel_unix_new(child_pipe[0]);
  19.     g_io_channel_set_close_on_unref(child_io, TRUE);
  20.     child_io_id = g_io_add_watch(child_io,
  21.                 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
  22.                 child_exit, NULL);
  23.     g_io_channel_unref(child_io);
  24.     //创建并且bind hci socket
  25.     /* Create and bind HCI socket */
  26.     sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
  27.     if (sock < 0) {
  28.         err = -errno;
  29.         error(“Can’t open HCI socket: %s (%d)”, strerror(-err),
  30.                                 -err);
  31.         return err;
  32.     }
  33.     /* Set filter */
  34.     //这里只关注bluez stack的internal的event,这个就是DEV_REG,DEV_UP之类的event的处理了
  35.     hci_filter_clear(&flt);
  36.     hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
  37.     hci_filter_set_event(EVT_STACK_INTERNAL, &flt);
  38.     if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
  39.         err = -errno;
  40.         error(“Can’t set filter: %s (%d)”, strerror(-err), -err);
  41.         return err;
  42.     }
  43.     memset(&addr, 0, sizeof(addr));
  44.     addr.hci_family = AF_BLUETOOTH;
  45.     addr.hci_dev = HCI_DEV_NONE;
  46.     //bind
  47.     if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  48.         err = -errno;
  49.         error(“Can’t bind HCI socket: %s (%d)”, strerror(-err), -err);
  50.         return err;
  51.     }
  52.     //再建一个io channel来监听它
  53.     ctl_io = g_io_channel_unix_new(sock);
  54.     g_io_channel_set_close_on_unref(ctl_io, TRUE);
  55.     //回调函数是io stack event,等用到的时候再具体分析好了,详细分析见2.3
  56.     ctl_io_id = g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL);
  57.     g_io_channel_unref(ctl_io);
  58.     //这里设置了一个空闲任务,就是空闲的时候,我们会执行init_known_adapters函数,从这里可以看出这个函数的优先级必然不高,但是他仍然会执行,所以,我们可以去看一下
  59.     g_idle_add(init_known_adapters, GINT_TO_POINTER(sock));
  60.     return 0;
  61. }

空闲的时候执行函数:init_known_adapters的分析

[cpp][/cpp] view plaincopy

  1. static gboolean init_known_adapters(gpointer user_data)
  2. {
  3.     struct hci_dev_list_req *dl;
  4.     struct hci_dev_req *dr;
  5.     int i, err, ctl = GPOINTER_TO_INT(user_data);
  6.     size_t req_size;
  7.     DBG(“”);
  8.     req_size = HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t);
  9.     //申请devcie list空间
  10.     dl = g_try_malloc0(req_size);
  11.     if (!dl) {
  12.         error(“Can’t allocate devlist buffer”);
  13.         return FALSE;
  14.     }
  15.     //最多16个设备
  16.     dl->dev_num = HCI_MAX_DEV;
  17.     dr = dl->dev_req;
  18.     //通过ioctl得到device 的列表
  19.     if (ioctl(ctl, HCIGETDEVLIST, dl) < 0) {
  20.         err = -errno;
  21.         error(“Can’t get device list: %s (%d)”, strerror(-err), -err);
  22.         g_free(dl);
  23.         return FALSE;
  24.     }
  25.     for (i = 0; i < dl->dev_num; i++, dr++) {
  26.         struct dev_info *dev;
  27.         gboolean already_up;
  28.     //这里检查是否up,bluetootd初始化的时候应该已经up了
  29.         already_up = hci_test_bit(HCI_UP, &dr->dev_opt);
  30.     //初始化device,这个在2.3.1中进行详细分析
  31.         dev = init_device(dr->dev_id, already_up);
  32.         if (dev == NULL)
  33.             continue;
  34.         if (!dev->already_up)
  35.             continue;
  36.         init_conn_list(dr->dev_id);
  37.         dev->pending = 0;
  38.     //设置pending version位
  39.         hci_set_bit(PENDING_VERSION, &dev->pending);
  40.     //发送read local version的cmd
  41.         hci_send_cmd(dev->sk, OGF_INFO_PARAM,
  42.                     OCF_READ_LOCAL_VERSION, 0, NULL);
  43.     //同时发送HCI_DEV_UP的event,这个在2.3.2中分析
  44.         device_event(HCI_DEV_UP, dr->dev_id);
  45.     }
  46.     g_free(dl);
  47.     return FALSE;
  48. }

标签