1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4#include <unistd.h>
5#include <sys/types.h>
6#include <sys/ioctl.h>
7#include <sys/socket.h>
8#include <net/if.h>
9#include <netinet/in.h>
10#include <arpa/inet.h>
11#include <net/if_arp.h>
12#include <time.h>
13#include <shutils.h>
14#include <rc.h>
15#include <wlioctl.h>
16#include <bcmnvram.h>
17
18#define A_UCHAR  unsigned char
19#define A_UINT8  unsigned char
20#define A_UINT16 unsigned int
21#define A_UINT32 unsigned long
22
23
24/*----------------------------------------------------------------*/
25/* Magic number, a quick test to see we're getting the desired struct */
26#define P80211_IOCTL_MAGIC	(0x4a2d464dUL)
27#define MSG_BUFF_LEN		4000
28#define WLAN_DEVNAMELEN_MAX	16
29
30
31#define CHANNEL_CW_INT              0x0001   // CW interference detected on the channel
32#define CHANNEL_RADAR_INT           0x0002   // Radar interference detected on the channel
33#define CHANNEL_BUSY                0x0004   // Busy, occupied directly or overlap from BSS on adjoining channel
34#define CHANNEL_TURBO               0x0100   // Turbo Channel
35#define CHANNEL_CCK                 0x0200   // CCK channel
36#define CHANNEL_OFDM                0x0400   // OFDM channel
37#define CHANNEL_2GHZ                0x0800   // 2 GHz spectrum channel.
38#define CHANNEL_5GHZ                0x1000   // 5 GHz spectrum channel
39#define CHANNEL_A       (CHANNEL_5GHZ|CHANNEL_OFDM)
40#define CHANNEL_B       (CHANNEL_2GHZ|CHANNEL_CCK)
41#define CHANNEL_PUREG   (CHANNEL_2GHZ|CHANNEL_OFDM)
42#define CHANNEL_T       (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
43#define CHANNEL_ALL     (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_5GHZ|CHANNEL_2GHZ|CHANNEL_TURBO)
44#define CHANNEL_DEFAULT (CHANNEL_5GHZ|CHANNEL_OFDM) // default is normal 11a mode
45#define MAX_REG_DOM_NAME_SIZE       10       // Max string size of reg dom name inc NULL
46
47enum {
48  FCC = 0,
49  MKK,
50  ETSI
51};
52
53#ifdef REMOVE_WL600
54enum {
55  DEBUG_REG_DMN = 0,
56  FCC1,
57  FCC2,
58  MKK1,
59  ETSI1,
60  ETSI2,
61  ETSI3,
62  ETSI4,
63  ETSI5,
64  ETSI6,
65  APL1,
66  APL2,
67  APL3,
68  APL4
69};
70
71#define APL5 APL4
72
73enum {
74  WORLD = 1,
75  FCCA,
76  MKKA,
77  APLA,
78  APLB,
79  APLC,
80  ETSIA,
81  ETSIB,
82  ETSIC,
83};
84#endif
85
86/* Enumerated Regulatory Domain Information */
87/* Enumerated Regulatory Domain Information */
88enum EnumRd {
89    /*
90     * The following regulatory domain definitions are
91     * found in the EEPROM. Each regulatory domain
92     * can operate in either a 5GHz or 2.4GHz wireless mode or
93     * both 5GHz and 2.4GHz wireless modes.
94     * In general, the value holds no special
95     * meaning and is used to decode into either specific
96     * 2.4GHz or 5GHz wireless mode for that particular
97     * regulatory domain.
98     *
99     */
100    NO_ENUMRD     = 0x00,
101    FCC1_FCCA     = 0x10, // USA
102    FCC1_WORLD    = 0x11, // Hong Kong
103
104    FCC2_FCCA     = 0x20, // Canada
105    FCC2_WORLD    = 0x21, // Australia
106    FCC2_ETSIC    = 0x22,
107
108    ETSI1_WORLD   = 0x37,
109    ETSI3_ETSIA   = 0x32, // France
110    ETSI2_WORLD   = 0x35, // Germany
111    ETSI3_WORLD   = 0x36, // Austria
112    ETSI4_WORLD   = 0x30,
113    ETSI4_ETSIC   = 0x38,
114    ETSI1_ETSIB   = 0x39, // Special for ISRAEL
115
116    MKK1_MKKA     = 0x40, // Japan
117    MKK1_MKKB     = 0x41, // Japan
118    APL4_WORLD    = 0x42, // Singapore
119    APL3_FCCA     = 0x43,
120    APL1_APLB     = 0x44, // China
121    APL2_WORLD    = 0x45, // Korea
122    APL2_APLC     = 0x46,
123    APL3_WORLD    = 0x47,
124
125    APL1_WORLD    = 0x52, // Latin America
126    APL1_FCCA     = 0x53, // Mexico
127    APL1_APLA     = 0x54, // Chile
128    APL1_ETSIC    = 0x55,
129
130
131    /*
132     * Super Domain Definitions
133     */
134    WOR0_WORLD    = 0x060,      /* World0 (WO0 SKU) */
135    WOR1_WORLD    = 0x061,      /* World1 (WO1 SKU) */
136    WOR2_WORLD    = 0x062,      /* World2 (WO2 SKU) */
137    WOR3_WORLD    = 0x063,      /* World3 (WO3 SKU) */
138    WOR4_WORLD    = 0x064,      /* World4 (WO4 SKU) */
139    APL5_WORLD    = 0x065,      /* Asia/Latin (AL1 SKU) */
140    APL5_APLB     = 0x066,      /* China (CN1 SKU) */
141
142    /*  "Regulatory domains ending in a number (e.g. APL1,
143     *   MKK1, ETSI4,etc) apply to 5GHz channel and power information.
144     *   Reg. domains ending in a letter (e.g. APLA, FCCA, etc.)
145     *   apply to 2.4GHz channel and power information."
146     */
147
148    /*
149     * The following wireless modes are either 2.4 or 5GHz
150     */
151    APL1          = 0x0150,     /* LAT & Asia */
152    APL2          = 0x0250,     /* LAT & Asia */
153    APL3          = 0x0350,     /* Taiwan */
154    APL4          = 0x0450,     /* Singapore */
155
156    ETSI1         = 0x0130,     /* Europe & others */
157    ETSI2         = 0x0230,     /* Europe & others */
158    ETSI3         = 0x0330,     /* Europe & others */
159    ETSI4         = 0x0430,     /* Europe & others */
160    ETSIA         = 0x0A30,     /* France */
161    ETSIB	  = 0x0B30,     /* Israel */
162    ETSIC         = 0x0C30,     /* Latin America */
163
164
165    FCC1          = 0x0110,     /* US & others */
166    FCC2          = 0x0120,     /* Canada, Australia & New Zealand */
167    FCCA          = 0x0A10,
168
169    APLA          = 0x0A50,     /* Chile */
170    APLB          = 0x0B50,     /* China */
171    APLC          = 0x0C50,     /* South Korea */
172
173    MKK1          = 0x0140,     /* Japan */
174    MKKA          = 0x0A40,     /* Japan */
175
176    WORLD         = 0x0199,
177    DEBUG_REG_DMN = 0x01ff
178};
179
180#define TURBO_CHANNEL_SEPARATION (8)
181#define OFDM5_CHANNEL_SEPARATION (4)
182#define CCK_CHANNEL_SEPARATION   (1)
183
184#define MHZ2IEEE_CH(mhz)        ( ( mhz - 5000  ) / 5 )
185#define FCC_OUTDOOR_FIRST_FREQ 5725
186
187/* 5 GHz table settings */
188
189typedef struct regDmnEnumChannelGroup {
190    A_UINT16    lowChannel;   // Low Channel center in MHz
191    A_UINT16    highChannel;  // High Channel center in MHz
192} REG_DMN_ENUM_CHANNEL_GROUP;
193
194/* TODO: Add EIRP emission addition */
195/* TODO: Define test groups for 2.4 */
196
197#define MAX_CHANNEL_GROUPS 2
198
199typedef struct regDmnEnumFreqTable {
200    A_UINT16         regDmnEnum;
201    A_UINT16         entries;
202    A_UINT8          testGroup;
203    A_UCHAR          name[8];
204    REG_DMN_ENUM_CHANNEL_GROUP chanGroup[MAX_CHANNEL_GROUPS];
205} REG_DMN_ENUM_FREQ_TABLE;
206
207typedef struct CountryCodeToEnumRd {
208    A_UINT16        regDmnEnum;
209    const A_UCHAR   isoName[3];
210    const A_UCHAR   name[16];
211} COUNTRY_CODE_TO_ENUM_RD;
212
213
214
215/*
216 * Regulatory Domain Tables
217 *
218 * Tables have entries ordered with AP/Adhoc planting preference in mind.
219 *  -Indoor channels are ordered before outdoor
220 *  -Higher power level indoor channels are first
221 */
222
223static const REG_DMN_ENUM_FREQ_TABLE regDmnEnum5[] = {
224    {DEBUG_REG_DMN, 2, FCC, "NONE", {
225    {36 , 64},
226    {149,165}}},
227
228    {FCC1, 2, FCC, "FCC1", {
229    {36 , 64},
230    {149,165}}},
231
232    {FCC2, 2, FCC, "FCC2", {
233    {36 , 64},
234    {149,165}}},
235
236    {MKK1, 1, MKK, "MKK1", {
237    { 34, 46},
238    {  0,  0}}},
239
240    {ETSI1, 2, ETSI, "ETSI1", {
241    { 36, 64},
242    {100,140}}},
243
244    {ETSI2, 1, ETSI, "ETSI2", {
245    { 36, 48},
246    {  0,  0}}},
247
248
249    {ETSI3, 1, ETSI, "ETSI3", {
250    { 36, 64},
251    {  0,  0}}},
252
253    {ETSI4, 1, ETSI, "ETSI4", {
254    { 36, 64},
255    {  0,  0}}},
256
257
258    {APL1, 1, FCC, "APL1", {
259    {149,165},
260    {  0,  0}}},
261
262    {APL2, 1, FCC, "APL2", {
263    {149,161},
264    {  0,  0}}},
265
266    {APL3, 2, FCC, "APL3", {
267    { 52, 64},
268    {149,165}}},
269
270    {APL4, 2, FCC, "APL4", {
271    { 36, 48},
272    {149,165}}},
273};
274
275static const REG_DMN_ENUM_FREQ_TABLE regDmnEnum5Turbo[] = {
276    {DEBUG_REG_DMN, 2, 0, "NONE", {
277    {42, 58},
278    {152,160}}},
279
280    {FCC1, 2, FCC, "FCC1", {
281    {42, 58},
282    {152,160}}}
283};
284
285/* "Worldwide", 1-13
286   "Thailand", "Israel", "Jordan", "China", "Japan", "USA", "Europe", "USA Low", "Japan High", "All" */
287
288static const char *br_name[] =
289{
290	"All",
291	"Europe",
292	"USA",
293	"Japan",
294	"Europe",
295	"Europe",
296	"USA",
297	"Jordan",
298	"Israel",
299	"Europe"
300};
301
302static const REG_DMN_ENUM_FREQ_TABLE regDmnEnum2[] = {
303    {DEBUG_REG_DMN, 1, 0, "NONE", {
304    {   1,   14},
305    {   0,    0}}},
306
307    {WORLD, 1, FCC, "WORLD", {
308    {   1,   13},
309    {   0,    0}}},
310
311    {FCCA, 1, FCC, "FCCA", {
312    {   1,   11},
313    {   0,    0}}},
314
315    {MKKA, 1, MKK, "MKKA", {
316    {   1,   14},
317    {   0,    0}}},
318
319    {APLA, 1, FCC, "APLA", {
320    {   1,   13},
321    {   0,    0}}},
322
323    {APLB, 1, FCC, "APLB", {
324    {   1,   13},
325    {   0,    0}}},
326
327    {APLC, 1, FCC, "APLC", {
328    {   1,   12},
329    {   0,    0}}},
330
331    {ETSIA, 1, ETSI, "ETSIA", {
332    {  10,   13},
333    {   0,    0}}},
334
335    {ETSIB, 1, ETSI, "ETSIB", {
336    {   5,    7},
337    {   0,    0}}},
338
339    {ETSIC, 1, ETSI, "ETSIC", {
340    {   1,   13},
341    {   0,    0}}},
342
343
344};
345
346#define RDMAPPING_SIZE 32
347
348static const A_UINT16 RDMapping[RDMAPPING_SIZE][3] =
349{
350   {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN},
351   {FCC2_FCCA,     FCC2,    FCCA    },
352   {FCC2_WORLD,    FCC2,    WORLD   },
353   {FCC2_ETSIC,    FCC2,    ETSIC   },
354
355   {ETSI1_WORLD,   ETSI1,   WORLD   },
356   {ETSI2_WORLD,   ETSI2,   WORLD   },
357   {ETSI3_WORLD,   ETSI3,   WORLD   },
358   {ETSI4_WORLD,   ETSI4,   WORLD   },
359
360   {ETSI3_ETSIA,   ETSI3,   ETSIA   },
361   {ETSI4_ETSIC,   ETSI4,   ETSIC   },
362
363   {FCC1_WORLD,    FCC1,    WORLD   },
364   {FCC1_FCCA,     FCC1,    FCCA    },
365
366   {APL1_WORLD,    APL1,    WORLD   },
367   {APL2_WORLD,    APL2,    WORLD   },
368   {APL3_WORLD,    APL3,    WORLD   },
369   {APL4_WORLD,    APL4,    WORLD   },
370
371   {APL1_APLA,     APL1,    APLA    },
372   {APL1_APLB,     APL1,    APLB    },
373
374   {APL1_FCCA,     APL1,    FCCA    },
375   {APL3_FCCA,     APL3,    FCCA    },
376
377   {APL1_ETSIC,    APL1,    ETSIC   },
378   {APL2_APLC,     APL2,    APLC    },
379
380   {MKK1_MKKA,     MKK1,    MKKA    },
381   {MKK1_MKKB,     MKK1,    MKKA    },
382
383   {ETSI1_ETSIB,   ETSI1,   ETSIB   },
384
385   /*
386    * The area below is reserved for super domains
387    */
388   {WOR0_WORLD,    WOR0_WORLD,   WOR0_WORLD    },
389   {WOR1_WORLD,    WOR1_WORLD,   WOR1_WORLD    },
390   {WOR2_WORLD,    WOR2_WORLD,   WOR2_WORLD    },
391   {WOR3_WORLD,    WOR3_WORLD,   WOR3_WORLD    },
392   {WOR4_WORLD,    WOR4_WORLD,   WOR4_WORLD    },
393   {APL5_WORLD,    APL5_WORLD,   APL5_WORLD    },
394   {APL5_APLB,     APL5_APLB,    APL5_APLB     }
395};
396
397static const COUNTRY_CODE_TO_ENUM_RD allCountries[] = {
398    	{0x00, 		"DB", "NONE"         },
399    	{APL1_ETSIC,    "AR", "ARGENTINA"    },
400    	{FCC2_WORLD,    "AU", "AUSTRALIA"   },
401    	{ETSI4_WORLD,   "AT", "AUSTRIA"     },
402    	{ETSI4_WORLD,   "BE", "BELGUIM"     },
403    	{APL1_ETSIC,    "BR", "BRAZIL"      },
404    	{FCC2_FCCA,     "CA", "CANADA"      },
405    	{APL1_APLA,     "CL", "CHILE"       },
406    	{ETSI4_WORLD,   "CZ", "CZECH_REPUBLIC"},
407    	{APL1_WORLD,    "CN", "CHINA"       },
408    	{APL1_ETSIC,    "CO", "COLOMBIA"    },
409    	{ETSI4_WORLD,   "DK", "DENMARK"     },
410    	{APL2_WORLD,    "EC", "ECUADOR"     },
411    	{ETSI4_WORLD,   "FI", "FINLAND"     },
412    	{ETSI3_ETSIA,   "FR", "FRANCE"      },
413    	{ETSI4_WORLD,   "DE", "GERMANY"     },
414    	{ETSI4_WORLD,   "GR", "GREECE"      },
415    	{FCC1_WORLD,    "HK", "HONG_KONG"   },
416    	{ETSI4_ETSIC,   "HU", "HUNGARY"     },
417    	{ETSI4_WORLD,   "IS", "ICELAND"     },
418    	{ETSI4_WORLD,   "IE", "IRELAND"     },
419    	{ETSI2_WORLD,   "IT", "ITALY"       },
420    	{MKK1_MKKA,     "JP", "JAPAN"       },
421    	{APL2_APLC,     "KR", "KOREA_REPUBLIC"},
422    	{ETSI4_WORLD, 	"LI", "LIECHTENSTEIN"},
423    	{ETSI4_WORLD,   "LT", "LITHUANIA"   },
424    	{ETSI4_WORLD,   "LU", "LUXEMBOURG"  },
425    	{FCC1_WORLD,    "MO", "MACAU"       },
426    	{APL1_WORLD,    "MX", "MEXICO"      },
427    	{ETSI4_WORLD,   "MC", "MONACO"      },
428    	{ETSI1_WORLD,   "NL", "NETHERLANDS" },
429    	{FCC2_ETSIC,    "NZ", "NEW_ZEALAND" },
430    	{ETSI3_WORLD,   "NO", "NORWAY"      },
431    	{APL1_WORLD,    "PA", "PANAMA"      },
432    	{APL1_WORLD,    "PE", "PERU"        },
433    	{FCC1_WORLD,    "PH", "PHILIPPINES" },
434    	{ETSI2_WORLD,   "PL", "POLAND"      },
435        {ETSI4_WORLD,   "PT", "PORTUGAL"    },
436	{FCC1_FCCA,     "PR", "PUERTO_RICO" },
437	{APL4_WORLD,    "SG", "SINGAPORE"   },
438	{ETSI4_WORLD,   "ZA", "SOUTH_AFRICA"},
439	{ETSI4_WORLD,   "ES", "SPAIN"       },
440	{ETSI4_WORLD,   "SE", "SWEDEN"      },
441	{ETSI2_WORLD,   "CH", "SWITZERLAND" },
442	{APL3_WORLD,    "TW", "TAIWAN"      },
443	{APL2_WORLD,    "TH", "THAILAND"    },
444	{ETSI2_WORLD,   "TR", "TURKEY"      },
445	{ETSI4_WORLD, 	"GB", "UNITED_KINGDOM"},
446	{FCC1_FCCA,   	"US", "UNITED_STATES" },
447	{APL1_ETSIC,    "VE", "VENEZUELA"   },
448	{ETSI1_ETSIB,   "IR", "ISRAEL"   }
449};
450
451static const REG_DMN_ENUM_FREQ_TABLE *
452wlanGetCcTable(A_UINT16 channelFlags)
453{
454    if (channelFlags & CHANNEL_2GHZ)
455    {
456        return (&regDmnEnum2[0]);
457    }
458    else if (channelFlags & CHANNEL_5GHZ) {
459        if (channelFlags & CHANNEL_TURBO)
460        {
461            return(&regDmnEnum5Turbo[0]);
462        } else {
463            return(&regDmnEnum5[0]);
464        }
465    }
466    else {
467        // either 2 or 5 GHz flags must be set
468        //ASSERT(0);
469        return NULL;
470    }
471}
472
473static int
474wlanGetCcEntries(A_UINT16 channelFlags)
475{
476    if (channelFlags & CHANNEL_2GHZ) {
477        return(sizeof(regDmnEnum2)/sizeof(REG_DMN_ENUM_FREQ_TABLE));
478    }
479    else if (channelFlags & CHANNEL_5GHZ) {
480        if (channelFlags & CHANNEL_TURBO) {
481            return(sizeof(regDmnEnum5Turbo)/sizeof(REG_DMN_ENUM_FREQ_TABLE));
482        } else {
483            return(sizeof(regDmnEnum5)/sizeof(REG_DMN_ENUM_FREQ_TABLE));
484        }
485    }
486    else {
487        // either 2 or 5 GHz flags must be set
488        //ASSERT(0);
489        return 0;
490    }
491}
492
493void ParseReg(char *regDmnName, A_UINT16 *regDmnCode, char *country)
494{
495    char reg[5];
496
497    if (strlen(regDmnName)>=4) // With Country Code
498    {
499    	strncpy(reg, regDmnName, 4);
500    	reg[4] = 0;
501    	sscanf(reg, "%x", regDmnCode);
502    	if (country!=NULL)
503    	   strcpy(country, regDmnName+4);
504    }
505    else
506    {
507    	*regDmnCode = 0x00;
508    	regDmnName = NULL;
509    }
510}
511
512
513/***********************************************************
514 * RefreshBRCountry
515 *
516 * Print out the channel list based only on the given reg
517 * domain and turbo mode
518 */
519void
520RefreshBRCountry(char *regDmnName, char *country, char *country_code)
521{
522    A_UINT16 regDmnEnum, channelFlags, regDmnCode;
523    int i, j, regDmnEnumEntries, newPrint = 0;
524    const REG_DMN_ENUM_FREQ_TABLE *pCcTable;
525    A_UINT16 lowChannel = 24, highChannel = 220;
526
527
528    /* Add by ChenI to translate regulatory domain code */
529    ParseReg(regDmnName, &regDmnCode, country_code);
530
531    dprintf("Domain Code: %x\n", regDmnCode);
532    regDmnEnum = regDmnCode;
533
534    for(i=0; i<RDMAPPING_SIZE; i++)
535    {
536    	if (RDMapping[i][0] == regDmnCode)
537    	   break;
538    }
539
540    if (i==RDMAPPING_SIZE) i=0;
541
542    regDmnEnum = RDMapping[i][2];
543    lowChannel = 1;
544    highChannel = 14;
545    channelFlags = CHANNEL_B;
546
547    pCcTable = wlanGetCcTable(channelFlags);
548    regDmnEnumEntries = wlanGetCcEntries(channelFlags);
549
550    /* Search through Regulatory Domain (Enum) table for a match */
551    for (i = 0; i < regDmnEnumEntries; i++)
552    {
553        if (pCcTable[i].regDmnEnum == regDmnEnum)
554        {
555            dprintf("%s\n",br_name[i]);
556	    strcpy(country, br_name[i]);
557            return;
558        }
559    }
560    strcpy(country, "WorldWide");
561    return;
562}
563
564
565/***********************************************************
566 * RefreshChannelList
567 *
568 * Print out the channel list based only on the given reg
569 * domain and turbo mode
570 */
571void
572RefreshChannelList(char *regDmnName, A_UINT16 current, A_UINT16 chanList[])
573{
574    A_UINT16 regDmnEnum, channelFlags, regDmnCode;
575    int i, j, regDmnEnumEntries, newPrint = 0;
576    const REG_DMN_ENUM_FREQ_TABLE *pCcTable;
577    A_UINT16 channelSpread, searchChannel, firstChannel;
578    A_UINT16 lowChannel = 24, highChannel = 220;
579    A_UINT16 maxRdChannel = 220;
580    A_UINT16 chanIdx=0;
581
582
583    /* Add by ChenI to translate regulatory domain code */
584    ParseReg(regDmnName, &regDmnCode, NULL);
585
586    dprintf("Domain Code: %x\n", regDmnCode);
587
588    regDmnEnum = regDmnCode;
589
590    for(i=0; i<RDMAPPING_SIZE; i++)
591    {
592    	if (RDMapping[i][0] == regDmnCode)
593    	   break;
594    }
595
596    if (i==RDMAPPING_SIZE) i=0;
597
598    regDmnEnum = RDMapping[i][2];
599    lowChannel = 1;
600    highChannel = 14;
601    channelFlags = CHANNEL_B;
602
603    pCcTable = wlanGetCcTable(channelFlags);
604    regDmnEnumEntries = wlanGetCcEntries(channelFlags);
605    channelSpread = CCK_CHANNEL_SEPARATION;
606
607
608    firstChannel = 0;
609    /* Search through Regulatory Domain (Enum) table for a match */
610    for (i = 0; i < regDmnEnumEntries; i++) {
611        if (pCcTable[i].regDmnEnum == regDmnEnum) {
612            for (j = 0; j < pCcTable[i].entries; j++)
613            {
614                /* Find this channel's entry */
615                for(searchChannel = pCcTable[i].chanGroup[j].lowChannel;
616                    searchChannel <= pCcTable[i].chanGroup[j].highChannel;
617                    searchChannel += channelSpread)
618                {
619                    if ((searchChannel >= lowChannel) && (searchChannel <= highChannel) &&   (searchChannel <= maxRdChannel))
620                    {
621			chanList[chanIdx++] = searchChannel;
622			chanList[chanIdx] = -1;
623
624			if (firstChannel==0)
625			{
626			     firstChannel = searchChannel;
627			}
628
629			if (current!=999)
630			{
631			    if (current == searchChannel)
632			    {
633			       dprintf("%d", current);
634			       return;
635			    }
636			}
637			else
638			{
639                            dprintf("%d\n", searchChannel);
640                        }
641                    }
642                }
643            }
644
645            if (current!=999)
646            {
647            	 /* Find the middle channel for default value */
648            	 if (chanIdx!=0)
649            	       firstChannel = chanList[chanIdx/2];
650
651                 dprintf("%d\n", firstChannel);
652            }
653            return;
654        }
655    }
656}
657
658
659void convert_country(void)
660{
661#ifdef REMOVE
662    char *countrylist[]=
663	{"Worldwide", "Thailand", "Israel", "Jordan", "China", "Japan", "USA",
664	 "Europe", "USA Low", "Japan High", "All", NULL};
665
666    char country[32], country_code[32];
667    int i;
668
669    strcpy(country, nvram_safe_get("wl_country"));
670
671    i=0;
672    while(countrylist[i]!=NULL)
673    {
674	if (strcmp(countrylist[i], country)==0)
675	{
676		break;
677	}
678	i++;
679    }
680
681    if (countrylist[i]==NULL)
682    {
683    	RefreshBRCountry(nvram_safe_get("regulation_domain"), country, country_code);
684    	nvram_set("wl_country", country);
685	if (strlen(country_code)<2)
686		nvram_set("wl_country_code", "ALL");
687	else
688		nvram_set("wl_country_code", country_code);
689    }
690#endif
691    A_UINT16 chanList[16];
692    char chanListStr[64];
693    char reg[32];
694    int i;
695
696    strcpy(reg, nvram_safe_get("regulation_domain"));
697
698    if (strlen(reg)>4) // With Country Code
699    {
700	nvram_set("wl_country_code", reg + 4);
701    }
702    else nvram_set("wl_country_code", "ALL");
703
704    RefreshChannelList(nvram_safe_get("regulation_domain"), 999, chanList);
705
706    i=0;
707
708    *chanListStr='\0';
709    while(chanList[i]!=-1)
710    {
711         if (i==0) sprintf(chanListStr, "%d", chanList[i]);
712	 else sprintf(chanListStr, "%s %d", chanListStr, chanList[i]);
713	 i++;
714	 //printf("chan :%s\n", chanListStr);
715    }
716    nvram_set("wl_chan_list", chanListStr);
717}
718
719#define MAXBUF 32
720
721void sync_mac(char *devname, char *mac)
722{
723	int cmd, result, i, j;
724	char buf[MAXBUF], macstr[32], s[3];
725	unsigned char t;
726	srom_rw_t *srom;
727
728	if (strlen(mac)!=17) return;
729
730	//printf("dev: %s, mac : %s\n", devname, mac);
731
732	s[2] = 0;
733
734	for (i=0; i<6; i++)
735	{
736		strncpy(s, mac+i*3, 2);
737		t = (unsigned char)strtoul(s, NULL, 16);
738		if (i%2==0) macstr[i+1] = t;
739		else macstr[i-1] = t ;
740	}
741
742	srom=buf;
743	srom->byteoff=72;
744	srom->nbytes=6;
745
746	if ( (result = wl_ioctl(devname, WLC_GET_SROM, buf, MAXBUF)) == 0 )
747	{
748		for(i=0;i<6;i++)
749		{
750			//printf(" %x %x \n", buf[8+i], macstr[i]);
751		}
752
753		if (memcmp(macstr, buf+8, 6)!=0)
754		{
755			eval("nvram", "set", "asuscfewatchdog=1");
756			memcpy(buf+8, macstr, 6);
757			result = wl_ioctl(devname, WLC_SET_SROM, buf, MAXBUF);
758#ifdef WL500GX_REMOVE
759			/* setup afterburner flag */
760			wsrom_main(devname, 114, 0x20f);
761#else
762			wlan_update();
763#endif
764			return;
765		}
766	}
767	return;
768}
769
770int
771rsrom_main(char *devname, unsigned int pos, int pflag)
772{
773	int result;
774	unsigned short *oval;
775	char buf[MAXBUF];
776	srom_rw_t *srom;
777	unsigned int val;
778
779	srom = buf;
780	srom->byteoff=pos;
781	srom->nbytes=2; //sizeof(val);
782
783	if ( (result = wl_ioctl(devname, WLC_GET_SROM, buf, MAXBUF)) == 0)
784	{
785		oval =(unsigned int)(buf + 8);
786		val = (unsigned int)*oval;
787	}
788	else val = 0;
789
790	if (pflag) printf("srom[%x] : %x\n", pos, val);
791	return val;
792}
793
794int
795wsrom_main(char *devname, unsigned int pos, unsigned short val)
796{
797	int result;
798	unsigned short *oval;
799	char buf[MAXBUF];
800	srom_rw_t *srom;
801	/* Usage srom [postion] [val in 2 byte] */
802	dprintf("write %s srom[%x] : %x\n", devname, pos, val);
803	srom = buf;
804	srom->byteoff=pos;
805	srom->nbytes=2; //sizeof(val);
806
807	if ( (result = wl_ioctl(devname, WLC_GET_SROM, buf, MAXBUF)) == 0)
808	{
809		oval =(unsigned int)(buf + 8);
810
811		if (*oval!=val)
812		{
813			memcpy(buf+8, &val, sizeof(val));
814			result = wl_ioctl(devname, WLC_SET_SROM, buf, MAXBUF);			}
815	}
816	return 0;
817}
818
819void write_mac(char *devname, char *mac)
820{
821	int cmd, result, i, j;
822	char buf[MAXBUF], macstr[32], s[3];
823	unsigned char t;
824	srom_rw_t *srom;
825
826	if (strlen(mac)!=17) return;
827
828	//printf("dev: %s, mac : %s\n", devname, mac);
829
830	s[2] = 0;
831
832	for (i=0; i<6; i++)
833	{
834		strncpy(s, mac+i*3, 2);
835		t = (unsigned char)strtoul(s, NULL, 16);
836		if (i%2==0) macstr[i+1] = t;
837		else macstr[i-1] = t ;
838	}
839
840	srom=buf;
841	srom->byteoff=72;
842	srom->nbytes=6;
843
844	memcpy(buf+8, macstr, 6);
845	result = wl_ioctl(devname, WLC_SET_SROM, buf, MAXBUF);
846	return;
847}
848
849
850int
851wlan_update()
852{
853	int result;
854	unsigned short *oval;
855	char buf[MAXBUF];
856	srom_rw_t *srom;
857	unsigned short val;
858
859	/* update eerpom for driver 3.90.x.x */
860	if (nvram_match("productid", "WL500g"))
861	{
862		val = rsrom_main("eth2", 104, 0);
863		if (val==0x003c) wsrom_main("eth2", 104, 0x004c);// ver 1.6
864		else if (val==0x0035) wsrom_main("eth2", 104, 0x0046);     // ver 2.2
865		else wsrom_main("eth2", 104, 0x0046);
866		wsrom_main("eth2", 114, 0x0249);
867	}
868	else if(nvram_match("productid", "WL500g.Deluxe"))
869	{
870		// ver 2.2
871		wsrom_main("eth1", 104, 0x0046);
872		wsrom_main("eth1", 114, 0x0249);
873	}
874	return 0;
875}
876
877