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
This commit is contained in:
commit
1c74a7f812
|
@ -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 @@
|
||||||
#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 @@
|
||||||
#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,
|
||||||
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[] = {
|
||||||
.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)
|
||||||
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)
|
||||||
* -----+------------------------------+-----+-----+
|
* -----+------------------------------+-----+-----+
|
||||||
* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
#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)
|
||||||
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)
|
||||||
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,
|
||||||
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)
|
||||||
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,31 +445,40 @@ 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->device_type & WACOM_DEVICETYPE_TOUCH) {
|
||||||
if (features->type > TABLETPC) {
|
if (features->type > TABLETPC) {
|
||||||
/* MT Tablet PC touch */
|
/* MT Tablet PC touch */
|
||||||
return wacom_set_device_mode(hdev, 3, 4, 4);
|
wacom_wac->mode_report = 3;
|
||||||
}
|
wacom_wac->mode_value = 4;
|
||||||
else if (features->type == WACOM_24HDT) {
|
} else if (features->type == WACOM_24HDT) {
|
||||||
return wacom_set_device_mode(hdev, 18, 3, 2);
|
wacom_wac->mode_report = 18;
|
||||||
}
|
wacom_wac->mode_value = 2;
|
||||||
else if (features->type == WACOM_27QHDT) {
|
} else if (features->type == WACOM_27QHDT) {
|
||||||
return wacom_set_device_mode(hdev, 131, 3, 2);
|
wacom_wac->mode_report = 131;
|
||||||
}
|
wacom_wac->mode_value = 2;
|
||||||
else if (features->type == BAMBOO_PAD) {
|
} else if (features->type == BAMBOO_PAD) {
|
||||||
return wacom_set_device_mode(hdev, 2, 2, 2);
|
wacom_wac->mode_report = 2;
|
||||||
|
wacom_wac->mode_value = 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) {
|
||||||
return wacom_set_device_mode(hdev, 2, 2, 2);
|
wacom_wac->mode_report = 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,
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
#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 {
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue