凡是真正分析过bluez代码或者debug过相关bug的童鞋,一定对hciops非常熟悉吧,是的,它是各个event的处理中心,承接着controller到上层host的各个方面的交互,本文就来详细分析一下它的初始化过程。
2.3.5.2 add_plugin分析
add_plugin只是单纯地把plugin加入到系统里面,或者就是plugin的初始化,来看看吧
static gboolean add_plugin(void *handle, struct bluetooth_plugin_desc *desc) { struct bluetooth_plugin *plugin; //检查是否有init函数,没有直接返回 if (desc->init == NULL) return FALSE; //检查一下version是不是匹配,那边初始化的时候就是用的VERSION,所以,没有问题 if (g_str_equal(desc->version, VERSION) == FALSE) { error("Version mismatch for %s", desc->name); return FALSE; } DBG("Loading %s plugin", desc->name); //初始化bluetooth_plugin结构体 plugin = g_try_new0(struct bluetooth_plugin, 1); if (plugin == NULL) return FALSE; plugin->handle = handle; plugin->active = FALSE; plugin->desc = desc; //按照priority来加入到plugins list中 plugins = g_slist_insert_sorted(plugins, plugin, compare_priority); return TRUE; }
2.3.5.3 hciops的init函数分析
初略一看,hciops的init函数还是蛮简单的,就是一句话:
static int hciops_init(void) { DBG(""); //这个我们比较熟悉,就是把hci_ops注册进来呗 //这里我们详细分析一下,究竟做了些什么 return btd_register_adapter_ops(&hci_ops, FALSE); }
int btd_register_adapter_ops(struct btd_adapter_ops *ops, gboolean priority) { //其实就是判断setup函数是否存在,具体的带用会在后面的adapter_ops_setup中 if (ops->setup == NULL) return -EINVAL; //根据priority,决定吧ops加入到ops_candidates的头还是尾中,这个还是蛮简单的吧 if (priority) ops_candidates = g_slist_prepend(ops_candidates, ops); else ops_candidates = g_slist_append(ops_candidates, ops); return 0; }
2.3.6 adapter_ops_setup的分析
其实这个函数很简单,就是setuphciops,我们来分析一下
int adapter_ops_setup(void) { GSList *l; int ret; //ops_candidates是在hciops的init函数中加入的 if (!ops_candidates) return -EINVAL; //这里也没有别的,就只有hciops,调用他的setup即可 for (l = ops_candidates; l != NULL; l = g_slist_next(l)) { struct btd_adapter_ops *ops = l->data; //Setup见下面的分析 ret = ops->setup(); if (ret < 0) continue; //同时需要把这个ops和adapter_ops相关联 adapter_ops = ops; break; } return ret; }
hciops的setup函数也是在对应的ops中定义的,我们去看一下:
static int hciops_setup(void) { struct sockaddr_hci addr; struct hci_filter flt; GIOChannel *ctl_io, *child_io; int sock, err; DBG(""); //先判断一下有没有pipe过 if (child_pipe[0] != -1) return -EALREADY; //创建一个管道,child_pipe[0]为读入端,child_pipe[1]为写入端 if (pipe(child_pipe) < 0) { err = -errno; error("pipe(): %s (%d)", strerror(-err), -err); return err; } //一个io channel进行监听,若是有数据,就会去读了 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); //创建并且bind hci socket /* 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 */ //这里只关注bluez stack的internal的event,这个就是DEV_REG,DEV_UP之类的event的处理了 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; //bind if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { err = -errno; error("Can't bind HCI socket: %s (%d)", strerror(-err), -err); return err; } //再建一个io channel来监听它 ctl_io = g_io_channel_unix_new(sock); g_io_channel_set_close_on_unref(ctl_io, TRUE); //回调函数是io stack event,等用到的时候再具体分析好了,详细分析见2.3 ctl_io_id = g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL); g_io_channel_unref(ctl_io); //这里设置了一个空闲任务,就是空闲的时候,我们会执行init_known_adapters函数,从这里可以看出这个函数的优先级必然不高,但是他仍然会执行,所以,我们可以去看一下 g_idle_add(init_known_adapters, GINT_TO_POINTER(sock)); return 0; }
空闲的时候执行函数:init_known_adapters的分析
static gboolean init_known_adapters(gpointer user_data) { struct hci_dev_list_req *dl; struct hci_dev_req *dr; int i, err, ctl = GPOINTER_TO_INT(user_data); size_t req_size; DBG(""); req_size = HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t); //申请devcie list空间 dl = g_try_malloc0(req_size); if (!dl) { error("Can't allocate devlist buffer"); return FALSE; } //最多16个设备 dl->dev_num = HCI_MAX_DEV; dr = dl->dev_req; //通过ioctl得到device 的列表 if (ioctl(ctl, HCIGETDEVLIST, dl) < 0) { err = -errno; error("Can't get device list: %s (%d)", strerror(-err), -err); g_free(dl); return FALSE; } for (i = 0; i < dl->dev_num; i++, dr++) { struct dev_info *dev; gboolean already_up; //这里检查是否up,bluetootd初始化的时候应该已经up了 already_up = hci_test_bit(HCI_UP, &dr->dev_opt); //初始化device,这个在2.3.1中进行详细分析 dev = init_device(dr->dev_id, already_up); if (dev == NULL) continue; if (!dev->already_up) continue; init_conn_list(dr->dev_id); dev->pending = 0; //设置pending version位 hci_set_bit(PENDING_VERSION, &dev->pending); //发送read local version的cmd hci_send_cmd(dev->sk, OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION, 0, NULL); //同时发送HCI_DEV_UP的event,这个在2.3.2中分析 device_event(HCI_DEV_UP, dr->dev_id); } g_free(dl); return FALSE; }
若您觉得该文章对您有帮助,请在下面用鼠标轻轻按一下“顶”,哈哈~~·