I'm pretty much set myself, now that I have it working the way I like. I just figured I'd try to wrap it up and send it where it might be useful. I'd like to avoid rolling my on driver forever :) I think I'm going to skip on adding more X buttons for the touch detection on the tablet buttons, xf86-input-wacom looks like it would take a while for me to figure out, and then I'd have to write a separate program to do pop-ups like the window's driver does, i.e. too much work.

In all things I defer to your expertise on this, as I haven't done much system programming or contributions to open source projects.

I agree about using the uniq field was poorly thought out, but that was the very first thing I did to get the tablet to be recognized in ubuntu properly. Then I realized that the leds weren't working so I spent some time learning about sysfs, and using wireshark to do some USB sniffing. Everything I got was figured out by sniffing the USB going to a windows VM. So I really have no idea about what the protocols are supposed to be.


On 03/26/2014 07:31 PM, Jason Gerecke wrote:
Thanks for the patch! I've added my comments in-line below :)

Firstly though, it looks like your patch was mangled along the way, so
I haven't been able to give it a whirl... In the future I'd suggest
either attaching the patches as files, or using `git send-email`.
I've attached the original two patches as you suggested.
You should introduce an e.g. WAC_CMD_WIRELESS_CONTROL macro rather
than use a magic constant.
Agreed.
Way more complex than it needs to be. `int crop_lum =
wacom->led.crop_lum & 0x03` should be all you need.
I gave crop_lum the same range as ring_lum since they are controlled by the same slider in windows, which seems to have a large range even though the Intuos Pro only support 4 values. I wasn't sure if limiting the range would be too premature, plus I liked keeping it consistent with the other ranges of values for led brightness.
This doesn't quite jibe with the protocol docs that I have. buf[2]
contains a "powersave" (EMR low-power mode) timer. The "sleep"
(EMR/MFT/wireless minimum power) timer is controlled by buf[1]. If
you'd like to export both timers through sysfs, that'd be awesome :)
The value in buf[2] was exactly the same as the number of minutes that the windows driver displayed. The windows driver is also probably wrong if what you say is correct. Which is most likely as setting it in windows didn't really seem to have the correct effect. Setting it to 1 minute, it didn't go to sleep for 30 minutes some times, regardless of being left alone. Other times is slept quite quickly.
-    return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]);    \
+    return snprintf(buf, 3, "%d\n", wacom->led.select[SET_ID]);    \
Keen eye.
For the sysfs show functions I would have prefered to do snprintf(buf, PAGE_SIZE, ... ) like sysfs.txt suggests, but when in rome ...
+    wacom->sleep_timer = clamp_val(time, 1, 20);
Valid values are from 5 to 60 (below the tablet defaults to 15 minute
sleep; above it disables sleep). For the powersave timer, they're 1 to
60 (below, 1 minute default; above disabled)

We might want to have seperate attributes that allow the user to
explicitely disable/default the timers, or possibly allow these to
take special values (0 = disabled, -1 = default?). Whatever the
decision, our sysfs documentaiton should be updated to reflect it.
The values for the sleep timer only goes from 1 to 20 in windows, so I copied that. I do like your suggestions much better.
+    return snprintf(buf, 5, "%d\n", wacom->sleep_timer);
Only need 4, not 5.
Yes, bad math ... should have just used PAGE_SIZE.
+            wacom->led.crop_lum = 32;
Should be `wacom->led.crop_lum = 2`
Staying consistent with llv and hlv.
+    if (wacom_wac->uniq[0] == 0) {
+        if (wacom_wac->features.quirks & WACOM_QUIRK_WIRELESS_KIT)
+            snprintf(wacom_wac->uniq, WACOM_UNIQ_MAX, "056a:%04x",
+                 wacom_wac->pid);
Instead of hardcoding "056a" into the string, use USB_VENDOR_ID_WACOM.
Doh!
+        else
+            snprintf(wacom_wac->uniq, WACOM_UNIQ_MAX, "%04x:%04x",
+            dev->descriptor.idVendor, dev->descriptor.idProduct);
+    }
+
      input_dev->name = wacom_wac->name;
