Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[deliverable/linux.git] / drivers / hid / wacom_sys.c
index 18154a5459b5f396c49c09ca49f67f2036dcda00..f0db7eca902324b84bf97ad915edd05d0c6a35a4 100644 (file)
@@ -20,6 +20,7 @@
 #define WAC_CMD_LED_CONTROL    0x20
 #define WAC_CMD_ICON_START     0x21
 #define WAC_CMD_ICON_XFER      0x23
+#define WAC_CMD_ICON_BT_XFER   0x26
 #define WAC_CMD_RETRIES                10
 
 static int wacom_get_report(struct hid_device *hdev, u8 type, u8 id,
@@ -35,13 +36,13 @@ static int wacom_get_report(struct hid_device *hdev, u8 type, u8 id,
        return retval;
 }
 
-static int wacom_set_report(struct hid_device *hdev, u8 type, u8 id,
-                           void *buf, size_t size, unsigned int retries)
+static int wacom_set_report(struct hid_device *hdev, u8 type, u8 *buf,
+                           size_t size, unsigned int retries)
 {
        int retval;
 
        do {
-               retval = hid_hw_raw_request(hdev, id, buf, size, type,
+               retval = hid_hw_raw_request(hdev, buf[0], buf, size, type,
                                HID_REQ_SET_REPORT);
        } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
 
@@ -250,8 +251,8 @@ static int wacom_set_device_mode(struct hid_device *hdev, int report_id,
                rep_data[0] = report_id;
                rep_data[1] = mode;
 
-               error = wacom_set_report(hdev, HID_FEATURE_REPORT,
-                                        report_id, rep_data, length, 1);
+               error = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data,
+                                        length, 1);
                if (error >= 0)
                        error = wacom_get_report(hdev, HID_FEATURE_REPORT,
                                                 report_id, rep_data, length, 1);
@@ -265,6 +266,53 @@ static int wacom_set_device_mode(struct hid_device *hdev, int report_id,
 static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed,
                struct wacom_features *features)
 {
+       struct wacom *wacom = hid_get_drvdata(hdev);
+       int ret;
+       u8 rep_data[2];
+
+       switch (features->type) {
+       case GRAPHIRE_BT:
+               rep_data[0] = 0x03;
+               rep_data[1] = 0x00;
+               ret = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data, 2,
+                                       3);
+
+               if (ret >= 0) {
+                       rep_data[0] = speed == 0 ? 0x05 : 0x06;
+                       rep_data[1] = 0x00;
+
+                       ret = wacom_set_report(hdev, HID_FEATURE_REPORT,
+                                               rep_data, 2, 3);
+
+                       if (ret >= 0) {
+                               wacom->wacom_wac.bt_high_speed = speed;
+                               return 0;
+                       }
+               }
+
+               /*
+                * Note that if the raw queries fail, it's not a hard failure
+                * and it is safe to continue
+                */
+               hid_warn(hdev, "failed to poke device, command %d, err %d\n",
+                        rep_data[0], ret);
+               break;
+       case INTUOS4WL:
+               if (speed == 1)
+                       wacom->wacom_wac.bt_features &= ~0x20;
+               else
+                       wacom->wacom_wac.bt_features |= 0x20;
+
+               rep_data[0] = 0x03;
+               rep_data[1] = wacom->wacom_wac.bt_features;
+
+               ret = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data, 2,
+                                       1);
+               if (ret >= 0)
+                       wacom->wacom_wac.bt_high_speed = speed;
+               break;
+       }
+
        return 0;
 }
 
@@ -472,39 +520,40 @@ static int wacom_led_control(struct wacom *wacom)
                buf[4] = wacom->led.img_lum;
        }
 
-       retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT,
-                                 WAC_CMD_LED_CONTROL, buf, 9, WAC_CMD_RETRIES);
+       retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 9,
+                                 WAC_CMD_RETRIES);
        kfree(buf);
 
        return retval;
 }
 
