OSDN Git Service

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