]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-4.0/upstream-fixes' into for-next
authorJiri Kosina <jkosina@suse.cz>
Tue, 17 Mar 2015 20:01:20 +0000 (21:01 +0100)
committerJiri Kosina <jkosina@suse.cz>
Tue, 17 Mar 2015 20:01:20 +0000 (21:01 +0100)
1  2 
drivers/hid/wacom_wac.c

diff --combined drivers/hid/wacom_wac.c
index d139860b9e664a779e731d6a426ab3c802bf5115,bbe32d66e5000157b4d3670c23350ff3fa1a0104..5588ba80ede9ed61adb8ead1e49663ea4738b513
@@@ -45,27 -45,6 +45,27 @@@ static unsigned short batcap_gr[8] = { 
   */
  static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 };
  
 +static void wacom_notify_battery(struct wacom_wac *wacom_wac,
 +      int bat_capacity, bool bat_charging, bool bat_connected,
 +      bool ps_connected)
 +{
 +      struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
 +      bool changed = wacom_wac->battery_capacity != bat_capacity  ||
 +                     wacom_wac->bat_charging     != bat_charging  ||
 +                     wacom_wac->bat_connected    != bat_connected ||
 +                     wacom_wac->ps_connected     != ps_connected;
 +
 +      if (changed) {
 +              wacom_wac->battery_capacity = bat_capacity;
 +              wacom_wac->bat_charging = bat_charging;
 +              wacom_wac->bat_connected = bat_connected;
 +              wacom_wac->ps_connected = ps_connected;
 +
 +              if (wacom->battery.dev)
 +                      power_supply_changed(&wacom->battery);
 +      }
 +}
 +
  static int wacom_penpartner_irq(struct wacom_wac *wacom)
  {
        unsigned char *data = wacom->data;
@@@ -440,26 -419,17 +440,26 @@@ static int wacom_graphire_irq(struct wa
                rw = (data[7] >> 2 & 0x07);
                battery_capacity = batcap_gr[rw];
                ps_connected = rw == 7;
 -              if ((wacom->battery_capacity != battery_capacity) ||
 -                  (wacom->ps_connected != ps_connected)) {
 -                      wacom->battery_capacity = battery_capacity;
 -                      wacom->ps_connected = ps_connected;
 -                      wacom_notify_battery(wacom);
 -              }
 +              wacom_notify_battery(wacom, battery_capacity, ps_connected,
 +                                   1, ps_connected);
        }
  exit:
        return retval;
  }
  
 +static void wacom_intuos_schedule_prox_event(struct wacom_wac *wacom_wac)
 +{
 +      struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
 +      struct hid_report *r;
 +      struct hid_report_enum *re;
 +
 +      re = &(wacom->hdev->report_enum[HID_FEATURE_REPORT]);
 +      r = re->report_id_hash[WACOM_REPORT_INTUOSREAD];
 +      if (r) {
 +              hid_hw_request(wacom->hdev, r, HID_REQ_GET_REPORT);
 +      }
 +}
 +
  static int wacom_intuos_inout(struct wacom_wac *wacom)
  {
        struct wacom_features *features = &wacom->features;
           (features->type == CINTIQ && !(data[1] & 0x40)))
                return 1;
  
-       if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
+       if (wacom->shared) {
                wacom->shared->stylus_in_proximity = true;
  
-       if (wacom->shared->touch_down)
-               return 1;
+               if (wacom->shared->touch_down)
+                       return 1;
+       }
  
        /* in Range while exiting */
        if (((data[1] & 0xfe) == 0x20) && wacom->reporting_data) {
        }
  
        /* don't report other events if we don't know the ID */
 -      if (!wacom->id[idx])
 +      if (!wacom->id[idx]) {
 +              /* but reschedule a read of the current tool */
 +              wacom_intuos_schedule_prox_event(wacom);
                return 1;
 +      }
  
        return 0;
  }
