diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c
index 64cf34e..d8d79d3 100644
--- a/drivers/input/mouse/synaptics_usb.c
+++ b/drivers/input/mouse/synaptics_usb.c
@@ -8,6 +8,8 @@
  *  Copyright (c) 2004 Jan Steinhoff (cpad@jan-steinhoff . de)
  *  Copyright (c) 2004 Ron Lee (ron@debian.org)
  *	rewritten for kernel 2.6
+ *  Copyright (c) 2013 Zach Carlson (FxChiP@Gmail.com)
+ *      Razer Blade / multi-finger-struct synaptics touchpad support
  *
  *  cPad display character device part is not included. It can be found at
  *  http://jan-steinhoff.de/linux/synaptics-usb.html
@@ -44,19 +46,23 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/usb.h>
+#include <linux/input/mt.h>
 #include <linux/input.h>
 #include <linux/usb/input.h>
 
-#define USB_VENDOR_ID_SYNAPTICS	0x06cb
-#define USB_DEVICE_ID_SYNAPTICS_TP	0x0001	/* Synaptics USB TouchPad */
-#define USB_DEVICE_ID_SYNAPTICS_INT_TP	0x0002	/* Integrated USB TouchPad */
-#define USB_DEVICE_ID_SYNAPTICS_CPAD	0x0003	/* Synaptics cPad */
-#define USB_DEVICE_ID_SYNAPTICS_TS	0x0006	/* Synaptics TouchScreen */
-#define USB_DEVICE_ID_SYNAPTICS_STICK	0x0007	/* Synaptics USB Styk */
-#define USB_DEVICE_ID_SYNAPTICS_WP	0x0008	/* Synaptics USB WheelPad */
-#define USB_DEVICE_ID_SYNAPTICS_COMP_TP	0x0009	/* Composite USB TouchPad */
-#define USB_DEVICE_ID_SYNAPTICS_WTP	0x0010	/* Wireless TouchPad */
-#define USB_DEVICE_ID_SYNAPTICS_DPAD	0x0013	/* DisplayPad */
+#define USB_VENDOR_ID_SYNAPTICS	        0x06cb
+#define USB_VENDOR_ID_SYNUSB_RAZER      0x1532
+
+#define USB_DEVICE_ID_SYNAPTICS_TP	       0x0001	/* Synaptics USB TouchPad */
+#define USB_DEVICE_ID_SYNAPTICS_INT_TP	       0x0002	/* Integrated USB TouchPad */
+#define USB_DEVICE_ID_SYNAPTICS_CPAD	       0x0003	/* Synaptics cPad */
+#define USB_DEVICE_ID_SYNAPTICS_TS	       0x0006	/* Synaptics TouchScreen */
+#define USB_DEVICE_ID_SYNAPTICS_STICK	       0x0007	/* Synaptics USB Styk */
+#define USB_DEVICE_ID_SYNAPTICS_WP	       0x0008	/* Synaptics USB WheelPad */
+#define USB_DEVICE_ID_SYNAPTICS_COMP_TP	       0x0009	/* Composite USB TouchPad */
+#define USB_DEVICE_ID_SYNAPTICS_WTP	       0x0010	/* Wireless TouchPad */
+#define USB_DEVICE_ID_SYNAPTICS_DPAD	       0x0013	/* DisplayPad */
+#define USB_DEVICE_ID_SYNUSB_RAZER_BLADE_TP    0x0116  	/* Razer Blade Touchpad */
 
 #define SYNUSB_TOUCHPAD			(1 << 0)
 #define SYNUSB_STICK			(1 << 1)
@@ -64,19 +70,32 @@
 #define SYNUSB_AUXDISPLAY		(1 << 3) /* For cPad */
 #define SYNUSB_COMBO			(1 << 4) /* Composite device (TP + stick) */
 #define SYNUSB_IO_ALWAYS		(1 << 5)
