root/drivers/staging/wilc1000/wilc_wlan_cfg.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wilc_wlan_cfg_set_byte
  2. wilc_wlan_cfg_set_hword
  3. wilc_wlan_cfg_set_word
  4. wilc_wlan_cfg_set_str
  5. wilc_wlan_cfg_set_bin
  6. wilc_wlan_parse_response_frame
  7. wilc_wlan_parse_info_frame
  8. wilc_wlan_cfg_set_wid
  9. wilc_wlan_cfg_get_wid
  10. wilc_wlan_cfg_get_val
  11. wilc_wlan_cfg_indicate_rx
  12. wilc_wlan_cfg_init
  13. wilc_wlan_cfg_deinit

   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 "wilc_wfi_netdevice.h"
  11 
  12 enum 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 
  20 static const struct wilc_cfg_byte g_cfg_byte[] = {
  21         {WID_STATUS, 0},
  22         {WID_RSSI, 0},
  23         {WID_LINKSPEED, 0},
  24         {WID_NIL, 0}
  25 };
  26 
  27 static const struct wilc_cfg_hword g_cfg_hword[] = {
  28         {WID_NIL, 0}
  29 };
  30 
  31 static const struct wilc_cfg_word g_cfg_word[] = {
  32         {WID_FAILED_COUNT, 0},
  33         {WID_RECEIVED_FRAGMENT_COUNT, 0},
  34         {WID_SUCCESS_FRAME_COUNT, 0},
  35         {WID_GET_INACTIVE_TIME, 0},
  36         {WID_NIL, 0}
  37 
  38 };
  39 
  40 static const struct wilc_cfg_str g_cfg_str[] = {
  41         {WID_FIRMWARE_VERSION, NULL},
  42         {WID_MAC_ADDR, NULL},
  43         {WID_ASSOC_RES_INFO, NULL},
  44         {WID_NIL, NULL}
  45 };
  46 
  47 /********************************************
  48  *
  49  *      Configuration Functions
  50  *
  51  ********************************************/
  52 
  53 static int wilc_wlan_cfg_set_byte(u8 *frame, u32 offset, u16 id, u8 val8)
  54 {
  55         if ((offset + 4) >= WILC_MAX_CFG_FRAME_SIZE)
  56                 return 0;
  57 
  58         put_unaligned_le16(id, &frame[offset]);
  59         put_unaligned_le16(1, &frame[offset + 2]);
  60         frame[offset + 4] = val8;
  61         return 5;
  62 }
  63 
  64 static int wilc_wlan_cfg_set_hword(u8 *frame, u32 offset, u16 id, u16 val16)
  65 {
  66         if ((offset + 5) >= WILC_MAX_CFG_FRAME_SIZE)
  67                 return 0;
  68 
  69         put_unaligned_le16(id, &frame[offset]);
  70         put_unaligned_le16(2, &frame[offset + 2]);
  71         put_unaligned_le16(val16, &frame[offset + 4]);
  72 
  73         return 6;
  74 }
  75 
  76 static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32)
  77 {
  78         if ((offset + 7) >= WILC_MAX_CFG_FRAME_SIZE)
  79                 return 0;
  80 
  81         put_unaligned_le16(id, &frame[offset]);
  82         put_unaligned_le16(4, &frame[offset + 2]);
  83         put_unaligned_le32(val32, &frame[offset + 4]);
  84 
  85         return 8;
  86 }
  87 
  88 static int wilc_wlan_cfg_set_str(u8 *frame, u32 offset, u16 id, u8 *str,
  89                                  u32 size)
  90 {
  91         if ((offset + size + 4) >= WILC_MAX_CFG_FRAME_SIZE)
  92                 return 0;
  93 
  94         put_unaligned_le16(id, &frame[offset]);
  95         put_unaligned_le16(size, &frame[offset + 2]);
  96         if (str && size != 0)
  97                 memcpy(&frame[offset + 4], str, size);
  98 
  99         return (size + 4);
 100 }
 101 
 102 static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size)
 103 {
 104         u32 i;
 105         u8 checksum = 0;
 106 
 107         if ((offset + size + 5) >= WILC_MAX_CFG_FRAME_SIZE)
 108                 return 0;
 109 
 110         put_unaligned_le16(id, &frame[offset]);
 111         put_unaligned_le16(size, &frame[offset + 2]);
 112 
 113         if ((b) && size != 0) {
 114                 memcpy(&frame[offset + 4], b, size);
 115                 for (i = 0; i < size; i++)
 116                         checksum += frame[offset + i + 4];
 117         }
 118 
 119         frame[offset + size + 4] = checksum;
 120 
 121         return (size + 5);
 122 }
 123 
 124 /********************************************
 125  *
 126  *      Configuration Response Functions
 127  *
 128  ********************************************/
 129 
 130 #define GET_WID_TYPE(wid)               (((wid) >> 12) & 0x7)
 131 static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size)
 132 {
 133         u16 wid;
 134         u32 len = 0, i = 0;
 135 
 136         while (size > 0) {
 137                 i = 0;
 138                 wid = get_unaligned_le16(info);
 139 
 140                 switch (GET_WID_TYPE(wid)) {
 141                 case WID_CHAR:
 142                         do {
 143                                 if (wl->cfg.b[i].id == WID_NIL)
 144                                         break;
 145 
 146                                 if (wl->cfg.b[i].id == wid) {
 147                                         wl->cfg.b[i].val = info[4];
 148                                         break;
 149                                 }
 150                                 i++;
 151                         } while (1);
 152                         len = 3;
 153                         break;
 154 
 155                 case WID_SHORT:
 156                         do {
 157                                 struct wilc_cfg_hword *hw = &wl->cfg.hw[i];
 158 
 159                                 if (hw->id == WID_NIL)
 160                                         break;
 161 
 162                                 if (hw->id == wid) {
 163                                         hw->val = get_unaligned_le16(&info[4]);
 164                                         break;
 165                                 }
 166                                 i++;
 167                         } while (1);
 168                         len = 4;
 169                         break;
 170 
 171                 case WID_INT:
 172                         do {
 173                                 struct wilc_cfg_word *w = &wl->cfg.w[i];
 174 
 175                                 if (w->id == WID_NIL)
 176                                         break;
 177 
 178                                 if (w->id == wid) {
 179                                         w->val = get_unaligned_le32(&info[4]);
 180                                         break;
 181                                 }
 182                                 i++;
 183                         } while (1);
 184                         len = 6;
 185                         break;
 186 
 187                 case WID_STR:
 188                         do {
 189                                 if (wl->cfg.s[i].id == WID_NIL)
 190                                         break;
 191 
 192                                 if (wl->cfg.s[i].id == wid) {
 193                                         memcpy(wl->cfg.s[i].str, &info[2],
 194                                                (info[2] + 2));
 195                                         break;
 196                                 }
 197                                 i++;
 198                         } while (1);
 199                         len = 2 + info[2];
 200                         break;
 201 
 202                 default:
 203                         break;
 204                 }
 205                 size -= (2 + len);
 206                 info += (2 + len);
 207         }
 208 }
 209 
 210 static void wilc_wlan_parse_info_frame(struct wilc *wl, u8 *info)
 211 {
 212         u32 wid, len;
 213 
 214         wid = get_unaligned_le16(info);
 215 
 216         len = info[2];
 217 
 218         if (len == 1 && wid == WID_STATUS) {
 219                 int i = 0;
 220 
 221                 do {
 222                         if (wl->cfg.b[i].id == WID_NIL)
 223                                 break;
 224 
 225                         if (wl->cfg.b[i].id == wid) {
 226                                 wl->cfg.b[i].val = info[3];
 227                                 break;
 228                         }
 229                         i++;
 230                 } while (1);
 231         }
 232 }
 233 
 234 /********************************************
 235  *
 236  *      Configuration Exported Functions
 237  *
 238  ********************************************/
 239 
 240 int wilc_wlan_cfg_set_wid(u8 *frame, u32 offset, u16 id, u8 *buf, int size)
 241 {
 242         u8 type = (id >> 12) & 0xf;
 243         int ret = 0;
 244 
 245         switch (type) {
 246         case CFG_BYTE_CMD:
 247                 if (size >= 1)
 248                         ret = wilc_wlan_cfg_set_byte(frame, offset, id, *buf);
 249                 break;
 250 
 251         case CFG_HWORD_CMD:
 252                 if (size >= 2)
 253                         ret = wilc_wlan_cfg_set_hword(frame, offset, id,
 254                                                       *((u16 *)buf));
 255                 break;
 256 
 257         case CFG_WORD_CMD:
 258                 if (size >= 4)
 259                         ret = wilc_wlan_cfg_set_word(frame, offset, id,
 260                                                      *((u32 *)buf));
 261                 break;
 262 
 263         case CFG_STR_CMD:
 264                 ret = wilc_wlan_cfg_set_str(frame, offset, id, buf, size);
 265                 break;
 266 
 267         case CFG_BIN_CMD:
 268                 ret = wilc_wlan_cfg_set_bin(frame, offset, id, buf, size);
 269                 break;
 270         }
 271 
 272         return ret;
 273 }
 274 
 275 int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id)
 276 {
 277         if ((offset + 2) >= WILC_MAX_CFG_FRAME_SIZE)
 278                 return 0;
 279 
 280         put_unaligned_le16(id, &frame[offset]);
 281 
 282         return 2;
 283 }
 284 
 285 int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer,
 286                           u32 buffer_size)
 287 {
 288         u32 type = (wid >> 12) & 0xf;
 289         int i, ret = 0;
 290 
 291         i = 0;
 292         if (type == CFG_BYTE_CMD) {
 293                 do {
 294                         if (wl->cfg.b[i].id == WID_NIL)
 295                                 break;
 296 
 297                         if (wl->cfg.b[i].id == wid) {
 298                                 memcpy(buffer, &wl->cfg.b[i].val, 1);
 299                                 ret = 1;
 300                                 break;
 301                         }
 302                         i++;
 303                 } while (1);
 304         } else if (type == CFG_HWORD_CMD) {
 305                 do {
 306                         if (wl->cfg.hw[i].id == WID_NIL)
 307                                 break;
 308 
 309                         if (wl->cfg.hw[i].id == wid) {
 310                                 memcpy(buffer, &wl->cfg.hw[i].val, 2);
 311                                 ret = 2;
 312                                 break;
 313                         }
 314                         i++;
 315                 } while (1);
 316         } else if (type == CFG_WORD_CMD) {
 317                 do {
 318                         if (wl->cfg.w[i].id == WID_NIL)
 319                                 break;
 320 
 321                         if (wl->cfg.w[i].id == wid) {
 322                                 memcpy(buffer, &wl->cfg.w[i].val, 4);
 323                                 ret = 4;
 324                                 break;
 325                         }
 326                         i++;
 327                 } while (1);
 328         } else if (type == CFG_STR_CMD) {
 329                 do {
 330                         u32 id = wl->cfg.s[i].id;
 331 
 332                         if (id == WID_NIL)
 333                                 break;
 334 
 335                         if (id == wid) {
 336                                 u16 size = get_unaligned_le16(wl->cfg.s[i].str);
 337 
 338                                 if (buffer_size >= size) {
 339                                         memcpy(buffer, &wl->cfg.s[i].str[2],
 340                                                size);
 341                                         ret = size;
 342                                 }
 343                                 break;
 344                         }
 345                         i++;
 346                 } while (1);
 347         }
 348         return ret;
 349 }
 350 
 351 void wilc_wlan_cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size,
 352                                struct wilc_cfg_rsp *rsp)
 353 {
 354         u8 msg_type;
 355         u8 msg_id;
 356 
 357         msg_type = frame[0];
 358         msg_id = frame[1];      /* seq no */
 359         frame += 4;
 360         size -= 4;
 361         rsp->type = 0;
 362 
 363         /*
 364          * The valid types of response messages are
 365          * 'R' (Response),
 366          * 'I' (Information), and
 367          * 'N' (Network Information)
 368          */
 369 
 370         switch (msg_type) {
 371         case 'R':
 372                 wilc_wlan_parse_response_frame(wilc, frame, size);
 373                 rsp->type = WILC_CFG_RSP;
 374                 rsp->seq_no = msg_id;
 375                 break;
 376 
 377         case 'I':
 378                 wilc_wlan_parse_info_frame(wilc, frame);
 379                 rsp->type = WILC_CFG_RSP_STATUS;
 380                 rsp->seq_no = msg_id;
 381                 /*call host interface info parse as well*/
 382                 wilc_gnrl_async_info_received(wilc, frame - 4, size + 4);
 383                 break;
 384 
 385         case 'N':
 386                 wilc_network_info_received(wilc, frame - 4, size + 4);
 387                 break;
 388 
 389         case 'S':
 390                 wilc_scan_complete_received(wilc, frame - 4, size + 4);
 391                 break;
 392 
 393         default:
 394                 rsp->seq_no = msg_id;
 395                 break;
 396         }
 397 }
 398 
 399 int wilc_wlan_cfg_init(struct wilc *wl)
 400 {
 401         struct wilc_cfg_str_vals *str_vals;
 402         int i = 0;
 403 
 404         wl->cfg.b = kmemdup(g_cfg_byte, sizeof(g_cfg_byte), GFP_KERNEL);
 405         if (!wl->cfg.b)
 406                 return -ENOMEM;
 407 
 408         wl->cfg.hw = kmemdup(g_cfg_hword, sizeof(g_cfg_hword), GFP_KERNEL);
 409         if (!wl->cfg.hw)
 410                 goto out_b;
 411 
 412         wl->cfg.w = kmemdup(g_cfg_word, sizeof(g_cfg_word), GFP_KERNEL);
 413         if (!wl->cfg.w)
 414                 goto out_hw;
 415 
 416         wl->cfg.s = kmemdup(g_cfg_str, sizeof(g_cfg_str), GFP_KERNEL);
 417         if (!wl->cfg.s)
 418                 goto out_w;
 419 
 420         str_vals = kzalloc(sizeof(*str_vals), GFP_KERNEL);
 421         if (!str_vals)
 422                 goto out_s;
 423 
 424         wl->cfg.str_vals = str_vals;
 425         /* store the string cfg parameters */
 426         wl->cfg.s[i].id = WID_FIRMWARE_VERSION;
 427         wl->cfg.s[i].str = str_vals->firmware_version;
 428         i++;
 429         wl->cfg.s[i].id = WID_MAC_ADDR;
 430         wl->cfg.s[i].str = str_vals->mac_address;
 431         i++;
 432         wl->cfg.s[i].id = WID_ASSOC_RES_INFO;
 433         wl->cfg.s[i].str = str_vals->assoc_rsp;
 434         i++;
 435         wl->cfg.s[i].id = WID_NIL;
 436         wl->cfg.s[i].str = NULL;
 437         return 0;
 438 
 439 out_s:
 440         kfree(wl->cfg.s);
 441 out_w:
 442         kfree(wl->cfg.w);
 443 out_hw:
 444         kfree(wl->cfg.hw);
 445 out_b:
 446         kfree(wl->cfg.b);
 447         return -ENOMEM;
 448 }
 449 
 450 void wilc_wlan_cfg_deinit(struct wilc *wl)
 451 {
 452         kfree(wl->cfg.b);
 453         kfree(wl->cfg.hw);
 454         kfree(wl->cfg.w);
 455         kfree(wl->cfg.s);
 456         kfree(wl->cfg.str_vals);
 457 }

/* [<][>][^][v][top][bottom][index][help] */