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

uwb: add the uwb include files

Signed-off-by: David Vrabel <david.vrabel@csr.com>

authored by

Inaky Perez-Gonzalez and committed by
David Vrabel
34e95e41 99d368bc

+2362
+761
include/linux/uwb.h
··· 1 + /* 2 + * Ultra Wide Band 3 + * UWB API 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: doc: overview of the API, different parts and pointers 24 + */ 25 + 26 + #ifndef __LINUX__UWB_H__ 27 + #define __LINUX__UWB_H__ 28 + 29 + #include <linux/limits.h> 30 + #include <linux/device.h> 31 + #include <linux/mutex.h> 32 + #include <linux/timer.h> 33 + #include <linux/workqueue.h> 34 + #include <linux/uwb/spec.h> 35 + 36 + struct uwb_dev; 37 + struct uwb_beca_e; 38 + struct uwb_rc; 39 + struct uwb_rsv; 40 + struct uwb_dbg; 41 + 42 + /** 43 + * struct uwb_dev - a UWB Device 44 + * @rc: UWB Radio Controller that discovered the device (kind of its 45 + * parent). 46 + * @bce: a beacon cache entry for this device; or NULL if the device 47 + * is a local radio controller. 48 + * @mac_addr: the EUI-48 address of this device. 49 + * @dev_addr: the current DevAddr used by this device. 50 + * @beacon_slot: the slot number the beacon is using. 51 + * @streams: bitmap of streams allocated to reservations targeted at 52 + * this device. For an RC, this is the streams allocated for 53 + * reservations targeted at DevAddrs. 54 + * 55 + * A UWB device may either by a neighbor or part of a local radio 56 + * controller. 57 + */ 58 + struct uwb_dev { 59 + struct mutex mutex; 60 + struct list_head list_node; 61 + struct device dev; 62 + struct uwb_rc *rc; /* radio controller */ 63 + struct uwb_beca_e *bce; /* Beacon Cache Entry */ 64 + 65 + struct uwb_mac_addr mac_addr; 66 + struct uwb_dev_addr dev_addr; 67 + int beacon_slot; 68 + DECLARE_BITMAP(streams, UWB_NUM_STREAMS); 69 + }; 70 + #define to_uwb_dev(d) container_of(d, struct uwb_dev, dev) 71 + 72 + /** 73 + * UWB HWA/WHCI Radio Control {Command|Event} Block context IDs 74 + * 75 + * RC[CE]Bs have a 'context ID' field that matches the command with 76 + * the event received to confirm it. 77 + * 78 + * Maximum number of context IDs 79 + */ 80 + enum { UWB_RC_CTX_MAX = 256 }; 81 + 82 + 83 + /** Notification chain head for UWB generated events to listeners */ 84 + struct uwb_notifs_chain { 85 + struct list_head list; 86 + struct mutex mutex; 87 + }; 88 + 89 + /** 90 + * struct uwb_mas_bm - a bitmap of all MAS in a superframe 91 + * @bm: a bitmap of length #UWB_NUM_MAS 92 + */ 93 + struct uwb_mas_bm { 94 + DECLARE_BITMAP(bm, UWB_NUM_MAS); 95 + }; 96 + 97 + /** 98 + * uwb_rsv_state - UWB Reservation state. 99 + * 100 + * NONE - reservation is not active (no DRP IE being transmitted). 101 + * 102 + * Owner reservation states: 103 + * 104 + * INITIATED - owner has sent an initial DRP request. 105 + * PENDING - target responded with pending Reason Code. 106 + * MODIFIED - reservation manager is modifying an established 107 + * reservation with a different MAS allocation. 108 + * ESTABLISHED - the reservation has been successfully negotiated. 109 + * 110 + * Target reservation states: 111 + * 112 + * DENIED - request is denied. 113 + * ACCEPTED - request is accepted. 114 + * PENDING - PAL has yet to make a decision to whether to accept or 115 + * deny. 116 + * 117 + * FIXME: further target states TBD. 118 + */ 119 + enum uwb_rsv_state { 120 + UWB_RSV_STATE_NONE, 121 + UWB_RSV_STATE_O_INITIATED, 122 + UWB_RSV_STATE_O_PENDING, 123 + UWB_RSV_STATE_O_MODIFIED, 124 + UWB_RSV_STATE_O_ESTABLISHED, 125 + UWB_RSV_STATE_T_ACCEPTED, 126 + UWB_RSV_STATE_T_DENIED, 127 + UWB_RSV_STATE_T_PENDING, 128 + 129 + UWB_RSV_STATE_LAST, 130 + }; 131 + 132 + enum uwb_rsv_target_type { 133 + UWB_RSV_TARGET_DEV, 134 + UWB_RSV_TARGET_DEVADDR, 135 + }; 136 + 137 + /** 138 + * struct uwb_rsv_target - the target of a reservation. 139 + * 140 + * Reservations unicast and targeted at a single device 141 + * (UWB_RSV_TARGET_DEV); or (e.g., in the case of WUSB) targeted at a 142 + * specific (private) DevAddr (UWB_RSV_TARGET_DEVADDR). 143 + */ 144 + struct uwb_rsv_target { 145 + enum uwb_rsv_target_type type; 146 + union { 147 + struct uwb_dev *dev; 148 + struct uwb_dev_addr devaddr; 149 + }; 150 + }; 151 + 152 + /* 153 + * Number of streams reserved for reservations targeted at DevAddrs. 154 + */ 155 + #define UWB_NUM_GLOBAL_STREAMS 1 156 + 157 + typedef void (*uwb_rsv_cb_f)(struct uwb_rsv *rsv); 158 + 159 + /** 160 + * struct uwb_rsv - a DRP reservation 161 + * 162 + * Data structure management: 163 + * 164 + * @rc: the radio controller this reservation is for 165 + * (as target or owner) 166 + * @rc_node: a list node for the RC 167 + * @pal_node: a list node for the PAL 168 + * 169 + * Owner and target parameters: 170 + * 171 + * @owner: the UWB device owning this reservation 172 + * @target: the target UWB device 173 + * @type: reservation type 174 + * 175 + * Owner parameters: 176 + * 177 + * @max_mas: maxiumum number of MAS 178 + * @min_mas: minimum number of MAS 179 + * @sparsity: owner selected sparsity 180 + * @is_multicast: true iff multicast 181 + * 182 + * @callback: callback function when the reservation completes 183 + * @pal_priv: private data for the PAL making the reservation 184 + * 185 + * Reservation status: 186 + * 187 + * @status: negotiation status 188 + * @stream: stream index allocated for this reservation 189 + * @mas: reserved MAS 190 + * @drp_ie: the DRP IE 191 + * @ie_valid: true iff the DRP IE matches the reservation parameters 192 + * 193 + * DRP reservations are uniquely identified by the owner, target and 194 + * stream index. However, when using a DevAddr as a target (e.g., for 195 + * a WUSB cluster reservation) the responses may be received from 196 + * devices with different DevAddrs. In this case, reservations are 197 + * uniquely identified by just the stream index. A number of stream 198 + * indexes (UWB_NUM_GLOBAL_STREAMS) are reserved for this. 199 + */ 200 + struct uwb_rsv { 201 + struct uwb_rc *rc; 202 + struct list_head rc_node; 203 + struct list_head pal_node; 204 + 205 + struct uwb_dev *owner; 206 + struct uwb_rsv_target target; 207 + enum uwb_drp_type type; 208 + int max_mas; 209 + int min_mas; 210 + int sparsity; 211 + bool is_multicast; 212 + 213 + uwb_rsv_cb_f callback; 214 + void *pal_priv; 215 + 216 + enum uwb_rsv_state state; 217 + u8 stream; 218 + struct uwb_mas_bm mas; 219 + struct uwb_ie_drp *drp_ie; 220 + bool ie_valid; 221 + struct timer_list timer; 222 + bool expired; 223 + }; 224 + 225 + static const 226 + struct uwb_mas_bm uwb_mas_bm_zero = { .bm = { 0 } }; 227 + 228 + static inline void uwb_mas_bm_copy_le(void *dst, const struct uwb_mas_bm *mas) 229 + { 230 + bitmap_copy_le(dst, mas->bm, UWB_NUM_MAS); 231 + } 232 + 233 + /** 234 + * struct uwb_drp_avail - a radio controller's view of MAS usage 235 + * @global: MAS unused by neighbors (excluding reservations targetted 236 + * or owned by the local radio controller) or the beaon period 237 + * @local: MAS unused by local established reservations 238 + * @pending: MAS unused by local pending reservations 239 + * @ie: DRP Availability IE to be included in the beacon 240 + * @ie_valid: true iff @ie is valid and does not need to regenerated from 241 + * @global and @local 242 + * 243 + * Each radio controller maintains a view of MAS usage or 244 + * availability. MAS available for a new reservation are determined 245 + * from the intersection of @global, @local, and @pending. 246 + * 247 + * The radio controller must transmit a DRP Availability IE that's the 248 + * intersection of @global and @local. 249 + * 250 + * A set bit indicates the MAS is unused and available. 251 + * 252 + * rc->rsvs_mutex should be held before accessing this data structure. 253 + * 254 + * [ECMA-368] section 17.4.3. 255 + */ 256 + struct uwb_drp_avail { 257 + DECLARE_BITMAP(global, UWB_NUM_MAS); 258 + DECLARE_BITMAP(local, UWB_NUM_MAS); 259 + DECLARE_BITMAP(pending, UWB_NUM_MAS); 260 + struct uwb_ie_drp_avail ie; 261 + bool ie_valid; 262 + }; 263 + 264 + 265 + const char *uwb_rsv_state_str(enum uwb_rsv_state state); 266 + const char *uwb_rsv_type_str(enum uwb_drp_type type); 267 + 268 + struct uwb_rsv *uwb_rsv_create(struct uwb_rc *rc, uwb_rsv_cb_f cb, 269 + void *pal_priv); 270 + void uwb_rsv_destroy(struct uwb_rsv *rsv); 271 + 272 + int uwb_rsv_establish(struct uwb_rsv *rsv); 273 + int uwb_rsv_modify(struct uwb_rsv *rsv, 274 + int max_mas, int min_mas, int sparsity); 275 + void uwb_rsv_terminate(struct uwb_rsv *rsv); 276 + 277 + void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv); 278 + 279 + /** 280 + * Radio Control Interface instance 281 + * 282 + * 283 + * Life cycle rules: those of the UWB Device. 284 + * 285 + * @index: an index number for this radio controller, as used in the 286 + * device name. 287 + * @version: version of protocol supported by this device 288 + * @priv: Backend implementation; rw with uwb_dev.dev.sem taken. 289 + * @cmd: Backend implementation to execute commands; rw and call 290 + * only with uwb_dev.dev.sem taken. 291 + * @reset: Hardware reset of radio controller and any PAL controllers. 292 + * @filter: Backend implementation to manipulate data to and from device 293 + * to be compliant to specification assumed by driver (WHCI 294 + * 0.95). 295 + * 296 + * uwb_dev.dev.mutex is used to execute commands and update 297 + * the corresponding structures; can't use a spinlock 298 + * because rc->cmd() can sleep. 299 + * @ies: This is a dynamically allocated array cacheing the 300 + * IEs (settable by the host) that the beacon of this 301 + * radio controller is currently sending. 302 + * 303 + * In reality, we store here the full command we set to 304 + * the radio controller (which is basically a command 305 + * prefix followed by all the IEs the beacon currently 306 + * contains). This way we don't have to realloc and 307 + * memcpy when setting it. 308 + * 309 + * We set this up in uwb_rc_ie_setup(), where we alloc 310 + * this struct, call get_ie() [so we know which IEs are 311 + * currently being sent, if any]. 312 + * 313 + * @ies_capacity:Amount of space (in bytes) allocated in @ies. The 314 + * amount used is given by sizeof(*ies) plus ies->wIELength 315 + * (which is a little endian quantity all the time). 316 + * @ies_mutex: protect the IE cache 317 + * @dbg: information for the debug interface 318 + */ 319 + struct uwb_rc { 320 + struct uwb_dev uwb_dev; 321 + int index; 322 + u16 version; 323 + 324 + struct module *owner; 325 + void *priv; 326 + int (*start)(struct uwb_rc *rc); 327 + void (*stop)(struct uwb_rc *rc); 328 + int (*cmd)(struct uwb_rc *, const struct uwb_rccb *, size_t); 329 + int (*reset)(struct uwb_rc *rc); 330 + int (*filter_cmd)(struct uwb_rc *, struct uwb_rccb **, size_t *); 331 + int (*filter_event)(struct uwb_rc *, struct uwb_rceb **, const size_t, 332 + size_t *, size_t *); 333 + 334 + spinlock_t neh_lock; /* protects neh_* and ctx_* */ 335 + struct list_head neh_list; /* Open NE handles */ 336 + unsigned long ctx_bm[UWB_RC_CTX_MAX / 8 / sizeof(unsigned long)]; 337 + u8 ctx_roll; 338 + 339 + int beaconing; /* Beaconing state [channel number] */ 340 + int scanning; 341 + enum uwb_scan_type scan_type:3; 342 + unsigned ready:1; 343 + struct uwb_notifs_chain notifs_chain; 344 + 345 + struct uwb_drp_avail drp_avail; 346 + struct list_head reservations; 347 + struct mutex rsvs_mutex; 348 + struct workqueue_struct *rsv_workq; 349 + struct work_struct rsv_update_work; 350 + 351 + struct mutex ies_mutex; 352 + struct uwb_rc_cmd_set_ie *ies; 353 + size_t ies_capacity; 354 + 355 + spinlock_t pal_lock; 356 + struct list_head pals; 357 + 358 + struct uwb_dbg *dbg; 359 + }; 360 + 361 + 362 + /** 363 + * struct uwb_pal - a UWB PAL 364 + * @new_rsv: called when a peer requests a reservation (may be NULL if 365 + * the PAL cannot accept reservation requests). 366 + * 367 + * A Protocol Adaptation Layer (PAL) is a user of the WiMedia UWB 368 + * radio platform (e.g., WUSB, WLP or Bluetooth UWB AMP). 369 + * 370 + * The PALs using a radio controller must register themselves to 371 + * permit the UWB stack to coordinate usage of the radio between the 372 + * various PALs or to allow PALs to response to certain requests from 373 + * peers. 374 + * 375 + * A struct uwb_pal should be embedded in a containing structure 376 + * belonging to the PAL and initialized with uwb_pal_init()). Fields 377 + * should be set appropriately by the PAL before registering the PAL 378 + * with uwb_pal_register(). 379 + */ 380 + struct uwb_pal { 381 + struct list_head node; 382 + 383 + void (*new_rsv)(struct uwb_rsv *rsv); 384 + }; 385 + 386 + void uwb_pal_init(struct uwb_pal *pal); 387 + int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal); 388 + void uwb_pal_unregister(struct uwb_rc *rc, struct uwb_pal *pal); 389 + 390 + /* 391 + * General public API 392 + * 393 + * This API can be used by UWB device drivers or by those implementing 394 + * UWB Radio Controllers 395 + */ 396 + struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, 397 + const struct uwb_dev_addr *devaddr); 398 + struct uwb_dev *uwb_dev_get_by_rc(struct uwb_dev *, struct uwb_rc *); 399 + static inline void uwb_dev_get(struct uwb_dev *uwb_dev) 400 + { 401 + get_device(&uwb_dev->dev); 402 + } 403 + static inline void uwb_dev_put(struct uwb_dev *uwb_dev) 404 + { 405 + put_device(&uwb_dev->dev); 406 + } 407 + struct uwb_dev *uwb_dev_try_get(struct uwb_rc *rc, struct uwb_dev *uwb_dev); 408 + 409 + /** 410 + * Callback function for 'uwb_{dev,rc}_foreach()'. 411 + * 412 + * @dev: Linux device instance 413 + * 'uwb_dev = container_of(dev, struct uwb_dev, dev)' 414 + * @priv: Data passed by the caller to 'uwb_{dev,rc}_foreach()'. 415 + * 416 + * @returns: 0 to continue the iterations, any other val to stop 417 + * iterating and return the value to the caller of 418 + * _foreach(). 419 + */ 420 + typedef int (*uwb_dev_for_each_f)(struct device *dev, void *priv); 421 + int uwb_dev_for_each(struct uwb_rc *rc, uwb_dev_for_each_f func, void *priv); 422 + 423 + struct uwb_rc *uwb_rc_alloc(void); 424 + struct uwb_rc *uwb_rc_get_by_dev(const struct uwb_dev_addr *); 425 + struct uwb_rc *uwb_rc_get_by_grandpa(const struct device *); 426 + void uwb_rc_put(struct uwb_rc *rc); 427 + 428 + typedef void (*uwb_rc_cmd_cb_f)(struct uwb_rc *rc, void *arg, 429 + struct uwb_rceb *reply, ssize_t reply_size); 430 + 431 + int uwb_rc_cmd_async(struct uwb_rc *rc, const char *cmd_name, 432 + struct uwb_rccb *cmd, size_t cmd_size, 433 + u8 expected_type, u16 expected_event, 434 + uwb_rc_cmd_cb_f cb, void *arg); 435 + ssize_t uwb_rc_cmd(struct uwb_rc *rc, const char *cmd_name, 436 + struct uwb_rccb *cmd, size_t cmd_size, 437 + struct uwb_rceb *reply, size_t reply_size); 438 + ssize_t uwb_rc_vcmd(struct uwb_rc *rc, const char *cmd_name, 439 + struct uwb_rccb *cmd, size_t cmd_size, 440 + u8 expected_type, u16 expected_event, 441 + struct uwb_rceb **preply); 442 + ssize_t uwb_rc_get_ie(struct uwb_rc *, struct uwb_rc_evt_get_ie **); 443 + int uwb_bg_joined(struct uwb_rc *rc); 444 + 445 + size_t __uwb_addr_print(char *, size_t, const unsigned char *, int); 446 + 447 + int uwb_rc_dev_addr_set(struct uwb_rc *, const struct uwb_dev_addr *); 448 + int uwb_rc_dev_addr_get(struct uwb_rc *, struct uwb_dev_addr *); 449 + int uwb_rc_mac_addr_set(struct uwb_rc *, const struct uwb_mac_addr *); 450 + int uwb_rc_mac_addr_get(struct uwb_rc *, struct uwb_mac_addr *); 451 + int __uwb_mac_addr_assigned_check(struct device *, void *); 452 + int __uwb_dev_addr_assigned_check(struct device *, void *); 453 + 454 + /* Print in @buf a pretty repr of @addr */ 455 + static inline size_t uwb_dev_addr_print(char *buf, size_t buf_size, 456 + const struct uwb_dev_addr *addr) 457 + { 458 + return __uwb_addr_print(buf, buf_size, addr->data, 0); 459 + } 460 + 461 + /* Print in @buf a pretty repr of @addr */ 462 + static inline size_t uwb_mac_addr_print(char *buf, size_t buf_size, 463 + const struct uwb_mac_addr *addr) 464 + { 465 + return __uwb_addr_print(buf, buf_size, addr->data, 1); 466 + } 467 + 468 + /* @returns 0 if device addresses @addr2 and @addr1 are equal */ 469 + static inline int uwb_dev_addr_cmp(const struct uwb_dev_addr *addr1, 470 + const struct uwb_dev_addr *addr2) 471 + { 472 + return memcmp(addr1, addr2, sizeof(*addr1)); 473 + } 474 + 475 + /* @returns 0 if MAC addresses @addr2 and @addr1 are equal */ 476 + static inline int uwb_mac_addr_cmp(const struct uwb_mac_addr *addr1, 477 + const struct uwb_mac_addr *addr2) 478 + { 479 + return memcmp(addr1, addr2, sizeof(*addr1)); 480 + } 481 + 482 + /* @returns !0 if a MAC @addr is a broadcast address */ 483 + static inline int uwb_mac_addr_bcast(const struct uwb_mac_addr *addr) 484 + { 485 + struct uwb_mac_addr bcast = { 486 + .data = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } 487 + }; 488 + return !uwb_mac_addr_cmp(addr, &bcast); 489 + } 490 + 491 + /* @returns !0 if a MAC @addr is all zeroes*/ 492 + static inline int uwb_mac_addr_unset(const struct uwb_mac_addr *addr) 493 + { 494 + struct uwb_mac_addr unset = { 495 + .data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } 496 + }; 497 + return !uwb_mac_addr_cmp(addr, &unset); 498 + } 499 + 500 + /* @returns !0 if the address is in use. */ 501 + static inline unsigned __uwb_dev_addr_assigned(struct uwb_rc *rc, 502 + struct uwb_dev_addr *addr) 503 + { 504 + return uwb_dev_for_each(rc, __uwb_dev_addr_assigned_check, addr); 505 + } 506 + 507 + /* 508 + * UWB Radio Controller API 509 + * 510 + * This API is used (in addition to the general API) to implement UWB 511 + * Radio Controllers. 512 + */ 513 + void uwb_rc_init(struct uwb_rc *); 514 + int uwb_rc_add(struct uwb_rc *, struct device *dev, void *rc_priv); 515 + void uwb_rc_rm(struct uwb_rc *); 516 + void uwb_rc_neh_grok(struct uwb_rc *, void *, size_t); 517 + void uwb_rc_neh_error(struct uwb_rc *, int); 518 + void uwb_rc_reset_all(struct uwb_rc *rc); 519 + 520 + /** 521 + * uwb_rsv_is_owner - is the owner of this reservation the RC? 522 + * @rsv: the reservation 523 + */ 524 + static inline bool uwb_rsv_is_owner(struct uwb_rsv *rsv) 525 + { 526 + return rsv->owner == &rsv->rc->uwb_dev; 527 + } 528 + 529 + /** 530 + * Events generated by UWB that can be passed to any listeners 531 + * 532 + * Higher layers can register callback functions with the radio 533 + * controller using uwb_notifs_register(). The radio controller 534 + * maintains a list of all registered handlers and will notify all 535 + * nodes when an event occurs. 536 + */ 537 + enum uwb_notifs { 538 + UWB_NOTIF_BG_JOIN = 0, /* radio controller joined a beacon group */ 539 + UWB_NOTIF_BG_LEAVE = 1, /* radio controller left a beacon group */ 540 + UWB_NOTIF_ONAIR, 541 + UWB_NOTIF_OFFAIR, 542 + }; 543 + 544 + /* Callback function registered with UWB */ 545 + struct uwb_notifs_handler { 546 + struct list_head list_node; 547 + void (*cb)(void *, struct uwb_dev *, enum uwb_notifs); 548 + void *data; 549 + }; 550 + 551 + int uwb_notifs_register(struct uwb_rc *, struct uwb_notifs_handler *); 552 + int uwb_notifs_deregister(struct uwb_rc *, struct uwb_notifs_handler *); 553 + 554 + 555 + /** 556 + * UWB radio controller Event Size Entry (for creating entry tables) 557 + * 558 + * WUSB and WHCI define events and notifications, and they might have 559 + * fixed or variable size. 560 + * 561 + * Each event/notification has a size which is not necessarily known 562 + * in advance based on the event code. As well, vendor specific 563 + * events/notifications will have a size impossible to determine 564 + * unless we know about the device's specific details. 565 + * 566 + * It was way too smart of the spec writers not to think that it would 567 + * be impossible for a generic driver to skip over vendor specific 568 + * events/notifications if there are no LENGTH fields in the HEADER of 569 + * each message...the transaction size cannot be counted on as the 570 + * spec does not forbid to pack more than one event in a single 571 + * transaction. 572 + * 573 + * Thus, we guess sizes with tables (or for events, when you know the 574 + * size ahead of time you can use uwb_rc_neh_extra_size*()). We 575 + * register tables with the known events and their sizes, and then we 576 + * traverse those tables. For those with variable length, we provide a 577 + * way to lookup the size inside the event/notification's 578 + * payload. This allows device-specific event size tables to be 579 + * registered. 580 + * 581 + * @size: Size of the payload 582 + * 583 + * @offset: if != 0, at offset @offset-1 starts a field with a length 584 + * that has to be added to @size. The format of the field is 585 + * given by @type. 586 + * 587 + * @type: Type and length of the offset field. Most common is LE 16 588 + * bits (that's why that is zero); others are there mostly to 589 + * cover for bugs and weirdos. 590 + */ 591 + struct uwb_est_entry { 592 + size_t size; 593 + unsigned offset; 594 + enum { UWB_EST_16 = 0, UWB_EST_8 = 1 } type; 595 + }; 596 + 597 + int uwb_est_register(u8 type, u8 code_high, u16 vendor, u16 product, 598 + const struct uwb_est_entry *, size_t entries); 599 + int uwb_est_unregister(u8 type, u8 code_high, u16 vendor, u16 product, 600 + const struct uwb_est_entry *, size_t entries); 601 + ssize_t uwb_est_find_size(struct uwb_rc *rc, const struct uwb_rceb *rceb, 602 + size_t len); 603 + 604 + /* -- Misc */ 605 + 606 + enum { 607 + EDC_MAX_ERRORS = 10, 608 + EDC_ERROR_TIMEFRAME = HZ, 609 + }; 610 + 611 + /* error density counter */ 612 + struct edc { 613 + unsigned long timestart; 614 + u16 errorcount; 615 + }; 616 + 617 + static inline 618 + void edc_init(struct edc *edc) 619 + { 620 + edc->timestart = jiffies; 621 + } 622 + 623 + /* Called when an error occured. 624 + * This is way to determine if the number of acceptable errors per time 625 + * period has been exceeded. It is not accurate as there are cases in which 626 + * this scheme will not work, for example if there are periodic occurences 627 + * of errors that straddle updates to the start time. This scheme is 628 + * sufficient for our usage. 629 + * 630 + * @returns 1 if maximum acceptable errors per timeframe has been exceeded. 631 + */ 632 + static inline int edc_inc(struct edc *err_hist, u16 max_err, u16 timeframe) 633 + { 634 + unsigned long now; 635 + 636 + now = jiffies; 637 + if (now - err_hist->timestart > timeframe) { 638 + err_hist->errorcount = 1; 639 + err_hist->timestart = now; 640 + } else if (++err_hist->errorcount > max_err) { 641 + err_hist->errorcount = 0; 642 + err_hist->timestart = now; 643 + return 1; 644 + } 645 + return 0; 646 + } 647 + 648 + 649 + /* Information Element handling */ 650 + 651 + /* For representing the state of writing to a buffer when iterating */ 652 + struct uwb_buf_ctx { 653 + char *buf; 654 + size_t bytes, size; 655 + }; 656 + 657 + typedef int (*uwb_ie_f)(struct uwb_dev *, const struct uwb_ie_hdr *, 658 + size_t, void *); 659 + struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len); 660 + ssize_t uwb_ie_for_each(struct uwb_dev *uwb_dev, uwb_ie_f fn, void *data, 661 + const void *buf, size_t size); 662 + int uwb_ie_dump_hex(struct uwb_dev *, const struct uwb_ie_hdr *, 663 + size_t, void *); 664 + int uwb_rc_set_ie(struct uwb_rc *, struct uwb_rc_cmd_set_ie *); 665 + struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len); 666 + 667 + 668 + /* 669 + * Transmission statistics 670 + * 671 + * UWB uses LQI and RSSI (one byte values) for reporting radio signal 672 + * strength and line quality indication. We do quick and dirty 673 + * averages of those. They are signed values, btw. 674 + * 675 + * For 8 bit quantities, we keep the min, the max, an accumulator 676 + * (@sigma) and a # of samples. When @samples gets to 255, we compute 677 + * the average (@sigma / @samples), place it in @sigma and reset 678 + * @samples to 1 (so we use it as the first sample). 679 + * 680 + * Now, statistically speaking, probably I am kicking the kidneys of 681 + * some books I have in my shelves collecting dust, but I just want to 682 + * get an approx, not the Nobel. 683 + * 684 + * LOCKING: there is no locking per se, but we try to keep a lockless 685 + * schema. Only _add_samples() modifies the values--as long as you 686 + * have other locking on top that makes sure that no two calls of 687 + * _add_sample() happen at the same time, then we are fine. Now, for 688 + * resetting the values we just set @samples to 0 and that makes the 689 + * next _add_sample() to start with defaults. Reading the values in 690 + * _show() currently can race, so you need to make sure the calls are 691 + * under the same lock that protects calls to _add_sample(). FIXME: 692 + * currently unlocked (It is not ultraprecise but does the trick. Bite 693 + * me). 694 + */ 695 + struct stats { 696 + s8 min, max; 697 + s16 sigma; 698 + atomic_t samples; 699 + }; 700 + 701 + static inline 702 + void stats_init(struct stats *stats) 703 + { 704 + atomic_set(&stats->samples, 0); 705 + wmb(); 706 + } 707 + 708 + static inline 709 + void stats_add_sample(struct stats *stats, s8 sample) 710 + { 711 + s8 min, max; 712 + s16 sigma; 713 + unsigned samples = atomic_read(&stats->samples); 714 + if (samples == 0) { /* it was zero before, so we initialize */ 715 + min = 127; 716 + max = -128; 717 + sigma = 0; 718 + } else { 719 + min = stats->min; 720 + max = stats->max; 721 + sigma = stats->sigma; 722 + } 723 + 724 + if (sample < min) /* compute new values */ 725 + min = sample; 726 + else if (sample > max) 727 + max = sample; 728 + sigma += sample; 729 + 730 + stats->min = min; /* commit */ 731 + stats->max = max; 732 + stats->sigma = sigma; 733 + if (atomic_add_return(1, &stats->samples) > 255) { 734 + /* wrapped around! reset */ 735 + stats->sigma = sigma / 256; 736 + atomic_set(&stats->samples, 1); 737 + } 738 + } 739 + 740 + static inline ssize_t stats_show(struct stats *stats, char *buf) 741 + { 742 + int min, max, avg; 743 + int samples = atomic_read(&stats->samples); 744 + if (samples == 0) 745 + min = max = avg = 0; 746 + else { 747 + min = stats->min; 748 + max = stats->max; 749 + avg = stats->sigma / samples; 750 + } 751 + return scnprintf(buf, PAGE_SIZE, "%d %d %d\n", min, max, avg); 752 + } 753 + 754 + static inline ssize_t stats_store(struct stats *stats, const char *buf, 755 + size_t size) 756 + { 757 + stats_init(stats); 758 + return size; 759 + } 760 + 761 + #endif /* #ifndef __LINUX__UWB_H__ */
+57
include/linux/uwb/debug-cmd.h
··· 1 + /* 2 + * Ultra Wide Band 3 + * Debug interface commands 4 + * 5 + * Copyright (C) 2008 Cambridge Silicon Radio Ltd. 6 + * 7 + * This program is free software; you can redistribute it and/or 8 + * modify it under the terms of the GNU General Public License version 9 + * 2 as published by the Free Software Foundation. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + #ifndef __LINUX__UWB__DEBUG_CMD_H__ 20 + #define __LINUX__UWB__DEBUG_CMD_H__ 21 + 22 + #include <linux/types.h> 23 + 24 + /* 25 + * Debug interface commands 26 + * 27 + * UWB_DBG_CMD_RSV_ESTABLISH: Establish a new unicast reservation. 28 + * 29 + * UWB_DBG_CMD_RSV_TERMINATE: Terminate the Nth reservation. 30 + */ 31 + 32 + enum uwb_dbg_cmd_type { 33 + UWB_DBG_CMD_RSV_ESTABLISH = 1, 34 + UWB_DBG_CMD_RSV_TERMINATE = 2, 35 + }; 36 + 37 + struct uwb_dbg_cmd_rsv_establish { 38 + __u8 target[6]; 39 + __u8 type; 40 + __u16 max_mas; 41 + __u16 min_mas; 42 + __u8 sparsity; 43 + }; 44 + 45 + struct uwb_dbg_cmd_rsv_terminate { 46 + int index; 47 + }; 48 + 49 + struct uwb_dbg_cmd { 50 + __u32 type; 51 + union { 52 + struct uwb_dbg_cmd_rsv_establish rsv_establish; 53 + struct uwb_dbg_cmd_rsv_terminate rsv_terminate; 54 + }; 55 + }; 56 + 57 + #endif /* #ifndef __LINUX__UWB__DEBUG_CMD_H__ */
+82
include/linux/uwb/debug.h
··· 1 + /* 2 + * Ultra Wide Band 3 + * Debug Support 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: doc 24 + * Invoke like: 25 + * 26 + * #define D_LOCAL 4 27 + * #include <linux/uwb/debug.h> 28 + * 29 + * At the end of your include files. 30 + */ 31 + #include <linux/types.h> 32 + 33 + struct device; 34 + extern void dump_bytes(struct device *dev, const void *_buf, size_t rsize); 35 + 36 + /* Master debug switch; !0 enables, 0 disables */ 37 + #define D_MASTER (!0) 38 + 39 + /* Local (per-file) debug switch; #define before #including */ 40 + #ifndef D_LOCAL 41 + #define D_LOCAL 0 42 + #endif 43 + 44 + #undef __d_printf 45 + #undef d_fnstart 46 + #undef d_fnend 47 + #undef d_printf 48 + #undef d_dump 49 + 50 + #define __d_printf(l, _tag, _dev, f, a...) \ 51 + do { \ 52 + struct device *__dev = (_dev); \ 53 + if (D_MASTER && D_LOCAL >= (l)) { \ 54 + char __head[64] = ""; \ 55 + if (_dev != NULL) { \ 56 + if ((unsigned long)__dev < 4096) \ 57 + printk(KERN_ERR "E: Corrupt dev %p\n", \ 58 + __dev); \ 59 + else \ 60 + snprintf(__head, sizeof(__head), \ 61 + "%s %s: ", \ 62 + dev_driver_string(__dev), \ 63 + __dev->bus_id); \ 64 + } \ 65 + printk(KERN_ERR "%s%s" _tag ": " f, __head, \ 66 + __func__, ## a); \ 67 + } \ 68 + } while (0 && _dev) 69 + 70 + #define d_fnstart(l, _dev, f, a...) \ 71 + __d_printf(l, " FNSTART", _dev, f, ## a) 72 + #define d_fnend(l, _dev, f, a...) \ 73 + __d_printf(l, " FNEND", _dev, f, ## a) 74 + #define d_printf(l, _dev, f, a...) \ 75 + __d_printf(l, "", _dev, f, ## a) 76 + #define d_dump(l, _dev, ptr, size) \ 77 + do { \ 78 + struct device *__dev = _dev; \ 79 + if (D_MASTER && D_LOCAL >= (l)) \ 80 + dump_bytes(__dev, ptr, size); \ 81 + } while (0 && _dev) 82 + #define d_test(l) (D_MASTER && D_LOCAL >= (l))
+727
include/linux/uwb/spec.h
··· 1 + /* 2 + * Ultra Wide Band 3 + * UWB Standard definitions 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 + * All these definitions are based on the ECMA-368 standard. 24 + * 25 + * Note all definitions are Little Endian in the wire, and we will 26 + * convert them to host order before operating on the bitfields (that 27 + * yes, we use extensively). 28 + */ 29 + 30 + #ifndef __LINUX__UWB_SPEC_H__ 31 + #define __LINUX__UWB_SPEC_H__ 32 + 33 + #include <linux/types.h> 34 + #include <linux/bitmap.h> 35 + 36 + #define i1480_FW 0x00000303 37 + /* #define i1480_FW 0x00000302 */ 38 + 39 + /** 40 + * Number of Medium Access Slots in a superframe. 41 + * 42 + * UWB divides time in SuperFrames, each one divided in 256 pieces, or 43 + * Medium Access Slots. See MBOA MAC[5.4.5] for details. The MAS is the 44 + * basic bandwidth allocation unit in UWB. 45 + */ 46 + enum { UWB_NUM_MAS = 256 }; 47 + 48 + /** 49 + * Number of Zones in superframe. 50 + * 51 + * UWB divides the superframe into zones with numbering starting from BPST. 52 + * See MBOA MAC[16.8.6] 53 + */ 54 + enum { UWB_NUM_ZONES = 16 }; 55 + 56 + /* 57 + * Number of MAS in a zone. 58 + */ 59 + #define UWB_MAS_PER_ZONE (UWB_NUM_MAS / UWB_NUM_ZONES) 60 + 61 + /* 62 + * Number of streams per DRP reservation between a pair of devices. 63 + * 64 + * [ECMA-368] section 16.8.6. 65 + */ 66 + enum { UWB_NUM_STREAMS = 8 }; 67 + 68 + /* 69 + * mMasLength 70 + * 71 + * The length of a MAS in microseconds. 72 + * 73 + * [ECMA-368] section 17.16. 74 + */ 75 + enum { UWB_MAS_LENGTH_US = 256 }; 76 + 77 + /* 78 + * mBeaconSlotLength 79 + * 80 + * The length of the beacon slot in microseconds. 81 + * 82 + * [ECMA-368] section 17.16 83 + */ 84 + enum { UWB_BEACON_SLOT_LENGTH_US = 85 }; 85 + 86 + /* 87 + * mMaxLostBeacons 88 + * 89 + * The number beacons missing in consecutive superframes before a 90 + * device can be considered as unreachable. 91 + * 92 + * [ECMA-368] section 17.16 93 + */ 94 + enum { UWB_MAX_LOST_BEACONS = 3 }; 95 + 96 + /* 97 + * Length of a superframe in microseconds. 98 + */ 99 + #define UWB_SUPERFRAME_LENGTH_US (UWB_MAS_LENGTH_US * UWB_NUM_MAS) 100 + 101 + /** 102 + * UWB MAC address 103 + * 104 + * It is *imperative* that this struct is exactly 6 packed bytes (as 105 + * it is also used to define headers sent down and up the wire/radio). 106 + */ 107 + struct uwb_mac_addr { 108 + u8 data[6]; 109 + } __attribute__((packed)); 110 + 111 + 112 + /** 113 + * UWB device address 114 + * 115 + * It is *imperative* that this struct is exactly 6 packed bytes (as 116 + * it is also used to define headers sent down and up the wire/radio). 117 + */ 118 + struct uwb_dev_addr { 119 + u8 data[2]; 120 + } __attribute__((packed)); 121 + 122 + 123 + /** 124 + * Types of UWB addresses 125 + * 126 + * Order matters (by size). 127 + */ 128 + enum uwb_addr_type { 129 + UWB_ADDR_DEV = 0, 130 + UWB_ADDR_MAC = 1, 131 + }; 132 + 133 + 134 + /** Size of a char buffer for printing a MAC/device address */ 135 + enum { UWB_ADDR_STRSIZE = 32 }; 136 + 137 + 138 + /** UWB WiMedia protocol IDs. */ 139 + enum uwb_prid { 140 + UWB_PRID_WLP_RESERVED = 0x0000, 141 + UWB_PRID_WLP = 0x0001, 142 + UWB_PRID_WUSB_BOT = 0x0010, 143 + UWB_PRID_WUSB = 0x0010, 144 + UWB_PRID_WUSB_TOP = 0x001F, 145 + }; 146 + 147 + 148 + /** PHY Rate (MBOA MAC[7.8.12, Table 61]) */ 149 + enum uwb_phy_rate { 150 + UWB_PHY_RATE_53 = 0, 151 + UWB_PHY_RATE_80, 152 + UWB_PHY_RATE_106, 153 + UWB_PHY_RATE_160, 154 + UWB_PHY_RATE_200, 155 + UWB_PHY_RATE_320, 156 + UWB_PHY_RATE_400, 157 + UWB_PHY_RATE_480, 158 + UWB_PHY_RATE_INVALID 159 + }; 160 + 161 + 162 + /** 163 + * Different ways to scan (MBOA MAC[6.2.2, Table 8], WUSB[Table 8-78]) 164 + */ 165 + enum uwb_scan_type { 166 + UWB_SCAN_ONLY = 0, 167 + UWB_SCAN_OUTSIDE_BP, 168 + UWB_SCAN_WHILE_INACTIVE, 169 + UWB_SCAN_DISABLED, 170 + UWB_SCAN_ONLY_STARTTIME, 171 + UWB_SCAN_TOP 172 + }; 173 + 174 + 175 + /** ACK Policy types (MBOA MAC[7.2.1.3]) */ 176 + enum uwb_ack_pol { 177 + UWB_ACK_NO = 0, 178 + UWB_ACK_INM = 1, 179 + UWB_ACK_B = 2, 180 + UWB_ACK_B_REQ = 3, 181 + }; 182 + 183 + 184 + /** DRP reservation types ([ECMA-368 table 106) */ 185 + enum uwb_drp_type { 186 + UWB_DRP_TYPE_ALIEN_BP = 0, 187 + UWB_DRP_TYPE_HARD, 188 + UWB_DRP_TYPE_SOFT, 189 + UWB_DRP_TYPE_PRIVATE, 190 + UWB_DRP_TYPE_PCA, 191 + }; 192 + 193 + 194 + /** DRP Reason Codes ([ECMA-368] table 107) */ 195 + enum uwb_drp_reason { 196 + UWB_DRP_REASON_ACCEPTED = 0, 197 + UWB_DRP_REASON_CONFLICT, 198 + UWB_DRP_REASON_PENDING, 199 + UWB_DRP_REASON_DENIED, 200 + UWB_DRP_REASON_MODIFIED, 201 + }; 202 + 203 + /** 204 + * DRP Notification Reason Codes (WHCI 0.95 [3.1.4.9]) 205 + */ 206 + enum uwb_drp_notif_reason { 207 + UWB_DRP_NOTIF_DRP_IE_RCVD = 0, 208 + UWB_DRP_NOTIF_CONFLICT, 209 + UWB_DRP_NOTIF_TERMINATE, 210 + }; 211 + 212 + 213 + /** Allocation of MAS slots in a DRP request MBOA MAC[7.8.7] */ 214 + struct uwb_drp_alloc { 215 + __le16 zone_bm; 216 + __le16 mas_bm; 217 + } __attribute__((packed)); 218 + 219 + 220 + /** General MAC Header format (ECMA-368[16.2]) */ 221 + struct uwb_mac_frame_hdr { 222 + __le16 Frame_Control; 223 + struct uwb_dev_addr DestAddr; 224 + struct uwb_dev_addr SrcAddr; 225 + __le16 Sequence_Control; 226 + __le16 Access_Information; 227 + } __attribute__((packed)); 228 + 229 + 230 + /** 231 + * uwb_beacon_frame - a beacon frame including MAC headers 232 + * 233 + * [ECMA] section 16.3. 234 + */ 235 + struct uwb_beacon_frame { 236 + struct uwb_mac_frame_hdr hdr; 237 + struct uwb_mac_addr Device_Identifier; /* may be a NULL EUI-48 */ 238 + u8 Beacon_Slot_Number; 239 + u8 Device_Control; 240 + u8 IEData[]; 241 + } __attribute__((packed)); 242 + 243 + 244 + /** Information Element codes (MBOA MAC[T54]) */ 245 + enum uwb_ie { 246 + UWB_PCA_AVAILABILITY = 2, 247 + UWB_IE_DRP_AVAILABILITY = 8, 248 + UWB_IE_DRP = 9, 249 + UWB_BP_SWITCH_IE = 11, 250 + UWB_MAC_CAPABILITIES_IE = 12, 251 + UWB_PHY_CAPABILITIES_IE = 13, 252 + UWB_APP_SPEC_PROBE_IE = 15, 253 + UWB_IDENTIFICATION_IE = 19, 254 + UWB_MASTER_KEY_ID_IE = 20, 255 + UWB_IE_WLP = 250, /* WiMedia Logical Link Control Protocol WLP 0.99 */ 256 + UWB_APP_SPEC_IE = 255, 257 + }; 258 + 259 + 260 + /** 261 + * Header common to all Information Elements (IEs) 262 + */ 263 + struct uwb_ie_hdr { 264 + u8 element_id; /* enum uwb_ie */ 265 + u8 length; 266 + } __attribute__((packed)); 267 + 268 + 269 + /** Dynamic Reservation Protocol IE (MBOA MAC[7.8.6]) */ 270 + struct uwb_ie_drp { 271 + struct uwb_ie_hdr hdr; 272 + __le16 drp_control; 273 + struct uwb_dev_addr dev_addr; 274 + struct uwb_drp_alloc allocs[]; 275 + } __attribute__((packed)); 276 + 277 + static inline int uwb_ie_drp_type(struct uwb_ie_drp *ie) 278 + { 279 + return (le16_to_cpu(ie->drp_control) >> 0) & 0x7; 280 + } 281 + 282 + static inline int uwb_ie_drp_stream_index(struct uwb_ie_drp *ie) 283 + { 284 + return (le16_to_cpu(ie->drp_control) >> 3) & 0x7; 285 + } 286 + 287 + static inline int uwb_ie_drp_reason_code(struct uwb_ie_drp *ie) 288 + { 289 + return (le16_to_cpu(ie->drp_control) >> 6) & 0x7; 290 + } 291 + 292 + static inline int uwb_ie_drp_status(struct uwb_ie_drp *ie) 293 + { 294 + return (le16_to_cpu(ie->drp_control) >> 9) & 0x1; 295 + } 296 + 297 + static inline int uwb_ie_drp_owner(struct uwb_ie_drp *ie) 298 + { 299 + return (le16_to_cpu(ie->drp_control) >> 10) & 0x1; 300 + } 301 + 302 + static inline int uwb_ie_drp_tiebreaker(struct uwb_ie_drp *ie) 303 + { 304 + return (le16_to_cpu(ie->drp_control) >> 11) & 0x1; 305 + } 306 + 307 + static inline int uwb_ie_drp_unsafe(struct uwb_ie_drp *ie) 308 + { 309 + return (le16_to_cpu(ie->drp_control) >> 12) & 0x1; 310 + } 311 + 312 + static inline void uwb_ie_drp_set_type(struct uwb_ie_drp *ie, enum uwb_drp_type type) 313 + { 314 + u16 drp_control = le16_to_cpu(ie->drp_control); 315 + drp_control = (drp_control & ~(0x7 << 0)) | (type << 0); 316 + ie->drp_control = cpu_to_le16(drp_control); 317 + } 318 + 319 + static inline void uwb_ie_drp_set_stream_index(struct uwb_ie_drp *ie, int stream_index) 320 + { 321 + u16 drp_control = le16_to_cpu(ie->drp_control); 322 + drp_control = (drp_control & ~(0x7 << 3)) | (stream_index << 3); 323 + ie->drp_control = cpu_to_le16(drp_control); 324 + } 325 + 326 + static inline void uwb_ie_drp_set_reason_code(struct uwb_ie_drp *ie, 327 + enum uwb_drp_reason reason_code) 328 + { 329 + u16 drp_control = le16_to_cpu(ie->drp_control); 330 + drp_control = (ie->drp_control & ~(0x7 << 6)) | (reason_code << 6); 331 + ie->drp_control = cpu_to_le16(drp_control); 332 + } 333 + 334 + static inline void uwb_ie_drp_set_status(struct uwb_ie_drp *ie, int status) 335 + { 336 + u16 drp_control = le16_to_cpu(ie->drp_control); 337 + drp_control = (drp_control & ~(0x1 << 9)) | (status << 9); 338 + ie->drp_control = cpu_to_le16(drp_control); 339 + } 340 + 341 + static inline void uwb_ie_drp_set_owner(struct uwb_ie_drp *ie, int owner) 342 + { 343 + u16 drp_control = le16_to_cpu(ie->drp_control); 344 + drp_control = (drp_control & ~(0x1 << 10)) | (owner << 10); 345 + ie->drp_control = cpu_to_le16(drp_control); 346 + } 347 + 348 + static inline void uwb_ie_drp_set_tiebreaker(struct uwb_ie_drp *ie, int tiebreaker) 349 + { 350 + u16 drp_control = le16_to_cpu(ie->drp_control); 351 + drp_control = (drp_control & ~(0x1 << 11)) | (tiebreaker << 11); 352 + ie->drp_control = cpu_to_le16(drp_control); 353 + } 354 + 355 + static inline void uwb_ie_drp_set_unsafe(struct uwb_ie_drp *ie, int unsafe) 356 + { 357 + u16 drp_control = le16_to_cpu(ie->drp_control); 358 + drp_control = (drp_control & ~(0x1 << 12)) | (unsafe << 12); 359 + ie->drp_control = cpu_to_le16(drp_control); 360 + } 361 + 362 + /** Dynamic Reservation Protocol IE (MBOA MAC[7.8.7]) */ 363 + struct uwb_ie_drp_avail { 364 + struct uwb_ie_hdr hdr; 365 + DECLARE_BITMAP(bmp, UWB_NUM_MAS); 366 + } __attribute__((packed)); 367 + 368 + /** 369 + * The Vendor ID is set to an OUI that indicates the vendor of the device. 370 + * ECMA-368 [16.8.10] 371 + */ 372 + struct uwb_vendor_id { 373 + u8 data[3]; 374 + } __attribute__((packed)); 375 + 376 + /** 377 + * The device type ID 378 + * FIXME: clarify what this means 379 + * ECMA-368 [16.8.10] 380 + */ 381 + struct uwb_device_type_id { 382 + u8 data[3]; 383 + } __attribute__((packed)); 384 + 385 + 386 + /** 387 + * UWB device information types 388 + * ECMA-368 [16.8.10] 389 + */ 390 + enum uwb_dev_info_type { 391 + UWB_DEV_INFO_VENDOR_ID = 0, 392 + UWB_DEV_INFO_VENDOR_TYPE, 393 + UWB_DEV_INFO_NAME, 394 + }; 395 + 396 + /** 397 + * UWB device information found in Identification IE 398 + * ECMA-368 [16.8.10] 399 + */ 400 + struct uwb_dev_info { 401 + u8 type; /* enum uwb_dev_info_type */ 402 + u8 length; 403 + u8 data[]; 404 + } __attribute__((packed)); 405 + 406 + /** 407 + * UWB Identification IE 408 + * ECMA-368 [16.8.10] 409 + */ 410 + struct uwb_identification_ie { 411 + struct uwb_ie_hdr hdr; 412 + struct uwb_dev_info info[]; 413 + } __attribute__((packed)); 414 + 415 + /* 416 + * UWB Radio Controller 417 + * 418 + * These definitions are common to the Radio Control layers as 419 + * exported by the WUSB1.0 HWA and WHCI interfaces. 420 + */ 421 + 422 + /** Radio Control Command Block (WUSB1.0[Table 8-65] and WHCI 0.95) */ 423 + struct uwb_rccb { 424 + u8 bCommandType; /* enum hwa_cet */ 425 + __le16 wCommand; /* Command code */ 426 + u8 bCommandContext; /* Context ID */ 427 + } __attribute__((packed)); 428 + 429 + 430 + /** Radio Control Event Block (WUSB[table 8-66], WHCI 0.95) */ 431 + struct uwb_rceb { 432 + u8 bEventType; /* enum hwa_cet */ 433 + __le16 wEvent; /* Event code */ 434 + u8 bEventContext; /* Context ID */ 435 + } __attribute__((packed)); 436 + 437 + 438 + enum { 439 + UWB_RC_CET_GENERAL = 0, /* General Command/Event type */ 440 + UWB_RC_CET_EX_TYPE_1 = 1, /* Extended Type 1 Command/Event type */ 441 + }; 442 + 443 + /* Commands to the radio controller */ 444 + enum uwb_rc_cmd { 445 + UWB_RC_CMD_CHANNEL_CHANGE = 16, 446 + UWB_RC_CMD_DEV_ADDR_MGMT = 17, /* Device Address Management */ 447 + UWB_RC_CMD_GET_IE = 18, /* GET Information Elements */ 448 + UWB_RC_CMD_RESET = 19, 449 + UWB_RC_CMD_SCAN = 20, /* Scan management */ 450 + UWB_RC_CMD_SET_BEACON_FILTER = 21, 451 + UWB_RC_CMD_SET_DRP_IE = 22, /* Dynamic Reservation Protocol IEs */ 452 + UWB_RC_CMD_SET_IE = 23, /* Information Element management */ 453 + UWB_RC_CMD_SET_NOTIFICATION_FILTER = 24, 454 + UWB_RC_CMD_SET_TX_POWER = 25, 455 + UWB_RC_CMD_SLEEP = 26, 456 + UWB_RC_CMD_START_BEACON = 27, 457 + UWB_RC_CMD_STOP_BEACON = 28, 458 + UWB_RC_CMD_BP_MERGE = 29, 459 + UWB_RC_CMD_SEND_COMMAND_FRAME = 30, 460 + UWB_RC_CMD_SET_ASIE_NOTIF = 31, 461 + }; 462 + 463 + /* Notifications from the radio controller */ 464 + enum uwb_rc_evt { 465 + UWB_RC_EVT_IE_RCV = 0, 466 + UWB_RC_EVT_BEACON = 1, 467 + UWB_RC_EVT_BEACON_SIZE = 2, 468 + UWB_RC_EVT_BPOIE_CHANGE = 3, 469 + UWB_RC_EVT_BP_SLOT_CHANGE = 4, 470 + UWB_RC_EVT_BP_SWITCH_IE_RCV = 5, 471 + UWB_RC_EVT_DEV_ADDR_CONFLICT = 6, 472 + UWB_RC_EVT_DRP_AVAIL = 7, 473 + UWB_RC_EVT_DRP = 8, 474 + UWB_RC_EVT_BP_SWITCH_STATUS = 9, 475 + UWB_RC_EVT_CMD_FRAME_RCV = 10, 476 + UWB_RC_EVT_CHANNEL_CHANGE_IE_RCV = 11, 477 + /* Events (command responses) use the same code as the command */ 478 + UWB_RC_EVT_UNKNOWN_CMD_RCV = 65535, 479 + }; 480 + 481 + enum uwb_rc_extended_type_1_cmd { 482 + UWB_RC_SET_DAA_ENERGY_MASK = 32, 483 + UWB_RC_SET_NOTIFICATION_FILTER_EX = 33, 484 + }; 485 + 486 + enum uwb_rc_extended_type_1_evt { 487 + UWB_RC_DAA_ENERGY_DETECTED = 0, 488 + }; 489 + 490 + /* Radio Control Result Code. [WHCI] table 3-3. */ 491 + enum { 492 + UWB_RC_RES_SUCCESS = 0, 493 + UWB_RC_RES_FAIL, 494 + UWB_RC_RES_FAIL_HARDWARE, 495 + UWB_RC_RES_FAIL_NO_SLOTS, 496 + UWB_RC_RES_FAIL_BEACON_TOO_LARGE, 497 + UWB_RC_RES_FAIL_INVALID_PARAMETER, 498 + UWB_RC_RES_FAIL_UNSUPPORTED_PWR_LEVEL, 499 + UWB_RC_RES_FAIL_INVALID_IE_DATA, 500 + UWB_RC_RES_FAIL_BEACON_SIZE_EXCEEDED, 501 + UWB_RC_RES_FAIL_CANCELLED, 502 + UWB_RC_RES_FAIL_INVALID_STATE, 503 + UWB_RC_RES_FAIL_INVALID_SIZE, 504 + UWB_RC_RES_FAIL_ACK_NOT_RECEIVED, 505 + UWB_RC_RES_FAIL_NO_MORE_ASIE_NOTIF, 506 + UWB_RC_RES_FAIL_TIME_OUT = 255, 507 + }; 508 + 509 + /* Confirm event. [WHCI] section 3.1.3.1 etc. */ 510 + struct uwb_rc_evt_confirm { 511 + struct uwb_rceb rceb; 512 + u8 bResultCode; 513 + } __attribute__((packed)); 514 + 515 + /* Device Address Management event. [WHCI] section 3.1.3.2. */ 516 + struct uwb_rc_evt_dev_addr_mgmt { 517 + struct uwb_rceb rceb; 518 + u8 baAddr[6]; 519 + u8 bResultCode; 520 + } __attribute__((packed)); 521 + 522 + 523 + /* Get IE Event. [WHCI] section 3.1.3.3. */ 524 + struct uwb_rc_evt_get_ie { 525 + struct uwb_rceb rceb; 526 + __le16 wIELength; 527 + u8 IEData[]; 528 + } __attribute__((packed)); 529 + 530 + /* Set DRP IE Event. [WHCI] section 3.1.3.7. */ 531 + struct uwb_rc_evt_set_drp_ie { 532 + struct uwb_rceb rceb; 533 + __le16 wRemainingSpace; 534 + u8 bResultCode; 535 + } __attribute__((packed)); 536 + 537 + /* Set IE Event. [WHCI] section 3.1.3.8. */ 538 + struct uwb_rc_evt_set_ie { 539 + struct uwb_rceb rceb; 540 + __le16 RemainingSpace; 541 + u8 bResultCode; 542 + } __attribute__((packed)); 543 + 544 + /* Scan command. [WHCI] 3.1.3.5. */ 545 + struct uwb_rc_cmd_scan { 546 + struct uwb_rccb rccb; 547 + u8 bChannelNumber; 548 + u8 bScanState; 549 + __le16 wStartTime; 550 + } __attribute__((packed)); 551 + 552 + /* Set DRP IE command. [WHCI] section 3.1.3.7. */ 553 + struct uwb_rc_cmd_set_drp_ie { 554 + struct uwb_rccb rccb; 555 + __le16 wIELength; 556 + struct uwb_ie_drp IEData[]; 557 + } __attribute__((packed)); 558 + 559 + /* Set IE command. [WHCI] section 3.1.3.8. */ 560 + struct uwb_rc_cmd_set_ie { 561 + struct uwb_rccb rccb; 562 + __le16 wIELength; 563 + u8 IEData[]; 564 + } __attribute__((packed)); 565 + 566 + /* Set DAA Energy Mask event. [WHCI 0.96] section 3.1.3.17. */ 567 + struct uwb_rc_evt_set_daa_energy_mask { 568 + struct uwb_rceb rceb; 569 + __le16 wLength; 570 + u8 result; 571 + } __attribute__((packed)); 572 + 573 + /* Set Notification Filter Extended event. [WHCI 0.96] section 3.1.3.18. */ 574 + struct uwb_rc_evt_set_notification_filter_ex { 575 + struct uwb_rceb rceb; 576 + __le16 wLength; 577 + u8 result; 578 + } __attribute__((packed)); 579 + 580 + /* IE Received notification. [WHCI] section 3.1.4.1. */ 581 + struct uwb_rc_evt_ie_rcv { 582 + struct uwb_rceb rceb; 583 + struct uwb_dev_addr SrcAddr; 584 + __le16 wIELength; 585 + u8 IEData[]; 586 + } __attribute__((packed)); 587 + 588 + /* Type of the received beacon. [WHCI] section 3.1.4.2. */ 589 + enum uwb_rc_beacon_type { 590 + UWB_RC_BEACON_TYPE_SCAN = 0, 591 + UWB_RC_BEACON_TYPE_NEIGHBOR, 592 + UWB_RC_BEACON_TYPE_OL_ALIEN, 593 + UWB_RC_BEACON_TYPE_NOL_ALIEN, 594 + }; 595 + 596 + /* Beacon received notification. [WHCI] 3.1.4.2. */ 597 + struct uwb_rc_evt_beacon { 598 + struct uwb_rceb rceb; 599 + u8 bChannelNumber; 600 + u8 bBeaconType; 601 + __le16 wBPSTOffset; 602 + u8 bLQI; 603 + u8 bRSSI; 604 + __le16 wBeaconInfoLength; 605 + u8 BeaconInfo[]; 606 + } __attribute__((packed)); 607 + 608 + 609 + /* Beacon Size Change notification. [WHCI] section 3.1.4.3 */ 610 + struct uwb_rc_evt_beacon_size { 611 + struct uwb_rceb rceb; 612 + __le16 wNewBeaconSize; 613 + } __attribute__((packed)); 614 + 615 + 616 + /* BPOIE Change notification. [WHCI] section 3.1.4.4. */ 617 + struct uwb_rc_evt_bpoie_change { 618 + struct uwb_rceb rceb; 619 + __le16 wBPOIELength; 620 + u8 BPOIE[]; 621 + } __attribute__((packed)); 622 + 623 + 624 + /* Beacon Slot Change notification. [WHCI] section 3.1.4.5. */ 625 + struct uwb_rc_evt_bp_slot_change { 626 + struct uwb_rceb rceb; 627 + u8 slot_info; 628 + } __attribute__((packed)); 629 + 630 + static inline int uwb_rc_evt_bp_slot_change_slot_num( 631 + const struct uwb_rc_evt_bp_slot_change *evt) 632 + { 633 + return evt->slot_info & 0x7f; 634 + } 635 + 636 + static inline int uwb_rc_evt_bp_slot_change_no_slot( 637 + const struct uwb_rc_evt_bp_slot_change *evt) 638 + { 639 + return (evt->slot_info & 0x80) >> 7; 640 + } 641 + 642 + /* BP Switch IE Received notification. [WHCI] section 3.1.4.6. */ 643 + struct uwb_rc_evt_bp_switch_ie_rcv { 644 + struct uwb_rceb rceb; 645 + struct uwb_dev_addr wSrcAddr; 646 + __le16 wIELength; 647 + u8 IEData[]; 648 + } __attribute__((packed)); 649 + 650 + /* DevAddr Conflict notification. [WHCI] section 3.1.4.7. */ 651 + struct uwb_rc_evt_dev_addr_conflict { 652 + struct uwb_rceb rceb; 653 + } __attribute__((packed)); 654 + 655 + /* DRP notification. [WHCI] section 3.1.4.9. */ 656 + struct uwb_rc_evt_drp { 657 + struct uwb_rceb rceb; 658 + struct uwb_dev_addr src_addr; 659 + u8 reason; 660 + u8 beacon_slot_number; 661 + __le16 ie_length; 662 + u8 ie_data[]; 663 + } __attribute__((packed)); 664 + 665 + static inline enum uwb_drp_notif_reason uwb_rc_evt_drp_reason(struct uwb_rc_evt_drp *evt) 666 + { 667 + return evt->reason & 0x0f; 668 + } 669 + 670 + 671 + /* DRP Availability Change notification. [WHCI] section 3.1.4.8. */ 672 + struct uwb_rc_evt_drp_avail { 673 + struct uwb_rceb rceb; 674 + DECLARE_BITMAP(bmp, UWB_NUM_MAS); 675 + } __attribute__((packed)); 676 + 677 + /* BP switch status notification. [WHCI] section 3.1.4.10. */ 678 + struct uwb_rc_evt_bp_switch_status { 679 + struct uwb_rceb rceb; 680 + u8 status; 681 + u8 slot_offset; 682 + __le16 bpst_offset; 683 + u8 move_countdown; 684 + } __attribute__((packed)); 685 + 686 + /* Command Frame Received notification. [WHCI] section 3.1.4.11. */ 687 + struct uwb_rc_evt_cmd_frame_rcv { 688 + struct uwb_rceb rceb; 689 + __le16 receive_time; 690 + struct uwb_dev_addr wSrcAddr; 691 + struct uwb_dev_addr wDstAddr; 692 + __le16 control; 693 + __le16 reserved; 694 + __le16 dataLength; 695 + u8 data[]; 696 + } __attribute__((packed)); 697 + 698 + /* Channel Change IE Received notification. [WHCI] section 3.1.4.12. */ 699 + struct uwb_rc_evt_channel_change_ie_rcv { 700 + struct uwb_rceb rceb; 701 + struct uwb_dev_addr wSrcAddr; 702 + __le16 wIELength; 703 + u8 IEData[]; 704 + } __attribute__((packed)); 705 + 706 + /* DAA Energy Detected notification. [WHCI 0.96] section 3.1.4.14. */ 707 + struct uwb_rc_evt_daa_energy_detected { 708 + struct uwb_rceb rceb; 709 + __le16 wLength; 710 + u8 bandID; 711 + u8 reserved; 712 + u8 toneBmp[16]; 713 + } __attribute__((packed)); 714 + 715 + 716 + /** 717 + * Radio Control Interface Class Descriptor 718 + * 719 + * WUSB 1.0 [8.6.1.2] 720 + */ 721 + struct uwb_rc_control_intf_class_desc { 722 + u8 bLength; 723 + u8 bDescriptorType; 724 + __le16 bcdRCIVersion; 725 + } __attribute__((packed)); 726 + 727 + #endif /* #ifndef __LINUX__UWB_SPEC_H__ */
+735
include/linux/wlp.h
··· 1 + /* 2 + * WiMedia Logical Link Control Protocol (WLP) 3 + * 4 + * Copyright (C) 2005-2006 Intel Corporation 5 + * Reinette Chatre <reinette.chatre@intel.com> 6 + * 7 + * This program is free software; you can redistribute it and/or 8 + * modify it under the terms of the GNU General Public License version 9 + * 2 as published by the Free Software Foundation. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program; if not, write to the Free Software 18 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 + * 02110-1301, USA. 20 + * 21 + * 22 + * FIXME: docs 23 + * 24 + * - Does not (yet) include support for WLP control frames 25 + * WLP Draft 0.99 [6.5]. 26 + * 27 + * A visual representation of the data structures. 28 + * 29 + * wssidB wssidB 30 + * ^ ^ 31 + * | | 32 + * wssidA wssidA 33 + * wlp interface { ^ ^ 34 + * ... | | 35 + * ... ... wssid wssid ... 36 + * wlp --- ... | | 37 + * }; neighbors --> neighbA --> neighbB 38 + * ... 39 + * wss 40 + * ... 41 + * eda cache --> neighborA --> neighborB --> neighborC ... 42 + */ 43 + 44 + #ifndef __LINUX__WLP_H_ 45 + #define __LINUX__WLP_H_ 46 + 47 + #include <linux/netdevice.h> 48 + #include <linux/skbuff.h> 49 + #include <linux/list.h> 50 + #include <linux/uwb.h> 51 + 52 + /** 53 + * WLP Protocol ID 54 + * WLP Draft 0.99 [6.2] 55 + * 56 + * The MUX header for all WLP frames 57 + */ 58 + #define WLP_PROTOCOL_ID 0x0100 59 + 60 + /** 61 + * WLP Version 62 + * WLP version placed in the association frames (WLP 0.99 [6.6]) 63 + */ 64 + #define WLP_VERSION 0x10 65 + 66 + /** 67 + * Bytes needed to print UUID as string 68 + */ 69 + #define WLP_WSS_UUID_STRSIZE 48 70 + 71 + /** 72 + * Bytes needed to print nonce as string 73 + */ 74 + #define WLP_WSS_NONCE_STRSIZE 48 75 + 76 + 77 + /** 78 + * Size used for WLP name size 79 + * 80 + * The WSS name is set to 65 bytes, 1 byte larger than the maximum 81 + * allowed by the WLP spec. This is to have a null terminated string 82 + * for display to the user. A maximum of 64 bytes will still be used 83 + * when placing the WSS name field in association frames. 84 + */ 85 + #define WLP_WSS_NAME_SIZE 65 86 + 87 + /** 88 + * Number of bytes added by WLP to data frame 89 + * 90 + * A data frame transmitted from a host will be placed in a Standard or 91 + * Abbreviated WLP frame. These have an extra 4 bytes of header (struct 92 + * wlp_frame_std_abbrv_hdr). 93 + * When the stack sends this data frame for transmission it needs to ensure 94 + * there is enough headroom for this header. 95 + */ 96 + #define WLP_DATA_HLEN 4 97 + 98 + /** 99 + * State of device regarding WLP Service Set 100 + * 101 + * WLP_WSS_STATE_NONE: the host does not participate in any WSS 102 + * WLP_WSS_STATE_PART_ENROLLED: used as part of the enrollment sequence 103 + * ("Partial Enroll"). This state is used to 104 + * indicate the first part of enrollment that is 105 + * unsecure. If the WSS is unsecure then the 106 + * state will promptly go to WLP_WSS_STATE_ENROLLED, 107 + * if the WSS is not secure then the enrollment 108 + * procedure is a few more steps before we are 109 + * enrolled. 110 + * WLP_WSS_STATE_ENROLLED: the host is enrolled in a WSS 111 + * WLP_WSS_STATE_ACTIVE: WSS is activated 112 + * WLP_WSS_STATE_CONNECTED: host is connected to neighbor in WSS 113 + * 114 + */ 115 + enum wlp_wss_state { 116 + WLP_WSS_STATE_NONE = 0, 117 + WLP_WSS_STATE_PART_ENROLLED, 118 + WLP_WSS_STATE_ENROLLED, 119 + WLP_WSS_STATE_ACTIVE, 120 + WLP_WSS_STATE_CONNECTED, 121 + }; 122 + 123 + /** 124 + * WSS Secure status 125 + * WLP 0.99 Table 6 126 + * 127 + * Set to one if the WSS is secure, zero if it is not secure 128 + */ 129 + enum wlp_wss_sec_status { 130 + WLP_WSS_UNSECURE = 0, 131 + WLP_WSS_SECURE, 132 + }; 133 + 134 + /** 135 + * WLP frame type 136 + * WLP Draft 0.99 [6.2 Table 1] 137 + */ 138 + enum wlp_frame_type { 139 + WLP_FRAME_STANDARD = 0, 140 + WLP_FRAME_ABBREVIATED, 141 + WLP_FRAME_CONTROL, 142 + WLP_FRAME_ASSOCIATION, 143 + }; 144 + 145 + /** 146 + * WLP Association Message Type 147 + * WLP Draft 0.99 [6.6.1.2 Table 8] 148 + */ 149 + enum wlp_assoc_type { 150 + WLP_ASSOC_D1 = 2, 151 + WLP_ASSOC_D2 = 3, 152 + WLP_ASSOC_M1 = 4, 153 + WLP_ASSOC_M2 = 5, 154 + WLP_ASSOC_M3 = 7, 155 + WLP_ASSOC_M4 = 8, 156 + WLP_ASSOC_M5 = 9, 157 + WLP_ASSOC_M6 = 10, 158 + WLP_ASSOC_M7 = 11, 159 + WLP_ASSOC_M8 = 12, 160 + WLP_ASSOC_F0 = 14, 161 + WLP_ASSOC_E1 = 32, 162 + WLP_ASSOC_E2 = 33, 163 + WLP_ASSOC_C1 = 34, 164 + WLP_ASSOC_C2 = 35, 165 + WLP_ASSOC_C3 = 36, 166 + WLP_ASSOC_C4 = 37, 167 + }; 168 + 169 + /** 170 + * WLP Attribute Type 171 + * WLP Draft 0.99 [6.6.1 Table 6] 172 + */ 173 + enum wlp_attr_type { 174 + WLP_ATTR_AUTH = 0x1005, /* Authenticator */ 175 + WLP_ATTR_DEV_NAME = 0x1011, /* Device Name */ 176 + WLP_ATTR_DEV_PWD_ID = 0x1012, /* Device Password ID */ 177 + WLP_ATTR_E_HASH1 = 0x1014, /* E-Hash1 */ 178 + WLP_ATTR_E_HASH2 = 0x1015, /* E-Hash2 */ 179 + WLP_ATTR_E_SNONCE1 = 0x1016, /* E-SNonce1 */ 180 + WLP_ATTR_E_SNONCE2 = 0x1017, /* E-SNonce2 */ 181 + WLP_ATTR_ENCR_SET = 0x1018, /* Encrypted Settings */ 182 + WLP_ATTR_ENRL_NONCE = 0x101A, /* Enrollee Nonce */ 183 + WLP_ATTR_KEYWRAP_AUTH = 0x101E, /* Key Wrap Authenticator */ 184 + WLP_ATTR_MANUF = 0x1021, /* Manufacturer */ 185 + WLP_ATTR_MSG_TYPE = 0x1022, /* Message Type */ 186 + WLP_ATTR_MODEL_NAME = 0x1023, /* Model Name */ 187 + WLP_ATTR_MODEL_NR = 0x1024, /* Model Number */ 188 + WLP_ATTR_PUB_KEY = 0x1032, /* Public Key */ 189 + WLP_ATTR_REG_NONCE = 0x1039, /* Registrar Nonce */ 190 + WLP_ATTR_R_HASH1 = 0x103D, /* R-Hash1 */ 191 + WLP_ATTR_R_HASH2 = 0x103E, /* R-Hash2 */ 192 + WLP_ATTR_R_SNONCE1 = 0x103F, /* R-SNonce1 */ 193 + WLP_ATTR_R_SNONCE2 = 0x1040, /* R-SNonce2 */ 194 + WLP_ATTR_SERIAL = 0x1042, /* Serial number */ 195 + WLP_ATTR_UUID_E = 0x1047, /* UUID-E */ 196 + WLP_ATTR_UUID_R = 0x1048, /* UUID-R */ 197 + WLP_ATTR_PRI_DEV_TYPE = 0x1054, /* Primary Device Type */ 198 + WLP_ATTR_SEC_DEV_TYPE = 0x1055, /* Secondary Device Type */ 199 + WLP_ATTR_PORT_DEV = 0x1056, /* Portable Device */ 200 + WLP_ATTR_APP_EXT = 0x1058, /* Application Extension */ 201 + WLP_ATTR_WLP_VER = 0x2000, /* WLP Version */ 202 + WLP_ATTR_WSSID = 0x2001, /* WSSID */ 203 + WLP_ATTR_WSS_NAME = 0x2002, /* WSS Name */ 204 + WLP_ATTR_WSS_SEC_STAT = 0x2003, /* WSS Secure Status */ 205 + WLP_ATTR_WSS_BCAST = 0x2004, /* WSS Broadcast Address */ 206 + WLP_ATTR_WSS_M_KEY = 0x2005, /* WSS Master Key */ 207 + WLP_ATTR_ACC_ENRL = 0x2006, /* Accepting Enrollment */ 208 + WLP_ATTR_WSS_INFO = 0x2007, /* WSS Information */ 209 + WLP_ATTR_WSS_SEL_MTHD = 0x2008, /* WSS Selection Method */ 210 + WLP_ATTR_ASSC_MTHD_LIST = 0x2009, /* Association Methods List */ 211 + WLP_ATTR_SEL_ASSC_MTHD = 0x200A, /* Selected Association Method */ 212 + WLP_ATTR_ENRL_HASH_COMM = 0x200B, /* Enrollee Hash Commitment */ 213 + WLP_ATTR_WSS_TAG = 0x200C, /* WSS Tag */ 214 + WLP_ATTR_WSS_VIRT = 0x200D, /* WSS Virtual EUI-48 */ 215 + WLP_ATTR_WLP_ASSC_ERR = 0x200E, /* WLP Association Error */ 216 + WLP_ATTR_VNDR_EXT = 0x200F, /* Vendor Extension */ 217 + }; 218 + 219 + /** 220 + * WLP Category ID of primary/secondary device 221 + * WLP Draft 0.99 [6.6.1.8 Table 12] 222 + */ 223 + enum wlp_dev_category_id { 224 + WLP_DEV_CAT_COMPUTER = 1, 225 + WLP_DEV_CAT_INPUT, 226 + WLP_DEV_CAT_PRINT_SCAN_FAX_COPIER, 227 + WLP_DEV_CAT_CAMERA, 228 + WLP_DEV_CAT_STORAGE, 229 + WLP_DEV_CAT_INFRASTRUCTURE, 230 + WLP_DEV_CAT_DISPLAY, 231 + WLP_DEV_CAT_MULTIM, 232 + WLP_DEV_CAT_GAMING, 233 + WLP_DEV_CAT_TELEPHONE, 234 + WLP_DEV_CAT_OTHER = 65535, 235 + }; 236 + 237 + /** 238 + * WLP WSS selection method 239 + * WLP Draft 0.99 [6.6.1.6 Table 10] 240 + */ 241 + enum wlp_wss_sel_mthd { 242 + WLP_WSS_ENRL_SELECT = 1, /* Enrollee selects */ 243 + WLP_WSS_REG_SELECT, /* Registrar selects */ 244 + }; 245 + 246 + /** 247 + * WLP association error values 248 + * WLP Draft 0.99 [6.6.1.5 Table 9] 249 + */ 250 + enum wlp_assc_error { 251 + WLP_ASSOC_ERROR_NONE, 252 + WLP_ASSOC_ERROR_AUTH, /* Authenticator Failure */ 253 + WLP_ASSOC_ERROR_ROGUE, /* Rogue activity suspected */ 254 + WLP_ASSOC_ERROR_BUSY, /* Device busy */ 255 + WLP_ASSOC_ERROR_LOCK, /* Setup Locked */ 256 + WLP_ASSOC_ERROR_NOT_READY, /* Registrar not ready */ 257 + WLP_ASSOC_ERROR_INV, /* Invalid WSS selection */ 258 + WLP_ASSOC_ERROR_MSG_TIME, /* Message timeout */ 259 + WLP_ASSOC_ERROR_ENR_TIME, /* Enrollment session timeout */ 260 + WLP_ASSOC_ERROR_PW, /* Device password invalid */ 261 + WLP_ASSOC_ERROR_VER, /* Unsupported version */ 262 + WLP_ASSOC_ERROR_INT, /* Internal error */ 263 + WLP_ASSOC_ERROR_UNDEF, /* Undefined error */ 264 + WLP_ASSOC_ERROR_NUM, /* Numeric comparison failure */ 265 + WLP_ASSOC_ERROR_WAIT, /* Waiting for user input */ 266 + }; 267 + 268 + /** 269 + * WLP Parameters 270 + * WLP 0.99 [7.7] 271 + */ 272 + enum wlp_parameters { 273 + WLP_PER_MSG_TIMEOUT = 15, /* Seconds to wait for response to 274 + association message. */ 275 + }; 276 + 277 + /** 278 + * WLP IE 279 + * 280 + * The WLP IE should be included in beacons by all devices. 281 + * 282 + * The driver can set only a few of the fields in this information element, 283 + * most fields are managed by the device self. When the driver needs to set 284 + * a field it will only provide values for the fields of interest, the rest 285 + * will be filled with zeroes. The fields of interest are: 286 + * 287 + * Element ID 288 + * Length 289 + * Capabilities (only to include WSSID Hash list length) 290 + * WSSID Hash List fields 291 + * 292 + * WLP 0.99 [6.7] 293 + * 294 + * Only the fields that will be used are detailed in this structure, rest 295 + * are not detailed or marked as "notused". 296 + */ 297 + struct wlp_ie { 298 + struct uwb_ie_hdr hdr; 299 + __le16 capabilities; 300 + __le16 cycle_param; 301 + __le16 acw_anchor_addr; 302 + u8 wssid_hash_list[]; 303 + } __attribute__((packed)); 304 + 305 + static inline int wlp_ie_hash_length(struct wlp_ie *ie) 306 + { 307 + return (le16_to_cpu(ie->capabilities) >> 12) & 0xf; 308 + } 309 + 310 + static inline void wlp_ie_set_hash_length(struct wlp_ie *ie, int hash_length) 311 + { 312 + u16 caps = le16_to_cpu(ie->capabilities); 313 + caps = (caps & ~(0xf << 12)) | (hash_length << 12); 314 + ie->capabilities = cpu_to_le16(caps); 315 + } 316 + 317 + /** 318 + * WLP nonce 319 + * WLP Draft 0.99 [6.6.1 Table 6] 320 + * 321 + * A 128-bit random number often used (E-SNonce1, E-SNonce2, Enrollee 322 + * Nonce, Registrar Nonce, R-SNonce1, R-SNonce2). It is passed to HW so 323 + * it is packed. 324 + */ 325 + struct wlp_nonce { 326 + u8 data[16]; 327 + } __attribute__((packed)); 328 + 329 + /** 330 + * WLP UUID 331 + * WLP Draft 0.99 [6.6.1 Table 6] 332 + * 333 + * Universally Unique Identifier (UUID) encoded as an octet string in the 334 + * order the octets are shown in string representation in RFC4122. A UUID 335 + * is often used (UUID-E, UUID-R, WSSID). It is passed to HW so it is packed. 336 + */ 337 + struct wlp_uuid { 338 + u8 data[16]; 339 + } __attribute__((packed)); 340 + 341 + 342 + /** 343 + * Primary and secondary device type attributes 344 + * WLP Draft 0.99 [6.6.1.8] 345 + */ 346 + struct wlp_dev_type { 347 + enum wlp_dev_category_id category:16; 348 + u8 OUI[3]; 349 + u8 OUIsubdiv; 350 + __le16 subID; 351 + } __attribute__((packed)); 352 + 353 + /** 354 + * WLP frame header 355 + * WLP Draft 0.99 [6.2] 356 + */ 357 + struct wlp_frame_hdr { 358 + __le16 mux_hdr; /* WLP_PROTOCOL_ID */ 359 + enum wlp_frame_type type:8; 360 + } __attribute__((packed)); 361 + 362 + /** 363 + * WLP attribute field header 364 + * WLP Draft 0.99 [6.6.1] 365 + * 366 + * Header of each attribute found in an association frame 367 + */ 368 + struct wlp_attr_hdr { 369 + __le16 type; 370 + __le16 length; 371 + } __attribute__((packed)); 372 + 373 + /** 374 + * Device information commonly used together 375 + * 376 + * Each of these device information elements has a specified range in which it 377 + * should fit (WLP 0.99 [Table 6]). This range provided in the spec does not 378 + * include the termination null '\0' character (when used in the 379 + * association protocol the attribute fields are accompanied 380 + * with a "length" field so the full range from the spec can be used for 381 + * the value). We thus allocate an extra byte to be able to store a string 382 + * of max length with a terminating '\0'. 383 + */ 384 + struct wlp_device_info { 385 + char name[33]; 386 + char model_name[33]; 387 + char manufacturer[65]; 388 + char model_nr[33]; 389 + char serial[33]; 390 + struct wlp_dev_type prim_dev_type; 391 + }; 392 + 393 + /** 394 + * Macros for the WLP attributes 395 + * 396 + * There are quite a few attributes (total is 43). The attribute layout can be 397 + * in one of three categories: one value, an array, an enum forced to 8 bits. 398 + * These macros help with their definitions. 399 + */ 400 + #define wlp_attr(type, name) \ 401 + struct wlp_attr_##name { \ 402 + struct wlp_attr_hdr hdr; \ 403 + type name; \ 404 + } __attribute__((packed)); 405 + 406 + #define wlp_attr_array(type, name) \ 407 + struct wlp_attr_##name { \ 408 + struct wlp_attr_hdr hdr; \ 409 + type name[]; \ 410 + } __attribute__((packed)); 411 + 412 + /** 413 + * WLP association attribute fields 414 + * WLP Draft 0.99 [6.6.1 Table 6] 415 + * 416 + * Attributes appear in same order as the Table in the spec 417 + * FIXME Does not define all attributes yet 418 + */ 419 + 420 + /* Device name: Friendly name of sending device */ 421 + wlp_attr_array(u8, dev_name) 422 + 423 + /* Enrollee Nonce: Random number generated by enrollee for an enrollment 424 + * session */ 425 + wlp_attr(struct wlp_nonce, enonce) 426 + 427 + /* Manufacturer name: Name of manufacturer of the sending device */ 428 + wlp_attr_array(u8, manufacturer) 429 + 430 + /* WLP Message Type */ 431 + wlp_attr(u8, msg_type) 432 + 433 + /* WLP Model name: Model name of sending device */ 434 + wlp_attr_array(u8, model_name) 435 + 436 + /* WLP Model number: Model number of sending device */ 437 + wlp_attr_array(u8, model_nr) 438 + 439 + /* Registrar Nonce: Random number generated by registrar for an enrollment 440 + * session */ 441 + wlp_attr(struct wlp_nonce, rnonce) 442 + 443 + /* Serial number of device */ 444 + wlp_attr_array(u8, serial) 445 + 446 + /* UUID of enrollee */ 447 + wlp_attr(struct wlp_uuid, uuid_e) 448 + 449 + /* UUID of registrar */ 450 + wlp_attr(struct wlp_uuid, uuid_r) 451 + 452 + /* WLP Primary device type */ 453 + wlp_attr(struct wlp_dev_type, prim_dev_type) 454 + 455 + /* WLP Secondary device type */ 456 + wlp_attr(struct wlp_dev_type, sec_dev_type) 457 + 458 + /* WLP protocol version */ 459 + wlp_attr(u8, version) 460 + 461 + /* WLP service set identifier */ 462 + wlp_attr(struct wlp_uuid, wssid) 463 + 464 + /* WLP WSS name */ 465 + wlp_attr_array(u8, wss_name) 466 + 467 + /* WLP WSS Secure Status */ 468 + wlp_attr(u8, wss_sec_status) 469 + 470 + /* WSS Broadcast Address */ 471 + wlp_attr(struct uwb_mac_addr, wss_bcast) 472 + 473 + /* WLP Accepting Enrollment */ 474 + wlp_attr(u8, accept_enrl) 475 + 476 + /** 477 + * WSS information attributes 478 + * WLP Draft 0.99 [6.6.3 Table 15] 479 + */ 480 + struct wlp_wss_info { 481 + struct wlp_attr_wssid wssid; 482 + struct wlp_attr_wss_name name; 483 + struct wlp_attr_accept_enrl accept; 484 + struct wlp_attr_wss_sec_status sec_stat; 485 + struct wlp_attr_wss_bcast bcast; 486 + } __attribute__((packed)); 487 + 488 + /* WLP WSS Information */ 489 + wlp_attr_array(struct wlp_wss_info, wss_info) 490 + 491 + /* WLP WSS Selection method */ 492 + wlp_attr(u8, wss_sel_mthd) 493 + 494 + /* WLP WSS tag */ 495 + wlp_attr(u8, wss_tag) 496 + 497 + /* WSS Virtual Address */ 498 + wlp_attr(struct uwb_mac_addr, wss_virt) 499 + 500 + /* WLP association error */ 501 + wlp_attr(u8, wlp_assc_err) 502 + 503 + /** 504 + * WLP standard and abbreviated frames 505 + * 506 + * WLP Draft 0.99 [6.3] and [6.4] 507 + * 508 + * The difference between the WLP standard frame and the WLP 509 + * abbreviated frame is that the standard frame includes the src 510 + * and dest addresses from the Ethernet header, the abbreviated frame does 511 + * not. 512 + * The src/dest (as well as the type/length and client data) are already 513 + * defined as part of the Ethernet header, we do not do this here. 514 + * From this perspective the standard and abbreviated frames appear the 515 + * same - they will be treated differently though. 516 + * 517 + * The size of this header is also captured in WLP_DATA_HLEN to enable 518 + * interfaces to prepare their headroom. 519 + */ 520 + struct wlp_frame_std_abbrv_hdr { 521 + struct wlp_frame_hdr hdr; 522 + u8 tag; 523 + } __attribute__((packed)); 524 + 525 + /** 526 + * WLP association frames 527 + * 528 + * WLP Draft 0.99 [6.6] 529 + */ 530 + struct wlp_frame_assoc { 531 + struct wlp_frame_hdr hdr; 532 + enum wlp_assoc_type type:8; 533 + struct wlp_attr_version version; 534 + struct wlp_attr_msg_type msg_type; 535 + u8 attr[]; 536 + } __attribute__((packed)); 537 + 538 + /* Ethernet to dev address mapping */ 539 + struct wlp_eda { 540 + spinlock_t lock; 541 + struct list_head cache; /* Eth<->Dev Addr cache */ 542 + }; 543 + 544 + /** 545 + * WSS information temporary storage 546 + * 547 + * This information is only stored temporarily during discovery. It should 548 + * not be stored unless the device is enrolled in the advertised WSS. This 549 + * is done mainly because we follow the letter of the spec in this regard. 550 + * See WLP 0.99 [7.2.3]. 551 + * When the device does become enrolled in a WSS the WSS information will 552 + * be stored as part of the more comprehensive struct wlp_wss. 553 + */ 554 + struct wlp_wss_tmp_info { 555 + char name[WLP_WSS_NAME_SIZE]; 556 + u8 accept_enroll; 557 + u8 sec_status; 558 + struct uwb_mac_addr bcast; 559 + }; 560 + 561 + struct wlp_wssid_e { 562 + struct list_head node; 563 + struct wlp_uuid wssid; 564 + struct wlp_wss_tmp_info *info; 565 + }; 566 + 567 + /** 568 + * A cache entry of WLP neighborhood 569 + * 570 + * @node: head of list is wlp->neighbors 571 + * @wssid: list of wssids of this neighbor, element is wlp_wssid_e 572 + * @info: temporary storage for information learned during discovery. This 573 + * storage is used together with the wssid_e temporary storage 574 + * during discovery. 575 + */ 576 + struct wlp_neighbor_e { 577 + struct list_head node; 578 + struct wlp_uuid uuid; 579 + struct uwb_dev *uwb_dev; 580 + struct list_head wssid; /* Elements are wlp_wssid_e */ 581 + struct wlp_device_info *info; 582 + }; 583 + 584 + struct wlp; 585 + /** 586 + * Information for an association session in progress. 587 + * 588 + * @exp_message: The type of the expected message. Both this message and a 589 + * F0 message (which can be sent in response to any 590 + * association frame) will be accepted as a valid message for 591 + * this session. 592 + * @cb: The function that will be called upon receipt of this 593 + * message. 594 + * @cb_priv: Private data of callback 595 + * @data: Data used in association process (always a sk_buff?) 596 + * @neighbor: Address of neighbor with which association session is in 597 + * progress. 598 + */ 599 + struct wlp_session { 600 + enum wlp_assoc_type exp_message; 601 + void (*cb)(struct wlp *); 602 + void *cb_priv; 603 + void *data; 604 + struct uwb_dev_addr neighbor_addr; 605 + }; 606 + 607 + /** 608 + * WLP Service Set 609 + * 610 + * @mutex: used to protect entire WSS structure. 611 + * 612 + * @name: The WSS name is set to 65 bytes, 1 byte larger than the maximum 613 + * allowed by the WLP spec. This is to have a null terminated string 614 + * for display to the user. A maximum of 64 bytes will still be used 615 + * when placing the WSS name field in association frames. 616 + * 617 + * @accept_enroll: Accepting enrollment: Set to one if registrar is 618 + * accepting enrollment in WSS, or zero otherwise. 619 + * 620 + * Global and local information for each WSS in which we are enrolled. 621 + * WLP 0.99 Section 7.2.1 and Section 7.2.2 622 + */ 623 + struct wlp_wss { 624 + struct mutex mutex; 625 + struct kobject kobj; 626 + /* Global properties. */ 627 + struct wlp_uuid wssid; 628 + u8 hash; 629 + char name[WLP_WSS_NAME_SIZE]; 630 + struct uwb_mac_addr bcast; 631 + u8 secure_status:1; 632 + u8 master_key[16]; 633 + /* Local properties. */ 634 + u8 tag; 635 + struct uwb_mac_addr virtual_addr; 636 + /* Extra */ 637 + u8 accept_enroll:1; 638 + enum wlp_wss_state state; 639 + }; 640 + 641 + /** 642 + * WLP main structure 643 + * @mutex: protect changes to WLP structure. We only allow changes to the 644 + * uuid, so currently this mutex only protects this field. 645 + */ 646 + struct wlp { 647 + struct mutex mutex; 648 + struct uwb_rc *rc; /* UWB radio controller */ 649 + struct uwb_pal pal; 650 + struct wlp_eda eda; 651 + struct wlp_uuid uuid; 652 + struct wlp_session *session; 653 + struct wlp_wss wss; 654 + struct mutex nbmutex; /* Neighbor mutex protects neighbors list */ 655 + struct list_head neighbors; /* Elements are wlp_neighbor_e */ 656 + struct uwb_notifs_handler uwb_notifs_handler; 657 + struct wlp_device_info *dev_info; 658 + void (*fill_device_info)(struct wlp *wlp, struct wlp_device_info *info); 659 + int (*xmit_frame)(struct wlp *, struct sk_buff *, 660 + struct uwb_dev_addr *); 661 + void (*stop_queue)(struct wlp *); 662 + void (*start_queue)(struct wlp *); 663 + }; 664 + 665 + /* sysfs */ 666 + 667 + 668 + struct wlp_wss_attribute { 669 + struct attribute attr; 670 + ssize_t (*show)(struct wlp_wss *wss, char *buf); 671 + ssize_t (*store)(struct wlp_wss *wss, const char *buf, size_t count); 672 + }; 673 + 674 + #define WSS_ATTR(_name, _mode, _show, _store) \ 675 + static struct wlp_wss_attribute wss_attr_##_name = __ATTR(_name, _mode, \ 676 + _show, _store) 677 + 678 + extern int wlp_setup(struct wlp *, struct uwb_rc *); 679 + extern void wlp_remove(struct wlp *); 680 + extern ssize_t wlp_neighborhood_show(struct wlp *, char *); 681 + extern int wlp_wss_setup(struct net_device *, struct wlp_wss *); 682 + extern void wlp_wss_remove(struct wlp_wss *); 683 + extern ssize_t wlp_wss_activate_show(struct wlp_wss *, char *); 684 + extern ssize_t wlp_wss_activate_store(struct wlp_wss *, const char *, size_t); 685 + extern ssize_t wlp_eda_show(struct wlp *, char *); 686 + extern ssize_t wlp_eda_store(struct wlp *, const char *, size_t); 687 + extern ssize_t wlp_uuid_show(struct wlp *, char *); 688 + extern ssize_t wlp_uuid_store(struct wlp *, const char *, size_t); 689 + extern ssize_t wlp_dev_name_show(struct wlp *, char *); 690 + extern ssize_t wlp_dev_name_store(struct wlp *, const char *, size_t); 691 + extern ssize_t wlp_dev_manufacturer_show(struct wlp *, char *); 692 + extern ssize_t wlp_dev_manufacturer_store(struct wlp *, const char *, size_t); 693 + extern ssize_t wlp_dev_model_name_show(struct wlp *, char *); 694 + extern ssize_t wlp_dev_model_name_store(struct wlp *, const char *, size_t); 695 + extern ssize_t wlp_dev_model_nr_show(struct wlp *, char *); 696 + extern ssize_t wlp_dev_model_nr_store(struct wlp *, const char *, size_t); 697 + extern ssize_t wlp_dev_serial_show(struct wlp *, char *); 698 + extern ssize_t wlp_dev_serial_store(struct wlp *, const char *, size_t); 699 + extern ssize_t wlp_dev_prim_category_show(struct wlp *, char *); 700 + extern ssize_t wlp_dev_prim_category_store(struct wlp *, const char *, 701 + size_t); 702 + extern ssize_t wlp_dev_prim_OUI_show(struct wlp *, char *); 703 + extern ssize_t wlp_dev_prim_OUI_store(struct wlp *, const char *, size_t); 704 + extern ssize_t wlp_dev_prim_OUI_sub_show(struct wlp *, char *); 705 + extern ssize_t wlp_dev_prim_OUI_sub_store(struct wlp *, const char *, 706 + size_t); 707 + extern ssize_t wlp_dev_prim_subcat_show(struct wlp *, char *); 708 + extern ssize_t wlp_dev_prim_subcat_store(struct wlp *, const char *, 709 + size_t); 710 + extern int wlp_receive_frame(struct device *, struct wlp *, struct sk_buff *, 711 + struct uwb_dev_addr *); 712 + extern int wlp_prepare_tx_frame(struct device *, struct wlp *, 713 + struct sk_buff *, struct uwb_dev_addr *); 714 + void wlp_reset_all(struct wlp *wlp); 715 + 716 + /** 717 + * Initialize WSS 718 + */ 719 + static inline 720 + void wlp_wss_init(struct wlp_wss *wss) 721 + { 722 + mutex_init(&wss->mutex); 723 + } 724 + 725 + static inline 726 + void wlp_init(struct wlp *wlp) 727 + { 728 + INIT_LIST_HEAD(&wlp->neighbors); 729 + mutex_init(&wlp->mutex); 730 + mutex_init(&wlp->nbmutex); 731 + wlp_wss_init(&wlp->wss); 732 + } 733 + 734 + 735 + #endif /* #ifndef __LINUX__WLP_H_ */