led.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006, Johannes Berg <johannes@sipsolutions.net>
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License version 2 as
00006  * published by the Free Software Foundation.
00007  */
00008 
00009 /* just for IFNAMSIZ */
00010 #include <linux/if.h>
00011 #include <linux/slab.h>
00012 #include <linux/export.h>
00013 #include "led.h"
00014 
00015 void ieee80211_led_rx(struct ieee80211_local *local)
00016 {
00017         if (unlikely(!local->rx_led))
00018                 return;
00019         if (local->rx_led_counter++ % 2 == 0)
00020                 led_trigger_event(local->rx_led, LED_OFF);
00021         else
00022                 led_trigger_event(local->rx_led, LED_FULL);
00023 }
00024 
00025 /* q is 1 if a packet was enqueued, 0 if it has been transmitted */
00026 void ieee80211_led_tx(struct ieee80211_local *local, int q)
00027 {
00028         if (unlikely(!local->tx_led))
00029                 return;
00030         /* not sure how this is supposed to work ... */
00031         local->tx_led_counter += 2*q-1;
00032         if (local->tx_led_counter % 2 == 0)
00033                 led_trigger_event(local->tx_led, LED_OFF);
00034         else
00035                 led_trigger_event(local->tx_led, LED_FULL);
00036 }
00037 
00038 void ieee80211_led_assoc(struct ieee80211_local *local, bool associated)
00039 {
00040         if (unlikely(!local->assoc_led))
00041                 return;
00042         if (associated)
00043                 led_trigger_event(local->assoc_led, LED_FULL);
00044         else
00045                 led_trigger_event(local->assoc_led, LED_OFF);
00046 }
00047 
00048 void ieee80211_led_radio(struct ieee80211_local *local, bool enabled)
00049 {
00050         if (unlikely(!local->radio_led))
00051                 return;
00052         if (enabled)
00053                 led_trigger_event(local->radio_led, LED_FULL);
00054         else
00055                 led_trigger_event(local->radio_led, LED_OFF);
00056 }
00057 
00058 void ieee80211_led_names(struct ieee80211_local *local)
00059 {
00060         snprintf(local->rx_led_name, sizeof(local->rx_led_name),
00061                  "%srx", wiphy_name(local->hw.wiphy));
00062         snprintf(local->tx_led_name, sizeof(local->tx_led_name),
00063                  "%stx", wiphy_name(local->hw.wiphy));
00064         snprintf(local->assoc_led_name, sizeof(local->assoc_led_name),
00065                  "%sassoc", wiphy_name(local->hw.wiphy));
00066         snprintf(local->radio_led_name, sizeof(local->radio_led_name),
00067                  "%sradio", wiphy_name(local->hw.wiphy));
00068 }
00069 
00070 void ieee80211_led_init(struct ieee80211_local *local)
00071 {
00072         local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
00073         if (local->rx_led) {
00074                 local->rx_led->name = local->rx_led_name;
00075                 if (led_trigger_register(local->rx_led)) {
00076                         kfree(local->rx_led);
00077                         local->rx_led = NULL;
00078                 }
00079         }
00080 
00081         local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
00082         if (local->tx_led) {
00083                 local->tx_led->name = local->tx_led_name;
00084                 if (led_trigger_register(local->tx_led)) {
00085                         kfree(local->tx_led);
00086                         local->tx_led = NULL;
00087                 }
00088         }
00089 
00090         local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
00091         if (local->assoc_led) {
00092                 local->assoc_led->name = local->assoc_led_name;
00093                 if (led_trigger_register(local->assoc_led)) {
00094                         kfree(local->assoc_led);
00095                         local->assoc_led = NULL;
00096                 }
00097         }
00098 
00099         local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
00100         if (local->radio_led) {
00101                 local->radio_led->name = local->radio_led_name;
00102                 if (led_trigger_register(local->radio_led)) {
00103                         kfree(local->radio_led);
00104                         local->radio_led = NULL;
00105                 }
00106         }
00107 
00108         if (local->tpt_led_trigger) {
00109                 if (led_trigger_register(&local->tpt_led_trigger->trig)) {
00110                         kfree(local->tpt_led_trigger);
00111                         local->tpt_led_trigger = NULL;
00112                 }
00113         }
00114 }
00115 
00116 void ieee80211_led_exit(struct ieee80211_local *local)
00117 {
00118         if (local->radio_led) {
00119                 led_trigger_unregister(local->radio_led);
00120                 kfree(local->radio_led);
00121         }
00122         if (local->assoc_led) {
00123                 led_trigger_unregister(local->assoc_led);
00124                 kfree(local->assoc_led);
00125         }
00126         if (local->tx_led) {
00127                 led_trigger_unregister(local->tx_led);
00128                 kfree(local->tx_led);
00129         }
00130         if (local->rx_led) {
00131                 led_trigger_unregister(local->rx_led);
00132                 kfree(local->rx_led);
00133         }
00134 
00135         if (local->tpt_led_trigger) {
00136                 led_trigger_unregister(&local->tpt_led_trigger->trig);
00137                 kfree(local->tpt_led_trigger);
00138         }
00139 }
00140 
00141 char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
00142 {
00143         struct ieee80211_local *local = hw_to_local(hw);
00144 
00145         return local->radio_led_name;
00146 }
00147 EXPORT_SYMBOL(__ieee80211_get_radio_led_name);
00148 
00149 char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
00150 {
00151         struct ieee80211_local *local = hw_to_local(hw);
00152 
00153         return local->assoc_led_name;
00154 }
00155 EXPORT_SYMBOL(__ieee80211_get_assoc_led_name);
00156 
00157 char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
00158 {
00159         struct ieee80211_local *local = hw_to_local(hw);
00160 
00161         return local->tx_led_name;
00162 }
00163 EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
00164 
00165 char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
00166 {
00167         struct ieee80211_local *local = hw_to_local(hw);
00168 
00169         return local->rx_led_name;
00170 }
00171 EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
00172 
00173 static unsigned long tpt_trig_traffic(struct ieee80211_local *local,
00174                                       struct tpt_led_trigger *tpt_trig)
00175 {
00176         unsigned long traffic, delta;
00177 
00178         traffic = tpt_trig->tx_bytes + tpt_trig->rx_bytes;
00179 
00180         delta = traffic - tpt_trig->prev_traffic;
00181         tpt_trig->prev_traffic = traffic;
00182         return DIV_ROUND_UP(delta, 1024 / 8);
00183 }
00184 
00185 static void tpt_trig_timer(unsigned long data)
00186 {
00187         struct ieee80211_local *local = (void *)data;
00188         struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
00189         struct led_classdev *led_cdev;
00190         unsigned long on, off, tpt;
00191         int i;
00192 
00193         if (!tpt_trig->running)
00194                 return;
00195 
00196         mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ));
00197 
00198         tpt = tpt_trig_traffic(local, tpt_trig);
00199 
00200         /* default to just solid on */
00201         on = 1;
00202         off = 0;
00203 
00204         for (i = tpt_trig->blink_table_len - 1; i >= 0; i--) {
00205                 if (tpt_trig->blink_table[i].throughput < 0 ||
00206                     tpt > tpt_trig->blink_table[i].throughput) {
00207                         off = tpt_trig->blink_table[i].blink_time / 2;
00208                         on = tpt_trig->blink_table[i].blink_time - off;
00209                         break;
00210                 }
00211         }
00212 
00213         read_lock(&tpt_trig->trig.leddev_list_lock);
00214         list_for_each_entry(led_cdev, &tpt_trig->trig.led_cdevs, trig_list)
00215                 led_blink_set(led_cdev, &on, &off);
00216         read_unlock(&tpt_trig->trig.leddev_list_lock);
00217 }
00218 
00219 char *__ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw,
00220                                 unsigned int flags,
00221                                 const struct ieee80211_tpt_blink *blink_table,
00222                                 unsigned int blink_table_len)
00223 {
00224         struct ieee80211_local *local = hw_to_local(hw);
00225         struct tpt_led_trigger *tpt_trig;
00226 
00227         if (WARN_ON(local->tpt_led_trigger))
00228                 return NULL;
00229 
00230         tpt_trig = kzalloc(sizeof(struct tpt_led_trigger), GFP_KERNEL);
00231         if (!tpt_trig)
00232                 return NULL;
00233 
00234         snprintf(tpt_trig->name, sizeof(tpt_trig->name),
00235                  "%stpt", wiphy_name(local->hw.wiphy));
00236 
00237         tpt_trig->trig.name = tpt_trig->name;
00238 
00239         tpt_trig->blink_table = blink_table;
00240         tpt_trig->blink_table_len = blink_table_len;
00241         tpt_trig->want = flags;
00242 
00243         setup_timer(&tpt_trig->timer, tpt_trig_timer, (unsigned long)local);
00244 
00245         local->tpt_led_trigger = tpt_trig;
00246 
00247         return tpt_trig->name;
00248 }
00249 EXPORT_SYMBOL(__ieee80211_create_tpt_led_trigger);
00250 
00251 static void ieee80211_start_tpt_led_trig(struct ieee80211_local *local)
00252 {
00253         struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
00254 
00255         if (tpt_trig->running)
00256                 return;
00257 
00258         /* reset traffic */
00259         tpt_trig_traffic(local, tpt_trig);
00260         tpt_trig->running = true;
00261 
00262         tpt_trig_timer((unsigned long)local);
00263         mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ));
00264 }
00265 
00266 static void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local)
00267 {
00268         struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
00269         struct led_classdev *led_cdev;
00270 
00271         if (!tpt_trig->running)
00272                 return;
00273 
00274         tpt_trig->running = false;
00275         del_timer_sync(&tpt_trig->timer);
00276 
00277         read_lock(&tpt_trig->trig.leddev_list_lock);
00278         list_for_each_entry(led_cdev, &tpt_trig->trig.led_cdevs, trig_list)
00279                 led_brightness_set(led_cdev, LED_OFF);
00280         read_unlock(&tpt_trig->trig.leddev_list_lock);
00281 }
00282 
00283 void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
00284                                 unsigned int types_on, unsigned int types_off)
00285 {
00286         struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
00287         bool allowed;
00288 
00289         WARN_ON(types_on & types_off);
00290 
00291         if (!tpt_trig)
00292                 return;
00293 
00294         tpt_trig->active &= ~types_off;
00295         tpt_trig->active |= types_on;
00296 
00297         /*
00298          * Regardless of wanted state, we shouldn't blink when
00299          * the radio is disabled -- this can happen due to some
00300          * code ordering issues with __ieee80211_recalc_idle()
00301          * being called before the radio is started.
00302          */
00303         allowed = tpt_trig->active & IEEE80211_TPT_LEDTRIG_FL_RADIO;
00304 
00305         if (!allowed || !(tpt_trig->active & tpt_trig->want))
00306                 ieee80211_stop_tpt_led_trig(local);
00307         else
00308                 ieee80211_start_tpt_led_trig(local);
00309 }


ros_rt_wmp
Author(s): Danilo Tardioli, dantard@unizar.es
autogenerated on Mon Oct 6 2014 08:27:10