diff options
Diffstat (limited to 'vbox.h')
-rw-r--r-- | vbox.h | 175 |
1 files changed, 143 insertions, 32 deletions
@@ -23,53 +23,164 @@ #include <stdbool.h> #include <stdint.h> +#include "utils.h" +#include "vboxdev.h" + +//#define VBOX_BUFFER_SIZE 64 +#define VBOX_BUFFER_SIZE (1024 + 32 + 24 + 20) + +typedef struct vboxcomm { + uint16_t iobase; + char buf[VBOX_BUFFER_SIZE]; + uint32_t buf_physaddr; +} vboxcomm_t; +typedef vboxcomm_t __far * LPVBOXCOMM; + /** Logs a single character to the VBox debug message port. */ -static void vbox_logc(char c); -#pragma aux vbox_logc = \ +static void vbox_log_putc(char c); +#pragma aux vbox_log_putc = \ "mov dx, 0x504" \ "out dx, al" \ __parm [al] \ __modify [dx] -/** Logs a string to the VBox debug message port. */ -static void vbox_logs(const char __far *str); -#pragma aux vbox_logs = \ - "mov di, si" \ - "xor cx, cx" \ - "not cx" /* First we have to strlen(str), prepare -1 as max length */ \ - "xor al, al" /* The '\0' that we're searching for */ \ - "cld" \ - "repne scas byte ptr es:[di]" /* afterwards, cx = -(len+2) */ \ - "not cx" /* cx = (len+1) */ \ - "dec cx" /* cx = len */ \ - "mov dx, 0x504" /* And now we can write the string */ \ - "rep outs dx, byte ptr es:[si]" \ - __parm [es si] \ - __modify [ax cx dx si di] +/** Actually send a request to the VirtualBox VMM device. + * @param addr 32-bit physical address containing the VMMDevRequest struct. + */ +static void vbox_send_request(uint16_t iobase, uint32_t addr); +#pragma aux vbox_send_request = \ + "push eax" /* Preserve 32-bit register, specifically the higher word. */ \ + "push bx" /* Combine bx:ax into single 32-bit eax */ \ + "push ax" \ + "pop eax" \ + "out dx, eax" \ + "pop eax" \ + __parm [dx] [bx ax] \ + __modify [dx] + +extern int vbox_init(LPVBOXCOMM vb); + +/** Lets VirtualBox know that there are VirtualBox Guest Additions on this guest. + * @param osType os installed on this guest. */ +static inline int vbox_report_guest_info(LPVBOXCOMM vb, uint32_t osType) +{ + VMMDevReportGuestInfo __far *req = (void __far *) vb->buf; + + bzero(req, sizeof(VMMDevReportGuestInfo)); + + req->header.size = sizeof(VMMDevReportGuestInfo); + req->header.version = VMMDEV_REQUEST_HEADER_VERSION; + req->header.requestType = VMMDevReq_ReportGuestInfo; + req->header.rc = -1; + req->guestInfo.interfaceVersion = VMMDEV_VERSION; + req->guestInfo.osType = osType; + + vbox_send_request(vb->iobase, vb->buf_physaddr); + + return req->header.rc; +} + +/** Tells VirtualBox whether we want absolute mouse information or not. */ +static inline int vbox_set_mouse(LPVBOXCOMM vb, bool absolute, bool pointer) +{ + VMMDevReqMouseStatus __far *req = (void __far *) vb->buf; + + bzero(req, sizeof(VMMDevReqMouseStatus)); + + req->header.size = sizeof(VMMDevReqMouseStatus); + req->header.version = VMMDEV_REQUEST_HEADER_VERSION; + req->header.requestType = VMMDevReq_SetMouseStatus; + req->header.rc = -1; + if (absolute) req->mouseFeatures |= VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE; + if (pointer) req->mouseFeatures |= VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR; + + vbox_send_request(vb->iobase, vb->buf_physaddr); + + return req->header.rc; +} + +/** Gets the current absolute mouse position from VirtualBox. + * @param abs false if user has disabled mouse integration in VirtualBox, + * in which case we should fallback to PS/2 relative events. */ +static inline int vbox_get_mouse(LPVBOXCOMM vb, bool *abs, + uint16_t *xpos, uint16_t *ypos) +{ + VMMDevReqMouseStatus __far *req = (void __far *) vb->buf; + + bzero(req, sizeof(VMMDevReqMouseStatus)); + + req->header.size = sizeof(VMMDevReqMouseStatus); + req->header.version = VMMDEV_REQUEST_HEADER_VERSION; + req->header.requestType = VMMDevReq_GetMouseStatus; + req->header.rc = -1; + + vbox_send_request(vb->iobase, vb->buf_physaddr); + + *abs = req->mouseFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE; + *xpos = req->pointerXPos; + *ypos = req->pointerYPos; + + return req->header.rc; +} + +/** @todo */ +static inline int vbox_set_pointer_visible(LPVBOXCOMM vb, bool visible) +{ + VMMDevReqMousePointer __far *req = (void __far *) vb->buf; + + bzero(req, sizeof(VMMDevReqMousePointer)); + + req->header.size = sizeof(VMMDevReqMousePointer); + req->header.version = VMMDEV_REQUEST_HEADER_VERSION; + req->header.requestType = VMMDevReq_SetPointerShape; + req->header.rc = -1; + + if (visible) req->fFlags |= VBOX_MOUSE_POINTER_VISIBLE; + + vbox_send_request(vb->iobase, vb->buf_physaddr); -/** Logs a single character followed by '\n' to force log flush. - * A life-saver when there is no data segment available. */ -#define vbox_putc(c) do { \ - vbox_logc(c); vbox_logc('\n'); \ - } while (0); + return req->header.rc; +} -extern int vbox_init(void); +static inline unsigned vbox_pointer_shape_data_size(unsigned width, unsigned height) +{ + //unsigned base_size = 24 + 20; + unsigned and_mask_size = (width + 7) / 8 * height; + unsigned xor_mask_size = width * height * 4; + return ((and_mask_size + 3) & ~3) + xor_mask_size; +} -extern int vbox_alloc_buffers(void); -extern int vbox_free_buffers(void); +static inline int vbox_set_pointer_shape(LPVBOXCOMM vb, + uint16_t xHot, uint16_t yHot, + uint16_t width, uint16_t height, + char __far *data) +{ + VMMDevReqMousePointer __far *req = (void __far *) vb->buf; + unsigned data_size = vbox_pointer_shape_data_size(width, height); + unsigned full_size = MAX(sizeof(VMMDevReqMousePointer), 24 + 20 + data_size); -extern int vbox_report_guest_info(uint32_t osType); + if (full_size >= VBOX_BUFFER_SIZE) { + return -2; + } -extern int vbox_set_filter_mask(uint32_t add, uint32_t remove); + bzero(req, full_size); -extern int vbox_set_mouse(bool enable); + req->header.size = full_size; + req->header.version = VMMDEV_REQUEST_HEADER_VERSION; + req->header.requestType = VMMDevReq_SetPointerShape; + req->header.rc = -1; -extern int vbox_get_mouse(bool *abs, uint16_t *xpos, uint16_t *ypos); + req->fFlags = VBOX_MOUSE_POINTER_SHAPE; + req->xHot = xHot; + req->yHot = yHot; + req->width = width; + req->height = height; -// In CALLBACKS segment: + ffmemcpy(req->pointerData, data, data_size); -extern int vbox_set_mouse_locked(bool enable); + vbox_send_request(vb->iobase, vb->buf_physaddr); -extern int vbox_get_mouse_locked(bool *abs, uint16_t *xpos, uint16_t *ypos); + return req->header.rc; +} #endif |