1942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg#include <errno.h> 2942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg 3942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg#include "nl80211.h" 4942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg#include "iw.h" 5942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg 6942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg 7118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzicstatic int parse_vht_chunk(const char *arg, __u8 *nss, __u16 *mcs) 8118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic{ 9118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic int count, i; 10118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic unsigned int inss, mcs_start, mcs_end, tab[10]; 11118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 12118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic *nss = 0; *mcs = 0; 13118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 14118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (strchr(arg, '-')) { 15118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic /* Format: NSS:MCS_START-MCS_END */ 16118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic count = sscanf(arg, "%u:%u-%u", &inss, &mcs_start, &mcs_end); 17118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 18118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (count != 3) 19118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return 0; 20118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 21118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (inss < 1 || inss > NL80211_VHT_NSS_MAX) 22118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return 0; 23118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 24118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (mcs_start > mcs_end) 25118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return 0; 26118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 27118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (mcs_start > 9 || mcs_end > 9) 28118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return 0; 29118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 30118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic *nss = inss; 31118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic for (i = mcs_start; i <= mcs_end; i++) 32118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic *mcs |= 1 << i; 33118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 34118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic } else { 35118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic /* Format: NSS:MCSx,MCSy,... */ 36118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic count = sscanf(arg, "%u:%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", &inss, 37118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic &tab[0], &tab[1], &tab[2], &tab[3], &tab[4], &tab[5], 38118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic &tab[6], &tab[7], &tab[8], &tab[9]); 39118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 40118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (count < 2) 41118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return 0; 42118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 43118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (inss < 1 || inss > NL80211_VHT_NSS_MAX) 44118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return 0; 45118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 46118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic *nss = inss; 47118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic for (i = 0; i < count - 1; i++) { 48118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (tab[i] > 9) 49118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return 0; 50118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic *mcs |= 1 << tab[i]; 51118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic } 52118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic } 53118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 54118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return 1; 55118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic} 56118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 57118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzicstatic int setup_vht(struct nl80211_txrate_vht *txrate_vht, 58118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic int argc, char **argv) 59118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic{ 60118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic __u8 nss; 61118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic __u16 mcs; 62118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic int i; 63118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 64118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic memset(txrate_vht, 0, sizeof(*txrate_vht)); 65118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 66118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic for (i = 0; i < argc; i++) { 67118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if(!parse_vht_chunk(argv[i], &nss, &mcs)) 68118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return 0; 69118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 70118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic nss--; 71118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic txrate_vht->mcs[nss] |= mcs; 72118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic } 73118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 74118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return 1; 75118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic} 76118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 77118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic#define VHT_ARGC_MAX 100 78118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 79942b5cd86434724ac31ff3847baf3d1365b75022Johannes Bergstatic int handle_bitrates(struct nl80211_state *state, 80942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg struct nl_cb *cb, 81942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg struct nl_msg *msg, 8205514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg int argc, char **argv, 8305514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg enum id_input id) 84942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg{ 85942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg struct nlattr *nl_rates, *nl_band; 86942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg int i; 87942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg bool have_legacy_24 = false, have_legacy_5 = false; 88942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg uint8_t legacy_24[32], legacy_5[32]; 89942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg int n_legacy_24 = 0, n_legacy_5 = 0; 90942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg uint8_t *legacy = NULL; 91942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg int *n_legacy = NULL; 92118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic bool have_ht_mcs_24 = false, have_ht_mcs_5 = false; 93118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic bool have_vht_mcs_24 = false, have_vht_mcs_5 = false; 94118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic uint8_t ht_mcs_24[77], ht_mcs_5[77]; 95118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic int n_ht_mcs_24 = 0, n_ht_mcs_5 = 0; 96118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic struct nl80211_txrate_vht txrate_vht_24 = {}; 97118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic struct nl80211_txrate_vht txrate_vht_5 = {}; 98942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg uint8_t *mcs = NULL; 99942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg int *n_mcs = NULL; 100118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic char *vht_argv_5[VHT_ARGC_MAX] = {}; char *vht_argv_24[VHT_ARGC_MAX] = {}; 101118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic char **vht_argv = NULL; 102118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic int vht_argc_5 = 0; int vht_argc_24 = 0; 103118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic int *vht_argc = NULL; 104eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic int sgi_24 = 0, sgi_5 = 0, lgi_24 = 0, lgi_5 = 0; 105118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 106942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg enum { 107942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg S_NONE, 108942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg S_LEGACY, 109118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic S_HT, 110118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic S_VHT, 111eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic S_GI, 112942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg } parser_state = S_NONE; 113942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg 114942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg for (i = 0; i < argc; i++) { 115942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg char *end; 116bd0f464b76491e46a08e20a2f149092a5e4b335cJohannes Berg double tmpd; 117942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg long tmpl; 118942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg 119942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg if (strcmp(argv[i], "legacy-2.4") == 0) { 120942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg if (have_legacy_24) 121942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg return 1; 122942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg parser_state = S_LEGACY; 123942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg legacy = legacy_24; 124942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg n_legacy = &n_legacy_24; 125942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg have_legacy_24 = true; 126942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg } else if (strcmp(argv[i], "legacy-5") == 0) { 127942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg if (have_legacy_5) 128942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg return 1; 129942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg parser_state = S_LEGACY; 130942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg legacy = legacy_5; 131942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg n_legacy = &n_legacy_5; 132942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg have_legacy_5 = true; 133942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg } 134118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic else if (strcmp(argv[i], "ht-mcs-2.4") == 0) { 135118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (have_ht_mcs_24) 136118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return 1; 137118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic parser_state = S_HT; 138118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic mcs = ht_mcs_24; 139118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic n_mcs = &n_ht_mcs_24; 140118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic have_ht_mcs_24 = true; 141118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic } else if (strcmp(argv[i], "ht-mcs-5") == 0) { 142118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (have_ht_mcs_5) 143118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return 1; 144118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic parser_state = S_HT; 145118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic mcs = ht_mcs_5; 146118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic n_mcs = &n_ht_mcs_5; 147118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic have_ht_mcs_5 = true; 148118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic } else if (strcmp(argv[i], "vht-mcs-2.4") == 0) { 149118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (have_vht_mcs_24) 150942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg return 1; 151118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic parser_state = S_VHT; 152118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic vht_argv = vht_argv_24; 153118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic vht_argc = &vht_argc_24; 154118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic have_vht_mcs_24 = true; 155118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic } else if (strcmp(argv[i], "vht-mcs-5") == 0) { 156118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (have_vht_mcs_5) 157942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg return 1; 158118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic parser_state = S_VHT; 159118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic vht_argv = vht_argv_5; 160118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic vht_argc = &vht_argc_5; 161118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic have_vht_mcs_5 = true; 162eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic } else if (strcmp(argv[i], "sgi-2.4") == 0) { 163eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic sgi_24 = 1; 164eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic parser_state = S_GI; 165eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic } else if (strcmp(argv[i], "sgi-5") == 0) { 166eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic sgi_5 = 1; 167eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic parser_state = S_GI; 168eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic } else if (strcmp(argv[i], "lgi-2.4") == 0) { 169eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic lgi_24 = 1; 170eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic parser_state = S_GI; 171eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic } else if (strcmp(argv[i], "lgi-5") == 0) { 172eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic lgi_5 = 1; 173eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic parser_state = S_GI; 174eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic } else switch (parser_state) { 175942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg case S_LEGACY: 176bd0f464b76491e46a08e20a2f149092a5e4b335cJohannes Berg tmpd = strtod(argv[i], &end); 177942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg if (*end != '\0') 178942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg return 1; 179bd0f464b76491e46a08e20a2f149092a5e4b335cJohannes Berg if (tmpd < 1 || tmpd > 255 * 2) 180942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg return 1; 181bd0f464b76491e46a08e20a2f149092a5e4b335cJohannes Berg legacy[(*n_legacy)++] = tmpd * 2; 182942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg break; 183118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic case S_HT: 184942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg tmpl = strtol(argv[i], &end, 0); 185942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg if (*end != '\0') 186942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg return 1; 187942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg if (tmpl < 0 || tmpl > 255) 188942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg return 1; 189942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg mcs[(*n_mcs)++] = tmpl; 190942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg break; 191118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic case S_VHT: 192118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (*vht_argc >= VHT_ARGC_MAX) 193118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return 1; 194118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic vht_argv[(*vht_argc)++] = argv[i]; 195118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic break; 196eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic case S_GI: 197eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic break; 198942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg default: 199942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg return 1; 200942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg } 201942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg } 202942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg 203118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (have_vht_mcs_24) 204118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if(!setup_vht(&txrate_vht_24, vht_argc_24, vht_argv_24)) 205118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return -EINVAL; 206118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 207118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (have_vht_mcs_5) 208118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if(!setup_vht(&txrate_vht_5, vht_argc_5, vht_argv_5)) 209118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic return -EINVAL; 210118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic 211eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic if (sgi_5 && lgi_5) 212eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic return 1; 213eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic 214eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic if (sgi_24 && lgi_24) 215eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic return 1; 216eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic 217942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg nl_rates = nla_nest_start(msg, NL80211_ATTR_TX_RATES); 218942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg if (!nl_rates) 219942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg goto nla_put_failure; 220942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg 221eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic if (have_legacy_24 || have_ht_mcs_24 || have_vht_mcs_24 || sgi_24 || lgi_24) { 222942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg nl_band = nla_nest_start(msg, NL80211_BAND_2GHZ); 223942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg if (!nl_band) 224942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg goto nla_put_failure; 225942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg if (have_legacy_24) 226942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg nla_put(msg, NL80211_TXRATE_LEGACY, n_legacy_24, legacy_24); 227118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (have_ht_mcs_24) 228118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic nla_put(msg, NL80211_TXRATE_HT, n_ht_mcs_24, ht_mcs_24); 229118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (have_vht_mcs_24) 230118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic nla_put(msg, NL80211_TXRATE_VHT, sizeof(txrate_vht_24), &txrate_vht_24); 231eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic if (sgi_24) 232eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic nla_put_u8(msg, NL80211_TXRATE_GI, NL80211_TXRATE_FORCE_SGI); 233eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic if (lgi_24) 234eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic nla_put_u8(msg, NL80211_TXRATE_GI, NL80211_TXRATE_FORCE_LGI); 235942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg nla_nest_end(msg, nl_band); 236942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg } 237942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg 238eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic if (have_legacy_5 || have_ht_mcs_5 || have_vht_mcs_5 || sgi_5 || lgi_5) { 239942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg nl_band = nla_nest_start(msg, NL80211_BAND_5GHZ); 240942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg if (!nl_band) 241942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg goto nla_put_failure; 242942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg if (have_legacy_5) 243942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg nla_put(msg, NL80211_TXRATE_LEGACY, n_legacy_5, legacy_5); 244118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (have_ht_mcs_5) 245118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic nla_put(msg, NL80211_TXRATE_HT, n_ht_mcs_5, ht_mcs_5); 246118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic if (have_vht_mcs_5) 247118976b2e36a9b9639657ac61aeff95770aa428aJanusz Dziedzic nla_put(msg, NL80211_TXRATE_VHT, sizeof(txrate_vht_5), &txrate_vht_5); 248eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic if (sgi_5) 249eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic nla_put_u8(msg, NL80211_TXRATE_GI, NL80211_TXRATE_FORCE_SGI); 250eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic if (lgi_5) 251eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic nla_put_u8(msg, NL80211_TXRATE_GI, NL80211_TXRATE_FORCE_LGI); 252942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg nla_nest_end(msg, nl_band); 253942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg } 254942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg 255942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg nla_nest_end(msg, nl_rates); 256942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg 257942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg return 0; 258942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg nla_put_failure: 259942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg return -ENOBUFS; 260942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg} 261942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg 262942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg#define DESCR_LEGACY "[legacy-<2.4|5> <legacy rate in Mbps>*]" 263eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz Dziedzic#define DESCR DESCR_LEGACY " [ht-mcs-<2.4|5> <MCS index>*] [vht-mcs-<2.4|5> <NSS:MCSx,MCSy... | NSS:MCSx-MCSy>*] [sgi-2.4|lgi-2.4] [sgi-5|lgi-5]" 264942b5cd86434724ac31ff3847baf3d1365b75022Johannes Berg 265eaa166977a392cdccb75e7ca63bff85d4b66da40Janusz DziedzicCOMMAND(set, bitrates, "[legacy-<2.4|5> <legacy rate in Mbps>*] [ht-mcs-<2.4|5> <MCS index>*] [vht-mcs-<2.4|5> <NSS:MCSx,MCSy... | NSS:MCSx-MCSy>*] [sgi-2.4|lgi-2.4] [sgi-5|lgi-5]", 266135e65d67ffbefadb27948b9c6e490c635bc9d74Simon Wunderlich NL80211_CMD_SET_TX_BITRATE_MASK, 0, CIB_NETDEV, handle_bitrates, 267dce7b72035abb76a95187a322ec91c76845dfb15Sujith Manoharan "Sets up the specified rate masks.\n" 268dce7b72035abb76a95187a322ec91c76845dfb15Sujith Manoharan "Not passing any arguments would clear the existing mask (if any)."); 269