Root/package/madwifi/files/lib/wifi/madwifi.sh

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

Archive Download this file



interactive