2 * wlc - Broadcom Wireless Driver Control Utility
4 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include <sys/types.h>
29 #include <proto/802.11.h>
33 #define PTABLE_MAGIC 0xbadc0ded
38 #define PTABLE_END 0xffffffff
41 * Copy each token in wordlist delimited by space into word
42 * Taken from Broadcom shutils.h
44 #define foreach(word, wordlist, next) \
45 for (next = &wordlist[strspn(wordlist, " ")], \
46 strncpy(word, next, sizeof(word)), \
47 word[strcspn(word, " ")] = '\0', \
48 word[sizeof(word) - 1] = '\0', \
49 next = strchr(next, ' '); \
51 next = next ? &next[strspn(next, " ")] : "", \
52 strncpy(word, next, sizeof(word)), \
53 word[strcspn(word, " ")] = '\0', \
54 word[sizeof(word) - 1] = '\0', \
55 next = strchr(next, ' '))
57 static char wlbuf
[8192];
58 static char interface
[16] = "wl0";
59 static unsigned long ptable
[128];
60 static unsigned long kmem_offset
= 0;
61 static int vif
= 0, debug
= 1, fromstdin
= 0;
72 PARAM_OPTIONS
= 0x0f0,
84 int (*handler
)(wlc_param param
, void *data
, void *value
);
93 /* can't use the system include because of the stupid broadcom header files */
94 extern struct ether_addr
*ether_aton(const char *asc
);
95 static inline int my_ether_ntoa(unsigned char *ea
, char *buf
)
97 return sprintf(buf
, "%02x:%02x:%02x:%02x:%02x:%02x",
98 ea
[0], ea
[1], ea
[2], ea
[3], ea
[4], ea
[5]);
102 * find the starting point of wl.o in memory
103 * by reading /proc/ksyms
105 static inline void wlc_get_mem_offset(void)
110 /* yes, i'm lazy ;) */
111 f
= popen("grep '\\[wl]' /proc/ksyms | sort", "r");
112 if (fgets(s
, 64, f
) == 0)
118 kmem_offset
= strtoul(s
, NULL
, 16);
121 if (kmem_offset
< 0xc0000000)
126 static int ptable_init(void)
132 if (ptable
[0] == PTABLE_MAGIC
)
135 glob("/lib/modules/2.4.*/wl.o.patch", 0, NULL
, &globbuf
);
137 if (globbuf
.gl_pathv
[0] == NULL
)
140 if ((fd
= open(globbuf
.gl_pathv
[0], O_RDONLY
)) < 0)
143 if (fstat(fd
, &statbuf
) < 0)
146 if (statbuf
.st_size
< 512)
149 if (read(fd
, ptable
, 512) < 512)
152 if (ptable
[0] != PTABLE_MAGIC
)
157 wlc_get_mem_offset();
158 if (kmem_offset
== 0)
169 static inline unsigned long wlc_kmem_read(unsigned long offset
)
174 if ((fd
= open("/dev/kmem", O_RDONLY
)) < 0)
177 lseek(fd
, 0x70000000, SEEK_SET
);
178 lseek(fd
, (kmem_offset
- 0x70000000) + offset
, SEEK_CUR
);
185 static inline void wlc_kmem_write(unsigned long offset
, unsigned long value
)
189 if ((fd
= open("/dev/kmem", O_WRONLY
)) < 0)
192 lseek(fd
, 0x70000000, SEEK_SET
);
193 lseek(fd
, (kmem_offset
- 0x70000000) + offset
, SEEK_CUR
);
194 write(fd
, &value
, 4);
198 static int wlc_patcher_getval(unsigned long key
, unsigned long *val
)
200 unsigned long *pt
= &ptable
[1];
203 if (ptable_init() < 0) {
204 fprintf(stderr
, "Could not load the ptable\n");
208 while (*pt
!= PTABLE_END
) {
210 tmp
= wlc_kmem_read(pt
[1]);
225 static int wlc_patcher_setval(unsigned long key
, unsigned long val
)
227 unsigned long *pt
= &ptable
[1];
229 if (ptable_init() < 0) {
230 fprintf(stderr
, "Could not load the ptable\n");
234 if (val
!= 0xffffffff)
235 val
= (pt
[2] & ~(0xffff)) | (val
& 0xffff);
237 while (*pt
!= PTABLE_END
) {
239 if (val
== 0xffffffff) /* default */
242 wlc_kmem_write(pt
[1], val
);
250 static int wlc_slottime(wlc_param param
, void *data
, void *value
)
252 int *val
= (int *) value
;
255 if ((param
& PARAM_MODE
) == SET
) {
256 wlc_patcher_setval(PTABLE_SLT1
, *val
);
257 wlc_patcher_setval(PTABLE_SLT2
, ((*val
== -1) ? *val
: *val
+ 510));
258 } else if ((param
& PARAM_MODE
) == GET
) {
259 ret
= wlc_patcher_getval(PTABLE_SLT1
, (unsigned long *) val
);
260 if (*val
!= 0xffffffff)
267 static int wlc_noack(wlc_param param
, void *data
, void *value
)
269 int *val
= (int *) value
;
272 if ((param
& PARAM_MODE
) == SET
) {
273 wlc_patcher_setval(PTABLE_ACKW
, ((*val
) ? 1 : 0));
274 } else if ((param
& PARAM_MODE
) == GET
) {
275 ret
= wlc_patcher_getval(PTABLE_ACKW
, (unsigned long *) val
);
277 *val
= (*val
? 1 : 0);
283 static int wlc_ibss_merge(wlc_param param
, void *data
, void *value
)
285 int *val
= (int *) value
;
288 if ((param
& PARAM_MODE
) == SET
) {
289 /* overwrite the instruction with 'lui v0,0x0' - fake a return
290 * status of 0 for wlc_bcn_tsf_later */
291 wlc_patcher_setval(PTABLE_ACKW
, ((*val
) ? -1 : 0x3c020000));
292 } else if ((param
& PARAM_MODE
) == GET
) {
293 ret
= wlc_patcher_getval(PTABLE_ACKW
, (unsigned long *) val
);
294 *val
= ((*val
== -1) ? 1 : 0);
300 static int wlc_ioctl(wlc_param param
, void *data
, void *value
)
302 unsigned int *var
= ((unsigned int *) data
);
303 unsigned int ioc
= *var
;
306 return wl_ioctl(interface
, ioc
, NULL
, 0);
308 switch(param
& PARAM_TYPE
) {
310 return wl_ioctl(interface
, ((param
& SET
) ? (ioc
) : (ioc
>> 16)) & 0xffff, value
, sizeof(int));
312 return wl_ioctl(interface
, ((param
& SET
) ? (ioc
) : (ioc
>> 16)) & 0xffff, value
, BUFSIZE
);
317 static int wlc_iovar(wlc_param param
, void *data
, void *value
)
319 int *val
= (int *) value
;
320 char *iov
= *((char **) data
);
324 switch(param
& PARAM_TYPE
) {
326 ret
= wl_iovar_setint(interface
, iov
, *val
);
330 switch(param
& PARAM_TYPE
) {
332 ret
= wl_iovar_getint(interface
, iov
, val
);
339 static int wlc_bssiovar(wlc_param param
, void *data
, void *value
)
341 int *val
= (int *) value
;
342 char *iov
= *((char **) data
);
346 switch(param
& PARAM_TYPE
) {
348 ret
= wl_bssiovar_setint(interface
, iov
, vif
, *val
);
352 switch(param
& PARAM_TYPE
) {
354 ret
= wl_bssiovar_getint(interface
, iov
, vif
, val
);
361 static int wlc_vif_enabled(wlc_param param
, void *data
, void *value
)
363 int *val
= (int *) value
;
367 sprintf((char *) buf
, "bss");
370 buf
[2] = (*val
? 1 : 0);
371 ret
= wl_ioctl(interface
, WLC_SET_VAR
, buf
, sizeof(buf
));
372 } else if (param
& GET
) {
373 ret
= wl_ioctl(interface
, WLC_GET_VAR
, buf
, sizeof(buf
));
380 static int wlc_ssid(wlc_param param
, void *data
, void *value
)
382 int ret
= -1, ret2
= -1;
383 char *dest
= (char *) value
;
386 if ((param
& PARAM_MODE
) == GET
) {
387 ret
= wl_bssiovar_get(interface
, "ssid", vif
, &ssid
, sizeof(ssid
));
390 /* if we can't get the ssid through the bssiovar, try WLC_GET_SSID */
391 ret
= wl_ioctl(interface
, WLC_GET_SSID
, &ssid
, sizeof(ssid
));
394 memcpy(dest
, ssid
.SSID
, ssid
.SSID_len
);
395 dest
[ssid
.SSID_len
] = 0;
397 } else if ((param
& PARAM_MODE
) == SET
) {
398 strncpy(ssid
.SSID
, value
, 32);
399 ssid
.SSID_len
= strlen(value
);
401 if (ssid
.SSID_len
> 32)
405 /* for the main interface, also try the WLC_SET_SSID call */
406 ret2
= wl_ioctl(interface
, WLC_SET_SSID
, &ssid
, sizeof(ssid
));
409 ret
= wl_bssiovar_set(interface
, "ssid", vif
, &ssid
, sizeof(ssid
));
410 ret
= (!ret2
? 0 : ret
);
416 static int wlc_int(wlc_param param
, void *data
, void *value
)
418 int *var
= *((int **) data
);
419 int *val
= (int *) value
;
421 if ((param
& PARAM_MODE
) == SET
) {
423 } else if ((param
& PARAM_MODE
) == GET
) {
430 static int wlc_flag(wlc_param param
, void *data
, void *value
)
432 int *var
= *((int **) data
);
439 static int wlc_string(wlc_param param
, void *data
, void *value
)
441 char *var
= *((char **) data
);
443 if ((param
& PARAM_MODE
) == GET
) {
450 static int wlc_afterburner(wlc_param param
, void *data
, void *value
)
452 int *val
= (int *) value
;
455 if ((param
& PARAM_MODE
) == GET
) {
456 ret
= wl_iovar_getint(interface
, "afterburner", val
);
458 wl_iovar_setint(interface
, "wlfeatureflag", (*val
? 3 : 0));
459 ret
= wl_iovar_setint(interface
, "afterburner", (*val
? 1 : 0));
460 wl_iovar_setint(interface
, "afterburner_override", *val
);
466 static int wlc_maclist(wlc_param param
, void *data
, void *value
)
468 unsigned int *var
= ((unsigned int *) data
);
469 unsigned int ioc
= *var
;
470 int limit
= (sizeof(wlbuf
) - 4) / sizeof(struct ether_addr
);
471 struct maclist
*list
= (struct maclist
*) wlbuf
;
472 char *str
= (char *) value
;
474 struct ether_addr
*addr
;
478 if ((param
& PARAM_MODE
) == GET
) {
480 ret
= wl_ioctl(interface
, (ioc
>> 16) & 0xffff, wlbuf
, sizeof(wlbuf
));
483 while (list
->count
) {
484 str
+= sprintf(str
, "%s", ((((char *) value
) == str
) ? "" : " "));
485 str
+= my_ether_ntoa((unsigned char *) &list
->ea
[list
->count
-- - 1], str
);
490 while (*str
&& isspace(*str
))
497 if (wl_ioctl(interface
, (ioc
>> 16) & 0xffff, wlbuf
, sizeof(wlbuf
)) == 0)
500 while (*str
&& isspace(*str
))
505 memset(wlbuf
, 0, sizeof(wlbuf
));
507 foreach(astr
, str
, p
) {
508 if (list
->count
>= limit
)
511 if ((addr
= ether_aton(astr
)) != NULL
)
512 memcpy(&list
->ea
[list
->count
++], addr
, sizeof(struct ether_addr
));
515 return wl_ioctl(interface
, ioc
& 0xffff, wlbuf
, sizeof(wlbuf
));
519 static int wlc_radio(wlc_param param
, void *data
, void *value
)
521 int *val
= (int *) value
;
524 if ((param
& PARAM_MODE
) == GET
) {
525 ret
= wl_ioctl(interface
, WLC_GET_RADIO
, val
, sizeof(int));
526 *val
= ((*val
& 1) ? 0 : 1);
528 *val
= (1 << 16) | (*val
? 0 : 1);
529 ret
= wl_ioctl(interface
, WLC_SET_RADIO
, val
, sizeof(int));
535 static int wlc_wsec_key(wlc_param param
, void *null
, void *value
)
537 wl_wsec_key_t wsec_key
;
538 unsigned char *index
= value
;
541 unsigned char hex
[3];
543 if ((param
& PARAM_MODE
) != SET
)
546 memset(&wsec_key
, 0, sizeof(wsec_key
));
547 if (index
[0] == '=') {
548 wsec_key
.flags
= WL_PRIMARY_KEY
;
552 if ((index
[0] < '1') || (index
[0] > '4') || (index
[1] != ','))
556 if (strncmp(key
, "d:", 2) == 0) { /* delete key */
557 } else if (strncmp(key
, "s:", 2) == 0) { /* ascii key */
559 wsec_key
.len
= strlen(key
);
561 if ((wsec_key
.len
!= 5) && (wsec_key
.len
!= 13))
564 strcpy(wsec_key
.data
, key
);
565 } else { /* hex key */
566 wsec_key
.len
= strlen(key
);
567 if ((wsec_key
.len
!= 10) && (wsec_key
.len
!= 26))
571 data
= wsec_key
.data
;
576 *(data
++) = (unsigned char) strtoul(hex
, NULL
, 16);
580 return wl_bssiovar_set(interface
, "wsec_key", vif
, &wsec_key
, sizeof(wsec_key
));
583 static inline int cw2ecw(int cw
)
586 for (cw
++, i
= 0; cw
; i
++) cw
>>=1;
590 static int wlc_wme_ac(wlc_param param
, void *data
, void *value
)
592 char *type
= *((char **) data
);
593 char *settings
= (char *) value
;
594 char cmd
[100], *p
, *val
;
595 edcf_acparam_t params
[AC_COUNT
];
601 if ((param
& PARAM_MODE
) != SET
)
604 memset(params
, 0, sizeof(params
));
605 ret
= wl_iovar_get(interface
, type
, params
, sizeof(params
));
606 memset(buf
, 0, BUFSIZE
);
608 buf
+= strlen(buf
) + 1;
610 foreach(cmd
, settings
, p
) {
611 val
= strchr(cmd
, '=');
613 if (strcmp(cmd
, "be") == 0)
615 else if (strcmp(cmd
, "bk") == 0)
617 else if (strcmp(cmd
, "vi") == 0)
619 else if (strcmp(cmd
, "vo") == 0)
625 params
[cur
].ACI
= (params
[cur
].ACI
& (0x3 << 5)) | (cur
<< 5);
629 intval
= strtoul(val
, NULL
, 10);
630 if (strcmp(cmd
, "cwmin") == 0)
631 params
[cur
].ECW
= (params
[cur
].ECW
& ~(0xf)) | cw2ecw(intval
);
632 else if (strcmp(cmd
, "ecwmin") == 0)
633 params
[cur
].ECW
= (params
[cur
].ECW
& ~(0xf)) | (intval
& 0xf);
634 else if (strcmp(cmd
, "cwmax") == 0)
635 params
[cur
].ECW
= (params
[cur
].ECW
& ~(0xf << 4)) | (cw2ecw(intval
) << 4);
636 else if (strcmp(cmd
, "ecwmax") == 0)
637 params
[cur
].ECW
= (params
[cur
].ECW
& ~(0xf << 4)) | ((intval
& 0xf) << 4);
638 else if (strcmp(cmd
, "aifsn") == 0)
639 params
[cur
].ACI
= (params
[cur
].ACI
& ~(0xf)) | (intval
& 0xf);
640 else if (strcmp(cmd
, "txop") == 0)
641 params
[cur
].TXOP
= intval
>> 5;
642 else if (strcmp(cmd
, "force") == 0)
643 params
[cur
].ACI
= (params
[cur
].ACI
& ~(1 << 4)) | ((intval
) ? (1 << 4) : 0);
646 memcpy(buf
, ¶ms
[cur
], sizeof(edcf_acparam_t
));
647 wl_ioctl(interface
, WLC_SET_VAR
, wlbuf
, BUFSIZE
);
653 static int wlc_ifname(wlc_param param
, void *data
, void *value
)
655 char *val
= (char *) value
;
659 if (strlen(val
) < 16)
660 strcpy(interface
, val
);
664 strcpy(val
, interface
);
670 static int wlc_wdsmac(wlc_param param
, void *data
, void *value
)
672 unsigned char mac
[6];
675 ret
= wl_ioctl(interface
, WLC_WDS_GET_REMOTE_HWADDR
, &mac
, 6);
677 my_ether_ntoa(mac
, value
);
682 static const struct wlc_call wlc_calls
[] = {
685 .param
= STRING
|NOARG
,
686 .handler
= wlc_string
,
688 .desc
= "Version of this program"
695 .desc
= "wlc debug level"
701 .data
.ptr
= &fromstdin
,
702 .desc
= "Accept input from stdin"
707 .handler
= wlc_ifname
,
708 .desc
= "interface to send commands to"
713 .handler
= wlc_ioctl
,
715 .desc
= "Bring the interface up"
720 .handler
= wlc_ioctl
,
721 .data
.num
= WLC_DOWN
,
722 .desc
= "Bring the interface down"
727 .handler
= wlc_radio
,
728 .desc
= "Radio enabled flag"
733 .handler
= wlc_ioctl
,
734 .data
.num
= ((WLC_GET_AP
<< 16) | WLC_SET_AP
),
735 .desc
= "Access Point mode"
740 .handler
= wlc_iovar
,
742 .desc
= "Multi-ssid mode"
747 .handler
= wlc_iovar
,
749 .desc
= "AP+STA mode"
754 .handler
= wlc_ioctl
,
755 .data
.num
= ((WLC_GET_INFRA
<< 16) | WLC_SET_INFRA
),
756 .desc
= "Infrastructure mode"
761 .handler
= wlc_ioctl
,
762 .data
.num
= ((WLC_GET_WET
<< 16) | WLC_SET_WET
),
763 .desc
= "Wireless repeater mode",
766 .name
= "statimeout",
768 .handler
= wlc_iovar
,
769 .data
.str
= "sta_retry_time",
770 .desc
= "STA connection timeout"
775 .handler
= wlc_ioctl
,
776 .data
.num
= ((WLC_GET_COUNTRY
<< 16) | WLC_SET_COUNTRY
),
777 .desc
= "Country code"
782 .handler
= wlc_ioctl
,
783 .data
.num
= ((WLC_GET_CHANNEL
<< 16) | WLC_SET_CHANNEL
),
789 .handler
= wlc_bssiovar
,
790 .data
.str
= "vlan_mode",
791 .desc
= "Parse 802.1Q tags",
798 .desc
= "Current vif index"
803 .handler
= wlc_vif_enabled
,
804 .desc
= "vif enabled flag"
810 .desc
= "Interface ESSID"
815 .handler
= wlc_bssiovar
,
816 .data
.str
= "closednet",
817 .desc
= "Hidden ESSID flag"
822 .handler
= wlc_bssiovar
,
824 .desc
= "Security mode flags"
829 .handler
= wlc_wsec_key
,
830 .desc
= "Set/Remove WEP keys"
833 .name
= "wsec_restrict",
835 .handler
= wlc_bssiovar
,
836 .data
.str
= "wsec_restrict",
837 .desc
= "Drop unencrypted traffic"
840 .name
= "eap_restrict",
842 .handler
= wlc_bssiovar
,
843 .data
.str
= "eap_restrict",
844 .desc
= "Only allow 802.1X traffic until 802.1X authorized"
849 .handler
= wlc_bssiovar
,
850 .data
.str
= "wpa_auth",
851 .desc
= "WPA authentication modes"
854 .name
= "ap_isolate",
856 .handler
= wlc_bssiovar
,
857 .data
.str
= "ap_isolate",
858 .desc
= "Isolate connected clients"
861 .name
= "supplicant",
863 .handler
= wlc_iovar
,
864 .data
.str
= "sup_wpa",
865 .desc
= "Built-in WPA supplicant"
870 .handler
= wlc_iovar
,
871 .data
.str
= "maxassoc",
872 .desc
= "Max. number of associated clients",
877 .handler
= wlc_iovar
,
879 .desc
= "WME enabled"
884 .handler
= wlc_wme_ac
,
885 .data
.str
= "wme_ac_ap",
886 .desc
= "Set WME AC options for AP mode",
889 .name
= "wme_ac_sta",
891 .handler
= wlc_wme_ac
,
892 .data
.str
= "wme_ac_sta",
893 .desc
= "Set WME AC options for STA mode",
898 .handler
= wlc_iovar
,
899 .data
.str
= "wme_noack",
900 .desc
= "WME ACK disable request",
903 .name
= "fragthresh",
905 .handler
= wlc_iovar
,
906 .data
.str
= "fragthresh",
907 .desc
= "Fragmentation threshold",
912 .handler
= wlc_iovar
,
913 .data
.str
= "rtsthresh",
914 .desc
= "RTS threshold"
919 .handler
= wlc_ioctl
,
920 .data
.num
= ((WLC_GET_ANTDIV
<< 16) | WLC_SET_ANTDIV
),
921 .desc
= "Rx antenna selection"
926 .handler
= wlc_ioctl
,
927 .data
.num
= ((WLC_GET_TXANT
<< 16) | WLC_SET_TXANT
),
928 .desc
= "Tx antenna selection"
933 .handler
= wlc_ioctl
,
934 .data
.num
= ((WLC_GET_DTIMPRD
<< 16) | WLC_SET_DTIMPRD
),
935 .desc
= "DTIM period",
940 .handler
= wlc_ioctl
,
941 .data
.num
= ((WLC_GET_BCNPRD
<< 16) | WLC_SET_BCNPRD
),
942 .desc
= "Beacon interval"
945 .name
= "frameburst",
947 .handler
= wlc_ioctl
,
948 .data
.num
= ((WLC_GET_FAKEFRAG
<< 16) | WLC_SET_FAKEFRAG
),
949 .desc
= "Framebursting"
954 .handler
= wlc_ioctl
,
955 .data
.num
= ((WLC_GET_MONITOR
<< 16) | WLC_SET_MONITOR
),
956 .desc
= "Monitor mode"
961 .handler
= wlc_ioctl
,
962 .data
.num
= ((WLC_GET_PASSIVE
<< 16) | WLC_SET_PASSIVE
),
963 .desc
= "Passive mode"
968 .handler
= wlc_ioctl
,
969 .data
.num
= ((WLC_GET_MACMODE
<< 16) | WLC_SET_MACMODE
),
970 .desc
= "MAC filter mode (0:disabled, 1:deny, 2:allow)"
975 .data
.num
= ((WLC_GET_MACLIST
<< 16) | WLC_SET_MACLIST
),
976 .handler
= wlc_maclist
,
977 .desc
= "MAC filter list"
982 .handler
= wlc_ioctl
,
983 .data
.num
= ((WLC_GET_LAZYWDS
<< 16) | WLC_SET_LAZYWDS
),
984 .desc
= "Automatic WDS"
989 .data
.num
= ((WLC_GET_WDSLIST
<< 16) | WLC_SET_WDSLIST
),
990 .handler
= wlc_maclist
,
991 .desc
= "WDS connection list"
994 .name
= "wdstimeout",
996 .handler
= wlc_iovar
,
997 .data
.str
= "wdstimeout",
998 .desc
= "WDS link detection timeout"
1002 .param
= STRING
|NOARG
,
1003 .handler
= wlc_wdsmac
,
1004 .desc
= "MAC of the remote WDS endpoint (only with wds0.* interfaces)"
1007 .name
= "afterburner",
1009 .handler
= wlc_afterburner
,
1010 .desc
= "Broadcom Afterburner"
1015 .handler
= wlc_slottime
,
1016 .desc
= "Slot time (-1 = auto)"
1021 .handler
= wlc_noack
,
1022 .desc
= "Tx ACK enabled flag"
1025 .name
= "ibss_merge",
1027 .handler
= wlc_ibss_merge
,
1028 .desc
= "Allow IBSS merge in Ad-Hoc mode"
1031 #define wlc_calls_size (sizeof(wlc_calls) / sizeof(struct wlc_call))
1033 static void usage(char *cmd
)
1036 fprintf(stderr
, "Usage: %s <command> [<argument> ...]\n"
1038 "Available commands:\n", cmd
);
1039 for (i
= 0; i
< wlc_calls_size
; i
++) {
1040 fprintf(stderr
, "\t%-16s\t%s\n", wlc_calls
[i
].name
?: "", wlc_calls
[i
].desc
?: "");
1042 fprintf(stderr
, "\n");
1046 static int do_command(const struct wlc_call
*cmd
, char *arg
)
1048 static char buf
[BUFSIZE
];
1055 fprintf(stderr
, "do_command %-16s\t'%s'\n", cmd
->name
, arg
);
1058 if ((arg
== NULL
) && ((cmd
->param
& PARAM_TYPE
) != NONE
)) {
1060 ret
= cmd
->handler(cmd
->param
| GET
, (void *) &cmd
->data
, (void *) buf
);
1062 switch(cmd
->param
& PARAM_TYPE
) {
1064 intval
= *((int *) buf
);
1067 format
= "0x%08x\n";
1068 else if (intval
> 255)
1069 format
= "0x%04x\n";
1073 fprintf(stdout
, format
, intval
);
1076 fprintf(stdout
, "%s\n", buf
);
1081 switch(cmd
->param
& PARAM_TYPE
) {
1083 intval
= strtoul(arg
, &end
, 10);
1084 if (end
&& !(*end
)) {
1085 memcpy(buf
, &intval
, sizeof(intval
));
1087 fprintf(stderr
, "%s: Invalid argument\n", cmd
->name
);
1092 strncpy(buf
, arg
, BUFSIZE
);
1093 buf
[BUFSIZE
- 1] = 0;
1096 ret
= cmd
->handler(cmd
->param
| SET
, (void *) &cmd
->data
, (void *) buf
);
1099 if ((debug
> 0) && (ret
!= 0))
1100 fprintf(stderr
, "Command '%s %s' failed: %d\n", (set
== 1 ? "set" : "get"), cmd
->name
, ret
);
1105 static struct wlc_call
*find_cmd(char *name
)
1107 int found
= 0, i
= 0;
1109 while (!found
&& (i
< wlc_calls_size
)) {
1110 if (strcmp(name
, wlc_calls
[i
].name
) == 0)
1116 return (struct wlc_call
*) (found
? &wlc_calls
[i
] : NULL
);
1119 int main(int argc
, char **argv
)
1121 static char buf
[BUFSIZE
];
1123 char *cmd
= argv
[0];
1124 struct wlc_call
*call
;
1130 for(interface
[2] = '0'; (interface
[2] < '3') && (wl_probe(interface
) != 0); interface
[2]++);
1131 if (interface
[2] == '3') {
1132 fprintf(stderr
, "No Broadcom wl interface found!\n");
1138 while ((argc
> 0) && (argv
[0] != NULL
)) {
1139 if ((call
= find_cmd(argv
[0])) == NULL
) {
1140 fprintf(stderr
, "Invalid command: %s\n\n", argv
[0]);
1143 if ((argc
> 1) && (!(call
->param
& NOARG
))) {
1144 ret
= do_command(call
, argv
[1]);
1148 ret
= do_command(call
, NULL
);
1154 while (fromstdin
&& !feof(stdin
)) {
1156 fgets(buf
, BUFSIZE
- 1, stdin
);
1161 if ((s
= strchr(buf
, '\r')) != NULL
)
1163 if ((s
= strchr(buf
, '\n')) != NULL
)
1173 if ((s2
= strchr(buf
, ' ')) != NULL
)
1176 while (s2
&& isspace(*s2
))
1179 if ((call
= find_cmd(buf
)) == NULL
) {
1180 fprintf(stderr
, "Invalid command: %s\n", buf
);
1183 ret
= do_command(call
, ((call
->param
& NOARG
) ? NULL
: s2
));