aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikolai Kondrashov <spbnick@gmail.com>2014-08-11 13:45:31 -0400
committerJiri Kosina <jkosina@suse.cz>2014-08-12 06:44:58 -0400
commit657d6dc4197e9bc13522d0ed0e1a4ae7d0d84614 (patch)
tree0dc75926ec3c4401c84b4d988f263860d6d46f3b
parent172bfe09dc52aef29f9c5c0bd9f77a558120faf4 (diff)
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>
-rw-r--r--drivers/hid/hid-huion.c96
1 files changed, 49 insertions, 47 deletions
diff --git a/drivers/hid/hid-huion.c b/drivers/hid/hid-huion.c
index 60f44cd1b0ed..a683d4b4a531 100644
--- a/drivers/hid/hid-huion.c
+++ b/drivers/hid/hid-huion.c
@@ -116,6 +116,10 @@ static int huion_tablet_enable(struct hid_device *hdev)
116 struct usb_device *usb_dev = hid_to_usb_dev(hdev); 116 struct usb_device *usb_dev = hid_to_usb_dev(hdev);
117 struct huion_drvdata *drvdata = hid_get_drvdata(hdev); 117 struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
118 __le16 buf[6]; 118 __le16 buf[6];
119 s32 params[HUION_PH_ID_NUM];
120 s32 resolution;
121 __u8 *p;
122 s32 v;
119 123
120 /* 124 /*
121 * Read string descriptor containing tablet parameters. The specific 125 * Read string descriptor containing tablet parameters. The specific
@@ -128,56 +132,54 @@ static int huion_tablet_enable(struct hid_device *hdev)
128 (USB_DT_STRING << 8) + 0x64, 132 (USB_DT_STRING << 8) + 0x64,
129 0x0409, buf, sizeof(buf), 133 0x0409, buf, sizeof(buf),
130 USB_CTRL_GET_TIMEOUT); 134 USB_CTRL_GET_TIMEOUT);
131 if (rc == -EPIPE) 135 if (rc == -EPIPE) {
132 hid_warn(hdev, "device parameters not found\n"); 136 hid_err(hdev, "device parameters not found\n");
133 else if (rc < 0) 137 return -ENODEV;
134 hid_warn(hdev, "failed to get device parameters: %d\n", rc); 138 } else if (rc < 0) {
135 else if (rc != sizeof(buf)) 139 hid_err(hdev, "failed to get device parameters: %d\n", rc);
136 hid_warn(hdev, "invalid device parameters\n"); 140 return -ENODEV;
137 else { 141 } else if (rc != sizeof(buf)) {
138 s32 params[HUION_PH_ID_NUM]; 142 hid_err(hdev, "invalid device parameters\n");
139 s32 resolution; 143 return -ENODEV;
140 __u8 *p; 144 }
141 s32 v;
142 145
143 /* Extract device parameters */ 146 /* Extract device parameters */
144 params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[1]); 147 params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[1]);
145 params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[2]); 148 params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[2]);
146 params[HUION_PH_ID_PRESSURE_LM] = le16_to_cpu(buf[4]); 149 params[HUION_PH_ID_PRESSURE_LM] = le16_to_cpu(buf[4]);
147 resolution = le16_to_cpu(buf[5]); 150 resolution = le16_to_cpu(buf[5]);
148 if (resolution == 0) { 151 if (resolution == 0) {
149 params[HUION_PH_ID_X_PM] = 0; 152 params[HUION_PH_ID_X_PM] = 0;
150 params[HUION_PH_ID_Y_PM] = 0; 153 params[HUION_PH_ID_Y_PM] = 0;
151 } else { 154 } else {
152 params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] * 155 params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] *
153 1000 / resolution; 156 1000 / resolution;
154 params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] * 157 params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] *
155 1000 / resolution; 158 1000 / resolution;
156 } 159 }
157 160
158 /* Allocate fixed report descriptor */ 161 /* Allocate fixed report descriptor */
159 drvdata->rdesc = devm_kmalloc(&hdev->dev, 162 drvdata->rdesc = devm_kmalloc(&hdev->dev,
160 sizeof(huion_tablet_rdesc_template), 163 sizeof(huion_tablet_rdesc_template),
161 GFP_KERNEL); 164 GFP_KERNEL);
162 if (drvdata->rdesc == NULL) { 165 if (drvdata->rdesc == NULL) {
163 hid_err(hdev, "failed to allocate fixed rdesc\n"); 166 hid_err(hdev, "failed to allocate fixed rdesc\n");
164 return -ENOMEM; 167 return -ENOMEM;
165 } 168 }
166 drvdata->rsize = sizeof(huion_tablet_rdesc_template); 169 drvdata->rsize = sizeof(huion_tablet_rdesc_template);
167 170
168 /* Format fixed report descriptor */ 171 /* Format fixed report descriptor */
169 memcpy(drvdata->rdesc, huion_tablet_rdesc_template, 172 memcpy(drvdata->rdesc, huion_tablet_rdesc_template,
170 drvdata->rsize); 173 drvdata->rsize);
171 for (p = drvdata->rdesc; 174 for (p = drvdata->rdesc;
172 p <= drvdata->rdesc + drvdata->rsize - 4;) { 175 p <= drvdata->rdesc + drvdata->rsize - 4;) {
173 if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D && 176 if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
174 p[3] < sizeof(params)) { 177 p[3] < sizeof(params)) {
175 v = params[p[3]]; 178 v = params[p[3]];
176 put_unaligned(cpu_to_le32(v), (s32 *)p); 179 put_unaligned(cpu_to_le32(v), (s32 *)p);
177 p += 4; 180 p += 4;
178 } else { 181 } else {
179 p++; 182 p++;
180 }
181 } 183 }
182 } 184 }
183 185