@@@ -1055,9 -1023,15 +1056,9 @@@ static int wacom_intuos_bt_irq(struct w
                bat_charging = (power_raw & 0x08) ? 1 : 0;
                ps_connected = (power_raw & 0x10) ? 1 : 0;
                battery_capacity = batcap_i4[power_raw & 0x07];
 -              if ((wacom->battery_capacity != battery_capacity) ||
 -                  (wacom->bat_charging != bat_charging) ||
 -                  (wacom->ps_connected != ps_connected)) {
 -                      wacom->battery_capacity = battery_capacity;
 -                      wacom->bat_charging = bat_charging;
 -                      wacom->ps_connected = ps_connected;
 -                      wacom_notify_battery(wacom);
 -              }
 -
 +              wacom_notify_battery(wacom, battery_capacity, bat_charging,
 +                                   battery_capacity || bat_charging,
 +                                   ps_connected);
                break;
        default:
                dev_dbg(wacom->input->dev.parent,
@@@ -1130,7 -1104,7 +1131,7 @@@ static int wacom_24hdt_irq(struct wacom
                        contact_with_no_pen_down_count++;
                }
        }
 -      input_mt_report_pointer_emulation(input, true);
 +      input_mt_sync_frame(input);
  
        wacom->num_contacts_left -= contacts_to_send;
        if (wacom->num_contacts_left <= 0) {
@@@ -1185,7 -1159,7 +1186,7 @@@ static int wacom_mt_touch(struct wacom_
                        contact_with_no_pen_down_count++;
                }
        }
 -      input_mt_report_pointer_emulation(input, true);
 +      input_mt_sync_frame(input);
  
        wacom->num_contacts_left -= contacts_to_send;
        if (wacom->num_contacts_left <= 0) {
@@@ -1217,7 -1191,7 +1218,7 @@@ static int wacom_tpc_mt_touch(struct wa
                        contact_with_no_pen_down_count++;
                }
        }
 -      input_mt_report_pointer_emulation(input, true);
 +      input_mt_sync_frame(input);
  
        /* keep touch state for pen event */
        wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
@@@ -1677,7 -1651,7 +1678,7 @@@ static int wacom_bpt_touch(struct wacom
                }
        }
  
 -      input_mt_report_pointer_emulation(input, true);
 +      input_mt_sync_frame(input);
  
        input_report_key(pad_input, BTN_LEFT, (data[1] & 0x08) != 0);
        input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0);
@@@ -1773,7 -1747,7 +1774,7 @@@ static int wacom_bpt3_touch(struct waco
                        wacom_bpt3_button_msg(wacom, data + offset);
  
        }
 -      input_mt_report_pointer_emulation(input, true);
 +      input_mt_sync_frame(input);
        wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
  
        return 1;
