7f44fd0d23b073cf48d07b25dd0d4b0a219edef0
[project/luci.git] / libs / iwinfo / src / iwinfo_wext.c
1 /*
2  * iwinfo - Wireless Information Library - Linux Wireless Extension Backend
3  *
4  *   Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
5  *
6  * The iwinfo library is free software: you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License version 2
8  * as published by the Free Software Foundation.
9  *
10  * The iwinfo library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with the iwinfo library. If not, see http://www.gnu.org/licenses/.
17  *
18  * Parts of this code are derived from the Linux wireless tools, iwlib.c,
19  * iwlist.c and iwconfig.c in particular.
20  */
21
22 #include "iwinfo.h"
23 #include "iwinfo_wext.h"
24
25 static int ioctl_socket = -1;
26
27 static double wext_freq2float(const struct iw_freq *in)
28 {
29         int             i;
30         double  res = (double) in->m;
31         for(i = 0; i < in->e; i++) res *= 10;
32         return res;
33 }
34
35 static int wext_ioctl(const char *ifname, int cmd, struct iwreq *wrq)
36 {
37         /* prepare socket */
38         if( ioctl_socket == -1 )
39                 ioctl_socket = socket(AF_INET, SOCK_DGRAM, 0);
40
41         strncpy(wrq->ifr_name, ifname, IFNAMSIZ);
42         return ioctl(ioctl_socket, cmd, wrq);
43 }
44
45
46 int wext_probe(const char *ifname)
47 {
48         struct iwreq wrq;
49
50         if(wext_ioctl(ifname, SIOCGIWNAME, &wrq) >= 0)
51                 return 1;
52
53         return 0;
54 }
55
56 int wext_get_mode(const char *ifname, char *buf)
57 {
58         struct iwreq wrq;
59
60         if(wext_ioctl(ifname, SIOCGIWMODE, &wrq) >= 0)
61         {
62                 switch(wrq.u.mode)
63                 {
64                         case 0:
65                                 sprintf(buf, "Auto");
66                                 break;
67
68                         case 1:
69                                 sprintf(buf, "Ad-Hoc");
70                                 break;
71
72                         case 2:
73                                 sprintf(buf, "Client");
74                                 break;
75
76                         case 3:
77                                 sprintf(buf, "Master");
78                                 break;
79
80                         case 4:
81                                 sprintf(buf, "Repeater");
82                                 break;
83
84                         case 5:
85                                 sprintf(buf, "Secondary");
86                                 break;
87
88                         case 6:
89                                 sprintf(buf, "Monitor");
90                                 break;
91
92                         default:
93                                 sprintf(buf, "Unknown");
94                 }
95
96                 return 0;
97         }
98
99         return -1;
100 }
101
102 int wext_get_ssid(const char *ifname, char *buf)
103 {
104         struct iwreq wrq;
105
106         wrq.u.essid.pointer = (caddr_t) buf;
107         wrq.u.essid.length  = IW_ESSID_MAX_SIZE + 1;
108         wrq.u.essid.flags   = 0;
109
110         if(wext_ioctl(ifname, SIOCGIWESSID, &wrq) >= 0)
111                 return 0;
112
113         return -1;
114 }
115
116 int wext_get_bssid(const char *ifname, char *buf)
117 {
118         struct iwreq wrq;
119
120         if(wext_ioctl(ifname, SIOCGIWAP, &wrq) >= 0)
121         {
122                 sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
123                         (uint8_t)wrq.u.ap_addr.sa_data[0], (uint8_t)wrq.u.ap_addr.sa_data[1],
124                         (uint8_t)wrq.u.ap_addr.sa_data[2], (uint8_t)wrq.u.ap_addr.sa_data[3],
125                         (uint8_t)wrq.u.ap_addr.sa_data[4], (uint8_t)wrq.u.ap_addr.sa_data[5]);
126
127                 return 0;
128         }
129
130         return -1;      
131 }
132
133 int wext_get_bitrate(const char *ifname, int *buf)
134 {
135         struct iwreq wrq;
136
137         if(wext_ioctl(ifname, SIOCGIWRATE, &wrq) >= 0)
138         {
139                 *buf = wrq.u.bitrate.value;
140                 return 0;
141         }
142
143         return -1;      
144 }
145
146 int wext_get_channel(const char *ifname, int *buf)
147 {
148         struct iwreq wrq;
149
150         if(wext_ioctl(ifname, SIOCGIWFREQ, &wrq) >= 0)
151         {
152                 /* FIXME: iwlib has some strange workarounds here, maybe we need them as well... */
153                 *buf = (int) wext_freq2float(&wrq.u.freq);
154                 return 0;
155         }
156
157         return -1;      
158 }
159
160 int wext_get_signal(const char *ifname, int *buf)
161 {
162         struct iwreq wrq;
163         struct iw_statistics stats;
164
165         wrq.u.data.pointer = (caddr_t) &stats;
166         wrq.u.data.length  = sizeof(struct iw_statistics);
167         wrq.u.data.flags   = 1;
168
169         if(wext_ioctl(ifname, SIOCGIWSTATS, &wrq) >= 0)
170         {
171                 *buf = (stats.qual.level - 0x100);
172                 return 0;
173         }
174
175         return -1;
176 }
177
178 int wext_get_noise(const char *ifname, int *buf)
179 {
180         struct iwreq wrq;
181         struct iw_statistics stats;
182
183         wrq.u.data.pointer = (caddr_t) &stats;
184         wrq.u.data.length  = sizeof(struct iw_statistics);
185         wrq.u.data.flags   = 1;
186
187         if(wext_ioctl(ifname, SIOCGIWSTATS, &wrq) >= 0)
188         {
189                 *buf = (stats.qual.noise - 0x100);
190                 return 0;
191         }
192
193         return -1;
194 }
195
196 int wext_get_quality(const char *ifname, int *buf)
197 {
198         struct iwreq wrq;
199         struct iw_statistics stats;
200
201         wrq.u.data.pointer = (caddr_t) &stats;
202         wrq.u.data.length  = sizeof(struct iw_statistics);
203         wrq.u.data.flags   = 1;
204
205         if(wext_ioctl(ifname, SIOCGIWSTATS, &wrq) >= 0)
206         {
207                 *buf = stats.qual.qual;
208                 return 0;
209         }
210
211         return -1;
212 }
213
214 int wext_get_quality_max(const char *ifname, int *buf)
215 {
216         struct iwreq wrq;
217         struct iw_range range;
218
219         wrq.u.data.pointer = (caddr_t) &range;
220         wrq.u.data.length  = sizeof(struct iw_range);
221         wrq.u.data.flags   = 0;
222
223         if(wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0)
224         {
225                 *buf = range.max_qual.qual;
226                 return 0;
227         }
228
229         return -1;
230 }
231
232 int wext_get_enctype(const char *ifname, char *buf)
233 {
234         /* Stub */
235         return -1;
236 }
237
238 int wext_get_assoclist(const char *ifname, char *buf, int *len)
239 {
240         /* Stub */
241         return -1;
242 }
243