📄 wlc_led.c
字号:
/* * Customer-defined whiz band LED maintenance for Broadcom 802.11 Networking Driver. * * Copyright 2005-2006, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * * * $Id$ */#include <wlc_cfg.h>#include <typedefs.h>#include <bcmdefs.h>#include <osl.h>#include <sbutils.h>#include <bcmutils.h>#include <wlioctl.h>#include <proto/802.11.h>#include <sbhndpio.h>#include <sbhnddma.h>#include <hnddma.h>#include <d11.h>#include <wlc_rate.h>#include <wlc_key.h>#include <wlc_channel.h>#include <wlc_pub.h>#include <wlc_bsscfg.h>#include <wlc_pio.h>#include <wlc.h>#include <wlc_phy.h>#include <wl_export.h>#include <wlc_led.h>#define LED_BLINK_TIME 10 /* 10ms wlc_led_blink_timer() period */#define LED_NUMDEFAULT 3 /* # of default LEDs */struct led { uint pin; /* gpio pin# == led index# */ uint behavior; /* led behavior of this pin */ bool activehi; /* polarity */ uint blinkticks; /* total number of on/off ticks */ uint8 blinkon; /* # ticks on */ uint8 blinkoff; /* # ticks off */};struct led_info { void *wlc; wlc_pub_t *pub; struct led led[WL_LED_NUMGPIO]; /* led fanciness */ bool act; /* recent tx/rx data frames */ uint lasttxrx; /* prev count of tx+rx frames */};/* blink models */static void wlc_led_blinkfast(struct led *led);static void wlc_led_blinkmed(struct led *led);static void wlc_led_blinkslow(struct led *led);static void wlc_led_blinkoff(struct led *led);/* led behavior function prototypes */static void wlc_led(led_info_t *li, uint32 mask, uint32 val, bool activehi);static void wlc_led_null(led_info_t *li, struct led *led);static void wlc_led_on(led_info_t *li, struct led *led);static void wlc_led_off(led_info_t *li, struct led *led);static void wlc_led_activity(led_info_t *li, struct led *led);static void wlc_led_a_radio(led_info_t *li, struct led *led);static void wlc_led_b_radio(led_info_t *li, struct led *led);static void wlc_led_bgmode(led_info_t *li, struct led *led);static void wlc_led_wi1(led_info_t *li, struct led *led);static void wlc_led_wi2(led_info_t *li, struct led *led);static void wlc_led_wi3(led_info_t *li, struct led *led);static void wlc_led_assoc(led_info_t *li, struct led *led);typedef void (*ledfunc_t)(led_info_t *li, struct led *led);/* use dynamic initialization in wlc_led_attach() for some compiler */static ledfunc_t ledfunc[WL_LED_NUMBEHAVIOR];led_info_t *BCMINITFN(wlc_led_attach)(wlc_pub_t *pub, uint d11_unit, void *cwlc){ led_info_t *li; struct led *led; int i; char name[32]; char *var; uint val; WL_TRACE(("wl: wlc_led_attach\n")); /* init static function array */ ledfunc[0] = wlc_led_null; ledfunc[1] = wlc_led_on; ledfunc[2] = wlc_led_activity; ledfunc[3] = wlc_led_on; ledfunc[4] = wlc_led_a_radio; ledfunc[5] = wlc_led_b_radio; ledfunc[6] = wlc_led_bgmode; ledfunc[7] = wlc_led_wi1; ledfunc[8] = wlc_led_wi2; ledfunc[9] = wlc_led_wi3; ledfunc[10] = wlc_led_assoc; ledfunc[11] = wlc_led_null; if ((li = (led_info_t *)MALLOC(pub->osh, sizeof(led_info_t))) == NULL) { WL_ERROR(("wlc_led_attach: out of memory, malloced %d bytes", MALLOCED(pub->osh))); return li; } bzero((char *)li, sizeof(led_info_t)); li->wlc = cwlc; li->pub = pub; /* init led behaviors */ ASSERT(LED_NUMDEFAULT <= WL_LED_NUMGPIO); led = &li->led[0]; led->pin = 0; led->behavior = WL_LED_ACTIVITY; led->activehi = TRUE; led++; led->pin = 1; led->behavior = WL_LED_BRADIO; led->activehi = TRUE; led++; led->pin = 2; led->behavior = WL_LED_ARADIO; led->activehi = TRUE; for (i = LED_NUMDEFAULT; i < WL_LED_NUMGPIO; i ++) { led ++; led->pin = i; led->behavior = WL_LED_OFF; led->activehi = TRUE; } if (li->pub->sbh->boardvendor == VENDOR_HP) li->led[0].behavior = WL_LED_RADIO; /* look for led gpio/behavior nvram overrides */ for (i = 0; i < WL_LED_NUMGPIO; i++) { led = &li->led[i]; sprintf(name, "wl%dgpio%d", d11_unit, i); if ((var = getvar(pub->vars, name)) == NULL) continue; val = bcm_strtoul(var, NULL, 0); /* silently ignore old card srom garbage */ if ((val & WL_LED_BEH_MASK) >= WL_LED_NUMBEHAVIOR) continue; led->pin = i; /* gpio pin# == led index# */ led->behavior = val & WL_LED_BEH_MASK; led->activehi = (val & WL_LED_AL_MASK)? FALSE : TRUE; } return li;}voidBCMUNINITFN(wlc_led_detach)(led_info_t *li){ WL_TRACE(("wl: %s: li = %p\n", __FUNCTION__, li)); if (li) { MFREE(li->pub->osh, li, sizeof(led_info_t)); }}voidBCMINITFN(wlc_led_init)(led_info_t *li, uint32 *gpio){ uint32 mask = 0; int i; wlc_pub_t *pub = li->pub; /* build gpio mask */ for (i = 0; i < WL_LED_NUMGPIO; i++) if ((li->led[i].behavior) && (li->led[i].behavior != WL_LED_INACTIVE)) mask |= (1 << li->led[i].pin); *gpio = mask; /* designate gpios driving LEDs . Make sure that we have the control */ sb_gpiocontrol(pub->sbh, mask, 0, GPIO_DRV_PRIORITY); sb_gpioled(pub->sbh, mask, mask); sb_gpioouten(pub->sbh, mask, mask, GPIO_DRV_PRIORITY); /* set all LEDs off */ sb_gpioout(pub->sbh, mask, 0, GPIO_DRV_PRIORITY);}/* this update can be called regardless driver is "up" or "down" */voidwlc_led_event(led_info_t *li){ wlc_info_t *wlc = (wlc_info_t *)li->wlc; struct led *led; int i; /* silently return if called w/o chip clock */ if (!wlc->sbclk) return; /* call each pin behavior function */ for (i = 0; i < WL_LED_NUMGPIO; i++) if ((led = &li->led[i])->behavior) ledfunc[led->behavior](li, led);}/* called periodically */voidwlc_led_timer(led_info_t *li){ wlc_pub_t *pub = li->pub; wlc_info_t *wlc = (wlc_info_t *)li->wlc; uint txrx; bool blink; int i; /* set/clear act */ txrx = WLCNTVAL(pub->_cnt.txframe) + WLCNTVAL(pub->_cnt.rxframe); li->act = (txrx != li->lasttxrx) ? TRUE : FALSE; li->lasttxrx = txrx; wlc_led_event(li); /* start/stop periodic led_blink_timer */ blink = FALSE; for (i = 0; i < WL_LED_NUMGPIO; i++) if (li->led[i].blinkon || li->led[i].blinkoff) blink = TRUE; if (blink && !pub->led_blink_run) { wl_add_timer(wlc->wl, pub->led_blink_timer, LED_BLINK_TIME, 1); pub->led_blink_run = TRUE; } else if (!blink && pub->led_blink_run) { wl_del_timer(wlc->wl, pub->led_blink_timer); pub->led_blink_run = FALSE; }}/* called every 10ms while any led->blinkrate is nonzero */voidwlc_led_blink_timer(led_info_t *li){ struct led *led; /* blink each pin at its respective blinkrate */ for (led = &li->led[0]; led < &li->led[WL_LED_NUMGPIO]; led++) { if (led->blinkticks) { if (led->blinkticks > led->blinkon) { wlc_led_off(li, led); } else { wlc_led_on(li, led); } if (--led->blinkticks == 0) led->blinkticks = led->blinkon + led->blinkoff; } }}/* 40ms-on/40ms-off */static voidwlc_led_blinkfast(struct led *led){ if ((led->blinkon == 4) && (led->blinkoff == 4)) return; led->blinkon = 4; led->blinkoff = 4; led->blinkticks = led->blinkon + led->blinkoff;}/* 80ms-on/20ms-off */static voidwlc_led_blinkmed(struct led *led){ if ((led->blinkon == 8) && (led->blinkoff == 2)) return; led->blinkon = 8; led->blinkoff = 2; led->blinkticks = led->blinkon + led->blinkoff;}/* 500ms-on/500ms-off */static voidwlc_led_blinkslow(struct led *led){ if ((led->blinkon == 50) && (led->blinkoff == 50)) return; led->blinkon = 50; led->blinkoff = 50; led->blinkticks = led->blinkon + led->blinkoff;}static voidwlc_led_blinkoff(struct led *led){ led->blinkon = led->blinkoff = led->blinkticks = 0;}/* turn gpio bits on or off */static voidwlc_led(led_info_t *li, uint32 mask, uint32 val, bool activehi){ ASSERT((val & ~mask) == 0); if (!activehi) val = ((~val) & mask); sb_gpioout(li->pub->sbh, mask, val, GPIO_DRV_PRIORITY);}static voidwlc_led_null(led_info_t *li, struct led *led){}static voidwlc_led_on(led_info_t *li, struct led *led){ uint mask, val; mask = 1 << led->pin; val = mask; /* Handle both on and Off cases */ if (!li->pub->up) val = 0; wlc_led(li, mask, val, led->activehi);}static voidwlc_led_off(led_info_t *li, struct led *led){ wlc_led(li, (1 << led->pin), 0, led->activehi);}static voidwlc_led_activity(led_info_t *li, struct led *led){ if (!li->pub->up) { /* make sure li->act is clear since wlc_led_timer may be stopped in wlc_down */ li->act = FALSE; } if (li->act) wlc_led_blinkmed(led); else { wlc_led_blinkoff(led); wlc_led_off(li, led); }}static voidwlc_led_a_radio(led_info_t *li, struct led *led){ wlc_info_t *wlc = (wlc_info_t *)li->wlc; uint bits; bool a_radio; uint i; a_radio = FALSE; if ((NBANDS_PUB(li->pub) == 1) || (wlc->bandlocked == TRUE)) { if (ISAPHY(wlc->band->pi)) a_radio = TRUE; } else { for (i = 0; i < NBANDS_PUB(li->pub); i++) if (ISAPHY(wlc->bandstate[i].pi)) a_radio = TRUE; } bits = a_radio? (1 << led->pin) : 0; /* when down, but not due to MPC only, turn off radio LED */ if (!li->pub->up) bits = 0; wlc_led(li, (1 << led->pin), bits, led->activehi);}static voidwlc_led_b_radio(led_info_t *li, struct led *led){ wlc_info_t *wlc = (wlc_info_t *)li->wlc; wlc_pub_t *pub = li->pub; uint bits; bool b_radio; uint i; b_radio = FALSE; if ((NBANDS_PUB(pub) == 1) || (wlc->bandlocked == TRUE)) { if (ISBPHY(wlc->band->pi) || ISGPHY(wlc->band->pi)) b_radio = TRUE; } else { for (i = 0; i < NBANDS_PUB(pub); i++) if (ISBPHY(wlc->bandstate[i].pi) || ISGPHY(wlc->bandstate[i].pi)) b_radio = TRUE; } bits = b_radio? (1 << led->pin) : 0; /* when down, but not due to MPC only, turn off radio LED */ if (!pub->up) bits = 0; wlc_led(li, (1 << led->pin), bits, led->activehi);}static voidwlc_led_bgmode(led_info_t *li, struct led *led){ wlc_info_t *wlc = (wlc_info_t *)li->wlc; uint bits; bits = (li->pub->associated && li->pub->BSS && wlc->band->gmode && wlc_rateset_isofdm(li->pub->current_bss.rateset.count, li->pub->current_bss.rateset.rates)) ? (1 << led->pin) : 0; wlc_led(li, bits, bits, led->activehi);}static voidwlc_led_wi1(led_info_t *li, struct led *led){ /* blink if activity, otherwise on */ if (li->act) wlc_led_blinkmed(led); else { wlc_led_blinkoff(led); wlc_led_on(li, led); }}/* 11g behavior */static voidwlc_led_wi2(led_info_t *li, struct led *led){ if (li->pub->associated) if (li->act) wlc_led_blinkfast(led); else { wlc_led_blinkoff(led); wlc_led_on(li, led); } else wlc_led_blinkslow(led);}/* 11b behavior */static voidwlc_led_wi3(led_info_t *li, struct led *led){ wlc_info_t *wlc = (wlc_info_t *)li->wlc; if (ISAPHY(wlc->band->pi)) return; if (li->pub->associated && !wlc_rateset_isofdm(li->pub->current_bss.rateset.count, li->pub->current_bss.rateset.rates)) if (li->act) wlc_led_blinkfast(led); else { wlc_led_blinkoff(led); wlc_led_on(li, led); } else wlc_led_blinkslow(led);}static voidwlc_led_assoc(led_info_t *li, struct led *led){ if (!li->pub->up) { ASSERT(li->pub->associated); li->pub->associated = FALSE; } if (li->pub->associated) { wlc_led_blinkoff(led); wlc_led_on(li, led); } else wlc_led_blinkslow(led);}/* turn activity LED on or off */voidwlc_led_activityset(led_info_t *li, bool led_state){ struct led *led; uint i; for (i = 0; i < WL_LED_NUMGPIO; i++) { led = &li->led[i]; if (led->behavior == WL_LED_ACTIVITY) { if (led_state == ON) wlc_led_on(li, led); else wlc_led_off(li, led); } }}/* turn radio LEDs on or off when switch band */voidwlc_led_radioset(led_info_t *li, bool led_state){ struct led *led; uint i; for (i = 0; i < WL_LED_NUMGPIO; i++) { led = &li->led[i]; if ((led->behavior == WL_LED_ARADIO) || (led->behavior == WL_LED_BRADIO)) { if (led_state == ON) wlc_led_on(li, led); else wlc_led_off(li, led); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -