Branch oldpackages for 14.07
[14.07/packages.git] / net / madwifi / files / lib / wifi / madwifi.sh
1 #!/bin/sh
2 append DRIVERS "atheros"
3
4 find_atheros_phy() {
5         local device="$1"
6
7         local macaddr="$(config_get "$device" macaddr | tr 'A-Z' 'a-z')"
8         config_get phy "$device" phy
9         [ -z "$phy" -a -n "$macaddr" ] && {
10                 cd /proc/sys/dev
11                 for phy in $(ls -d wifi* 2>&-); do
12                         [ "$macaddr" = "$(cat /sys/class/net/${phy}/address)" ] || continue
13                         config_set "$device" phy "$phy"
14                         break
15                 done
16                 config_get phy "$device" phy
17         }
18         [ -n "$phy" -a -d "/proc/sys/dev/$phy" ] || {
19                 echo "phy for wifi device $1 not found"
20                 return 1
21         }
22         [ -z "$macaddr" ] && {
23                 config_set "$device" macaddr "$(cat /sys/class/net/${phy}/address)"
24         }
25         return 0
26 }
27
28 scan_atheros() {
29         local device="$1"
30         local wds
31         local adhoc ahdemo sta ap monitor disabled
32
33         [ ${device%[0-9]} = "wifi" ] && config_set "$device" phy "$device"
34
35         local ifidx=0
36         
37         config_get vifs "$device" vifs
38         for vif in $vifs; do
39                 config_get_bool disabled "$vif" disabled 0
40                 [ $disabled = 0 ] || continue
41
42                 local vifname
43                 [ $ifidx -gt 0 ] && vifname="ath${device#radio}-$ifidx" || vifname="ath${device#radio}"
44
45                 config_get ifname "$vif" ifname
46                 config_set "$vif" ifname "${ifname:-$vifname}"
47                 
48                 config_get mode "$vif" mode
49                 case "$mode" in
50                         adhoc|ahdemo|sta|ap|monitor)
51                                 append $mode "$vif"
52                         ;;
53                         wds)
54                                 config_get ssid "$vif" ssid
55                                 [ -z "$ssid" ] && continue
56
57                                 config_set "$vif" wds 1
58                                 config_set "$vif" mode sta
59                                 mode="sta"
60                                 addr="$ssid"
61                                 ${addr:+append $mode "$vif"}
62                         ;;
63                         *) echo "$device($vif): Invalid mode, ignored."; continue;;
64                 esac
65
66                 ifidx=$(($ifidx + 1))
67         done
68
69         case "${adhoc:+1}:${sta:+1}:${ap:+1}" in
70                 # valid mode combinations
71                 1::) wds="";;
72                 1::1);;
73                 :1:1)config_set "$device" nosbeacon 1;; # AP+STA, can't use beacon timers for STA
74                 :1:);;
75                 ::1);;
76                 ::);;
77                 *) echo "$device: Invalid mode combination in config"; return 1;;
78         esac
79
80         config_set "$device" vifs "${sta:+$sta }${ap:+$ap }${adhoc:+$adhoc }${ahdemo:+$ahdemo }${wds:+$wds }${monitor:+$monitor}"
81 }
82
83
84 disable_atheros() (
85         local device="$1"
86
87         find_atheros_phy "$device" || return 0
88         config_get phy "$device" phy
89
90         set_wifi_down "$device"
91
92         include /lib/network
93         cd /proc/sys/net
94         for dev in *; do
95                 grep "$phy" "$dev/%parent" >/dev/null 2>/dev/null && {
96                         [ -f "/var/run/wifi-${dev}.pid" ] &&
97                                 kill "$(cat "/var/run/wifi-${dev}.pid")"
98                         ifconfig "$dev" down
99                         unbridge "$dev"
100                         wlanconfig "$dev" destroy
101                 }
102         done
103         return 0
104 )
105
106 enable_atheros() {
107         local device="$1"
108
109         find_atheros_phy "$device" || return 0
110         config_get phy "$device" phy
111
112         config_get regdomain "$device" regdomain
113         [ -n "$regdomain" ] && echo "$regdomain" > /proc/sys/dev/$phy/regdomain
114
115         config_get country "$device" country
116         case "$country" in
117                 [A-Za-z]*) country=`grep -i "$country" /lib/wifi/madwifi_countrycodes.txt |cut -d " " -f 2`;;
118                 [0-9]*) ;;
119                 *) country="" ;;
120         esac
121         [ -n "$country" ] && echo "$country" > /proc/sys/dev/$phy/countrycode
122
123         config_get_bool outdoor "$device" outdoor "0"
124         echo "$outdoor" > /proc/sys/dev/$phy/outdoor
125
126         config_get channel "$device" channel
127         config_get vifs "$device" vifs
128         config_get txpower "$device" txpower
129
130         [ auto = "$channel" ] && channel=0
131
132         config_get_bool antdiv "$device" diversity
133         config_get antrx "$device" rxantenna
134         config_get anttx "$device" txantenna
135         config_get_bool softled "$device" softled
136         config_get antenna "$device" antenna
137
138         devname="$(cat /proc/sys/dev/$phy/dev_name)"
139         local antgpio=
140         local invert=
141         case "$devname" in
142                 NanoStation2) antgpio=7; invert=1;;
143                 NanoStation5) antgpio=1; invert=1;;
144                 "NanoStation Loco2") antgpio=2;;
145                 "NanoStation Loco5")
146                         case "$antenna" in
147                                 horizontal) antdiv=0; anttx=1; antrx=1;;
148                                 vertical) antdiv=0; anttx=2; antrx=2;;
149                                 *) antdiv=1; anttx=0; antrx=0;;
150                         esac
151                 ;;
152         esac
153         if [ -n "$invert" ]; then
154                 _set="clear"
155                 _clear="set"
156         else
157                 _set="set"
158                 _clear="clear"
159         fi
160         if [ -n "$antgpio" ]; then
161                 softled=0
162                 case "$devname" in
163                         "NanoStation Loco2")
164                                 antdiv=0
165                                 antrx=1
166                                 anttx=1
167                                 case "$antenna" in
168                                         horizontal) gpioval=0;;
169                                         *) gpioval=1;;
170                                 esac
171                         ;;
172                         *)
173                                 case "$antenna" in
174                                         external) antdiv=0; antrx=1; anttx=1; gpioval=1;;
175                                         horizontal) antdiv=0; antrx=1; anttx=1; gpioval=0;;
176                                         vertical) antdiv=0; antrx=2; anttx=2; gpioval=0;;
177                                         auto) antdiv=1; antrx=0; anttx=0; gpioval=0;;
178                                 esac
179                         ;;
180                 esac
181
182                 [ -x "$(which gpioctl 2>/dev/null)" ] || antenna=
183                 gpioctl "dirout" "$antgpio" >/dev/null 2>&1
184                 case "$gpioval" in
185                         0)
186                                 gpioctl "$_clear" "$antgpio" >/dev/null 2>&1
187                         ;;
188                         1)
189                                 gpioctl "$_set" "$antgpio" >/dev/null 2>&1
190                         ;;
191                 esac
192         fi
193
194         [ -n "$antdiv" ] && sysctl -w dev."$phy".diversity="$antdiv" >&-
195         [ -n "$antrx" ] && sysctl -w dev."$phy".rxantenna="$antrx" >&-
196         [ -n "$anttx" ] && sysctl -w dev."$phy".txantenna="$anttx" >&-
197         [ -n "$softled" ] && sysctl -w dev."$phy".softled="$softled" >&-
198
199         config_get distance "$device" distance
200         [ -n "$distance" ] && sysctl -w dev."$phy".distance="$distance" >&-
201
202         for vif in $vifs; do
203                 local start_hostapd= vif_txpower= nosbeacon=
204                 config_get ifname "$vif" ifname
205                 config_get enc "$vif" encryption
206                 config_get eap_type "$vif" eap_type
207                 config_get mode "$vif" mode
208
209                 case "$mode" in
210                         sta) config_get_bool nosbeacon "$device" nosbeacon;;
211                         adhoc) config_get_bool nosbeacon "$vif" sw_merge 1;;
212                 esac
213
214                 [ "$nosbeacon" = 1 ] || nosbeacon=""
215                 ifname=$(wlanconfig "$ifname" create nounit wlandev "$phy" wlanmode "$mode" ${nosbeacon:+nosbeacon})
216                 [ $? -ne 0 ] && {
217                         echo "enable_atheros($device): Failed to set up $mode vif $ifname" >&2
218                         continue
219                 }
220                 config_set "$vif" ifname "$ifname"
221
222                 config_get hwmode "$device" hwmode
223                 [ -z "$hwmode" ] && config_get hwmode "$device" mode
224
225                 pureg=0
226                 case "$hwmode" in
227                         *b) hwmode=11b;;
228                         *bg) hwmode=11g;;
229                         *g) hwmode=11g; pureg=1;;
230                         *gdt) hwmode=11gdt;;
231                         *a) hwmode=11a;;
232                         *adt) hwmode=11adt;;
233                         *ast) hwmode=11ast;;
234                         *fh) hwmode=fh;;
235                         *) hwmode=auto;;
236                 esac
237                 iwpriv "$ifname" mode "$hwmode"
238                 iwpriv "$ifname" pureg "$pureg"
239
240                 iwconfig "$ifname" channel "$channel" >/dev/null 2>/dev/null 
241
242                 config_get_bool hidden "$vif" hidden 0
243                 iwpriv "$ifname" hide_ssid "$hidden"
244
245                 config_get ff "$vif" ff
246                 if [ -n "$ff" ]; then
247                         iwpriv "$ifname" ff "$ff"
248                 fi
249
250                 config_get wds "$vif" wds
251                 case "$wds" in
252                         1|on|enabled) wds=1;;
253                         *) wds=0;;
254                 esac
255                 iwpriv "$ifname" wds "$wds" >/dev/null 2>&1
256
257                 [ "$mode" = ap -a "$wds" = 1 ] && {
258                         config_get_bool wdssep "$vif" wdssep 1
259                         [ -n "$wdssep" ] && iwpriv "$ifname" wdssep "$wdssep"
260                 }
261
262                 case "$enc" in
263                         wep*)
264                                 case "$enc" in
265                                         *shared*) iwpriv "$ifname" authmode 2;;
266                                         *)        iwpriv "$ifname" authmode 1;;
267                                 esac
268                                 for idx in 1 2 3 4; do
269                                         config_get key "$vif" "key${idx}"
270                                         iwconfig "$ifname" enc "[$idx]" "${key:-off}"
271                                 done
272                                 config_get key "$vif" key
273                                 key="${key:-1}"
274                                 case "$key" in
275                                         [1234]) iwconfig "$ifname" enc "[$key]";;
276                                         *) iwconfig "$ifname" enc "$key";;
277                                 esac
278                         ;;
279                         psk*|wpa*)
280                                 start_hostapd=1
281                                 config_get key "$vif" key
282                         ;;
283                 esac
284
285                 case "$mode" in
286                         sta|adhoc|ahdemo)
287                                 config_get addr "$vif" bssid
288                                 [ -z "$addr" ] || { 
289                                         iwconfig "$ifname" ap "$addr"
290                                 }
291                         ;;
292                 esac
293
294                 config_get_bool uapsd "$vif" uapsd 0
295                 iwpriv "$ifname" uapsd "$uapsd"
296
297                 config_get_bool bgscan "$vif" bgscan
298                 [ -n "$bgscan" ] && iwpriv "$ifname" bgscan "$bgscan"
299
300                 config_get rate "$vif" rate
301                 [ -n "$rate" ] && iwconfig "$ifname" rate "${rate%%.*}"
302
303                 config_get mcast_rate "$vif" mcast_rate
304                 [ -n "$mcast_rate" ] && iwpriv "$ifname" mcast_rate "${mcast_rate%%.*}"
305
306                 config_get frag "$vif" frag
307                 [ -n "$frag" ] && iwconfig "$ifname" frag "${frag%%.*}"
308
309                 config_get rts "$vif" rts
310                 [ -n "$rts" ] && iwconfig "$ifname" rts "${rts%%.*}"
311
312                 config_get_bool comp "$vif" compression 0
313                 iwpriv "$ifname" compression "$comp" >/dev/null 2>&1
314
315                 config_get minrate "$vif" minrate
316                 [ -n "$minrate" ] && iwpriv "$ifname" minrate "$minrate"
317
318                 config_get maxrate "$vif" maxrate
319                 [ -n "$maxrate" ] && iwpriv "$ifname" maxrate "$maxrate"
320
321                 config_get_bool burst "$vif" bursting
322                 [ -n "$burst" ] && iwpriv "$ifname" burst "$burst"
323
324                 config_get_bool wmm "$vif" wmm
325                 [ -n "$wmm" ] && iwpriv "$ifname" wmm "$wmm"
326
327                 config_get_bool xr "$vif" xr
328                 [ -n "$xr" ] && iwpriv "$ifname" xr "$xr"
329
330                 config_get_bool ar "$vif" ar
331                 [ -n "$ar" ] && iwpriv "$ifname" ar "$ar"
332
333                 config_get_bool beacon_power "$vif" beacon_power
334                 [ -n "$beacon_power" ] && iwpriv "$ifname" beacon_pwr "$beacon_power"
335
336                 config_get_bool doth "$vif" doth 0
337                 [ -n "$doth" ] && iwpriv "$ifname" doth "$doth"
338
339                 config_get_bool probereq "$vif" probereq
340                 [ -n "$probereq" ] && iwpriv "$ifname" probereq "$probereq"
341
342                 config_get maclist "$vif" maclist
343                 [ -n "$maclist" ] && {
344                         # flush MAC list
345                         iwpriv "$ifname" maccmd 3
346                         for mac in $maclist; do
347                                 iwpriv "$ifname" addmac "$mac"
348                         done
349                 }
350
351                 config_get macpolicy "$vif" macpolicy
352                 case "$macpolicy" in
353                         allow)
354                                 iwpriv "$ifname" maccmd 1
355                         ;;
356                         deny)
357                                 iwpriv "$ifname" maccmd 2
358                         ;;
359                         *)
360                                 # default deny policy if mac list exists
361                                 [ -n "$maclist" ] && iwpriv "$ifname" maccmd 2
362                         ;;
363                 esac
364
365                 ifconfig "$ifname" up
366
367                 local net_cfg bridge
368                 net_cfg="$(find_net_config "$vif")"
369                 [ -z "$net_cfg" ] || {
370                         bridge="$(bridge_interface "$net_cfg")"
371                         config_set "$vif" bridge "$bridge"
372                         start_net "$ifname" "$net_cfg"
373                 }
374
375                 config_get ssid "$vif" ssid
376                 [ -n "$ssid" ] && {
377                         iwconfig "$ifname" essid on
378                         iwconfig "$ifname" essid ${ssid:+-- }"$ssid"
379                 }
380
381                 set_wifi_up "$vif" "$ifname"
382
383                 # TXPower settings only work if device is up already
384                 # while atheros hardware theoretically is capable of per-vif (even per-packet) txpower
385                 # adjustment it does not work with the current atheros hal/madwifi driver
386
387                 config_get vif_txpower "$vif" txpower
388                 # use vif_txpower (from wifi-iface) instead of txpower (from wifi-device) if
389                 # the latter doesn't exist
390                 txpower="${txpower:-$vif_txpower}"
391                 [ -z "$txpower" ] || iwconfig "$ifname" txpower "${txpower%%.*}"
392
393                 case "$mode:$enc" in
394                         ap:*)
395                                 config_get_bool isolate "$vif" isolate 0
396                                 iwpriv "$ifname" ap_bridge "$((isolate^1))"
397
398                                 if [ -n "$start_hostapd" ] && eval "type hostapd_setup_vif" 2>/dev/null >/dev/null; then
399                                         hostapd_setup_vif "$vif" madwifi || {
400                                                 echo "enable_atheros($device): Failed to set up hostapd for interface $ifname" >&2
401                                                 # make sure this wifi interface won't accidentally stay open without encryption
402                                                 ifconfig "$ifname" down
403                                                 wlanconfig "$ifname" destroy
404                                                 continue
405                                         }
406                                 fi
407                         ;;
408                         wds:*|sta:*)
409                                 if eval "type wpa_supplicant_setup_vif" 2>/dev/null >/dev/null; then
410                                         wpa_supplicant_setup_vif "$vif" wext || {
411                                                 echo "enable_atheros($device): Failed to set up wpa_supplicant for interface $ifname" >&2
412                                                 ifconfig "$ifname" down
413                                                 wlanconfig "$ifname" destroy
414                                                 continue
415                                         }
416                                 fi
417                         ;;
418                         adhoc:wep*|adhoc:psk*|adhoc:wpa*)
419                                 if eval "type wpa_supplicant_setup_vif" 2>/dev/null >/dev/null; then
420                                         wpa_supplicant_setup_vif "$vif" madwifi || {
421                                                 echo "enable_atheros($device): Failed to set up wpa"
422                                                 ifconfig "$ifname" down
423                                                 wlanconfig "$ifname" destroy
424                                                 continue
425                                         }
426                                 fi
427                         ;;
428                 esac
429         done
430 }
431
432 check_atheros_device() {
433         [ ${1%[0-9]} = "wifi" ] && config_set "$1" phy "$1"
434         config_get phy "$1" phy
435         [ -z "$phy" ] && {
436                 find_atheros_phy "$1" >/dev/null || return 0
437                 config_get phy "$1" phy
438         }
439         [ "$phy" = "$dev" ] && found=1
440 }
441
442
443 detect_atheros() {
444         devidx=0
445         config_load wireless
446         while :; do
447                 config_get type "radio$devidx" type
448                 [ -n "$type" ] || break
449                 devidx=$(($devidx + 1))
450         done
451         cd /proc/sys/dev
452         [ -d ath ] || return
453         for dev in $(ls -d wifi* 2>&-); do
454                 found=0
455                 config_foreach check_atheros_device wifi-device
456                 [ "$found" -gt 0 ] && continue
457
458                 devname="$(cat /proc/sys/dev/$dev/dev_name)"
459                 case "$devname" in
460                         "NanoStation Loco2")
461                                 EXTRA_DEV="
462 # Ubiquiti NanoStation Loco2 features
463         option antenna  vertical # (horizontal|vertical)
464 "
465                         ;;
466                         "NanoStation Loco5")
467                                 EXTRA_DEV="
468 # Ubiquiti NanoStation Loco5 features
469         option antenna  auto # (auto|horizontal|vertical)
470 "
471                         ;;
472                         NanoStation*)
473                                 EXTRA_DEV="
474 # Ubiquiti NanoStation features
475         option antenna  auto # (auto|horizontal|vertical|external)
476 "
477                         ;;
478                 esac
479
480                 cat <<EOF
481 config wifi-device  radio$devidx
482         option type     atheros
483         option channel  auto
484         option macaddr  $(cat /sys/class/net/${dev}/address)
485 $EXTRA_DEV
486         # REMOVE THIS LINE TO ENABLE WIFI:
487         option disabled 1
488
489 config wifi-iface
490         option device   radio$devidx
491         option network  lan
492         option mode     ap
493         option ssid     OpenWrt
494         option encryption none
495
496 EOF
497         devidx=$(($devidx + 1))
498         done
499 }