diff options
Diffstat (limited to 'drivers/input/tablet/wacom_sys.c')
-rw-r--r-- | drivers/input/tablet/wacom_sys.c | 187 |
1 files changed, 105 insertions, 82 deletions
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index aaf23aeae2ea..867e7c33ac55 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -221,39 +221,6 @@ static int wacom_calc_hid_res(int logical_extents, int physical_extents, return logical_extents / physical_extents; } -/* - * The physical dimension specified by the HID descriptor is likely not in - * the "100th of a mm" units expected by wacom_calculate_touch_res. This - * function adjusts the value of [xy]_phy based on the unit and exponent - * provided by the HID descriptor. If an error occurs durring conversion - * (e.g. from the unit being left unspecified) [xy]_phy is not modified. - */ -static void wacom_fix_phy_from_hid(struct wacom_features *features) -{ - int xres = wacom_calc_hid_res(features->x_max, features->x_phy, - features->unit, features->unitExpo); - int yres = wacom_calc_hid_res(features->y_max, features->y_phy, - features->unit, features->unitExpo); - - if (xres > 0 && yres > 0) { - features->x_phy = (100 * features->x_max) / xres; - features->y_phy = (100 * features->y_max) / yres; - } -} - -/* - * Static values for max X/Y and resolution of Pen interface is stored in - * features. This mean physical size of active area can be computed. - * This is useful to do when Pen and Touch have same active area of tablet. - * This means for Touch device, we only need to find max X/Y value and we - * have enough information to compute resolution of touch. - */ -static void wacom_set_phy_from_res(struct wacom_features *features) -{ - features->x_phy = (features->x_max * 100) / features->x_resolution; - features->y_phy = (features->y_max * 100) / features->y_resolution; -} - static int wacom_parse_logical_collection(unsigned char *report, struct wacom_features *features) { @@ -265,8 +232,6 @@ static int wacom_parse_logical_collection(unsigned char *report, features->pktlen = WACOM_PKGLEN_BBTOUCH3; features->device_type = BTN_TOOL_FINGER; - wacom_set_phy_from_res(features); - features->x_max = features->y_max = get_unaligned_le16(&report[10]); @@ -559,9 +524,6 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, report_id, rep_data, length, 1); - if (error >= 0) - error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT, - report_id, rep_data, length, 1); } while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES); kfree(rep_data); @@ -583,7 +545,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat /* MT Tablet PC touch */ return wacom_set_device_mode(intf, 3, 4, 4); } - else if (features->type == WACOM_24HDT) { + else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) { return wacom_set_device_mode(intf, 18, 3, 2); } } else if (features->device_type == BTN_TOOL_PEN) { @@ -640,9 +602,6 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, } } error = wacom_parse_hid(intf, hid_desc, features); - if (error) - goto out; - wacom_fix_phy_from_hid(features); out: return error; @@ -757,7 +716,7 @@ static int wacom_led_control(struct wacom *wacom) return -ENOMEM; if (wacom->wacom_wac.features.type >= INTUOS5S && - wacom->wacom_wac.features.type <= INTUOS5L) { + wacom->wacom_wac.features.type <= INTUOSPL) { /* * Touch Ring and crop mark LED luminance may take on * one of four values: @@ -1019,14 +978,20 @@ static int wacom_initialize_leds(struct wacom *wacom) case INTUOS5S: case INTUOS5: case INTUOS5L: - wacom->led.select[0] = 0; - wacom->led.select[1] = 0; - wacom->led.llv = 32; - wacom->led.hlv = 0; - wacom->led.img_lum = 0; - - error = sysfs_create_group(&wacom->intf->dev.kobj, - &intuos5_led_attr_group); + case INTUOSPS: + case INTUOSPM: + case INTUOSPL: + if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) { + wacom->led.select[0] = 0; + wacom->led.select[1] = 0; + wacom->led.llv = 32; + wacom->led.hlv = 0; + wacom->led.img_lum = 0; + + error = sysfs_create_group(&wacom->intf->dev.kobj, + &intuos5_led_attr_group); + } else + return 0; break; default: @@ -1062,13 +1027,18 @@ static void wacom_destroy_leds(struct wacom *wacom) case INTUOS5S: case INTUOS5: case INTUOS5L: - sysfs_remove_group(&wacom->intf->dev.kobj, - &intuos5_led_attr_group); + case INTUOSPS: + case INTUOSPM: + case INTUOSPL: + if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) + sysfs_remove_group(&wacom->intf->dev.kobj, + &intuos5_led_attr_group); break; } } static enum power_supply_property wacom_battery_props[] = { + POWER_SUPPLY_PROP_SCOPE, POWER_SUPPLY_PROP_CAPACITY }; @@ -1080,6 +1050,9 @@ static int wacom_battery_get_property(struct power_supply *psy, int ret = 0; switch (psp) { + case POWER_SUPPLY_PROP_SCOPE: + val->intval = POWER_SUPPLY_SCOPE_DEVICE; + break; case POWER_SUPPLY_PROP_CAPACITY: val->intval = wacom->wacom_wac.battery_capacity * 100 / 31; @@ -1219,38 +1192,77 @@ static void wacom_wireless_work(struct work_struct *work) wacom_wac1->features = *((struct wacom_features *)id->driver_info); wacom_wac1->features.device_type = BTN_TOOL_PEN; + snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen", + wacom_wac1->features.name); error = wacom_register_input(wacom1); if (error) - goto fail1; + goto fail; /* Touch interface */ - wacom_wac2->features = - *((struct wacom_features *)id->driver_info); - wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; - wacom_wac2->features.device_type = BTN_TOOL_FINGER; - wacom_set_phy_from_res(&wacom_wac2->features); - wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096; - error = wacom_register_input(wacom2); - if (error) - goto fail2; + if (wacom_wac1->features.touch_max) { + wacom_wac2->features = + *((struct wacom_features *)id->driver_info); + wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; + wacom_wac2->features.device_type = BTN_TOOL_FINGER; + wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096; + if (wacom_wac2->features.touch_max) + snprintf(wacom_wac2->name, WACOM_NAME_MAX, + "%s (WL) Finger",wacom_wac2->features.name); + else + snprintf(wacom_wac2->name, WACOM_NAME_MAX, + "%s (WL) Pad",wacom_wac2->features.name); + error = wacom_register_input(wacom2); + if (error) + goto fail; + } error = wacom_initialize_battery(wacom); if (error) - goto fail3; + goto fail; } return; -fail3: - input_unregister_device(wacom_wac2->input); - wacom_wac2->input = NULL; -fail2: - input_unregister_device(wacom_wac1->input); - wacom_wac1->input = NULL; -fail1: +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; + } return; } +/* + * Not all devices report physical dimensions from HID. + * Compute the default from hardcoded logical dimension + * and resolution before driver overwrites them. + */ +static void wacom_set_default_phy(struct wacom_features *features) +{ + if (features->x_resolution) { + features->x_phy = (features->x_max * 100) / + features->x_resolution; + features->y_phy = (features->y_max * 100) / + features->y_resolution; + } +} + +static void wacom_calculate_res(struct wacom_features *features) +{ + features->x_resolution = wacom_calc_hid_res(features->x_max, + features->x_phy, + features->unit, + features->unitExpo); + features->y_resolution = wacom_calc_hid_res(features->y_max, + features->y_phy, + features->unit, + features->unitExpo); +} + static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); @@ -1297,6 +1309,9 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i endpoint = &intf->cur_altsetting->endpoint[0].desc; + /* set the default size in case we do not get them from hid */ + wacom_set_default_phy(features); + /* Retrieve the physical and logical size for touch devices */ error = wacom_retrieve_hid_descriptor(intf, features); if (error) @@ -1307,13 +1322,11 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i * HID descriptor. If this is the touch interface (wMaxPacketSize * of WACOM_PKGLEN_BBTOUCH3), override the table values. */ - if (features->type >= INTUOS5S && features->type <= INTUOS5L) { + if (features->type >= INTUOS5S && features->type <= INTUOSPL) { if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) { features->device_type = BTN_TOOL_FINGER; features->pktlen = WACOM_PKGLEN_BBTOUCH3; - wacom_set_phy_from_res(features); - features->x_max = 4096; features->y_max = 4096; } else { @@ -1323,17 +1336,25 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom_setup_device_quirks(features); + /* set unit to "100th of a mm" for devices not reported by HID */ + if (!features->unit) { + features->unit = 0x11; + features->unitExpo = 16 - 3; + } + wacom_calculate_res(features); + strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); if (features->quirks & WACOM_QUIRK_MULTI_INPUT) { struct usb_device *other_dev; /* Append the device type to the name */ - strlcat(wacom_wac->name, - features->device_type == BTN_TOOL_PEN ? - " Pen" : " Finger", - sizeof(wacom_wac->name)); - + if (features->device_type != BTN_TOOL_FINGER) + strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX); + else if (features->touch_max) + strlcat(wacom_wac->name, " Finger", WACOM_NAME_MAX); + else + strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX); other_dev = wacom_get_sibling(dev, features->oVid, features->oPid); if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL) @@ -1366,8 +1387,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i usb_set_intfdata(intf, wacom); if (features->quirks & WACOM_QUIRK_MONITOR) { - if (usb_submit_urb(wacom->irq, GFP_KERNEL)) + if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { + error = -EIO; goto fail5; + } } return 0; @@ -1422,8 +1445,8 @@ static int wacom_resume(struct usb_interface *intf) wacom_query_tablet_data(intf, features); wacom_led_control(wacom); - if ((wacom->open || features->quirks & WACOM_QUIRK_MONITOR) - && usb_submit_urb(wacom->irq, GFP_NOIO) < 0) + if ((wacom->open || (features->quirks & WACOM_QUIRK_MONITOR)) && + usb_submit_urb(wacom->irq, GFP_NOIO) < 0) rv = -EIO; mutex_unlock(&wacom->lock); |