10612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/* 20612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Ultra Wide Band Radio Control 30612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Event Size Tables management 40612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 50612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Copyright (C) 2005-2006 Intel Corporation 60612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 70612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 80612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * This program is free software; you can redistribute it and/or 90612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * modify it under the terms of the GNU General Public License version 100612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2 as published by the Free Software Foundation. 110612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 120612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * This program is distributed in the hope that it will be useful, 130612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * but WITHOUT ANY WARRANTY; without even the implied warranty of 140612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 150612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * GNU General Public License for more details. 160612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 170612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * You should have received a copy of the GNU General Public License 180612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * along with this program; if not, write to the Free Software 190612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 200612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 02110-1301, USA. 210612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 220612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 230612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * FIXME: docs 240612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 250612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Infrastructure, code and data tables for guessing the size of 260612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * events received on the notification endpoints of UWB radio 270612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * controllers. 280612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 290612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * You define a table of events and for each, its size and how to get 300612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * the extra size. 310612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 320612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * ENTRY POINTS: 330612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 340612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * uwb_est_{init/destroy}(): To initialize/release the EST subsystem. 350612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 360612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * uwb_est_[u]register(): To un/register event size tables 370612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * uwb_est_grow() 380612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 390612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * uwb_est_find_size(): Get the size of an event 400612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * uwb_est_get_size() 410612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 420612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez#include <linux/spinlock.h> 435a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 44475c0a6b2cff037ca522d3aff839024ab30ed7ebPaul Gortmaker#include <linux/export.h> 450612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 46bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel#include "uwb-internal.h" 470612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 480612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstruct uwb_est { 490612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez u16 type_event_high; 500612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez u16 vendor, product; 510612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez u8 entries; 520612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez const struct uwb_est_entry *entry; 530612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez}; 540612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 550612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstatic struct uwb_est *uwb_est; 560612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstatic u8 uwb_est_size; 570612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstatic u8 uwb_est_used; 580612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstatic DEFINE_RWLOCK(uwb_est_lock); 590612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 600612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** 610612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * WUSB Standard Event Size Table, HWA-RC interface 620612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 630612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Sizes for events and notifications type 0 (general), high nibble 0. 640612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 650612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstatic 660612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstruct uwb_est_entry uwb_est_00_00xx[] = { 670612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_EVT_IE_RCV] = { 680612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_ie_rcv), 690612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .offset = 1 + offsetof(struct uwb_rc_evt_ie_rcv, wIELength), 700612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 710612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_EVT_BEACON] = { 720612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_beacon), 730612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .offset = 1 + offsetof(struct uwb_rc_evt_beacon, wBeaconInfoLength), 740612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 750612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_EVT_BEACON_SIZE] = { 760612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_beacon_size), 770612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 780612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_EVT_BPOIE_CHANGE] = { 790612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_bpoie_change), 800612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .offset = 1 + offsetof(struct uwb_rc_evt_bpoie_change, 810612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez wBPOIELength), 820612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 830612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_EVT_BP_SLOT_CHANGE] = { 840612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_bp_slot_change), 850612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 860612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_EVT_BP_SWITCH_IE_RCV] = { 870612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_bp_switch_ie_rcv), 880612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .offset = 1 + offsetof(struct uwb_rc_evt_bp_switch_ie_rcv, wIELength), 890612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 900612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_EVT_DEV_ADDR_CONFLICT] = { 910612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_dev_addr_conflict), 920612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 930612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_EVT_DRP_AVAIL] = { 940612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_drp_avail) 950612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 960612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_EVT_DRP] = { 970612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_drp), 980612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .offset = 1 + offsetof(struct uwb_rc_evt_drp, ie_length), 990612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1000612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_EVT_BP_SWITCH_STATUS] = { 1010612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_bp_switch_status), 1020612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1030612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_EVT_CMD_FRAME_RCV] = { 1040612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_cmd_frame_rcv), 1050612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .offset = 1 + offsetof(struct uwb_rc_evt_cmd_frame_rcv, dataLength), 1060612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1070612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_EVT_CHANNEL_CHANGE_IE_RCV] = { 1080612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_channel_change_ie_rcv), 1090612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .offset = 1 + offsetof(struct uwb_rc_evt_channel_change_ie_rcv, wIELength), 1100612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1110612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_CHANNEL_CHANGE] = { 1120612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_confirm), 1130612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1140612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_DEV_ADDR_MGMT] = { 1150612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_dev_addr_mgmt) }, 1160612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_GET_IE] = { 1170612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_get_ie), 1180612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .offset = 1 + offsetof(struct uwb_rc_evt_get_ie, wIELength), 1190612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1200612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_RESET] = { 1210612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_confirm), 1220612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1230612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_SCAN] = { 1240612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_confirm), 1250612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1260612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_SET_BEACON_FILTER] = { 1270612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_confirm), 1280612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1290612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_SET_DRP_IE] = { 1300612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_set_drp_ie), 1310612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1320612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_SET_IE] = { 1330612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_set_ie), 1340612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1350612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_SET_NOTIFICATION_FILTER] = { 1360612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_confirm), 1370612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1380612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_SET_TX_POWER] = { 1390612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_confirm), 1400612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1410612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_SLEEP] = { 1420612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_confirm), 1430612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1440612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_START_BEACON] = { 1450612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_confirm), 1460612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1470612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_STOP_BEACON] = { 1480612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_confirm), 1490612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1500612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_BP_MERGE] = { 1510612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_confirm), 1520612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1530612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_SEND_COMMAND_FRAME] = { 1540612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_confirm), 1550612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1560612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_CMD_SET_ASIE_NOTIF] = { 1570612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_confirm), 1580612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1590612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez}; 1600612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1610612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstatic 1620612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstruct uwb_est_entry uwb_est_01_00xx[] = { 1630612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_DAA_ENERGY_DETECTED] = { 1640612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_daa_energy_detected), 1650612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1660612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_SET_DAA_ENERGY_MASK] = { 1670612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_set_daa_energy_mask), 1680612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1690612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez [UWB_RC_SET_NOTIFICATION_FILTER_EX] = { 1700612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .size = sizeof(struct uwb_rc_evt_set_notification_filter_ex), 1710612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }, 1720612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez}; 1730612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1740612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** 1750612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Initialize the EST subsystem 1760612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 1770612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Register the standard tables also. 1780612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 1790612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * FIXME: tag init 1800612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 1810612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezint uwb_est_create(void) 1820612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 1830612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez int result; 1840612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1850612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est_size = 2; 1860612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est_used = 0; 187a451eaf9c57feaacfd76226a06bd57c4b66a6ab3Thomas Meyer uwb_est = kcalloc(uwb_est_size, sizeof(uwb_est[0]), GFP_KERNEL); 1880612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (uwb_est == NULL) 1890612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return -ENOMEM; 1900612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1910612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez result = uwb_est_register(UWB_RC_CET_GENERAL, 0, 0xffff, 0xffff, 1920612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est_00_00xx, ARRAY_SIZE(uwb_est_00_00xx)); 1930612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (result < 0) 1940612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez goto out; 1950612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez result = uwb_est_register(UWB_RC_CET_EX_TYPE_1, 0, 0xffff, 0xffff, 1960612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est_01_00xx, ARRAY_SIZE(uwb_est_01_00xx)); 1970612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezout: 1980612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return result; 1990612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 2000612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2010612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2020612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** Clean it up */ 2030612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezvoid uwb_est_destroy(void) 2040612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 2050612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez kfree(uwb_est); 2060612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est = NULL; 2070612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est_size = uwb_est_used = 0; 2080612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 2090612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2100612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2110612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** 2120612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Double the capacity of the EST table 2130612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2140612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @returns 0 if ok, < 0 errno no error. 2150612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 2160612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstatic 2170612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezint uwb_est_grow(void) 2180612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 2190612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez size_t actual_size = uwb_est_size * sizeof(uwb_est[0]); 2200612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez void *new = kmalloc(2 * actual_size, GFP_ATOMIC); 2210612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (new == NULL) 2220612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return -ENOMEM; 2230612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez memcpy(new, uwb_est, actual_size); 2240612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez memset(new + actual_size, 0, actual_size); 2250612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez kfree(uwb_est); 2260612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est = new; 2270612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est_size *= 2; 2280612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return 0; 2290612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 2300612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2310612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2320612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** 2330612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Register an event size table 2340612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2350612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Makes room for it if the table is full, and then inserts it in the 2360612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * right position (entries are sorted by type, event_high, vendor and 2370612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * then product). 2380612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2390612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @vendor: vendor code for matching against the device (0x0000 and 2400612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 0xffff mean any); use 0x0000 to force all to match without 2410612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * checking possible vendor specific ones, 0xfffff to match 2420612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * after checking vendor specific ones. 2430612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2440612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @product: product code from that vendor; same matching rules, use 2450612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 0x0000 for not allowing vendor specific matches, 0xffff 2460612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * for allowing. 2470612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2480612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * This arragement just makes the tables sort differenty. Because the 2490612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * table is sorted by growing type-event_high-vendor-product, a zero 2500612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * vendor will match before than a 0x456a vendor, that will match 2510612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * before a 0xfffff vendor. 2520612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2530612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @returns 0 if ok, < 0 errno on error (-ENOENT if not found). 2540612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 2550612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/* FIXME: add bus type to vendor/product code */ 2560612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezint uwb_est_register(u8 type, u8 event_high, u16 vendor, u16 product, 2570612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez const struct uwb_est_entry *entry, size_t entries) 2580612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 2590612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez unsigned long flags; 2600612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez unsigned itr; 2610612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez int result = 0; 2620612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2630612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez write_lock_irqsave(&uwb_est_lock, flags); 2640612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (uwb_est_used == uwb_est_size) { 2650612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez result = uwb_est_grow(); 2660612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (result < 0) 2670612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez goto out; 2680612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 2690612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez /* Find the right spot to insert it in */ 2700612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez for (itr = 0; itr < uwb_est_used; itr++) 2710612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (uwb_est[itr].type_event_high < type 2720612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez && uwb_est[itr].vendor < vendor 2730612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez && uwb_est[itr].product < product) 2740612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez break; 2750612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2760612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez /* Shift others to make room for the new one? */ 2770612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (itr < uwb_est_used) 2780612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez memmove(&uwb_est[itr+1], &uwb_est[itr], uwb_est_used - itr); 2790612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est[itr].type_event_high = type << 8 | event_high; 2800612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est[itr].vendor = vendor; 2810612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est[itr].product = product; 2820612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est[itr].entry = entry; 2830612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est[itr].entries = entries; 2840612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est_used++; 2850612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezout: 2860612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez write_unlock_irqrestore(&uwb_est_lock, flags); 2870612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return result; 2880612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 2890612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-GonzalezEXPORT_SYMBOL_GPL(uwb_est_register); 2900612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2910612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2920612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** 2930612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Unregister an event size table 2940612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2950612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * This just removes the specified entry and moves the ones after it 2960612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * to fill in the gap. This is needed to keep the list sorted; no 2970612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * reallocation is done to reduce the size of the table. 2980612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2990612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * We unregister by all the data we used to register instead of by 3000612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * pointer to the @entry array because we might have used the same 3010612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * table for a bunch of IDs (for example). 3020612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 3030612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @returns 0 if ok, < 0 errno on error (-ENOENT if not found). 3040612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 3050612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezint uwb_est_unregister(u8 type, u8 event_high, u16 vendor, u16 product, 3060612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez const struct uwb_est_entry *entry, size_t entries) 3070612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 3080612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez unsigned long flags; 3090612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez unsigned itr; 3100612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_est est_cmp = { 3110612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .type_event_high = type << 8 | event_high, 3120612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .vendor = vendor, 3130612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .product = product, 3140612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .entry = entry, 3150612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez .entries = entries 3160612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez }; 3170612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez write_lock_irqsave(&uwb_est_lock, flags); 3180612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez for (itr = 0; itr < uwb_est_used; itr++) 3190612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (!memcmp(&uwb_est[itr], &est_cmp, sizeof(est_cmp))) 3200612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez goto found; 3210612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez write_unlock_irqrestore(&uwb_est_lock, flags); 3220612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return -ENOENT; 3230612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 3240612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezfound: 3250612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (itr < uwb_est_used - 1) /* Not last one? move ones above */ 3260612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez memmove(&uwb_est[itr], &uwb_est[itr+1], uwb_est_used - itr - 1); 3270612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_est_used--; 3280612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez write_unlock_irqrestore(&uwb_est_lock, flags); 3290612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return 0; 3300612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 3310612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-GonzalezEXPORT_SYMBOL_GPL(uwb_est_unregister); 3320612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 3330612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 3340612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** 3350612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Get the size of an event from a table 3360612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 3370612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @rceb: pointer to the buffer with the event 3380612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @rceb_size: size of the area pointed to by @rceb in bytes. 3390612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @returns: > 0 Size of the event 3400612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * -ENOSPC An area big enough was not provided to look 3410612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * ahead into the event's guts and guess the size. 3420612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * -EINVAL Unknown event code (wEvent). 3430612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 3440612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * This will look at the received RCEB and guess what is the total 3450612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * size. For variable sized events, it will look further ahead into 3460612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * their length field to see how much data should be read. 3470612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 3480612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Note this size is *not* final--the neh (Notification/Event Handle) 3490612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * might specificy an extra size to add. 3500612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 3510612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstatic 3520612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezssize_t uwb_est_get_size(struct uwb_rc *uwb_rc, struct uwb_est *est, 3530612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez u8 event_low, const struct uwb_rceb *rceb, 3540612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez size_t rceb_size) 3550612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 3560612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez unsigned offset; 3570612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez ssize_t size; 3580612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct device *dev = &uwb_rc->uwb_dev.dev; 3590612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez const struct uwb_est_entry *entry; 3600612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 3610612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez size = -ENOENT; 3620612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (event_low >= est->entries) { /* in range? */ 3638092d7c9789581eea478c40d615a2632c3af17bbDavid Vrabel dev_err(dev, "EST %p 0x%04x/%04x/%04x[%u]: event %u out of range\n", 3648092d7c9789581eea478c40d615a2632c3af17bbDavid Vrabel est, est->type_event_high, est->vendor, est->product, 3658092d7c9789581eea478c40d615a2632c3af17bbDavid Vrabel est->entries, event_low); 3660612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez goto out; 3670612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 3680612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez size = -ENOENT; 3690612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez entry = &est->entry[event_low]; 3700612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (entry->size == 0 && entry->offset == 0) { /* unknown? */ 3718092d7c9789581eea478c40d615a2632c3af17bbDavid Vrabel dev_err(dev, "EST %p 0x%04x/%04x/%04x[%u]: event %u unknown\n", 3728092d7c9789581eea478c40d615a2632c3af17bbDavid Vrabel est, est->type_event_high, est->vendor, est->product, 3738092d7c9789581eea478c40d615a2632c3af17bbDavid Vrabel est->entries, event_low); 3740612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez goto out; 3750612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 3760612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez offset = entry->offset; /* extra fries with that? */ 3770612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (offset == 0) 3780612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez size = entry->size; 3790612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez else { 3800612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez /* Ops, got an extra size field at 'offset'--read it */ 3810612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez const void *ptr = rceb; 3820612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez size_t type_size = 0; 3830612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez offset--; 3840612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez size = -ENOSPC; /* enough data for more? */ 3850612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez switch (entry->type) { 3860612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez case UWB_EST_16: type_size = sizeof(__le16); break; 3870612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez case UWB_EST_8: type_size = sizeof(u8); break; 3880612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez default: BUG(); 3890612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 3909d839477f85438695bd870898ffa77347e61b637Anderson Lizardo if (offset + type_size > rceb_size) { 3918092d7c9789581eea478c40d615a2632c3af17bbDavid Vrabel dev_err(dev, "EST %p 0x%04x/%04x/%04x[%u]: " 3928092d7c9789581eea478c40d615a2632c3af17bbDavid Vrabel "not enough data to read extra size\n", 3938092d7c9789581eea478c40d615a2632c3af17bbDavid Vrabel est, est->type_event_high, est->vendor, 3948092d7c9789581eea478c40d615a2632c3af17bbDavid Vrabel est->product, est->entries); 3950612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez goto out; 3960612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 3970612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez size = entry->size; 3980612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez ptr += offset; 3990612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez switch (entry->type) { 4000612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez case UWB_EST_16: size += le16_to_cpu(*(__le16 *)ptr); break; 4010612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez case UWB_EST_8: size += *(u8 *)ptr; break; 4020612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez default: BUG(); 4030612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 4040612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 4050612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezout: 4060612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return size; 4070612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 4080612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 4090612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 4100612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** 4110612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Guesses the size of a WA event 4120612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 4130612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @rceb: pointer to the buffer with the event 4140612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @rceb_size: size of the area pointed to by @rceb in bytes. 4150612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @returns: > 0 Size of the event 4160612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * -ENOSPC An area big enough was not provided to look 4170612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * ahead into the event's guts and guess the size. 4180612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * -EINVAL Unknown event code (wEvent). 4190612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 4200612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * This will look at the received RCEB and guess what is the total 4210612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * size by checking all the tables registered with 4220612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * uwb_est_register(). For variable sized events, it will look further 4230612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * ahead into their length field to see how much data should be read. 4240612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 4250612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Note this size is *not* final--the neh (Notification/Event Handle) 4260612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * might specificy an extra size to add or replace. 4270612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 4280612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezssize_t uwb_est_find_size(struct uwb_rc *rc, const struct uwb_rceb *rceb, 4290612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez size_t rceb_size) 4300612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 4310612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez /* FIXME: add vendor/product data */ 4320612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez ssize_t size; 4330612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct device *dev = &rc->uwb_dev.dev; 4340612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez unsigned long flags; 4350612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez unsigned itr; 4360612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez u16 type_event_high, event; 4370612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 4380612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez read_lock_irqsave(&uwb_est_lock, flags); 4390612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez size = -ENOSPC; 4400612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (rceb_size < sizeof(*rceb)) 4410612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez goto out; 4420612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez event = le16_to_cpu(rceb->wEvent); 4430612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez type_event_high = rceb->bEventType << 8 | (event & 0xff00) >> 8; 4440612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez for (itr = 0; itr < uwb_est_used; itr++) { 4450612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (uwb_est[itr].type_event_high != type_event_high) 4460612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez continue; 4470612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez size = uwb_est_get_size(rc, &uwb_est[itr], 4480612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez event & 0x00ff, rceb, rceb_size); 4490612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez /* try more tables that might handle the same type */ 4500612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (size != -ENOENT) 4510612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez goto out; 4520612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 453021ad8694039545d69c19ca9bddc6f89b7469a61Andy Shevchenko dev_dbg(dev, 454021ad8694039545d69c19ca9bddc6f89b7469a61Andy Shevchenko "event 0x%02x/%04x/%02x: no handlers available; RCEB %4ph\n", 4558092d7c9789581eea478c40d615a2632c3af17bbDavid Vrabel (unsigned) rceb->bEventType, 4568092d7c9789581eea478c40d615a2632c3af17bbDavid Vrabel (unsigned) le16_to_cpu(rceb->wEvent), 4578092d7c9789581eea478c40d615a2632c3af17bbDavid Vrabel (unsigned) rceb->bEventContext, 458021ad8694039545d69c19ca9bddc6f89b7469a61Andy Shevchenko rceb); 4590612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez size = -ENOENT; 4600612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezout: 4610612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez read_unlock_irqrestore(&uwb_est_lock, flags); 4620612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return size; 4630612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 4640612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-GonzalezEXPORT_SYMBOL_GPL(uwb_est_find_size); 465