diff --git a/drivers/uwb/Makefile b/drivers/uwb/Makefile index 257e6908304c..2b99c3e61671 100644 --- a/drivers/uwb/Makefile +++ b/drivers/uwb/Makefile @@ -13,6 +13,7 @@ uwb-objs := \ drp-ie.o \ est.o \ ie.o \ + ie-rcv.o \ lc-dev.o \ lc-rc.o \ neh.o \ diff --git a/drivers/uwb/ie-rcv.c b/drivers/uwb/ie-rcv.c new file mode 100644 index 000000000000..917e6d78a798 --- /dev/null +++ b/drivers/uwb/ie-rcv.c @@ -0,0 +1,55 @@ +/* + * Ultra Wide Band + * IE Received notification handling. + * + * Copyright (C) 2008 Cambridge Silicon Radio Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include "uwb-internal.h" + +/* + * Process an incoming IE Received notification. + */ +int uwbd_evt_handle_rc_ie_rcv(struct uwb_event *evt) +{ + int result = -EINVAL; + struct device *dev = &evt->rc->uwb_dev.dev; + struct uwb_rc_evt_ie_rcv *iercv; + size_t iesize; + + /* Is there enough data to decode it? */ + if (evt->notif.size < sizeof(*iercv)) { + dev_err(dev, "IE Received notification: Not enough data to " + "decode (%zu vs %zu bytes needed)\n", + evt->notif.size, sizeof(*iercv)); + goto error; + } + iercv = container_of(evt->notif.rceb, struct uwb_rc_evt_ie_rcv, rceb); + iesize = le16_to_cpu(iercv->wIELength); + + dev_dbg(dev, "IE received, element ID=%d\n", iercv->IEData[0]); + + if (iercv->IEData[0] == UWB_RELINQUISH_REQUEST_IE) { + dev_warn(dev, "unhandled Relinquish Request IE\n"); + } + + return 0; +error: + return result; +} diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h index 983ebc4dd8d5..031e8a885681 100644 --- a/drivers/uwb/uwb-internal.h +++ b/drivers/uwb/uwb-internal.h @@ -167,6 +167,7 @@ extern void uwbd_event_queue(struct uwb_event *); void uwbd_flush(struct uwb_rc *rc); /* UWB event handlers */ +extern int uwbd_evt_handle_rc_ie_rcv(struct uwb_event *); extern int uwbd_evt_handle_rc_beacon(struct uwb_event *); extern int uwbd_evt_handle_rc_beacon_size(struct uwb_event *); extern int uwbd_evt_handle_rc_bpoie_change(struct uwb_event *); diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c index 78908416e42c..f75113571f4a 100644 --- a/drivers/uwb/uwbd.c +++ b/drivers/uwb/uwbd.c @@ -104,6 +104,10 @@ struct uwbd_event { /** Table of handlers for and properties of the UWBD Radio Control Events */ static struct uwbd_event uwbd_events[] = { + [UWB_RC_EVT_IE_RCV] = { + .handler = uwbd_evt_handle_rc_ie_rcv, + .name = "IE_RECEIVED" + }, [UWB_RC_EVT_BEACON] = { .handler = uwbd_evt_handle_rc_beacon, .name = "BEACON_RECEIVED" diff --git a/include/linux/uwb/spec.h b/include/linux/uwb/spec.h index 198c15f8e251..a30436ea53aa 100644 --- a/include/linux/uwb/spec.h +++ b/include/linux/uwb/spec.h @@ -200,6 +200,12 @@ enum uwb_drp_reason { UWB_DRP_REASON_MODIFIED, }; +/** Relinquish Request Reason Codes ([ECMA-368] table 113) */ +enum uwb_relinquish_req_reason { + UWB_RELINQUISH_REQ_REASON_NON_SPECIFIC = 0, + UWB_RELINQUISH_REQ_REASON_OVER_ALLOCATION, +}; + /** * DRP Notification Reason Codes (WHCI 0.95 [3.1.4.9]) */ @@ -252,6 +258,7 @@ enum uwb_ie { UWB_APP_SPEC_PROBE_IE = 15, UWB_IDENTIFICATION_IE = 19, UWB_MASTER_KEY_ID_IE = 20, + UWB_RELINQUISH_REQUEST_IE = 21, UWB_IE_WLP = 250, /* WiMedia Logical Link Control Protocol WLP 0.99 */ UWB_APP_SPEC_IE = 255, }; @@ -365,6 +372,27 @@ struct uwb_ie_drp_avail { DECLARE_BITMAP(bmp, UWB_NUM_MAS); } __attribute__((packed)); +/* Relinqish Request IE ([ECMA-368] section 16.8.19). */ +struct uwb_relinquish_request_ie { + struct uwb_ie_hdr hdr; + __le16 relinquish_req_control; + struct uwb_dev_addr dev_addr; + struct uwb_drp_alloc allocs[]; +} __attribute__((packed)); + +static inline int uwb_ie_relinquish_req_reason_code(struct uwb_relinquish_request_ie *ie) +{ + return (le16_to_cpu(ie->relinquish_req_control) >> 0) & 0xf; +} + +static inline void uwb_ie_relinquish_req_set_reason_code(struct uwb_relinquish_request_ie *ie, + int reason_code) +{ + u16 ctrl = le16_to_cpu(ie->relinquish_req_control); + ctrl = (ctrl & ~(0xf << 0)) | (reason_code << 0); + ie->relinquish_req_control = cpu_to_le16(ctrl); +} + /** * The Vendor ID is set to an OUI that indicates the vendor of the device. * ECMA-368 [16.8.10]