diff -r e0ca5674399b modules/graphics/src/main/native-glass/lens/input/udev/udevInput.c
--- a/modules/graphics/src/main/native-glass/lens/input/udev/udevInput.c	Mon Dec 09 15:52:41 2013 -0800
+++ b/modules/graphics/src/main/native-glass/lens/input/udev/udevInput.c	Sun Dec 15 13:58:24 2013 +0200
@@ -101,7 +101,7 @@
             isTraceTimeInit = JNI_TRUE;                             \
         }                                                           \
         gettimeofday(&tv,NULL);                                     \
-        printf("lens.input.trace: %lu.%lu " format,                 \
+        printf("lens.input.trace: %lu.%lu " format "\n",            \
               (tv.tv_sec-tv_start.tv_sec),                          \
               (tv.tv_usec - tv_start.tv_usec), ##__VA_ARGS__);      \
         fflush(stdout);                                             \
@@ -131,11 +131,13 @@
     int                     touchXs[LENS_MAX_TOUCH_POINTS];
     int                     touchYs[LENS_MAX_TOUCH_POINTS];
     jboolean                touchIsDragging[LENS_MAX_TOUCH_POINTS];
+    int                     touchTrackingIDs[LENS_MAX_TOUCH_POINTS];
     /* new touch points that have not yet been sent up to Glass */
     int                     pendingTouchPointCount;
     int                     pendingTouchIDs[LENS_MAX_TOUCH_POINTS];
     int                     pendingTouchXs[LENS_MAX_TOUCH_POINTS];
     int                     pendingTouchYs[LENS_MAX_TOUCH_POINTS];
+    int                     pendingTouchTrackingIDs[LENS_MAX_TOUCH_POINTS];
 
     /* pending input events that have not yet been reported to the upper stack */
     struct input_event      *pendingInputEvents;
@@ -1489,8 +1491,13 @@
     jboolean reportMouseMove = JNI_FALSE;
     mouseState->pendingTouchPointCount = 0;
     mouseState->pressedX = mouseState->pressedY = -1;
-    int numOfMTPoints = 0;
+    int numOfUpdatePoints = 0;
     int touchButtonValue = -1; //not set
+    jboolean isPartialProtocolB = 
+                device->info->caps.absinfo[ABS_MT_TOUCH_MAJOR].maximum == 1 ?
+                JNI_TRUE :
+                JNI_FALSE;
+    int numOfReleasePoints = 0;
 
     //Pass on the events of this sync
     for (i = 0; i < mouseState->pendingInputEventCount; i++) {
@@ -1511,7 +1518,17 @@
                 lens_input_pointerEvents_handleAbsMotion(device, pointerEvent);
                 if (mouseState->pendingTouchPointCount < LENS_MAX_TOUCH_POINTS &&
                     pointerEvent->code == ABS_MT_POSITION_X) {
-                    numOfMTPoints++;
+                    numOfUpdatePoints++;
+                }
+
+                if (isPartialProtocolB) {
+                    if (pointerEvent->code == ABS_MT_TRACKING_ID) {
+                        mouseState->pendingTouchTrackingIDs[mouseState->pendingTouchPointCount] =
+                            pointerEvent->value;                        
+                    } else  if (pointerEvent->code == ABS_MT_TOUCH_MAJOR && pointerEvent->value == 0) {
+                        //release event
+                        numOfReleasePoints++;
+                    }
                 }
                 break;
             case EV_SYN:
@@ -1540,11 +1557,11 @@
     //assigning ID and determining state will be done in touch shared code
     //below
     if (device->touchProtocolType == TOUCH_PROTOCOL_ST) {
-        GLASS_LOG_FINEST("ST device event, touchButtonValue = %d",
+        GLASS_LOG_FINEST("[preprocessing ST] device event, touchButtonValue = %d",
                          touchButtonValue);
         //if BTN_TOUCH was sent it must be honored
         if (touchButtonValue == 1) {
-            GLASS_LOG_FINEST("ST - pressed on %d %d",
+            GLASS_LOG_FINEST("[preprocessing ST] pressed on %d %d",
                              mouseState->pressedX,
                              mouseState->pressedY);
             //we need to record only pressed events
@@ -1552,16 +1569,16 @@
             mouseState->pendingTouchXs[0] = mouseState->pressedX;
             mouseState->pendingTouchYs[0] = mouseState->pressedY;
         } else if (touchButtonValue == -1 && mouseState->pressedX != -1 && mouseState->pressedY != -1) {
-            GLASS_LOG_FINEST("ST - press event with no button on %d %d",
+            GLASS_LOG_FINEST("[preprocessing ST] press event with no button on %d %d",
                              mouseState->pressedX,
                              mouseState->pressedY);
             //we have a touch event without a BTN_TOUCH event
             mouseState->pendingTouchPointCount = 1; //we always have 1 event
             mouseState->pendingTouchXs[0] = mouseState->pressedX;
-            mouseState->pendingTouchYs[0] = mouseState->pressedY;            
+            mouseState->pendingTouchYs[0] = mouseState->pressedY;
         } else if (touchButtonValue == 0) {
             //release
-             GLASS_LOG_FINEST("ST - RELEASE");
+            GLASS_LOG_FINEST("[preprocessing ST] RELEASE");
 
         }
     }
@@ -1585,18 +1602,76 @@
      * intersted in the pressed points we need to make sure that
      * pendingTouchPointCount holds the correct number of points
      */
-    if (device->touchProtocolType == TOUCH_PROTOCOL_MT_A) {
-        if (numOfMTPoints < mouseState->pendingTouchPointCount) {             
-             GLASS_LOG_FINEST("MT_A - updating pendingTouchPointCount from "
+    if (device->touchProtocolType == TOUCH_PROTOCOL_MT_A && !isPartialProtocolB) {
+        if (numOfUpdatePoints < mouseState->pendingTouchPointCount) {             
+             GLASS_LOG_FINEST("[preprocessing MT_A] updating pendingTouchPointCount from "
                               "%d to %d",
                               mouseState->pendingTouchPointCount,
-                              numOfMTPoints);
-             mouseState->pendingTouchPointCount = numOfMTPoints;
-        } else if (numOfMTPoints > mouseState->pendingTouchPointCount) {
-            GLASS_LOG_SEVERE("malformed multi touch event - ignoring");
+                              numOfUpdatePoints);
+             mouseState->pendingTouchPointCount = numOfUpdatePoints;
+        } else if (numOfUpdatePoints > mouseState->pendingTouchPointCount) {
+            GLASS_LOG_SEVERE("[preprocessing MT_A] malformed multi touch event - ignoring");
             mouseState->pendingInputEventCount = 0;
             return;
         }
+    } else if (isPartialProtocolB) {
+        /**
+         * we are counting 3 things: 
+         * 1) total touch events -> mouseState->pendingTouchPointCount
+         * 2) number of update events (press, move...) 
+         * -> numOfUpdatePoints 
+         * 3) number of release events -> numOfReleasePoints 
+         *  
+         * In this mode total event can't be greater then update event, 
+         * but we can have remove events without update events. So we 
+         * check for this condition and handle it here 
+         *  
+         */
+
+         GLASS_LOG_FINEST("[preprocessing MIXED] total touch events %d, update "
+                          "events %d, release events %d" ,
+                          mouseState->pendingTouchPointCount,
+                          numOfUpdatePoints,
+                          numOfReleasePoints);
+        if (numOfReleasePoints == mouseState->pendingTouchPointCount && numOfUpdatePoints == 0) {
+            /**
+             * all reported points are points to be released according to 
+             * their tracking ID. 
+             * Traverse over existing points and copy non-released points to 
+             * pending points array so in the end we will provide a well 
+             * formated list for further processing which is compliant with 
+             * Protocol A processing 
+             */
+            int actualCount = 0;
+            GLASS_LOG_FINEST("[preprocessing MIXED] touchPointCount = %d , "
+                             "pendingTouchPointCount %d",
+                             mouseState->touchPointCount,
+                             mouseState->pendingTouchPointCount);
+            for (i = 0; i < mouseState->touchPointCount; i++) {
+                int j;
+                jboolean matchFound = JNI_FALSE;
+                for (j = 0; j < mouseState->pendingTouchPointCount; j++) {
+                    if (mouseState->pendingTouchTrackingIDs[j] == mouseState->touchTrackingIDs[i]) {
+                        GLASS_LOG_FINEST("[preprocessing MIXED] releasing "
+                                         "existing point %d ,id %d, tracking id %d",
+                                         i,
+                                         mouseState->touchIDs[i],
+                                         mouseState->touchTrackingIDs[i]);
+                        matchFound = JNI_TRUE;
+                        break;
+                    }
+                }
+
+                if (!matchFound) {
+                    //exsisting point is still valid, copy it to pending list
+                    mouseState->pendingTouchTrackingIDs[actualCount] = mouseState->touchTrackingIDs[i];
+                    mouseState->pendingTouchXs[actualCount] = mouseState->touchXs[i];
+                    mouseState->pendingTouchYs[actualCount] = mouseState->touchYs[i];
+                    actualCount++;
+                }
+            }
+            mouseState->pendingTouchPointCount = actualCount;
+        }
     }
 
     //at this point ST devices and MT_A devices touch points are registered
@@ -1712,6 +1787,7 @@
     jlong ids[LENS_MAX_TOUCH_POINTS];
     int xs[LENS_MAX_TOUCH_POINTS];
     int ys[LENS_MAX_TOUCH_POINTS];
+    int deviceIDs[LENS_MAX_TOUCH_POINTS];
     jboolean needToSavePendingPoints = JNI_TRUE;
 
     if (mouseState->pendingTouchPointCount) {
@@ -1733,6 +1809,9 @@
                     int dX = newX - oldX;
                     int dY = newY - oldY;
 
+                    //save current point ID that was assigned by the device
+                    int newDeviceID = mouseState->pendingTouchTrackingIDs[j];
+
                     //touch point get a move only when its moved out the tap radius
                     //after first move (dragging) all moves should be reported 
                     //as long as the move event is bigger then gTouchMoveSensitivity
@@ -1775,6 +1854,7 @@
                             GLASS_LOG_FINEST("point %d tap radius check -> MOVE", count+1);
                         }
                     }
+                    deviceIDs[count] = newDeviceID;
                     matched = JNI_TRUE;
                 }
             }
@@ -1803,6 +1883,7 @@
                 ids[count] = id;
                 xs[count] = mouseState->pendingTouchXs[i];
                 ys[count] = mouseState->pendingTouchYs[i];
+                deviceIDs[count] = mouseState->pendingTouchTrackingIDs[i];
                 states[count] = com_sun_glass_events_TouchEvent_TOUCH_PRESSED;
                 mouseState->touchIsDragging[i] = JNI_FALSE;
                 GLASS_LOG_FINEST("point %d - no match -> PRESSED", count+1);
@@ -2012,11 +2093,13 @@
                 mouseState->touchIDs[activeTouchPointsCount] = ids[i];
                 mouseState->touchXs[activeTouchPointsCount] = xs[i];
                 mouseState->touchYs[activeTouchPointsCount] = ys[i];
-                GLASS_LOG_FINEST("[store points] Touch point %i at %i, %i (id=%i)",
+                mouseState->touchTrackingIDs[activeTouchPointsCount] = deviceIDs[i];
+                GLASS_LOG_FINEST("[store points] Touch point %i at %i, %i (id=%i, deviceId=%i)",
                                  i,
                                  mouseState->touchXs[activeTouchPointsCount],
                                  mouseState->touchYs[activeTouchPointsCount],
-                                 mouseState->touchIDs[activeTouchPointsCount]);
+                                 mouseState->touchIDs[activeTouchPointsCount],
+                                 mouseState->touchTrackingIDs[activeTouchPointsCount]);
                 activeTouchPointsCount++;
 
             }
