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