linux/drivers/uwb/address.c
<<
>>
Prefs
   1/*
   2 * Ultra Wide Band
   3 * Address 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/slab.h>
  27#include <linux/errno.h>
  28#include <linux/module.h>
  29#include <linux/device.h>
  30#include <linux/random.h>
  31#include <linux/etherdevice.h>
  32
  33#include "uwb-internal.h"
  34
  35
  36/** Device Address Management command */
  37struct uwb_rc_cmd_dev_addr_mgmt {
  38        struct uwb_rccb rccb;
  39        u8 bmOperationType;
  40        u8 baAddr[6];
  41} __attribute__((packed));
  42
  43
  44/**
  45 * Low level command for setting/getting UWB radio's addresses
  46 *
  47 * @hwarc:      HWA Radio Control interface instance
  48 * @bmOperationType:
  49 *              Set/get, MAC/DEV (see WUSB1.0[8.6.2.2])
  50 * @baAddr:     address buffer--assumed to have enough data to hold
  51 *              the address type requested.
  52 * @reply:      Pointer to reply buffer (can be stack allocated)
  53 * @returns:    0 if ok, < 0 errno code on error.
  54 *
  55 * @cmd has to be allocated because USB cannot grok USB or vmalloc
  56 * buffers depending on your combination of host architecture.
  57 */
  58static
  59int uwb_rc_dev_addr_mgmt(struct uwb_rc *rc,
  60                         u8 bmOperationType, const u8 *baAddr,
  61                         struct uwb_rc_evt_dev_addr_mgmt *reply)
  62{
  63        int result;
  64        struct uwb_rc_cmd_dev_addr_mgmt *cmd;
  65
  66        result = -ENOMEM;
  67        cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
  68        if (cmd == NULL)
  69                goto error_kzalloc;
  70        cmd->rccb.bCommandType = UWB_RC_CET_GENERAL;
  71        cmd->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_DEV_ADDR_MGMT);
  72        cmd->bmOperationType = bmOperationType;
  73        if (baAddr) {
  74                size_t size = 0;
  75                switch (bmOperationType >> 1) {
  76                case 0: size = 2; break;
  77                case 1: size = 6; break;
  78                default: BUG();
  79                }
  80                memcpy(cmd->baAddr, baAddr, size);
  81        }
  82        reply->rceb.bEventType = UWB_RC_CET_GENERAL;
  83        reply->rceb.wEvent = UWB_RC_CMD_DEV_ADDR_MGMT;
  84        result = uwb_rc_cmd(rc, "DEV-ADDR-MGMT",
  85                            &cmd->rccb, sizeof(*cmd),
  86                            &reply->rceb, sizeof(*reply));
  87        if (result < 0)
  88                goto error_cmd;
  89        if (result < sizeof(*reply)) {
  90                dev_err(&rc->uwb_dev.dev,
  91                        "DEV-ADDR-MGMT: not enough data replied: "
  92                        "%d vs %zu bytes needed\n", result, sizeof(*reply));
  93                result = -ENOMSG;
  94        } else if (reply->bResultCode != UWB_RC_RES_SUCCESS) {
  95                dev_err(&rc->uwb_dev.dev,
  96                        "DEV-ADDR-MGMT: command execution failed: %s (%d)\n",
  97                        uwb_rc_strerror(reply->bResultCode),
  98                        reply->bResultCode);
  99                result = -EIO;
 100        } else
 101                result = 0;
 102error_cmd:
 103        kfree(cmd);
 104error_kzalloc:
 105        return result;
 106}
 107
 108
 109/**
 110 * Set the UWB RC MAC or device address.
 111 *
 112 * @rc:      UWB Radio Controller
 113 * @_addr:   Pointer to address to write [assumed to be either a
 114 *           'struct uwb_mac_addr *' or a 'struct uwb_dev_addr *'].
 115 * @type:    Type of address to set (UWB_ADDR_DEV or UWB_ADDR_MAC).
 116 * @returns: 0 if ok, < 0 errno code on error.
 117 *
 118 * Some anal retentivity here: even if both 'struct
 119 * uwb_{dev,mac}_addr' have the actual byte array in the same offset
 120 * and I could just pass _addr to hwarc_cmd_dev_addr_mgmt(), I prefer
 121 * to use some syntatic sugar in case someday we decide to change the
 122 * format of the structs. The compiler will optimize it out anyway.
 123 */
 124static int uwb_rc_addr_set(struct uwb_rc *rc,
 125                    const void *_addr, enum uwb_addr_type type)
 126{
 127        int result;
 128        u8 bmOperationType = 0x1;               /* Set address */
 129        const struct uwb_dev_addr *dev_addr = _addr;
 130        const struct uwb_mac_addr *mac_addr = _addr;
 131        struct uwb_rc_evt_dev_addr_mgmt reply;
 132        const u8 *baAddr;
 133
 134        result = -EINVAL;
 135        switch (type) {
 136        case UWB_ADDR_DEV:
 137                baAddr = dev_addr->data;
 138                break;
 139        case UWB_ADDR_MAC:
 140                baAddr = mac_addr->data;
 141                bmOperationType |= 0x2;
 142                break;
 143        default:
 144                return result;
 145        }
 146        return uwb_rc_dev_addr_mgmt(rc, bmOperationType, baAddr, &reply);
 147}
 148
 149
 150/**
 151 * Get the UWB radio's MAC or device address.
 152 *
 153 * @rc:      UWB Radio Controller
 154 * @_addr:   Where to write the address data [assumed to be either a
 155 *           'struct uwb_mac_addr *' or a 'struct uwb_dev_addr *'].
 156 * @type:    Type of address to get (UWB_ADDR_DEV or UWB_ADDR_MAC).
 157 * @returns: 0 if ok (and *_addr set), < 0 errno code on error.
 158 *
 159 * See comment in uwb_rc_addr_set() about anal retentivity in the
 160 * type handling of the address variables.
 161 */
 162static int uwb_rc_addr_get(struct uwb_rc *rc,
 163                    void *_addr, enum uwb_addr_type type)
 164{
 165        int result;
 166        u8 bmOperationType = 0x0;               /* Get address */
 167        struct uwb_rc_evt_dev_addr_mgmt evt;
 168        struct uwb_dev_addr *dev_addr = _addr;
 169        struct uwb_mac_addr *mac_addr = _addr;
 170        u8 *baAddr;
 171
 172        result = -EINVAL;
 173        switch (type) {
 174        case UWB_ADDR_DEV:
 175                baAddr = dev_addr->data;
 176                break;
 177        case UWB_ADDR_MAC:
 178                bmOperationType |= 0x2;
 179                baAddr = mac_addr->data;
 180                break;
 181        default:
 182                return result;
 183        }
 184        result = uwb_rc_dev_addr_mgmt(rc, bmOperationType, baAddr, &evt);
 185        if (result == 0)
 186                switch (type) {
 187                case UWB_ADDR_DEV:
 188                        memcpy(&dev_addr->data, evt.baAddr,
 189                               sizeof(dev_addr->data));
 190                        break;
 191                case UWB_ADDR_MAC:
 192                        memcpy(&mac_addr->data, evt.baAddr,
 193                               sizeof(mac_addr->data));
 194                        break;
 195                default:                /* shut gcc up */
 196                        BUG();
 197                }
 198        return result;
 199}
 200
 201
 202/** Get @rc's MAC address to @addr */
 203int uwb_rc_mac_addr_get(struct uwb_rc *rc,
 204                        struct uwb_mac_addr *addr) {
 205        return uwb_rc_addr_get(rc, addr, UWB_ADDR_MAC);
 206}
 207EXPORT_SYMBOL_GPL(uwb_rc_mac_addr_get);
 208
 209
 210/** Get @rc's device address to @addr */
 211int uwb_rc_dev_addr_get(struct uwb_rc *rc,
 212                        struct uwb_dev_addr *addr) {
 213        return uwb_rc_addr_get(rc, addr, UWB_ADDR_DEV);
 214}
 215EXPORT_SYMBOL_GPL(uwb_rc_dev_addr_get);
 216
 217
 218/** Set @rc's address to @addr */
 219int uwb_rc_mac_addr_set(struct uwb_rc *rc,
 220                        const struct uwb_mac_addr *addr)
 221{
 222        int result = -EINVAL;
 223        mutex_lock(&rc->uwb_dev.mutex);
 224        result = uwb_rc_addr_set(rc, addr, UWB_ADDR_MAC);
 225        mutex_unlock(&rc->uwb_dev.mutex);
 226        return result;
 227}
 228
 229
 230/** Set @rc's address to @addr */
 231int uwb_rc_dev_addr_set(struct uwb_rc *rc,
 232                        const struct uwb_dev_addr *addr)
 233{
 234        int result = -EINVAL;
 235        mutex_lock(&rc->uwb_dev.mutex);
 236        result = uwb_rc_addr_set(rc, addr, UWB_ADDR_DEV);
 237        rc->uwb_dev.dev_addr = *addr;
 238        mutex_unlock(&rc->uwb_dev.mutex);
 239        return result;
 240}
 241
 242/* Returns !0 if given address is already assigned to device. */
 243int __uwb_mac_addr_assigned_check(struct device *dev, void *_addr)
 244{
 245        struct uwb_dev *uwb_dev = to_uwb_dev(dev);
 246        struct uwb_mac_addr *addr = _addr;
 247
 248        if (!uwb_mac_addr_cmp(addr, &uwb_dev->mac_addr))
 249                return !0;
 250        return 0;
 251}
 252
 253/* Returns !0 if given address is already assigned to device. */
 254int __uwb_dev_addr_assigned_check(struct device *dev, void *_addr)
 255{
 256        struct uwb_dev *uwb_dev = to_uwb_dev(dev);
 257        struct uwb_dev_addr *addr = _addr;
 258        if (!uwb_dev_addr_cmp(addr, &uwb_dev->dev_addr))
 259                return !0;
 260        return 0;
 261}
 262
 263/**
 264 * uwb_dev_addr_assign - assigned a generated DevAddr to a radio controller
 265 * @rc:      the (local) radio controller device requiring a new DevAddr
 266 *
 267 * A new DevAddr is required when:
 268 *    - first setting up a radio controller
 269 *    - if the hardware reports a DevAddr conflict
 270 *
 271 * The DevAddr is randomly generated in the generated DevAddr range
 272 * [0x100, 0xfeff]. The number of devices in a beacon group is limited
 273 * by mMaxBPLength (96) so this address space will never be exhausted.
 274 *
 275 * [ECMA-368] 17.1.1, 17.16.
 276 */
 277int uwb_rc_dev_addr_assign(struct uwb_rc *rc)
 278{
 279        struct uwb_dev_addr new_addr;
 280
 281        do {
 282                get_random_bytes(new_addr.data, sizeof(new_addr.data));
 283        } while (new_addr.data[0] == 0x00 || new_addr.data[0] == 0xff
 284                 || __uwb_dev_addr_assigned(rc, &new_addr));
 285
 286        return uwb_rc_dev_addr_set(rc, &new_addr);
 287}
 288
 289/**
 290 * uwbd_evt_handle_rc_dev_addr_conflict - handle a DEV_ADDR_CONFLICT event
 291 * @evt: the DEV_ADDR_CONFLICT notification from the radio controller
 292 *
 293 * A new (non-conflicting) DevAddr is assigned to the radio controller.
 294 *
 295 * [ECMA-368] 17.1.1.1.
 296 */
 297int uwbd_evt_handle_rc_dev_addr_conflict(struct uwb_event *evt)
 298{
 299        struct uwb_rc *rc = evt->rc;
 300
 301        return uwb_rc_dev_addr_assign(rc);
 302}
 303
 304/*
 305 * Print the 48-bit EUI MAC address of the radio controller when
 306 * reading /sys/class/uwb_rc/XX/mac_address
 307 */
 308static ssize_t uwb_rc_mac_addr_show(struct device *dev,
 309                                    struct device_attribute *attr, char *buf)
 310{
 311        struct uwb_dev *uwb_dev = to_uwb_dev(dev);
 312        struct uwb_rc *rc = uwb_dev->rc;
 313        struct uwb_mac_addr addr;
 314        ssize_t result;
 315
 316        mutex_lock(&rc->uwb_dev.mutex);
 317        result = uwb_rc_addr_get(rc, &addr, UWB_ADDR_MAC);
 318        mutex_unlock(&rc->uwb_dev.mutex);
 319        if (result >= 0) {
 320                result = uwb_mac_addr_print(buf, UWB_ADDR_STRSIZE, &addr);
 321                buf[result++] = '\n';
 322        }
 323        return result;
 324}
 325
 326/*
 327 * Parse a 48 bit address written to /sys/class/uwb_rc/XX/mac_address
 328 * and if correct, set it.
 329 */
 330static ssize_t uwb_rc_mac_addr_store(struct device *dev,
 331                                     struct device_attribute *attr,
 332                                     const char *buf, size_t size)
 333{
 334        struct uwb_dev *uwb_dev = to_uwb_dev(dev);
 335        struct uwb_rc *rc = uwb_dev->rc;
 336        struct uwb_mac_addr addr;
 337        ssize_t result;
 338
 339        result = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\n",
 340                        &addr.data[0], &addr.data[1], &addr.data[2],
 341                        &addr.data[3], &addr.data[4], &addr.data[5]);
 342        if (result != 6) {
 343                result = -EINVAL;
 344                goto out;
 345        }
 346        if (is_multicast_ether_addr(addr.data)) {
 347                dev_err(&rc->uwb_dev.dev, "refusing to set multicast "
 348                        "MAC address %s\n", buf);
 349                result = -EINVAL;
 350                goto out;
 351        }
 352        result = uwb_rc_mac_addr_set(rc, &addr);
 353        if (result == 0)
 354                rc->uwb_dev.mac_addr = addr;
 355out:
 356        return result < 0 ? result : size;
 357}
 358DEVICE_ATTR(mac_address, S_IRUGO | S_IWUSR, uwb_rc_mac_addr_show, uwb_rc_mac_addr_store);
 359
 360/** Print @addr to @buf, @return bytes written */
 361size_t __uwb_addr_print(char *buf, size_t buf_size, const unsigned char *addr,
 362                        int type)
 363{
 364        size_t result;
 365        if (type)
 366                result = scnprintf(buf, buf_size, "%pM", addr);
 367        else
 368                result = scnprintf(buf, buf_size, "%02x:%02x",
 369                                  addr[1], addr[0]);
 370        return result;
 371}
 372EXPORT_SYMBOL_GPL(__uwb_addr_print);
 373
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.