. Use right Linux APIs to access multicast address list.
. changes in shared code that don't affect open-vm-tools functionality.
Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
case UNITY_WINDOW_CONTENTS_V1:
struct UnityWindowContentsRequestV1 *requestV1;
};
+
+
+/*
+ * Mouse wheel.
+ */
+
+enum UnityMouseWheelVersion {
+ UNITY_MOUSE_WHEEL_V1 = 1
+};
+
+struct UnityMouseWheelV1
+{
+ int32 deltaX;
+ int32 deltaY;
+ int32 deltaZ;
+ uint32 modifierFlags;
+};
+
+union UnityMouseWheel switch (UnityMouseWheelVersion ver) {
+case UNITY_MOUSE_WHEEL_V1:
+ struct UnityMouseWheelV1 *mouseWheelV1;
+};--- lib/unityWindowTracker/unityWindowTracker.c
*
* Determines whether it is safe to write to the MCE control
* register MC0_CTL.
- * Known safe: P4, Nahalem, All AMD.
- * Known not safe: P6, Core, Core2, Penryn
+ * Known safe: P4, All AMD, all family 6 model > 0x1a, except core/atom
* Don't know: P2, P3
*
* Results:
CPUIDSummary_RegsFromCpuid0(&cpuidSummary->id0, &id0);
return CPUID_IsVendorAMD(&id0) ||
(CPUID_IsVendorIntel(&id0) &&
- (CPUID_FAMILY_IS_PENTIUM4(id0.eax) ||
- CPUID_UARCH_IS_NEHALEM(cpuidSummary->id1.version)));
+ (CPUID_FAMILY_IS_PENTIUM4(cpuidSummary->id1.version) ||
+ (CPUID_FAMILY_IS_P6(cpuidSummary->id1.version) &&
+ (CPUID_EFFECTIVE_MODEL(cpuidSummary->id1.version) ==
+ CPUID_MODEL_NEHALEM_1A ||
+ CPUID_EFFECTIVE_MODEL(cpuidSummary->id1.version) >=
+ CPUID_MODEL_NEHALEM_1E))));
}
#define UNITY_RPC_WINDOW_UNSTICK "unity.window.unstick"
#define UNITY_RPC_CONFIRM_OPERATION "unity.operation.confirm"
#define UNITY_RPC_WINDOW_CONTENTS_REQUEST "unity.window.contents.request"
+#define UNITY_RPC_SEND_MOUSE_WHEEL "unity.sendMouseWheel"
#define GHI_RPC_GUEST_SHELL_ACTION "ghi.guest.shell.action"
#define GHI_RPC_SET_GUEST_HANDLER "ghi.guest.handler.set"
@endcode
@param[in] XDR_REP XDR Encoded (see unity.x) representation of arguments.
+ @def UNITY_RPC_SEND_MOUSE_WHEEL
+ @brief Send mouse wheel events to the window under the mouse.
+ @code
+ UNITY_RPC_SEND_MOUSE_WHEEL horizontal deltaX deltaY deltaZ modifierFlags
+ @endcode
+ @param[in] horizontal 0 to send vertical mouse wheel event, 1 for horizontal
+ @param[in] deltaX the horizontal distance the wheel is rotated
+ @param[in] deltaY the vertial distance the wheel is rotated
+ @param[in] deltaZ the distance the wheel is rotated in the Z axis
+ @param[in] modifierFlags modifier flags pressed during the event
+
@}
*/
typedef void (*UnityUpdateCallback)(void *param, UnityUpdate *update);
+void UnityWindowTracker_ParseUnityUpdate(const char *result,
+ int len,
+ UnityUpdateCallback cb,
+ void *param);
+
/*
* Internal state --
* Do not fiddle with these bits! They are included in this header to aid in debugging.
unsigned short _outpw(unsigned short, unsigned short);
unsigned long _outpd(uint16, unsigned long);
#pragma intrinsic(_inp, _inpw, _inpd, _outp, _outpw, _outpw, _outpd)
+
+/*
+ * Prevents compiler from re-ordering reads, writes and reads&writes.
+ * These functions do not add any instructions thus only affect
+ * the compiler ordering.
+ *
+ * See:
+ * `Lockless Programming Considerations for Xbox 360 and Microsoft Windows'
+ * http://msdn.microsoft.com/en-us/library/bb310595(VS.85).aspx
+ */
+void _ReadBarrier(void);
+void _WriteBarrier(void);
void _ReadWriteBarrier(void);
-#pragma intrinsic(_ReadWriteBarrier)
+#pragma intrinsic(_ReadBarrier, _WriteBarrier, _ReadWriteBarrier)
#ifdef VM_X86_64
/*
#if defined(__i386__) || defined(__x86_64__)
-#ifdef __GNUC__ // {
/*
* COMPILER_MEM_BARRIER prevents the compiler from re-ordering memory
* references accross the barrier. NOTE: It does not generate any
* instruction, so the CPU is free to do whatever it wants to...
*/
-#define COMPILER_MEM_BARRIER() __asm__ __volatile__ ("": : :"memory")
-#elif defined(_MSC_VER) // } {
-#define COMPILER_MEM_BARRIER() _ReadWriteBarrier()
+#ifdef __GNUC__ // {
+#define COMPILER_MEM_BARRIER() __asm__ __volatile__ ("": : :"memory")
+#define COMPILER_READ_BARRIER() COMPILER_MEM_BARRIER()
+#define COMPILER_WRITE_BARRIER() COMPILER_MEM_BARRIER()
+#elif _MSC_VER
+#define COMPILER_MEM_BARRIER() _ReadWriteBarrier()
+#define COMPILER_READ_BARRIER() _ReadBarrier()
+#define COMPILER_WRITE_BARRIER() _WriteBarrier()
#endif // }
CPUIDLEVEL(FALSE, A, 0xA) \
CPUIDLEVEL(FALSE, B, 0xB) \
CPUIDLEVEL(FALSE, D, 0xD) \
- CPUIDLEVEL(FALSE, 86, 0x80000006)
+ CPUIDLEVEL(FALSE, 86, 0x80000006) \
+ CPUIDLEVEL(FALSE, 81D, 0x8000001D)
#define CPUID_ALL_LEVELS \
CPUID_CACHED_LEVELS \
FLAGDEF( 81, ECX, AMD, 12, 1, SKINIT, NO, FALSE) \
FLAGDEF( 81, ECX, AMD, 13, 1, WATCHDOG, NO, FALSE) \
FLAGDEF( 81, ECX, AMD, 19, 1, NODEID, NO, FALSE) \
+FLAGDEF( 81, ECX, AMD, 22, 1, TOPOLOGY, NO, FALSE) \
FLAGDEF( 81, EDX, AMD, 0, 1, FPU, YES, TRUE) \
FLAGDEF( 81, EDX, AMD, 1, 1, VME, YES, FALSE) \
FLAGDEF( 81, EDX, AMD, 2, 1, DBGE, YES, FALSE) \
FIELDDEF( 8A, EDX, AMD, 11, 21, SVMEDX_RSVD1, NO, FALSE)
+/* LEVEL, REG, VENDOR, POS, SIZE, NAME, MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_81D \
+FIELDDEFA( 81D,EAX, AMD, 0, 5, CACHE_TYPE, NA, FALSE, AMD_CACHE_TYPE) \
+FIELDDEFA( 81D,EAX, AMD, 5, 3, CACHE_LEVEL, NA, FALSE, AMD_CACHE_LEVEL) \
+FIELDDEFA( 81D,EBX, AMD, 22, 10, CACHE_WAYS, NA, FALSE, AMD_CACHE_WAYS)
#define CPUID_FIELD_DATA \
CPUID_FIELD_DATA_LEVEL_80 \
CPUID_FIELD_DATA_LEVEL_81 \
CPUID_FIELD_DATA_LEVEL_8x \
- CPUID_FIELD_DATA_LEVEL_8A_BD
+ CPUID_FIELD_DATA_LEVEL_8A_BD \
+ CPUID_FIELD_DATA_LEVEL_81D
/*
FIELD_FUNC(TOPOLOGY_LEVEL_NUMBER, CPUID_INTEL_IDBECX_LEVEL_NUMBER)
FIELD_FUNC(TOPOLOGY_LEVEL_TYPE, CPUID_INTEL_IDBECX_LEVEL_TYPE)
FIELD_FUNC(TOPOLOGY_X2APIC_ID, CPUID_INTEL_IDBEDX_X2APIC_ID)
+FIELD_FUNC(AMD_CACHE_TYPE, CPUID_AMD_ID81DEAX_CACHE_TYPE)
+FIELD_FUNC(AMD_CACHE_LEVEL, CPUID_AMD_ID81DEAX_CACHE_LEVEL)
+FIELD_FUNC(AMD_CACHE_WAYS, CPUID_AMD_ID81DEBX_CACHE_WAYS)
#undef FIELD_FUNC
}
+/*
+ *----------------------------------------------------------------------------
+ *
+ * UnityTcloSendMouseWheel --
+ *
+ * RPC handler for 'unity.sendMouseWheel'.
+ *
+ * Results:
+ * TRUE on success, FALSE on failure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+RpcInRet
+UnityTcloSendMouseWheel(RpcInData *data) // IN/OUT
+{
+ UnityMouseWheel unityMouseWheelMsg = {0};
+ UnityMouseWheelV1 *mouseWheelV1 = NULL;
+ Bool retVal = FALSE;
+ unsigned int ret;
+ Debug("%s: Enter.\n", __FUNCTION__);
+
+ /*
+ * Deserialize the XDR data. Note that the data begins with args + 1 since
+ * there is a space between the RPC name and the XDR serialization.
+ */
+ if (!XdrUtil_Deserialize(data->args + 1, data->argsSize - 1,
+ xdr_UnityMouseWheel, &unityMouseWheelMsg)) {
+ ret = RPCIN_SETRETVALS(data, "Failed to deserialize data", FALSE);
+ goto exit;
+ }
+
+ mouseWheelV1 = unityMouseWheelMsg.UnityMouseWheel_u.mouseWheelV1;
+ retVal = UnityPlatformSendMouseWheel(unity.up,
+ mouseWheelV1->deltaX,
+ mouseWheelV1->deltaY,
+ mouseWheelV1->deltaZ,
+ mouseWheelV1->modifierFlags);
+
+ /* Free any memory allocated by XDR - we're done with unityMouseWheelMsg */
+ VMX_XDR_FREE(xdr_UnityMouseWheel, &unityMouseWheelMsg);
+ ret = RPCIN_SETRETVALS(data, "", retVal);
+
+exit:
+ Debug("%s: Exit.\n", __FUNCTION__);
+ return ret;
+}
+
+
/*
*----------------------------------------------------------------------------
*
UnityWindowId windowIds[],
uint32 numWindowIds);
+Bool UnityPlatformSendMouseWheel(UnityPlatform *up,
+ int32 deltaX,
+ int32 deltaY,
+ int32 deltaZ,
+ uint32 modifierFlags);
+
/*
* Function called by UnityUpdateCallbackFn whenever a window is removed from
* the tracker.
}
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * UnityPlatformSendMouseWheel --
+ *
+ * Sends the given mouse wheel event to the window at the given location.
+ *
+ * Results:
+ * Returns TRUE if successful, and FALSE otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *------------------------------------------------------------------------------
+ */
+
+Bool
+UnityPlatformSendMouseWheel(UnityPlatform *up, // IN
+ int32 deltaX, // IN
+ int32 deltaY, // IN
+ int32 deltaZ, // IN
+ uint32 modifierFlags) // IN
+{
+ ASSERT(up);
+ return FALSE;
+}
+
+
/*
*
* End file-scope functions.
* Used to buffer state about a window manager.
*/
+#include <stdio.h>
#include "vmware.h"
#include "str.h"
+#include "strutil.h"
#include "util.h"
#include "log.h"
#include "unityWindowTracker.h"
(const unsigned char*)DynBuf_Get(second),
DynBuf_GetSize(first)) == 0) ? TRUE : FALSE;
}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * UnityWindowTracker_ParseUnityUpdate --
+ *
+ * Validate and parse Unity update command strings. The caller
+ * should pass in a UnityUpdateCallback function (see lib/public/
+ * unityWindowTracker.h). The callback will fire once for each
+ * window update in the result string.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+UnityWindowTracker_ParseUnityUpdate(const char *result, // IN
+ int len, // IN
+ UnityUpdateCallback cb, // IN
+ void *param) // IN
+{
+ if (result && len > 1) {
+ uint32 id = 0;
+ int x1, y1, x2, y2;
+ const char *buf;
+
+ /*
+ * Protect against malicious guests. If the string is not double
+ * null terminated, ignore it completely.
+ */
+
+ if (result[len - 1] || result[len - 2]) {
+ Warning("%s called with non-double null terminated string!\n",
+ __FUNCTION__);
+
+ return;
+ }
+
+ /*
+ * Parse the result
+ */
+
+ for (buf = result; *buf; buf += strlen(buf) + 1) {
+ UnityUpdate update;
+ Bool ok = FALSE;
+
+ if (StrUtil_StartsWith(buf, "add ")) {
+ const char *argumentStart = buf + strlen("add ");
+ unsigned int index = 0;
+
+ DynBuf_Init(&update.u.addWindow.windowPathUtf8);
+ DynBuf_Init(&update.u.addWindow.execPathUtf8);
+
+ /*
+ * The arguments take the form 'add <id> [arguments]' where [arguments] are
+ * space seperated 'key=value' pairs, if an argument is simply key= the value
+ * should be treated as an empty string.
+ * Only the <id> may be present if the guest is running certain older
+ * versions of tools.
+ */
+ ok = StrUtil_GetNextUintToken(&id, &index, argumentStart, " ");
+
+ /*
+ * If we failed to get the required <id> argument there's little point
+ * carrying on. However failure to receive any of the following arguments
+ * is not an error (they're optional) - it's also not an error to get
+ * an expected key here since we may well add new keys in the future and
+ * don't want to log needless error messages if the host hasn't been updated
+ * to match.
+ */
+ if (ok) {
+ char *field;
+ update.type = UNITY_UPDATE_ADD_WINDOW;
+ update.u.addWindow.id = id;
+ while ((field = StrUtil_GetNextToken(&index, argumentStart, " "))) {
+
+ if (StrUtil_StartsWith(field, "windowPath=")) {
+ ok = DynBuf_AppendString(&update.u.addWindow.windowPathUtf8,
+ field + strlen("windowPath="));
+ }
+
+ if (StrUtil_StartsWith(field, "execPath=")) {
+ ok = DynBuf_AppendString(&update.u.addWindow.execPathUtf8,
+ field + strlen("execPath="));
+ }
+
+ /*
+ * Free the results of the tokenization (field)
+ */
+ free(field);
+ }
+ } else {
+ LOG(0, ("TOOLS Expected window id but no id found in string.\n"));
+ }
+ } else if (StrUtil_StartsWith(buf, "remove ")) {
+ if (sscanf(buf, "remove %u", &id) == 1) {
+ update.type = UNITY_UPDATE_REMOVE_WINDOW;
+ update.u.removeWindow.id = id;
+ ok = TRUE;
+ }
+ } else if (StrUtil_StartsWith(buf, "move ")) {
+ if (sscanf(buf, "move %u %d %d %d %d", &id, &x1, &y1,
+ &x2, &y2) == 5) {
+ update.type = UNITY_UPDATE_MOVE_WINDOW;
+ update.u.moveWindow.id = id;
+ RECT_SETRECT(&update.u.moveWindow.rect, x1, y1, x2, y2);
+ ok = TRUE;
+ }
+ } else if (StrUtil_StartsWith(buf, "title ")) {
+ const char *titleInfo = buf + 6;
+
+ /* StrUtil_* functions do not like NULL strings. */
+ if (*titleInfo) {
+ unsigned int index = 0;
+ if (StrUtil_GetNextUintToken(&id, &index, titleInfo, " ")) {
+ char *titleUtf8 = NULL;
+ update.u.changeWindowTitle.id = id;
+
+ if (titleInfo[index] == ' ') {
+ index++; // Skip the space
+ if (titleInfo[index]) {
+ titleUtf8 = StrUtil_GetNextToken(&index, titleInfo,
+ "");
+ }
+ }
+ if (!titleUtf8) {
+ titleUtf8 = Util_SafeStrdup("");
+ }
+
+ DynBuf_Init(&update.u.changeWindowTitle.titleUtf8);
+ if (DynBuf_AppendString(&update.u.changeWindowTitle.titleUtf8,
+ titleUtf8)) {
+ update.type = UNITY_UPDATE_CHANGE_WINDOW_TITLE;
+ ok = TRUE;
+ }
+ free(titleUtf8);
+ } else {
+ LOG(0,
+ ("TOOLS Malformed title string, couldn't get the window id.\n"));
+ }
+ } else {
+ LOG(0, ("TOOLS Empty title string, couldn't get the title.\n"));
+ }
+ } else if (StrUtil_StartsWith(buf, "zorder ")) {
+ int count = 0;
+ int i = 0;
+ const char *bufPtr = buf;
+ bufPtr = strchr(bufPtr, ' ');
+ if (sscanf(bufPtr, " %d", &count) == 1) {
+ count = MIN(count, ARRAYSIZE(update.u.zorder.ids));
+ bufPtr = strchr(++bufPtr, ' ');
+ while (bufPtr && *bufPtr && i < count &&
+ sscanf(bufPtr, " %u", update.u.zorder.ids + i) == 1) {
+ i++;
+ bufPtr = strchr(++bufPtr, ' ');
+ }
+ if (i == count) {
+ update.type = UNITY_UPDATE_CHANGE_ZORDER;
+ update.u.zorder.count = count;
+ ok = TRUE;
+ } else {
+ LOG(0, ("TOOLS Expected %d but received %d in zorder string.\n",
+ count, i));
+ }
+ } else {
+ LOG(0, ("TOOLS Malformed zorder string, couldn't scan count.\n"));
+ }
+ } else if (StrUtil_StartsWith(buf, "region ")) {
+ int current = 0, numRects;
+ if (sscanf(buf, "region %u %d", &id, &numRects) == 2) {
+ RegionPtr region = NULL;
+
+ update.type = UNITY_UPDATE_CHANGE_WINDOW_REGION;
+ update.u.changeWindowRegion.region = NULL;
+ update.u.changeWindowRegion.id = id;
+
+ if (numRects) {
+ BoxRec rc;
+ RECT_SETRECT(&rc, 0, 0, 0, 0);
+ region = miRegionCreate(&rc, 0);
+
+ do {
+ buf += strlen(buf) + 1;
+ current++;
+ if (sscanf(buf, "rect %d %d %d %d", &x1, &y1, &x2, &y2) == 4) {
+ RECT_SETRECT(&rc, x1, y1, x2, y2);
+ miApplyRect(region, region, &rc, miUnion);
+ } else {
+ Warning("Malformed processing unity region" \
+ " (attempting to continue): %s.\n",
+ buf);
+ }
+ } while (current < numRects && *buf);
+ }
+ update.u.changeWindowRegion.region = region;
+ ok = TRUE;
+ } else {
+ Warning("Malformed processing unity region %s.\n", buf);
+ }
+ } else if (StrUtil_StartsWith(buf, "state ")) {
+ uint32 state = 0;
+
+ update.type = UNITY_UPDATE_CHANGE_WINDOW_STATE;
+ if (sscanf(buf, "state %u %d", &id, &state) == 2) {
+ update.u.changeWindowState.id = id;
+ update.u.changeWindowState.state = state;
+ ok = TRUE;
+ }
+ } else if (StrUtil_StartsWith(buf, "attr ")) {
+ update.type = UNITY_UPDATE_CHANGE_WINDOW_ATTRIBUTE;
+ if (sscanf(buf, "attr %u %u %u",
+ &update.u.changeWindowAttribute.id,
+ (unsigned int *)&update.u.changeWindowAttribute.attr,
+ &update.u.changeWindowAttribute.value) == 3 &&
+ update.u.changeWindowAttribute.attr < UNITY_MAX_ATTRIBUTES) {
+ ok = TRUE;
+ }
+ } else if (StrUtil_StartsWith(buf, "type ")) {
+ update.type = UNITY_UPDATE_CHANGE_WINDOW_TYPE;
+ if (sscanf(buf, "type %u %d", &update.u.changeWindowType.id,
+ (int *)&update.u.changeWindowType.winType) == 2 &&
+ update.u.changeWindowType.winType < UNITY_MAX_WINDOW_TYPES) {
+ ok = TRUE;
+ }
+ } else if (StrUtil_StartsWith(buf, "icon ")) {
+ update.type = UNITY_UPDATE_CHANGE_WINDOW_ICON;
+ if (sscanf(buf, "icon %u %u", &update.u.changeWindowIcon.id,
+ (unsigned int *)&update.u.changeWindowIcon.iconType) == 2 &&
+ update.u.changeWindowIcon.iconType < UNITY_MAX_ICONS) {
+ ok = TRUE;
+ }
+ } else if (StrUtil_StartsWith(buf, "desktop ")) {
+ update.type = UNITY_UPDATE_CHANGE_WINDOW_DESKTOP;
+ if (sscanf(buf, "desktop %u %d", &update.u.changeWindowDesktop.id,
+ &update.u.changeWindowDesktop.desktopId) == 2) {
+ ok = TRUE;
+ }
+ } else if (StrUtil_StartsWith(buf, "activedesktop ")) {
+ update.type = UNITY_UPDATE_CHANGE_ACTIVE_DESKTOP;
+ if (sscanf(buf, "activedesktop %d",
+ &update.u.changeActiveDesktop.desktopId) == 1) {
+ ok = TRUE;
+ }
+ }
+
+ if (ok) {
+ (*cb)(param, &update);
+ } else {
+ Warning("Malformed unity response string: %s.\n", buf);
+ }
+
+ if (ok && (update.type == UNITY_UPDATE_ADD_WINDOW)) {
+ DynBuf_Destroy(&update.u.addWindow.windowPathUtf8);
+ DynBuf_Destroy(&update.u.addWindow.execPathUtf8);
+ }
+
+ if (ok && (update.type == UNITY_UPDATE_CHANGE_WINDOW_TITLE)) {
+ DynBuf_Destroy(&update.u.changeWindowTitle.titleUtf8);
+ }
+
+ if (ok &&
+ (update.type == UNITY_UPDATE_CHANGE_WINDOW_REGION) &&
+ (update.u.changeWindowRegion.region != NULL)) {
+ miRegionDestroy(update.u.changeWindowRegion.region);
+ }
+ }
+ }
+}
{
struct Vmxnet_Private *lp = netdev_priv(dev);
volatile u16 *mcast_table = (u16 *)lp->dd->LADRF;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
struct netdev_hw_addr *dmi;
#else
struct dev_mc_list *dmi = dev->mc_list;
lp->dd->LADRF[1] = 0;
/* Add addresses */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
netdev_for_each_mc_addr(dmi, dev) {
addrs = dmi->addr;
#else
#ifndef _VMXNET_VERSION_H_
#define _VMXNET_VERSION_H_
-#define VMXNET_DRIVER_VERSION 2.0.7.0
-#define VMXNET_DRIVER_VERSION_COMMAS 2,0,7,0
-#define VMXNET_DRIVER_VERSION_STRING "2.0.7.0"
+#define VMXNET_DRIVER_VERSION 2.0.8.0
+#define VMXNET_DRIVER_VERSION_COMMAS 2,0,8,0
+#define VMXNET_DRIVER_VERSION_STRING "2.0.8.0"
#endif /* _VMXNET_VERSION_H_ */