+    input_dev->uniq = wacom_wac->uniq;
The tablet VID:PID isn't a unique enough identifier to be stored in
the `uniq` field. You should add a sysfs attribute to the wireless
group which exports the information.
Agree completely, but after going through the trouble of adding the wacom_wireless sysfs group, I realized I should move the wireless tablet pid there, but the sleep timer was the last thing I did, and redoing previous work when I finally got everything working was too much.
+
+    switch (wacom_features->type) {
+    case INTUOSPS:
+    case INTUOSPM:
+    case INTUOSPL:
All wireless tablets should have this particular group, IIRC. Bamboo
PIDs 0xDC-0xDF, Intuos, Intuos5, and Intuos Pro.
Wasn't sure if they worked the same.
+        if (wacom_features->device_type == BTN_TOOL_PEN) {
+            wacom->sleep_timer = 2;
The default value for this and the powersave timer are 15 minutes and
1 minute respectively. You should set them to zero to use the hardware
default.

The windows default was 2. I wasn't sure if 0 meant never sleep and I don't like killing my batteries.
Jason
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one  /
(That is to say, eight) to the two,     /
But you can’t take seven from three,    /
So you look at the sixty-fours....

 {3.7-0 => 3.7-1}/wacom.h     |   2 +
 {3.7-0 => 3.7-1}/wacom_sys.c | 241 ++++++++++++++++++++++++++++++++++++-------
 {3.7-0 => 3.7-1}/wacom_wac.h |   3 +
 3 files changed, 208 insertions(+), 38 deletions(-)

diff --git a/3.7-0/wacom.h b/3.7-1/wacom.h
index b79d451..cb49f84 100644
--- a/3.7-0/wacom.h
+++ b/3.7-1/wacom.h
@@ -121,8 +121,10 @@ struct wacom {
 		u8 llv;       /* status led brightness no button (1..127) */
 		u8 hlv;       /* status led brightness button pressed (1..127) */
 		u8 img_lum;   /* OLED matrix display brightness */
+		u8 crop_lum;  /* crop marks led brightness (1..127) */
 	} led;
 	struct power_supply battery;
+	u8 sleep_timer; /* wireless tablet sleeps after X minutes idle (1..20) */
 };
 
 static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
diff --git a/3.7-0/wacom_sys.c b/3.7-1/wacom_sys.c
index 8de1cc3..0da44a7 100644
--- a/3.7-0/wacom_sys.c
+++ b/3.7-1/wacom_sys.c
@@ -713,9 +713,19 @@ static void wacom_remove_shared_data(struct wacom_wac *wacom)
 static int wacom_led_control(struct wacom *wacom)
 {
 	unsigned char *buf;
+	int buf_size;
+	int command;
 	int retval;
+	
+	if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_WIRELESS_KIT) {
+		command = 0x03;
+		buf_size = 13;
+	} else {
+		command = WAC_CMD_LED_CONTROL;
+		buf_size = 9;
+	}
 
-	buf = kzalloc(9, GFP_KERNEL);
+	buf = kzalloc(buf_size, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
@@ -728,10 +738,19 @@ static int wacom_led_control(struct wacom *wacom)
 		 */
 		int ring_led = wacom->led.select[0] & 0x03;
 		int ring_lum = (((wacom->led.llv & 0x60) >> 5) - 1) & 0x03;
-		int crop_lum = 0;
+		int crop_lum = (((wacom->led.crop_lum & 0x60) >> 5) - 1) & 0x03;
+		int bits = (crop_lum << 4) | (ring_lum << 2) | (ring_led);
 
-		buf[0] = WAC_CMD_LED_CONTROL;
-		buf[1] = (crop_lum << 4) | (ring_lum << 2) | (ring_led);
+		if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_WIRELESS_KIT) {
+			buf[2] = wacom->sleep_timer;
+			buf[3] = 0x04;
+			buf[4] = 0x40 | bits;
+		} else {
+			buf[1] = bits;
+			
+			if (wacom->wacom_wac.features.type >= INTUOSPS)
+				buf[2] = ring_lum;
+		}
 	}
 	else {
 		int led = wacom->led.select[0] | 0x4;
@@ -740,15 +759,15 @@ static int wacom_led_control(struct wacom *wacom)
 		    wacom->wacom_wac.features.type == WACOM_24HD)
 			led |= (wacom->led.select[1] << 4) | 0x40;
 
