add i8x0 audio driver
[openwrt.git] / package / nvram / src / wl.c
index f09317ad065f7e0da86528bad749189997cb5ea9..c33610310c5de4bfeebcd871056ea48ea8506ab5 100644 (file)
  *
  * $Id$
  */
+#include <stdio.h>
+#include <unistd.h>
 #include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
 
 #include <typedefs.h>
 #include <wlutils.h>
 
+int
+wl_ioctl(char *name, int cmd, void *buf, int len)
+{
+       struct ifreq ifr;
+       wl_ioctl_t ioc;
+       int ret = 0;
+       int s;
+
+       /* open socket to kernel */
+       if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+               perror("socket");
+               return errno;
+       }
+
+       /* do it */
+       ioc.cmd = cmd;
+       ioc.buf = buf;
+       ioc.len = len;
+       strncpy(ifr.ifr_name, name, IFNAMSIZ);
+       ifr.ifr_data = (caddr_t) &ioc;
+       if ((ret = ioctl(s, SIOCDEVPRIVATE, &ifr)) < 0)
+               if (cmd != WLC_GET_MAGIC)
+                       perror(ifr.ifr_name);
+
+       /* cleanup */
+       close(s);
+       return ret;
+}
+
+int
+wl_hwaddr(char *name, unsigned char *hwaddr)
+{
+       struct ifreq ifr;
+       int ret = 0;
+       int s;
+
+       /* open socket to kernel */
+       if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+               perror("socket");
+               return errno;
+       }
+
+       /* do it */
+       strncpy(ifr.ifr_name, name, IFNAMSIZ);
+       if ((ret = ioctl(s, SIOCGIFHWADDR, &ifr)) == 0)
+               memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
+
+       /* cleanup */
+       close(s);
+       return ret;
+}      
+
 int
 wl_probe(char *name)
 {
@@ -84,3 +141,216 @@ wl_get_int(char *name, char *var, int *val)
        return wl_get_val(name, var, val, sizeof(*val));
 }
 
