Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

uwb: add an ASIE sysfs attribute to uwb_rc devices

Allow user mode to add and remove application specific information
elements (ASIEs) to the beacon of a uwb_rc device.

Signed-off-by: Thomas Pugliese <thomas.pugliese@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Thomas Pugliese and committed by
Greg Kroah-Hartman
d08e1ad9 005799d5

+99
+99
drivers/uwb/lc-rc.c
··· 119 119 } 120 120 EXPORT_SYMBOL_GPL(uwb_rc_alloc); 121 121 122 + /* 123 + * Show the ASIE that is broadcast in the UWB beacon by this uwb_rc device. 124 + */ 125 + static ssize_t ASIE_show(struct device *dev, 126 + struct device_attribute *attr, char *buf) 127 + { 128 + struct uwb_dev *uwb_dev = to_uwb_dev(dev); 129 + struct uwb_rc *rc = uwb_dev->rc; 130 + struct uwb_ie_hdr *ie; 131 + void *ptr; 132 + size_t len; 133 + int result = 0; 134 + 135 + /* init empty buffer. */ 136 + result = scnprintf(buf, PAGE_SIZE, "\n"); 137 + mutex_lock(&rc->ies_mutex); 138 + /* walk IEData looking for an ASIE. */ 139 + ptr = rc->ies->IEData; 140 + len = le16_to_cpu(rc->ies->wIELength); 141 + for (;;) { 142 + ie = uwb_ie_next(&ptr, &len); 143 + if (!ie) 144 + break; 145 + if (ie->element_id == UWB_APP_SPEC_IE) { 146 + result = uwb_ie_dump_hex(ie, 147 + ie->length + sizeof(struct uwb_ie_hdr), 148 + buf, PAGE_SIZE); 149 + break; 150 + } 151 + } 152 + mutex_unlock(&rc->ies_mutex); 153 + 154 + return result; 155 + } 156 + 157 + /* 158 + * Update the ASIE that is broadcast in the UWB beacon by this uwb_rc device. 159 + */ 160 + static ssize_t ASIE_store(struct device *dev, 161 + struct device_attribute *attr, 162 + const char *buf, size_t size) 163 + { 164 + struct uwb_dev *uwb_dev = to_uwb_dev(dev); 165 + struct uwb_rc *rc = uwb_dev->rc; 166 + char ie_buf[255]; 167 + int result, ie_len = 0; 168 + const char *cur_ptr = buf; 169 + struct uwb_ie_hdr *ie; 170 + 171 + /* empty string means clear the ASIE. */ 172 + if (strlen(buf) <= 1) { 173 + uwb_rc_ie_rm(rc, UWB_APP_SPEC_IE); 174 + return size; 175 + } 176 + 177 + /* if non-empty string, convert string of hex chars to binary. */ 178 + while (ie_len < sizeof(ie_buf)) { 179 + int char_count; 180 + 181 + if (sscanf(cur_ptr, " %02hhX %n", 182 + &(ie_buf[ie_len]), &char_count) > 0) { 183 + ++ie_len; 184 + /* skip chars read from cur_ptr. */ 185 + cur_ptr += char_count; 186 + } else { 187 + break; 188 + } 189 + } 190 + 191 + /* validate IE length and type. */ 192 + if (ie_len < sizeof(struct uwb_ie_hdr)) { 193 + dev_err(dev, "%s: Invalid ASIE size %d.\n", __func__, ie_len); 194 + return -EINVAL; 195 + } 196 + 197 + ie = (struct uwb_ie_hdr *)ie_buf; 198 + if (ie->element_id != UWB_APP_SPEC_IE) { 199 + dev_err(dev, "%s: Invalid IE element type size = 0x%02X.\n", 200 + __func__, ie->element_id); 201 + return -EINVAL; 202 + } 203 + 204 + /* bounds check length field from user. */ 205 + if (ie->length > (ie_len - sizeof(struct uwb_ie_hdr))) 206 + ie->length = ie_len - sizeof(struct uwb_ie_hdr); 207 + 208 + /* 209 + * Valid ASIE received. Remove current ASIE then add the new one using 210 + * uwb_rc_ie_add. 211 + */ 212 + uwb_rc_ie_rm(rc, UWB_APP_SPEC_IE); 213 + 214 + result = uwb_rc_ie_add(rc, ie, ie->length + sizeof(struct uwb_ie_hdr)); 215 + 216 + return result >= 0 ? size : result; 217 + } 218 + static DEVICE_ATTR_RW(ASIE); 219 + 122 220 static struct attribute *rc_attrs[] = { 123 221 &dev_attr_mac_address.attr, 124 222 &dev_attr_scan.attr, 125 223 &dev_attr_beacon.attr, 224 + &dev_attr_ASIE.attr, 126 225 NULL, 127 226 }; 128 227