diff options
Diffstat (limited to 'drivers/uwb/wlp/messages.c')
-rw-r--r-- | drivers/uwb/wlp/messages.c | 106 |
1 files changed, 61 insertions, 45 deletions
diff --git a/drivers/uwb/wlp/messages.c b/drivers/uwb/wlp/messages.c index aa42fcee4c4f..75164866c2d8 100644 --- a/drivers/uwb/wlp/messages.c +++ b/drivers/uwb/wlp/messages.c | |||
@@ -259,6 +259,63 @@ out: | |||
259 | } | 259 | } |
260 | 260 | ||
261 | 261 | ||
262 | static ssize_t wlp_get_attribute(struct wlp *wlp, u16 type_code, | ||
263 | struct wlp_attr_hdr *attr_hdr, void *value, ssize_t value_len, | ||
264 | ssize_t buflen) | ||
265 | { | ||
266 | struct device *dev = &wlp->rc->uwb_dev.dev; | ||
267 | ssize_t attr_len = sizeof(*attr_hdr) + value_len; | ||
268 | if (buflen < 0) | ||
269 | return -EINVAL; | ||
270 | if (buflen < attr_len) { | ||
271 | dev_err(dev, "WLP: Not enough space in buffer to parse" | ||
272 | " attribute field. Need %d, received %zu\n", | ||
273 | (int)attr_len, buflen); | ||
274 | return -EIO; | ||
275 | } | ||
276 | if (wlp_check_attr_hdr(wlp, attr_hdr, type_code, value_len) < 0) { | ||
277 | dev_err(dev, "WLP: Header verification failed. \n"); | ||
278 | return -EINVAL; | ||
279 | } | ||
280 | memcpy(value, (void *)attr_hdr + sizeof(*attr_hdr), value_len); | ||
281 | return attr_len; | ||
282 | } | ||
283 | |||
284 | static ssize_t wlp_vget_attribute(struct wlp *wlp, u16 type_code, | ||
285 | struct wlp_attr_hdr *attr_hdr, void *value, ssize_t max_value_len, | ||
286 | ssize_t buflen) | ||
287 | { | ||
288 | struct device *dev = &wlp->rc->uwb_dev.dev; | ||
289 | size_t len; | ||
290 | if (buflen < 0) | ||
291 | return -EINVAL; | ||
292 | if (buflen < sizeof(*attr_hdr)) { | ||
293 | dev_err(dev, "WLP: Not enough space in buffer to parse" | ||
294 | " header.\n"); | ||
295 | return -EIO; | ||
296 | } | ||
297 | if (le16_to_cpu(attr_hdr->type) != type_code) { | ||
298 | dev_err(dev, "WLP: Unexpected attribute type. Got %u, " | ||
299 | "expected %u.\n", le16_to_cpu(attr_hdr->type), | ||
300 | type_code); | ||
301 | return -EINVAL; | ||
302 | } | ||
303 | len = le16_to_cpu(attr_hdr->length); | ||
304 | if (len > max_value_len) { | ||
305 | dev_err(dev, "WLP: Attribute larger than maximum " | ||
306 | "allowed. Received %zu, max is %d.\n", len, | ||
307 | (int)max_value_len); | ||
308 | return -EFBIG; | ||
309 | } | ||
310 | if (buflen < sizeof(*attr_hdr) + len) { | ||
311 | dev_err(dev, "WLP: Not enough space in buffer to parse " | ||
312 | "variable data.\n"); | ||
313 | return -EIO; | ||
314 | } | ||
315 | memcpy(value, (void *)attr_hdr + sizeof(*attr_hdr), len); | ||
316 | return sizeof(*attr_hdr) + len; | ||
317 | } | ||
318 | |||
262 | /** | 319 | /** |
263 | * Get value of attribute from fixed size attribute field. | 320 | * Get value of attribute from fixed size attribute field. |
264 | * | 321 | * |
@@ -274,22 +331,8 @@ out: | |||
274 | ssize_t wlp_get_##name(struct wlp *wlp, struct wlp_attr_##name *attr, \ | 331 | ssize_t wlp_get_##name(struct wlp *wlp, struct wlp_attr_##name *attr, \ |
275 | type *value, ssize_t buflen) \ | 332 | type *value, ssize_t buflen) \ |
276 | { \ | 333 | { \ |
277 | struct device *dev = &wlp->rc->uwb_dev.dev; \ | 334 | return wlp_get_attribute(wlp, (type_code), &attr->hdr, \ |
278 | if (buflen < 0) \ | 335 | value, sizeof(*value), buflen); \ |
279 | return -EINVAL; \ | ||
280 | if (buflen < sizeof(*attr)) { \ | ||
281 | dev_err(dev, "WLP: Not enough space in buffer to parse" \ | ||
282 | " attribute field. Need %d, received %zu\n", \ | ||
283 | (int)sizeof(*attr), buflen); \ | ||
284 | return -EIO; \ | ||
285 | } \ | ||
286 | if (wlp_check_attr_hdr(wlp, &attr->hdr, type_code, \ | ||
287 | sizeof(attr->name)) < 0) { \ | ||
288 | dev_err(dev, "WLP: Header verification failed. \n"); \ | ||
289 | return -EINVAL; \ | ||
290 | } \ | ||
291 | *value = attr->name; \ | ||
292 | return sizeof(*attr); \ | ||
293 | } | 336 | } |
294 | 337 | ||
295 | #define wlp_get_sparse(type, type_code, name) \ | 338 | #define wlp_get_sparse(type, type_code, name) \ |
@@ -313,35 +356,8 @@ static ssize_t wlp_get_##name(struct wlp *wlp, \ | |||
313 | struct wlp_attr_##name *attr, \ | 356 | struct wlp_attr_##name *attr, \ |
314 | type_val *value, ssize_t buflen) \ | 357 | type_val *value, ssize_t buflen) \ |
315 | { \ | 358 | { \ |
316 | struct device *dev = &wlp->rc->uwb_dev.dev; \ | 359 | return wlp_vget_attribute(wlp, (type_code), &attr->hdr, \ |
317 | size_t len; \ | 360 | value, (max), buflen); \ |
318 | if (buflen < 0) \ | ||
319 | return -EINVAL; \ | ||
320 | if (buflen < sizeof(*attr)) { \ | ||
321 | dev_err(dev, "WLP: Not enough space in buffer to parse" \ | ||
322 | " header.\n"); \ | ||
323 | return -EIO; \ | ||
324 | } \ | ||
325 | if (le16_to_cpu(attr->hdr.type) != type_code) { \ | ||
326 | dev_err(dev, "WLP: Unexpected attribute type. Got %u, " \ | ||
327 | "expected %u.\n", le16_to_cpu(attr->hdr.type), \ | ||
328 | type_code); \ | ||
329 | return -EINVAL; \ | ||
330 | } \ | ||
331 | len = le16_to_cpu(attr->hdr.length); \ | ||
332 | if (len > max) { \ | ||
333 | dev_err(dev, "WLP: Attribute larger than maximum " \ | ||
334 | "allowed. Received %zu, max is %d.\n", len, \ | ||
335 | (int)max); \ | ||
336 | return -EFBIG; \ | ||
337 | } \ | ||
338 | if (buflen < sizeof(*attr) + len) { \ | ||
339 | dev_err(dev, "WLP: Not enough space in buffer to parse "\ | ||
340 | "variable data.\n"); \ | ||
341 | return -EIO; \ | ||
342 | } \ | ||
343 | memcpy(value, (void *) attr + sizeof(*attr), len); \ | ||
344 | return sizeof(*attr) + len; \ | ||
345 | } | 361 | } |
346 | 362 | ||
347 | wlp_get(u8, WLP_ATTR_WLP_VER, version) | 363 | wlp_get(u8, WLP_ATTR_WLP_VER, version) |