5738e2cd049d3ec0c777ca2cd2a3f0c684d33363
[openwrt.git] / package / nvram / src / wl.c
1 /*
2  * Wireless network adapter utilities
3  *
4  * Copyright 2004, Broadcom Corporation
5  * All Rights Reserved.
6  * 
7  * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8  * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9  * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10  * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11  *
12  * $Id$
13  */
14 #include <string.h>
15
16 #include <typedefs.h>
17 #include <wlutils.h>
18
19 int
20 wl_probe(char *name)
21 {
22         int ret, val;
23
24         /* Check interface */
25         if ((ret = wl_ioctl(name, WLC_GET_MAGIC, &val, sizeof(val))))
26                 return ret;
27         if (val != WLC_IOCTL_MAGIC)
28                 return -1;
29         if ((ret = wl_ioctl(name, WLC_GET_VERSION, &val, sizeof(val))))
30                 return ret;
31         if (val > WLC_IOCTL_VERSION)
32                 return -1;
33
34         return ret;
35 }
36
37 int
38 wl_set_val(char *name, char *var, void *val, int len)
39 {
40         char buf[128];
41         int buf_len;
42
43         /* check for overflow */
44         if ((buf_len = strlen(var)) + 1 + len > sizeof(buf))
45                 return -1;
46         
47         strcpy(buf, var);
48         buf_len += 1;
49
50         /* append int value onto the end of the name string */
51         memcpy(&buf[buf_len], val, len);
52         buf_len += len;
53
54         return wl_ioctl(name, WLC_SET_VAR, buf, buf_len);
55 }
56
57 int
58 wl_get_val(char *name, char *var, void *val, int len)
59 {
60         char buf[128];
61         int ret;
62
63         /* check for overflow */
64         if (strlen(var) + 1 > sizeof(buf) || len > sizeof(buf))
65                 return -1;
66         
67         strcpy(buf, var);
68         if ((ret = wl_ioctl(name, WLC_GET_VAR, buf, sizeof(buf))))
69                 return ret;
70
71         memcpy(val, buf, len);
72         return 0;
73 }
74
75 int
76 wl_set_int(char *name, char *var, int val)
77 {
78         return wl_set_val(name, var, &val, sizeof(val));
79 }
80
81 int
82 wl_get_int(char *name, char *var, int *val)
83 {
84         return wl_get_val(name, var, val, sizeof(*val));
85 }
86
87 /**************************************************************************
88  *  The following code is from Broadcom (wl.c)                            *
89  **************************************************************************/
90
91 int 
92 wl_iovar_getbuf(char *ifname, char *iovar, void *param,
93                 int paramlen, void *bufptr, int buflen)
94 {
95         int err;
96         uint namelen;
97         uint iolen;
98
99         namelen = strlen(iovar) + 1;     /* length of iovar name plus null */
100         iolen = namelen + paramlen;
101
102         /* check for overflow */
103         if (iolen > buflen) 
104                 return (-1);
105
106         memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
107         memcpy((int8*)bufptr + namelen, param, paramlen);
108
109         err = wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
110         
111         return (err);
112 }
113
114 int 
115 wl_iovar_setbuf(char *ifname, char *iovar, void *param,
116                 int paramlen, void *bufptr, int buflen)
117 {
118         uint namelen;
119         uint iolen;
120
121         namelen = strlen(iovar) + 1;     /* length of iovar name plus null */
122         iolen = namelen + paramlen;
123
124         /* check for overflow */
125         if (iolen > buflen) 
126                 return (-1);
127
128         memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
129         memcpy((int8*)bufptr + namelen, param, paramlen);
130
131         return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
132 }
133
134 int
135 wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen)
136 {
137         char smbuf[WLC_IOCTL_SMLEN];
138
139         return wl_iovar_setbuf(ifname, iovar, param, paramlen, smbuf, sizeof(smbuf));
140 }
141
142 int
143 wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen)
144 {
145         char smbuf[WLC_IOCTL_SMLEN];
146         int ret;
147
148         /* use the return buffer if it is bigger than what we have on the stack */
149         if (buflen > sizeof(smbuf)) {
150                 ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, bufptr, buflen);
151         } else {
152                 ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, smbuf, sizeof(smbuf));
153                 if (ret == 0)
154                         memcpy(bufptr, smbuf, buflen);
155         }
156
157         return ret;
158 }
159
160 /* 
161  * set named driver variable to int value
162  * calling example: wl_iovar_setint(ifname, "arate", rate) 
163 */
164 int
165 wl_iovar_setint(char *ifname, char *iovar, int val)
166 {
167         return wl_iovar_set(ifname, iovar, &val, sizeof(val));
168 }
169
170 /* 
171  * get named driver variable to int value and return error indication 
172  * calling example: wl_iovar_getint(ifname, "arate", &rate) 
173  */
174 int
175 wl_iovar_getint(char *ifname, char *iovar, int *val)
176 {
177         return wl_iovar_get(ifname, iovar, val, sizeof(int));
178 }
179
180 /* 
181  * format a bsscfg indexed iovar buffer
182  */
183 static int
184 wl_bssiovar_mkbuf(char *iovar, int bssidx, void *param,
185                   int paramlen, void *bufptr, int buflen, int *plen)
186 {
187         char *prefix = "bsscfg:";
188         int8* p;
189         uint prefixlen;
190         uint namelen;
191         uint iolen;
192
193         prefixlen = strlen(prefix);     /* length of bsscfg prefix */
194         namelen = strlen(iovar) + 1;    /* length of iovar name + null */
195         iolen = prefixlen + namelen + sizeof(int) + paramlen;
196
197         /* check for overflow */
198         if (buflen < 0 || iolen > (uint)buflen) {
199                 *plen = 0;
200                 return -1;
201         }
202
203         p = (int8*)bufptr;
204
205         /* copy prefix, no null */
206         memcpy(p, prefix, prefixlen);   
207         p += prefixlen;
208
209         /* copy iovar name including null */
210         memcpy(p, iovar, namelen);      
211         p += namelen;
212
213         /* bss config index as first param */
214         memcpy(p, &bssidx, sizeof(int32));
215         p += sizeof(int32);
216         
217         /* parameter buffer follows */
218         if (paramlen)
219                 memcpy(p, param, paramlen);
220
221         *plen = iolen;
222         return 0;
223 }
224
225 /* 
226  * set named & bss indexed driver variable to buffer value
227  */
228 int
229 wl_bssiovar_setbuf(char *ifname, char *iovar, int bssidx, void *param, 
230                    int paramlen, void *bufptr, int buflen)
231 {
232         int err;
233         uint iolen;
234
235         err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen);
236         if (err)
237                 return err;
238         
239         return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
240 }
241
242 /* 
243  * get named & bss indexed driver variable buffer value
244  */
245 int
246 wl_bssiovar_getbuf(char *ifname, char *iovar, int bssidx, void *param, 
247                    int paramlen, void *bufptr, int buflen)
248 {
249         int err;
250         uint iolen;
251
252         err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen);
253         if (err)
254                 return err;
255         
256         return wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
257 }
258
259 /* 
260  * set named & bss indexed driver variable to buffer value
261  */
262 int
263 wl_bssiovar_set(char *ifname, char *iovar, int bssidx, void *param, int paramlen)
264 {
265         char smbuf[WLC_IOCTL_SMLEN];
266
267         return wl_bssiovar_setbuf(ifname, iovar, bssidx, param, paramlen, smbuf, sizeof(smbuf));
268 }
269
270 /* 
271  * get named & bss indexed driver variable buffer value
272  */
273 int
274 wl_bssiovar_get(char *ifname, char *iovar, int bssidx, void *outbuf, int len)
275 {
276         char smbuf[WLC_IOCTL_SMLEN];
277         int err;
278
279         /* use the return buffer if it is bigger than what we have on the stack */
280         if (len > (int)sizeof(smbuf)) {
281                 err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, outbuf, len);
282         } else {
283                 memset(smbuf, 0, sizeof(smbuf));
284                 err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, smbuf, sizeof(smbuf));
285                 if (err == 0)
286                         memcpy(outbuf, smbuf, len);
287         }
288
289         return err;
290 }
291
292 /* 
293  * set named & bss indexed driver variable to int value
294  */
295 int
296 wl_bssiovar_setint(char *ifname, char *iovar, int bssidx, int val)
297 {
298         return wl_bssiovar_set(ifname, iovar, bssidx, &val, sizeof(int));
299 }