-		buf[0] = WAC_CMD_LED_CONTROL;
 		buf[1] = led;
 		buf[2] = wacom->led.llv;
 		buf[3] = wacom->led.hlv;
 		buf[4] = wacom->led.img_lum;
 	}
 
-	retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL,
-				  buf, 9, WAC_CMD_RETRIES);
+	buf[0] = command;
+	retval = wacom_set_report(wacom->intf, 0x03, command, buf, buf_size,
+				  WAC_CMD_RETRIES);
 	kfree(buf);
 
 	return retval;
@@ -825,7 +844,7 @@ static ssize_t wacom_led##SET_ID##_select_show(struct device *dev,	\
 	struct device_attribute *attr, char *buf)			\
 {									\
 	struct wacom *wacom = dev_get_drvdata(dev);			\
-	return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]);	\
+	return snprintf(buf, 3, "%d\n", wacom->led.select[SET_ID]);	\
 }									\
 static DEVICE_ATTR(status_led##SET_ID##_select, S_IWUSR | S_IRUSR,	\
 		    wacom_led##SET_ID##_select_show,			\
@@ -863,11 +882,19 @@ static ssize_t wacom_##name##_luminance_store(struct device *dev,	\
 	return wacom_luminance_store(wacom, &wacom->led.field,		\
 				     buf, count);			\
 }									\
