1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-06 00:13:33 +00:00

Added MacOS KVM files

This commit is contained in:
Bryan Roe
2019-01-11 10:58:46 -08:00
parent e040b11c70
commit a0f146b38d
6 changed files with 1912 additions and 0 deletions

View File

@@ -0,0 +1,257 @@
#include "mac_events.h"
#include <assert.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include <string.h>
static const int g_keymapLen = 114; // Modify this when you change anything in g_keymap.
static int g_capsLock = 0;
static int g_lMouseDown = 0;
static int g_rMouseDown = 0;
static struct keymap_t g_keymap[] = {
{ kVK_Space, VK_SPACE },
{ kVK_CapsLock, VK_CAPITAL },
{ kVK_ANSI_Q, VK_Q },
{ kVK_ANSI_W, VK_W },
{ kVK_ANSI_E, VK_E },
{ kVK_ANSI_R, VK_R },
{ kVK_ANSI_T, VK_T },
{ kVK_ANSI_Y, VK_Y },
{ kVK_ANSI_U, VK_U },
{ kVK_ANSI_I, VK_I },
{ kVK_ANSI_O, VK_O },
{ kVK_ANSI_P, VK_P },
{ kVK_ANSI_A, VK_A },
{ kVK_ANSI_S, VK_S },
{ kVK_ANSI_D, VK_D },
{ kVK_ANSI_F, VK_F },
{ kVK_ANSI_G, VK_G },
{ kVK_ANSI_H, VK_H },
{ kVK_ANSI_J, VK_J },
{ kVK_ANSI_K, VK_K },
{ kVK_ANSI_L, VK_L },
{ kVK_ANSI_Z, VK_Z },
{ kVK_ANSI_X, VK_X },
{ kVK_ANSI_C, VK_C },
{ kVK_ANSI_V, VK_V },
{ kVK_ANSI_B, VK_B },
{ kVK_ANSI_N, VK_N },
{ kVK_ANSI_M, VK_M },
{ kVK_ANSI_1, VK_1 },
{ kVK_ANSI_2, VK_2 },
{ kVK_ANSI_3, VK_3 },
{ kVK_ANSI_4, VK_4 },
{ kVK_ANSI_5, VK_5 },
{ kVK_ANSI_6, VK_6 },
{ kVK_ANSI_7, VK_7 },
{ kVK_ANSI_8, VK_8 },
{ kVK_ANSI_9, VK_9 },
{ kVK_ANSI_0, VK_0 },
{ kVK_Delete, VK_BACK },
{ kVK_Tab, VK_TAB },
{ kVK_ANSI_KeypadClear, VK_CLEAR },
{ kVK_Return, VK_RETURN },
{ kVK_Help, VK_PAUSE },
{ kVK_Escape, VK_ESCAPE },
{ kVK_ForwardDelete, VK_DELETE },
{ kVK_Home, VK_HOME },
{ kVK_LeftArrow, VK_LEFT },
{ kVK_UpArrow, VK_UP },
{ kVK_RightArrow, VK_RIGHT },
{ kVK_DownArrow, VK_DOWN },
{ kVK_PageUp, VK_PRIOR },
{ kVK_PageDown, VK_NEXT },
{ kVK_End, VK_END },
{ kVK_Help, VK_SELECT },
{ kVK_Help, VK_SNAPSHOT },
{ kVK_Help, VK_EXECUTE },
{ kVK_Help, VK_INSERT },
{ kVK_Help, VK_HELP },
{ kVK_Escape, VK_CANCEL },
{ kVK_F1, VK_F1 },
{ kVK_F2, VK_F2 },
{ kVK_F3, VK_F3 },
{ kVK_F4, VK_F4 },
{ kVK_F5, VK_F5 },
{ kVK_F6, VK_F6 },
{ kVK_F7, VK_F7 },
{ kVK_F8, VK_F8 },
{ kVK_F9, VK_F9 },
{ kVK_F10, VK_F10 },
{ kVK_F11, VK_F11 },
{ kVK_F12, VK_F12 },
{ kVK_F13, VK_F13 },
{ kVK_F14, VK_F14 },
{ kVK_F15, VK_F15 },
{ kVK_F16, VK_F16 },
{ kVK_F17, VK_F17 },
{ kVK_F18, VK_F18 },
{ kVK_F19, VK_F19 },
{ kVK_F20, VK_F20 },
{ kVK_Home, VK_HOME },
{ kVK_ANSI_KeypadMultiply, VK_MULTIPLY },
{ kVK_ANSI_Equal, VK_ADD },
{ kVK_ANSI_Comma, VK_SEPARATOR },
{ kVK_ANSI_Minus, VK_SUBTRACT },
{ kVK_ANSI_KeypadDecimal, VK_DECIMAL },
{ kVK_ANSI_KeypadDivide, VK_DIVIDE },
{ kVK_ANSI_Keypad0, VK_NUMPAD0 },
{ kVK_ANSI_Keypad1, VK_NUMPAD1 },
{ kVK_ANSI_Keypad2, VK_NUMPAD2 },
{ kVK_ANSI_Keypad3, VK_NUMPAD3 },
{ kVK_ANSI_Keypad4, VK_NUMPAD4 },
{ kVK_ANSI_Keypad5, VK_NUMPAD5 },
{ kVK_ANSI_Keypad6, VK_NUMPAD6 },
{ kVK_ANSI_Keypad7, VK_NUMPAD7 },
{ kVK_ANSI_Keypad8, VK_NUMPAD8 },
{ kVK_ANSI_Keypad9, VK_NUMPAD9 },
{ kVK_Shift, VK_SHIFT },
{ kVK_Control, VK_CONTROL },
{ kVK_Option, VK_MENU },
{ kVK_Command, VK_RWIN },
{ kVK_Command, VK_LWIN },
{ kVK_Option, VK_APPS },
{ kVK_JIS_Kana, VK_KANA },
{ kVK_ANSI_Semicolon, VK_OEM_1 },
{ kVK_ANSI_Equal, VK_OEM_PLUS },
{ kVK_ANSI_Comma, VK_OEM_COMMA },
{ kVK_ANSI_Minus, VK_OEM_MINUS },
{ kVK_ANSI_Period, VK_OEM_PERIOD },
{ kVK_ANSI_Slash, VK_OEM_2 },
{ kVK_ANSI_Grave, VK_OEM_3 },
{ kVK_ANSI_LeftBracket, VK_OEM_4 },
{ kVK_ANSI_Backslash, VK_OEM_5 },
{ kVK_ANSI_RightBracket, VK_OEM_6 },
{ kVK_ANSI_Quote, VK_OEM_7 }
};
char* getCurrentSession() {
SCDynamicStoreRef store;
CFStringRef name;
uid_t uid;
char *buf;
Boolean ok;
buf = (char *)malloc (BUFSIZ);
store = SCDynamicStoreCreate(NULL, CFSTR("GetConsoleUser"), NULL, NULL);
assert(store != NULL);
name = SCDynamicStoreCopyConsoleUser(store, &uid, NULL);
CFRelease(store);
if (name != NULL) {
ok = CFStringGetCString(name, buf, BUFSIZ, kCFStringEncodingUTF8);
assert(ok == true);
CFRelease(name);
} else {
strcpy(buf, "<none>");
}
return buf;
}
void MouseAction(double absX, double absY, int button, short wheel)
{
CGPoint curPos;
CGEventRef e;
CGEventType event;
CGEventSourceRef source;
curPos.x = absX;
curPos.y = absY;
source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
if (g_lMouseDown || g_rMouseDown) {
event = g_lMouseDown ? kCGEventLeftMouseDragged : kCGEventRightMouseDragged;
e = CGEventCreateMouseEvent(source, event, curPos, 1);
CGEventPost(kCGHIDEventTap, e);
CGEventPost(kCGSessionEventTap, e);
CFRelease(e);
}
else {
CGWarpMouseCursorPosition (curPos);
}
if (button != 0) {
switch (button) {
case MOUSEEVENTF_LEFTDOWN:
event = kCGEventLeftMouseDown;
g_lMouseDown = 1;
break;
case MOUSEEVENTF_RIGHTDOWN:
g_rMouseDown = 1;
event = kCGEventRightMouseDown;
break;
case MOUSEEVENTF_LEFTUP:
g_lMouseDown = 0;
event = kCGEventLeftMouseUp;
break;
case MOUSEEVENTF_RIGHTUP:
g_rMouseDown = 0;
event = kCGEventRightMouseUp;
break;
default:
break;
}
/*
if (!strcmp(getCurrentSession(), "<none>"))
{
// This call is deprecated in OSX 10.6
CGPostMouseEvent(curPos, TRUE, 3, (event == kCGEventLeftMouseDown) ? TRUE : FALSE, (event == kCGEventRightMouseDown) ? TRUE : FALSE, FALSE); // mouse down
}
else
{
*/
e = CGEventCreateMouseEvent(source, event, curPos, 1);
CGEventPost(kCGHIDEventTap, e);
CFRelease(e);
/*
}
*/
}
else if (wheel != 0)
{
e = CGEventCreateScrollWheelEvent(source, kCGScrollEventUnitPixel, 1, wheel);
CGEventPost(kCGHIDEventTap, e);
CFRelease(e);
}
if (source != NULL) CFRelease(source);
}
void KeyAction(unsigned char vk, int up) {
int i;
CGKeyCode keycode;
CGEventSourceRef source;
source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
for (i = 0 ; i < g_keymapLen; i++) {
if (g_keymap[i].vk == vk) {
keycode = g_keymap[i].keycode;
break;
}
}
if (i == g_keymapLen) { return; }
if (vk == VK_CAPITAL && up) { g_capsLock = g_capsLock ? 0 : 1; }
/*
if (!strcmp(getCurrentSession(), "<none>")) {
// This call is deprecated in OSX 10.6
CGPostKeyboardEvent(0, keycode, !up);
}
else
{
*/
CGEventRef key = CGEventCreateKeyboardEvent(source, keycode, !up);
if (g_capsLock) { CGEventSetFlags(key, kCGEventFlagMaskAlphaShift); }
CGEventPost(kCGHIDEventTap, key);
CFRelease(key);
/*
}
*/
if (source != NULL) CFRelease(source);
}

