[Spice-devel] [PATCH 2/5] vdagent: mv vdi_port files from vdservice

Arnon Gilboa agilboa at redhat.com
Wed Nov 7 05:19:48 PST 2012


---
 vdagent/pci_vdi_port.cpp      |  132 +++++++++++++++++++++++++++++
 vdagent/pci_vdi_port.h        |   59 +++++++++++++
 vdagent/vdi_port.cpp          |   90 ++++++++++++++++++++
 vdagent/vdi_port.h            |   75 ++++++++++++++++
 vdagent/virtio_vdi_port.cpp   |  187 +++++++++++++++++++++++++++++++++++++++++
 vdagent/virtio_vdi_port.h     |   33 +++++++
 vdservice/pci_vdi_port.cpp    |  132 -----------------------------
 vdservice/pci_vdi_port.h      |   59 -------------
 vdservice/vdi_port.cpp        |   90 --------------------
 vdservice/vdi_port.h          |   75 ----------------
 vdservice/virtio_vdi_port.cpp |  187 -----------------------------------------
 vdservice/virtio_vdi_port.h   |   33 -------
 12 files changed, 576 insertions(+), 576 deletions(-)
 create mode 100644 vdagent/pci_vdi_port.cpp
 create mode 100644 vdagent/pci_vdi_port.h
 create mode 100644 vdagent/vdi_port.cpp
 create mode 100644 vdagent/vdi_port.h
 create mode 100644 vdagent/virtio_vdi_port.cpp
 create mode 100644 vdagent/virtio_vdi_port.h
 delete mode 100644 vdservice/pci_vdi_port.cpp
 delete mode 100644 vdservice/pci_vdi_port.h
 delete mode 100644 vdservice/vdi_port.cpp
 delete mode 100644 vdservice/vdi_port.h
 delete mode 100644 vdservice/virtio_vdi_port.cpp
 delete mode 100644 vdservice/virtio_vdi_port.h