-static DEVICE_ATTR(name##_luminance, S_IWUSR,				\
-		   NULL, wacom_##name##_luminance_store)
+static ssize_t wacom_##name##_luminance_show(struct device *dev,	\
+	struct device_attribute *attr, char *buf)			\
+{									\
+	struct wacom *wacom = dev_get_drvdata(dev);			\
+	return snprintf(buf, 5, "%d\n", wacom->led.field);	\
+}									\
+static DEVICE_ATTR(name##_luminance, S_IWUSR | S_IRUSR,			\
+		   wacom_##name##_luminance_show,			\
+		   wacom_##name##_luminance_store)
 
 DEVICE_LUMINANCE_ATTR(status0, llv);
 DEVICE_LUMINANCE_ATTR(status1, hlv);
+DEVICE_LUMINANCE_ATTR(crop_marks, crop_lum);
 DEVICE_LUMINANCE_ATTR(buttons, img_lum);
 
 static ssize_t wacom_button_image_store(struct device *dev, int button_id,
@@ -906,6 +933,48 @@ DEVICE_BTNIMG_ATTR(5);
 DEVICE_BTNIMG_ATTR(6);
 DEVICE_BTNIMG_ATTR(7);
 
+static ssize_t wacom_sleep_timer_store(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
+{
+	struct wacom *wacom = dev_get_drvdata(dev);
+	unsigned int time;
+	int err;
+
+	err = kstrtouint(buf, 10, &time);
+	if (err)
+		return err;
+
+	mutex_lock(&wacom->lock);
+	
+	wacom->sleep_timer = clamp_val(time, 1, 20);
+	err = wacom_led_control(wacom);
+
+	mutex_unlock(&wacom->lock);
+
+	return err < 0 ? err : count;
+}
+
+static ssize_t wacom_sleep_timer_show(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct wacom *wacom = dev_get_drvdata(dev);
+	return snprintf(buf, 5, "%d\n", wacom->sleep_timer);
+}
+
+static DEVICE_ATTR(sleep_timer, S_IWUSR | S_IRUSR, wacom_sleep_timer_show,
+		   wacom_sleep_timer_store);
+
+static struct attribute *wireless_attrs[] = {
+	&dev_attr_sleep_timer.attr,
+	NULL
+};
+
+static struct attribute_group wireless_attr_group = {
+	.name = "wacom_wireless",
+	.attrs = wireless_attrs,
+};
+
 static struct attribute *cintiq_led_attrs[] = {
 	&dev_attr_status_led0_select.attr,
 	&dev_attr_status_led1_select.attr,
@@ -940,6 +1009,7 @@ static struct attribute_group intuos4_led_attr_group = {
 
 static struct attribute *intuos5_led_attrs[] = {
 	&dev_attr_status0_luminance.attr,
+	&dev_attr_crop_marks_luminance.attr,
 	&dev_attr_status_led0_select.attr,
 	NULL
 };
@@ -990,6 +1060,7 @@ static int wacom_initialize_leds(struct wacom *wacom)
 			wacom->led.select[1] = 0;
 			wacom->led.llv = 32;
 			wacom->led.hlv = 0;
+			wacom->led.crop_lum = 32;
 			wacom->led.img_lum = 0;
 
 			error = sysfs_create_group(&wacom->intf->dev.kobj,
@@ -1004,7 +1075,7 @@ static int wacom_initialize_leds(struct wacom *wacom)
 
 	if (error) {
 		dev_err(&wacom->intf->dev,
-			"cannot create sysfs group err: %d\n", error);
+			"cannot create 'wacom_led' sysfs group: err %d\n", error);
 		return error;
 	}
 	wacom_led_control(wacom);
@@ -1111,7 +1182,17 @@ static int wacom_register_input(struct wacom *wacom)
 		goto fail1;
 	}
 
+	if (wacom_wac->uniq[0] == 0) {
+		if (wacom_wac->features.quirks & WACOM_QUIRK_WIRELESS_KIT)
+			snprintf(wacom_wac->uniq, WACOM_UNIQ_MAX, "056a:%04x",
+				 wacom_wac->pid);
+		else
+			snprintf(wacom_wac->uniq, WACOM_UNIQ_MAX, "%04x:%04x",
+			dev->descriptor.idVendor, dev->descriptor.idProduct);
+	}
+
 	input_dev->name = wacom_wac->name;
+	input_dev->uniq = wacom_wac->uniq;
 	input_dev->dev.parent = &intf->dev;
 	input_dev->open = wacom_open;
 	input_dev->close = wacom_close;
@@ -1136,6 +1217,102 @@ fail1:
 	return error;
 }
 
+static void wacom_unregister_wireless(struct wacom *wacom)
+{
+	struct wacom_features *wacom_features = &wacom->wacom_wac.features;
+	
+	if (!(wacom_features->quirks & WACOM_QUIRK_WIRELESS_KIT))
+		return;
+
+	switch (wacom_features->type) {
+	case INTUOSPS:
+	case INTUOSPM:
+	case INTUOSPL:
+		if (wacom_features->device_type == BTN_TOOL_PEN) {
+			sysfs_remove_group(&wacom->intf->dev.kobj,
+					   &wireless_attr_group);
+		}
+		break;
+	}
+}
+
+static int wacom_register_wireless(struct wacom *wacom)
+{
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *wacom_features = &wacom_wac->features;
+	int error;
+
+	if (!(wacom_features->quirks & WACOM_QUIRK_WIRELESS_KIT))
+		return 0;
+
+	/* Initialize default values */
+	switch (wacom_features->type) {
+	case INTUOSPS:
+	case INTUOSPM:
+	case INTUOSPL:
+		if (wacom_features->device_type == BTN_TOOL_PEN) {
+			wacom->sleep_timer = 2;
+
+			error = sysfs_create_group(&wacom->intf->dev.kobj,
+						  &wireless_attr_group);
+		} else
+			return 0;
+		break;
+
+	default:
+		return 0;
+	}
+
+	if (error) {
+		dev_err(&wacom->intf->dev,
+			"cannot create 'wacom_wireless' sysfs group: err %d\n",
+			error);
+		return error;
+	}
+	wacom_led_control(wacom);
+	
+	return 0;
+}
+
+static void wacom_unregister(struct wacom *wacom)
+{
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	
+	if (wacom_wac->input) {
+		input_unregister_device(wacom_wac->input);
+		wacom_unregister_wireless(wacom);
+		wacom_destroy_leds(wacom);
+	}
+
+	wacom_wac->input = NULL;
+	wacom_wac->uniq[0] = 0;
+}
+
+static int wacom_register(struct wacom *wacom)
+{
+	int error;
+	
+	error = wacom_initialize_leds(wacom);
+	if (error)
+		goto fail1;
+
+	
+	error = wacom_register_wireless(wacom);
+	if (error)
+		goto fail2;
+	
+	error = wacom_register_input(wacom);
+	if (error)
+		goto fail3;
+
+	return 0;
+
+fail3: wacom_unregister_wireless(wacom);
+fail2: wacom_destroy_leds(wacom);
+fail1:
+	return error;
+}
+
 static void wacom_wireless_work(struct work_struct *work)
 {
 	struct wacom *wacom = container_of(work, struct wacom, work);
@@ -1155,16 +1332,12 @@ static void wacom_wireless_work(struct work_struct *work)
 	/* Stylus interface */
 	wacom1 = usb_get_intfdata(usbdev->config->interface[1]);
 	wacom_wac1 = &(wacom1->wacom_wac);
-	if (wacom_wac1->input)
-		input_unregister_device(wacom_wac1->input);
-	wacom_wac1->input = NULL;
+	wacom_unregister(wacom1);
 
 	/* Touch interface */
 	wacom2 = usb_get_intfdata(usbdev->config->interface[2]);
 	wacom_wac2 = &(wacom2->wacom_wac);
-	if (wacom_wac2->input)
-		input_unregister_device(wacom_wac2->input);
-	wacom_wac2->input = NULL;
+	wacom_unregister(wacom2);
 
 	if (wacom_wac->pid == 0) {
 		dev_info(&wacom->intf->dev, "wireless tablet disconnected\n");
@@ -1187,6 +1360,9 @@ static void wacom_wireless_work(struct work_struct *work)
 				 "ignoring unknown PID.\n");
 			return;
 		}
+	
+	wacom_wac1->pid = wacom_wac->pid;
+	wacom_wac2->pid = wacom_wac->pid;
 
 		/* Stylus interface */
 		wacom_wac1->features =
@@ -1196,7 +1372,8 @@ static void wacom_wireless_work(struct work_struct *work)
 			 wacom_wac1->features.name);
 		wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max;
 		wacom_wac1->shared->type = wacom_wac1->features.type;
-		error = wacom_register_input(wacom1);
+		wacom_wac1->features.quirks |= WACOM_QUIRK_WIRELESS_KIT;
+		error = wacom_register(wacom1);
 		if (error)
 			goto fail;
 
@@ -1214,7 +1391,8 @@ static void wacom_wireless_work(struct work_struct *work)
 			else
 				snprintf(wacom_wac2->name, WACOM_NAME_MAX,
 					 "%s (WL) Pad",wacom_wac2->features.name);
-			error = wacom_register_input(wacom2);
+			wacom_wac2->features.quirks |= WACOM_QUIRK_WIRELESS_KIT;
+			error = wacom_register(wacom2);
 			if (error)
 				goto fail;
 
@@ -1231,15 +1409,8 @@ static void wacom_wireless_work(struct work_struct *work)
 	return;
 
 fail:
-	if (wacom_wac2->input) {
-		input_unregister_device(wacom_wac2->input);
-		wacom_wac2->input = NULL;
-	}
-
-	if (wacom_wac1->input) {
-		input_unregister_device(wacom_wac1->input);
-		wacom_wac1->input = NULL;
-	}
+	wacom_unregister(wacom2);
+	wacom_unregister(wacom1);
 	return;
 }
 
@@ -1374,14 +1545,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 	wacom->irq->transfer_dma = wacom->data_dma;
 	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	error = wacom_initialize_leds(wacom);
-	if (error)
-		goto fail4;
-
 	if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
-		error = wacom_register_input(wacom);
+		error = wacom_register(wacom);
 		if (error)
-			goto fail5;
+			goto fail4;
 	}
 
 	/* Note that if query fails it is not a hard failure */