View File

@@ -0,0 +1,380 @@
/*
* linux_events.h
*
* Created on: Jul 8, 2011
* Author: Intel
*/
#ifndef LINUX_EVENTS_H_
#define LINUX_EVENTS_H_
#include <Carbon/Carbon.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
enum MOUSE_EVENTS {
MOUSEEVENTF_LEFTDOWN = 0x0002,
MOUSEEVENTF_RIGHTDOWN = 0x0008,
MOUSEEVENTF_MIDDLEDOWN = 0x0020,
MOUSEEVENTF_LEFTUP = 0x0004,
MOUSEEVENTF_RIGHTUP = 0x0010,
MOUSEEVENTF_MIDDLEUP = 0x0040
};
// VK_LBUTTON (01) Left mouse button
#define VK_LBUTTON 0x01
// VK_RBUTTON (02) Right mouse button
#define VK_RBUTTON 0x02
// VK_CANCEL (03) Control-break processing
#define VK_CANCEL 0x03
// VK_MBUTTON (04) Middle mouse button (three-button mouse)
#define VK_MBUTTON 0x04
// VK_XBUTTON1 (05)
#define VK_XBUTTON1 0x05
// VK_XBUTTON2 (06)
#define VK_XBUTTON2 0x06
// VK_BACK (08) BACKSPACE key
#define VK_BACK 0x08
// VK_TAB (09) TAB key
#define VK_TAB 0x09
// VK_CLEAR (0C) CLEAR key
#define VK_CLEAR 0x0C
// VK_RETURN (0D)
#define VK_RETURN 0x0D
// VK_SHIFT (10) SHIFT key
#define VK_SHIFT 0x10
// VK_CONTROL (11) CTRL key
#define VK_CONTROL 0x11
// VK_MENU (12) ALT key
#define VK_MENU 0x12
// VK_PAUSE (13) PAUSE key
#define VK_PAUSE 0x13
// VK_CAPITAL (14) CAPS LOCK key
#define VK_CAPITAL 0x14
// VK_KANA (15) Input Method Editor (IME) Kana mode
#define VK_KANA 0x15
// VK_HANGUEL (15) IME Hanguel mode (maintained for compatibility; use VK_HANGUL)
// VK_HANGUL (15) IME Hangul mode
#define VK_HANGUL 0x15
// VK_JUNJA (17) IME Junja mode
#define VK_JUNJA 0x17
// VK_FINAL (18) IME final mode
#define VK_FINAL 0x18
// VK_HANJA (19) IME Hanja mode
#define VK_HANJA 0x19
// VK_KANJI (19) IME Kanji mode
#define VK_KANJI 0x19
// VK_ESCAPE (1B) ESC key
#define VK_ESCAPE 0x1B
// VK_CONVERT (1C) IME convert
#define VK_CONVERT 0x1C
// VK_NONCONVERT (1D) IME nonconvert
#define VK_NONCONVERT 0x1D
// VK_ACCEPT (1E) IME accept
#define VK_ACCEPT 0x1E
// VK_MODECHANGE (1F) IME mode change request
#define VK_MODECHANGE 0x1F
// VK_SPACE (20) SPACEBAR
#define VK_SPACE 0x20
// VK_PRIOR (21) PAGE UP key
#define VK_PRIOR 0x21
// VK_NEXT (22) PAGE DOWN key
#define VK_NEXT 0x22
// VK_END (23) END key
#define VK_END 0x23
// VK_HOME (24) HOME key
#define VK_HOME 0x24
// VK_LEFT (25) LEFT ARROW key
#define VK_LEFT 0x25
// VK_UP (26) UP ARROW key
#define VK_UP 0x26
// VK_RIGHT (27) RIGHT ARROW key
#define VK_RIGHT 0x27
// VK_DOWN (28) DOWN ARROW key
#define VK_DOWN 0x28
// VK_SELECT (29) SELECT key
#define VK_SELECT 0x29
// VK_PRINT (2A) PRINT key
#define VK_PRINT 0x2A
// VK_EXECUTE (2B) EXECUTE key
#define VK_EXECUTE 0x2B
// VK_SNAPSHOT (2C) PRINT SCREEN key
#define VK_SNAPSHOT 0x2C
// VK_INSERT (2D) INS key
#define VK_INSERT 0x2D
// VK_DELETE (2E) DEL key
#define VK_DELETE 0x2E
// VK_HELP (2F) HELP key
#define VK_HELP 0x2F
// (30) 0 key
#define VK_0 0x30
// (31) 1 key
#define VK_1 0x31
// (32) 2 key
#define VK_2 0x32
// (33) 3 key
#define VK_3 0x33
// (34) 4 key
#define VK_4 0x34
// (35) 5 key;
#define VK_5 0x35
// (36) 6 key
#define VK_6 0x36
// (37) 7 key
#define VK_7 0x37
// (38) 8 key
#define VK_8 0x38
// (39) 9 key
#define VK_9 0x39
// (41) A key
#define VK_A 0x41
// (42) B key
#define VK_B 0x42
// (43) C key
#define VK_C 0x43
// (44) D key
#define VK_D 0x44
// (45) E key
#define VK_E 0x45
// (46) F key
#define VK_F 0x46
// (47) G key
#define VK_G 0x47
// (48) H key
#define VK_H 0x48
// (49) I key
#define VK_I 0x49
// (4A) J key
#define VK_J 0x4A
// (4B) K key
#define VK_K 0x4B
// (4C) L key
#define VK_L 0x4C
// (4D) M key
#define VK_M 0x4D
// (4E) N key
#define VK_N 0x4E
// (4F) O key
#define VK_O 0x4F
// (50) P key
#define VK_P 0x50
// (51) Q key
#define VK_Q 0x51
// (52) R key
#define VK_R 0x52
// (53) S key
#define VK_S 0x53
// (54) T key
#define VK_T 0x54
// (55) U key
#define VK_U 0x55
// (56) V key
#define VK_V 0x56
// (57) W key
#define VK_W 0x57
// (58) X key
#define VK_X 0x58
// (59) Y key
#define VK_Y 0x59
// (5A) Z key
#define VK_Z 0x5A
// VK_LWIN (5B) Left Windows key (Microsoft Natural keyboard)
#define VK_LWIN 0x5B
// VK_RWIN (5C) Right Windows key (Natural keyboard)
#define VK_RWIN 0x5C
// VK_APPS (5D) Applications key (Natural keyboard)
#define VK_APPS 0x5D
// VK_SLEEP (5F) Computer Sleep key
#define VK_SLEEP 0x5F
// VK_NUMPAD0 (60) Numeric keypad 0 key
#define VK_NUMPAD0 0x60
// VK_NUMPAD1 (61) Numeric keypad 1 key
#define VK_NUMPAD1 0x61
// VK_NUMPAD2 (62) Numeric keypad 2 key
#define VK_NUMPAD2 0x62
// VK_NUMPAD3 (63) Numeric keypad 3 key
#define VK_NUMPAD3 0x63
// VK_NUMPAD4 (64) Numeric keypad 4 key
#define VK_NUMPAD4 0x64
// VK_NUMPAD5 (65) Numeric keypad 5 key
#define VK_NUMPAD5 0x65
// VK_NUMPAD6 (66) Numeric keypad 6 key
#define VK_NUMPAD6 0x66
// VK_NUMPAD7 (67) Numeric keypad 7 key
#define VK_NUMPAD7 0x67
// VK_NUMPAD8 (68) Numeric keypad 8 key
#define VK_NUMPAD8 0x68
// VK_NUMPAD9 (69) Numeric keypad 9 key
#define VK_NUMPAD9 0x69
// VK_MULTIPLY (6A) Multiply key
#define VK_MULTIPLY 0x6A
// VK_ADD (6B) Add key
#define VK_ADD 0x6B
// VK_SEPARATOR (6C) Separator key
#define VK_SEPARATOR 0x6C
// VK_SUBTRACT (6D) Subtract key
#define VK_SUBTRACT 0x6D
// VK_DECIMAL (6E) Decimal key
#define VK_DECIMAL 0x6E
// VK_DIVIDE (6F) Divide key
#define VK_DIVIDE 0x6F
// VK_F1 (70) F1 key
#define VK_F1 0x70
// VK_F2 (71) F2 key
#define VK_F2 0x71
// VK_F3 (72) F3 key
#define VK_F3 0x72
// VK_F4 (73) F4 key
#define VK_F4 0x73
// VK_F5 (74) F5 key
#define VK_F5 0x74
// VK_F6 (75) F6 key
#define VK_F6 0x75
// VK_F7 (76) F7 key
#define VK_F7 0x76
// VK_F8 (77) F8 key
#define VK_F8 0x77
// VK_F9 (78) F9 key
#define VK_F9 0x78
// VK_F10 (79) F10 key
#define VK_F10 0x79
// VK_F11 (7A) F11 key
#define VK_F11 0x7A
// VK_F12 (7B) F12 key
#define VK_F12 0x7B
// VK_F13 (7C) F13 key
#define VK_F13 0x7C
// VK_F14 (7D) F14 key
#define VK_F14 0x7D
// VK_F15 (7E) F15 key
#define VK_F15 0x7E
// VK_F16 (7F) F16 key
#define VK_F16 0x7F
// VK_F17 (80H) F17 key
#define VK_F17 0x80
// VK_F18 (81H) F18 key
#define VK_F18 0x81
// VK_F19 (82H) F19 key
#define VK_F19 0x82
// VK_F20 (83H) F20 key
#define VK_F20 0x83
// VK_F21 (84H) F21 key
#define VK_F21 0x84
// VK_F22 (85H) F22 key
#define VK_F22 0x85
// VK_F23 (86H) F23 key
#define VK_F23 0x86
// VK_F24 (87H) F24 key
#define VK_F24 0x87
// VK_NUMLOCK (90) NUM LOCK key
#define VK_NUMLOCK 0x90
// VK_SCROLL (91) SCROLL LOCK key
#define VK_SCROLL 0x91
// VK_LSHIFT (A0) Left SHIFT key
#define VK_LSHIFT 0xA0
// VK_RSHIFT (A1) Right SHIFT key
#define VK_RSHIFT 0xA1
// VK_LCONTROL (A2) Left CONTROL key
#define VK_LCONTROL 0xA2
// VK_RCONTROL (A3) Right CONTROL key
#define VK_RCONTROL 0xA3
// VK_LMENU (A4) Left MENU key
#define VK_LMENU 0xA4
// VK_RMENU (A5) Right MENU key
#define VK_RMENU 0xA5
// VK_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key
#define VK_BROWSER_BACK 0xA6
// VK_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key
#define VK_BROWSER_FORWARD 0xA7
// VK_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key
#define VK_BROWSER_REFRESH 0xA8
// VK_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key
#define VK_BROWSER_STOP 0xA9
// VK_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key
#define VK_BROWSER_SEARCH 0xAA
// VK_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key
#define VK_BROWSER_FAVORITES 0xAB
// VK_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key
#define VK_BROWSER_HOME 0xAC
// VK_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key
#define VK_VOLUME_MUTE 0xAD
// VK_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key
#define VK_VOLUME_DOWN 0xAE
// VK_VOLUME_UP (AF) Windows 2000/XP: Volume Up key
#define VK_VOLUME_UP 0xAF
// VK_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key
#define VK_MEDIA_NEXT_TRACK 0xB0
// VK_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key
#define VK_MEDIA_PREV_TRACK 0xB1
// VK_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key
#define VK_MEDIA_STOP 0xB2
// VK_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key
#define VK_MEDIA_PLAY_PAUSE 0xB3
// VK_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key
#define VK_MEDIA_LAUNCH_MAIL 0xB4
// VK_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key
#define VK_MEDIA_LAUNCH_MEDIA_SELECT 0xB5
// VK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key
#define VK_MEDIA_LAUNCH_APP1 0xB6
// VK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key
#define VK_MEDIA_LAUNCH_APP2 0xB7
// VK_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key
#define VK_OEM_1 0xBA
// VK_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key
#define VK_OEM_PLUS 0xBB
// VK_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key
#define VK_OEM_COMMA 0xBC
// VK_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key
#define VK_OEM_MINUS 0xBD
// VK_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key
#define VK_OEM_PERIOD 0xBE
// VK_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key
#define VK_OEM_2 0xBF
// VK_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key
#define VK_OEM_3 0xC0
// VK_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key
#define VK_OEM_4 0xDB
// VK_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key
#define VK_OEM_5 0xDC
// VK_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key
#define VK_OEM_6 0xDD
// VK_OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key
#define VK_OEM_7 0xDE
// VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard.
#define VK_OEM_8 0xDF
// VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
#define VK_OEM_102 0xE2
// VK_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
#define VK_PROCESSKEY 0xE5
// VK_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP
#define VK_PACKET 0xE7
// VK_ATTN (F6) Attn key
#define VK_ATTN 0xF6
// VK_CRSEL (F7) CrSel key
#define VK_CRSEL 0xF7
// VK_EXSEL (F8) ExSel key
#define VK_EXSEL 0xF8
// VK_EREOF (F9) Erase EOF key
#define VK_EREOF 0xF9
// VK_PLAY (FA) Play key
#define VK_PLAY 0xFA
// VK_ZOOM (FB) Zoom key
#define VK_ZOOM 0xFB
// VK_NONAME (FC) Reserved for future use
#define VK_NONAME 0xFC
// VK_PA1 (FD) PA1 key
#define VK_PA1 0xFD
// VK_OEM_CLEAR (FE) Clear key
#define VK_OEM_CLEAR 0xFE
#define VK_UNKNOWN 0
struct keymap_t {
unsigned int keycode;
unsigned char vk;
};
extern void MouseAction(double absX, double absY, int button, short wheel);
extern void KeyAction(unsigned char vk, int up);
#endif /* LINUX_EVENTS_H_ */

