Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
address.c
Go to the documentation of this file.
1 /*
2  * Ultra Wide Band
3  * Address management
4  *
5  * Copyright (C) 2005-2006 Intel Corporation
6  * Inaky Perez-Gonzalez <[email protected]>
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 
38  struct uwb_rccb rccb;
40  u8 baAddr[6];
41 } __attribute__((packed));
42 
43 
58 static
59 int 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;
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);
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",
98  reply->bResultCode);
99  result = -EIO;
100  } else
101  result = 0;
102 error_cmd:
103  kfree(cmd);
104 error_kzalloc:
105  return result;
106 }
107 
108 
124 static 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 
162 static 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 */
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 
204  struct uwb_mac_addr *addr) {
205  return uwb_rc_addr_get(rc, addr, UWB_ADDR_MAC);
206 }
208 
209 
212  struct uwb_dev_addr *addr) {
213  return uwb_rc_addr_get(rc, addr, UWB_ADDR_DEV);
214 }
216 
217 
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 
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. */
243 int __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. */
254 int __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 
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 
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  */
308 static 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  */
330 static 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;
355 out:
356  return result < 0 ? result : size;
357 }
358 DEVICE_ATTR(mac_address, S_IRUGO | S_IWUSR, uwb_rc_mac_addr_show, uwb_rc_mac_addr_store);
359 
361 size_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 }