@@ -1403,7 +1570,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 
 	return 0;
 
- fail5: wacom_destroy_leds(wacom);
+ fail5: wacom_unregister(wacom);
  fail4:	wacom_remove_shared_data(wacom_wac);
  fail3:	usb_free_urb(wacom->irq);
  fail2:	usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
@@ -1419,10 +1586,8 @@ static void wacom_disconnect(struct usb_interface *intf)
 
 	usb_kill_urb(wacom->irq);
 	cancel_work_sync(&wacom->work);
-	if (wacom->wacom_wac.input)
-		input_unregister_device(wacom->wacom_wac.input);
+	wacom_unregister(wacom);
 	wacom_destroy_battery(wacom);
-	wacom_destroy_leds(wacom);
 	usb_free_urb(wacom->irq);
 	usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
 			wacom->wacom_wac.data, wacom->data_dma);
diff --git a/3.7-0/wacom_wac.h b/3.7-1/wacom_wac.h
index f69c0eb..1cd54df 100644
--- a/3.7-0/wacom_wac.h
+++ b/3.7-1/wacom_wac.h
@@ -15,6 +15,7 @@
 #define WACOM_PKGLEN_MAX	68
 
 #define WACOM_NAME_MAX		64
+#define WACOM_UNIQ_MAX		16
 
 /* packet length for individual models */
 #define WACOM_PKGLEN_PENPRTN	 7