+/**************************************************************************
+ *  The following code is from Broadcom (wl.c)                            *
+ **************************************************************************/
+
+int 
+wl_iovar_getbuf(char *ifname, char *iovar, void *param,
+               int paramlen, void *bufptr, int buflen)
+{
+       int err;
+       uint namelen;
+       uint iolen;
+
+       namelen = strlen(iovar) + 1;     /* length of iovar name plus null */
+       iolen = namelen + paramlen;
+
+       /* check for overflow */
+       if (iolen > buflen) 
+               return (-1);
+
+       memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
+       memcpy((int8*)bufptr + namelen, param, paramlen);
+
+       err = wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
+       
+       return (err);
+}
+
+int 
+wl_iovar_setbuf(char *ifname, char *iovar, void *param,
+               int paramlen, void *bufptr, int buflen)
+{
+       uint namelen;
+       uint iolen;
+
+       namelen = strlen(iovar) + 1;     /* length of iovar name plus null */
+       iolen = namelen + paramlen;
+
+       /* check for overflow */
+       if (iolen > buflen) 
+               return (-1);
+
+       memcpy(bufptr, iovar, namelen); /* copy iovar name including null */
+       memcpy((int8*)bufptr + namelen, param, paramlen);
+
+       return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
+}
+
+int
+wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen)
+{
+       char smbuf[WLC_IOCTL_SMLEN];
+
+       return wl_iovar_setbuf(ifname, iovar, param, paramlen, smbuf, sizeof(smbuf));
+}
+
+int
+wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen)
+{
+       char smbuf[WLC_IOCTL_SMLEN];
+       int ret;
+
+       /* use the return buffer if it is bigger than what we have on the stack */
+       if (buflen > sizeof(smbuf)) {
+               ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, bufptr, buflen);
+       } else {
+               ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, smbuf, sizeof(smbuf));
+               if (ret == 0)
+                       memcpy(bufptr, smbuf, buflen);
+       }
+
+       return ret;
+}
+
+/* 
+ * set named driver variable to int value
+ * calling example: wl_iovar_setint(ifname, "arate", rate) 
+*/
+int
+wl_iovar_setint(char *ifname, char *iovar, int val)
+{
+       return wl_iovar_set(ifname, iovar, &val, sizeof(val));
+}
+
+/* 
+ * get named driver variable to int value and return error indication 
+ * calling example: wl_iovar_getint(ifname, "arate", &rate) 
+ */
+int
+wl_iovar_getint(char *ifname, char *iovar, int *val)
+{
+       return wl_iovar_get(ifname, iovar, val, sizeof(int));
+}
+
+/* 
+ * format a bsscfg indexed iovar buffer
+ */
+static int
+wl_bssiovar_mkbuf(char *iovar, int bssidx, void *param,
+                 int paramlen, void *bufptr, int buflen, int *plen)
+{
+       char *prefix = "bsscfg:";
+       int8* p;
+       uint prefixlen;
+       uint namelen;
+       uint iolen;
+
+       prefixlen = strlen(prefix);     /* length of bsscfg prefix */
+       namelen = strlen(iovar) + 1;    /* length of iovar name + null */
+       iolen = prefixlen + namelen + sizeof(int) + paramlen;
+
+       /* check for overflow */
+       if (buflen < 0 || iolen > (uint)buflen) {
+               *plen = 0;
+               return -1;
+       }
+
+       p = (int8*)bufptr;
+
+       /* copy prefix, no null */
+       memcpy(p, prefix, prefixlen);   
+       p += prefixlen;
+
+       /* copy iovar name including null */
+       memcpy(p, iovar, namelen);      
+       p += namelen;
+
+       /* bss config index as first param */
+       memcpy(p, &bssidx, sizeof(int32));
+       p += sizeof(int32);
+       
+       /* parameter buffer follows */
+       if (paramlen)
+               memcpy(p, param, paramlen);
+
+       *plen = iolen;
+       return 0;
+}
+
+/* 
+ * set named & bss indexed driver variable to buffer value
+ */
+int
+wl_bssiovar_setbuf(char *ifname, char *iovar, int bssidx, void *param, 
+                  int paramlen, void *bufptr, int buflen)
+{
+       int err;
+       uint iolen;
+
+       err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen);
+       if (err)
+               return err;
+       
+       return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen);
+}
+
+/* 
+ * get named & bss indexed driver variable buffer value
+ */
+int
+wl_bssiovar_getbuf(char *ifname, char *iovar, int bssidx, void *param, 
+                  int paramlen, void *bufptr, int buflen)
+{
+       int err;
+       uint iolen;
+
+       err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen);
+       if (err)
+               return err;
+       
+       return wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen);
+}
+
+/* 
+ * set named & bss indexed driver variable to buffer value
+ */
+int
+wl_bssiovar_set(char *ifname, char *iovar, int bssidx, void *param, int paramlen)
+{
+       char smbuf[WLC_IOCTL_SMLEN];
+
+       return wl_bssiovar_setbuf(ifname, iovar, bssidx, param, paramlen, smbuf, sizeof(smbuf));
+}
+
+/* 
+ * get named & bss indexed driver variable buffer value
+ */
+int
+wl_bssiovar_get(char *ifname, char *iovar, int bssidx, void *outbuf, int len)
+{
+       char smbuf[WLC_IOCTL_SMLEN];
+       int err;
+
+       /* use the return buffer if it is bigger than what we have on the stack */
+       if (len > (int)sizeof(smbuf)) {
+               err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, outbuf, len);
+       } else {
+               memset(smbuf, 0, sizeof(smbuf));
+               err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, smbuf, sizeof(smbuf));
+               if (err == 0)
+                       memcpy(outbuf, smbuf, len);
+       }
+
+       return err;
+}
+
+/* 
+ * set named & bss indexed driver variable to int value
+ */
+int
+wl_bssiovar_setint(char *ifname, char *iovar, int bssidx, int val)
+{
+       return wl_bssiovar_set(ifname, iovar, bssidx, &val, sizeof(int));
+}