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