1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <fcntl.h>
8#include <typedefs.h>
9#include <bcmnvram.h>
10#include <sys/ioctl.h>
11#include <ralink.h>
12#include <iwlib.h>
13#include "utils.h"
14#include "shutils.h"
15#include <shared.h>
16#include <sys/mman.h>
17#include <sys/ioctl.h>
18#include <iwlib.h>
19#ifndef O_BINARY
20#define O_BINARY 	0
21#endif
22#include <image.h>
23#ifndef MAP_FAILED
24#define MAP_FAILED (-1)
25#endif
26#include <linux_gpio.h>
27
28typedef uint32_t __u32;
29
30#if defined(RTN14U) || defined(RTAC52U) || defined(RTAC51U) || defined(RTN11P) || defined(RTN300) || defined(RTN54U) || defined(RTAC1200HP) || defined(RTN56UB1) || defined(RTN56UB2) ||defined(RTAC54U)
31const char WIF_5G[]	= "rai0";
32const char WIF_2G[]	= "ra0";
33const char WDSIF_5G[]	= "wdsi";
34const char APCLI_5G[]	= "apclii0";
35const char APCLI_2G[]	= "apcli0";
36#else
37const char WIF_5G[]	= "ra0";
38const char WIF_2G[]	= "rai0";
39const char WDSIF_5G[]	= "wds";
40const char APCLI_5G[]	= "apcli0";
41const char APCLI_2G[]	= "apclii0";
42#endif
43
44#if defined(RA_ESW)
45/* Read TX/RX byte count information from switch's register. */
46#if defined(RTCONFIG_RALINK_MT7620)
47int get_mt7620_wan_unit_bytecount(int unit, unsigned long *tx, unsigned long *rx)
48#elif defined(RTCONFIG_RALINK_MT7621)
49int get_mt7621_wan_unit_bytecount(int unit, unsigned long *tx, unsigned long *rx)
50#endif
51{
52#if defined(RTCONFIG_RALINK_MT7620)
53	return __mt7620_wan_bytecount(unit, tx, rx);
54#elif defined(RTCONFIG_RALINK_MT7621)
55	return __mt7621_wan_bytecount(unit, tx, rx);
56#endif
57}
58#endif
59uint32_t gpio_dir(uint32_t gpio, int dir)
60{
61	return ralink_gpio_init(gpio, dir);
62}
63
64uint32_t get_gpio(uint32_t gpio)
65{
66	return ralink_gpio_read_bit(gpio);
67}
68
69
70uint32_t set_gpio(uint32_t gpio, uint32_t value)
71{
72	ralink_gpio_write_bit(gpio, value);
73	return 0;
74}
75
76int get_switch_model(void)
77{
78	// TODO
79	return SWITCH_UNKNOWN;
80}
81
82uint32_t get_phy_status(uint32_t portmask)
83{
84	// TODO
85	return 1;
86}
87
88uint32_t get_phy_speed(uint32_t portmask)
89{
90	// TODO
91	return 1;
92}
93
94uint32_t set_phy_ctrl(uint32_t portmask, int ctrl)
95{
96	// TODO
97	return 1;
98}
99
100#define SWAP_LONG(x) \
101	((__u32)( \
102		(((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
103		(((__u32)(x) & (__u32)0x0000ff00UL) <<  8) | \
104		(((__u32)(x) & (__u32)0x00ff0000UL) >>  8) | \
105		(((__u32)(x) & (__u32)0xff000000UL) >> 24) ))
106
107/* 0: it is not a legal image
108 * 1: it is legal image
109 */
110int check_imageheader(char *buf, long *filelen)
111{
112	uint32_t checksum;
113	image_header_t header2;
114	image_header_t *hdr, *hdr2;
115
116	hdr  = (image_header_t *) buf;
117	hdr2 = &header2;
118
119	/* check header magic */
120	if (SWAP_LONG(hdr->ih_magic) != IH_MAGIC) {
121		_dprintf ("Bad Magic Number\n");
122		return 0;
123	}
124
125	/* check header crc */
126	memcpy (hdr2, hdr, sizeof(image_header_t));
127	hdr2->ih_hcrc = 0;
128	checksum = crc_calc(0, (const char *)hdr2, sizeof(image_header_t));
129	_dprintf("header crc: %X\n", checksum);
130	_dprintf("org header crc: %X\n", SWAP_LONG(hdr->ih_hcrc));
131	if (checksum != SWAP_LONG(hdr->ih_hcrc))
132	{
133		_dprintf("Bad Header Checksum\n");
134		return 0;
135	}
136
137	{
138		if(strcmp(buf+36, nvram_safe_get("productid"))==0) {
139			*filelen  = SWAP_LONG(hdr->ih_size);
140			*filelen += sizeof(image_header_t);
141#ifdef RTCONFIG_DSL
142			// DSL product may have modem firmware
143			*filelen+=(512*1024);
144#endif
145			_dprintf("image len: %x\n", *filelen);
146			return 1;
147		}
148	}
149	return 0;
150}
151
152int
153checkcrc(char *fname)
154{
155	int ifd = -1;
156	uint32_t checksum;
157	struct stat sbuf;
158	unsigned char *ptr = NULL;
159	image_header_t *hdr;
160	char *imagefile;
161	int ret = -1;
162	int len;
163
164	imagefile = fname;
165//	fprintf(stderr, "img file: %s\n", imagefile);
166
167	ifd = open(imagefile, O_RDONLY|O_BINARY);
168
169	if (ifd < 0) {
170		_dprintf("Can't open %s: %s\n",
171			imagefile, strerror(errno));
172		goto checkcrc_end;
173	}
174
175	/* We're a bit of paranoid */
176#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__)
177	(void) fdatasync (ifd);
178#else
179	(void) fsync (ifd);
180#endif
181	if (fstat(ifd, &sbuf) < 0) {
182		_dprintf("Can't stat %s: %s\n",
183			imagefile, strerror(errno));
184		goto checkcrc_fail;
185	}
186
187	ptr = (unsigned char *)mmap(0, sbuf.st_size,
188				    PROT_READ, MAP_SHARED, ifd, 0);
189	if (ptr == (unsigned char *)MAP_FAILED) {
190		_dprintf("Can't map %s: %s\n",
191			imagefile, strerror(errno));
192		goto checkcrc_fail;
193	}
194	hdr = (image_header_t *)ptr;
195
196	/* check image header */
197	if(check_imageheader((char*)hdr, (long*)&len) == 0)
198	{
199		_dprintf("Check image heaer fail !!!\n");
200		goto checkcrc_fail;
201	}
202
203	len = SWAP_LONG(hdr->ih_size);
204	if (sbuf.st_size < (len + sizeof(image_header_t))) {
205		_dprintf("Size mismatch %lx/%lx !!!\n", sbuf.st_size, (len + sizeof(image_header_t)));
206		goto checkcrc_fail;
207	}
208
209	/* check body crc */
210	_dprintf("Verifying Checksum ... ");
211	checksum = crc_calc(0, (const char *)ptr + sizeof(image_header_t), len);
212	if(checksum != SWAP_LONG(hdr->ih_dcrc))
213	{
214		_dprintf("Bad Data CRC\n");
215		goto checkcrc_fail;
216	}
217	_dprintf("OK\n");
218
219	ret = 0;
220
221	/* We're a bit of paranoid */
222checkcrc_fail:
223	if(ptr != NULL)
224		munmap(ptr, sbuf.st_size);
225#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__)
226	(void) fdatasync (ifd);
227#else
228	(void) fsync (ifd);
229#endif
230	if (close(ifd)) {
231		_dprintf("Read error on %s: %s\n",
232			imagefile, strerror(errno));
233		ret=-1;
234	}
235checkcrc_end:
236	return ret;
237}
238
239/*
240 * 0: illegal image
241 * 1: legal image
242 *
243 * check product id, crc ..
244 */
245
246int check_imagefile(char *fname)
247{
248	if(checkcrc(fname)==0) return 1;
249	return 0;
250}
251
252int wl_ioctl(const char *ifname, int cmd, struct iwreq *pwrq)
253{
254	int ret = 0;
255 	int s;
256
257	/* open socket to kernel */
258	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
259		perror("socket");
260		return errno;
261	}
262
263	/* do it */
264	strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
265	if ((ret = ioctl(s, cmd, pwrq)) < 0)
266		perror(pwrq->ifr_name);
267
268	/* cleanup */
269	close(s);
270	return ret;
271}
272
273unsigned int get_radio_status(char *ifname)
274{
275	struct iwreq wrq;
276	unsigned int data = 0;
277
278	wrq.u.data.length = sizeof(data);
279	wrq.u.data.pointer = (caddr_t) &data;
280	wrq.u.data.flags = ASUS_SUBCMD_RADIO_STATUS;
281	if (wl_ioctl(ifname, RTPRIV_IOCTL_ASUSCMD, &wrq) < 0)
282		printf("ioctl error\n");
283
284	return data;
285}
286
287int get_radio(int unit, int subunit)
288{
289	char tmp[100], prefix[] = "wlXXXXXXXXXXXXXX";
290
291	if (subunit > 0)
292		snprintf(prefix, sizeof(prefix), "wl%d.%d_", unit, subunit);
293	else
294		snprintf(prefix, sizeof(prefix), "wl%d_", unit);
295
296	// TODO: handle subunit
297	if (subunit > 0)
298		return nvram_match(strcat_r(prefix, "radio", tmp), "1");
299	else
300		return get_radio_status(nvram_safe_get(strcat_r(prefix, "ifname", tmp)));
301}
302
303void set_radio(int on, int unit, int subunit)
304{
305	char /*tmp[100],*/ prefix[] = "wlXXXXXXXXXXXXXX";
306
307	if (subunit > 0)
308		snprintf(prefix, sizeof(prefix), "wl%d.%d_", unit, subunit);
309	else
310		snprintf(prefix, sizeof(prefix), "wl%d_", unit);
311
312	//if (nvram_match(strcat_r(prefix, "radio", tmp), "0")) return;
313	// TODO: replace hardcoded
314	// TODO: handle subunit
315	if(unit==0)
316		doSystem("iwpriv %s set RadioOn=%d", WIF_2G, on);
317	else doSystem("iwpriv %s set RadioOn=%d", WIF_5G, on);
318
319#if defined(RTAC1200HP) || defined(RTN56UB1) || defined(RTN56UB2)//5G:7612E 2G:7603E
320	led_onoff(unit);
321#endif
322}
323
324char *wif_to_vif(char *wif)
325{
326	static char vif[32];
327	int unit = 0, subunit = 0;
328	char tmp[100], prefix[] = "wlXXXXXXXXXXXXXX";
329
330	vif[0] = '\0';
331
332	for (unit = 0; unit < 2; unit++)
333		for (subunit = 1; subunit < 4; subunit++)
334		{
335			snprintf(prefix, sizeof(prefix), "wl%d.%d", unit, subunit);
336
337			if (nvram_match(strcat_r(prefix, "_ifname", tmp), wif))
338			{
339				sprintf(vif, "%s", prefix);
340				goto RETURN_VIF;
341			}
342		}
343
344RETURN_VIF:
345	return vif;
346}
347
348
349/* get channel list via currently setting in wifi driver */
350int get_channel_list_via_driver(int unit, char *buffer, int len)
351{
352	struct iwreq wrq;
353	char tmp[128], prefix[] = "wlXXXXXXXXXX_", *ifname;
354
355	if(buffer == NULL || len <= 0)
356		return -1;
357
358	memset(buffer, 0, len);
359	snprintf(prefix, sizeof(prefix), "wl%d_", unit);
360	ifname = nvram_safe_get(strcat_r(prefix, "ifname", tmp));
361
362	memset(&wrq, 0, sizeof(wrq));
363	wrq.u.data.pointer = buffer;
364	wrq.u.data.length  = len;
365	wrq.u.data.flags   = ASUS_SUBCMD_CHLIST;
366	if (wl_ioctl(ifname, RTPRIV_IOCTL_ASUSCMD, &wrq) < 0)
367		return -1;
368
369	return wrq.u.data.length;
370}
371
372/* get channel list via value of countryCode */
373unsigned char A_BAND_REGION_0_CHANNEL_LIST[]={36, 40, 44, 48, 149, 153, 157, 161, 165};
374unsigned char A_BAND_REGION_1_CHANNEL_LIST[]={36, 40, 44, 48};
375#ifdef RTCONFIG_LOCALE2012
376unsigned char A_BAND_REGION_2_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165};
377unsigned char A_BAND_REGION_3_CHANNEL_LIST[]={52, 56, 60, 64, 149, 153, 157, 161, 165};
378#else
379unsigned char A_BAND_REGION_2_CHANNEL_LIST[]={36, 40, 44, 48};
380unsigned char A_BAND_REGION_3_CHANNEL_LIST[]={149, 153, 157, 161};
381#endif
382unsigned char A_BAND_REGION_4_CHANNEL_LIST[]={149, 153, 157, 161, 165};
383unsigned char A_BAND_REGION_5_CHANNEL_LIST[]={149, 153, 157, 161};
384#ifdef RTCONFIG_LOCALE2012
385unsigned char A_BAND_REGION_6_CHANNEL_LIST[]={36, 40, 44, 48, 132, 136, 140, 149, 153, 157, 161, 165};
386#else
387unsigned char A_BAND_REGION_6_CHANNEL_LIST[]={36, 40, 44, 48};
388#endif
389unsigned char A_BAND_REGION_7_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 169, 173};
390unsigned char A_BAND_REGION_8_CHANNEL_LIST[]={52, 56, 60, 64};
391#ifdef RTCONFIG_LOCALE2012
392unsigned char A_BAND_REGION_9_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132};
393#else
394unsigned char A_BAND_REGION_9_CHANNEL_LIST[]={36, 40, 44, 48};
395#endif
396unsigned char A_BAND_REGION_10_CHANNEL_LIST[]={36, 40, 44, 48, 149, 153, 157, 161, 165};
397unsigned char A_BAND_REGION_11_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161};
398unsigned char A_BAND_REGION_12_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
399unsigned char A_BAND_REGION_13_CHANNEL_LIST[]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161};
400unsigned char A_BAND_REGION_14_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165};
401unsigned char A_BAND_REGION_15_CHANNEL_LIST[]={149, 153, 157, 161, 165, 169, 173};
402unsigned char A_BAND_REGION_16_CHANNEL_LIST[]={52, 56, 60, 64, 149, 153, 157, 161, 165};
403unsigned char A_BAND_REGION_17_CHANNEL_LIST[]={36, 40, 44, 48, 149, 153, 157, 161};
404unsigned char A_BAND_REGION_18_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140};
405unsigned char A_BAND_REGION_19_CHANNEL_LIST[]={56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161};
406unsigned char A_BAND_REGION_20_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161};
407unsigned char A_BAND_REGION_21_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161};
408
409unsigned char G_BAND_REGION_0_CHANNEL_LIST[]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
410unsigned char G_BAND_REGION_1_CHANNEL_LIST[]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
411unsigned char G_BAND_REGION_5_CHANNEL_LIST[]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
412
413#define A_BAND_REGION_0				0
414#define A_BAND_REGION_1				1
415#define A_BAND_REGION_2				2
416#define A_BAND_REGION_3				3
417#define A_BAND_REGION_4				4
418#define A_BAND_REGION_5				5
419#define A_BAND_REGION_6				6
420#define A_BAND_REGION_7				7
421#define A_BAND_REGION_8				8
422#define A_BAND_REGION_9				9
423#define A_BAND_REGION_10			10
424#define A_BAND_REGION_11			11
425#define A_BAND_REGION_12			12
426#define A_BAND_REGION_13			13
427#define A_BAND_REGION_14			14
428#define A_BAND_REGION_15			15
429#define A_BAND_REGION_16			16
430#define A_BAND_REGION_17			17
431#define A_BAND_REGION_18			18
432#define A_BAND_REGION_19			19
433#define A_BAND_REGION_20			20
434#define A_BAND_REGION_21			21
435
436#define G_BAND_REGION_0				0
437#define G_BAND_REGION_1				1
438#define G_BAND_REGION_2				2
439#define G_BAND_REGION_3				3
440#define G_BAND_REGION_4				4
441#define G_BAND_REGION_5				5
442#define G_BAND_REGION_6				6
443
444typedef struct CountryCodeToCountryRegion {
445	unsigned char	IsoName[3];
446	unsigned char	RegDomainNum11A;
447	unsigned char	RegDomainNum11G;
448} COUNTRY_CODE_TO_COUNTRY_REGION;
449
450COUNTRY_CODE_TO_COUNTRY_REGION allCountry[] = {
451	/* {Country Number, ISO Name, Country Name, Support 11A, 11A Country Region, Support 11G, 11G Country Region} */
452	{"DB", A_BAND_REGION_7, G_BAND_REGION_5},
453	{"AL", A_BAND_REGION_0, G_BAND_REGION_1},
454	{"DZ", A_BAND_REGION_0, G_BAND_REGION_1},
455#ifdef RTCONFIG_LOCALE2012
456	{"AR", A_BAND_REGION_0, G_BAND_REGION_1},
457	{"AM", A_BAND_REGION_1, G_BAND_REGION_1},
458#else
459	{"AR", A_BAND_REGION_3, G_BAND_REGION_1},
460	{"AM", A_BAND_REGION_2, G_BAND_REGION_1},
461#endif
462	{"AU", A_BAND_REGION_0, G_BAND_REGION_1},
463	{"AT", A_BAND_REGION_1, G_BAND_REGION_1},
464#ifdef RTCONFIG_LOCALE2012
465	{"AZ", A_BAND_REGION_1, G_BAND_REGION_1},
466#else
467	{"AZ", A_BAND_REGION_2, G_BAND_REGION_1},
468#endif
469	{"BH", A_BAND_REGION_0, G_BAND_REGION_1},
470	{"BY", A_BAND_REGION_0, G_BAND_REGION_1},
471	{"BE", A_BAND_REGION_1, G_BAND_REGION_1},
472	{"BZ", A_BAND_REGION_4, G_BAND_REGION_1},
473	{"BO", A_BAND_REGION_4, G_BAND_REGION_1},
474#ifdef RTCONFIG_LOCALE2012
475	{"BR", A_BAND_REGION_4, G_BAND_REGION_1},
476#else
477	{"BR", A_BAND_REGION_1, G_BAND_REGION_1},
478#endif
479	{"BN", A_BAND_REGION_4, G_BAND_REGION_1},
480	{"BG", A_BAND_REGION_1, G_BAND_REGION_1},
481	{"CA", A_BAND_REGION_0, G_BAND_REGION_0},
482	{"CL", A_BAND_REGION_0, G_BAND_REGION_1},
483	{"CN", A_BAND_REGION_4, G_BAND_REGION_1},
484	{"CO", A_BAND_REGION_0, G_BAND_REGION_0},
485	{"CR", A_BAND_REGION_0, G_BAND_REGION_1},
486#ifdef RTCONFIG_LOCALE2012
487	{"HR", A_BAND_REGION_1, G_BAND_REGION_1},
488#else
489	{"HR", A_BAND_REGION_2, G_BAND_REGION_1},
490#endif
491	{"CY", A_BAND_REGION_1, G_BAND_REGION_1},
492#ifdef RTCONFIG_LOCALE2012
493	{"CZ", A_BAND_REGION_1, G_BAND_REGION_1},
494#else
495	{"CZ", A_BAND_REGION_2, G_BAND_REGION_1},
496#endif
497	{"DK", A_BAND_REGION_1, G_BAND_REGION_1},
498	{"DO", A_BAND_REGION_0, G_BAND_REGION_0},
499	{"EC", A_BAND_REGION_0, G_BAND_REGION_1},
500#ifdef RTCONFIG_LOCALE2012
501	{"EG", A_BAND_REGION_1, G_BAND_REGION_1},
502#else
503	{"EG", A_BAND_REGION_2, G_BAND_REGION_1},
504#endif
505	{"SV", A_BAND_REGION_0, G_BAND_REGION_1},
506	{"EE", A_BAND_REGION_1, G_BAND_REGION_1},
507	{"FI", A_BAND_REGION_1, G_BAND_REGION_1},
508#ifdef RTCONFIG_LOCALE2012
509	{"FR", A_BAND_REGION_1, G_BAND_REGION_1},
510	{"GE", A_BAND_REGION_1, G_BAND_REGION_1},
511#else
512	{"FR", A_BAND_REGION_2, G_BAND_REGION_1},
513	{"GE", A_BAND_REGION_2, G_BAND_REGION_1},
514#endif
515	{"DE", A_BAND_REGION_1, G_BAND_REGION_1},
516	{"GR", A_BAND_REGION_1, G_BAND_REGION_1},
517	{"GT", A_BAND_REGION_0, G_BAND_REGION_0},
518	{"HN", A_BAND_REGION_0, G_BAND_REGION_1},
519	{"HK", A_BAND_REGION_0, G_BAND_REGION_1},
520	{"HU", A_BAND_REGION_1, G_BAND_REGION_1},
521	{"IS", A_BAND_REGION_1, G_BAND_REGION_1},
522#ifdef RTCONFIG_LOCALE2012
523	{"IN", A_BAND_REGION_2, G_BAND_REGION_1},
524#else
525	{"IN", A_BAND_REGION_0, G_BAND_REGION_1},
526#endif
527	{"ID", A_BAND_REGION_4, G_BAND_REGION_1},
528	{"IR", A_BAND_REGION_4, G_BAND_REGION_1},
529	{"IE", A_BAND_REGION_1, G_BAND_REGION_1},
530	{"IL", A_BAND_REGION_0, G_BAND_REGION_1},
531	{"IT", A_BAND_REGION_1, G_BAND_REGION_1},
532#ifdef RTCONFIG_LOCALE2012
533	{"JP", A_BAND_REGION_1, G_BAND_REGION_1},
534#else
535	{"JP", A_BAND_REGION_9, G_BAND_REGION_1},
536#endif
537	{"JO", A_BAND_REGION_0, G_BAND_REGION_1},
538	{"KZ", A_BAND_REGION_0, G_BAND_REGION_1},
539#ifdef RTCONFIG_LOCALE2012
540	{"KP", A_BAND_REGION_1, G_BAND_REGION_1},
541	{"KR", A_BAND_REGION_1, G_BAND_REGION_1},
542#else
543	{"KP", A_BAND_REGION_5, G_BAND_REGION_1},
544	{"KR", A_BAND_REGION_5, G_BAND_REGION_1},
545#endif
546	{"KW", A_BAND_REGION_0, G_BAND_REGION_1},
547	{"LV", A_BAND_REGION_1, G_BAND_REGION_1},
548	{"LB", A_BAND_REGION_0, G_BAND_REGION_1},
549	{"LI", A_BAND_REGION_1, G_BAND_REGION_1},
550	{"LT", A_BAND_REGION_1, G_BAND_REGION_1},
551	{"LU", A_BAND_REGION_1, G_BAND_REGION_1},
552#ifdef RTCONFIG_LOCALE2012
553	{"MO", A_BAND_REGION_4, G_BAND_REGION_1},
554#else
555	{"MO", A_BAND_REGION_0, G_BAND_REGION_1},
556#endif
557	{"MK", A_BAND_REGION_0, G_BAND_REGION_1},
558	{"MY", A_BAND_REGION_0, G_BAND_REGION_1},
559#ifdef RTCONFIG_LOCALE2012
560	{"MX", A_BAND_REGION_2, G_BAND_REGION_0},
561	{"MC", A_BAND_REGION_1, G_BAND_REGION_1},
562#else
563	{"MX", A_BAND_REGION_0, G_BAND_REGION_0},
564	{"MC", A_BAND_REGION_2, G_BAND_REGION_1},
565#endif
566	{"MA", A_BAND_REGION_0, G_BAND_REGION_1},
567	{"NL", A_BAND_REGION_1, G_BAND_REGION_1},
568	{"NZ", A_BAND_REGION_0, G_BAND_REGION_1},
569#ifdef RTCONFIG_LOCALE2012
570	{"NO", A_BAND_REGION_1, G_BAND_REGION_0},
571#else
572	{"NO", A_BAND_REGION_0, G_BAND_REGION_0},
573#endif
574	{"OM", A_BAND_REGION_0, G_BAND_REGION_1},
575	{"PK", A_BAND_REGION_0, G_BAND_REGION_1},
576	{"PA", A_BAND_REGION_0, G_BAND_REGION_0},
577	{"PE", A_BAND_REGION_4, G_BAND_REGION_1},
578	{"PH", A_BAND_REGION_4, G_BAND_REGION_1},
579	{"PL", A_BAND_REGION_1, G_BAND_REGION_1},
580	{"PT", A_BAND_REGION_1, G_BAND_REGION_1},
581	{"PR", A_BAND_REGION_0, G_BAND_REGION_0},
582	{"QA", A_BAND_REGION_0, G_BAND_REGION_1},
583#ifdef RTCONFIG_LOCALE2012
584	{"RO", A_BAND_REGION_1, G_BAND_REGION_1},
585	{"RU", A_BAND_REGION_6, G_BAND_REGION_1},
586#else
587	{"RO", A_BAND_REGION_0, G_BAND_REGION_1},
588	{"RU", A_BAND_REGION_0, G_BAND_REGION_1},
589#endif
590	{"SA", A_BAND_REGION_0, G_BAND_REGION_1},
591	{"SG", A_BAND_REGION_0, G_BAND_REGION_1},
592	{"SK", A_BAND_REGION_1, G_BAND_REGION_1},
593	{"SI", A_BAND_REGION_1, G_BAND_REGION_1},
594	{"ZA", A_BAND_REGION_1, G_BAND_REGION_1},
595	{"ES", A_BAND_REGION_1, G_BAND_REGION_1},
596	{"SE", A_BAND_REGION_1, G_BAND_REGION_1},
597	{"CH", A_BAND_REGION_1, G_BAND_REGION_1},
598	{"SY", A_BAND_REGION_0, G_BAND_REGION_1},
599	{"TW", A_BAND_REGION_3, G_BAND_REGION_0},
600	{"TH", A_BAND_REGION_0, G_BAND_REGION_1},
601#ifdef RTCONFIG_LOCALE2012
602	{"TT", A_BAND_REGION_1, G_BAND_REGION_1},
603	{"TN", A_BAND_REGION_1, G_BAND_REGION_1},
604	{"TR", A_BAND_REGION_1, G_BAND_REGION_1},
605	{"UA", A_BAND_REGION_9, G_BAND_REGION_1},
606#else
607	{"TT", A_BAND_REGION_2, G_BAND_REGION_1},
608	{"TN", A_BAND_REGION_2, G_BAND_REGION_1},
609	{"TR", A_BAND_REGION_2, G_BAND_REGION_1},
610	{"UA", A_BAND_REGION_0, G_BAND_REGION_1},
611#endif
612	{"AE", A_BAND_REGION_0, G_BAND_REGION_1},
613	{"GB", A_BAND_REGION_1, G_BAND_REGION_1},
614	{"US", A_BAND_REGION_0, G_BAND_REGION_0},
615#ifdef RTCONFIG_LOCALE2012
616	{"UY", A_BAND_REGION_0, G_BAND_REGION_1},
617#else
618	{"UY", A_BAND_REGION_5, G_BAND_REGION_1},
619#endif
620	{"UZ", A_BAND_REGION_1, G_BAND_REGION_0},
621#ifdef RTCONFIG_LOCALE2012
622	{"VE", A_BAND_REGION_4, G_BAND_REGION_1},
623#else
624	{"VE", A_BAND_REGION_5, G_BAND_REGION_1},
625#endif
626	{"VN", A_BAND_REGION_0, G_BAND_REGION_1},
627	{"YE", A_BAND_REGION_0, G_BAND_REGION_1},
628	{"ZW", A_BAND_REGION_0, G_BAND_REGION_1},
629	{"",	0,	0}
630};
631
632#define NUM_OF_COUNTRIES	(sizeof(allCountry)/sizeof(COUNTRY_CODE_TO_COUNTRY_REGION))
633
634int get_channel_list_via_country(int unit, const char *country_code, char *buffer, int len)
635{
636	unsigned char *pChannelListTemp = NULL;
637	int index, num, i;
638	char *p = buffer;
639	int band = unit;
640
641	if(buffer == NULL || len <= 0)
642		return -1;
643
644	memset(buffer, 0, len);
645
646	if (band != 0 && band != 1) return -1;
647
648	for (index = 0; index < NUM_OF_COUNTRIES; index++)
649	{
650		if (strncmp((char *) allCountry[index].IsoName, country_code, 2) == 0)
651			break;
652	}
653
654	if (index >= NUM_OF_COUNTRIES) return 0;
655
656	if (band == 1)
657	switch (allCountry[index].RegDomainNum11A)
658	{
659		case A_BAND_REGION_0:
660			num = sizeof(A_BAND_REGION_0_CHANNEL_LIST)/sizeof(unsigned char);
661			pChannelListTemp = A_BAND_REGION_0_CHANNEL_LIST;
662			break;
663		case A_BAND_REGION_1:
664			num = sizeof(A_BAND_REGION_1_CHANNEL_LIST)/sizeof(unsigned char);
665			pChannelListTemp = A_BAND_REGION_1_CHANNEL_LIST;
666			break;
667		case A_BAND_REGION_2:
668			num = sizeof(A_BAND_REGION_2_CHANNEL_LIST)/sizeof(unsigned char);
669			pChannelListTemp = A_BAND_REGION_2_CHANNEL_LIST;
670			break;
671		case A_BAND_REGION_3:
672			num = sizeof(A_BAND_REGION_3_CHANNEL_LIST)/sizeof(unsigned char);
673			pChannelListTemp = A_BAND_REGION_3_CHANNEL_LIST;
674			break;
675		case A_BAND_REGION_4:
676			num = sizeof(A_BAND_REGION_4_CHANNEL_LIST)/sizeof(unsigned char);
677			pChannelListTemp = A_BAND_REGION_4_CHANNEL_LIST;
678			break;
679		case A_BAND_REGION_5:
680			num = sizeof(A_BAND_REGION_5_CHANNEL_LIST)/sizeof(unsigned char);
681			pChannelListTemp = A_BAND_REGION_5_CHANNEL_LIST;
682			break;
683		case A_BAND_REGION_6:
684			num = sizeof(A_BAND_REGION_6_CHANNEL_LIST)/sizeof(unsigned char);
685			pChannelListTemp = A_BAND_REGION_6_CHANNEL_LIST;
686			break;
687		case A_BAND_REGION_7:
688			num = sizeof(A_BAND_REGION_7_CHANNEL_LIST)/sizeof(unsigned char);
689			pChannelListTemp = A_BAND_REGION_7_CHANNEL_LIST;
690			break;
691		case A_BAND_REGION_8:
692			num = sizeof(A_BAND_REGION_8_CHANNEL_LIST)/sizeof(unsigned char);
693			pChannelListTemp = A_BAND_REGION_8_CHANNEL_LIST;
694			break;
695		case A_BAND_REGION_9:
696			num = sizeof(A_BAND_REGION_9_CHANNEL_LIST)/sizeof(unsigned char);
697			pChannelListTemp = A_BAND_REGION_9_CHANNEL_LIST;
698			break;
699		case A_BAND_REGION_10:
700			num = sizeof(A_BAND_REGION_10_CHANNEL_LIST)/sizeof(unsigned char);
701			pChannelListTemp = A_BAND_REGION_10_CHANNEL_LIST;
702			break;
703		case A_BAND_REGION_11:
704			num = sizeof(A_BAND_REGION_11_CHANNEL_LIST)/sizeof(unsigned char);
705			pChannelListTemp = A_BAND_REGION_11_CHANNEL_LIST;
706			break;
707		case A_BAND_REGION_12:
708			num = sizeof(A_BAND_REGION_12_CHANNEL_LIST)/sizeof(unsigned char);
709			pChannelListTemp = A_BAND_REGION_12_CHANNEL_LIST;
710			break;
711		case A_BAND_REGION_13:
712			num = sizeof(A_BAND_REGION_13_CHANNEL_LIST)/sizeof(unsigned char);
713			pChannelListTemp = A_BAND_REGION_13_CHANNEL_LIST;
714			break;
715		case A_BAND_REGION_14:
716			num = sizeof(A_BAND_REGION_14_CHANNEL_LIST)/sizeof(unsigned char);
717			pChannelListTemp = A_BAND_REGION_14_CHANNEL_LIST;
718			break;
719		case A_BAND_REGION_15:
720			num = sizeof(A_BAND_REGION_15_CHANNEL_LIST)/sizeof(unsigned char);
721			pChannelListTemp = A_BAND_REGION_15_CHANNEL_LIST;
722			break;
723		case A_BAND_REGION_16:
724			num = sizeof(A_BAND_REGION_16_CHANNEL_LIST)/sizeof(unsigned char);
725			pChannelListTemp = A_BAND_REGION_16_CHANNEL_LIST;
726			break;
727		case A_BAND_REGION_17:
728			num = sizeof(A_BAND_REGION_17_CHANNEL_LIST)/sizeof(unsigned char);
729			pChannelListTemp = A_BAND_REGION_17_CHANNEL_LIST;
730			break;
731		case A_BAND_REGION_18:
732			num = sizeof(A_BAND_REGION_18_CHANNEL_LIST)/sizeof(unsigned char);
733			pChannelListTemp = A_BAND_REGION_18_CHANNEL_LIST;
734			break;
735		case A_BAND_REGION_19:
736			num = sizeof(A_BAND_REGION_19_CHANNEL_LIST)/sizeof(unsigned char);
737			pChannelListTemp = A_BAND_REGION_19_CHANNEL_LIST;
738			break;
739		case A_BAND_REGION_20:
740			num = sizeof(A_BAND_REGION_20_CHANNEL_LIST)/sizeof(unsigned char);
741			pChannelListTemp = A_BAND_REGION_20_CHANNEL_LIST;
742			break;
743		case A_BAND_REGION_21:
744			num = sizeof(A_BAND_REGION_21_CHANNEL_LIST)/sizeof(unsigned char);
745			pChannelListTemp = A_BAND_REGION_21_CHANNEL_LIST;
746			break;
747		default:	// Error. should never happen
748			dbg("countryregionA=%d not support", allCountry[index].RegDomainNum11A);
749			break;
750	}
751	else if (band == 0)
752	switch (allCountry[index].RegDomainNum11G)
753	{
754		case G_BAND_REGION_0:
755			num = sizeof(G_BAND_REGION_0_CHANNEL_LIST)/sizeof(unsigned char);
756			pChannelListTemp = G_BAND_REGION_0_CHANNEL_LIST;
757			break;
758		case G_BAND_REGION_1:
759			num = sizeof(G_BAND_REGION_1_CHANNEL_LIST)/sizeof(unsigned char);
760			pChannelListTemp = G_BAND_REGION_1_CHANNEL_LIST;
761			break;
762		case G_BAND_REGION_5:
763			num = sizeof(G_BAND_REGION_5_CHANNEL_LIST)/sizeof(unsigned char);
764			pChannelListTemp = G_BAND_REGION_5_CHANNEL_LIST;
765			break;
766		default:	// Error. should never happen
767			dbg("countryregionG=%d not support", allCountry[index].RegDomainNum11G);
768			break;
769	}
770
771	if (pChannelListTemp != NULL)
772	{
773		for (i = 0; i < num; i++)
774		{
775#if 0
776			if (i == 0)
777				p += sprintf(p, "\"%d\"", pChannelListTemp[i]);
778			else
779				p += sprintf(p,  ", \"%d\"", pChannelListTemp[i]);
780#else
781			if (i == 0)
782				p += sprintf(p, "%d", pChannelListTemp[i]);
783			else
784				p += sprintf(p,  ",%d", pChannelListTemp[i]);
785#endif
786		}
787	}
788
789	return (p - buffer);
790}
791
792
793#if defined(RTAC1200HP) || defined(RTN56UB1) || defined(RTN56UB2)
794void led_onoff(int unit)
795{
796#if defined(RTAC1200HP)
797	if(unit==1)
798#endif
799		if(get_radio(unit, 0))
800			led_control(unit?LED_5G:LED_2G, LED_ON);
801		else
802			led_control(unit?LED_5G:LED_2G, LED_OFF);
803}
804#endif
805