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