spice-gtk 之usb相關代碼(1)

spice-gtk是裏面有一個spicy的測試工具,可以直接用來遠程連接虛擬機代替remote-viewer,但是spicy遠程連接的虛擬機卻不能自動加載插入的usb設備,下面簡單解析一下spice-gtk中關於usb的代碼.

usb-device-manager.c

下面是usb-device-manager.c中幾個重要的函數調用:spice_usb_device_manager_initable_init初始化了一個回調函數spice_usb_device_manager_hotplug_cb當檢測到usb接入和拔出的時候就會調用這個回調函數,之後再調用spice_usb_device_manager_hotplug_idle_cb裏面又調用了下面這兩個函數spice_usb_device_manager_add_dev和spice_usb_device_manager_remove_dev一個是插一個是拔。

usb-device-manager.c這個文件和spice-session是關聯的,session啓動的時候起來一個spice-channel,其實就是usb-device-manager.c(這個類似一個channel-display.c)裏面的,裏面有一個spice_usb_device_manager_add_dev這個函數就是channel檢測到有usb之後執行的任務。函數裏面有一個判斷 if (priv->auto_connect)如果這個執行,就會自動連接usb的,如果不執行那就需要在上面的input的menu菜單裏面點擊usb設置選擇usb以後才能重定向usb     spice_usb_device_manager_add_dev最後發射:

g_signal_emit(self, signals[DEVICE_ADDED], 0, device);信號傳輸給usb-deivce-widget.c裏面

其實我們考慮auto_connect變量是哪邊給賦值的呢,只要我們從根源給這個變量設置成ture其實就不需要上述操作了,根據我的尋找在spice-gtk-session.c裏面的spice_gtk_session_set_property會設置此變量,在case PROP_AUTO_USBREDIR時,將s->auto_usbredir_enable寫死爲true即可。

usb-device-widget.c

在這個裏面收到信號的時候就會在這個widget類中添加這個usb的界面按鈕,spicy窗口上面有一個input菜單欄,點擊之後會出現一個選擇usb設備的窗口,如果說上文不執行auto_connect那就需要你點擊按鈕以後纔會將usb重定向,如果上文執行auto_connect,那就直接給你按鈕按下去了,自動重定向連接usb。

虛擬機重新連接的時候不能直接重定向所有的usb設備

上述操作僅僅在虛擬機正常連接spice之後才能進行,虛擬機在剛連接的時候如果u盤是插着的,那麼這個u盤是不會被重定向到虛擬機裏面的,需要重新插拔一下,因爲spice_usb_device_manager_add_dev執行的時候auto_connect還沒被賦值,或者說即使auto_connect被強制賦值成true,usb重定向的時候也會因爲某些錯誤而失敗。最終將usb重定向到虛擬機中的函數是spice_usb_device_manager_connect_device_async。

實現連接虛擬機時自動重定向已經插着的usb

上文說到usb在插着的時候連接虛擬機是不會被重定向的,需要重新插拔,那麼怎樣去實現自動識別呢?在這個地方我自己實現了一個spice_usb_device_manager_connect_device_async的包裝,在spicy.c中包裝了一個函數想辦法去調用usb-device-manager.c中的spice_usb_device_manager_connect_device_async實現自動連接usb。在spice_usb_device_manager_add_dev中有這樣一行代碼g_ptr_array_add(priv->devices, device);是指將剛檢測到的usb設備存儲到devices這個數組中以供後面的使用,usb-device-widget.c中的界面啓動的時候界面上就會列舉已經插着的u盤讓你去選擇連接,其實這邊列舉的時候就是講devices裏面的usb設備讀取出來的。我們在usb-device-manager.c中實現了下面的代碼:

void spice_usb_device_manager_connect_all_usb_device(SpiceUsbDeviceManager *self)
{
    SpiceUsbDeviceManagerPrivate *priv = self->priv;
    guint i;
    for (i = 0; i < priv->devices->len; i++) {
        SpiceUsbDevice *device = g_ptr_array_index(priv->devices, i);
        spice_usb_device_manager_connect_device_async(self,
                                   device, NULL,
                                   spice_usb_device_manager_auto_connect_cb,
                                   spice_usb_device_ref(device));
    }
    printf("device num = %d\n", (int)i);
}

這裏實現了將devices裏面的所有usb設備都進行重定向,spice_usb_device_manager_connect_device_async重定向的根本函數,那應該在哪裏調用呢?我們寫的這個函數在調用的時候需要在所有資源都初始化完成之後才能調用成功,在spic-session.c中加上這麼一個函數:

void spice_session_connect_all_usb_device(SpiceSession *session)
{
    SpiceUsbDeviceManager *manager = spice_usb_device_manager_get(session, NULL);
    if (manager)
        spice_usb_device_manager_connect_all_usb_device(manager);
}

之後再在spicy.c中這樣調用:

spice_session_connect_all_usb_device(conn->session);//連接所有usb

但是關鍵問題是這行代碼到底放在spicy.c中的哪個地方呢?

connection_connect裏面不行調用的時候devices還是空的;g_message("main channel: opened");這個後面,也不行,提示usb重定向失敗,應該還是某些資源沒初始化完成;只有放在全屏按鈕觸發的函數裏面纔會生效,所以之後usb到底在開機後多久才能自己連上呢?才能調用重定向usb的操作呢??還是有待研究!

請閱讀《spice-gtk之usb相關代碼(2)》:

https://mp.csdn.net/postedit/89332051

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章