diff --git a/vdagent/pci_vdi_port.cpp b/vdagent/pci_vdi_port.cpp
new file mode 100644
index 0000000..7466fbc
--- /dev/null
+++ b/vdagent/pci_vdi_port.cpp
@@ -0,0 +1,132 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdio.h"
+#include "pci_vdi_port.h"
+#include "vdlog.h"
+
+#define VDI_PORT_DEV_NAME   TEXT("\\\\.\\VDIPort")
+#define FILE_DEVICE_UNKNOWN 0x00000022
+#define METHOD_BUFFERED     0
+#define FILE_ANY_ACCESS     0
+
+#ifndef CTL_CODE
+//With mingw, this is defined in winioctl.h
+#define CTL_CODE(DeviceType, Function, Method, Access) (                   \
+    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+#endif
+
+#define FIRST_AVAIL_IO_FUNC 0x800
+#define RED_TUNNEL_CTL_FUNC FIRST_AVAIL_IO_FUNC
+
+#define IOCTL_RED_TUNNEL_SET_EVENT \
+    CTL_CODE(FILE_DEVICE_UNKNOWN, RED_TUNNEL_CTL_FUNC, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+PCIVDIPort::PCIVDIPort()
+    : _handle (INVALID_HANDLE_VALUE)
+    , _event (NULL)
+{
+}
+
+PCIVDIPort::~PCIVDIPort()
+{
+    if (_handle != INVALID_HANDLE_VALUE) {
+        CloseHandle(_handle);
+    }
+    if (_event) {
+        CloseHandle(_event);
+    }
+}
+
+void PCIVDIPort::fill_events(HANDLE* handles) {
+    handles[PCI_VDI_PORT_EVENT] = _event;
+}
+
+bool PCIVDIPort::init()
+{
+    DWORD io_ret_len;
+    _handle = CreateFile(VDI_PORT_DEV_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+                         OPEN_EXISTING, 0, NULL);
+    if (_handle == INVALID_HANDLE_VALUE) {
+        vd_printf("CreateFile() failed: %lu", GetLastError());
+        return false;
+    }
+    _event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (_event == NULL) {
+        vd_printf("CreateEvent() failed: %lu", GetLastError());
+        return false;
+    }
+    if (!DeviceIoControl(_handle, IOCTL_RED_TUNNEL_SET_EVENT, &_event, sizeof(_event),
+                         NULL, 0, &io_ret_len, NULL)) {
+        vd_printf("DeviceIoControl() failed: %lu", GetLastError());
+        return false;
+    }
+    return true;
+}
+
+int PCIVDIPort::write()
+{
+    int size;
+    int n;
+
+    if (_write.start == _write.end) {
+        return 0;
+    }
+    if (_write.start < _write.end) {
+        size = (int)(_write.end - _write.start);
+    } else {
+        size = (int)(&_write.ring[BUF_SIZE] - _write.start);
+    }
+    if (!WriteFile(_handle, _write.start, size, (LPDWORD)&n, NULL)) {
+        return handle_error();
+    }
+    _write.start = _write.ring + (_write.start - _write.ring + n) % BUF_SIZE;
+    return n;
+}
+
+int PCIVDIPort::read()
+{
+    int size;
+    int n;
+
+    if ((_read.end - _read.ring + 1) % BUF_SIZE == _read.start - _read.ring) {
+        return 0;
+    }
+    if (_read.start == _read.end) {
+        _read.start = _read.end = _read.ring;
+    }
+    if (_read.start <= _read.end) {
+        size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end));
+    } else {
+        size = (int)(_read.start - _read.end - 1);
+    }
+    if (!ReadFile(_handle, _read.end, size, (LPDWORD)&n, NULL)) {
+        return handle_error();
+    }
+    _read.end = _read.ring + (_read.end - _read.ring + n) % BUF_SIZE;
+    return n;
+}
+
+bool PCIVDIPort::handle_event(int event)
+{
+    // do nothing - the event merely serves to wake us up, then we call read/write
+    // at VDService::execute start of while(_running) loop.
+    return true;
+}
diff --git a/vdagent/pci_vdi_port.h b/vdagent/pci_vdi_port.h
new file mode 100644
index 0000000..fcc76dc
--- /dev/null
+++ b/vdagent/pci_vdi_port.h
@@ -0,0 +1,59 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H_PCI_VDI_PORT
+#define _H_PCI_VDI_PORT
+
+#include "vdi_port.h"
+
+#define BUF_READ    (1 << 0)
+#define BUF_WRITE   (1 << 1)
+#define BUF_ALL     (BUF_READ | BUF_WRITE)
+
+enum {
+    PCI_VDI_PORT_EVENT = 0,
+    PCI_VDI_PORT_EVENT_COUNT
+};
+
+class PCIVDIPort : public VDIPort {
+public:
+    PCIVDIPort();
+    ~PCIVDIPort();
+    virtual bool init();
+    virtual const char *name() {
+        return "PCIVDIPort";
+    }
+    virtual int write();
+    virtual int read();
+    virtual unsigned get_num_events() { return PCI_VDI_PORT_EVENT_COUNT; }
+    virtual void fill_events(HANDLE* handles);
+    virtual bool handle_event(int event);
+
+private:
+    HANDLE _handle;
+    HANDLE _event;
+};
+
+// Ring notes:
+// _end is one after the end of data
+// _start==_end means empty ring
+// _start-1==_end (modulo) means full ring
+// _start-1 is never used
+// ring_write & read on right side of the ring (update _end)
+// ring_read & write from left (update _start)
+
+#endif
diff --git a/vdagent/vdi_port.cpp b/vdagent/vdi_port.cpp
new file mode 100644
index 0000000..bd5ea05
--- /dev/null
+++ b/vdagent/vdi_port.cpp
@@ -0,0 +1,90 @@
+#include "vdlog.h"
+#include "vdi_port.h"
+
+VDIPort::VDIPort()
+{
+    ZeroMemory(&_write, offsetof(VDIPortBuffer, ring));
+    _write.start = _write.end = _write.ring;
+    ZeroMemory(&_read, offsetof(VDIPortBuffer, ring));
+    _read.start = _read.end = _read.ring;
+}
+
+size_t VDIPort::read_ring_size()
+{
+    return (BUF_SIZE + _read.end - _read.start) % BUF_SIZE;
+}
+
+size_t VDIPort::write_ring_free_space()
+{
+    return (BUF_SIZE + _write.start - _write.end - 1) % BUF_SIZE;
+}
+
+size_t VDIPort::ring_write(const void* buf, size_t size)
+{
+    size_t free_size = (BUF_SIZE + _write.start - _write.end - 1) % BUF_SIZE;
+    size_t n;
+
+    if (size > free_size) {
+        size = free_size;
+    }
+    if (_write.end < _write.start) {
+        memcpy(_write.end, buf, size);
+    } else {
+        n = MIN(size, (size_t)(&_write.ring[BUF_SIZE] - _write.end));
+        memcpy(_write.end, buf, n);
+        if (size > n) {
+            memcpy(_write.ring, (uint8_t*)buf + n, size - n);
+        }
+    }
+    _write.end = _write.ring + (_write.end - _write.ring + size) % BUF_SIZE;
+    return size;
+}
+
+size_t VDIPort::read_ring_continuous_remaining_size()
+{
+    DWORD size;
+
+    if (_read.start <= _read.end) {
+        size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end));
+    } else {
+        size = (DWORD)(_read.start - _read.end - 1);
+    }
+    return size;
+}
+
+size_t VDIPort::ring_read(void* buf, size_t size)
+{
+    size_t n;
+    size_t m = 0;
+
+    if (_read.start == _read.end) {
+        return 0;
+    }
+    if (_read.start < _read.end) {
+        n = MIN(size, (size_t)(_read.end - _read.start));
+        memcpy(buf, _read.start, n);
+    } else {
+        n = MIN(size, (size_t)(&_read.ring[BUF_SIZE] - _read.start));
+        memcpy(buf, _read.start, n);
+        if (size > n) {
+            m = MIN(size - n, (size_t)(_read.end - _read.ring));
+            memcpy((uint8_t*)buf + n, _read.ring, m);
+        }
+    }
+    _read.start = _read.ring + (_read.start - _read.ring + n + m) % BUF_SIZE;
+    return n + m;
+}
+
+int VDIPort::handle_error()
+{
+    switch (GetLastError()) {
+    case ERROR_CONNECTION_INVALID:
+        vd_printf("port reset");
+        _write.start = _write.end = _write.ring;
+        _read.start = _read.end = _read.ring;
+        return VDI_PORT_RESET;
+    default:
+        vd_printf("port io failed: %lu", GetLastError());
+        return VDI_PORT_ERROR;
+    }
+}
diff --git a/vdagent/vdi_port.h b/vdagent/vdi_port.h
new file mode 100644
index 0000000..a0fb20e
--- /dev/null
+++ b/vdagent/vdi_port.h
@@ -0,0 +1,75 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H_VDI_PORT
+#define _H_VDI_PORT
+
+#include <windows.h>
+#include <stdint.h>
+
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+#define BUF_SIZE    (1024 * 1024)
+
+#define VDI_PORT_BLOCKED    0
+#define VDI_PORT_RESET      -1
+#define VDI_PORT_ERROR      -2
+
+// Ring notes:
+// _end is one after the end of data
+// _start==_end means empty ring
+// _start-1==_end (modulo) means full ring
+// _start-1 is never used
+// ring_write & read on right side of the ring (update _end)
+// ring_read & write from left (update _start)
+
+typedef struct VDIPortBuffer {
+    OVERLAPPED overlap;
+    uint8_t* start;
+    uint8_t* end;
+    bool pending;
+    int bytes;
+    uint8_t ring[BUF_SIZE];
+} VDIPortBuffer;
+
+class VDIPort {
+public:
+    VDIPort();
+    virtual ~VDIPort() {}
+
+    size_t ring_write(const void* buf, size_t size);
+    size_t write_ring_free_space();
+    size_t ring_read(void* buf, size_t size);
+    size_t read_ring_size();
+    size_t read_ring_continuous_remaining_size();
+
+    virtual const char *name() = 0;
+    virtual bool init() = 0;
+    virtual unsigned get_num_events() = 0;
+    virtual void fill_events(HANDLE* handles) = 0;
+    virtual bool handle_event(int event) = 0;
+    virtual int write() = 0;
+    virtual int read() = 0;
+
+protected:
+    int handle_error();
+
+    VDIPortBuffer _write;
+    VDIPortBuffer _read;
+};
+
+#endif
diff --git a/vdagent/virtio_vdi_port.cpp b/vdagent/virtio_vdi_port.cpp
new file mode 100644
index 0000000..be5568a
--- /dev/null
+++ b/vdagent/virtio_vdi_port.cpp
@@ -0,0 +1,187 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdio.h"
+#include "virtio_vdi_port.h"
+#include "vdlog.h"
+
+#define VIOSERIAL_PORT_PATH                 L"\\\\.\\Global\\com.redhat.spice.0"
+
+// Current limitation of virtio-serial windows driver (RHBZ 617000)
+#define VIOSERIAL_PORT_MAX_WRITE_BYTES      2048
+
+VirtioVDIPort* VirtioVDIPort::_singleton;
+
+VirtioVDIPort::VirtioVDIPort()
+    : VDIPort()
+    , _handle (INVALID_HANDLE_VALUE)
+{
+    _singleton = this;
+}
+
+VirtioVDIPort::~VirtioVDIPort()
+{
+    if (_handle != INVALID_HANDLE_VALUE) {
+        CloseHandle(_handle);
+    }
+    if (_read.overlap.hEvent) {
+        CloseHandle(_read.overlap.hEvent);
+    }
+    if (_write.overlap.hEvent) {
+        CloseHandle(_write.overlap.hEvent);
+    }
+}
+
+void VirtioVDIPort::fill_events(HANDLE* handles) {
+    handles[VIRTIO_VDI_PORT_EVENT_WRITE] = _write.overlap.hEvent;
+    handles[VIRTIO_VDI_PORT_EVENT_READ] = _read.overlap.hEvent;
+}
+
+bool VirtioVDIPort::handle_event(int event) {
+    bool ret;
+
+    switch (event) {
+        case VIRTIO_VDI_PORT_EVENT_WRITE:
+            ret = write_completion();
+            break;
+        case VIRTIO_VDI_PORT_EVENT_READ:
+            ret = read_completion();
+            break;
+        default:
+            vd_printf("ERROR: unexpected event %d", event);
+            ret = false;
+    }
+    return ret;
+}
+
+bool VirtioVDIPort::init()
+{
+    _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
+                         OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+    if (_handle == INVALID_HANDLE_VALUE) {
+        vd_printf("CreateFile() %ls failed: %lu", VIOSERIAL_PORT_PATH, GetLastError());
+        return false;
+    }
+    _write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (_write.overlap.hEvent == NULL) {
+        vd_printf("CreateEvent() failed: %lu", GetLastError());
+        return false;
+    }
+    _read.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (_read.overlap.hEvent == NULL) {
+        vd_printf("CreateEvent() failed: %lu", GetLastError());
+        return false;
+    }
+    return true;
+}
+
+int VirtioVDIPort::write()
+{
+    int size;
+    int ret;
+
+    //FIXME: return VDI_PORT_NO_DATA
+    if (_write.start == _write.end) {
+        return 0;
+    }
+    if (!_write.pending) {
+        if (_write.start < _write.end) {
+            size = (int)(_write.end - _write.start);
+        } else {
+            size = (int)(&_write.ring[BUF_SIZE] - _write.start);
+        }
+        size = MIN(size, VIOSERIAL_PORT_MAX_WRITE_BYTES);
+        _write.pending = true;
+        if (WriteFile(_handle, _write.start, size, NULL, &_write.overlap)) {
+            write_completion();
+        } if (GetLastError() != ERROR_IO_PENDING) {
+            return handle_error();
+        }
+    }
+    ret = _write.bytes;
+    _write.bytes = 0;
+    return ret;
+}
+
+bool VirtioVDIPort::write_completion()
+{
+    DWORD bytes;
+
+    if (!_write.pending) {
+        return true;
+    }
+    if (!GetOverlappedResult(_handle, &_write.overlap, &bytes, FALSE)) {
+        vd_printf("GetOverlappedResult failed: %lu", GetLastError());
+        return false;
+    }
+    _write.start = _write.ring + (_write.start - _write.ring + bytes) % BUF_SIZE;
+    _write.bytes = bytes;
+    _write.pending = false;
+    return true;
+}
+
+int VirtioVDIPort::read()
+{
+    int size;
+    int ret;
+
+    if (!_read.pending) {
+        //FIXME: read_ring_continuous_remaining_size? return VDI_PORT_BUFFER_FULL
+        if ((_read.end - _read.ring + 1) % BUF_SIZE == _read.start - _read.ring) {
+            vd_printf("DEBUG: buffer full");
+            return 0;
+        }
+        if (_read.start == _read.end) {
+            _read.start = _read.end = _read.ring;
+        }
+        if (_read.start <= _read.end) {
+            size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end));
+        } else {
+            size = (int)(_read.start - _read.end - 1);
+        }
+        _read.pending = true;
+        if (ReadFile(_handle, _read.end, size, NULL, &_read.overlap)) {
+            read_completion();
+        } else if (GetLastError() != ERROR_IO_PENDING) {
+            return handle_error();
+        }
+    }
+    ret = _read.bytes;
+    _read.bytes = 0;
+    return ret;
+}
+
+bool VirtioVDIPort::read_completion()
+{
+    DWORD bytes;
+
+    if (!GetOverlappedResult(_handle, &_read.overlap, &bytes, FALSE)) {
+        DWORD err = GetLastError();
+
+        if (err == ERROR_OPERATION_ABORTED || err == ERROR_NO_SYSTEM_RESOURCES) {
+            _read.pending = false;
+            return true;
+        } else if (err != ERROR_MORE_DATA) {
+            vd_printf("GetOverlappedResult failed: %lu", err);
+            return false;
+        }
+    }
+    _read.end = _read.ring + (_read.end - _read.ring + bytes) % BUF_SIZE;
+    _read.bytes = bytes;
+    _read.pending = false;
+    return true;
+}
diff --git a/vdagent/virtio_vdi_port.h b/vdagent/virtio_vdi_port.h
new file mode 100644
index 0000000..d72edf4
--- /dev/null
+++ b/vdagent/virtio_vdi_port.h
@@ -0,0 +1,33 @@
+#ifndef _H_VIRTIO_VDI_PORT
+#define _H_VIRTIO_VDI_PORT
+
+#include "vdi_port.h"
+
+enum {
+    VIRTIO_VDI_PORT_EVENT_WRITE=0,
+    VIRTIO_VDI_PORT_EVENT_READ,
+    VIRTIO_VDI_PORT_EVENT_COUNT
+};
+
+class VirtioVDIPort : public VDIPort {
+public:
+    VirtioVDIPort();
+    ~VirtioVDIPort();
+    virtual const char *name() { return "VirtioVDIPort"; }
+    virtual bool init();
+    virtual unsigned get_num_events() { return VIRTIO_VDI_PORT_EVENT_COUNT; }
+    virtual void fill_events(HANDLE* handles);
+    virtual bool handle_event(int event);
+    virtual int write();
+    virtual int read();
+
+private:
+    bool write_completion();
+    bool read_completion();
+
+private:
+    static VirtioVDIPort* _singleton;
+    HANDLE _handle;
+};
+
+#endif //_H_VIRTIO_VDI_PORT
diff --git a/vdservice/pci_vdi_port.cpp b/vdservice/pci_vdi_port.cpp
deleted file mode 100644
index 7466fbc..0000000
--- a/vdservice/pci_vdi_port.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdio.h"
-#include "pci_vdi_port.h"
-#include "vdlog.h"
-
-#define VDI_PORT_DEV_NAME   TEXT("\\\\.\\VDIPort")
-#define FILE_DEVICE_UNKNOWN 0x00000022
-#define METHOD_BUFFERED     0
-#define FILE_ANY_ACCESS     0
-
-#ifndef CTL_CODE
-//With mingw, this is defined in winioctl.h
-#define CTL_CODE(DeviceType, Function, Method, Access) (                   \
-    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
-)
-#endif
-
-#define FIRST_AVAIL_IO_FUNC 0x800
-#define RED_TUNNEL_CTL_FUNC FIRST_AVAIL_IO_FUNC
-
-#define IOCTL_RED_TUNNEL_SET_EVENT \
-    CTL_CODE(FILE_DEVICE_UNKNOWN, RED_TUNNEL_CTL_FUNC, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define MIN(a, b) ((a) > (b) ? (b) : (a))
-
-PCIVDIPort::PCIVDIPort()
-    : _handle (INVALID_HANDLE_VALUE)
-    , _event (NULL)
-{
-}
-
-PCIVDIPort::~PCIVDIPort()
-{
-    if (_handle != INVALID_HANDLE_VALUE) {
-        CloseHandle(_handle);
-    }
-    if (_event) {
-        CloseHandle(_event);
-    }
-}
-
-void PCIVDIPort::fill_events(HANDLE* handles) {
-    handles[PCI_VDI_PORT_EVENT] = _event;
-}
-
-bool PCIVDIPort::init()
-{
-    DWORD io_ret_len;
-    _handle = CreateFile(VDI_PORT_DEV_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
-                         OPEN_EXISTING, 0, NULL);
-    if (_handle == INVALID_HANDLE_VALUE) {
-        vd_printf("CreateFile() failed: %lu", GetLastError());
-        return false;
-    }
-    _event = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (_event == NULL) {
-        vd_printf("CreateEvent() failed: %lu", GetLastError());
-        return false;
-    }
-    if (!DeviceIoControl(_handle, IOCTL_RED_TUNNEL_SET_EVENT, &_event, sizeof(_event),
-                         NULL, 0, &io_ret_len, NULL)) {
-        vd_printf("DeviceIoControl() failed: %lu", GetLastError());
-        return false;
-    }
-    return true;
-}
-
-int PCIVDIPort::write()
-{
-    int size;
-    int n;
-
-    if (_write.start == _write.end) {
-        return 0;
-    }
-    if (_write.start < _write.end) {
-        size = (int)(_write.end - _write.start);
-    } else {
-        size = (int)(&_write.ring[BUF_SIZE] - _write.start);
-    }
-    if (!WriteFile(_handle, _write.start, size, (LPDWORD)&n, NULL)) {
-        return handle_error();
-    }
-    _write.start = _write.ring + (_write.start - _write.ring + n) % BUF_SIZE;
-    return n;
-}
-
-int PCIVDIPort::read()
-{
-    int size;
-    int n;
-
-    if ((_read.end - _read.ring + 1) % BUF_SIZE == _read.start - _read.ring) {
-        return 0;
-    }
-    if (_read.start == _read.end) {
-        _read.start = _read.end = _read.ring;
-    }
-    if (_read.start <= _read.end) {
-        size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end));
-    } else {
-        size = (int)(_read.start - _read.end - 1);
-    }
-    if (!ReadFile(_handle, _read.end, size, (LPDWORD)&n, NULL)) {
-        return handle_error();
-    }
-    _read.end = _read.ring + (_read.end - _read.ring + n) % BUF_SIZE;
-    return n;
-}
-
-bool PCIVDIPort::handle_event(int event)
-{
-    // do nothing - the event merely serves to wake us up, then we call read/write
-    // at VDService::execute start of while(_running) loop.
-    return true;
-}
diff --git a/vdservice/pci_vdi_port.h b/vdservice/pci_vdi_port.h
deleted file mode 100644
index fcc76dc..0000000
--- a/vdservice/pci_vdi_port.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_PCI_VDI_PORT
-#define _H_PCI_VDI_PORT
-
-#include "vdi_port.h"
-
-#define BUF_READ    (1 << 0)
-#define BUF_WRITE   (1 << 1)
-#define BUF_ALL     (BUF_READ | BUF_WRITE)
-
-enum {
-    PCI_VDI_PORT_EVENT = 0,
-    PCI_VDI_PORT_EVENT_COUNT
-};
-
-class PCIVDIPort : public VDIPort {
-public:
-    PCIVDIPort();
-    ~PCIVDIPort();
-    virtual bool init();
-    virtual const char *name() {
-        return "PCIVDIPort";
-    }
-    virtual int write();
-    virtual int read();
-    virtual unsigned get_num_events() { return PCI_VDI_PORT_EVENT_COUNT; }
-    virtual void fill_events(HANDLE* handles);
-    virtual bool handle_event(int event);
-
-private:
-    HANDLE _handle;
-    HANDLE _event;
-};
-
-// Ring notes:
-// _end is one after the end of data
-// _start==_end means empty ring
-// _start-1==_end (modulo) means full ring
-// _start-1 is never used
-// ring_write & read on right side of the ring (update _end)
-// ring_read & write from left (update _start)
-
-#endif
diff --git a/vdservice/vdi_port.cpp b/vdservice/vdi_port.cpp
deleted file mode 100644
index bd5ea05..0000000
--- a/vdservice/vdi_port.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "vdlog.h"
-#include "vdi_port.h"
-
-VDIPort::VDIPort()
-{
-    ZeroMemory(&_write, offsetof(VDIPortBuffer, ring));
-    _write.start = _write.end = _write.ring;
-    ZeroMemory(&_read, offsetof(VDIPortBuffer, ring));
-    _read.start = _read.end = _read.ring;
-}
-
-size_t VDIPort::read_ring_size()
-{
-    return (BUF_SIZE + _read.end - _read.start) % BUF_SIZE;
-}
-
-size_t VDIPort::write_ring_free_space()
-{
-    return (BUF_SIZE + _write.start - _write.end - 1) % BUF_SIZE;
-}
-
-size_t VDIPort::ring_write(const void* buf, size_t size)
-{
-    size_t free_size = (BUF_SIZE + _write.start - _write.end - 1) % BUF_SIZE;
-    size_t n;
-
-    if (size > free_size) {
-        size = free_size;
-    }
-    if (_write.end < _write.start) {
-        memcpy(_write.end, buf, size);
-    } else {
-        n = MIN(size, (size_t)(&_write.ring[BUF_SIZE] - _write.end));
-        memcpy(_write.end, buf, n);
-        if (size > n) {
-            memcpy(_write.ring, (uint8_t*)buf + n, size - n);
-        }
-    }
-    _write.end = _write.ring + (_write.end - _write.ring + size) % BUF_SIZE;
-    return size;
-}
-
-size_t VDIPort::read_ring_continuous_remaining_size()
-{
-    DWORD size;
-
-    if (_read.start <= _read.end) {
-        size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end));
-    } else {
-        size = (DWORD)(_read.start - _read.end - 1);
-    }
-    return size;
-}
-
-size_t VDIPort::ring_read(void* buf, size_t size)
-{
-    size_t n;
-    size_t m = 0;
-
-    if (_read.start == _read.end) {
-        return 0;
-    }
-    if (_read.start < _read.end) {
-        n = MIN(size, (size_t)(_read.end - _read.start));
-        memcpy(buf, _read.start, n);
-    } else {
-        n = MIN(size, (size_t)(&_read.ring[BUF_SIZE] - _read.start));
-        memcpy(buf, _read.start, n);
-        if (size > n) {
-            m = MIN(size - n, (size_t)(_read.end - _read.ring));
-            memcpy((uint8_t*)buf + n, _read.ring, m);
-        }
-    }
-    _read.start = _read.ring + (_read.start - _read.ring + n + m) % BUF_SIZE;
-    return n + m;
-}
-
-int VDIPort::handle_error()
-{
-    switch (GetLastError()) {
-    case ERROR_CONNECTION_INVALID:
-        vd_printf("port reset");
-        _write.start = _write.end = _write.ring;
-        _read.start = _read.end = _read.ring;
-        return VDI_PORT_RESET;
-    default:
-        vd_printf("port io failed: %lu", GetLastError());
-        return VDI_PORT_ERROR;
-    }
-}
diff --git a/vdservice/vdi_port.h b/vdservice/vdi_port.h
deleted file mode 100644
index a0fb20e..0000000
--- a/vdservice/vdi_port.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_VDI_PORT
-#define _H_VDI_PORT
-
-#include <windows.h>
-#include <stdint.h>
-
-#define MIN(a, b) ((a) > (b) ? (b) : (a))
-
-#define BUF_SIZE    (1024 * 1024)
-
-#define VDI_PORT_BLOCKED    0
-#define VDI_PORT_RESET      -1
-#define VDI_PORT_ERROR      -2
-
-// Ring notes:
-// _end is one after the end of data
-// _start==_end means empty ring
-// _start-1==_end (modulo) means full ring
-// _start-1 is never used
-// ring_write & read on right side of the ring (update _end)
-// ring_read & write from left (update _start)
-
-typedef struct VDIPortBuffer {
-    OVERLAPPED overlap;
-    uint8_t* start;
-    uint8_t* end;
-    bool pending;
-    int bytes;
-    uint8_t ring[BUF_SIZE];
-} VDIPortBuffer;
-
-class VDIPort {
-public:
-    VDIPort();
-    virtual ~VDIPort() {}
-
-    size_t ring_write(const void* buf, size_t size);
-    size_t write_ring_free_space();
-    size_t ring_read(void* buf, size_t size);
-    size_t read_ring_size();
-    size_t read_ring_continuous_remaining_size();
-
-    virtual const char *name() = 0;
-    virtual bool init() = 0;
-    virtual unsigned get_num_events() = 0;
-    virtual void fill_events(HANDLE* handles) = 0;
-    virtual bool handle_event(int event) = 0;
-    virtual int write() = 0;
-    virtual int read() = 0;
-
-protected:
-    int handle_error();
-
-    VDIPortBuffer _write;
-    VDIPortBuffer _read;
-};
-
-#endif
diff --git a/vdservice/virtio_vdi_port.cpp b/vdservice/virtio_vdi_port.cpp
deleted file mode 100644
index be5568a..0000000
--- a/vdservice/virtio_vdi_port.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdio.h"
-#include "virtio_vdi_port.h"
-#include "vdlog.h"
-
-#define VIOSERIAL_PORT_PATH                 L"\\\\.\\Global\\com.redhat.spice.0"
-
-// Current limitation of virtio-serial windows driver (RHBZ 617000)
-#define VIOSERIAL_PORT_MAX_WRITE_BYTES      2048
-
-VirtioVDIPort* VirtioVDIPort::_singleton;
-
-VirtioVDIPort::VirtioVDIPort()
-    : VDIPort()
-    , _handle (INVALID_HANDLE_VALUE)
-{
-    _singleton = this;
-}
-
-VirtioVDIPort::~VirtioVDIPort()
-{
-    if (_handle != INVALID_HANDLE_VALUE) {
-        CloseHandle(_handle);
-    }
-    if (_read.overlap.hEvent) {
-        CloseHandle(_read.overlap.hEvent);
-    }
-    if (_write.overlap.hEvent) {
-        CloseHandle(_write.overlap.hEvent);
-    }
-}
-
-void VirtioVDIPort::fill_events(HANDLE* handles) {
-    handles[VIRTIO_VDI_PORT_EVENT_WRITE] = _write.overlap.hEvent;
-    handles[VIRTIO_VDI_PORT_EVENT_READ] = _read.overlap.hEvent;
-}
-
-bool VirtioVDIPort::handle_event(int event) {
-    bool ret;
-
-    switch (event) {
-        case VIRTIO_VDI_PORT_EVENT_WRITE:
-            ret = write_completion();
-            break;
-        case VIRTIO_VDI_PORT_EVENT_READ:
-            ret = read_completion();
-            break;
-        default:
-            vd_printf("ERROR: unexpected event %d", event);
-            ret = false;
-    }
-    return ret;
-}
-
-bool VirtioVDIPort::init()
-{
-    _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
-                         OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
-    if (_handle == INVALID_HANDLE_VALUE) {
-        vd_printf("CreateFile() %ls failed: %lu", VIOSERIAL_PORT_PATH, GetLastError());
-        return false;
-    }
-    _write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (_write.overlap.hEvent == NULL) {
-        vd_printf("CreateEvent() failed: %lu", GetLastError());
-        return false;
-    }
-    _read.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (_read.overlap.hEvent == NULL) {
-        vd_printf("CreateEvent() failed: %lu", GetLastError());
-        return false;
-    }
-    return true;
-}
-
-int VirtioVDIPort::write()
-{
-    int size;
-    int ret;
-
-    //FIXME: return VDI_PORT_NO_DATA
-    if (_write.start == _write.end) {
-        return 0;
-    }
-    if (!_write.pending) {
-        if (_write.start < _write.end) {
-            size = (int)(_write.end - _write.start);
-        } else {
-            size = (int)(&_write.ring[BUF_SIZE] - _write.start);
-        }
-        size = MIN(size, VIOSERIAL_PORT_MAX_WRITE_BYTES);
-        _write.pending = true;
-        if (WriteFile(_handle, _write.start, size, NULL, &_write.overlap)) {
-            write_completion();
-        } if (GetLastError() != ERROR_IO_PENDING) {
-            return handle_error();
-        }
-    }
-    ret = _write.bytes;
-    _write.bytes = 0;
-    return ret;
-}
-
-bool VirtioVDIPort::write_completion()
-{
-    DWORD bytes;
-
-    if (!_write.pending) {
-        return true;
-    }
-    if (!GetOverlappedResult(_handle, &_write.overlap, &bytes, FALSE)) {
-        vd_printf("GetOverlappedResult failed: %lu", GetLastError());
-        return false;
-    }
-    _write.start = _write.ring + (_write.start - _write.ring + bytes) % BUF_SIZE;
-    _write.bytes = bytes;
-    _write.pending = false;
-    return true;
-}
-
-int VirtioVDIPort::read()
-{
-    int size;
-    int ret;
-
-    if (!_read.pending) {
-        //FIXME: read_ring_continuous_remaining_size? return VDI_PORT_BUFFER_FULL
-        if ((_read.end - _read.ring + 1) % BUF_SIZE == _read.start - _read.ring) {
-            vd_printf("DEBUG: buffer full");
-            return 0;
-        }
-        if (_read.start == _read.end) {
-            _read.start = _read.end = _read.ring;
-        }
-        if (_read.start <= _read.end) {
-            size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end));
-        } else {
-            size = (int)(_read.start - _read.end - 1);
-        }
-        _read.pending = true;
-        if (ReadFile(_handle, _read.end, size, NULL, &_read.overlap)) {
-            read_completion();
-        } else if (GetLastError() != ERROR_IO_PENDING) {
-            return handle_error();
-        }
-    }
-    ret = _read.bytes;
-    _read.bytes = 0;
-    return ret;
-}
-
-bool VirtioVDIPort::read_completion()
-{
-    DWORD bytes;
-
-    if (!GetOverlappedResult(_handle, &_read.overlap, &bytes, FALSE)) {
-        DWORD err = GetLastError();
-
-        if (err == ERROR_OPERATION_ABORTED || err == ERROR_NO_SYSTEM_RESOURCES) {
-            _read.pending = false;
-            return true;
-        } else if (err != ERROR_MORE_DATA) {
-            vd_printf("GetOverlappedResult failed: %lu", err);
-            return false;
-        }
-    }
-    _read.end = _read.ring + (_read.end - _read.ring + bytes) % BUF_SIZE;
-    _read.bytes = bytes;
-    _read.pending = false;
-    return true;
-}
diff --git a/vdservice/virtio_vdi_port.h b/vdservice/virtio_vdi_port.h
deleted file mode 100644
index d72edf4..0000000
--- a/vdservice/virtio_vdi_port.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef _H_VIRTIO_VDI_PORT
-#define _H_VIRTIO_VDI_PORT
-
-#include "vdi_port.h"
-
-enum {
-    VIRTIO_VDI_PORT_EVENT_WRITE=0,
-    VIRTIO_VDI_PORT_EVENT_READ,
-    VIRTIO_VDI_PORT_EVENT_COUNT
-};
-
-class VirtioVDIPort : public VDIPort {
-public:
-    VirtioVDIPort();
-    ~VirtioVDIPort();
-    virtual const char *name() { return "VirtioVDIPort"; }
-    virtual bool init();
-    virtual unsigned get_num_events() { return VIRTIO_VDI_PORT_EVENT_COUNT; }
-    virtual void fill_events(HANDLE* handles);
-    virtual bool handle_event(int event);
-    virtual int write();
-    virtual int read();
-
-private:
-    bool write_completion();
-    bool read_completion();
-
-private:
-    static VirtioVDIPort* _singleton;
-    HANDLE _handle;
-};
-
-#endif //_H_VIRTIO_VDI_PORT
-- 
1.7.4.1



More information about the Spice-devel mailing list