Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android源碼分析]bluez internal event的處理

[Android源碼分析]bluez internal event的處理

編輯:關於Android編程

在上面2.1中是hci dev的注冊和up,2.3中有bluez的初始化,這兩者是有一個交集的,那就是說bluez初始化後會監聽hci dev的一些event,主要有HCI_DEV_REG和HCI_DEV_UP兩個比較重要,那本集就是主要分析這兩個event帶來的影響。            從上面的分析中,我們已經知道,這兩個event的處理函數是io_stack_event:   [cpp]   static gboolean io_stack_event(GIOChannel *chan, GIOCondition cond,                                   gpointer data)   {       unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr;       evt_stack_internal *si;       evt_si_device *sd;       hci_event_hdr *eh;       int type, fd;       ssize_t len;          ptr = buf;          fd = g_io_channel_unix_get_fd(chan);       //讀取event的內容       len = read(fd, buf, sizeof(buf));       if (len < 0) {           if (errno == EAGAIN)               return TRUE;              error("Read from control socket failed: %s (%d)",                           strerror(errno), errno);           return FALSE;       }          type = *ptr++;          if (type != HCI_EVENT_PKT)           return TRUE;          eh = (hci_event_hdr *) ptr;   //判斷是否是internal的event       if (eh->evt != EVT_STACK_INTERNAL)           return TRUE;          ptr += HCI_EVENT_HDR_SIZE;          si = (evt_stack_internal *) ptr;       switch (si->type) {       case EVT_SI_DEVICE:           sd = (void *) &si->data;       //event的處理           device_event(sd->event, sd->dev_id);           break;       }          return TRUE;   }   static void device_event(int event, int index)   {       switch (event) {       //device register後的操作,詳細見2.4.1       case HCI_DEV_REG:           info("HCI dev %d registered", index);           init_device(index, FALSE);           break;       //unreg,不做詳細分析       case HCI_DEV_UNREG:           info("HCI dev %d unregistered", index);           stop_hci_dev(index);           if (devs[index].registered)               btd_manager_unregister_adapter(index);           break;       //device up的操作,詳細分析見2.4.2       case HCI_DEV_UP:           info("HCI dev %d up", index);           devs[index].up = TRUE;           device_devup_setup(index);           break;       //Down的操作       case HCI_DEV_DOWN:           info("HCI dev %d down", index);           devs[index].up = FALSE;           devs[index].pending_cod = 0;           devs[index].cache_enable = TRUE;           if (!devs[index].pending) {               struct btd_adapter *adapter;                  adapter = manager_find_adapter_by_id(index);               if (adapter)                   btd_adapter_stop(adapter);                  init_pending(index);           }           break;       }   }         2.4.1 device register後的bluez的操作分析            這個函數是bluez收到底層hci dev registe的消息之後的操作。事實上,因為init_known_adapters的存在,這裡可能都沒有走到。不過,在上面init_known_adapters中我們也沒有分析這個函數,這裡我們分析一下吧,反正這個函數終歸是要走的。   [cpp]   static struct dev_info *init_device(int index, gboolean already_up)   {       struct dev_info *dev;       struct hci_dev_req dr;       int dd;       pid_t pid;          DBG("hci%d", index);       //open hci device       //其實就是建一個hci對應的socket,並bind,返回的dd就是socket的句柄       dd = hci_open_dev(index);       if (dd < 0) {           error("Unable to open hci%d: %s (%d)", index,                           strerror(errno), errno);           return NULL;       }       //max_dev默認為0,申請對應的空間       if (index > max_dev) {           max_dev = index;           devs = g_realloc(devs, sizeof(devs[0]) * (max_dev + 1));       }       //初始化devcie的info,見2.4.1.1       dev = init_dev_info(index, dd, FALSE, already_up);       //設置device的pending位,把dev->pending的bdaddr,version,features和name都置位       init_pending(index);       //開始hci device,這裡會對一系列的event進行監聽,具體見2.4.1.2       start_hci_dev(index);       //已經up了,就不需要做什麼了   /* Avoid forking if nothing else has to be done */       if (already_up)           return dev;          /* Do initialization in the separate process */   //fork一個進程出來繼續,子進程繼續下去,父進程這裡直接返回device       pid = fork();       switch (pid) {           case 0:           //注冊一個子進程退出時調用的函數               atexit(at_child_exit);               break;           //fork出錯,直接返回device,注意這裡沒有break           case -1:               error("Fork failed. Can't init device hci%d: %s (%d)",                       index, strerror(errno), errno);           default:           //父進程直接返回device               DBG("child %d forked", pid);               return dev;       }       memset(&dr, 0, sizeof(dr));       dr.dev_id = index;   //根據配置的link mode來進行設置,默認的link policy(7)是不支持park的,支持sniff,roleswitch和hold       /* Set link mode */       dr.dev_opt = main_opts.link_mode;       if (ioctl(dd, HCISETLINKMODE, (unsigned long) &dr) < 0)           error("Can't set link mode on hci%d: %s (%d)",                           index, strerror(errno), errno);       //這裡會再次up,其實之前在bluetoothd啟動之前的enable_native中已經up過了,所以這裡應該沒有什麼了       /* Start HCI device */       if (ioctl(dd, HCIDEVUP, index) < 0 && errno != EALREADY) {           error("Can't init device hci%d: %s (%d)",                       index, strerror(errno), errno);           goto fail;       }          hci_close_dev(dd);       exit(0);      fail:       hci_close_dev(dd);       exit(1);   }         至此,device register在bluez和kernel中的所有操作就都完成了。       2.4.1.1 device info的初始化   [cpp]            static struct dev_info *init_dev_info(int index, int sk, gboolean registered,                                                                       gboolean already_up)      {               struct dev_info *dev = &devs[index];               //初始化wie0               memset(dev, 0, sizeof(*dev));                      dev->id = index; //id就是0,就是hci0               dev->sk = sk;    //和剛剛建立的socket綁定               dev->cache_enable = TRUE;    //cache enable置位true               dev->registered = registered; //registered為false               dev->already_up = already_up;       //already up是傳入的值,這裡理論上應該是false               dev->io_capability = 0x03; /* No Input No Output */ //no input no output               dev->discov_state = DISCOV_HALTED; //初始化discovery的state為DISCOV_HALTED,這個狀態的轉變我們在inquiry的時候再詳細分析                      return dev;      }         2.4.1.2  hci device的start            這個函數說白了就是對一系列的event進行監聽,這也是我們後期能夠對event處理的關鍵前提所在。       [cpp]   static void start_hci_dev(int index)   {       struct dev_info *dev = &devs[index];       GIOChannel *chan = dev->io;       GIOCondition cond;       struct hci_filter flt;          if (chan)           return;          info("Listening for HCI events on hci%d", index);       //對下面一系列的event進行處理       /* 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);       hci_filter_set_event(EVT_LE_META_EVENT, &flt);       if (setsockopt(dev->sk, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {           error("Can't set filter on hci%d: %s (%d)",                           index, strerror(errno), errno);           return;       }       //處理的函數是io_security_event。所以,後期的一系列event上來之後,我們在這裡還需要進行一次處理,其實上文中的up過程中的event,是不需要再走這邊的,因為在up的時候bluetoothd還沒有啟動,這裡肯定是還沒有注冊了       chan = g_io_channel_unix_new(dev->sk);       cond = G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR;       dev->watch_id = g_io_add_watch_full(chan, G_PRIORITY_LOW, cond,                           io_security_event,                           GINT_TO_POINTER(index), NULL);       dev->io = chan;       dev->pin_length = 0;      }         2.4.2 device up後的bluez的操作分析            這個函數device up之後bluez的需要進行的各種操作。   [cpp]   static void device_devup_setup(int index)   {       struct dev_info *dev = &devs[index];       struct hci_dev_info di;       read_stored_link_key_cp cp;          DBG("hci%d", index);       //得到kernel中的device info,並初始化到di中       if (hci_devinfo(index, &di) < 0)           return;       //檢查是否是bredr或者device_raw被置位       if (ignore_device(&di))           return;       //拷貝kernel中的bdaddr和features       bacpy(&dev->bdaddr, &di.bdaddr);       memcpy(dev->features, di.features, 8);          /* Set page timeout */       if ((main_opts.flags & (1 << HCID_SET_PAGETO))) {           write_page_timeout_cp cp;              cp.timeout = htobs(main_opts.pageto);           //這裡會發送write page timeout的cmd,所以,我們要修改page timeout,就可以通過修改main_opts.pageto來實現,他是可以通過main.conf修改來得到的           hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_PAGE_TIMEOUT,                       WRITE_PAGE_TIMEOUT_CP_SIZE, &cp);       }       bacpy(&cp.bdaddr, BDADDR_ANY);       cp.read_all = 1;       //發送read stored link key的cmd       hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_READ_STORED_LINK_KEY,                       READ_STORED_LINK_KEY_CP_SIZE, &cp);       //若是沒有pending的內容,就init_adapter了。       //我們從上面的分析中知道,這裡是有一個pending version的,所以這裡先不急,我們來分析一下上面共3個cmd,他們的response所帶來的影響。分別是read local version information和write page timeout以及read stored link key。       if (!dev->pending)           init_adapter(index);   }         2.4.2.1 read local version information的response的影響。            kernel中這個event的影響我們已經分析,不再累述。我們只分析bluez這裡的處理:   他的處理在io_security_event中的command complete中有分析:   [cpp]   case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION):           ptr += sizeof(evt_cmd_complete);           read_local_version_complete(index, ptr);           break;   所以就是read_local_version_complete這個函數了:   [cpp]  static void read_local_version_complete(int index,                   const read_local_version_rp *rp)   {       struct dev_info *dev = &devs[index];          if (rp->status)           return;       //得到device的一些信息       dev->ver.manufacturer = btohs(bt_get_unaligned(&rp->manufacturer));       dev->ver.hci_ver = rp->hci_ver;       dev->ver.hci_rev = btohs(bt_get_unaligned(&rp->hci_rev));       dev->ver.lmp_ver = rp->lmp_ver;       dev->ver.lmp_subver = btohs(bt_get_unaligned(&rp->lmp_subver));       //若是沒有設置pending位,則直接return       if (!dev->pending)           return;       //否則,就把pending version的位清空       hci_clear_bit(PENDING_VERSION, &dev->pending);          DBG("Got version for hci%d", index);       //沒有其他pending了,且up了,就需要init adapter了,所以,我們終歸是要走到init_adapter的。所以這個函數的分析見2.3.2.4       if (!dev->pending && dev->up)           init_adapter(index);   }         2.4.2.2 write page timeout的response的分析            依然是command complete,我們會發現,其實我們什麼都沒有做。包括kernel中也沒有做。   2.4.2.3 read stored link key的response的分析            這個和2.4.2.2是一樣的。所以什麼都沒有做。       2.4.2.4 init_adapter函數的分析            這個函數就是adapter的初始化了   [cpp]   static gboolean init_adapter(int index)   {   //得到對應device的info       struct dev_info *dev = &devs[index];       struct btd_adapter *adapter = NULL;       gboolean existing_adapter = dev->registered;       uint8_t mode, on_mode;       gboolean pairable, discoverable;       //從上面我們知道dev->registered是false,所以會走if中的resister,就是還沒有注冊過,就先register,否則就是find,意味著已經注冊過了       if (!dev->registered) {           //見下面的2.4.2.4.1           adapter = btd_manager_register_adapter(index);           if (adapter)               dev->registered = TRUE;       } else {           adapter = manager_find_adapter(&dev->bdaddr);           /* FIXME: manager_find_adapter should return a new ref */           btd_adapter_ref(adapter);       }       //沒有創建成功,就直接return false了       if (adapter == NULL)           return FALSE;       //設置mode,on_mode以及pairable的值,見2.4.2.4.2       btd_adapter_get_mode(adapter, &mode, &on_mode, &pairable);   //這個地方是false,所以不會進這個if       if (existing_adapter)           mode = on_mode;   //不是mode off,所以,不會進       if (mode == MODE_OFF) {           hciops_power_off(index);           goto done;       }       //這個就是通過一系列的cmd來啟動adapter了,詳細見2.4.2.4.3       start_adapter(index);       //繼續start adapter,詳細分析2.4.2.4.4       btd_adapter_start(adapter);       //因為我們這裡目前的mode是connectable,所以,discoverable是0       discoverable = (mode == MODE_DISCOVERABLE);       //write scan enable,然後mode是scan_page就是2       hciops_set_discoverable(index, discoverable);       //設置pairable的值       hciops_set_pairable(index, pairable);       //這裡就是發送inquiry cancel的command       if (dev->already_up)           hciops_stop_inquiry(index);       //以上一共有兩個cmd,分別是write scan enable,inquiry cancel。這兩個cmd的event的分析見2.4.2.4.5   done:       btd_adapter_unref(adapter);       return TRUE;  
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved