1 // SPDX-License-Identifier: GPL-2.0+ 2 /* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ 3 4 #include <linux/nl80211.h> 5 6 #include "qlink_util.h" 7 8 u16 qlink_iface_type_to_nl_mask(u16 qlink_type) 9 { 10 u16 result = 0; 11 12 switch (qlink_type) { 13 case QLINK_IFTYPE_AP: 14 result |= BIT(NL80211_IFTYPE_AP); 15 break; 16 case QLINK_IFTYPE_STATION: 17 result |= BIT(NL80211_IFTYPE_STATION); 18 break; 19 case QLINK_IFTYPE_ADHOC: 20 result |= BIT(NL80211_IFTYPE_ADHOC); 21 break; 22 case QLINK_IFTYPE_MONITOR: 23 result |= BIT(NL80211_IFTYPE_MONITOR); 24 break; 25 case QLINK_IFTYPE_WDS: 26 result |= BIT(NL80211_IFTYPE_WDS); 27 break; 28 case QLINK_IFTYPE_AP_VLAN: 29 result |= BIT(NL80211_IFTYPE_AP_VLAN); 30 break; 31 } 32 33 return result; 34 } 35 36 u8 qlink_chan_width_mask_to_nl(u16 qlink_mask) 37 { 38 u8 result = 0; 39 40 if (qlink_mask & BIT(QLINK_CHAN_WIDTH_5)) 41 result |= BIT(NL80211_CHAN_WIDTH_5); 42 43 if (qlink_mask & BIT(QLINK_CHAN_WIDTH_10)) 44 result |= BIT(NL80211_CHAN_WIDTH_10); 45 46 if (qlink_mask & BIT(QLINK_CHAN_WIDTH_20_NOHT)) 47 result |= BIT(NL80211_CHAN_WIDTH_20_NOHT); 48 49 if (qlink_mask & BIT(QLINK_CHAN_WIDTH_20)) 50 result |= BIT(NL80211_CHAN_WIDTH_20); 51 52 if (qlink_mask & BIT(QLINK_CHAN_WIDTH_40)) 53 result |= BIT(NL80211_CHAN_WIDTH_40); 54 55 if (qlink_mask & BIT(QLINK_CHAN_WIDTH_80)) 56 result |= BIT(NL80211_CHAN_WIDTH_80); 57 58 if (qlink_mask & BIT(QLINK_CHAN_WIDTH_80P80)) 59 result |= BIT(NL80211_CHAN_WIDTH_80P80); 60 61 if (qlink_mask & BIT(QLINK_CHAN_WIDTH_160)) 62 result |= BIT(NL80211_CHAN_WIDTH_160); 63 64 return result; 65 } 66 67 static enum nl80211_chan_width qlink_chanwidth_to_nl(u8 qlw) 68 { 69 switch (qlw) { 70 case QLINK_CHAN_WIDTH_20_NOHT: 71 return NL80211_CHAN_WIDTH_20_NOHT; 72 case QLINK_CHAN_WIDTH_20: 73 return NL80211_CHAN_WIDTH_20; 74 case QLINK_CHAN_WIDTH_40: 75 return NL80211_CHAN_WIDTH_40; 76 case QLINK_CHAN_WIDTH_80: 77 return NL80211_CHAN_WIDTH_80; 78 case QLINK_CHAN_WIDTH_80P80: 79 return NL80211_CHAN_WIDTH_80P80; 80 case QLINK_CHAN_WIDTH_160: 81 return NL80211_CHAN_WIDTH_160; 82 case QLINK_CHAN_WIDTH_5: 83 return NL80211_CHAN_WIDTH_5; 84 case QLINK_CHAN_WIDTH_10: 85 return NL80211_CHAN_WIDTH_10; 86 default: 87 return -1; 88 } 89 } 90 91 static u8 qlink_chanwidth_nl_to_qlink(enum nl80211_chan_width nlwidth) 92 { 93 switch (nlwidth) { 94 case NL80211_CHAN_WIDTH_20_NOHT: 95 return QLINK_CHAN_WIDTH_20_NOHT; 96 case NL80211_CHAN_WIDTH_20: 97 return QLINK_CHAN_WIDTH_20; 98 case NL80211_CHAN_WIDTH_40: 99 return QLINK_CHAN_WIDTH_40; 100 case NL80211_CHAN_WIDTH_80: 101 return QLINK_CHAN_WIDTH_80; 102 case NL80211_CHAN_WIDTH_80P80: 103 return QLINK_CHAN_WIDTH_80P80; 104 case NL80211_CHAN_WIDTH_160: 105 return QLINK_CHAN_WIDTH_160; 106 case NL80211_CHAN_WIDTH_5: 107 return QLINK_CHAN_WIDTH_5; 108 case NL80211_CHAN_WIDTH_10: 109 return QLINK_CHAN_WIDTH_10; 110 default: 111 return -1; 112 } 113 } 114 115 void qlink_chandef_q2cfg(struct wiphy *wiphy, 116 const struct qlink_chandef *qch, 117 struct cfg80211_chan_def *chdef) 118 { 119 struct ieee80211_channel *chan; 120 121 chan = ieee80211_get_channel(wiphy, le16_to_cpu(qch->chan.center_freq)); 122 123 chdef->chan = chan; 124 chdef->center_freq1 = le16_to_cpu(qch->center_freq1); 125 chdef->center_freq2 = le16_to_cpu(qch->center_freq2); 126 chdef->width = qlink_chanwidth_to_nl(qch->width); 127 } 128 129 void qlink_chandef_cfg2q(const struct cfg80211_chan_def *chdef, 130 struct qlink_chandef *qch) 131 { 132 struct ieee80211_channel *chan = chdef->chan; 133 134 qch->chan.hw_value = cpu_to_le16(chan->hw_value); 135 qch->chan.center_freq = cpu_to_le16(chan->center_freq); 136 qch->chan.flags = cpu_to_le32(chan->flags); 137 138 qch->center_freq1 = cpu_to_le16(chdef->center_freq1); 139 qch->center_freq2 = cpu_to_le16(chdef->center_freq2); 140 qch->width = qlink_chanwidth_nl_to_qlink(chdef->width); 141 } 142 143 enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val) 144 { 145 switch (nl_val) { 146 case NL80211_HIDDEN_SSID_ZERO_LEN: 147 return QLINK_HIDDEN_SSID_ZERO_LEN; 148 case NL80211_HIDDEN_SSID_ZERO_CONTENTS: 149 return QLINK_HIDDEN_SSID_ZERO_CONTENTS; 150 case NL80211_HIDDEN_SSID_NOT_IN_USE: 151 default: 152 return QLINK_HIDDEN_SSID_NOT_IN_USE; 153 } 154 } 155 156 bool qtnf_utils_is_bit_set(const u8 *arr, unsigned int bit, 157 unsigned int arr_max_len) 158 { 159 unsigned int idx = bit / BITS_PER_BYTE; 160 u8 mask = 1 << (bit - (idx * BITS_PER_BYTE)); 161 162 if (idx >= arr_max_len) 163 return false; 164 165 return arr[idx] & mask; 166 } 167 168 void qlink_acl_data_cfg2q(const struct cfg80211_acl_data *acl, 169 struct qlink_acl_data *qacl) 170 { 171 switch (acl->acl_policy) { 172 case NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: 173 qacl->policy = 174 cpu_to_le32(QLINK_ACL_POLICY_ACCEPT_UNLESS_LISTED); 175 break; 176 case NL80211_ACL_POLICY_DENY_UNLESS_LISTED: 177 qacl->policy = cpu_to_le32(QLINK_ACL_POLICY_DENY_UNLESS_LISTED); 178 break; 179 } 180 181 qacl->num_entries = cpu_to_le32(acl->n_acl_entries); 182 memcpy(qacl->mac_addrs, acl->mac_addrs, 183 acl->n_acl_entries * sizeof(*qacl->mac_addrs)); 184 } 185