本來只想分析一下hciops的初始化就不再管了,後來發現別的plugin的初始化在後面還是會有涉及,心中想,既然已經分析了這麼多,咋就索性都分析了算了,反正也不差這一點代碼,其它的plugin還有audio,input,network,health。我們只看兩個函數init或者setup。所以看起來應該會比較簡單一點。
2.3.7.1 audio的init分析
audio 這個插件的分析
[cpp]
static int audio_init(void)
{
GKeyFile *config;
gboolean enable_sco;
//得到系統的dbus
connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
if (connection == NULL)
return -EIO;
//得到audio.config文件
config = load_config_file(CONFIGDIR "/audio.conf");
//根據config來進行init
if (audio_manager_init(connection, config, &enable_sco) < 0)
goto failed;
//沒有使能sco,就直接return了,我們這裡的確沒有使能sco,所以,沒什麼好說的,直接return吧
if (!enable_sco)
return 0;
……
return -EIO;
}
1)audio.conf的內容簡介如下:
[plain]
[General]
Enable=Sink,Control
Disable=Headset,Gateway,Source
Master=false
FastConnectable=false
[A2DP]
SBCSources=1
MPEG12Sources=0
[AVRCP]
InputDeviceName=AVRCP
2)根據config來進行init
[cpp]
int audio_manager_init(DBusConnection *conn, GKeyFile *conf,
gboolean *enable_sco)
{
char **list;
int i;
gboolean b;
GError *err = NULL;
//dbus的connection的ref+1
connection = dbus_connection_ref(conn);
//沒有config文件,直接結束
if (!conf)
goto proceed;
//config是一個全局變量
config = conf;
/*
//從上面1)中可以得到
Enable=Sink,Control
Disable=Headset,Gateway,Source
*/
list = g_key_file_get_string_list(config, "General", "Enable",
NULL, NULL);
//enable的有哪些,加粗的就是enable的
for (i = 0; list && list[i] != NULL; i++) {
if (g_str_equal(list[i], "Headset"))
enabled.headset = TRUE;
else if (g_str_equal(list[i], "Gateway"))
enabled.gateway = TRUE;
else if (g_str_equal(list[i], "Sink"))
enabled.sink = TRUE;
else if (g_str_equal(list[i], "Source"))
enabled.source = TRUE;
else if (g_str_equal(list[i], "Control"))
enabled.control = TRUE;
else if (g_str_equal(list[i], "Socket"))
enabled.socket = TRUE;
else if (g_str_equal(list[i], "Media"))
enabled.media = TRUE;
}
g_strfreev(list);
//再看disable的,加粗的就是disable的
list = g_key_file_get_string_list(config, "General", "Disable",
NULL, NULL);
for (i = 0; list && list[i] != NULL; i++) {
if (g_str_equal(list[i], "Headset"))
enabled.headset = FALSE;
else if (g_str_equal(list[i], "Gateway"))
enabled.gateway = FALSE;
else if (g_str_equal(list[i], "Sink"))
enabled.sink = FALSE;
else if (g_str_equal(list[i], "Source"))
enabled.source = FALSE;
else if (g_str_equal(list[i], "Control"))
enabled.control = FALSE;
else if (g_str_equal(list[i], "Socket"))
enabled.socket = FALSE;
else if (g_str_equal(list[i], "Media"))
enabled.media = FALSE;
}
//除了上面這些設置,下面就還有幾個默認的
/*
//這裡是一些默認
//hsp是沒有的,hfp有的
static struct enabled_interfaces enabled = {
.hfp = TRUE,
.headset = TRUE,
.gateway = FALSE,
.sink = TRUE,
.source = FALSE,
.control = TRUE,
.socket = TRUE, //主要就是這個沒有配置了
.media = FALSE
};
*/
b = g_key_file_get_boolean(config, "General", "AutoConnect", &err);
if (err) { //沒有,所以就是not found,使用默認值,是true
DBG("audio.conf: %s", err->message);
g_clear_error(&err);
} else
auto_connect = b;
b = g_key_file_get_boolean(config, "Headset", "HFP",
&err);
if (err)
g_clear_error(&err);
else
enabled.hfp = b; //默認是true是支持的
err = NULL;
i = g_key_file_get_integer(config, "Headset", "MaxConnected",
&err);
if (err) {
DBG("audio.conf: %s", err->message);
g_clear_error(&err);
} else
max_connected_headsets = i; //沒有設置,默認是1
proceed:
//socket是肯定要的
if (enabled.socket)
unix_init();
//media默認是false
if (enabled.media)
btd_register_adapter_driver(&media_server_driver);
//headset也是false
if (enabled.headset)
btd_register_adapter_driver(&headset_server_driver);
//gateway也是flase的
if (enabled.gateway)
btd_register_adapter_driver(&gateway_server_driver);
//這兩個是enable的,把對應的driver加入到adapter_drivers列表中,並調用driver的probe函數,同時把這個driver加入到adapter->loaded_drivers列表中。然而這些有一個前提就是adapter需要up,若是沒有也是不會做的,後面自然會有分析他們的地方,我們到時再繼續分析。
if (enabled.source || enabled.sink)
btd_register_adapter_driver(&a2dp_server_driver);
//control也是enable的
if (enabled.control)
btd_register_adapter_driver(&avrcp_server_driver);
//audio也是enable的,不過這是一個device driver
btd_register_device_driver(&audio_driver);
//這裡是false,sco是沒有enable的
*enable_sco = (enabled.gateway || enabled.headset);
return 0;
}
所以,這裡一共是3個driver注冊了。
3)unix_init分析
[cpp]
//這裡其實是新建一個本地的socket,作為server端,後期會有client可以通過這裡進行交互和通信。
int unix_init(void)
{
GIOChannel *io;
struct sockaddr_un addr = {
AF_UNIX, BT_IPC_SOCKET_NAME
};
int sk, err;
//新建一個stram的socket
sk = socket(PF_LOCAL, SOCK_STREAM, 0);
if (sk < 0) {
err = errno;
error("Can't create unix socket: %s (%d)", strerror(err), err);
return -err;
}
//和這個地址綁定在一起
if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
error("Can't bind unix socket: %s (%d)", strerror(errno),
errno);
close(sk);
return -1;
}
//設置為non block
set_nonblocking(sk);
//最大連接數為1
if (listen(sk, 1) < 0) {
error("Can't listen on unix socket: %s (%d)",
strerror(errno), errno);
close(sk);
return -1;
}
unix_sock = sk;
//這邊加一個io的watch,有了數據後就會去調用accept
io = g_io_channel_unix_new(sk);
//server_cb中會accept
g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
server_cb, NULL);
g_io_channel_unref(io);
DBG("Unix socket created: %d", sk);
return 0;
}
2.3.7.2 input的init函數分析
input 這個插件的初始化
[cpp]
static int input_init(void)
{
GKeyFile *config;
//老規矩,不多說
connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
if (connection == NULL)
return -EIO;
//加載input.conf,內容見1)
config = load_config_file(CONFIGDIR "/input.conf");
//根據config進行初始化
if (input_manager_init(connection, config) < 0) {
dbus_connection_unref(connection);
return -EIO;
}
if (config)
g_key_file_free(config);
return 0;
}
1)input.conf的內容
內容簡單的分析就如下:
[General]
別的什麼都沒有了,他其實能有的也就一個參數#IdleTimeout=30,這裡用的是默認值。
2)input_manager_init分析
[cpp]
int input_manager_init(DBusConnection *conn, GKeyFile *config)
{
GError *err = NULL;
//得到idle的timeout參數,沒有設置,就是默認值0
if (config) {
idle_timeout = g_key_file_get_integer(config, "General",
"IdleTimeout", &err);
if (err) {
DBG("input.conf: %s", err->message);
g_error_free(err);
}
}
//dbus的ref+1
connection = dbus_connection_ref(conn);
//初始化了input server,同樣因為adapter沒有up,所以沒有做對應的probe
btd_register_adapter_driver(&input_server_driver);
//注冊了兩個device driver
btd_register_device_driver(&input_hid_driver);
btd_register_device_driver(&input_headset_driver);
return 0;
}
2.3.7.3 network的init函數分析
[cpp]
static int network_init(void)
{
connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
if (connection == NULL)
return -EIO;
//根據network.conf來進行各種配置
if (network_manager_init(connection) < 0) {
dbus_connection_unref(connection);
return -EIO;
}
return 0;
}
int network_manager_init(DBusConnection *conn)
{
//讀取network.conf文件,network.conf裡面也沒有內容,設置conf_security,默認為true
read_config(CONFIGDIR "/network.conf");
//新建一個bnep的socket
if (bnep_init()) {
error("Can't init bnep module");
return -1;
}
/*
* There is one socket to handle the incomming connections. NAP,
* GN and PANU servers share the same PSM. The initial BNEP message
* (setup connection request) contains the destination service
* field that defines which service the source is connecting to.
*/
//初始化security
if (server_init(conn, conf_security) < 0)
return -1;
//加入到adapter_drivers列表中
/* Register network server if it doesn't exist */
btd_register_adapter_driver(&network_server_driver);
//dbus connection
if (connection_init(conn) < 0)
return -1;
//初始化了3個device driver
btd_register_device_driver(&network_panu_driver);
btd_register_device_driver(&network_gn_driver);
btd_register_device_driver(&network_nap_driver);
connection = dbus_connection_ref(conn);
return 0;
}
2.3.7.4 health的init
health總得來說用得還是蠻少的,不過android4.0也是支持了,我們來看一下吧:
[cpp]
static int hdp_init(void)
{
connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
if (connection == NULL)
return -EIO;
//就是這個函數了
if (hdp_manager_init(connection) < 0) {
dbus_connection_unref(connection);
return -EIO;
}
return 0;
}
int hdp_manager_init(DBusConnection *conn)
{
//就是注冊了一個health_manager_methods的接口,裡面有creatapplication和destroyapplication兩個函數
if (hdp_manager_start(conn))
return -1;
connection = dbus_connection_ref(conn);
//注冊一個adapter drvier和一個device driver。
btd_register_adapter_driver(&hdp_adapter_driver);
btd_register_device_driver(&hdp_device_driver);
return 0;
}
至此,所有的plugin都已經完成了。總共注冊了一下幾個adapter_driver:a2dp_server_driver,avrcp_server_driver,input_server_driver,network_server_driver,hdp_adapter_driver。另外還有幾個devcie driver:audio_driver,input_hid_driver,input_headset_driver,network_panu_driver,network_gn_driver,network_nap_driver,hdp_device_driver。在後面adapter up之後我們會加載這些driver,到時我們再來詳細分析他們各自都做了些什麼。