View File

@@ -0,0 +1,691 @@
/*
Copyright 2010 - 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "mac_kvm.h"
#include "../../meshdefines.h"
#include "../../meshinfo.h"
#include "../../../microstack/ILibParsers.h"
#include "../../../microstack/ILibAsyncSocket.h"
#include "../../../microstack/ILibAsyncServerSocket.h"
#include "../../../microstack/ILibProcessPipe.h"
#include <CoreFoundation/CoreFoundation.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
int KVM_Listener_FD = -1;
#define KVM_Listener_Path "/usr/local/mesh_services/mesh2/kvm"
int KVM_AGENT_FD = -1;
int KVM_SEND(char *buffer, int bufferLen)
{
int retVal = -1;
retVal = write(KVM_AGENT_FD == -1 ? STDOUT_FILENO : KVM_AGENT_FD, buffer, bufferLen);
if (KVM_AGENT_FD == -1) { fsync(STDOUT_FILENO); }
else
{
if (retVal < 0)
{
char tmp[255];
int tmpLen = sprintf_s(tmp, sizeof(tmp), "Write Error: %d on %d\n", errno, KVM_AGENT_FD);
write(STDOUT_FILENO, tmp, tmpLen);
fsync(STDOUT_FILENO);
}
}
return(retVal);
}
CGDirectDisplayID SCREEN_NUM = 0;
int SH_HANDLE = 0;
int SCREEN_WIDTH = 0;
int SCREEN_HEIGHT = 0;
int SCREEN_DEPTH = 0;
int TILE_WIDTH = 0;
int TILE_HEIGHT = 0;
int TILE_WIDTH_COUNT = 0;
int TILE_HEIGHT_COUNT = 0;
int COMPRESSION_RATIO = 0;
int FRAME_RATE_TIMER = 0;
struct tileInfo_t **g_tileInfo = NULL;
int g_remotepause = 0;
int g_pause = 0;
int g_shutdown = 0;
int g_resetipc = 0;
int kvm_clientProcessId = 0;
int g_restartcount = 0;
int g_totalRestartCount = 0;
int restartKvm = 0;
extern void* tilebuffer;
pid_t g_slavekvm = 0;
pthread_t kvmthread = (pthread_t)NULL;
ILibProcessPipe_Process gChildProcess;
//int logenabled = 1;
//FILE *logfile = NULL;
//#define MASTERLOGFILE "/dev/null"
//#define SLAVELOGFILE "/dev/null"
//#define LOGFILE "/dev/null"
#define KvmDebugLog(...)
//#define KvmDebugLog(...) printf(__VA_ARGS__); //if (logfile != NULL) fprintf(logfile, __VA_ARGS__);
//#define KvmDebugLog(x) if (logenabled) printf(x);
//#define KvmDebugLog(x) if (logenabled) fprintf(logfile, "Writing from slave in kvm_send_resolution\n");
void senddebug(int val)
{
char buffer[8];
((unsigned short*)buffer)[0] = (unsigned short)htons((unsigned short)MNG_DEBUG); // Write the type
((unsigned short*)buffer)[1] = (unsigned short)htons((unsigned short)8); // Write the size
((int*)buffer)[1] = val;
KVM_SEND(buffer, 8);
}
void kvm_send_resolution()
{
char buffer[8];
((unsigned short*)buffer)[0] = (unsigned short)htons((unsigned short)MNG_KVM_SCREEN); // Write the type
((unsigned short*)buffer)[1] = (unsigned short)htons((unsigned short)8); // Write the size
((unsigned short*)buffer)[2] = (unsigned short)htons((unsigned short)SCREEN_WIDTH); // X position
((unsigned short*)buffer)[3] = (unsigned short)htons((unsigned short)SCREEN_HEIGHT); // Y position
// Write the reply to the pipe.
KVM_SEND(buffer, 8);
}
#define BUFSIZE 65535
int kvm_init()
{
int old_height_count = TILE_HEIGHT_COUNT;
SCREEN_NUM = CGMainDisplayID();
SCREEN_HEIGHT = CGDisplayPixelsHigh(SCREEN_NUM);
SCREEN_WIDTH = CGDisplayPixelsWide(SCREEN_NUM);
// Some magic numbers.
TILE_WIDTH = 32;
TILE_HEIGHT = 32;
COMPRESSION_RATIO = 50;
FRAME_RATE_TIMER = 100;
TILE_HEIGHT_COUNT = SCREEN_HEIGHT / TILE_HEIGHT;
TILE_WIDTH_COUNT = SCREEN_WIDTH / TILE_WIDTH;
if (SCREEN_WIDTH % TILE_WIDTH) { TILE_WIDTH_COUNT++; }
if (SCREEN_HEIGHT % TILE_HEIGHT) { TILE_HEIGHT_COUNT++; }
kvm_send_resolution();
reset_tile_info(old_height_count);
return 0;
}
// void CheckDesktopSwitch(int checkres) { return; }
int kvm_server_inputdata(char* block, int blocklen)
{
unsigned short type, size;
//CheckDesktopSwitch(0);
//senddebug(100+blocklen);
// Decode the block header
if (blocklen < 4) return 0;
type = ntohs(((unsigned short*)(block))[0]);
size = ntohs(((unsigned short*)(block))[1]);
if (size > blocklen) return 0;
switch (type)
{
case MNG_KVM_KEY: // Key
{
if (size != 6 || KVM_AGENT_FD != -1) { break; }
KeyAction(block[5], block[4]);
break;
}
case MNG_KVM_MOUSE: // Mouse
{
int x, y;
short w = 0;
if (KVM_AGENT_FD != -1) { break; }
if (size == 10 || size == 12)
{
x = ((int)ntohs(((unsigned short*)(block))[3]));
y = ((int)ntohs(((unsigned short*)(block))[4]));
if (size == 12) w = ((short)ntohs(((short*)(block))[5]));
//printf("x:%d, y:%d, b:%d, w:%d\n", x, y, block[5], w);
MouseAction(x, y, block[5], w);
}
break;
}
case MNG_KVM_COMPRESSION: // Compression
{
if (size != 6) break;
set_tile_compression((int)block[4], (int)block[5]);
COMPRESSION_RATIO = 100;
break;
}
case MNG_KVM_REFRESH: // Refresh
{
int row, col;
if (size != 4) break;
if (g_tileInfo == NULL) {
if ((g_tileInfo = (struct tileInfo_t **) malloc(TILE_HEIGHT_COUNT * sizeof(struct tileInfo_t *))) == NULL) ILIBCRITICALEXIT(254);
for (row = 0; row < TILE_HEIGHT_COUNT; row++) {
if ((g_tileInfo[row] = (struct tileInfo_t *) malloc(TILE_WIDTH_COUNT * sizeof(struct tileInfo_t))) == NULL) ILIBCRITICALEXIT(254);
}
}
for (row = 0; row < TILE_HEIGHT_COUNT; row++) {
for (col = 0; col < TILE_WIDTH_COUNT; col++) {
g_tileInfo[row][col].crc = 0xFF;
g_tileInfo[row][col].flag = 0;
}
}
break;
}
case MNG_KVM_PAUSE: // Pause
{
if (size != 5) break;
g_remotepause = block[4];
break;
}
case MNG_KVM_FRAME_RATE_TIMER:
{
//int fr = ((int)ntohs(((unsigned short*)(block))[2]));
//if (fr > 20 && fr < 2000) FRAME_RATE_TIMER = fr;
break;
}
}
return size;
}
int kvm_relay_feeddata(char* buf, int len)
{
ILibProcessPipe_Process_WriteStdIn(gChildProcess, buf, len, ILibTransport_MemoryOwnership_USER);
return(len);
}
// Set the KVM pause state
void kvm_pause(int pause)
{
g_pause = pause;
}
void* kvm_mainloopinput(void* param)
{
int ptr = 0;
int ptr2 = 0;
int len = 0;
char* pchRequest2[30000];
int cbBytesRead = 0;
char tmp[255];
int tmpLen;
if (KVM_AGENT_FD == -1)
{
int flags;
flags = fcntl(STDIN_FILENO, F_GETFL, 0);
if (fcntl(STDIN_FILENO, F_SETFL, (O_NONBLOCK | flags) ^ O_NONBLOCK) == -1) { senddebug(-999); }
}
while (!g_shutdown)
{
if (KVM_AGENT_FD != -1)
{
tmpLen = sprintf_s(tmp, sizeof(tmp), "About to read from IPC Socket\n");
write(STDOUT_FILENO, tmp, tmpLen);
fsync(STDOUT_FILENO);
}
KvmDebugLog("Reading from master in kvm_mainloopinput\n");
cbBytesRead = read(KVM_AGENT_FD == -1 ? STDIN_FILENO: KVM_AGENT_FD, pchRequest2 + len, 30000 - len);
KvmDebugLog("Read %d bytes from master in kvm_mainloopinput\n", cbBytesRead);
if (KVM_AGENT_FD != -1)
{
tmpLen = sprintf_s(tmp, sizeof(tmp), "Read %d bytes from IPC-xx-Socket\n", cbBytesRead);
write(STDOUT_FILENO, tmp, tmpLen);
fsync(STDOUT_FILENO);
}
if (cbBytesRead == -1 || cbBytesRead == 0)
{
/*ILIBMESSAGE("KVMBREAK-K1\r\n"); g_shutdown = 1; printf("shutdown\n");*/
if (KVM_AGENT_FD == -1)
{
g_shutdown = 1;
}
else
{
g_resetipc = 1;
}
break;
}
len += cbBytesRead;
ptr2 = 0;
if (KVM_AGENT_FD != -1)
{
tmpLen = sprintf_s(tmp, sizeof(tmp), "enter while\n");
write(STDOUT_FILENO, tmp, tmpLen);
fsync(STDOUT_FILENO);
}
while ((ptr2 = kvm_server_inputdata((char*)pchRequest2 + ptr, cbBytesRead - ptr)) != 0) { ptr += ptr2; }
if (KVM_AGENT_FD != -1)
{
tmpLen = sprintf_s(tmp, sizeof(tmp), "exited while\n");
write(STDOUT_FILENO, tmp, tmpLen);
fsync(STDOUT_FILENO);
}
if (ptr == len) { len = 0; ptr = 0; }
// TODO: else move the reminder.
}
return 0;
}
void ExitSink(int s)
{
UNREFERENCED_PARAMETER(s);
signal(SIGTERM, SIG_IGN);
if (KVM_Listener_FD > 0)
{
write(STDOUT_FILENO, "EXITING\n", 8);
fsync(STDOUT_FILENO);
close(KVM_Listener_FD);
}
g_shutdown = 1;
}
void* kvm_server_mainloop(void* param)
{
CGDirectDisplayID displays[10];
int x, y, height, width, r, c = 0;
long long desktopsize = 0;
long long tilesize = 0;
long long prev_timestamp = 0;
long long cur_timestamp = 0;
long long time_diff = 50;
struct timeb tp;
void *desktop = NULL;
void *buf = NULL;
int screen_height, screen_width, screen_num;
int written = 0;
struct sockaddr_un serveraddr;
if (param == NULL)
{
// This is doing I/O via StdIn/StdOut
int flags;
flags = fcntl(STDOUT_FILENO, F_GETFL, 0);
if (fcntl(STDOUT_FILENO, F_SETFL, (O_NONBLOCK | flags) ^ O_NONBLOCK) == -1) {}
}
else
{
// this is doing I/O via a Unix Domain Socket
if ((KVM_Listener_FD = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
{
char tmp[255];
int tmplen = sprintf_s(tmp, sizeof(tmp), "ERROR CREATING DOMAIN SOCKET: %d\n", errno);
// Error creating domain socket
written = write(STDOUT_FILENO, tmp, tmplen);
fsync(STDOUT_FILENO);
return(NULL);
}
int flags;
flags = fcntl(KVM_Listener_FD, F_GETFL, 0);
if (fcntl(KVM_Listener_FD, F_SETFL, (O_NONBLOCK | flags) ^ O_NONBLOCK) == -1) { }
written = write(STDOUT_FILENO, "Set FCNTL2\n", 11);
fsync(STDOUT_FILENO);
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sun_family = AF_UNIX;
strcpy(serveraddr.sun_path, KVM_Listener_Path);
remove(KVM_Listener_Path);
if (bind(KVM_Listener_FD, (struct sockaddr *)&serveraddr, SUN_LEN(&serveraddr)) < 0)
{
char tmp[255];
int tmplen = sprintf_s(tmp, sizeof(tmp), "BIND ERROR on DOMAIN SOCKET: %d\n", errno);
// Error creating domain socket
written = write(STDOUT_FILENO, tmp, tmplen);
fsync(STDOUT_FILENO);
return(NULL);
}
if (listen(KVM_Listener_FD, 1) < 0)
{
written = write(STDOUT_FILENO, "LISTEN ERROR ON DOMAIN SOCKET", 29);
fsync(STDOUT_FILENO);
return(NULL);
}
written = write(STDOUT_FILENO, "LISTENING ON DOMAIN SOCKET\n", 27);
fsync(STDOUT_FILENO);
signal(SIGTERM, ExitSink);
if ((KVM_AGENT_FD = accept(KVM_Listener_FD, NULL, NULL)) < 0)
{
written = write(STDOUT_FILENO, "ACCEPT ERROR ON DOMAIN SOCKET", 29);
fsync(STDOUT_FILENO);
return(NULL);
}
else
{
char tmp[255];
int tmpLen = sprintf_s(tmp, sizeof(tmp), "ACCEPTed new connection %d on Domain Socket\n", KVM_AGENT_FD);
written = write(STDOUT_FILENO, tmp, tmpLen);
fsync(STDOUT_FILENO);
}
}
// Init the kvm
if (kvm_init() != 0) { return (void*)-1; }
g_shutdown = 0;
pthread_create(&kvmthread, NULL, kvm_mainloopinput, param);
if (KVM_AGENT_FD != -1)
{
written = write(STDOUT_FILENO, "Starting Loop []\n", 14);
fsync(STDOUT_FILENO);
char stmp[255];
int stmpLen = sprintf_s(stmp, sizeof(stmp), "TILE_HEIGHT_COUNT=%d, TILE_WIDTH_COUNT=%d\n", TILE_HEIGHT_COUNT, TILE_WIDTH_COUNT);
written = write(STDOUT_FILENO, stmp, stmpLen);
fsync(STDOUT_FILENO);
}
while (!g_shutdown)
{
if (g_resetipc != 0)
{
g_resetipc = 0;
close(KVM_AGENT_FD);
SCREEN_HEIGHT = SCREEN_WIDTH = 0;
char stmp[255];
int stmpLen = sprintf_s(stmp, sizeof(stmp), "Waiting for NEXT DomainSocket, TILE_HEIGHT_COUNT=%d, TILE_WIDTH_COUNT=%d\n", TILE_HEIGHT_COUNT, TILE_WIDTH_COUNT);
written = write(STDOUT_FILENO, stmp, stmpLen);
fsync(STDOUT_FILENO);
if ((KVM_AGENT_FD = accept(KVM_Listener_FD, NULL, NULL)) < 0)
{
g_shutdown = 1;
written = write(STDOUT_FILENO, "ACCEPT ERROR ON DOMAIN SOCKET", 29);
fsync(STDOUT_FILENO);
break;
}
else
{
char tmp[255];
int tmpLen = sprintf_s(tmp, sizeof(tmp), "ACCEPTed new connection %d on Domain Socket\n", KVM_AGENT_FD);
written = write(STDOUT_FILENO, tmp, tmpLen);
fsync(STDOUT_FILENO);
pthread_create(&kvmthread, NULL, kvm_mainloopinput, param);
}
}
for (r = 0; r < TILE_HEIGHT_COUNT; r++) {
for (c = 0; c < TILE_WIDTH_COUNT; c++) {
g_tileInfo[r][c].flag = TILE_TODO;
}
}
//senddebug(2);
screen_num = CGMainDisplayID();
if (screen_num == 0) { g_shutdown = 1; senddebug(-2); break; }
screen_height = CGDisplayPixelsHigh(screen_num);
screen_width = CGDisplayPixelsWide(screen_num);
if ((SCREEN_HEIGHT != screen_height || SCREEN_WIDTH != screen_width || SCREEN_NUM != screen_num))
{
kvm_init();
continue;
}
//senddebug(screen_num);
CGImageRef image = CGDisplayCreateImage(screen_num);
//senddebug(99);
if (image == NULL)
{
g_shutdown = 1;
senddebug(0);
}
else {
//senddebug(100);
getScreenBuffer((unsigned char **)&desktop, &desktopsize, image);
if (KVM_AGENT_FD != -1)
{
char tmp[255];
int tmpLen = sprintf_s(tmp, sizeof(tmp), "...Enter for loop\n");
written = write(STDOUT_FILENO, tmp, tmpLen);
fsync(STDOUT_FILENO);
}
for (y = 0; y < TILE_HEIGHT_COUNT; y++)
{
for (x = 0; x < TILE_WIDTH_COUNT; x++) {
height = TILE_HEIGHT * y;
width = TILE_WIDTH * x;
if (!g_shutdown && (g_pause)) { usleep(100000); g_pause = 0; } //HACK: Change this
if (g_shutdown) { x = TILE_WIDTH_COUNT; y = TILE_HEIGHT_COUNT; break; }
if (g_tileInfo[y][x].flag == TILE_SENT || g_tileInfo[y][x].flag == TILE_DONT_SEND) {
continue;
}
getTileAt(width, height, &buf, &tilesize, desktop, desktopsize, y, x);
if (buf && !g_shutdown)
{
// Write the reply to the pipe.
//KvmDebugLog("Writing to master in kvm_server_mainloop\n");
written = KVM_SEND(buf, tilesize);
//KvmDebugLog("Wrote %d bytes to master in kvm_server_mainloop\n", written);
if (written == -1)
{
/*ILIBMESSAGE("KVMBREAK-K2\r\n");*/
if(KVM_AGENT_FD == -1)
{
// This is a User Session, so if the connection fails, we exit out... We can be spawned again later
g_shutdown = 1; height = SCREEN_HEIGHT; width = SCREEN_WIDTH; break;
}
}
//else
//{
// char tmp[255];
// int tmpLen = sprintf_s(tmp, sizeof(tmp), "KVM_SEND => tilesize: %d\n", tilesize);
// written = write(STDOUT_FILENO, tmp, tmpLen);
// fsync(STDOUT_FILENO);
//}
free(buf);
}
}
}
if (KVM_AGENT_FD != -1)
{
char tmp[255];
int tmpLen = sprintf_s(tmp, sizeof(tmp), "...exit for loop\n");
written = write(STDOUT_FILENO, tmp, tmpLen);
fsync(STDOUT_FILENO);
}
}
CGImageRelease(image);
}
pthread_join(kvmthread, NULL);
kvmthread = (pthread_t)NULL;
if (g_tileInfo != NULL) { for (r = 0; r < TILE_HEIGHT_COUNT; r++) { free(g_tileInfo[r]); } }
g_tileInfo = NULL;
if(tilebuffer != NULL) {
free(tilebuffer);
tilebuffer = NULL;
}
if (KVM_AGENT_FD != -1)
{
written = write(STDOUT_FILENO, "Exiting...\n", 11);
fsync(STDOUT_FILENO);
}
return (void*)0;
}
void kvm_relay_ExitHandler(ILibProcessPipe_Process sender, int exitCode, void* user)
{
ILibKVM_WriteHandler writeHandler = (ILibKVM_WriteHandler)((void**)user)[0];
void *reserved = ((void**)user)[1];
void *pipeMgr = ((void**)user)[2];
char *exePath = (char*)((void**)user)[3];
}
void kvm_relay_StdOutHandler(ILibProcessPipe_Process sender, char *buffer, int bufferLen, int* bytesConsumed, void* user)
{
unsigned short size = 0;
UNREFERENCED_PARAMETER(sender);
ILibKVM_WriteHandler writeHandler = (ILibKVM_WriteHandler)((void**)user)[0];
void *reserved = ((void**)user)[1];
if (bufferLen > 4)
{
size = ntohs(((unsigned short*)(buffer))[1]);
if (size <= bufferLen)
{
if (ntohs(((unsigned short*)(buffer))[0]) == MNG_DEBUG)
{
char tmp[255];
int x = sprintf_s(tmp, sizeof(tmp), "DEBUG: %d\n", ((int*)buffer)[1]);
write(STDOUT_FILENO, tmp, x);
}
*bytesConsumed = size;
writeHandler(buffer, size, reserved);
return;
}
}
*bytesConsumed = 0;
}
void kvm_relay_StdErrHandler(ILibProcessPipe_Process sender, char *buffer, int bufferLen, int* bytesConsumed, void* user)
{
//KVMDebugLog *log = (KVMDebugLog*)buffer;
//UNREFERENCED_PARAMETER(sender);
//UNREFERENCED_PARAMETER(user);
//if (bufferLen < sizeof(KVMDebugLog) || bufferLen < log->length) { *bytesConsumed = 0; return; }
//*bytesConsumed = log->length;
////ILibRemoteLogging_printf(ILibChainGetLogger(gILibChain), (ILibRemoteLogging_Modules)log->logType, (ILibRemoteLogging_Flags)log->logFlags, "%s", log->logData);
//ILibRemoteLogging_printf(ILibChainGetLogger(gILibChain), ILibRemoteLogging_Modules_Microstack_Generic, (ILibRemoteLogging_Flags)log->logFlags, "%s", log->logData);
*bytesConsumed = bufferLen;
}
// Setup the KVM session. Return 1 if ok, 0 if it could not be setup.
void* kvm_relay_setup(char *exePath, void *processPipeMgr, ILibKVM_WriteHandler writeHandler, void *reserved, int uid)
{
char * parms0[] = { "meshagent_osx64", "-kvm0", NULL };
void **user = (void**)ILibMemory_Allocate(4 * sizeof(void*), 0, NULL, NULL);
user[0] = writeHandler;
user[1] = reserved;
user[2] = processPipeMgr;
user[3] = exePath;
char tmp[255];
int x;
if (uid != 0)
{
// Spawn child kvm process into a specific user session
x = sprintf_s(tmp, sizeof(tmp), "Spawning Process: %d\n", uid);
write(STDOUT_FILENO, tmp, x);
gChildProcess = ILibProcessPipe_Manager_SpawnProcessEx3(processPipeMgr, exePath, parms0, ILibProcessPipe_SpawnTypes_DEFAULT, (void*)(uint64_t)uid, 0);
x = sprintf_s(tmp, sizeof(tmp), "Result: %p\n", (void*)gChildProcess);
write(STDOUT_FILENO, tmp, x);
g_slavekvm = ILibProcessPipe_Process_GetPID(gChildProcess);
ILibProcessPipe_Process_AddHandlers(gChildProcess, 65535, &kvm_relay_ExitHandler, &kvm_relay_StdOutHandler, &kvm_relay_StdErrHandler, NULL, user);
// Run the relay
g_shutdown = 0;
return(ILibProcessPipe_Process_GetStdOut(gChildProcess));
}
else
{
// No users are logged in. This is a special case for MacOS
//int fd = socket(AF_UNIX, SOCK_STREAM, 0);
//if (!fd < 0)
//{
// struct sockaddr_un serveraddr;
// memset(&serveraddr, 0, sizeof(serveraddr));
// serveraddr.sun_family = AF_UNIX;
// strcpy(serveraddr.sun_path, KVM_Listener_Path);
// if (!connect(fd, (struct sockaddr *)&serveraddr, SUN_LEN(&serveraddr)) < 0)
// {
// return((void*)(uint64_t)fd);
// }
//}
return((void*)KVM_Listener_Path);
}
}
// Force a KVM reset & refresh
void kvm_relay_reset()
{
char buffer[4];
((unsigned short*)buffer)[0] = (unsigned short)htons((unsigned short)MNG_KVM_REFRESH); // Write the type
((unsigned short*)buffer)[1] = (unsigned short)htons((unsigned short)4); // Write the size
kvm_relay_feeddata(buffer, 4);
}
// Clean up the KVM session.
void kvm_cleanup()
{
KvmDebugLog("kvm_cleanup\n");
g_shutdown = 1;
}

View File

@@ -0,0 +1,36 @@
/*
* mac_kvm.h
*
*
* Created by Ylian Saint-Hilaire on 8/17/11.
* Copyright 2011 __MyCompanyName__. All rights reserved.
*
*/
#ifndef LINUX_KVM_H_
#define LINUX_KVM_H_
#include <ApplicationServices/ApplicationServices.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/timeb.h>
#include <unistd.h>
#include "mac_tile.h"
#include "mac_events.h"
#include "../../../microstack/ILibParsers.h"
typedef ILibTransport_DoneState(*ILibKVM_WriteHandler)(char *buffer, int bufferLen, void *reserved);
int kvm_relay_feeddata(char* buf, int len);
void kvm_pause(int pause);
void* kvm_relay_setup(char *exePath, void *processPipeMgr, ILibKVM_WriteHandler writeHandler, void *reserved, int uid);
void kvm_relay_reset();
void kvm_cleanup();
#endif /* LINUX_KVM_H_ */

View File

@@ -0,0 +1,507 @@
/*
* mac_tile.c
*
*
* Created by Ylian Saint-Hilaire on 8/18/11.
* Copyright 2011 __MyCompanyName__. All rights reserved.
*
*/
#include "mac_tile.h"
#include "../../meshinfo.h"
#include "../../meshdefines.h"
extern CGDirectDisplayID SCREEN_NUM;
extern int SCREEN_WIDTH;
extern int SCREEN_HEIGHT;
extern int SCREEN_DEPTH;
extern int TILE_WIDTH;
extern int TILE_HEIGHT;
extern int TILE_WIDTH_COUNT;
extern int TILE_HEIGHT_COUNT;
extern int COMPRESSION_RATIO;
extern struct tileInfo_t **g_tileInfo;
extern unsigned char *jpeg_buffer;
extern int jpeg_buffer_length;
int tilebuffersize = 0;
void* tilebuffer = NULL;
int COMPRESSION_QUALITY = 50;
/******************************************************************************
* INTERNAL FUNCTIONS
******************************************************************************/
//Extracts the required tile buffer from the desktop buffer
int get_tile_buffer(int x, int y, void **buffer, long long bufferSize, void *desktop, long long desktopsize, int tilewidth, int tileheight)
{
char *target = *buffer;
int height = 0;
for (height = y; height < y + tileheight; height++) {
memcpy(target, (const void *)(((char *)desktop) + (3 * ((height * adjust_screen_size(SCREEN_WIDTH)) + x))), (size_t)(tilewidth * 3));
target = (char *) (target + (3 * tilewidth));
}
return 0;
}
//This function returns 0 and *buffer != NULL if everything was good. retval = jpegsize if the captured image was too large.
int calc_opt_compr_send(int x, int y, int captureWidth, int captureHeight, void* desktop, long long desktopsize, void ** buffer, long long *bufferSize)
{
*buffer = NULL;
*bufferSize = 0;
// Make sure a tile buffer is available. Most of the time, this is skipped.
if (tilebuffersize != captureWidth * captureHeight * 3)
{
if (tilebuffer != NULL) free(tilebuffer);
tilebuffersize = captureWidth * captureHeight * 3;
if ((tilebuffer = malloc(tilebuffersize)) == NULL) return 0;
}
//Get the final coalesced tile
get_tile_buffer(x, y, &tilebuffer, tilebuffersize, desktop, desktopsize, captureWidth, captureHeight);
write_JPEG_buffer(tilebuffer, captureWidth, captureHeight, COMPRESSION_QUALITY);
if (jpeg_buffer_length > 65500) {
return jpeg_buffer_length;
}
else {
return 0;
}
}
#if 0
void dump32bit (const XImage * input)
{
int row, col;
static char head[256];
static FILE *fp2 = NULL;
char *ptr2, *output;
long size;
register unsigned int
rm = input->red_mask,
gm = input->green_mask,
bm = input->blue_mask,
rs = 16,
gs = 8,
bs = 0, *p32 = (unsigned int *) input->data;
printf("%x %x %x\n", rm, gm, bm);
sprintf (head, "P6\n%d %d\n%d\n", input->width, input->height, 255);
size = ((input->bytes_per_line * input->height) / 4) * 3;
output = malloc (size);
ptr2 = output;
for (row = 0; row < input->height; row++) {
for (col = 0; col < input->width; col++) {
*output++ = ((*p32 & rm) >> rs);
*output++ = ((*p32 & gm) >> gs);
*output++ = ((*p32 & bm) >> bs);
p32++; // ignore alpha values
}
//
// eat padded bytes, for better speed we use shifting,
// (bytes_per_line - bits_per_pixel / 8 * width ) / 4
//
p32 += (input->bytes_per_line - (input->bits_per_pixel >> 3)
* input->width) >> 2;
}
fp2 = fopen ("/tmp/pic.rgb.pnm", "w");
fwrite (head, strlen (head), 1, fp2);
fwrite (ptr2, size, 1, fp2);
fclose (fp2);
free (ptr2);
}
#endif
// Really fast CRC-like method. Used for the KVM.
int util_crc(int x, int y, long long bufferSize, void *desktop, long long desktopsize, int tilewidth, int tileheight)
{
int hval = 0;
int *bp = NULL;
int *be = NULL;
int height = 0;
for (height = y; height < y + tileheight; height++) {
bp = (int *)(((char *)desktop) + (3 * ((height * adjust_screen_size(SCREEN_WIDTH)) + x)));
be = (int *)(((char *)desktop) + (3 * ((height * adjust_screen_size(SCREEN_WIDTH)) + x + tilewidth)));
while ((bp + 1) <= be)
{
//hval *= 0x01000193;
hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
hval ^= *bp++;
}
/*if ((int)be - (int)bp >= 0) {
hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
hval ^= (*(int *)(((int)be) - 3));
}*/
}
return hval;
}
/******************************************************************************
* EXTERNAL FUNCTIONS
******************************************************************************/
//Adjusts the screen size(width or height) to be exactly divisible by TILE_WIDTH
int adjust_screen_size(int pixles)
{
int extra = pixles % TILE_WIDTH; //Assuming tile width and height will remain the same.
if (extra != 0) { return pixles + TILE_WIDTH - extra; }
return pixles;
}
// Reset the tile info structure
int reset_tile_info(int old_height_count) {
int row, col;
if (g_tileInfo != NULL)
{
for (row = 0; row < old_height_count; row++) { free(g_tileInfo[row]); }
free(g_tileInfo);
g_tileInfo = NULL;
}
g_tileInfo = (struct tileInfo_t **) malloc(sizeof(struct tileInfo_t *) * TILE_HEIGHT_COUNT);
for (row = 0; row < TILE_HEIGHT_COUNT; row++) {
g_tileInfo[row] = (struct tileInfo_t *) calloc (TILE_WIDTH_COUNT, sizeof(struct tileInfo_t));
for (col = 0; col < TILE_WIDTH_COUNT; col++) { g_tileInfo[row][col].crc = 0xff; }
}
return 0;
}
//Fetches the encoded jpeg tile at the given location. The neighboring tiles are coalesced to form a larger jpeg before returning.
int getTileAt(int x, int y, void** buffer, long long *bufferSize, void *desktop, long long desktopsize, int row, int col)
{
int CRC, rcol, i, r, c;
int rightcol = col; //Used in coalescing. Indicates the rightmost column to be coalesced.
int botrow = row; //Used in coalescing. Indicates the bottom most row to be coalesced.
int r_x = x;
int r_y = y;
int captureWidth = TILE_WIDTH;
int captureHeight = TILE_HEIGHT;
*buffer = NULL; // If anything fails, this will be the indication.
*bufferSize = 0;
if (g_tileInfo[row][col].flag == TILE_TODO) { //First check whether the tile-crc needs to be calculated or not.
if ((CRC = util_crc(x, y, TILE_HEIGHT * TILE_WIDTH * 3, desktop, desktopsize, TILE_WIDTH, TILE_HEIGHT)) == g_tileInfo[row][col].crc) return 0;
g_tileInfo[row][col].crc = CRC; //Update the tile CRC in the global data structure.
}
g_tileInfo[row][col].flag = TILE_MARKED_NOT_SENT;
//COALESCING SECTION
// First got to the right most changed tile and record it
while (rightcol + 1 < TILE_WIDTH_COUNT) {
rightcol++;
r_x = rightcol * TILE_WIDTH;
CRC = g_tileInfo[row][rightcol].crc;
if (g_tileInfo[row][rightcol].flag == TILE_TODO) {
CRC = util_crc(r_x, y, TILE_HEIGHT * TILE_WIDTH * 3, desktop, desktopsize, TILE_WIDTH, TILE_HEIGHT);
}
if (CRC != g_tileInfo[row][rightcol].crc || g_tileInfo[row][rightcol].flag == TILE_MARKED_NOT_SENT) { //If the tile has changed, increment the capturewidth.
g_tileInfo[row][rightcol].crc = CRC;
//Here we check whether the size of the coalesced bitmap is greater than the threshold (65500)
if ((captureWidth + TILE_WIDTH) * TILE_HEIGHT * 3 / COMPRESSION_RATIO > 65500) {
g_tileInfo[row][rightcol].flag = TILE_MARKED_NOT_SENT;
--rightcol;
break;
}
g_tileInfo[row][rightcol].flag = TILE_MARKED_NOT_SENT;
captureWidth += TILE_WIDTH;
}
else {
g_tileInfo[row][rightcol].flag = TILE_DONT_SEND;
--rightcol;
break;
}
}
//int TOLERANCE = (rightcol - col) / 3;
// Now go to the bottom tiles, check if they have changed and record them
while ((botrow + 1 < TILE_HEIGHT_COUNT) && ((captureHeight + TILE_HEIGHT) * captureWidth * 3 / COMPRESSION_RATIO <= 65500)) {
botrow++;
r_y = botrow * TILE_HEIGHT;
int fail = 0;
r_x = x;
//int missCount = 0;
for (rcol = col; rcol <= rightcol; rcol++) {
CRC = g_tileInfo[botrow][rcol].crc;
if (g_tileInfo[botrow][rcol].flag == TILE_TODO) {
CRC = util_crc(r_x, r_y, TILE_HEIGHT * TILE_WIDTH * 3, desktop, desktopsize, TILE_WIDTH, TILE_HEIGHT);
}
if (CRC != g_tileInfo[botrow][rcol].crc || g_tileInfo[botrow][rcol].flag == TILE_MARKED_NOT_SENT) {
g_tileInfo[botrow][rcol].flag = TILE_MARKED_NOT_SENT;
g_tileInfo[botrow][rcol].crc = CRC;
r_x += TILE_WIDTH;
}
else {
/*//Keep this part commented. Adding tolerance adds to the complexity of this code.
missCount++;
if (missCount > TOLERANCE) {
fail = 1;
for (int i = col; i < rcol; i++) {
if (g_tileInfo[botrow][i].flag == TILE_SKIPPED) {
g_tileInfo[botrow][i].flag = TILE_DONT_SEND;
}
else {
g_tileInfo[botrow][i].flag = TILE_MARKED_NOT_SENT;
}
}
g_tileInfo[botrow][rcol].flag = TILE_DONT_SEND;
botrow--;
break;
}
else {
g_tileInfo[botrow][rcol].flag = TILE_SKIPPED;
g_tileInfo[botrow][rcol].crc = CRC;
r_x += TILE_WIDTH;
}*/
fail = 1;
for (i = col; i < rcol; i++) {
g_tileInfo[botrow][i].flag = TILE_MARKED_NOT_SENT;
}
g_tileInfo[botrow][rcol].flag = TILE_DONT_SEND;
botrow--;
break;
}
}
if (!fail) {
captureHeight += TILE_HEIGHT;
}
else {
break;
}
}
int retval = 0;
int firstTime = 1;
//This loop is used to adjust the COMPRESSION_RATIO. This loop runs only once most of the time.
do {
//retval here is 0 if everything was good. It is > 0 if it contains the size of the jpeg that was created and not sent.
retval = calc_opt_compr_send(x, y, captureWidth, captureHeight, desktop, desktopsize, buffer, bufferSize);
if (retval != 0) {
if (firstTime) {
//Re-adjust the compression ratio.
COMPRESSION_RATIO = (int)(((double)COMPRESSION_RATIO/(double)retval) * 60000);//Magic number: 60000 ~= 65500
if (COMPRESSION_RATIO <= 1) {
COMPRESSION_RATIO = 2;
}
firstTime = 0;
}
if (botrow > row) { //First time, try reducing the height.
botrow = row + ((botrow - row + 1) / 2);
captureHeight = (botrow - row + 1) * TILE_HEIGHT;
}
else if (rightcol > col){ //If it is not possible, reduce the width
rightcol = col + ((rightcol - col + 1) / 2);
captureWidth = (rightcol - col + 1) * TILE_WIDTH;
}
else { //This never happens in any case.
retval = 0;
break;
}
}
} while (retval != 0);
//Set the flags to TILE_SENT
if (jpeg_buffer != NULL) {
*bufferSize = jpeg_buffer_length + 8;
*buffer = malloc (*bufferSize);
((unsigned short*)*buffer)[0] = (unsigned short)htons((unsigned short)MNG_KVM_PICTURE); // Write the type
((unsigned short*)*buffer)[1] = (unsigned short)htons((unsigned short)*bufferSize); // Write the size
((unsigned short*)*buffer)[2] = (unsigned short)htons((unsigned short)x); // X position
((unsigned short*)*buffer)[3] = (unsigned short)htons((unsigned short)y); // Y position
memcpy((char *)(*buffer) + 8, jpeg_buffer, jpeg_buffer_length);
free(jpeg_buffer);
jpeg_buffer = NULL;
jpeg_buffer_length = 0;
for (r = row; r <= botrow; r++) {
for (c = col; c <= rightcol; c++) {
g_tileInfo[r][c].flag = TILE_SENT;
}
}
}
return retval;
}
// Get screen buffer from the CGImageRef structure
int getScreenBuffer(unsigned char **desktop, long long *desktopsize, CGImageRef image)
{
unsigned int row, col, bpp, len, width_padding_size, height_padding_size, i;
unsigned char *output;
int height = CGImageGetHeight(image);
int width = CGImageGetWidth(image);
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(image);
CFDataRef dataRef = CGDataProviderCopyData(CGImageGetDataProvider(image));
const unsigned char *sourceBytesPtr = CFDataGetBytePtr(dataRef);
len = CFDataGetLength(dataRef);
if (*desktopsize != len) {
if (*desktop != NULL) { free(*desktop); }
*desktopsize = len;
*desktop = (unsigned char *) malloc (*desktopsize);
}
output = *desktop;
bpp = CGImageGetBitsPerPixel(image);
width_padding_size = (adjust_screen_size(SCREEN_WIDTH) - width) * 3;
switch(bpp) {
case 16:
{
const unsigned short *tmpPtr = (const unsigned short *)sourceBytesPtr;
if(alphaInfo == kCGImageAlphaNoneSkipFirst ||
alphaInfo == kCGImageAlphaPremultipliedFirst ||
alphaInfo == kCGImageAlphaFirst) {
for (row = 0; row < height; row++) {
for (col = 0; col < width; col++) {
*output++ = (*tmpPtr & 0x7C00) >> 7;
*output++ = (*tmpPtr & 0x3E0) >> 2;
*output++ = (*tmpPtr & 0x1F) << 3;
tmpPtr++;
}
if (width_padding_size != 0) {
for (i = 0; i < width_padding_size; i++) {
*output++ = 0;
}
}
tmpPtr += (CGImageGetBytesPerRow(image) - (bpp >> 3) * width) >> 2;
}
}
else if (alphaInfo == kCGImageAlphaNone ||
alphaInfo == kCGImageAlphaNoneSkipLast ||
alphaInfo == kCGImageAlphaPremultipliedLast ||
alphaInfo == kCGImageAlphaLast) {
for (row = 0; row < height; row++) {
for (col = 0; col < width; col++) {
*output++ = (*tmpPtr & 0xF800) >> 8;
*output++ = (*tmpPtr & 0x7C0) >> 3;
*output++ = (*tmpPtr & 0x3E) << 2;
tmpPtr++;
}
if (width_padding_size != 0) {
for (i = 0; i < width_padding_size; i++) {
*output++ = 0;
}
}
tmpPtr += (CGImageGetBytesPerRow(image) - (bpp >> 3) * width) >> 2;
}
}
}
break;
case 32:
{
const unsigned int *tmpPtr1 = (const unsigned int *)sourceBytesPtr;
if(alphaInfo == kCGImageAlphaNoneSkipFirst ||
alphaInfo == kCGImageAlphaPremultipliedFirst ||
alphaInfo == kCGImageAlphaFirst) {
for (row = 0; row < height; row++) {
for (col = 0; col < width; col++) {
*output++ = (*tmpPtr1 & 0x0ff0000) >> 16;
*output++ = (*tmpPtr1 & 0x0ff00) >> 8;
*output++ = (*tmpPtr1 & 0x0FF);
tmpPtr1++;
}
if (width_padding_size != 0) {
for (i = 0; i < width_padding_size; i++) {
*output++ = 0;
}
}
tmpPtr1 += (CGImageGetBytesPerRow(image) - (bpp >> 3) * width) >> 2;
}
}
else if (alphaInfo == kCGImageAlphaNone ||
alphaInfo == kCGImageAlphaNoneSkipLast ||
alphaInfo == kCGImageAlphaPremultipliedLast ||
alphaInfo == kCGImageAlphaLast) {
for (row = 0; row < height; row++) {
for (col = 0; col < width; col++) {
*output++ = (*tmpPtr1 & 0xFF000000) >> 24;
*output++ = (*tmpPtr1 & 0x0ff0000) >> 16;
*output++ = (*tmpPtr1 & 0x0ff00) >> 8;
tmpPtr1++;
}
if (width_padding_size != 0) {
for (i = 0; i < width_padding_size; i++) {
*output++ = 0;
}
}
tmpPtr1 += (CGImageGetBytesPerRow(image) - (bpp >> 3) * width) >> 2;
}
}
}
break;
default:
fprintf(stderr, "This image depth is not supported.\n");
return -1;
}
height_padding_size = adjust_screen_size(SCREEN_HEIGHT) - height;
if (height_padding_size != 0) {
for (row = 0; row < height_padding_size; row++) {
for (col = 0; col < (width * 3) + width_padding_size; col++) {
*output++ = 0;
}
}
}
CFRelease(dataRef);
return 0;
}
// Set the compression quality
void set_tile_compression(int type, int level)
{
if (level > 0 && level <= 100) {
COMPRESSION_QUALITY = level;
}
else {
COMPRESSION_QUALITY = 60;
}
// TODO Make sure the all the types are handled. We ignore the type variable for now.
}

View File

@@ -0,0 +1,41 @@
/*
* mac_tile.h
*
*
* Created by Ylian Saint-Hilaire on 8/18/11.
* Copyright 2011 __MyCompanyName__. All rights reserved.
*
*/
#ifndef LINUX_TILE_H_
#define LINUX_TILE_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <Carbon/Carbon.h>
#include "../Linux/linux_compression.h"
enum TILE_FLAGS_ENUM {
TILE_TODO, //The tile CRC needs to be calculated.
TILE_SENT, //CRC has been calculated and the tile has been sent.
TILE_MARKED_NOT_SENT, //CRC has been calculated, but the tile was not sent.
TILE_DONT_SEND //CRC has been calculated, tile need not be sent.
//TILE_SKIPPED //CRC has been calculated, tile need not be sent, but was skipped to include a greater region
};
struct tileInfo_t {
int crc;
enum TILE_FLAGS_ENUM flag;
};
extern int reset_tile_info(int old_height_count);
extern int adjust_screen_size(int pixles);
extern int getTileAt(int x, int y, void** buffer, long long *bufferSize, void *desktop, long long desktopsize, int row, int col);
extern int getScreenBuffer(unsigned char **desktop, long long *desktopsize, CGImageRef image);
extern void set_tile_compression(int type, int level);
#endif /* LINUX_TILE_H_ */