@@ -65,6 +66,7 @@
 #define WACOM_QUIRK_BBTOUCH_LOWRES	0x0002
 #define WACOM_QUIRK_NO_INPUT		0x0004
 #define WACOM_QUIRK_MONITOR		0x0008
+#define WACOM_QUIRK_WIRELESS_KIT	0x0016
 
 enum {
 	PENPARTNER = 0,
@@ -144,6 +146,7 @@ struct wacom_shared {
 
 struct wacom_wac {
 	char name[WACOM_NAME_MAX];
+	char uniq[WACOM_UNIQ_MAX];
 	unsigned char *data;
 	int tool[2];
 	int id[2];
 {libwacom-0 => libwacom-1}/libwacom.c | 33 ++++++++++++++++++++++++++++++---
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/libwacom-0/libwacom.c b/libwacom-1/libwacom.c
index 574e6f3..2967846 100644
--- a/libwacom-0/libwacom.c
+++ b/libwacom-1/libwacom.c
@@ -47,6 +47,18 @@
 #define INPUT_PROP_DIRECT		0x01	/* direct input devices */
 #endif
 
+
+#define WACOM_WIRELESS_KIT_VENDOR_ID 0x056a
+#define WACOM_WIRELESS_KIT_PRODUCT_ID 0x0084
+
+static gboolean
+is_wireless(int vendor_id, int product_id)
+{
+  return vendor_id == WACOM_WIRELESS_KIT_VENDOR_ID 
+  && product_id == WACOM_WIRELESS_KIT_PRODUCT_ID;
+}
+
+
 static const WacomDevice *
 libwacom_get_device(const WacomDeviceDatabase *db, const char *match)
 {
@@ -207,7 +219,7 @@ get_device_info (const char            *path,
 
 	*bus = bus_from_str (bus_str);
 	if (*bus == WBUSTYPE_USB) {
-		const char *vendor_str, *product_str;
+		const char *vendor_str, *product_str, *uniq_str;
 		GUdevDevice *parent;
 
 		vendor_str = g_udev_device_get_property (device, "ID_VENDOR_ID");
@@ -221,14 +233,29 @@ get_device_info (const char            *path,
 			if (parent) {
 				vendor_str = g_udev_device_get_property (parent, "ID_VENDOR_ID");
 				product_str = g_udev_device_get_property (parent, "ID_MODEL_ID");
+				g_object_unref (parent);
 			}
 		}
 
 		*vendor_id = strtol (vendor_str, NULL, 16);
 		*product_id = strtol (product_str, NULL, 16);
+		
+		/* check for wireless kit enabled tablet */
+		if (is_wireless (*vendor_id, *product_id)) {
+		  char *sysfs_path, *contents;
+		  sysfs_path = g_build_filename ("/sys/class/input", devname, "device/uniq", NULL);
+		  if (g_file_get_contents (sysfs_path, &contents, NULL, NULL)) {
+		    if (sscanf(contents, "%x:%x", vendor_id, product_id) != 2) {
+		      libwacom_error_set(error, WERROR_UNKNOWN_MODEL, "Unable to parse wireless tablet model");
+		      g_free (contents);
+		      g_free (sysfs_path);
+		      goto bail;
+		    }
+		    g_free (contents);
+		  }
+		  g_free (sysfs_path);
+		}
 
-		if (parent)
-			g_object_unref (parent);
 	} else if (*bus == WBUSTYPE_BLUETOOTH || *bus == WBUSTYPE_SERIAL) {
 		GUdevDevice *parent;
 		const char *product_str;
------------------------------------------------------------------------------
_______________________________________________
Linuxwacom-devel mailing list
Linuxwacom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to