+#define SYNUSB_MF_PACKETS               (1 << 6) /* Multi-finger packets */
+#define SYNUSB_SHARES_DEVICE            (1 << 7) /* Shares device with other inputs */
 
 #define USB_DEVICE_SYNAPTICS(prod, kind)		\
 	USB_DEVICE(USB_VENDOR_ID_SYNAPTICS,		\
 		   USB_DEVICE_ID_SYNAPTICS_##prod),	\
 	.driver_info = (kind),
 
+#define USB_DEVICE_SYNUSB_RAZER(prod, kind)	        \
+	USB_DEVICE(USB_VENDOR_ID_SYNUSB_RAZER,		\
+		   USB_DEVICE_ID_SYNUSB_RAZER_##prod),	        \
+	.driver_info = (kind),
+
 #define SYNUSB_RECV_SIZE	8
+#define SYNUSB_MF_RECV_SIZE     64
 
 #define XMIN_NOMINAL		1472
 #define XMAX_NOMINAL		5472
 #define YMIN_NOMINAL		1408
 #define YMAX_NOMINAL		4448
 
+#define XMIN_NOMINAL_RZR        1181
+#define XMAX_NOMINAL_RZR        5888
+#define YMIN_NOMINAL_RZR        1056
+#define YMAX_NOMINAL_RZR        4686
+
 struct synusb {
 	struct usb_device *udev;
 	struct usb_interface *intf;
@@ -129,31 +148,40 @@ static void synusb_report_touchpad(struct synusb *synusb)
 	unsigned int num_fingers, tool_width;
 	unsigned int x, y;
 	unsigned int pressure, w;
-
-	pressure = synusb->data[6];
-	x = be16_to_cpup((__be16 *)&synusb->data[2]);
-	y = be16_to_cpup((__be16 *)&synusb->data[4]);
-	w = synusb->data[0] & 0x0f;
-
-	if (pressure > 0) {
-		num_fingers = 1;
-		tool_width = 5;
-		switch (w) {
-		case 0 ... 1:
-			num_fingers = 2 + w;
-			break;
-
-		case 2:	                /* pen, pretend its a finger */
-			break;
-
-		case 4 ... 15:
-			tool_width = w;
-			break;
+	unsigned int finger_index, packet_offset;
+	unsigned short already_submitted = 0;
+
+	for (finger_index = 0;
+	     finger_index < (synusb->flags & SYNUSB_MF_PACKETS ? 5 :  1);
+	     finger_index++) {
+		packet_offset = finger_index * 8; 
+
+		pressure = synusb->data[packet_offset+6];
+		x = be16_to_cpup((__be16 *)&synusb->data[packet_offset+2]);
+		y = be16_to_cpup((__be16 *)&synusb->data[packet_offset+4]);
+		w = synusb->data[packet_offset] & 0x0f;
+
+		if (pressure > 0) {
+			num_fingers = (synusb->flags & SYNUSB_MF_PACKETS ? synusb->data[packet_offset+7] >> 4 : 1);
+			tool_width = 5;
+			switch (w) {
+			case 0 ... 1:
+				/* The finger-count delimiter is always correct */
+				if (!(synusb->flags & SYNUSB_MF_PACKETS))
+					num_fingers = 2 + w;
+				break;
+
+			case 2:	                /* pen, pretend its a finger */
+				break;
+
+			case 3 ... 15:
+				tool_width = w;
+				break;
+			}
+		} else {
+			num_fingers = (synusb->flags & SYNUSB_MF_PACKETS) ? synusb->data[packet_offset+7] >> 4 : 0;
+			tool_width = 0;
 		}
-	} else {
-		num_fingers = 0;
-		tool_width = 0;
-	}
 
 	/*
 	 * Post events
@@ -161,27 +189,56 @@ static void synusb_report_touchpad(struct synusb *synusb)
 	 * absolute -> relative conversion
 	 */
 
-	if (pressure > 30)
-		input_report_key(input_dev, BTN_TOUCH, 1);
-	if (pressure < 25)
-		input_report_key(input_dev, BTN_TOUCH, 0);
-
-	if (num_fingers > 0) {
-		input_report_abs(input_dev, ABS_X, x);
-		input_report_abs(input_dev, ABS_Y,
-				 YMAX_NOMINAL + YMIN_NOMINAL - y);
+		if (synusb->flags & SYNUSB_MF_PACKETS) {
+			input_mt_slot(input_dev, synusb->data[packet_offset+7] & 0x0F);
+			input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, (pressure > 30));
+			if (pressure > 30) {
+				if (already_submitted == 0) {
+					/* First finger with pressure should emulate mouse...
+					 * but ONLY if it is the ONLY finger. (Otherwise, gestures
+					 * should be processed) */
+					input_mt_report_pointer_emulation(input_dev, 
+					                                  (pressure > 30 && num_fingers == 1)
+									 );
+					already_submitted = 1;
+				}
+				input_report_abs(input_dev, ABS_MT_POSITION_X, x);
+				input_report_abs(input_dev, ABS_MT_POSITION_Y, 
+				                 YMAX_NOMINAL_RZR + YMIN_NOMINAL_RZR - y);
+				input_report_abs(input_dev, ABS_MT_PRESSURE, pressure);
+				input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, tool_width);
+			}
+
+			if (finger_index == 4) {
+				// Final finger count = report
+				input_mt_report_finger_count(input_dev, num_fingers);
+			}
+
+
+		} else {
+			if (pressure > 30)
+				input_report_key(input_dev, BTN_TOUCH, 1);
+			if (pressure < 25)
+				input_report_key(input_dev, BTN_TOUCH, 0);
+
+			if (num_fingers > 0) {
+				input_report_abs(input_dev, ABS_X, x);
+				input_report_abs(input_dev, ABS_Y,
+						 YMAX_NOMINAL + YMIN_NOMINAL - y);
+			}
+
+			input_report_abs(input_dev, ABS_PRESSURE, pressure);
+			input_report_abs(input_dev, ABS_TOOL_WIDTH, tool_width);
+
+			input_report_key(input_dev, BTN_TOOL_FINGER, num_fingers == 1);
+			input_report_key(input_dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
+			input_report_key(input_dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
+
+			if (synusb->flags & SYNUSB_AUXDISPLAY)
+				input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x08);
+		}
 	}
-
-	input_report_abs(input_dev, ABS_PRESSURE, pressure);
-	input_report_abs(input_dev, ABS_TOOL_WIDTH, tool_width);
-
-	input_report_key(input_dev, BTN_TOOL_FINGER, num_fingers == 1);
-	input_report_key(input_dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
-	input_report_key(input_dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
-
 	synusb_report_buttons(synusb);
-	if (synusb->flags & SYNUSB_AUXDISPLAY)
-		input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x08);
 
 	input_sync(input_dev);
 }
@@ -293,6 +350,14 @@ static int synusb_probe(struct usb_interface *intf,
 	unsigned int intf_num = intf->cur_altsetting->desc.bInterfaceNumber;
 	unsigned int altsetting = min(intf->num_altsetting, 1U);
 	int error;
+	size_t recv_size = SYNUSB_RECV_SIZE;
+
+	if (id->driver_info & SYNUSB_SHARES_DEVICE) {
+		/* XXX: Trackpad on interface 0. Hack to ignore other interfaces until better method found. */
+		/* Must NOT bind to keyboards, etc. */
+		if (intf_num > 0)
+			return -ENODEV;
+	}
 
 	error = usb_set_interface(udev, intf_num, altsetting);
 	if (error) {
@@ -327,13 +392,16 @@ static int synusb_probe(struct usb_interface *intf,
 					SYNUSB_STICK : SYNUSB_TOUCHPAD;
 	}
 
+	if (synusb->flags & SYNUSB_MF_PACKETS)
+		recv_size = SYNUSB_MF_RECV_SIZE;
+
 	synusb->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!synusb->urb) {
 		error = -ENOMEM;
 		goto err_free_mem;
 	}
 
-	synusb->data = usb_alloc_coherent(udev, SYNUSB_RECV_SIZE, GFP_KERNEL,
+	synusb->data = usb_alloc_coherent(udev, recv_size, GFP_KERNEL,
 					  &synusb->urb->transfer_dma);
 	if (!synusb->data) {
 		error = -ENOMEM;
@@ -342,7 +410,7 @@ static int synusb_probe(struct usb_interface *intf,
 
 	usb_fill_int_urb(synusb->urb, udev,
 			 usb_rcvintpipe(udev, ep->bEndpointAddress),
-			 synusb->data, SYNUSB_RECV_SIZE,
+			 synusb->data, recv_size,
 			 synusb_irq, synusb,
 			 ep->bInterval);
 	synusb->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -366,6 +434,13 @@ static int synusb_probe(struct usb_interface *intf,
 	if (synusb->flags & SYNUSB_STICK)
 		strlcat(synusb->name, " (Stick)", sizeof(synusb->name));
 
+	if (synusb->flags & SYNUSB_MF_PACKETS)
+		strlcat(synusb->name, " (MT)", sizeof(synusb->name));
+	
+	if (synusb->flags & SYNUSB_SHARES_DEVICE) 
+		strlcat(synusb->name, " (shared)", sizeof(synusb->name));
+
+
 	usb_make_path(udev, synusb->phys, sizeof(synusb->phys));
 	strlcat(synusb->phys, "/input0", sizeof(synusb->phys));
 
@@ -384,6 +459,15 @@ static int synusb_probe(struct usb_interface *intf,
 	__set_bit(EV_ABS, input_dev->evbit);
 	__set_bit(EV_KEY, input_dev->evbit);
 
+	if (synusb->flags & SYNUSB_MF_PACKETS) {
+		input_mt_init_slots(input_dev, 5, INPUT_MT_POINTER);
+		input_set_abs_params(input_dev, ABS_MT_POSITION_X, 
+		                     XMIN_NOMINAL_RZR, XMAX_NOMINAL_RZR, 0, 0);
+		input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+		                     YMIN_NOMINAL_RZR, YMAX_NOMINAL_RZR, 0, 0);
+		input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 15, 0, 0);
+	}
+
 	if (synusb->flags & SYNUSB_STICK) {
 		__set_bit(EV_REL, input_dev->evbit);
 		__set_bit(REL_X, input_dev->relbit);
@@ -428,7 +512,7 @@ err_stop_io:
 	if (synusb->flags & SYNUSB_IO_ALWAYS)
 		synusb_close(synusb->input);
 err_free_dma:
-	usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data,
+	usb_free_coherent(udev, recv_size, synusb->data,
 			  synusb->urb->transfer_dma);
 err_free_urb:
 	usb_free_urb(synusb->urb);
@@ -444,13 +528,17 @@ static void synusb_disconnect(struct usb_interface *intf)
 {
 	struct synusb *synusb = usb_get_intfdata(intf);
 	struct usb_device *udev = interface_to_usbdev(intf);
+	size_t recv_size = SYNUSB_RECV_SIZE;
 
 	if (synusb->flags & SYNUSB_IO_ALWAYS)
 		synusb_close(synusb->input);
 
+	if (synusb->flags & SYNUSB_MF_PACKETS)
+		recv_size = SYNUSB_MF_RECV_SIZE;
+
 	input_unregister_device(synusb->input);
 
-	usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data,
+	usb_free_coherent(udev, recv_size, synusb->data,
 			  synusb->urb->transfer_dma);
 	usb_free_urb(synusb->urb);
 	kfree(synusb);
@@ -531,6 +619,7 @@ static struct usb_device_id synusb_idtable[] = {
 	{ USB_DEVICE_SYNAPTICS(COMP_TP, SYNUSB_COMBO) },
 	{ USB_DEVICE_SYNAPTICS(WTP, SYNUSB_TOUCHPAD) },
 	{ USB_DEVICE_SYNAPTICS(DPAD, SYNUSB_TOUCHPAD) },
+	{ USB_DEVICE_SYNUSB_RAZER(BLADE_TP, SYNUSB_TOUCHPAD | SYNUSB_MF_PACKETS | SYNUSB_SHARES_DEVICE) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, synusb_idtable);
