HID: huion: Fail on parameter retrieval errors
Fail Huion tablet interface enabling and probing, if parameter retrieval fails. Move the main code path out of the else block accordingly. This should prevent devices appearing in a half-working state due to original report descriptor being used, simplifying diagnostics. This also makes it easier to add cleanup in later commits, as error handling is simplified. Signed-off-by: Nikolai Kondrashov <spbnick@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
Родитель
172bfe09dc
Коммит
657d6dc419
|
@ -116,6 +116,10 @@ static int huion_tablet_enable(struct hid_device *hdev)
|
||||||
struct usb_device *usb_dev = hid_to_usb_dev(hdev);
|
struct usb_device *usb_dev = hid_to_usb_dev(hdev);
|
||||||
struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
|
struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
|
||||||
__le16 buf[6];
|
__le16 buf[6];
|
||||||
|
s32 params[HUION_PH_ID_NUM];
|
||||||
|
s32 resolution;
|
||||||
|
__u8 *p;
|
||||||
|
s32 v;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read string descriptor containing tablet parameters. The specific
|
* Read string descriptor containing tablet parameters. The specific
|
||||||
|
@ -128,56 +132,54 @@ static int huion_tablet_enable(struct hid_device *hdev)
|
||||||
(USB_DT_STRING << 8) + 0x64,
|
(USB_DT_STRING << 8) + 0x64,
|
||||||
0x0409, buf, sizeof(buf),
|
0x0409, buf, sizeof(buf),
|
||||||
USB_CTRL_GET_TIMEOUT);
|
USB_CTRL_GET_TIMEOUT);
|
||||||
if (rc == -EPIPE)
|
if (rc == -EPIPE) {
|
||||||
hid_warn(hdev, "device parameters not found\n");
|
hid_err(hdev, "device parameters not found\n");
|
||||||
else if (rc < 0)
|
return -ENODEV;
|
||||||
hid_warn(hdev, "failed to get device parameters: %d\n", rc);
|
} else if (rc < 0) {
|
||||||
else if (rc != sizeof(buf))
|
hid_err(hdev, "failed to get device parameters: %d\n", rc);
|
||||||
hid_warn(hdev, "invalid device parameters\n");
|
return -ENODEV;
|
||||||
else {
|
} else if (rc != sizeof(buf)) {
|
||||||
s32 params[HUION_PH_ID_NUM];
|
hid_err(hdev, "invalid device parameters\n");
|
||||||
s32 resolution;
|
return -ENODEV;
|
||||||
__u8 *p;
|
}
|
||||||
s32 v;
|
|
||||||
|
|
||||||
/* Extract device parameters */
|
/* Extract device parameters */
|
||||||
params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[1]);
|
params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[1]);
|
||||||
params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[2]);
|
params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[2]);
|
||||||
params[HUION_PH_ID_PRESSURE_LM] = le16_to_cpu(buf[4]);
|
params[HUION_PH_ID_PRESSURE_LM] = le16_to_cpu(buf[4]);
|
||||||
resolution = le16_to_cpu(buf[5]);
|
resolution = le16_to_cpu(buf[5]);
|
||||||
if (resolution == 0) {
|
if (resolution == 0) {
|
||||||
params[HUION_PH_ID_X_PM] = 0;
|
params[HUION_PH_ID_X_PM] = 0;
|
||||||
params[HUION_PH_ID_Y_PM] = 0;
|
params[HUION_PH_ID_Y_PM] = 0;
|
||||||
|
} else {
|
||||||
|
params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] *
|
||||||
|
1000 / resolution;
|
||||||
|
params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] *
|
||||||
|
1000 / resolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate fixed report descriptor */
|
||||||
|
drvdata->rdesc = devm_kmalloc(&hdev->dev,
|
||||||
|
sizeof(huion_tablet_rdesc_template),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (drvdata->rdesc == NULL) {
|
||||||
|
hid_err(hdev, "failed to allocate fixed rdesc\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
drvdata->rsize = sizeof(huion_tablet_rdesc_template);
|
||||||
|
|
||||||
|
/* Format fixed report descriptor */
|
||||||
|
memcpy(drvdata->rdesc, huion_tablet_rdesc_template,
|
||||||
|
drvdata->rsize);
|
||||||
|
for (p = drvdata->rdesc;
|
||||||
|
p <= drvdata->rdesc + drvdata->rsize - 4;) {
|
||||||
|
if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
|
||||||
|
p[3] < sizeof(params)) {
|
||||||
|
v = params[p[3]];
|
||||||
|
put_unaligned(cpu_to_le32(v), (s32 *)p);
|
||||||
|
p += 4;
|
||||||
} else {
|
} else {
|
||||||
params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] *
|
p++;
|
||||||
1000 / resolution;
|
|
||||||
params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] *
|
|
||||||
1000 / resolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate fixed report descriptor */
|
|
||||||
drvdata->rdesc = devm_kmalloc(&hdev->dev,
|
|
||||||
sizeof(huion_tablet_rdesc_template),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (drvdata->rdesc == NULL) {
|
|
||||||
hid_err(hdev, "failed to allocate fixed rdesc\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
drvdata->rsize = sizeof(huion_tablet_rdesc_template);
|
|
||||||
|
|
||||||
/* Format fixed report descriptor */
|
|
||||||
memcpy(drvdata->rdesc, huion_tablet_rdesc_template,
|
|
||||||
drvdata->rsize);
|
|
||||||
for (p = drvdata->rdesc;
|
|
||||||
p <= drvdata->rdesc + drvdata->rsize - 4;) {
|
|
||||||
if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
|
|
||||||
p[3] < sizeof(params)) {
|
|
||||||
v = params[p[3]];
|
|
||||||
put_unaligned(cpu_to_le32(v), (s32 *)p);
|
|
||||||
p += 4;
|
|
||||||
} else {
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче