linux/drivers/uwb/beacon.c
<<
>>
Prefs
   1/*
   2 * Ultra Wide Band
   3 * Beacon management
   4 *
   5 * Copyright (C) 2005-2006 Intel Corporation
   6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License version
  10 * 2 as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20 * 02110-1301, USA.
  21 *
  22 *
  23 * FIXME: docs
  24 */
  25
  26#include <linux/kernel.h>
  27#include <linux/init.h>
  28#include <linux/module.h>
  29#include <linux/device.h>
  30#include <linux/err.h>
  31#include <linux/kdev_t.h>
  32#include "uwb-internal.h"
  33
  34#define D_LOCAL 0
  35#include <linux/uwb/debug.h>
  36
  37/** Start Beaconing command structure */
  38struct uwb_rc_cmd_start_beacon {
  39        struct uwb_rccb rccb;
  40        __le16 wBPSTOffset;
  41        u8 bChannelNumber;
  42} __attribute__((packed));
  43
  44
  45static int uwb_rc_start_beacon(struct uwb_rc *rc, u16 bpst_offset, u8 channel)
  46{
  47        int result;
  48        struct uwb_rc_cmd_start_beacon *cmd;
  49        struct uwb_rc_evt_confirm reply;
  50
  51        cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
  52        if (cmd == NULL)
  53                return -ENOMEM;
  54        cmd->rccb.bCommandType = UWB_RC_CET_GENERAL;
  55        cmd->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_START_BEACON);
  56        cmd->wBPSTOffset = cpu_to_le16(bpst_offset);
  57        cmd->bChannelNumber = channel;
  58        reply.rceb.bEventType = UWB_RC_CET_GENERAL;
  59        reply.rceb.wEvent = UWB_RC_CMD_START_BEACON;
  60        result = uwb_rc_cmd(rc, "START-BEACON", &cmd->rccb, sizeof(*cmd),
  61                            &reply.rceb, sizeof(reply));
  62        if (result < 0)
  63                goto error_cmd;
  64        if (reply.bResultCode != UWB_RC_RES_SUCCESS) {
  65                dev_err(&rc->uwb_dev.dev,
  66                        "START-BEACON: command execution failed: %s (%d)\n",
  67                        uwb_rc_strerror(reply.bResultCode), reply.bResultCode);
  68                result = -EIO;
  69        }
  70error_cmd:
  71        kfree(cmd);
  72        return result;
  73}
  74
  75static int uwb_rc_stop_beacon(struct uwb_rc *rc)
  76{
  77        int result;
  78        struct uwb_rccb *cmd;
  79        struct uwb_rc_evt_confirm reply;
  80
  81        cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
  82        if (cmd == NULL)
  83                return -ENOMEM;
  84        cmd->bCommandType = UWB_RC_CET_GENERAL;
  85        cmd->wCommand = cpu_to_le16(UWB_RC_CMD_STOP_BEACON);
  86        reply.rceb.bEventType = UWB_RC_CET_GENERAL;
  87        reply.rceb.wEvent = UWB_RC_CMD_STOP_BEACON;
  88        result = uwb_rc_cmd(rc, "STOP-BEACON", cmd, sizeof(*cmd),
  89                            &reply.rceb, sizeof(reply));
  90        if (result < 0)
  91                goto error_cmd;
  92        if (reply.bResultCode != UWB_RC_RES_SUCCESS) {
  93                dev_err(&rc->uwb_dev.dev,
  94                        "STOP-BEACON: command execution failed: %s (%d)\n",
  95                        uwb_rc_strerror(reply.bResultCode), reply.bResultCode);
  96                result = -EIO;
  97        }
  98error_cmd:
  99        kfree(cmd);
 100        return result;
 101}
 102
 103/*
 104 * Start/stop beacons
 105 *
 106 * @rc:          UWB Radio Controller to operate on
 107 * @channel:     UWB channel on which to beacon (WUSB[table
 108 *               5-12]). If -1, stop beaconing.
 109 * @bpst_offset: Beacon Period Start Time offset; FIXME-do zero
 110 *
 111 * According to WHCI 0.95 [4.13.6] the driver will only receive the RCEB
 112 * of a SET IE command after the device sent the first beacon that includes
 113 * the IEs specified in the SET IE command. So, after we start beaconing we
 114 * check if there is anything in the IE cache and call the SET IE command
 115 * if needed.
 116 */
 117int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset)
 118{
 119        int result;
 120        struct device *dev = &rc->uwb_dev.dev;
 121
 122        mutex_lock(&rc->uwb_dev.mutex);
 123        if (channel < 0)
 124                channel = -1;
 125        if (channel == -1)
 126                result = uwb_rc_stop_beacon(rc);
 127        else {
 128                /* channel >= 0...dah */
 129                result = uwb_rc_start_beacon(rc, bpst_offset, channel);
 130                if (result < 0)
 131                        goto out_up;
 132                if (le16_to_cpu(rc->ies->wIELength) > 0) {
 133                        result = uwb_rc_set_ie(rc, rc->ies);
 134                        if (result < 0) {
 135                                dev_err(dev, "Cannot set new IE on device: "
 136                                        "%d\n", result);
 137                                result = uwb_rc_stop_beacon(rc);
 138                                channel = -1;
 139                                bpst_offset = 0;
 140                        } else
 141                                result = 0;
 142                }
 143        }
 144
 145        if (result < 0)
 146                goto out_up;
 147        rc->beaconing = channel;
 148
 149        uwb_notify(rc, NULL, uwb_bg_joined(rc) ? UWB_NOTIF_BG_JOIN : UWB_NOTIF_BG_LEAVE);
 150
 151out_up:
 152        mutex_unlock(&rc->uwb_dev.mutex);
 153        return result;
 154}
 155
 156/*
 157 * Beacon cache
 158 *
 159 * The purpose of this is to speed up the lookup of becon information
 160 * when a new beacon arrives. The UWB Daemon uses it also to keep a
 161 * tab of which devices are in radio distance and which not. When a
 162 * device's beacon stays present for more than a certain amount of
 163 * time, it is considered a new, usable device. When a beacon ceases
 164 * to be received for a certain amount of time, it is considered that
 165 * the device is gone.
 166 *
 167 * FIXME: use an allocator for the entries
 168 * FIXME: use something faster for search than a list
 169 */
 170
 171struct uwb_beca uwb_beca = {
 172        .list = LIST_HEAD_INIT(uwb_beca.list),
 173        .mutex = __MUTEX_INITIALIZER(uwb_beca.mutex)
 174};
 175
 176
 177void uwb_bce_kfree(struct kref *_bce)
 178{
 179        struct uwb_beca_e *bce = container_of(_bce, struct uwb_beca_e, refcnt);
 180
 181        kfree(bce->be);
 182        kfree(bce);
 183}
 184
 185
 186/* Find a beacon by dev addr in the cache */
 187static
 188struct uwb_beca_e *__uwb_beca_find_bydev(const struct uwb_dev_addr *dev_addr)
 189{
 190        struct uwb_beca_e *bce, *next;
 191        list_for_each_entry_safe(bce, next, &uwb_beca.list, node) {
 192                d_printf(6, NULL, "looking for addr %02x:%02x in %02x:%02x\n",
 193                         dev_addr->data[0], dev_addr->data[1],
 194                         bce->dev_addr.data[0], bce->dev_addr.data[1]);
 195                if (!memcmp(&bce->dev_addr, dev_addr, sizeof(bce->dev_addr)))
 196                        goto out;
 197        }
 198        bce = NULL;
 199out:
 200        return bce;
 201}
 202
 203/* Find a beacon by dev addr in the cache */
 204static
 205struct uwb_beca_e *__uwb_beca_find_bymac(const struct uwb_mac_addr *mac_addr)
 206{
 207        struct uwb_beca_e *bce, *next;
 208        list_for_each_entry_safe(bce, next, &uwb_beca.list, node) {
 209                if (!memcmp(bce->mac_addr, mac_addr->data,
 210                            sizeof(struct uwb_mac_addr)))
 211                        goto out;
 212        }
 213        bce = NULL;
 214out:
 215        return bce;
 216}
 217
 218/**
 219 * uwb_dev_get_by_devaddr - get a UWB device with a specific DevAddr
 220 * @rc:      the radio controller that saw the device
 221 * @devaddr: DevAddr of the UWB device to find
 222 *
 223 * There may be more than one matching device (in the case of a
 224 * DevAddr conflict), but only the first one is returned.
 225 */
 226struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc,
 227                                       const struct uwb_dev_addr *devaddr)
 228{
 229        struct uwb_dev *found = NULL;
 230        struct uwb_beca_e *bce;
 231
 232        mutex_lock(&uwb_beca.mutex);
 233        bce = __uwb_beca_find_bydev(devaddr);
 234        if (bce)
 235                found = uwb_dev_try_get(rc, bce->uwb_dev);
 236        mutex_unlock(&uwb_beca.mutex);
 237
 238        return found;
 239}
 240
 241/**
 242 * uwb_dev_get_by_macaddr - get a UWB device with a specific EUI-48
 243 * @rc:      the radio controller that saw the device
 244 * @devaddr: EUI-48 of the UWB device to find
 245 */
 246struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc,
 247                                       const struct uwb_mac_addr *macaddr)
 248{
 249        struct uwb_dev *found = NULL;
 250        struct uwb_beca_e *bce;
 251
 252        mutex_lock(&uwb_beca.mutex);
 253        bce = __uwb_beca_find_bymac(macaddr);
 254        if (bce)
 255                found = uwb_dev_try_get(rc, bce->uwb_dev);
 256        mutex_unlock(&uwb_beca.mutex);
 257
 258        return found;
 259}
 260
 261/* Initialize a beacon cache entry */
 262static void uwb_beca_e_init(struct uwb_beca_e *bce)
 263{
 264        mutex_init(&bce->mutex);
 265        kref_init(&bce->refcnt);
 266        stats_init(&bce->lqe_stats);
 267        stats_init(&bce->rssi_stats);
 268}
 269
 270/*
 271 * Add a beacon to the cache
 272 *
 273 * @be:         Beacon event information
 274 * @bf:         Beacon frame (part of b, really)
 275 * @ts_jiffies: Timestamp (in jiffies) when the beacon was received
 276 */
 277struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be,
 278                                  struct uwb_beacon_frame *bf,
 279                                  unsigned long ts_jiffies)
 280{
 281        struct uwb_beca_e *bce;
 282
 283        bce = kzalloc(sizeof(*bce), GFP_KERNEL);
 284        if (bce == NULL)
 285                return NULL;
 286        uwb_beca_e_init(bce);
 287        bce->ts_jiffies = ts_jiffies;
 288        bce->uwb_dev = NULL;
 289        list_add(&bce->node, &uwb_beca.list);
 290        return bce;
 291}
 292
 293/*
 294 * Wipe out beacon entries that became stale
 295 *
 296 * Remove associated devicest too.
 297 */
 298void uwb_beca_purge(void)
 299{
 300        struct uwb_beca_e *bce, *next;
 301        unsigned long expires;
 302
 303        mutex_lock(&uwb_beca.mutex);
 304        list_for_each_entry_safe(bce, next, &uwb_beca.list, node) {
 305                expires = bce->ts_jiffies + msecs_to_jiffies(beacon_timeout_ms);
 306                if (time_after(jiffies, expires)) {
 307                        uwbd_dev_offair(bce);
 308                        list_del(&bce->node);
 309                        uwb_bce_put(bce);
 310                }
 311        }
 312        mutex_unlock(&uwb_beca.mutex);
 313}
 314
 315/* Clean up the whole beacon cache. Called on shutdown */
 316void uwb_beca_release(void)
 317{
 318        struct uwb_beca_e *bce, *next;
 319        mutex_lock(&uwb_beca.mutex);
 320        list_for_each_entry_safe(bce, next, &uwb_beca.list, node) {
 321                list_del(&bce->node);
 322                uwb_bce_put(bce);
 323        }
 324        mutex_unlock(&uwb_beca.mutex);
 325}
 326
 327static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be,
 328                             struct uwb_beacon_frame *bf)
 329{
 330        char macbuf[UWB_ADDR_STRSIZE];
 331        char devbuf[UWB_ADDR_STRSIZE];
 332        char dstbuf[UWB_ADDR_STRSIZE];
 333
 334        uwb_mac_addr_print(macbuf, sizeof(macbuf), &bf->Device_Identifier);
 335        uwb_dev_addr_print(devbuf, sizeof(devbuf), &bf->hdr.SrcAddr);
 336        uwb_dev_addr_print(dstbuf, sizeof(dstbuf), &bf->hdr.DestAddr);
 337        dev_info(&rc->uwb_dev.dev,
 338                 "BEACON from %s to %s (ch%u offset %u slot %u MAC %s)\n",
 339                 devbuf, dstbuf, be->bChannelNumber, be->wBPSTOffset,
 340                 bf->Beacon_Slot_Number, macbuf);
 341}
 342
 343/*
 344 * @bce: beacon cache entry, referenced
 345 */
 346ssize_t uwb_bce_print_IEs(struct uwb_dev *uwb_dev, struct uwb_beca_e *bce,
 347                          char *buf, size_t size)
 348{
 349        ssize_t result = 0;
 350        struct uwb_rc_evt_beacon *be;
 351        struct uwb_beacon_frame *bf;
 352        struct uwb_buf_ctx ctx = {
 353                .buf = buf,
 354                .bytes = 0,
 355                .size = size
 356        };
 357
 358        mutex_lock(&bce->mutex);
 359        be = bce->be;
 360        if (be == NULL)
 361                goto out;
 362        bf = (void *) be->BeaconInfo;
 363        uwb_ie_for_each(uwb_dev, uwb_ie_dump_hex, &ctx,
 364                        bf->IEData, be->wBeaconInfoLength - sizeof(*bf));
 365        result = ctx.bytes;
 366out:
 367        mutex_unlock(&bce->mutex);
 368        return result;
 369}
 370
 371/*
 372 * Verify that the beacon event, frame and IEs are ok
 373 */
 374static int uwb_verify_beacon(struct uwb_rc *rc, struct uwb_event *evt,
 375                             struct uwb_rc_evt_beacon *be)
 376{
 377        int result = -EINVAL;
 378        struct uwb_beacon_frame *bf;
 379        struct device *dev = &rc->uwb_dev.dev;
 380
 381        /* Is there enough data to decode a beacon frame? */
 382        if (evt->notif.size < sizeof(*be) + sizeof(*bf)) {
 383                dev_err(dev, "BEACON event: Not enough data to decode "
 384                        "(%zu vs %zu bytes needed)\n", evt->notif.size,
 385                        sizeof(*be) + sizeof(*bf));
 386                goto error;
 387        }
 388        /* FIXME: make sure beacon frame IEs are fine and that the whole thing
 389         * is consistent */
 390        result = 0;
 391error:
 392        return result;
 393}
 394
 395/*
 396 * Handle UWB_RC_EVT_BEACON events
 397 *
 398 * We check the beacon cache to see how the received beacon fares. If
 399 * is there already we refresh the timestamp. If not we create a new
 400 * entry.
 401 *
 402 * According to the WHCI and WUSB specs, only one beacon frame is
 403 * allowed per notification block, so we don't bother about scanning
 404 * for more.
 405 */
 406int uwbd_evt_handle_rc_beacon(struct uwb_event *evt)
 407{
 408        int result = -EINVAL;
 409        struct uwb_rc *rc;
 410        struct uwb_rc_evt_beacon *be;
 411        struct uwb_beacon_frame *bf;
 412        struct uwb_beca_e *bce;
 413        unsigned long last_ts;
 414
 415        rc = evt->rc;
 416        be = container_of(evt->notif.rceb, struct uwb_rc_evt_beacon, rceb);
 417        result = uwb_verify_beacon(rc, evt, be);
 418        if (result < 0)
 419                return result;
 420
 421        /* FIXME: handle alien beacons. */
 422        if (be->bBeaconType == UWB_RC_BEACON_TYPE_OL_ALIEN ||
 423            be->bBeaconType == UWB_RC_BEACON_TYPE_NOL_ALIEN) {
 424                return -ENOSYS;
 425        }
 426
 427        bf = (struct uwb_beacon_frame *) be->BeaconInfo;
 428
 429        /*
 430         * Drop beacons from devices with a NULL EUI-48 -- they cannot
 431         * be uniquely identified.
 432         *
 433         * It's expected that these will all be WUSB devices and they
 434         * have a WUSB specific connection method so ignoring them
 435         * here shouldn't be a problem.
 436         */
 437        if (uwb_mac_addr_bcast(&bf->Device_Identifier))
 438                return 0;
 439
 440        mutex_lock(&uwb_beca.mutex);
 441        bce = __uwb_beca_find_bymac(&bf->Device_Identifier);
 442        if (bce == NULL) {
 443                /* Not in there, a new device is pinging */
 444                uwb_beacon_print(evt->rc, be, bf);
 445                bce = __uwb_beca_add(be, bf, evt->ts_jiffies);
 446                if (bce == NULL) {
 447                        mutex_unlock(&uwb_beca.mutex);
 448                        return -ENOMEM;
 449                }
 450        }
 451        mutex_unlock(&uwb_beca.mutex);
 452
 453        mutex_lock(&bce->mutex);
 454        /* purge old beacon data */
 455        kfree(bce->be);
 456
 457        last_ts = bce->ts_jiffies;
 458
 459        /* Update commonly used fields */
 460        bce->ts_jiffies = evt->ts_jiffies;
 461        bce->be = be;
 462        bce->dev_addr = bf->hdr.SrcAddr;
 463        bce->mac_addr = &bf->Device_Identifier;
 464        be->wBPSTOffset = le16_to_cpu(be->wBPSTOffset);
 465        be->wBeaconInfoLength = le16_to_cpu(be->wBeaconInfoLength);
 466        stats_add_sample(&bce->lqe_stats, be->bLQI - 7);
 467        stats_add_sample(&bce->rssi_stats, be->bRSSI + 18);
 468
 469        /*
 470         * This might be a beacon from a new device.
 471         */
 472        if (bce->uwb_dev == NULL)
 473                uwbd_dev_onair(evt->rc, bce);
 474
 475        mutex_unlock(&bce->mutex);
 476
 477        return 1; /* we keep the event data */
 478}
 479
 480/*
 481 * Handle UWB_RC_EVT_BEACON_SIZE events
 482 *
 483 * XXXXX
 484 */
 485int uwbd_evt_handle_rc_beacon_size(struct uwb_event *evt)
 486{
 487        int result = -EINVAL;
 488        struct device *dev = &evt->rc->uwb_dev.dev;
 489        struct uwb_rc_evt_beacon_size *bs;
 490
 491        /* Is there enough data to decode the event? */
 492        if (evt->notif.size < sizeof(*bs)) {
 493                dev_err(dev, "BEACON SIZE notification: Not enough data to "
 494                        "decode (%zu vs %zu bytes needed)\n",
 495                        evt->notif.size, sizeof(*bs));
 496                goto error;
 497        }
 498        bs = container_of(evt->notif.rceb, struct uwb_rc_evt_beacon_size, rceb);
 499        if (0)
 500                dev_info(dev, "Beacon size changed to %u bytes "
 501                        "(FIXME: action?)\n", le16_to_cpu(bs->wNewBeaconSize));
 502        else {
 503                /* temporary hack until we do something with this message... */
 504                static unsigned count;
 505                if (++count % 1000 == 0)
 506                        dev_info(dev, "Beacon size changed %u times "
 507                                "(FIXME: action?)\n", count);
 508        }
 509        result = 0;
 510error:
 511        return result;
 512}
 513
 514/**
 515 * uwbd_evt_handle_rc_bp_slot_change - handle a BP_SLOT_CHANGE event
 516 * @evt: the BP_SLOT_CHANGE notification from the radio controller
 517 *
 518 * If the event indicates that no beacon period slots were available
 519 * then radio controller has transitioned to a non-beaconing state.
 520 * Otherwise, simply save the current beacon slot.
 521 */
 522int uwbd_evt_handle_rc_bp_slot_change(struct uwb_event *evt)
 523{
 524        struct uwb_rc *rc = evt->rc;
 525        struct device *dev = &rc->uwb_dev.dev;
 526        struct uwb_rc_evt_bp_slot_change *bpsc;
 527
 528        if (evt->notif.size < sizeof(*bpsc)) {
 529                dev_err(dev, "BP SLOT CHANGE event: Not enough data\n");
 530                return -EINVAL;
 531        }
 532        bpsc = container_of(evt->notif.rceb, struct uwb_rc_evt_bp_slot_change, rceb);
 533
 534        mutex_lock(&rc->uwb_dev.mutex);
 535        if (uwb_rc_evt_bp_slot_change_no_slot(bpsc)) {
 536                dev_info(dev, "stopped beaconing: No free slots in BP\n");
 537                rc->beaconing = -1;
 538        } else
 539                rc->uwb_dev.beacon_slot = uwb_rc_evt_bp_slot_change_slot_num(bpsc);
 540        mutex_unlock(&rc->uwb_dev.mutex);
 541
 542        return 0;
 543}
 544
 545/**
 546 * Handle UWB_RC_EVT_BPOIE_CHANGE events
 547 *
 548 * XXXXX
 549 */
 550struct uwb_ie_bpo {
 551        struct uwb_ie_hdr hdr;
 552        u8                bp_length;
 553        u8                data[];
 554} __attribute__((packed));
 555
 556int uwbd_evt_handle_rc_bpoie_change(struct uwb_event *evt)
 557{
 558        int result = -EINVAL;
 559        struct device *dev = &evt->rc->uwb_dev.dev;
 560        struct uwb_rc_evt_bpoie_change *bpoiec;
 561        struct uwb_ie_bpo *bpoie;
 562        static unsigned count;  /* FIXME: this is a temp hack */
 563        size_t iesize;
 564
 565        /* Is there enough data to decode it? */
 566        if (evt->notif.size < sizeof(*bpoiec)) {
 567                dev_err(dev, "BPOIEC notification: Not enough data to "
 568                        "decode (%zu vs %zu bytes needed)\n",
 569                        evt->notif.size, sizeof(*bpoiec));
 570                goto error;
 571        }
 572        bpoiec = container_of(evt->notif.rceb, struct uwb_rc_evt_bpoie_change, rceb);
 573        iesize = le16_to_cpu(bpoiec->wBPOIELength);
 574        if (iesize < sizeof(*bpoie)) {
 575                dev_err(dev, "BPOIEC notification: Not enough IE data to "
 576                        "decode (%zu vs %zu bytes needed)\n",
 577                        iesize, sizeof(*bpoie));
 578                goto error;
 579        }
 580        if (++count % 1000 == 0)        /* Lame placeholder */
 581                dev_info(dev, "BPOIE: %u changes received\n", count);
 582        /*
 583         * FIXME: At this point we should go over all the IEs in the
 584         *        bpoiec->BPOIE array and act on each.
 585         */
 586        result = 0;
 587error:
 588        return result;
 589}
 590
 591/**
 592 * uwb_bg_joined - is the RC in a beacon group?
 593 * @rc: the radio controller
 594 *
 595 * Returns true if the radio controller is in a beacon group (even if
 596 * it's the sole member).
 597 */
 598int uwb_bg_joined(struct uwb_rc *rc)
 599{
 600        return rc->beaconing != -1;
 601}
 602EXPORT_SYMBOL_GPL(uwb_bg_joined);
 603
 604/*
 605 * Print beaconing state.
 606 */
 607static ssize_t uwb_rc_beacon_show(struct device *dev,
 608                                  struct device_attribute *attr, char *buf)
 609{
 610        struct uwb_dev *uwb_dev = to_uwb_dev(dev);
 611        struct uwb_rc *rc = uwb_dev->rc;
 612        ssize_t result;
 613
 614        mutex_lock(&rc->uwb_dev.mutex);
 615        result = sprintf(buf, "%d\n", rc->beaconing);
 616        mutex_unlock(&rc->uwb_dev.mutex);
 617        return result;
 618}
 619
 620/*
 621 * Start beaconing on the specified channel, or stop beaconing.
 622 *
 623 * The BPST offset of when to start searching for a beacon group to
 624 * join may be specified.
 625 */
 626static ssize_t uwb_rc_beacon_store(struct device *dev,
 627                                   struct device_attribute *attr,
 628                                   const char *buf, size_t size)
 629{
 630        struct uwb_dev *uwb_dev = to_uwb_dev(dev);
 631        struct uwb_rc *rc = uwb_dev->rc;
 632        int channel;
 633        unsigned bpst_offset = 0;
 634        ssize_t result = -EINVAL;
 635
 636        result = sscanf(buf, "%d %u\n", &channel, &bpst_offset);
 637        if (result >= 1)
 638                result = uwb_rc_beacon(rc, channel, bpst_offset);
 639
 640        return result < 0 ? result : size;
 641}
 642DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, uwb_rc_beacon_show, uwb_rc_beacon_store);
 643