diff --git a/repos/ports/ports/virtualbox.hash b/repos/ports/ports/virtualbox.hash index c3a0e9566..b31dd355d 100644 --- a/repos/ports/ports/virtualbox.hash +++ b/repos/ports/ports/virtualbox.hash @@ -1 +1 @@ -2fc156a977246088b14dc9acad72ea3013c9e596 +d0f14330729a8ef3234c8a569e183e230c28e100 diff --git a/repos/ports/ports/virtualbox.port b/repos/ports/ports/virtualbox.port index f3b08c119..db4928aba 100644 --- a/repos/ports/ports/virtualbox.port +++ b/repos/ports/ports/virtualbox.port @@ -65,6 +65,7 @@ VBOX_MAIN_INC += USBDeviceImpl HostUSBDeviceImpl Matching Wrapper VBOX_SRC_VBOX := VMM Devices Runtime GuestHost/HGSMI Storage Disassembler VBOX_SRC_VBOX += HostDrivers/VBoxUSB/USBFilter.cpp VBOX_SRC_VBOX += HostServices/SharedFolders Main/xml/Settings.cpp +VBOX_SRC_VBOX += HostServices/SharedClipboard VBOX_SRC_VBOX += Main/xml/VirtualBox-settings.xsd Main/xml/SchemaDefs.xsl VBOX_SRC_VBOX += $(addsuffix .h, $(addprefix Main/include/, $(VBOX_MAIN_INC))) VBOX_SRC_VBOX += $(addsuffix .cpp, $(addprefix Main/src-client/, $(VBOX_MAIN_CLI))) @@ -83,9 +84,12 @@ VBOX_INC += usb.h usbfilter.h VBOX_INC_COM := array.h assert.h AutoLock.h ErrorInfo.h EventQueue.h Guid.h VBOX_INC_COM += list.h MultiResult.h string.h -VBOX_CONTENT += $(addprefix src/VBox/, $(VBOX_SRC_VBOX)) -VBOX_CONTENT += $(addprefix include/VBox/, $(VBOX_INC)) +VBOX_INC_HOST := VBoxClipboardExt.h VBoxClipboardSvc.h + +VBOX_CONTENT += $(addprefix src/VBox/,$(VBOX_SRC_VBOX)) +VBOX_CONTENT += $(addprefix include/VBox/, $(VBOX_INC)) VBOX_CONTENT += $(addprefix include/VBox/com/, $(VBOX_INC_COM)) +VBOX_CONTENT += $(addprefix include/VBox/HostServices/, $(VBOX_INC_HOST)) VBOX_CONTENT += src/libs/zlib-1.2.6 src/libs/liblzf-3.4 src/libs/libxml2-2.6.31 VBOX_CONTENT += src/recompiler include/VBox/vmm include/iprt Config.kmk diff --git a/repos/ports/src/virtualbox/dynlib.cc b/repos/ports/src/virtualbox/dynlib.cc index ad846b59c..ed44778a8 100644 --- a/repos/ports/src/virtualbox/dynlib.cc +++ b/repos/ports/src/virtualbox/dynlib.cc @@ -22,14 +22,18 @@ extern "C" { -DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable); +DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad_sf (VBOXHGCMSVCFNTABLE *ptable); +DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad_cb (VBOXHGCMSVCFNTABLE *ptable); static struct shared { const char * name; const char * symbol; void * func; -} shared[] = {{ "VBoxSharedFolders", VBOX_HGCM_SVCLOAD_NAME, (void *)VBoxHGCMSvcLoad }}; +} shared[] = { + { "VBoxSharedFolders", VBOX_HGCM_SVCLOAD_NAME, (void *)VBoxHGCMSvcLoad_sf }, + { "VBoxSharedClipboard", VBOX_HGCM_SVCLOAD_NAME, (void *)VBoxHGCMSvcLoad_cb } +}; int RTLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod) diff --git a/repos/ports/src/virtualbox/frontend/console.cc b/repos/ports/src/virtualbox/frontend/console.cc index 5c1c20be0..25e634418 100644 --- a/repos/ports/src/virtualbox/frontend/console.cc +++ b/repos/ports/src/virtualbox/frontend/console.cc @@ -1,6 +1,22 @@ +/* + * \brief Port of VirtualBox to Genode + * \author Norman Feske + * \author Alexander Boettcher + */ + +/* + * Copyright (C) 2013-2015 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + #include +#include #include +#include +#include #include "ConsoleImpl.h" #include "MachineImpl.h" @@ -15,11 +31,13 @@ static const bool debug = false; +static Genode::Attached_rom_dataspace *clipboard_rom = nullptr; +static Genode::Reporter *clipboard_reporter = nullptr; + void Console::uninit() DUMMY() HRESULT Console::resume(Reason_T aReason) DUMMY(E_FAIL) HRESULT Console::pause(Reason_T aReason) DUMMY(E_FAIL) void Console::enableVMMStatistics(BOOL aEnable) DUMMY() -void Console::changeClipboardMode(ClipboardMode_T aClipboardMode) DUMMY() HRESULT Console::updateMachineState(MachineState_T aMachineState) DUMMY(E_FAIL) HRESULT Console::attachToTapInterface(INetworkAdapter *networkAdapter) @@ -314,6 +332,41 @@ void GenodeConsole::handle_mode_change(unsigned) update_video_mode(); } +void GenodeConsole::init_clipboard() +{ + if (!&*machine()) + return; + + ClipboardMode_T mode; + machine()->COMGETTER(ClipboardMode)(&mode); + + if (mode == ClipboardMode_Bidirectional || + mode == ClipboardMode_HostToGuest) { + + _clipboard_rom = new Genode::Attached_rom_dataspace("clipboard"); + _clipboard_rom->sigh(_clipboard_signal_dispatcher); + + clipboard_rom = _clipboard_rom; + } + + if (mode == ClipboardMode_Bidirectional || + mode == ClipboardMode_GuestToHost) { + + _clipboard_reporter = new Genode::Reporter("clipboard"); + _clipboard_reporter->enabled(true); + + clipboard_reporter = _clipboard_reporter; + } +} + +void GenodeConsole::handle_cb_rom_change(unsigned) +{ + if (!_clipboard_rom) + return; + + vboxClipboardSync(nullptr); +} + void GenodeConsole::event_loop(IKeyboard * gKeyboard, IMouse * gMouse) { _vbox_keyboard = gKeyboard; @@ -345,3 +398,151 @@ void GenodeConsole::onMouseCapabilityChange(BOOL supportsAbsolute, BOOL supports gMouse->PutMouseEventAbsolute(-1, -1, 0, 0, 0); } } + + + + +/********************** + * Clipboard handling * + **********************/ + +struct _VBOXCLIPBOARDCONTEXT +{ + VBOXCLIPBOARDCLIENTDATA *pClient; +}; + +static VBOXCLIPBOARDCONTEXT context; + +int vboxClipboardInit (void) { return VINF_SUCCESS; } + +void vboxClipboardDestroy (void) +{ + clipboard_rom = nullptr; +} + +int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient, bool fHeadless) +{ + if (!pClient || context.pClient != NULL) + return VERR_NOT_SUPPORTED; + + vboxSvcClipboardLock(); + + pClient->pCtx = &context; + pClient->pCtx->pClient = pClient; + + vboxSvcClipboardUnlock(); + + int rc = vboxClipboardSync (pClient); + + return rc; +} + +void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *pClient) +{ + if (!pClient || !pClient->pCtx) + return; + + vboxSvcClipboardLock(); + pClient->pCtx->pClient = NULL; + vboxSvcClipboardUnlock(); +} + +void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient, + uint32_t formats) +{ + if (!pClient) + return; + + vboxSvcClipboardReportMsg (pClient, + VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA, + formats); +} + +int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t format, + void *pv, uint32_t const cb, uint32_t *pcbActual) +{ + if (!clipboard_rom || format != VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) + return VERR_NOT_SUPPORTED; + + if (!pv || !pcbActual || cb == 0) + return VERR_INVALID_PARAMETER; + + clipboard_rom->update(); + + if (!clipboard_rom->is_valid()) { + PERR("invalid clipboard dataspace"); + return VERR_NOT_SUPPORTED; + } + + char * data = clipboard_rom->local_addr(); + + try { + + Genode::Xml_node node(data); + if (!node.has_type("clipboard")) { + PERR("invalid clipboard xml syntax"); + return VERR_INVALID_PARAMETER; + } + + size_t const len = node.content_size(); + size_t written = 0; + + PRTUTF16 utf16_string = reinterpret_cast(pv); + int rc = RTStrToUtf16Ex(node.content_base(), len, &utf16_string, cb, &written); + + if (RT_SUCCESS(rc)) { + if ((written * 2) + 2 > cb) + written = (cb - 2) / 2; + + /* +1 stuff required for Windows guests ... linux guest doesn't care */ + *pcbActual = (written + 1) * 2; + utf16_string[written] = 0; + } else + *pcbActual = 0; + + } catch (Genode::Xml_node::Invalid_syntax) { + PERR("invalid clipboard xml syntax"); + return VERR_INVALID_PARAMETER; + } + + return VINF_SUCCESS; +} + +void vboxClipboardWriteData (VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, + uint32_t cb, uint32_t format) +{ + if (format != VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT || !pv || !pClient || + !clipboard_reporter) + return; + + PCRTUTF16 utf16str = reinterpret_cast(pv); + char * message = 0; + + int rc = RTUtf16ToUtf8(utf16str, &message); + + if (!RT_SUCCESS(rc) || !message) + return; + + try { + Genode::Reporter::Xml_generator xml(*clipboard_reporter, [&] () { + xml.append_sanitized(message, strlen(message)); }); + } catch (...) { + PERR("could not write clipboard data"); + } + + RTStrFree(message); +} + +int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient) +{ + if (!pClient) + pClient = context.pClient; + + if (!pClient) + return VERR_NOT_SUPPORTED; + + vboxSvcClipboardReportMsg (pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, + VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT); + + return VINF_SUCCESS; +} diff --git a/repos/ports/src/virtualbox/frontend/console.h b/repos/ports/src/virtualbox/frontend/console.h index d0edc5065..89926c30d 100644 --- a/repos/ports/src/virtualbox/frontend/console.h +++ b/repos/ports/src/virtualbox/frontend/console.h @@ -13,20 +13,24 @@ */ /* Genode includes */ +#include #include #include #include +#include +#include +#include +#include #include /* included from os/src/drivers/input/spec/ps2 */ #include +/* repos/ports includes */ +#include + /* VirtualBox includes */ #include "ConsoleImpl.h" -#include -#include -#include -#include class Scan_code @@ -115,10 +119,13 @@ class GenodeConsole : public Console { Report::Connection _shape_report_connection; Genode::Attached_dataspace _shape_report_ds; Vbox_pointer::Shape_report *_shape_report; + Genode::Reporter *_clipboard_reporter; + Genode::Attached_rom_dataspace *_clipboard_rom; IKeyboard *_vbox_keyboard; IMouse *_vbox_mouse; Genode::Signal_dispatcher _input_signal_dispatcher; Genode::Signal_dispatcher _mode_change_signal_dispatcher; + Genode::Signal_dispatcher _clipboard_signal_dispatcher; bool _key_status[Input::KEY_MAX + 1]; @@ -140,10 +147,13 @@ class GenodeConsole : public Console { _shape_report_connection("shape", sizeof(Vbox_pointer::Shape_report)), _shape_report_ds(_shape_report_connection.dataspace()), _shape_report(_shape_report_ds.local_addr()), + _clipboard_reporter(nullptr), + _clipboard_rom(nullptr), _vbox_keyboard(0), _vbox_mouse(0), _input_signal_dispatcher(_receiver, *this, &GenodeConsole::handle_input), - _mode_change_signal_dispatcher(_receiver, *this, &GenodeConsole::handle_mode_change) + _mode_change_signal_dispatcher(_receiver, *this, &GenodeConsole::handle_mode_change), + _clipboard_signal_dispatcher(_receiver, *this, &GenodeConsole::handle_cb_rom_change) { for (unsigned i = 0; i <= Input::KEY_MAX; i++) _key_status[i] = 0; @@ -151,6 +161,8 @@ class GenodeConsole : public Console { _input.sigh(_input_signal_dispatcher); } + void init_clipboard(); + void event_loop(IKeyboard * gKeyboard, IMouse * gMouse); void onMouseCapabilityChange(BOOL supportsAbsolute, BOOL supportsRelative, @@ -219,4 +231,5 @@ class GenodeConsole : public Console { void handle_input(unsigned); void handle_mode_change(unsigned); + void handle_cb_rom_change(unsigned); }; diff --git a/repos/ports/src/virtualbox/frontend/main.cc b/repos/ports/src/virtualbox/frontend/main.cc index 9db1fd65d..bdef5a971 100644 --- a/repos/ports/src/virtualbox/frontend/main.cc +++ b/repos/ports/src/virtualbox/frontend/main.cc @@ -145,6 +145,12 @@ HRESULT setupmachine() ComPtr gConsole; rc = session->COMGETTER(Console)(gConsole.asOutParam()); + /* handle input of Genode and forward it to VMM layer */ + ComPtr genodeConsole = gConsole; + RTLogPrintf("genodeConsole = %p\n", genodeConsole); + + genodeConsole->init_clipboard(); + /* Display object */ ComPtr display; rc = gConsole->COMGETTER(Display)(display.asOutParam()); @@ -194,10 +200,6 @@ HRESULT setupmachine() return rc; Assert (&*gKeyboard); - /* handle input of Genode and forward it to VMM layer */ - ComPtr genodeConsole = gConsole; - RTLogPrintf("genodeConsole = %p\n", genodeConsole); - genodeConsole->event_loop(gKeyboard, gMouse); Assert(!"return not expected"); diff --git a/repos/ports/src/virtualbox/include/VBox/HostServices/VBoxClipboardSvc.h b/repos/ports/src/virtualbox/include/VBox/HostServices/VBoxClipboardSvc.h deleted file mode 100644 index 14565a70a..000000000 --- a/repos/ports/src/virtualbox/include/VBox/HostServices/VBoxClipboardSvc.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef ___VBox_HostService_VBoxClipboardSvc_h -#define ___VBox_HostService_VBoxClipboardSvc_h - -#define VBOX_SHARED_CLIPBOARD_HOST_FN_SET_HEADLESS 2 - -#endif diff --git a/repos/ports/src/virtualbox/patches/hostservice.patch b/repos/ports/src/virtualbox/patches/hostservice.patch new file mode 100644 index 000000000..85301fe2c --- /dev/null +++ b/repos/ports/src/virtualbox/patches/hostservice.patch @@ -0,0 +1,20 @@ ++++ a/src/app/virtualbox/src/VBox/HostServices/SharedFolders/service.cpp +@@ -1445,7 +1489,7 @@ + return rc; + } + +-extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable) ++extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad_sf (VBOXHGCMSVCFNTABLE *ptable) + { + int rc = VINF_SUCCESS; + ++++ a/src/app/virtualbox/src/VBox/HostServices/SharedClipboard/service.cpp +@@ -966,7 +966,7 @@ + return VINF_SUCCESS; + } + +-extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable) ++extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad_cb (VBOXHGCMSVCFNTABLE *ptable) + { + int rc = VINF_SUCCESS; + diff --git a/repos/ports/src/virtualbox/patches/series b/repos/ports/src/virtualbox/patches/series index 4eb5ca280..5523f9407 100644 --- a/repos/ports/src/virtualbox/patches/series +++ b/repos/ports/src/virtualbox/patches/series @@ -22,3 +22,4 @@ rem_irq.patch usb.patch tm_smp.patch posix.patch +hostservice.patch diff --git a/repos/ports/src/virtualbox/patches/vbox_main.patch b/repos/ports/src/virtualbox/patches/vbox_main.patch index 6df439977..e78f42160 100644 --- a/repos/ports/src/virtualbox/patches/vbox_main.patch +++ b/repos/ports/src/virtualbox/patches/vbox_main.patch @@ -772,14 +772,14 @@ index 69e3109..141bb98 100644 /** * Fetches the list of global or machine shared folders from the server. * -@@ -8353,6 +8437,8 @@ DECLCALLBACK(void) Console::vmstateChangeCallback(PUVM pUVM, VMSTATE enmState, V - } +@@ -8390,6 +8474,8 @@ + pVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE, 1, &parm); } +#if 0 + /** - * Changes the clipboard mode. + * Changes the drag'n_drop mode. * @@ -8426,7 +8512,7 @@ void Console::changeDragAndDropMode(DragAndDropMode_T aDragAndDropMode) diff --git a/repos/ports/src/virtualbox/target.mk b/repos/ports/src/virtualbox/target.mk index 7b456a66a..7ebb0e071 100644 --- a/repos/ports/src/virtualbox/target.mk +++ b/repos/ports/src/virtualbox/target.mk @@ -13,7 +13,7 @@ SRC_CC = frontend/main.cc frontend/console.cc \ frontend/USBProxyDevice-genode.cpp \ devices.cc drivers.cc dummies.cc libc.cc \ logger.cc mm.cc pdm.cc pgm.cc rt.cc sup.cc iommio.cc ioport.cc \ - hm.cc thread.cc dynlib.cc unimpl.cc + hm.cc thread.cc dynlib.cc unimpl.cc LIBS += base LIBS += config_args @@ -38,6 +38,8 @@ SRC_CC += HostServices/SharedFolders/mappings.cpp SRC_CC += HostServices/SharedFolders/vbsf.cpp SRC_CC += HostServices/SharedFolders/shflhandle.cpp +SRC_CC += HostServices/SharedClipboard/service.cpp + SRC_CC += frontend/dummy/errorinfo.cc frontend/dummy/virtualboxbase.cc SRC_CC += frontend/dummy/autostart.cc frontend/dummy/rest.cc SRC_CC += frontend/dummy/host.cc @@ -50,6 +52,7 @@ INC_DIR += $(REP_DIR)/src/virtualbox/frontend/VBoxAPIWrap INC_DIR += $(VBOX_DIR)/Main/xml INC_DIR += $(VBOX_DIR)/Devices/USB +INC_DIR += $(VBOX_DIR)/HostServices # search path to 'scan_code_set_2.h' INC_DIR += $(call select_from_repositories,src/drivers/input/spec/ps2)