Commit 1c74a7f8 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid

Pull HID fixes from Jiri Kosina:

 - fix for how scaling linearization is computed in wiimote driver, by
   Cyan Ogilvie

 - endless retry loop fix in generic USB HID core reset-resume handling,
   by Alan Stern

 - two functional fixes affecting particular devices, and oops fix for
   wacom driver, by Jason Gerecke

 - multitouch slot numbering fix from Gabriele Mazzotta

 - a couple more small fixes on top

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
  HID: wacom: Support switching from vendor-defined device mode on G9 and G11
  HID: wacom: Initialize hid_data.inputmode to -1
  HID: microsoft: add support for 3 more devices
  HID: multitouch: Synchronize MT frame on reset_resume
  HID: wacom: fix Bamboo ONE oops
  HID: lenovo: Don't use stack variables for DMA buffers
  HID: usbhid: fix inconsistent reset/resume/reset-resume behavior
  HID: wiimote: Fix wiimote mp scale linearization
parents 6c6563a4 326ea2a9
...@@ -1979,6 +1979,9 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1979,6 +1979,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
......
...@@ -676,6 +676,7 @@ ...@@ -676,6 +676,7 @@
#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b #define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
#define USB_DEVICE_ID_MS_OFFICE_KB 0x0048 #define USB_DEVICE_ID_MS_OFFICE_KB 0x0048
#define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d #define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
#define USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K 0x00b4
#define USB_DEVICE_ID_MS_NE4K 0x00db #define USB_DEVICE_ID_MS_NE4K 0x00db
#define USB_DEVICE_ID_MS_NE4K_JP 0x00dc #define USB_DEVICE_ID_MS_NE4K_JP 0x00dc
#define USB_DEVICE_ID_MS_LK6K 0x00f9 #define USB_DEVICE_ID_MS_LK6K 0x00f9
...@@ -683,6 +684,8 @@ ...@@ -683,6 +684,8 @@
#define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713 #define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713
#define USB_DEVICE_ID_MS_NE7K 0x071d #define USB_DEVICE_ID_MS_NE7K 0x071d
#define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730 #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730
#define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1 0x0732
#define USB_DEVICE_ID_MS_DIGITAL_MEDIA_600 0x0750
#define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c
#define USB_DEVICE_ID_MS_COMFORT_KEYBOARD 0x00e3 #define USB_DEVICE_ID_MS_COMFORT_KEYBOARD 0x00e3
#define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799 #define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799
......
...@@ -184,21 +184,31 @@ static int lenovo_send_cmd_cptkbd(struct hid_device *hdev, ...@@ -184,21 +184,31 @@ static int lenovo_send_cmd_cptkbd(struct hid_device *hdev,
unsigned char byte2, unsigned char byte3) unsigned char byte2, unsigned char byte3)
{ {
int ret; int ret;
unsigned char buf[] = {0x18, byte2, byte3}; unsigned char *buf;
buf = kzalloc(3, GFP_KERNEL);
if (!buf)
return -ENOMEM;
buf[0] = 0x18;
buf[1] = byte2;
buf[2] = byte3;
switch (hdev->product) { switch (hdev->product) {
case USB_DEVICE_ID_LENOVO_CUSBKBD: case USB_DEVICE_ID_LENOVO_CUSBKBD:
ret = hid_hw_raw_request(hdev, 0x13, buf, sizeof(buf), ret = hid_hw_raw_request(hdev, 0x13, buf, 3,
HID_FEATURE_REPORT, HID_REQ_SET_REPORT); HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
break; break;
case USB_DEVICE_ID_LENOVO_CBTKBD: case USB_DEVICE_ID_LENOVO_CBTKBD:
ret = hid_hw_output_report(hdev, buf, sizeof(buf)); ret = hid_hw_output_report(hdev, buf, 3);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
kfree(buf);
return ret < 0 ? ret : 0; /* BT returns 0, USB returns sizeof(buf) */ return ret < 0 ? ret : 0; /* BT returns 0, USB returns sizeof(buf) */
} }
......
...@@ -272,6 +272,12 @@ static const struct hid_device_id ms_devices[] = { ...@@ -272,6 +272,12 @@ static const struct hid_device_id ms_devices[] = {
.driver_data = MS_PRESENTER }, .driver_data = MS_PRESENTER },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K),
.driver_data = MS_ERGONOMY | MS_RDESC_3K }, .driver_data = MS_ERGONOMY | MS_RDESC_3K },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K),
.driver_data = MS_ERGONOMY },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600),
.driver_data = MS_ERGONOMY },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1),
.driver_data = MS_ERGONOMY },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
.driver_data = MS_NOGET }, .driver_data = MS_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
......
...@@ -1169,6 +1169,7 @@ static void mt_release_contacts(struct hid_device *hid) ...@@ -1169,6 +1169,7 @@ static void mt_release_contacts(struct hid_device *hid)
MT_TOOL_FINGER, MT_TOOL_FINGER,
false); false);
} }
input_mt_sync_frame(input_dev);
input_sync(input_dev); input_sync(input_dev);
} }
} }
......
...@@ -2049,9 +2049,11 @@ static void wiimod_mp_in_mp(struct wiimote_data *wdata, const __u8 *ext) ...@@ -2049,9 +2049,11 @@ static void wiimod_mp_in_mp(struct wiimote_data *wdata, const __u8 *ext)
* -----+------------------------------+-----+-----+ * -----+------------------------------+-----+-----+
* The single bits Yaw, Roll, Pitch in the lower right corner specify * The single bits Yaw, Roll, Pitch in the lower right corner specify
* whether the wiimote is rotating fast (0) or slow (1). Speed for slow * whether the wiimote is rotating fast (0) or slow (1). Speed for slow
* roation is 440 deg/s and for fast rotation 2000 deg/s. To get a * roation is 8192/440 units / deg/s and for fast rotation 8192/2000
* linear scale we multiply by 2000/440 = ~4.5454 which is 18 for fast * units / deg/s. To get a linear scale for fast rotation we multiply
* and 9 for slow. * by 2000/440 = ~4.5454 and scale both fast and slow by 9 to match the
* previous scale reported by this driver.
* This leaves a linear scale with 8192*9/440 (~167.564) units / deg/s.
* If the wiimote is not rotating the sensor reports 2^13 = 8192. * If the wiimote is not rotating the sensor reports 2^13 = 8192.
* Ext specifies whether an extension is connected to the motionp. * Ext specifies whether an extension is connected to the motionp.
* which is parsed by wiimote-core. * which is parsed by wiimote-core.
...@@ -2070,15 +2072,15 @@ static void wiimod_mp_in_mp(struct wiimote_data *wdata, const __u8 *ext) ...@@ -2070,15 +2072,15 @@ static void wiimod_mp_in_mp(struct wiimote_data *wdata, const __u8 *ext)
z -= 8192; z -= 8192;
if (!(ext[3] & 0x02)) if (!(ext[3] & 0x02))
x *= 18; x = (x * 2000 * 9) / 440;
else else
x *= 9; x *= 9;
if (!(ext[4] & 0x02)) if (!(ext[4] & 0x02))
y *= 18; y = (y * 2000 * 9) / 440;
else else
y *= 9; y *= 9;
if (!(ext[3] & 0x01)) if (!(ext[3] & 0x01))
z *= 18; z = (z * 2000 * 9) / 440;
else else
z *= 9; z *= 9;
......
...@@ -951,14 +951,6 @@ static int usbhid_output_report(struct hid_device *hid, __u8 *buf, size_t count) ...@@ -951,14 +951,6 @@ static int usbhid_output_report(struct hid_device *hid, __u8 *buf, size_t count)
return ret; return ret;
} }
static void usbhid_restart_queues(struct usbhid_device *usbhid)
{
if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl))
usbhid_restart_out_queue(usbhid);
if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
usbhid_restart_ctrl_queue(usbhid);
}
static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
{ {
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
...@@ -1404,6 +1396,37 @@ static void hid_cease_io(struct usbhid_device *usbhid) ...@@ -1404,6 +1396,37 @@ static void hid_cease_io(struct usbhid_device *usbhid)
usb_kill_urb(usbhid->urbout); usb_kill_urb(usbhid->urbout);
} }
static void hid_restart_io(struct hid_device *hid)
{
struct usbhid_device *usbhid = hid->driver_data;
int clear_halt = test_bit(HID_CLEAR_HALT, &usbhid->iofl);
int reset_pending = test_bit(HID_RESET_PENDING, &usbhid->iofl);
spin_lock_irq(&usbhid->lock);
clear_bit(HID_SUSPENDED, &usbhid->iofl);
usbhid_mark_busy(usbhid);
if (clear_halt || reset_pending)
schedule_work(&usbhid->reset_work);
usbhid->retry_delay = 0;
spin_unlock_irq(&usbhid->lock);
if (reset_pending || !test_bit(HID_STARTED, &usbhid->iofl))
return;
if (!clear_halt) {
if (hid_start_in(hid) < 0)
hid_io_error(hid);
}
spin_lock_irq(&usbhid->lock);
if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl))
usbhid_restart_out_queue(usbhid);
if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
usbhid_restart_ctrl_queue(usbhid);
spin_unlock_irq(&usbhid->lock);
}
/* Treat USB reset pretty much the same as suspend/resume */ /* Treat USB reset pretty much the same as suspend/resume */
static int hid_pre_reset(struct usb_interface *intf) static int hid_pre_reset(struct usb_interface *intf)
{ {
...@@ -1453,14 +1476,14 @@ static int hid_post_reset(struct usb_interface *intf) ...@@ -1453,14 +1476,14 @@ static int hid_post_reset(struct usb_interface *intf)
return 1; return 1;
} }
/* No need to do another reset or clear a halted endpoint */
spin_lock_irq(&usbhid->lock); spin_lock_irq(&usbhid->lock);
clear_bit(HID_RESET_PENDING, &usbhid->iofl); clear_bit(HID_RESET_PENDING, &usbhid->iofl);
clear_bit(HID_CLEAR_HALT, &usbhid->iofl);
spin_unlock_irq(&usbhid->lock); spin_unlock_irq(&usbhid->lock);
hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
status = hid_start_in(hid);
if (status < 0) hid_restart_io(hid);
hid_io_error(hid);
usbhid_restart_queues(usbhid);
return 0; return 0;
} }
...@@ -1483,25 +1506,9 @@ void usbhid_put_power(struct hid_device *hid) ...@@ -1483,25 +1506,9 @@ void usbhid_put_power(struct hid_device *hid)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int hid_resume_common(struct hid_device *hid, bool driver_suspended) static int hid_resume_common(struct hid_device *hid, bool driver_suspended)
{ {
struct usbhid_device *usbhid = hid->driver_data; int status = 0;
int status;
spin_lock_irq(&usbhid->lock);
clear_bit(HID_SUSPENDED, &usbhid->iofl);
usbhid_mark_busy(usbhid);
if (test_bit(HID_CLEAR_HALT, &usbhid->iofl) ||
test_bit(HID_RESET_PENDING, &usbhid->iofl))
schedule_work(&usbhid->reset_work);
usbhid->retry_delay = 0;
usbhid_restart_queues(usbhid);
spin_unlock_irq(&usbhid->lock);
status = hid_start_in(hid);
if (status < 0)
hid_io_error(hid);
hid_restart_io(hid);
if (driver_suspended && hid->driver && hid->driver->resume) if (driver_suspended && hid->driver && hid->driver->resume)
status = hid->driver->resume(hid); status = hid->driver->resume(hid);
return status; return status;
...@@ -1570,12 +1577,8 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) ...@@ -1570,12 +1577,8 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
static int hid_resume(struct usb_interface *intf) static int hid_resume(struct usb_interface *intf)
{ {
struct hid_device *hid = usb_get_intfdata (intf); struct hid_device *hid = usb_get_intfdata (intf);
struct usbhid_device *usbhid = hid->driver_data;
int status; int status;
if (!test_bit(HID_STARTED, &usbhid->iofl))
return 0;
status = hid_resume_common(hid, true); status = hid_resume_common(hid, true);
dev_dbg(&intf->dev, "resume status %d\n", status); dev_dbg(&intf->dev, "resume status %d\n", status);
return 0; return 0;
...@@ -1584,10 +1587,8 @@ static int hid_resume(struct usb_interface *intf) ...@@ -1584,10 +1587,8 @@ static int hid_resume(struct usb_interface *intf)
static int hid_reset_resume(struct usb_interface *intf) static int hid_reset_resume(struct usb_interface *intf)
{ {
struct hid_device *hid = usb_get_intfdata(intf); struct hid_device *hid = usb_get_intfdata(intf);
struct usbhid_device *usbhid = hid->driver_data;
int status; int status;
clear_bit(HID_SUSPENDED, &usbhid->iofl);
status = hid_post_reset(intf); status = hid_post_reset(intf);
if (status >= 0 && hid->driver && hid->driver->reset_resume) { if (status >= 0 && hid->driver && hid->driver->reset_resume) {
int ret = hid->driver->reset_resume(hid); int ret = hid->driver->reset_resume(hid);
......
...@@ -152,6 +152,25 @@ static void wacom_feature_mapping(struct hid_device *hdev, ...@@ -152,6 +152,25 @@ static void wacom_feature_mapping(struct hid_device *hdev,
hid_data->inputmode = field->report->id; hid_data->inputmode = field->report->id;
hid_data->inputmode_index = usage->usage_index; hid_data->inputmode_index = usage->usage_index;
break; break;
case HID_UP_DIGITIZER:
if (field->report->id == 0x0B &&
(field->application == WACOM_G9_DIGITIZER ||
field->application == WACOM_G11_DIGITIZER)) {
wacom->wacom_wac.mode_report = field->report->id;
wacom->wacom_wac.mode_value = 0;
}
break;
case WACOM_G9_PAGE:
case WACOM_G11_PAGE:
if (field->report->id == 0x03 &&
(field->application == WACOM_G9_TOUCHSCREEN ||
field->application == WACOM_G11_TOUCHSCREEN)) {
wacom->wacom_wac.mode_report = field->report->id;
wacom->wacom_wac.mode_value = 0;
}
break;
} }
} }
...@@ -322,26 +341,41 @@ static int wacom_hid_set_device_mode(struct hid_device *hdev) ...@@ -322,26 +341,41 @@ static int wacom_hid_set_device_mode(struct hid_device *hdev)
return 0; return 0;
} }
static int wacom_set_device_mode(struct hid_device *hdev, int report_id, static int wacom_set_device_mode(struct hid_device *hdev,
int length, int mode) struct wacom_wac *wacom_wac)
{ {
unsigned char *rep_data; u8 *rep_data;
struct hid_report *r;
struct hid_report_enum *re;
int length;
int error = -ENOMEM, limit = 0; int error = -ENOMEM, limit = 0;
rep_data = kzalloc(length, GFP_KERNEL); if (wacom_wac->mode_report < 0)
return 0;
re = &(hdev->report_enum[HID_FEATURE_REPORT]);
r = re->report_id_hash[wacom_wac->mode_report];
if (!r)
return -EINVAL;
rep_data = hid_alloc_report_buf(r, GFP_KERNEL);
if (!rep_data) if (!rep_data)
return error; return -ENOMEM;
length = hid_report_len(r);
do { do {
rep_data[0] = report_id; rep_data[0] = wacom_wac->mode_report;
rep_data[1] = mode; rep_data[1] = wacom_wac->mode_value;
error = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data, error = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data,
length, 1); length, 1);
if (error >= 0) if (error >= 0)
error = wacom_get_report(hdev, HID_FEATURE_REPORT, error = wacom_get_report(hdev, HID_FEATURE_REPORT,
rep_data, length, 1); rep_data, length, 1);
} while (error >= 0 && rep_data[1] != mode && limit++ < WAC_MSG_RETRIES); } while (error >= 0 &&
rep_data[1] != wacom_wac->mode_report &&
limit++ < WAC_MSG_RETRIES);
kfree(rep_data); kfree(rep_data);
...@@ -411,32 +445,41 @@ static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed, ...@@ -411,32 +445,41 @@ static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed,
static int wacom_query_tablet_data(struct hid_device *hdev, static int wacom_query_tablet_data(struct hid_device *hdev,
struct wacom_features *features) struct wacom_features *features)
{ {
struct wacom *wacom = hid_get_drvdata(hdev);
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
if (hdev->bus == BUS_BLUETOOTH) if (hdev->bus == BUS_BLUETOOTH)
return wacom_bt_query_tablet_data(hdev, 1, features); return wacom_bt_query_tablet_data(hdev, 1, features);
if (features->type == HID_GENERIC) if (features->type != HID_GENERIC) {
return wacom_hid_set_device_mode(hdev); if (features->device_type & WACOM_DEVICETYPE_TOUCH) {
if (features->type > TABLETPC) {
if (features->device_type & WACOM_DEVICETYPE_TOUCH) { /* MT Tablet PC touch */
if (features->type > TABLETPC) { wacom_wac->mode_report = 3;
/* MT Tablet PC touch */ wacom_wac->mode_value = 4;
return wacom_set_device_mode(hdev, 3, 4, 4); } else if (features->type == WACOM_24HDT) {
} wacom_wac->mode_report = 18;
else if (features->type == WACOM_24HDT) { wacom_wac->mode_value = 2;
return wacom_set_device_mode(hdev, 18, 3, 2); } else if (features->type == WACOM_27QHDT) {
} wacom_wac->mode_report = 131;
else if (features->type == WACOM_27QHDT) { wacom_wac->mode_value = 2;
return wacom_set_device_mode(hdev, 131, 3, 2); } else if (features->type == BAMBOO_PAD) {
} wacom_wac->mode_report = 2;
else if (features->type == BAMBOO_PAD) { wacom_wac->mode_value = 2;
return wacom_set_device_mode(hdev, 2, 2, 2); }
} } else if (features->device_type & WACOM_DEVICETYPE_PEN) {
} else if (features->device_type & WACOM_DEVICETYPE_PEN) { if (features->type <= BAMBOO_PT) {
if (features->type <= BAMBOO_PT) { wacom_wac->mode_report = 2;
return wacom_set_device_mode(hdev, 2, 2, 2); wacom_wac->mode_value = 2;
}
} }
} }
wacom_set_device_mode(hdev, wacom_wac);
if (features->type == HID_GENERIC)
return wacom_hid_set_device_mode(hdev);
return 0; return 0;
} }
...@@ -1817,6 +1860,9 @@ static int wacom_probe(struct hid_device *hdev, ...@@ -1817,6 +1860,9 @@ static int wacom_probe(struct hid_device *hdev,
goto fail_type; goto fail_type;
} }
wacom_wac->hid_data.inputmode = -1;
wacom_wac->mode_report = -1;
wacom->usbdev = dev; wacom->usbdev = dev;
wacom->intf = intf; wacom->intf = intf;
mutex_init(&wacom->lock); mutex_init(&wacom->lock);
......
...@@ -2425,6 +2425,17 @@ void wacom_setup_device_quirks(struct wacom *wacom) ...@@ -2425,6 +2425,17 @@ void wacom_setup_device_quirks(struct wacom *wacom)
} }
} }
/*
* Hack for the Bamboo One:
* the device presents a PAD/Touch interface as most Bamboos and even
* sends ghosts PAD data on it. However, later, we must disable this
* ghost interface, and we can not detect it unless we set it here
* to WACOM_DEVICETYPE_PAD or WACOM_DEVICETYPE_TOUCH.
*/
if (features->type == BAMBOO_PEN &&
features->pktlen == WACOM_PKGLEN_BBTOUCH3)
features->device_type |= WACOM_DEVICETYPE_PAD;
/* /*
* Raw Wacom-mode pen and touch events both come from interface * Raw Wacom-mode pen and touch events both come from interface
* 0, whose HID descriptor has an application usage of 0xFF0D * 0, whose HID descriptor has an application usage of 0xFF0D
......
...@@ -84,6 +84,12 @@ ...@@ -84,6 +84,12 @@
#define WACOM_DEVICETYPE_WL_MONITOR 0x0008 #define WACOM_DEVICETYPE_WL_MONITOR 0x0008
#define WACOM_VENDORDEFINED_PEN 0xff0d0001 #define WACOM_VENDORDEFINED_PEN 0xff0d0001
#define WACOM_G9_PAGE 0xff090000
#define WACOM_G9_DIGITIZER (WACOM_G9_PAGE | 0x02)
#define WACOM_G9_TOUCHSCREEN (WACOM_G9_PAGE | 0x11)
#define WACOM_G11_PAGE 0xff110000
#define WACOM_G11_DIGITIZER (WACOM_G11_PAGE | 0x02)
#define WACOM_G11_TOUCHSCREEN (WACOM_G11_PAGE | 0x11)
#define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \
((f)->physical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_STYLUS) || \
...@@ -238,6 +244,8 @@ struct wacom_wac { ...@@ -238,6 +244,8 @@ struct wacom_wac {
int ps_connected; int ps_connected;
u8 bt_features; u8 bt_features;
u8 bt_high_speed; u8 bt_high_speed;
int mode_report;
int mode_value;
struct hid_data hid_data; struct hid_data hid_data;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment