sample_pm.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /* Note : this particular snipset of code is available under
  2. * the LGPL, MPL or BSD license (at your choice).
  3. * Jean II
  4. */
  5. /* --------------------------- INCLUDE --------------------------- */
  6. /* Backward compatibility for Wireless Extension 9 */
  7. #ifndef IW_POWER_MODIFIER
  8. #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */
  9. #define IW_POWER_MIN 0x0001 /* Value is a minimum */
  10. #define IW_POWER_MAX 0x0002 /* Value is a maximum */
  11. #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
  12. #endif IW_POWER_MODIFIER
  13. struct net_local {
  14. int pm_on; // Power Management enabled
  15. int pm_multi; // Receive multicasts
  16. int pm_period; // Power Management period
  17. int pm_period_auto; // Power Management auto mode
  18. int pm_max_period; // Power Management max period
  19. int pm_min_period; // Power Management min period
  20. int pm_timeout; // Power Management timeout
  21. };
  22. /* --------------------------- HANDLERS --------------------------- */
  23. static int ioctl_set_power(struct net_device *dev,
  24. struct iw_request_info *info,
  25. struct iw_param *prq,
  26. char *extra)
  27. {
  28. /* Disable it ? */
  29. if(prq->disabled)
  30. {
  31. local->pm_on = 0;
  32. }
  33. else
  34. {
  35. /* Check mode */
  36. switch(prq->flags & IW_POWER_MODE)
  37. {
  38. case IW_POWER_UNICAST_R:
  39. local->pm_multi = 0;
  40. local->need_commit = 1;
  41. break;
  42. case IW_POWER_ALL_R:
  43. local->pm_multi = 1;
  44. local->need_commit = 1;
  45. break;
  46. case IW_POWER_ON: /* None = ok */
  47. break;
  48. default: /* Invalid */
  49. return(-EINVAL);
  50. }
  51. /* Set period */
  52. if(prq->flags & IW_POWER_PERIOD)
  53. {
  54. int period = prq->value;
  55. #if WIRELESS_EXT < 21
  56. period /= 1000000;
  57. #endif
  58. /* Hum: check if within bounds... */
  59. /* Activate PM */
  60. local->pm_on = 1;
  61. local->need_commit = 1;
  62. /* Check min value */
  63. if(prq->flags & IW_POWER_MIN)
  64. {
  65. local->pm_min_period = period;
  66. local->pm_period_auto = 1;
  67. }
  68. else
  69. /* Check max value */
  70. if(prq->flags & IW_POWER_MAX)
  71. {
  72. local->pm_max_period = period;
  73. local->pm_period_auto = 1;
  74. }
  75. else
  76. {
  77. /* Fixed value */
  78. local->pm_period = period;
  79. local->pm_period_auto = 0;
  80. }
  81. }
  82. /* Set timeout */
  83. if(prq->flags & IW_POWER_TIMEOUT)
  84. {
  85. /* Activate PM */
  86. local->pm_on = 1;
  87. local->need_commit = 1;
  88. /* Fixed value in ms */
  89. local->pm_timeout = prq->value/1000;
  90. }
  91. }
  92. return(0);
  93. }
  94. static int ioctl_get_power(struct net_device *dev,
  95. struct iw_request_info *info,
  96. struct iw_param *prq,
  97. char *extra)
  98. {
  99. prq->disabled = !local->pm_on;
  100. /* By default, display the period */
  101. if(!(prq->flags & IW_POWER_TIMEOUT))
  102. {
  103. int inc_flags = prq->flags;
  104. prq->flags = IW_POWER_PERIOD | IW_POWER_RELATIVE;
  105. /* Check if auto */
  106. if(local->pm_period_auto)
  107. {
  108. /* By default, the min */
  109. if(!(inc_flags & IW_POWER_MAX))
  110. {
  111. prq->value = local->pm_min_period;
  112. #if WIRELESS_EXT < 21
  113. prq->value *= 1000000;
  114. #endif
  115. prq->flags |= IW_POWER_MIN;
  116. }
  117. else
  118. {
  119. prq->value = local->pm_max_period;
  120. #if WIRELESS_EXT < 21
  121. prq->value *= 1000000;
  122. #endif
  123. prq->flags |= IW_POWER_MAX;
  124. }
  125. }
  126. else
  127. {
  128. /* Fixed value. Check the flags */
  129. if(inc_flags & (IW_POWER_MIN | IW_POWER_MAX))
  130. return(-EINVAL);
  131. else
  132. {
  133. prq->value = local->pm_period;
  134. #if WIRELESS_EXT < 21
  135. prq->value *= 1000000;
  136. #endif
  137. }
  138. }
  139. }
  140. else
  141. {
  142. /* Deal with the timeout - always fixed */
  143. prq->flags = IW_POWER_TIMEOUT;
  144. prq->value = local->pm_timeout * 1000;
  145. }
  146. if(local->pm_multi)
  147. prq->flags |= IW_POWER_ALL_R;
  148. else
  149. prq->flags |= IW_POWER_UNICAST_R;
  150. return(0);
  151. }
  152. static int ioctl_get_range(struct net_device *dev,
  153. struct iw_request_info *info,
  154. struct iw_point *rrq,
  155. char *extra)
  156. {
  157. struct iw_range *range = (struct iw_range *) extra;
  158. rrq->length = sizeof(struct iw_range);
  159. memset(range, 0, sizeof(struct iw_range));
  160. #if WIRELESS_EXT > 10
  161. /* Version we are compiled with */
  162. range->we_version_compiled = WIRELESS_EXT;
  163. /* Minimum version we recommend */
  164. range->we_version_source = 8;
  165. #endif /* WIRELESS_EXT > 10 */
  166. #if WIRELESS_EXT > 9
  167. #if WIRELESS_EXT < 21
  168. range.min_pmp = 1000000; /* 1 units */
  169. range.max_pmp = 12000000; /* 12 units */
  170. #else
  171. range.min_pmp = 1; /* 1 units */
  172. range.max_pmp = 12; /* 12 units */
  173. #endif
  174. range.min_pmt = 1000; /* 1 ms */
  175. range.max_pmt = 1000000; /* 1 s */
  176. range.pmp_flags = IW_POWER_PERIOD | IW_POWER_RELATIVE |
  177. IW_POWER_MIN | IW_POWER_MAX;
  178. range.pmt_flags = IW_POWER_TIMEOUT;
  179. range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
  180. #endif /* WIRELESS_EXT > 9 */
  181. return(0);
  182. }
  183. /* --------------------------- BINDING --------------------------- */
  184. #if WIRELESS_EXT > 12
  185. /* Use the new driver API, save overhead */
  186. static const iw_handler handler_table[] =
  187. {
  188. ...
  189. (iw_handler) ioctl_set_power, /* SIOCSIWPOWER */
  190. (iw_handler) ioctl_get_power, /* SIOCGIWPOWER */
  191. };
  192. #else /* WIRELESS_EXT < 12 */
  193. /* Use old API in the ioctl handler */
  194. static int
  195. do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  196. {
  197. struct iwreq *wrq = (struct iwreq *) ifr;
  198. int err = 0;
  199. switch (cmd)
  200. {
  201. #if WIRELESS_EXT > 8
  202. /* Set the desired Power Management mode */
  203. case SIOCSIWPOWER:
  204. err = ioctl_set_power(dev, NULL, &(wrq->u.power), NULL);
  205. break;
  206. /* Get the power management settings */
  207. case SIOCGIWPOWER:
  208. err = ioctl_get_power(dev, NULL, &(wrq->u.power), NULL);
  209. break;
  210. #endif /* WIRELESS_EXT > 8 */
  211. }
  212. return(err);
  213. }
  214. #endif /* WIRELESS_EXT < 12 */