Root/package/broadcom-wl/src/wlc/ioctl.c

1/*
2 * Wireless network adapter utilities
3 *
4 * Copyright 2006, 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 */
13#include <stdio.h>
14#include <unistd.h>
15#include <string.h>
16#include <errno.h>
17#include <sys/ioctl.h>
18#include <net/if.h>
19#include <linux/types.h>
20
21typedef u_int64_t u64;
22typedef u_int32_t u32;
23typedef u_int16_t u16;
24typedef u_int8_t u8;
25#include <linux/sockios.h>
26#include <linux/ethtool.h>
27
28#include <typedefs.h>
29#include <wlioctl.h>
30#include <bcmutils.h>
31#include <wlutils.h>
32
33int
34wl_ioctl(char *name, int cmd, void *buf, int len)
35{
36    struct ifreq ifr;
37    wl_ioctl_t ioc;
38    int ret = 0;
39    int s;
40
41    /* open socket to kernel */
42    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
43        perror("socket");
44        return errno;
45    }
46
47    /* do it */
48    ioc.cmd = cmd;
49    ioc.buf = buf;
50    ioc.len = len;
51    strncpy(ifr.ifr_name, name, IFNAMSIZ);
52    ifr.ifr_data = (caddr_t) &ioc;
53    if ((ret = ioctl(s, SIOCDEVPRIVATE, &ifr)) < 0)
54
55    /* cleanup */
56    close(s);
57    return ret;
58}
59
60static inline int
61wl_get_dev_type(char *name, void *buf, int len)
62{
63    int s;
64    int ret;
65    struct ifreq ifr;
66    struct ethtool_drvinfo info;
67
68    /* open socket to kernel */
69    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
70        perror("socket");
71        return -1;
72    }
73
74    /* get device type */
75    memset(&info, 0, sizeof(info));
76    info.cmd = ETHTOOL_GDRVINFO;
77    ifr.ifr_data = (caddr_t)&info;
78    strncpy(ifr.ifr_name, name, IFNAMSIZ);
79    if ((ret = ioctl(s, SIOCETHTOOL, &ifr)) < 0) {
80        *(char *)buf = '\0';
81    } else
82        strncpy(buf, info.driver, len);
83
84    close(s);
85    return ret;
86}
87
88int
89wl_probe(char *name)
90{
91    int ret, val;
92    char buf[3];
93    if ((ret = wl_get_dev_type(name, buf, 3)) < 0)
94        return ret;
95    /* Check interface */
96    if (strncmp(buf, "wl", 2))
97        return -1;
98    if ((ret = wl_ioctl(name, WLC_GET_VERSION, &val, sizeof(val))))
99        return ret;
100    if (val > WLC_IOCTL_VERSION)
101        return -1;
102
103    return ret;
104}
105
106static int
107wl_iovar_getbuf(char *ifname, char *iovar, void *param, int paramlen, void *bufptr, int buflen)
108{
109    int err;
110    uint namelen;
111    uint iolen;
112
113    namelen = strlen(iovar) + 1; /* length of iovar name plus null */
114    iolen = namelen + paramlen;
115
116    /* check for overflow */
117    if (iolen > buflen)
118        return (BCME_BUFTOOSHORT);
119
120    memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
121    memcpy((int8*)bufptr + namelen, param, paramlen);
122
123    err = wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
124
125    return (err);
126}
127
128static int
129wl_iovar_setbuf(char *ifname, char *iovar, void *param, int paramlen, void *bufptr, int buflen)
130{
131    uint namelen;
132    uint iolen;
133
134    namelen = strlen(iovar) + 1; /* length of iovar name plus null */
135    iolen = namelen + paramlen;
136
137    /* check for overflow */
138    if (iolen > buflen)
139        return (BCME_BUFTOOSHORT);
140
141    memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
142    memcpy((int8*)bufptr + namelen, param, paramlen);
143
144    return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
145}
146
147int
148wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen)
149{
150    char smbuf[WLC_IOCTL_SMLEN];
151
152    return wl_iovar_setbuf(ifname, iovar, param, paramlen, smbuf, sizeof(smbuf));
153}
154
155int
156wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen)
157{
158    char smbuf[WLC_IOCTL_SMLEN];
159    int ret;
160
161    /* use the return buffer if it is bigger than what we have on the stack */
162    if (buflen > sizeof(smbuf)) {
163        ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, bufptr, buflen);
164    } else {
165        ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, smbuf, sizeof(smbuf));
166        if (ret == 0)
167            memcpy(bufptr, smbuf, buflen);
168    }
169
170    return ret;
171}
172
173
174/*
175 * format a bsscfg indexed iovar buffer
176 */
177static int
178wl_bssiovar_mkbuf(char *iovar, int bssidx, void *param, int paramlen, void *bufptr, int buflen,
179                  int *plen)
180{
181    char *prefix = "bsscfg:";
182    int8* p;
183    uint prefixlen;
184    uint namelen;
185    uint iolen;
186
187    prefixlen = strlen(prefix); /* length of bsscfg prefix */
188    namelen = strlen(iovar) + 1; /* length of iovar name + null */
189    iolen = prefixlen + namelen + sizeof(int) + paramlen;
190
191    /* check for overflow */
192    if (buflen < 0 || iolen > (uint)buflen) {
193        *plen = 0;
194        return BCME_BUFTOOSHORT;
195    }
196
197    p = (int8*)bufptr;
198
199    /* copy prefix, no null */
200    memcpy(p, prefix, prefixlen);
201    p += prefixlen;
202
203    /* copy iovar name including null */
204    memcpy(p, iovar, namelen);
205    p += namelen;
206
207    /* bss config index as first param */
208    memcpy(p, &bssidx, sizeof(int32));
209    p += sizeof(int32);
210
211    /* parameter buffer follows */
212    if (paramlen)
213        memcpy(p, param, paramlen);
214
215    *plen = iolen;
216    return 0;
217}
218
219/*
220 * set named & bss indexed driver variable to buffer value
221 */
222static int
223wl_bssiovar_setbuf(char *ifname, char *iovar, int bssidx, void *param, int paramlen, void *bufptr,
224                   int buflen)
225{
226    int err;
227    int iolen;
228
229    err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen);
230    if (err)
231        return err;
232
233    return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
234}
235
236/*
237 * get named & bss indexed driver variable buffer value
238 */
239static int
240wl_bssiovar_getbuf(char *ifname, char *iovar, int bssidx, void *param, int paramlen, void *bufptr,
241                   int buflen)
242{
243    int err;
244    int iolen;
245
246    err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen);
247    if (err)
248        return err;
249
250    return wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
251}
252
253/*
254 * set named & bss indexed driver variable to buffer value
255 */
256int
257wl_bssiovar_set(char *ifname, char *iovar, int bssidx, void *param, int paramlen)
258{
259    char smbuf[WLC_IOCTL_SMLEN];
260
261    return wl_bssiovar_setbuf(ifname, iovar, bssidx, param, paramlen, smbuf, sizeof(smbuf));
262}
263
264/*
265 * get named & bss indexed driver variable buffer value
266 */
267int
268wl_bssiovar_get(char *ifname, char *iovar, int bssidx, void *outbuf, int len)
269{
270    char smbuf[WLC_IOCTL_SMLEN];
271    int err;
272
273    /* use the return buffer if it is bigger than what we have on the stack */
274    if (len > (int)sizeof(smbuf)) {
275        err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, outbuf, len);
276    } else {
277        memset(smbuf, 0, sizeof(smbuf));
278        err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, smbuf, sizeof(smbuf));
279        if (err == 0)
280            memcpy(outbuf, smbuf, len);
281    }
282
283    return err;
284}
285
286void
287wl_printlasterror(char *name)
288{
289    char err_buf[WLC_IOCTL_SMLEN];
290    strcpy(err_buf, "bcmerrstr");
291
292    fprintf(stderr, "Error: ");
293    if ( wl_ioctl(name, WLC_GET_VAR, err_buf, sizeof (err_buf)) != 0)
294        fprintf(stderr, "Error getting the Errorstring from driver\n");
295    else
296        fprintf(stderr, err_buf);
297}
298

Archive Download this file



interactive