1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
7 #include "wilc_wlan_if.h"
9 #include "wilc_wlan_cfg.h"
10 #include "wilc_wfi_netdevice.h"
20 static const struct wilc_cfg_byte g_cfg_byte[] = {
27 static const struct wilc_cfg_hword g_cfg_hword[] = {
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},
40 static const struct wilc_cfg_str g_cfg_str[] = {
41 {WID_FIRMWARE_VERSION, NULL},
43 {WID_ASSOC_RES_INFO, NULL},
47 /********************************************
49 * Configuration Functions
51 ********************************************/
53 static int wilc_wlan_cfg_set_byte(u8 *frame, u32 offset, u16 id, u8 val8)
57 if ((offset + 4) >= MAX_CFG_FRAME_SIZE)
63 buf[1] = (u8)(id >> 8);
70 static int wilc_wlan_cfg_set_hword(u8 *frame, u32 offset, u16 id, u16 val16)
74 if ((offset + 5) >= MAX_CFG_FRAME_SIZE)
80 buf[1] = (u8)(id >> 8);
84 buf[5] = (u8)(val16 >> 8);
89 static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32)
93 if ((offset + 7) >= MAX_CFG_FRAME_SIZE)
99 buf[1] = (u8)(id >> 8);
103 buf[5] = (u8)(val32 >> 8);
104 buf[6] = (u8)(val32 >> 16);
105 buf[7] = (u8)(val32 >> 24);
110 static int wilc_wlan_cfg_set_str(u8 *frame, u32 offset, u16 id, u8 *str,
115 if ((offset + size + 4) >= MAX_CFG_FRAME_SIZE)
118 buf = &frame[offset];
121 buf[1] = (u8)(id >> 8);
123 buf[3] = (u8)(size >> 8);
125 if (str && size != 0)
126 memcpy(&buf[4], str, size);
131 static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size)
137 if ((offset + size + 5) >= MAX_CFG_FRAME_SIZE)
140 buf = &frame[offset];
142 buf[1] = (u8)(id >> 8);
144 buf[3] = (u8)(size >> 8);
146 if ((b) && size != 0) {
147 memcpy(&buf[4], b, size);
148 for (i = 0; i < size; i++)
149 checksum += buf[i + 4];
152 buf[size + 4] = checksum;
157 /********************************************
159 * Configuration Response Functions
161 ********************************************/
163 #define GET_WID_TYPE(wid) (((wid) >> 12) & 0x7)
164 static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size)
171 wid = info[0] | (info[1] << 8);
173 switch (GET_WID_TYPE(wid)) {
176 if (wl->cfg.b[i].id == WID_NIL)
179 if (wl->cfg.b[i].id == wid) {
180 wl->cfg.b[i].val = info[4];
190 if (wl->cfg.hw[i].id == WID_NIL)
193 if (wl->cfg.hw[i].id == wid) {
194 wl->cfg.hw[i].val = (info[4] |
205 if (wl->cfg.w[i].id == WID_NIL)
208 if (wl->cfg.w[i].id == wid) {
209 wl->cfg.w[i].val = (info[4] |
222 if (wl->cfg.s[i].id == WID_NIL)
225 if (wl->cfg.s[i].id == wid) {
226 memcpy(wl->cfg.s[i].str, &info[2],
243 static void wilc_wlan_parse_info_frame(struct wilc *wl, u8 *info)
247 wid = info[0] | (info[1] << 8);
251 if (len == 1 && wid == WID_STATUS) {
255 if (wl->cfg.b[i].id == WID_NIL)
258 if (wl->cfg.b[i].id == wid) {
259 wl->cfg.b[i].val = info[3];
267 /********************************************
269 * Configuration Exported Functions
271 ********************************************/
273 int wilc_wlan_cfg_set_wid(u8 *frame, u32 offset, u16 id, u8 *buf, int size)
275 u8 type = (id >> 12) & 0xf;
281 ret = wilc_wlan_cfg_set_byte(frame, offset, id, *buf);
286 ret = wilc_wlan_cfg_set_hword(frame, offset, id,
292 ret = wilc_wlan_cfg_set_word(frame, offset, id,
297 ret = wilc_wlan_cfg_set_str(frame, offset, id, buf, size);
301 ret = wilc_wlan_cfg_set_bin(frame, offset, id, buf, size);
308 int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id)
312 if ((offset + 2) >= MAX_CFG_FRAME_SIZE)
315 buf = &frame[offset];
318 buf[1] = (u8)(id >> 8);
323 int wilc_wlan_cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer,
326 u32 type = (wid >> 12) & 0xf;
330 if (type == CFG_BYTE_CMD) {
332 if (wl->cfg.b[i].id == WID_NIL)
335 if (wl->cfg.b[i].id == wid) {
336 memcpy(buffer, &wl->cfg.b[i].val, 1);
342 } else if (type == CFG_HWORD_CMD) {
344 if (wl->cfg.hw[i].id == WID_NIL)
347 if (wl->cfg.hw[i].id == wid) {
348 memcpy(buffer, &wl->cfg.hw[i].val, 2);
354 } else if (type == CFG_WORD_CMD) {
356 if (wl->cfg.w[i].id == WID_NIL)
359 if (wl->cfg.w[i].id == wid) {
360 memcpy(buffer, &wl->cfg.w[i].val, 4);
366 } else if (type == CFG_STR_CMD) {
368 u32 id = wl->cfg.s[i].id;
374 u32 size = (wl->cfg.s[i].str[0] |
375 (wl->cfg.s[i].str[1] << 8));
377 if (buffer_size >= size) {
378 memcpy(buffer, &wl->cfg.s[i].str[2],
390 void wilc_wlan_cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size,
391 struct wilc_cfg_rsp *rsp)
397 msg_id = frame[1]; /* seq no */
403 * The valid types of response messages are
405 * 'I' (Information), and
406 * 'N' (Network Information)
411 wilc_wlan_parse_response_frame(wilc, frame, size);
412 rsp->type = WILC_CFG_RSP;
413 rsp->seq_no = msg_id;
417 wilc_wlan_parse_info_frame(wilc, frame);
418 rsp->type = WILC_CFG_RSP_STATUS;
419 rsp->seq_no = msg_id;
420 /*call host interface info parse as well*/
421 wilc_gnrl_async_info_received(wilc, frame - 4, size + 4);
425 wilc_network_info_received(wilc, frame - 4, size + 4);
429 wilc_scan_complete_received(wilc, frame - 4, size + 4);
433 rsp->seq_no = msg_id;
438 int wilc_wlan_cfg_init(struct wilc *wl)
440 struct wilc_cfg_str_vals *str_vals;
443 wl->cfg.b = kmemdup(g_cfg_byte, sizeof(g_cfg_byte), GFP_KERNEL);
447 wl->cfg.hw = kmemdup(g_cfg_hword, sizeof(g_cfg_hword), GFP_KERNEL);
451 wl->cfg.w = kmemdup(g_cfg_word, sizeof(g_cfg_word), GFP_KERNEL);
455 wl->cfg.s = kmemdup(g_cfg_str, sizeof(g_cfg_str), GFP_KERNEL);
459 str_vals = kzalloc(sizeof(*str_vals), GFP_KERNEL);
463 wl->cfg.str_vals = str_vals;
464 /* store the string cfg parameters */
465 wl->cfg.s[i].id = WID_FIRMWARE_VERSION;
466 wl->cfg.s[i].str = str_vals->firmware_version;
468 wl->cfg.s[i].id = WID_MAC_ADDR;
469 wl->cfg.s[i].str = str_vals->mac_address;
471 wl->cfg.s[i].id = WID_ASSOC_RES_INFO;
472 wl->cfg.s[i].str = str_vals->assoc_rsp;
474 wl->cfg.s[i].id = WID_NIL;
475 wl->cfg.s[i].str = NULL;
489 void wilc_wlan_cfg_deinit(struct wilc *wl)
495 kfree(wl->cfg.str_vals);