122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/* 222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * Ultra Wide Band 322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * Address management 422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * Copyright (C) 2005-2006 Intel Corporation 622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * This program is free software; you can redistribute it and/or 922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * modify it under the terms of the GNU General Public License version 1022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 2 as published by the Free Software Foundation. 1122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 1222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * This program is distributed in the hope that it will be useful, 1322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * but WITHOUT ANY WARRANTY; without even the implied warranty of 1422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * GNU General Public License for more details. 1622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 1722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * You should have received a copy of the GNU General Public License 1822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * along with this program; if not, write to the Free Software 1922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 02110-1301, USA. 2122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 2222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 2322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * FIXME: docs 2422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez */ 2522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 265a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 2722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez#include <linux/errno.h> 2822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez#include <linux/module.h> 2922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez#include <linux/device.h> 3022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez#include <linux/random.h> 3122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez#include <linux/etherdevice.h> 32a01777ecf227de735d7e525ecda48fe74b838a17David Vrabel 3322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez#include "uwb-internal.h" 3422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 3522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 3622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/** Device Address Management command */ 3722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezstruct uwb_rc_cmd_dev_addr_mgmt { 3822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_rccb rccb; 3922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez u8 bmOperationType; 4022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez u8 baAddr[6]; 4122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} __attribute__((packed)); 4222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 4322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 4422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/** 4522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * Low level command for setting/getting UWB radio's addresses 4622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 4722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @hwarc: HWA Radio Control interface instance 4822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @bmOperationType: 4922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * Set/get, MAC/DEV (see WUSB1.0[8.6.2.2]) 5022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @baAddr: address buffer--assumed to have enough data to hold 5122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * the address type requested. 5222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @reply: Pointer to reply buffer (can be stack allocated) 5322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @returns: 0 if ok, < 0 errno code on error. 5422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 5522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @cmd has to be allocated because USB cannot grok USB or vmalloc 5622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * buffers depending on your combination of host architecture. 5722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez */ 5822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezstatic 5922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezint uwb_rc_dev_addr_mgmt(struct uwb_rc *rc, 6022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez u8 bmOperationType, const u8 *baAddr, 6122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_rc_evt_dev_addr_mgmt *reply) 6222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez{ 6322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez int result; 6422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_rc_cmd_dev_addr_mgmt *cmd; 6522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 6622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = -ENOMEM; 6722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 6822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez if (cmd == NULL) 6922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez goto error_kzalloc; 7022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez cmd->rccb.bCommandType = UWB_RC_CET_GENERAL; 7122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez cmd->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_DEV_ADDR_MGMT); 7222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez cmd->bmOperationType = bmOperationType; 7322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez if (baAddr) { 7422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez size_t size = 0; 7522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez switch (bmOperationType >> 1) { 7622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez case 0: size = 2; break; 7722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez case 1: size = 6; break; 7822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez default: BUG(); 7922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez } 8022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez memcpy(cmd->baAddr, baAddr, size); 8122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez } 8222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez reply->rceb.bEventType = UWB_RC_CET_GENERAL; 8322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez reply->rceb.wEvent = UWB_RC_CMD_DEV_ADDR_MGMT; 8422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = uwb_rc_cmd(rc, "DEV-ADDR-MGMT", 8522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez &cmd->rccb, sizeof(*cmd), 8622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez &reply->rceb, sizeof(*reply)); 8722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez if (result < 0) 8822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez goto error_cmd; 8922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez if (result < sizeof(*reply)) { 9022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez dev_err(&rc->uwb_dev.dev, 9122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez "DEV-ADDR-MGMT: not enough data replied: " 9222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez "%d vs %zu bytes needed\n", result, sizeof(*reply)); 9322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = -ENOMSG; 9422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez } else if (reply->bResultCode != UWB_RC_RES_SUCCESS) { 9522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez dev_err(&rc->uwb_dev.dev, 9622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez "DEV-ADDR-MGMT: command execution failed: %s (%d)\n", 9722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez uwb_rc_strerror(reply->bResultCode), 9822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez reply->bResultCode); 9922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = -EIO; 10022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez } else 10122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = 0; 10222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezerror_cmd: 10322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez kfree(cmd); 10422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezerror_kzalloc: 10522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return result; 10622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 10722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 10822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 10922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/** 11022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * Set the UWB RC MAC or device address. 11122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 11222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @rc: UWB Radio Controller 11322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @_addr: Pointer to address to write [assumed to be either a 11422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 'struct uwb_mac_addr *' or a 'struct uwb_dev_addr *']. 11522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @type: Type of address to set (UWB_ADDR_DEV or UWB_ADDR_MAC). 11622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @returns: 0 if ok, < 0 errno code on error. 11722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 11822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * Some anal retentivity here: even if both 'struct 11922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * uwb_{dev,mac}_addr' have the actual byte array in the same offset 12022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * and I could just pass _addr to hwarc_cmd_dev_addr_mgmt(), I prefer 12122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * to use some syntatic sugar in case someday we decide to change the 12222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * format of the structs. The compiler will optimize it out anyway. 12322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez */ 12422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezstatic int uwb_rc_addr_set(struct uwb_rc *rc, 12522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez const void *_addr, enum uwb_addr_type type) 12622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez{ 12722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez int result; 12822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez u8 bmOperationType = 0x1; /* Set address */ 12922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez const struct uwb_dev_addr *dev_addr = _addr; 13022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez const struct uwb_mac_addr *mac_addr = _addr; 13122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_rc_evt_dev_addr_mgmt reply; 13222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez const u8 *baAddr; 13322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 13422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = -EINVAL; 13522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez switch (type) { 13622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez case UWB_ADDR_DEV: 13722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez baAddr = dev_addr->data; 13822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez break; 13922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez case UWB_ADDR_MAC: 14022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez baAddr = mac_addr->data; 14122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez bmOperationType |= 0x2; 14222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez break; 14322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez default: 14422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return result; 14522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez } 14622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return uwb_rc_dev_addr_mgmt(rc, bmOperationType, baAddr, &reply); 14722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 14822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 14922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 15022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/** 15122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * Get the UWB radio's MAC or device address. 15222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 15322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @rc: UWB Radio Controller 15422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @_addr: Where to write the address data [assumed to be either a 15522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 'struct uwb_mac_addr *' or a 'struct uwb_dev_addr *']. 15622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @type: Type of address to get (UWB_ADDR_DEV or UWB_ADDR_MAC). 15722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @returns: 0 if ok (and *_addr set), < 0 errno code on error. 15822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 15922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * See comment in uwb_rc_addr_set() about anal retentivity in the 16022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * type handling of the address variables. 16122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez */ 16222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezstatic int uwb_rc_addr_get(struct uwb_rc *rc, 16322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez void *_addr, enum uwb_addr_type type) 16422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez{ 16522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez int result; 16622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez u8 bmOperationType = 0x0; /* Get address */ 16722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_rc_evt_dev_addr_mgmt evt; 16822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_dev_addr *dev_addr = _addr; 16922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_mac_addr *mac_addr = _addr; 17022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez u8 *baAddr; 17122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 17222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = -EINVAL; 17322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez switch (type) { 17422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez case UWB_ADDR_DEV: 17522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez baAddr = dev_addr->data; 17622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez break; 17722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez case UWB_ADDR_MAC: 17822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez bmOperationType |= 0x2; 17922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez baAddr = mac_addr->data; 18022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez break; 18122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez default: 18222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return result; 18322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez } 18422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = uwb_rc_dev_addr_mgmt(rc, bmOperationType, baAddr, &evt); 18522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez if (result == 0) 18622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez switch (type) { 18722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez case UWB_ADDR_DEV: 18822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez memcpy(&dev_addr->data, evt.baAddr, 18922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez sizeof(dev_addr->data)); 19022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez break; 19122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez case UWB_ADDR_MAC: 19222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez memcpy(&mac_addr->data, evt.baAddr, 19322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez sizeof(mac_addr->data)); 19422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez break; 19522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez default: /* shut gcc up */ 19622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez BUG(); 19722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez } 19822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return result; 19922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 20022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 20122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 20222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/** Get @rc's MAC address to @addr */ 20322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezint uwb_rc_mac_addr_get(struct uwb_rc *rc, 20422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_mac_addr *addr) { 20522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return uwb_rc_addr_get(rc, addr, UWB_ADDR_MAC); 20622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 20722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-GonzalezEXPORT_SYMBOL_GPL(uwb_rc_mac_addr_get); 20822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 20922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 21022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/** Get @rc's device address to @addr */ 21122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezint uwb_rc_dev_addr_get(struct uwb_rc *rc, 21222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_dev_addr *addr) { 21322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return uwb_rc_addr_get(rc, addr, UWB_ADDR_DEV); 21422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 21522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-GonzalezEXPORT_SYMBOL_GPL(uwb_rc_dev_addr_get); 21622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 21722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 21822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/** Set @rc's address to @addr */ 21922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezint uwb_rc_mac_addr_set(struct uwb_rc *rc, 22022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez const struct uwb_mac_addr *addr) 22122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez{ 22222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez int result = -EINVAL; 22322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez mutex_lock(&rc->uwb_dev.mutex); 22422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = uwb_rc_addr_set(rc, addr, UWB_ADDR_MAC); 22522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez mutex_unlock(&rc->uwb_dev.mutex); 22622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return result; 22722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 22822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 22922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 23022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/** Set @rc's address to @addr */ 23122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezint uwb_rc_dev_addr_set(struct uwb_rc *rc, 23222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez const struct uwb_dev_addr *addr) 23322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez{ 23422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez int result = -EINVAL; 23522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez mutex_lock(&rc->uwb_dev.mutex); 23622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = uwb_rc_addr_set(rc, addr, UWB_ADDR_DEV); 23722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez rc->uwb_dev.dev_addr = *addr; 23822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez mutex_unlock(&rc->uwb_dev.mutex); 23922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return result; 24022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 24122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 24222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/* Returns !0 if given address is already assigned to device. */ 24322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezint __uwb_mac_addr_assigned_check(struct device *dev, void *_addr) 24422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez{ 24522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 24622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_mac_addr *addr = _addr; 24722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 24822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez if (!uwb_mac_addr_cmp(addr, &uwb_dev->mac_addr)) 24922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return !0; 25022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return 0; 25122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 25222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 25322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/* Returns !0 if given address is already assigned to device. */ 25422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezint __uwb_dev_addr_assigned_check(struct device *dev, void *_addr) 25522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez{ 25622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 25722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_dev_addr *addr = _addr; 25822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez if (!uwb_dev_addr_cmp(addr, &uwb_dev->dev_addr)) 25922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return !0; 26022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return 0; 26122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 26222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 26322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/** 26422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * uwb_dev_addr_assign - assigned a generated DevAddr to a radio controller 26522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @rc: the (local) radio controller device requiring a new DevAddr 26622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 26722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * A new DevAddr is required when: 26822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * - first setting up a radio controller 26922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * - if the hardware reports a DevAddr conflict 27022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 27122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * The DevAddr is randomly generated in the generated DevAddr range 27222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * [0x100, 0xfeff]. The number of devices in a beacon group is limited 27322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * by mMaxBPLength (96) so this address space will never be exhausted. 27422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 27522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * [ECMA-368] 17.1.1, 17.16. 27622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez */ 27722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezint uwb_rc_dev_addr_assign(struct uwb_rc *rc) 27822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez{ 27922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_dev_addr new_addr; 28022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 28122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez do { 28222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez get_random_bytes(new_addr.data, sizeof(new_addr.data)); 28322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez } while (new_addr.data[0] == 0x00 || new_addr.data[0] == 0xff 28422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez || __uwb_dev_addr_assigned(rc, &new_addr)); 28522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 28622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return uwb_rc_dev_addr_set(rc, &new_addr); 28722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 28822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 28922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/** 29022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * uwbd_evt_handle_rc_dev_addr_conflict - handle a DEV_ADDR_CONFLICT event 29122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * @evt: the DEV_ADDR_CONFLICT notification from the radio controller 29222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 29322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * A new (non-conflicting) DevAddr is assigned to the radio controller. 29422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * 29522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * [ECMA-368] 17.1.1.1. 29622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez */ 29722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezint uwbd_evt_handle_rc_dev_addr_conflict(struct uwb_event *evt) 29822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez{ 29922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_rc *rc = evt->rc; 30022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 30122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return uwb_rc_dev_addr_assign(rc); 30222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 30322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 30422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/* 30522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * Print the 48-bit EUI MAC address of the radio controller when 30622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * reading /sys/class/uwb_rc/XX/mac_address 30722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez */ 30822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezstatic ssize_t uwb_rc_mac_addr_show(struct device *dev, 30922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct device_attribute *attr, char *buf) 31022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez{ 31122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 31222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_rc *rc = uwb_dev->rc; 31322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_mac_addr addr; 31422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez ssize_t result; 31522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 31622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez mutex_lock(&rc->uwb_dev.mutex); 31722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = uwb_rc_addr_get(rc, &addr, UWB_ADDR_MAC); 31822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez mutex_unlock(&rc->uwb_dev.mutex); 31922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez if (result >= 0) { 32022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = uwb_mac_addr_print(buf, UWB_ADDR_STRSIZE, &addr); 32122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez buf[result++] = '\n'; 32222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez } 32322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return result; 32422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 32522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 32622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/* 32722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * Parse a 48 bit address written to /sys/class/uwb_rc/XX/mac_address 32822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez * and if correct, set it. 32922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez */ 33022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezstatic ssize_t uwb_rc_mac_addr_store(struct device *dev, 33122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct device_attribute *attr, 33222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez const char *buf, size_t size) 33322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez{ 33422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 33522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_rc *rc = uwb_dev->rc; 33622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez struct uwb_mac_addr addr; 33722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez ssize_t result; 33822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 33922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\n", 34022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez &addr.data[0], &addr.data[1], &addr.data[2], 34122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez &addr.data[3], &addr.data[4], &addr.data[5]); 34222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez if (result != 6) { 34322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = -EINVAL; 34422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez goto out; 34522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez } 34622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez if (is_multicast_ether_addr(addr.data)) { 34722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez dev_err(&rc->uwb_dev.dev, "refusing to set multicast " 34822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez "MAC address %s\n", buf); 34922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = -EINVAL; 35022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez goto out; 35122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez } 35222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = uwb_rc_mac_addr_set(rc, &addr); 35322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez if (result == 0) 35422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez rc->uwb_dev.mac_addr = addr; 35522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezout: 35622d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return result < 0 ? result : size; 35722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 35822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-GonzalezDEVICE_ATTR(mac_address, S_IRUGO | S_IWUSR, uwb_rc_mac_addr_show, uwb_rc_mac_addr_store); 35922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez 36022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez/** Print @addr to @buf, @return bytes written */ 36122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalezsize_t __uwb_addr_print(char *buf, size_t buf_size, const unsigned char *addr, 36222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez int type) 36322d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez{ 36422d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez size_t result; 36522d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez if (type) 366d3134c3b1a5d2a9dca2ddacacb5d08fad7941d8cAndy Shevchenko result = scnprintf(buf, buf_size, "%pM", addr); 36722d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez else 36822d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez result = scnprintf(buf, buf_size, "%02x:%02x", 36922d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez addr[1], addr[0]); 37022d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez return result; 37122d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-Gonzalez} 37222d203ecef9b0cc1fa8d8f64c935b451ca7d1022Inaky Perez-GonzalezEXPORT_SYMBOL_GPL(__uwb_addr_print); 373