linux/drivers/staging/wilc1000/wilc_wlan_cfg.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
   4 * All rights reserved.
   5 */
   6
   7#include "wilc_wlan_if.h"
   8#include "wilc_wlan.h"
   9#include "wilc_wlan_cfg.h"
  10#include "coreconfigurator.h"
  11
  12enum cfg_cmd_type {
  13        CFG_BYTE_CMD    = 0,
  14        CFG_HWORD_CMD   = 1,
  15        CFG_WORD_CMD    = 2,
  16        CFG_STR_CMD     = 3,
  17        CFG_BIN_CMD     = 4
  18};
  19
  20struct wilc_mac_cfg {
  21        int mac_status;
  22        u8 mac_address[7];
  23        u8 ip_address[5];
  24        u8 bssid[7];
  25        u8 ssid[34];
  26        u8 firmware_version[129];
  27        u8 supp_rate[24];
  28        u8 wep_key[28];
  29        u8 i_psk[66];
  30        u8 hw_product_version[33];
  31        u8 phyversion[17];
  32        u8 supp_username[21];
  33        u8 supp_password[64];
  34        u8 assoc_req[256];
  35        u8 assoc_rsp[256];
  36        u8 firmware_info[8];
  37        u8 scan_result[256];
  38        u8 scan_result1[256];
  39};
  40
  41static struct wilc_mac_cfg g_mac;
  42
  43static struct wilc_cfg_byte g_cfg_byte[] = {
  44        {WID_BSS_TYPE, 0},
  45        {WID_CURRENT_TX_RATE, 0},
  46        {WID_CURRENT_CHANNEL, 0},
  47        {WID_PREAMBLE, 0},
  48        {WID_11G_OPERATING_MODE, 0},
  49        {WID_STATUS, 0},
  50        {WID_SCAN_TYPE, 0},
  51        {WID_KEY_ID, 0},
  52        {WID_QOS_ENABLE, 0},
  53        {WID_POWER_MANAGEMENT, 0},
  54        {WID_11I_MODE, 0},
  55        {WID_AUTH_TYPE, 0},
  56        {WID_SITE_SURVEY, 0},
  57        {WID_LISTEN_INTERVAL, 0},
  58        {WID_DTIM_PERIOD, 0},
  59        {WID_ACK_POLICY, 0},
  60        {WID_BCAST_SSID, 0},
  61        {WID_REKEY_POLICY, 0},
  62        {WID_SHORT_SLOT_ALLOWED, 0},
  63        {WID_START_SCAN_REQ, 0},
  64        {WID_RSSI, 0},
  65        {WID_LINKSPEED, 0},
  66        {WID_AUTO_RX_SENSITIVITY, 0},
  67        {WID_DATAFLOW_CONTROL, 0},
  68        {WID_SCAN_FILTER, 0},
  69        {WID_11N_PROT_MECH, 0},
  70        {WID_11N_ERP_PROT_TYPE, 0},
  71        {WID_11N_ENABLE, 0},
  72        {WID_11N_OPERATING_MODE, 0},
  73        {WID_11N_OBSS_NONHT_DETECTION, 0},
  74        {WID_11N_HT_PROT_TYPE, 0},
  75        {WID_11N_RIFS_PROT_ENABLE, 0},
  76        {WID_11N_SMPS_MODE, 0},
  77        {WID_11N_CURRENT_TX_MCS, 0},
  78        {WID_11N_SHORT_GI_ENABLE, 0},
  79        {WID_RIFS_MODE, 0},
  80        {WID_TX_ABORT_CONFIG, 0},
  81        {WID_11N_IMMEDIATE_BA_ENABLED, 0},
  82        {WID_11N_TXOP_PROT_DISABLE, 0},
  83        {WID_NIL, 0}
  84};
  85
  86static struct wilc_cfg_hword g_cfg_hword[] = {
  87        {WID_LINK_LOSS_THRESHOLD, 0},
  88        {WID_RTS_THRESHOLD, 0},
  89        {WID_FRAG_THRESHOLD, 0},
  90        {WID_SHORT_RETRY_LIMIT, 0},
  91        {WID_LONG_RETRY_LIMIT, 0},
  92        {WID_BEACON_INTERVAL, 0},
  93        {WID_RX_SENSE, 0},
  94        {WID_ACTIVE_SCAN_TIME, 0},
  95        {WID_PASSIVE_SCAN_TIME, 0},
  96        {WID_SITE_SURVEY_SCAN_TIME, 0},
  97        {WID_JOIN_START_TIMEOUT, 0},
  98        {WID_AUTH_TIMEOUT, 0},
  99        {WID_ASOC_TIMEOUT, 0},
 100        {WID_11I_PROTOCOL_TIMEOUT, 0},
 101        {WID_EAPOL_RESPONSE_TIMEOUT, 0},
 102        {WID_11N_SIG_QUAL_VAL, 0},
 103        {WID_CCA_THRESHOLD, 0},
 104        {WID_NIL, 0}
 105};
 106
 107static struct wilc_cfg_word g_cfg_word[] = {
 108        {WID_FAILED_COUNT, 0},
 109        {WID_RETRY_COUNT, 0},
 110        {WID_MULTIPLE_RETRY_COUNT, 0},
 111        {WID_FRAME_DUPLICATE_COUNT, 0},
 112        {WID_ACK_FAILURE_COUNT, 0},
 113        {WID_RECEIVED_FRAGMENT_COUNT, 0},
 114        {WID_MCAST_RECEIVED_FRAME_COUNT, 0},
 115        {WID_FCS_ERROR_COUNT, 0},
 116        {WID_SUCCESS_FRAME_COUNT, 0},
 117        {WID_TX_FRAGMENT_COUNT, 0},
 118        {WID_TX_MULTICAST_FRAME_COUNT, 0},
 119        {WID_RTS_SUCCESS_COUNT, 0},
 120        {WID_RTS_FAILURE_COUNT, 0},
 121        {WID_WEP_UNDECRYPTABLE_COUNT, 0},
 122        {WID_REKEY_PERIOD, 0},
 123        {WID_REKEY_PACKET_COUNT, 0},
 124        {WID_HW_RX_COUNT, 0},
 125        {WID_GET_INACTIVE_TIME, 0},
 126        {WID_NIL, 0}
 127
 128};
 129
 130static struct wilc_cfg_str g_cfg_str[] = {
 131        {WID_SSID, g_mac.ssid}, /* 33 + 1 bytes */
 132        {WID_FIRMWARE_VERSION, g_mac.firmware_version},
 133        {WID_OPERATIONAL_RATE_SET, g_mac.supp_rate},
 134        {WID_BSSID, g_mac.bssid},       /* 6 bytes */
 135        {WID_WEP_KEY_VALUE, g_mac.wep_key},     /* 27 bytes */
 136        {WID_11I_PSK, g_mac.i_psk},     /* 65 bytes */
 137        {WID_HARDWARE_VERSION, g_mac.hw_product_version},
 138        {WID_MAC_ADDR, g_mac.mac_address},
 139        {WID_PHY_VERSION, g_mac.phyversion},
 140        {WID_SUPP_USERNAME, g_mac.supp_username},
 141        {WID_SUPP_PASSWORD, g_mac.supp_password},
 142        {WID_SITE_SURVEY_RESULTS, g_mac.scan_result},
 143        {WID_SITE_SURVEY_RESULTS, g_mac.scan_result1},
 144        {WID_ASSOC_REQ_INFO, g_mac.assoc_req},
 145        {WID_ASSOC_RES_INFO, g_mac.assoc_rsp},
 146        {WID_FIRMWARE_INFO, g_mac.firmware_version},
 147        {WID_IP_ADDRESS, g_mac.ip_address},
 148        {WID_NIL, NULL}
 149};
 150
 151/********************************************
 152 *
 153 *      Configuration Functions
 154 *
 155 ********************************************/
 156
 157static int wilc_wlan_cfg_set_byte(u8 *frame, u32 offset, u16 id, u8 val8)
 158{
 159        u8 *buf;
 160
 161        if ((offset + 4) >= MAX_CFG_FRAME_SIZE)
 162                return 0;
 163
 164        buf = &frame[offset];
 165
 166        buf[0] = (u8)id;
 167        buf[1] = (u8)(id >> 8);
 168        buf[2] = 1;
 169        buf[3] = 0;
 170        buf[4] = val8;
 171        return 5;
 172}
 173
 174static int wilc_wlan_cfg_set_hword(u8 *frame, u32 offset, u16 id, u16 val16)
 175{
 176        u8 *buf;
 177
 178        if ((offset + 5) >= MAX_CFG_FRAME_SIZE)
 179                return 0;
 180
 181        buf = &frame[offset];
 182
 183        buf[0] = (u8)id;
 184        buf[1] = (u8)(id >> 8);
 185        buf[2] = 2;
 186        buf[3] = 0;
 187        buf[4] = (u8)val16;
 188        buf[5] = (u8)(val16 >> 8);
 189
 190        return 6;
 191}
 192
 193static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32)
 194{
 195        u8 *buf;
 196
 197        if ((offset + 7) >= MAX_CFG_FRAME_SIZE)
 198                return 0;
 199
 200        buf = &frame[offset];
 201
 202        buf[0] = (u8)id;
 203        buf[1] = (u8)(id >> 8);
 204        buf[2] = 4;
 205        buf[3] = 0;
 206        buf[4] = (u8)val32;
 207        buf[5] = (u8)(val32 >> 8);
 208        buf[6] = (u8)(val32 >> 16);
 209        buf[7] = (u8)(val32 >> 24);
 210
 211        return 8;
 212}
 213
 214static int wilc_wlan_cfg_set_str(u8 *frame, u32 offset, u16 id, u8 *str,
 215                                 u32 size)
 216{
 217        u8 *buf;
 218
 219        if ((offset + size + 4) >= MAX_CFG_FRAME_SIZE)
 220                return 0;
 221
 222        buf = &frame[offset];
 223
 224        buf[0] = (u8)id;
 225        buf[1] = (u8)(id >> 8);
 226        buf[2] = (u8)size;
 227        buf[3] = (u8)(size >> 8);
 228
 229        if (str && size != 0)
 230                memcpy(&buf[4], str, size);
 231
 232        return (size + 4);
 233}
 234
 235static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size)
 236{
 237        u8 *buf;
 238        u32 i;
 239        u8 checksum = 0;
 240
 241        if ((offset + size + 5) >= MAX_CFG_FRAME_SIZE)
 242                return 0;
 243
 244        buf = &frame[offset];
 245        buf[0] = (u8)id;
 246        buf[1] = (u8)(id >> 8);
 247        buf[2] = (u8)size;
 248        buf[3] = (u8)(size >> 8);
 249
 250        if ((b) && size != 0) {
 251                memcpy(&buf[4], b, size);
 252                for (i = 0; i < size; i++)
 253                        checksum += buf[i + 4];
 254        }
 255
 256        buf[size + 4] = checksum;
 257
 258        return (size + 5);
 259}
 260
 261/********************************************
 262 *
 263 *      Configuration Response Functions
 264 *
 265 ********************************************/
 266
 267#define GET_WID_TYPE(wid)               (((wid) >> 12) & 0x7)
 268static void wilc_wlan_parse_response_frame(u8 *info, int size)
 269{
 270        u16 wid;
 271        u32 len = 0, i = 0;
 272
 273        while (size > 0) {
 274                i = 0;
 275                wid = info[0] | (info[1] << 8);
 276
 277                switch (GET_WID_TYPE(wid)) {
 278                case WID_CHAR:
 279                        do {
 280                                if (g_cfg_byte[i].id == WID_NIL)
 281                                        break;
 282
 283                                if (g_cfg_byte[i].id == wid) {
 284                                        g_cfg_byte[i].val = info[4];
 285                                        break;
 286                                }
 287                                i++;
 288                        } while (1);
 289                        len = 3;
 290                        break;
 291
 292                case WID_SHORT:
 293                        do {
 294                                if (g_cfg_hword[i].id == WID_NIL)
 295                                        break;
 296
 297                                if (g_cfg_hword[i].id == wid) {
 298                                        g_cfg_hword[i].val = (info[4] |
 299                                                              (info[5] << 8));
 300                                        break;
 301                                }
 302                                i++;
 303                        } while (1);
 304                        len = 4;
 305                        break;
 306
 307                case WID_INT:
 308                        do {
 309                                if (g_cfg_word[i].id == WID_NIL)
 310                                        break;
 311
 312                                if (g_cfg_word[i].id == wid) {
 313                                        g_cfg_word[i].val = (info[4] |
 314                                                             (info[5] << 8) |
 315                                                             (info[6] << 16) |
 316                                                             (info[7] << 24));
 317                                        break;
 318                                }
 319                                i++;
 320                        } while (1);
 321                        len = 6;
 322                        break;
 323
 324                case WID_STR:
 325                        do {
 326                                if (g_cfg_str[i].id == WID_NIL)
 327                                        break;
 328
 329                                if (g_cfg_str[i].id == wid) {
 330                                        if (wid == WID_SITE_SURVEY_RESULTS) {
 331                                                static int toggle;
 332
 333                                                i += toggle;
 334                                                toggle ^= 1;
 335                                        }
 336                                        memcpy(g_cfg_str[i].str, &info[2],
 337                                               (info[2] + 2));
 338                                        break;
 339                                }
 340                                i++;
 341                        } while (1);
 342                        len = 2 + info[2];
 343                        break;
 344
 345                default:
 346                        break;
 347                }
 348                size -= (2 + len);
 349                info += (2 + len);
 350        }
 351}
 352
 353static int wilc_wlan_parse_info_frame(u8 *info, int size)
 354{
 355        struct wilc_mac_cfg *pd = &g_mac;
 356        u32 wid, len;
 357        int type = WILC_CFG_RSP_STATUS;
 358
 359        wid = info[0] | (info[1] << 8);
 360
 361        len = info[2];
 362
 363        if (len == 1 && wid == WID_STATUS) {
 364                pd->mac_status = info[3];
 365                type = WILC_CFG_RSP_STATUS;
 366        }
 367
 368        return type;
 369}
 370
 371/********************************************
 372 *
 373 *      Configuration Exported Functions
 374 *
 375 ********************************************/
 376
 377int wilc_wlan_cfg_set_wid(u8 *frame, u32 offset, u16 id, u8 *buf, int size)
 378{
 379        u8 type = (id >> 12) & 0xf;
 380        int ret = 0;
 381
 382        switch (type) {
 383        case CFG_BYTE_CMD:
 384                if (size >= 1)
 385                        ret = wilc_wlan_cfg_set_byte(frame, offset, id, *buf);
 386                break;
 387
 388        case CFG_HWORD_CMD:
 389                if (size >= 2)
 390                        ret = wilc_wlan_cfg_set_hword(frame, offset, id,
 391                                                      *((u16 *)buf));
 392                break;
 393
 394        case CFG_WORD_CMD:
 395                if (size >= 4)
 396                        ret = wilc_wlan_cfg_set_word(frame, offset, id,
 397                                                     *((u32 *)buf));
 398                break;
 399
 400        case CFG_STR_CMD:
 401                ret = wilc_wlan_cfg_set_str(frame, offset, id, buf, size);
 402                break;
 403
 404        case CFG_BIN_CMD:
 405                ret = wilc_wlan_cfg_set_bin(frame, offset, id, buf, size);
 406                break;
 407        }
 408
 409        return ret;
 410}
 411
 412int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id)
 413{
 414        u8 *buf;
 415
 416        if ((offset + 2) >= MAX_CFG_FRAME_SIZE)
 417                return 0;
 418
 419        buf = &frame[offset];
 420
 421        buf[0] = (u8)id;
 422        buf[1] = (u8)(id >> 8);
 423
 424        return 2;
 425}
 426
 427int wilc_wlan_cfg_get_wid_value(u16 wid, u8 *buffer, u32 buffer_size)
 428{
 429        u32 type = (wid >> 12) & 0xf;
 430        int i, ret = 0;
 431
 432        if (wid == WID_STATUS) {
 433                *((u32 *)buffer) = g_mac.mac_status;
 434                return 4;
 435        }
 436
 437        i = 0;
 438        if (type == CFG_BYTE_CMD) {
 439                do {
 440                        if (g_cfg_byte[i].id == WID_NIL)
 441                                break;
 442
 443                        if (g_cfg_byte[i].id == wid) {
 444                                memcpy(buffer,  &g_cfg_byte[i].val, 1);
 445                                ret = 1;
 446                                break;
 447                        }
 448                        i++;
 449                } while (1);
 450        } else if (type == CFG_HWORD_CMD) {
 451                do {
 452                        if (g_cfg_hword[i].id == WID_NIL)
 453                                break;
 454
 455                        if (g_cfg_hword[i].id == wid) {
 456                                memcpy(buffer,  &g_cfg_hword[i].val, 2);
 457                                ret = 2;
 458                                break;
 459                        }
 460                        i++;
 461                } while (1);
 462        } else if (type == CFG_WORD_CMD) {
 463                do {
 464                        if (g_cfg_word[i].id == WID_NIL)
 465                                break;
 466
 467                        if (g_cfg_word[i].id == wid) {
 468                                memcpy(buffer,  &g_cfg_word[i].val, 4);
 469                                ret = 4;
 470                                break;
 471                        }
 472                        i++;
 473                } while (1);
 474        } else if (type == CFG_STR_CMD) {
 475                do {
 476                        u32 id = g_cfg_str[i].id;
 477
 478                        if (id == WID_NIL)
 479                                break;
 480
 481                        if (id == wid) {
 482                                u32 size = g_cfg_str[i].str[0] |
 483                                                (g_cfg_str[i].str[1] << 8);
 484
 485                                if (buffer_size >= size) {
 486                                        if (id == WID_SITE_SURVEY_RESULTS) {
 487                                                static int toggle;
 488
 489                                                i += toggle;
 490                                                toggle ^= 1;
 491                                        }
 492                                        memcpy(buffer,  &g_cfg_str[i].str[2],
 493                                               size);
 494                                        ret = size;
 495                                }
 496                                break;
 497                        }
 498                        i++;
 499                } while (1);
 500        }
 501
 502        return ret;
 503}
 504
 505int wilc_wlan_cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size,
 506                              struct wilc_cfg_rsp *rsp)
 507{
 508        int ret = 1;
 509        u8 msg_type;
 510        u8 msg_id;
 511
 512        msg_type = frame[0];
 513        msg_id = frame[1];      /* seq no */
 514        frame += 4;
 515        size -= 4;
 516
 517        /*
 518         * The valid types of response messages are
 519         * 'R' (Response),
 520         * 'I' (Information), and
 521         * 'N' (Network Information)
 522         */
 523
 524        switch (msg_type) {
 525        case 'R':
 526                wilc_wlan_parse_response_frame(frame, size);
 527                rsp->type = WILC_CFG_RSP;
 528                rsp->seq_no = msg_id;
 529                break;
 530
 531        case 'I':
 532                rsp->type = wilc_wlan_parse_info_frame(frame, size);
 533                rsp->seq_no = msg_id;
 534                /*call host interface info parse as well*/
 535                wilc_gnrl_async_info_received(wilc, frame - 4, size + 4);
 536                break;
 537
 538        case 'N':
 539                wilc_network_info_received(wilc, frame - 4, size + 4);
 540                rsp->type = 0;
 541                break;
 542
 543        case 'S':
 544                wilc_scan_complete_received(wilc, frame - 4, size + 4);
 545                break;
 546
 547        default:
 548                rsp->type = 0;
 549                rsp->seq_no = msg_id;
 550                ret = 0;
 551                break;
 552        }
 553
 554        return ret;
 555}
 556
 557int wilc_wlan_cfg_init(void)
 558{
 559        memset((void *)&g_mac, 0, sizeof(struct wilc_mac_cfg));
 560        return 1;
 561}
 562