Android源碼分析]hciops的初始化

凡是真正分析過bluez代碼或者debug過相關bug的童鞋,一定對hciops非常熟悉吧,是的,它是各個event的處理中心,承接著controller到上層host的各個方面的交互,本文就來詳細分析一下它的初始化過程。

 

2.3.5.2 add_plugin分析

 

add_plugin隻是單純地把plugin加入到系統裡面,或者就是plugin的初始化,來看看吧

 

[cpp] 

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函數還是蠻簡單的,就是一句話:

 

[cpp] 

static int hciops_init(void)  

{  

    DBG("");  

    //這個我們比較熟悉,就是把hci_ops註冊進來唄  

    //這裡我們詳細分析一下,究竟做瞭些什麼  

    return btd_register_adapter_ops(&hci_ops, FALSE);  

}  

[cpp] 

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,我們來分析一下

 

[cpp] 

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中定義的,我們去看一下:

 

[cpp] 

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的分析

 

[cpp]  

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;  

}  

 

發佈留言