@@@ -1786,9 -1760,23 +1787,9 @@@ static int wacom_bpt_pen(struct wacom_w
        unsigned char *data = wacom->data;
        int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
  
 -      if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_USB)
 +      if (data[0] != WACOM_REPORT_PENABLED)
            return 0;
  
 -      if (data[0] == WACOM_REPORT_USB) {
 -              if (features->type == INTUOSHT &&
 -                  wacom->shared->touch_input &&
 -                  features->touch_max) {
 -                      input_report_switch(wacom->shared->touch_input,
 -                                          SW_MUTE_DEVICE, data[8] & 0x40);
 -                      input_sync(wacom->shared->touch_input);
 -              }
 -              return 0;
 -      }
 -
 -      if (wacom->shared->touch_down)
 -              return 0;
 -
        prox = (data[1] & 0x20) == 0x20;
  
        /*
@@@ -1861,91 -1849,6 +1862,91 @@@ static int wacom_bpt_irq(struct wacom_w
        return 0;
  }
  
 +static void wacom_bamboo_pad_pen_event(struct wacom_wac *wacom,
 +              unsigned char *data)
 +{
 +      unsigned char prefix;
 +
 +      /*
 +       * We need to reroute the event from the debug interface to the
 +       * pen interface.
 +       * We need to add the report ID to the actual pen report, so we
 +       * temporary overwrite the first byte to prevent having to kzalloc/kfree
 +       * and memcpy the report.
 +       */
 +      prefix = data[0];
 +      data[0] = WACOM_REPORT_BPAD_PEN;
 +
 +      /*
 +       * actually reroute the event.
 +       * No need to check if wacom->shared->pen is valid, hid_input_report()
 +       * will check for us.
 +       */
 +      hid_input_report(wacom->shared->pen, HID_INPUT_REPORT, data,
 +                       WACOM_PKGLEN_PENABLED, 1);
 +
 +      data[0] = prefix;
 +}
 +
 +static int wacom_bamboo_pad_touch_event(struct wacom_wac *wacom,
 +              unsigned char *data)
 +{
 +      struct input_dev *input = wacom->input;
 +      unsigned char *finger_data, prefix;
 +      unsigned id;
 +      int x, y;
 +      bool valid;
 +
 +      prefix = data[0];
 +
 +      for (id = 0; id < wacom->features.touch_max; id++) {
 +              valid = !!(prefix & BIT(id)) &&
 +                      !wacom->shared->stylus_in_proximity;
 +
 +              input_mt_slot(input, id);
 +              input_mt_report_slot_state(input, MT_TOOL_FINGER, valid);
 +
 +              if (!valid)
 +                      continue;
 +
 +              finger_data = data + 1 + id * 3;
 +              x = finger_data[0] | ((finger_data[1] & 0x0f) << 8);
 +              y = (finger_data[2] << 4) | (finger_data[1] >> 4);
 +
 +              input_report_abs(input, ABS_MT_POSITION_X, x);
 +              input_report_abs(input, ABS_MT_POSITION_Y, y);
 +      }
 +
 +      input_mt_sync_frame(input);
 +
 +      input_report_key(input, BTN_LEFT, prefix & 0x40);
 +      input_report_key(input, BTN_RIGHT, prefix & 0x80);
 +
 +      /* keep touch state for pen event */
 +      wacom->shared->touch_down = !!prefix &&
 +                                  !wacom->shared->stylus_in_proximity;
 +
 +      return 1;
 +}
 +
 +static int wacom_bamboo_pad_irq(struct wacom_wac *wacom, size_t len)
 +{
 +      unsigned char *data = wacom->data;
 +
 +      if (!((len == WACOM_PKGLEN_BPAD_TOUCH) ||
 +            (len == WACOM_PKGLEN_BPAD_TOUCH_USB)) ||
 +          (data[0] != WACOM_REPORT_BPAD_TOUCH))
 +              return 0;
 +
 +      if (data[1] & 0x01)
 +              wacom_bamboo_pad_pen_event(wacom, &data[1]);
 +
 +      if (data[1] & 0x02)
 +              return wacom_bamboo_pad_touch_event(wacom, &data[9]);
 +
 +      return 0;
 +}
 +
  static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
  {
        unsigned char *data = wacom->data;
  
        connected = data[1] & 0x01;
        if (connected) {
 -              int pid, battery, ps_connected;
 +              int pid, battery, charging;
  
                if ((wacom->shared->type == INTUOSHT) &&
                    wacom->shared->touch_input &&
  
                pid = get_unaligned_be16(&data[6]);
                battery = (data[5] & 0x3f) * 100 / 31;
 -              ps_connected = !!(data[5] & 0x80);
 +              charging = !!(data[5] & 0x80);
                if (wacom->pid != pid) {
                        wacom->pid = pid;
                        wacom_schedule_work(wacom);
                }
  
 -              if (wacom->shared->type &&
 -                  (battery != wacom->battery_capacity ||
 -                   ps_connected != wacom->ps_connected)) {
 -                      wacom->battery_capacity = battery;
 -                      wacom->ps_connected = ps_connected;
 -                      wacom->bat_charging = ps_connected &&
 -                                              wacom->battery_capacity < 100;
 -                      wacom_notify_battery(wacom);
 -              }
 +              if (wacom->shared->type)
 +                      wacom_notify_battery(wacom, battery, charging, 1, 0);
 +
        } else if (wacom->pid != 0) {
                /* disconnected while previously connected */
                wacom->pid = 0;
                wacom_schedule_work(wacom);
 -              wacom->battery_capacity = 0;
 -              wacom->bat_charging = 0;
 -              wacom->ps_connected = 0;
 +              wacom_notify_battery(wacom, 0, 0, 0, 0);
        }
  
        return 0;
  }
  
 +static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len)
 +{
 +      struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
 +      struct wacom_features *features = &wacom_wac->features;
 +      unsigned char *data = wacom_wac->data;
 +
 +      if (data[0] != WACOM_REPORT_USB)
 +              return 0;
 +
 +      if (features->type == INTUOSHT &&
 +          wacom_wac->shared->touch_input &&
 +          features->touch_max) {
 +              input_report_switch(wacom_wac->shared->touch_input,
 +                                  SW_MUTE_DEVICE, data[8] & 0x40);
 +              input_sync(wacom_wac->shared->touch_input);
 +      }
 +
 +      if (data[9] & 0x02) { /* wireless module is attached */
 +              int battery = (data[8] & 0x3f) * 100 / 31;
 +              bool charging = !!(data[8] & 0x80);
 +
 +              wacom_notify_battery(wacom_wac, battery, charging,
 +                                   battery || charging, 1);
 +
 +              if (!wacom->battery.dev &&
 +                  !(features->quirks & WACOM_QUIRK_BATTERY)) {
 +                      features->quirks |= WACOM_QUIRK_BATTERY;
 +                      INIT_WORK(&wacom->work, wacom_battery_work);
 +                      wacom_schedule_work(wacom_wac);
 +              }
 +      }
 +      else if ((features->quirks & WACOM_QUIRK_BATTERY) &&
 +               wacom->battery.dev) {
 +              features->quirks &= ~WACOM_QUIRK_BATTERY;
 +              INIT_WORK(&wacom->work, wacom_battery_work);
 +              wacom_schedule_work(wacom_wac);
 +              wacom_notify_battery(wacom_wac, 0, 0, 0, 0);
 +      }
 +      return 0;
 +}
 +
  void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
  {
        bool sync;
        case INTUOSPL:
                if (len == WACOM_PKGLEN_BBTOUCH3)
                        sync = wacom_bpt3_touch(wacom_wac);
 +              else if (wacom_wac->data[0] == WACOM_REPORT_USB)
 +                      sync = wacom_status_irq(wacom_wac, len);
                else
                        sync = wacom_intuos_irq(wacom_wac);
                break;
  
        case BAMBOO_PT:
        case INTUOSHT:
 -              sync = wacom_bpt_irq(wacom_wac, len);
 +              if (wacom_wac->data[0] == WACOM_REPORT_USB)
 +                      sync = wacom_status_irq(wacom_wac, len);
 +              else
 +                      sync = wacom_bpt_irq(wacom_wac, len);
 +              break;
 +
 +      case BAMBOO_PAD:
 +              sync = wacom_bamboo_pad_irq(wacom_wac, len);
                break;
  
        case WIRELESS:
@@@ -2462,13 -2323,6 +2463,13 @@@ int wacom_setup_pentouch_input_capabili
                                              0, 0);
                }
                break;
 +      case BAMBOO_PAD:
 +              __clear_bit(ABS_MISC, input_dev->absbit);
 +              input_mt_init_slots(input_dev, features->touch_max,
 +                                  INPUT_MT_POINTER);
 +              __set_bit(BTN_LEFT, input_dev->keybit);
 +              __set_bit(BTN_RIGHT, input_dev->keybit);
 +              break;
        }
        return 0;
  }
@@@ -3122,12 -2976,6 +3123,12 @@@ static const struct wacom_features waco
        { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */
          .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30A, .touch_max = 10,
          .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 +static const struct wacom_features wacom_features_0x318 =
 +      { "Wacom USB Bamboo PAD", 4095, 4095, /* Touch */
 +        .type = BAMBOO_PAD, 35, 48, .touch_max = 4 };
 +static const struct wacom_features wacom_features_0x319 =
 +      { "Wacom Wireless Bamboo PAD", 4095, 4095, /* Touch */
 +        .type = BAMBOO_PAD, 35, 48, .touch_max = 4 };
  static const struct wacom_features wacom_features_0x323 =
        { "Wacom Intuos P M", 21600, 13500, 1023, 31,
          INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
@@@ -3144,10 -2992,6 +3145,10 @@@ static const struct wacom_features waco
        HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
        .driver_data = (kernel_ulong_t)&wacom_features_##prod
  
 +#define I2C_DEVICE_WACOM(prod)                                                \
 +      HID_DEVICE(BUS_I2C, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
 +      .driver_data = (kernel_ulong_t)&wacom_features_##prod
 +
  #define USB_DEVICE_LENOVO(prod)                                       \
        HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod),                     \
        .driver_data = (kernel_ulong_t)&wacom_features_##prod
@@@ -3280,8 -3124,6 +3281,8 @@@ const struct hid_device_id wacom_ids[] 
        { USB_DEVICE_WACOM(0x314) },
        { USB_DEVICE_WACOM(0x315) },
        { USB_DEVICE_WACOM(0x317) },
 +      { USB_DEVICE_WACOM(0x318) },
 +      { USB_DEVICE_WACOM(0x319) },
        { USB_DEVICE_WACOM(0x323) },
        { USB_DEVICE_WACOM(0x32A) },
        { USB_DEVICE_WACOM(0x32B) },
        { USB_DEVICE_LENOVO(0x6004) },
  
        { USB_DEVICE_WACOM(HID_ANY_ID) },
 +      { I2C_DEVICE_WACOM(HID_ANY_ID) },
        { }
  };
  MODULE_DEVICE_TABLE(hid, wacom_ids);