OSDN Git Service

8735cc8a51d9ccdd1f5aad0943632f51b4e63377
[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/1000000;
60           /* Hum: check if within bounds... */
61
62           /* Activate PM */
63           local->pm_on = 1;
64           local->need_commit = 1;
65
66           /* Check min value */
67           if(prq->flags & IW_POWER_MIN)
68             {
69               local->pm_min_period = period;
70               local->pm_period_auto = 1;
71             }
72           else
73             /* Check max value */
74             if(prq->flags & IW_POWER_MAX)
75               {
76                 local->pm_max_period = period;
77                 local->pm_period_auto = 1;
78               }
79             else
80               {
81                 /* Fixed value */
82                 local->pm_period = period;
83                 local->pm_period_auto = 0;
84               }
85         }
86       /* Set timeout */
87       if(prq->flags & IW_POWER_TIMEOUT)
88         {
89           /* Activate PM */
90           local->pm_on = 1;
91           local->need_commit = 1;
92           /* Fixed value in ms */
93           local->pm_timeout = prq->value/1000;
94         }
95     }
96
97   return(0);
98 }
99
100 static int ioctl_get_power(struct net_device *dev,
101                            struct iw_request_info *info,
102                            struct iw_param *prq,
103                            char *extra)
104 {
105   prq->disabled = !local->pm_on;
106   /* By default, display the period */
107   if(!(prq->flags & IW_POWER_TIMEOUT))
108     {
109       int       inc_flags = prq->flags;
110       prq->flags = IW_POWER_PERIOD | IW_POWER_RELATIVE;
111       /* Check if auto */
112       if(local->pm_period_auto)
113         {
114           /* By default, the min */
115           if(!(inc_flags & IW_POWER_MAX))
116             {
117               prq->value = local->pm_min_period * 1000000;
118               prq->flags |= IW_POWER_MIN;
119             }
120           else
121             {
122               prq->value = local->pm_max_period * 1000000;
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             prq->value = local->pm_period * 1000000;
133         }
134     }
135   else
136     {
137       /* Deal with the timeout - always fixed */
138       prq->flags = IW_POWER_TIMEOUT;
139       prq->value = local->pm_timeout * 1000;
140     }
141   if(local->pm_multi)
142     prq->flags |= IW_POWER_ALL_R;
143   else
144     prq->flags |= IW_POWER_UNICAST_R;
145
146   return(0);
147 }
148
149 static int ioctl_get_range(struct net_device *dev,
150                            struct iw_request_info *info,
151                            struct iw_point *rrq,
152                            char *extra)
153 {
154   struct iw_range *range = (struct iw_range *) extra;
155
156   rrq->length = sizeof(struct iw_range);
157
158   memset(range, 0, sizeof(struct iw_range));
159
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
167 #if WIRELESS_EXT > 9
168       range.min_pmp = 1000000;  /* 1 units */
169       range.max_pmp = 12000000; /* 12 units */
170       range.min_pmt = 1000;     /* 1 ms */
171       range.max_pmt = 1000000;  /* 1 s */
172       range.pmp_flags = IW_POWER_PERIOD | IW_POWER_RELATIVE |
173         IW_POWER_MIN | IW_POWER_MAX;
174       range.pmt_flags = IW_POWER_TIMEOUT;
175       range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
176 #endif /* WIRELESS_EXT > 9 */
177   return(0);
178 }
179
180 /* --------------------------- BINDING --------------------------- */
181
182 #if WIRELESS_EXT > 12
183 /* Use the new driver API, save overhead */
184 static const iw_handler         handler_table[] =
185 {
186         ...
187         (iw_handler) ioctl_set_power,           /* SIOCSIWPOWER */
188         (iw_handler) ioctl_get_power,           /* SIOCGIWPOWER */
189 };
190 #else   /* WIRELESS_EXT < 12 */
191 /* Use old API in the ioctl handler */
192 static int
193 do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
194 {
195   struct iwreq *wrq = (struct iwreq *) ifr;
196   int           err = 0;
197
198   switch (cmd)
199     {
200 #if WIRELESS_EXT > 8
201       /* Set the desired Power Management mode */
202     case SIOCSIWPOWER:
203       err = ioctl_set_power(dev, NULL, &(wrq->u.power), NULL);
204       break;
205
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 */
215