1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/*
* VBMouse - VirtualBox's HGCM protocol communication routines
* Copyright (C) 2022 Javier S. Pedro
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef VBOXHGCM_H
#define VBOXHGCM_H
#include "vbox.h"
#include "vboxdev.h"
typedef uint32_t hgcm_client_id_t;
static void vbox_hgcm_wait(VMMDevHGCMRequestHeader __far * req)
{
volatile uint32_t __far * req_flags = &req->fu32Flags;
while (!(*req_flags & VBOX_HGCM_REQ_DONE)) {
// TODO yield somehow?
}
}
static vboxerr vbox_hgcm_connect_existing(LPVBOXCOMM vb, const char *service, hgcm_client_id_t __far *client_id)
{
VMMDevHGCMConnect __far *req = (void __far *) vb->buf;
vbox_init_req(&req->header.header, VMMDevReq_HGCMConnect, sizeof(VMMDevHGCMConnect));
req->loc.type = VMMDevHGCMLoc_LocalHost_Existing;
_fstrcpy(req->loc.u.host.achName, service);
req->u32ClientID = 7;
vbox_send_request(vb->iobase, vb->dds.physicalAddress);
if (req->header.header.rc < 0) {
return req->header.header.rc;
} else if (req->header.header.rc == VINF_HGCM_ASYNC_EXECUTE) {
vbox_hgcm_wait(&req->header);
}
*client_id = req->u32ClientID;
return req->header.result;
}
static vboxerr vbox_hgcm_disconnect(LPVBOXCOMM vb, hgcm_client_id_t client_id)
{
VMMDevHGCMDisconnect __far *req = (void __far *) vb->buf;
vbox_init_req(&req->header.header, VMMDevReq_HGCMDisconnect, sizeof(VMMDevHGCMDisconnect));
req->u32ClientID = client_id;
vbox_send_request(vb->iobase, vb->dds.physicalAddress);
if (req->header.header.rc < 0) {
return req->header.header.rc;
} else if (req->header.header.rc == VINF_HGCM_ASYNC_EXECUTE) {
vbox_hgcm_wait(&req->header);
}
return req->header.result;
}
static void vbox_hgcm_init_call(VMMDevHGCMCall __far *req, hgcm_client_id_t client_id, uint32_t function, unsigned narg)
{
vbox_init_req(&req->header.header, VMMDevReq_HGCMCall32, sizeof(VMMDevHGCMCall) + (narg * sizeof(HGCMFunctionParameter)));
req->u32ClientID = client_id;
req->u32Function = function;
req->cParms = narg;
}
static vboxerr vbox_hgcm_do_call_sync(LPVBOXCOMM vb, VMMDevHGCMCall __far *req)
{
vbox_send_request(vb->iobase, vb->dds.physicalAddress);
if (req->header.header.rc < 0) {
return req->header.header.rc;
} else if (req->header.header.rc == VINF_HGCM_ASYNC_EXECUTE) {
vbox_hgcm_wait(&req->header);
}
return 0;
}
static void vbox_hgcm_set_parameter_uint32(VMMDevHGCMCall __far *req, unsigned arg, uint32_t value)
{
req->aParms[arg].type = VMMDevHGCMParmType_32bit;
req->aParms[arg].u.value32 = value;
}
static inline uint32_t vbox_hgcm_get_parameter_uint32(VMMDevHGCMCall __far *req, unsigned arg)
{
return req->aParms[arg].u.value32;
}
static void vbox_hgcm_set_parameter_uint64(VMMDevHGCMCall __far *req, unsigned arg, uint64_t value)
{
req->aParms[arg].type = VMMDevHGCMParmType_64bit;
req->aParms[arg].u.value64 = value;
}
static inline uint64_t vbox_hgcm_get_parameter_uint64(VMMDevHGCMCall __far *req, unsigned arg)
{
return req->aParms[arg].u.value64;
}
static void vbox_hgcm_set_parameter_pointer(VMMDevHGCMCall __far *req, unsigned arg, unsigned size, void __far *ptr)
{
req->aParms[arg].type = VMMDevHGCMParmType_LinAddr;
req->aParms[arg].u.LinAddr.cb = size;
req->aParms[arg].u.LinAddr.uAddr = linear_addr(ptr);
}
#endif // VBOXHGCM_H
|