-static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *img)
+static int wacom_led_putimage(struct wacom *wacom, int button_id, u8 xfer_id,
+               const unsigned len, const void *img)
 {
        unsigned char *buf;
        int i, retval;
+       const unsigned chunk_len = len / 4; /* 4 chunks are needed to be sent */
 
-       buf = kzalloc(259, GFP_KERNEL);
+       buf = kzalloc(chunk_len + 3 , GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
 
        /* Send 'start' command */
        buf[0] = WAC_CMD_ICON_START;
        buf[1] = 1;
-       retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT,
-                                 WAC_CMD_ICON_START, buf, 2, WAC_CMD_RETRIES);
+       retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 2,
+                                 WAC_CMD_RETRIES);
        if (retval < 0)
                goto out;
 
-       buf[0] = WAC_CMD_ICON_XFER;
+       buf[0] = xfer_id;
        buf[1] = button_id & 0x07;
        for (i = 0; i < 4; i++) {
                buf[2] = i;
-               memcpy(buf + 3, img + i * 256, 256);
+               memcpy(buf + 3, img + i * chunk_len, chunk_len);
 
                retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT,
-                                         WAC_CMD_ICON_XFER,
-                                         buf, 259, WAC_CMD_RETRIES);
+                                         buf, chunk_len + 3, WAC_CMD_RETRIES);
                if (retval < 0)
                        break;
        }
@@ -512,8 +561,8 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *im
        /* Send 'stop' */
        buf[0] = WAC_CMD_ICON_START;
        buf[1] = 0;
-       wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, WAC_CMD_ICON_START,
-                        buf, 2, WAC_CMD_RETRIES);
+       wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 2,
+                        WAC_CMD_RETRIES);
 
 out:
        kfree(buf);
@@ -605,13 +654,23 @@ static ssize_t wacom_button_image_store(struct device *dev, int button_id,
        struct hid_device *hdev = container_of(dev, struct hid_device, dev);
        struct wacom *wacom = hid_get_drvdata(hdev);
        int err;
+       unsigned len;
+       u8 xfer_id;
+
+       if (hdev->bus == BUS_BLUETOOTH) {
+               len = 256;
+               xfer_id = WAC_CMD_ICON_BT_XFER;
+       } else {
+               len = 1024;
+               xfer_id = WAC_CMD_ICON_XFER;
+       }
 
-       if (count != 1024)
+       if (count != len)
                return -EINVAL;
 
        mutex_lock(&wacom->lock);
 
-       err = wacom_led_putimage(wacom, button_id, buf);
+       err = wacom_led_putimage(wacom, button_id, xfer_id, len, buf);
 
        mutex_unlock(&wacom->lock);
 
@@ -687,6 +746,7 @@ static int wacom_initialize_leds(struct wacom *wacom)
        switch (wacom->wacom_wac.features.type) {
        case INTUOS4S:
        case INTUOS4:
+       case INTUOS4WL:
        case INTUOS4L:
                wacom->led.select[0] = 0;
                wacom->led.select[1] = 0;
@@ -753,6 +813,7 @@ static void wacom_destroy_leds(struct wacom *wacom)
        switch (wacom->wacom_wac.features.type) {
        case INTUOS4S:
        case INTUOS4:
+       case INTUOS4WL:
        case INTUOS4L:
                sysfs_remove_group(&wacom->hdev->dev.kobj,
                                   &intuos4_led_attr_group);
@@ -1355,6 +1416,7 @@ static void wacom_remove(struct hid_device *hdev)
        kfree(wacom);
 }
 
+#ifdef CONFIG_PM
 static int wacom_resume(struct hid_device *hdev)
 {
        struct wacom *wacom = hid_get_drvdata(hdev);
@@ -1375,6 +1437,7 @@ static int wacom_reset_resume(struct hid_device *hdev)
 {
        return wacom_resume(hdev);
 }
+#endif /* CONFIG_PM */
 
 static struct hid_driver wacom_driver = {
        .name =         "wacom",
@@ -1388,3 +1451,8 @@ static struct hid_driver wacom_driver = {
        .raw_event =    wacom_raw_event,
 };
 module_hid_driver(wacom_driver);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
This page took 0.028253 seconds and 5 git commands to generate.