ieee80211softmac_event.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * Event system
  3. * Also see comments in public header file and longer explanation below.
  4. *
  5. * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
  6. * Joseph Jezak <josejx@gentoo.org>
  7. * Larry Finger <Larry.Finger@lwfinger.net>
  8. * Danny van Dyk <kugelfang@gentoo.org>
  9. * Michael Buesch <mbuesch@freenet.de>
  10. *
  11. * This program is free software; you can redistribute it and/or modify it
  12. * under the terms of version 2 of the GNU General Public License as
  13. * published by the Free Software Foundation.
  14. *
  15. * This program is distributed in the hope that it will be useful, but WITHOUT
  16. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  17. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  18. * more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * The full GNU General Public License is included in this distribution in the
  25. * file called COPYING.
  26. */
  27. #include "ieee80211softmac_priv.h"
  28. /*
  29. * Each event has associated to it
  30. * - an event type (see constants in public header)
  31. * - an event context (see below)
  32. * - the function to be called
  33. * - a context (extra parameter to call the function with)
  34. * - and the softmac struct
  35. *
  36. * The event context is private and can only be used from
  37. * within this module. Its meaning varies with the event
  38. * type:
  39. * SCAN_FINISHED: no special meaning
  40. * ASSOCIATED,
  41. * ASSOCIATE_FAILED,
  42. * ASSOCIATE_TIMEOUT,
  43. * AUTHENTICATED,
  44. * AUTH_FAILED,
  45. * AUTH_TIMEOUT: a pointer to the network struct
  46. * ...
  47. * Code within this module can use the event context to be only
  48. * called when the event is true for that specific context
  49. * as per above table.
  50. * If the event context is NULL, then the notification is always called,
  51. * regardless of the event context. The event context is not passed to
  52. * the callback, it is assumed that the context suffices.
  53. *
  54. * You can also use the event context only by setting the event type
  55. * to -1 (private use only), in which case you'll be notified
  56. * whenever the event context matches.
  57. */
  58. static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
  59. "scan finished",
  60. "associated",
  61. "associating failed",
  62. "associating timed out",
  63. "authenticated",
  64. "authenticating failed",
  65. "authenticating timed out",
  66. "associating failed because no suitable network was found",
  67. "disassociated",
  68. };
  69. static void
  70. ieee80211softmac_notify_callback(void *d)
  71. {
  72. struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d;
  73. kfree(d);
  74. event.fun(event.mac->dev, event.context);
  75. }
  76. int
  77. ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac,
  78. int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask)
  79. {
  80. struct ieee80211softmac_event *eventptr;
  81. unsigned long flags;
  82. if (event < -1 || event > IEEE80211SOFTMAC_EVENT_LAST)
  83. return -ENOSYS;
  84. if (!fun)
  85. return -EINVAL;
  86. eventptr = kmalloc(sizeof(struct ieee80211softmac_event), gfp_mask);
  87. if (!eventptr)
  88. return -ENOMEM;
  89. eventptr->event_type = event;
  90. INIT_WORK(&eventptr->work, ieee80211softmac_notify_callback, eventptr);
  91. eventptr->fun = fun;
  92. eventptr->context = context;
  93. eventptr->mac = mac;
  94. eventptr->event_context = event_context;
  95. spin_lock_irqsave(&mac->lock, flags);
  96. list_add(&eventptr->list, &mac->events);
  97. spin_unlock_irqrestore(&mac->lock, flags);
  98. return 0;
  99. }
  100. int
  101. ieee80211softmac_notify_gfp(struct net_device *dev,
  102. int event, notify_function_ptr fun, void *context, gfp_t gfp_mask)
  103. {
  104. struct ieee80211softmac_device *mac = ieee80211_priv(dev);
  105. if (event < 0 || event > IEEE80211SOFTMAC_EVENT_LAST)
  106. return -ENOSYS;
  107. return ieee80211softmac_notify_internal(mac, event, NULL, fun, context, gfp_mask);
  108. }
  109. EXPORT_SYMBOL_GPL(ieee80211softmac_notify_gfp);
  110. /* private -- calling all callbacks that were specified */
  111. void
  112. ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
  113. {
  114. struct ieee80211softmac_event *eventptr, *tmp;
  115. struct ieee80211softmac_network *network;
  116. if (event >= 0) {
  117. union iwreq_data wrqu;
  118. int we_event;
  119. char *msg = NULL;
  120. switch(event) {
  121. case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
  122. network = (struct ieee80211softmac_network *)event_ctx;
  123. wrqu.data.length = 0;
  124. wrqu.data.flags = 0;
  125. memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
  126. wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  127. we_event = SIOCGIWAP;
  128. break;
  129. case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
  130. wrqu.data.length = 0;
  131. wrqu.data.flags = 0;
  132. memset(&wrqu, '\0', sizeof (union iwreq_data));
  133. wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  134. we_event = SIOCGIWAP;
  135. break;
  136. case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
  137. wrqu.data.length = 0;
  138. wrqu.data.flags = 0;
  139. memset(&wrqu, '\0', sizeof (union iwreq_data));
  140. we_event = SIOCGIWSCAN;
  141. break;
  142. default:
  143. msg = event_descriptions[event];
  144. wrqu.data.length = strlen(msg);
  145. we_event = IWEVCUSTOM;
  146. break;
  147. }
  148. wireless_send_event(mac->dev, we_event, &wrqu, msg);
  149. }
  150. if (!list_empty(&mac->events))
  151. list_for_each_entry_safe(eventptr, tmp, &mac->events, list) {
  152. if ((eventptr->event_type == event || eventptr->event_type == -1)
  153. && (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
  154. list_del(&eventptr->list);
  155. schedule_work(&eventptr->work);
  156. }
  157. }
  158. }
  159. void
  160. ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_ctx)
  161. {
  162. unsigned long flags;
  163. spin_lock_irqsave(&mac->lock, flags);
  164. ieee80211softmac_call_events_locked(mac, event, event_ctx);
  165. spin_unlock_irqrestore(&mac->lock, flags);
  166. }