Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  fwil.c   Sprache: C

 
// SPDX-License-Identifier: ISC
/*
 * Copyright (c) 2012 Broadcom Corporation
 */


/* FWIL is the Firmware Interface Layer. In this module the support functions
 * are located to set and get variables to and from the firmware.
 */


#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
#include "core.h"
#include "bus.h"
#include "debug.h"
#include "tracepoint.h"
#include "xtlv.h"
#include "fwil.h"
#include "proto.h"


#define MAX_HEX_DUMP_LEN 64

#ifdef DEBUG
static const char * const brcmf_fil_errstr[] = {
 "BCME_OK",
 "BCME_ERROR",
 "BCME_BADARG",
 "BCME_BADOPTION",
 "BCME_NOTUP",
 "BCME_NOTDOWN",
 "BCME_NOTAP",
 "BCME_NOTSTA",
 "BCME_BADKEYIDX",
 "BCME_RADIOOFF",
 "BCME_NOTBANDLOCKED",
 "BCME_NOCLK",
 "BCME_BADRATESET",
 "BCME_BADBAND",
 "BCME_BUFTOOSHORT",
 "BCME_BUFTOOLONG",
 "BCME_BUSY",
 "BCME_NOTASSOCIATED",
 "BCME_BADSSIDLEN",
 "BCME_OUTOFRANGECHAN",
 "BCME_BADCHAN",
 "BCME_BADADDR",
 "BCME_NORESOURCE",
 "BCME_UNSUPPORTED",
 "BCME_BADLEN",
 "BCME_NOTREADY",
 "BCME_EPERM",
 "BCME_NOMEM",
 "BCME_ASSOCIATED",
 "BCME_RANGE",
 "BCME_NOTFOUND",
 "BCME_WME_NOT_ENABLED",
 "BCME_TSPEC_NOTFOUND",
 "BCME_ACM_NOTSUPPORTED",
 "BCME_NOT_WME_ASSOCIATION",
 "BCME_SDIO_ERROR",
 "BCME_DONGLE_DOWN",
 "BCME_VERSION",
 "BCME_TXFAIL",
 "BCME_RXFAIL",
 "BCME_NODEVICE",
 "BCME_NMODE_DISABLED",
 "BCME_NONRESIDENT",
 "BCME_SCANREJECT",
 "BCME_USAGE_ERROR",
 "BCME_IOCTL_ERROR",
 "BCME_SERIAL_PORT_ERR",
 "BCME_DISABLED",
 "BCME_DECERR",
 "BCME_ENCERR",
 "BCME_MICERR",
 "BCME_REPLAY",
 "BCME_IE_NOTFOUND",
};

static const char *brcmf_fil_get_errstr(u32 err)
{
 if (err >= ARRAY_SIZE(brcmf_fil_errstr))
  return "(unknown)";

 return brcmf_fil_errstr[err];
}
#else
static const char *brcmf_fil_get_errstr(u32 err)
{
 return "";
}
#endif /* DEBUG */

static s32
brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
{
 struct brcmf_pub *drvr = ifp->drvr;
 s32 err, fwerr;

 if (drvr->bus_if->state != BRCMF_BUS_UP) {
  bphy_err(drvr, "bus is down. we have nothing to do.\n");
  return -EIO;
 }

 if (data != NULL)
  len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
 if (set)
  err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd,
        data, len, &fwerr);
 else
  err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd,
          data, len, &fwerr);

 if (err) {
  brcmf_dbg(FIL, "Failed: error=%d\n", err);
 } else if (fwerr < 0) {
  brcmf_dbg(FIL, "Firmware error: %s (%d)\n",
     brcmf_fil_get_errstr((u32)(-fwerr)), fwerr);
  err = -EBADE;
 }
 if (ifp->fwil_fwerr)
  return fwerr;

 return err;
}

s32
brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
{
 s32 err;

 mutex_lock(&ifp->drvr->proto_block);

 brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d\n", ifp->ifidx, cmd, len);
 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
      min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");

 err = brcmf_fil_cmd_data(ifp, cmd, data, len, true);
 mutex_unlock(&ifp->drvr->proto_block);

 return err;
}
BRCMF_EXPORT_SYMBOL_GPL(brcmf_fil_cmd_data_set);

s32
brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
{
 s32 err;

 mutex_lock(&ifp->drvr->proto_block);
 err = brcmf_fil_cmd_data(ifp, cmd, data, len, false);

 brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d, err=%d\n", ifp->ifidx, cmd,
    len, err);
 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
      min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");

 mutex_unlock(&ifp->drvr->proto_block);

 return err;
}
BRCMF_EXPORT_SYMBOL_GPL(brcmf_fil_cmd_data_get);

static u32
brcmf_create_iovar(const char *name, const char *data, u32 datalen,
     char *buf, u32 buflen)
{
 u32 len;

 len = strlen(name) + 1;

 if ((len + datalen) > buflen)
  return 0;

 memcpy(buf, name, len);

 /* append data onto the end of the name string */
 if (data && datalen)
  memcpy(&buf[len], data, datalen);

 return len + datalen;
}


s32
brcmf_fil_iovar_data_set(struct brcmf_if *ifp, const char *name, const void *data,
    u32 len)
{
 struct brcmf_pub *drvr = ifp->drvr;
 s32 err;
 u32 buflen;

 mutex_lock(&drvr->proto_block);

 brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len);
 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
      min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");

 buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
        sizeof(drvr->proto_buf));
 if (buflen) {
  err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
      buflen, true);
 } else {
  err = -EPERM;
  bphy_err(drvr, "Creating iovar failed\n");
 }

 mutex_unlock(&drvr->proto_block);
 return err;
}
BRCMF_EXPORT_SYMBOL_GPL(brcmf_fil_iovar_data_set);

s32
brcmf_fil_iovar_data_get(struct brcmf_if *ifp, const char *name, void *data,
    u32 len)
{
 struct brcmf_pub *drvr = ifp->drvr;
 s32 err;
 u32 buflen;

 mutex_lock(&drvr->proto_block);

 buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
        sizeof(drvr->proto_buf));
 if (buflen) {
  err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
      buflen, false);
  if (err == 0)
   memcpy(data, drvr->proto_buf, len);
 } else {
  err = -EPERM;
  bphy_err(drvr, "Creating iovar failed\n");
 }

 brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d, err=%d\n", ifp->ifidx, name,
    len, err);
 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
      min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");

 mutex_unlock(&drvr->proto_block);
 return err;
}
BRCMF_EXPORT_SYMBOL_GPL(brcmf_fil_iovar_data_get);

static u32
brcmf_create_bsscfg(s32 bsscfgidx, const char *name, char *data, u32 datalen,
      char *buf, u32 buflen)
{
 const s8 *prefix = "bsscfg:";
 s8 *p;
 u32 prefixlen;
 u32 namelen;
 u32 iolen;
 __le32 bsscfgidx_le;

 if (bsscfgidx == 0)
  return brcmf_create_iovar(name, data, datalen, buf, buflen);

 prefixlen = strlen(prefix);
 namelen = strlen(name) + 1; /* length of iovar  name + null */
 iolen = prefixlen + namelen + sizeof(bsscfgidx_le) + datalen;

 if (buflen < iolen) {
  brcmf_err("buffer is too short\n");
  return 0;
 }

 p = buf;

 /* copy prefix, no null */
 memcpy(p, prefix, prefixlen);
 p += prefixlen;

 /* copy iovar name including null */
 memcpy(p, name, namelen);
 p += namelen;

 /* bss config index as first data */
 bsscfgidx_le = cpu_to_le32(bsscfgidx);
 memcpy(p, &bsscfgidx_le, sizeof(bsscfgidx_le));
 p += sizeof(bsscfgidx_le);

 /* parameter buffer follows */
 if (datalen)
  memcpy(p, data, datalen);

 return iolen;
}

s32
brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, const char *name,
     void *data, u32 len)
{
 struct brcmf_pub *drvr = ifp->drvr;
 s32 err;
 u32 buflen;

 mutex_lock(&drvr->proto_block);

 brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx,
    ifp->bsscfgidx, name, len);
 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
      min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");

 buflen = brcmf_create_bsscfg(ifp->bsscfgidx, name, data, len,
         drvr->proto_buf, sizeof(drvr->proto_buf));
 if (buflen) {
  err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
      buflen, true);
 } else {
  err = -EPERM;
  bphy_err(drvr, "Creating bsscfg failed\n");
 }

 mutex_unlock(&drvr->proto_block);
 return err;
}
BRCMF_EXPORT_SYMBOL_GPL(brcmf_fil_bsscfg_data_set);

s32
brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, const char *name,
     void *data, u32 len)
{
 struct brcmf_pub *drvr = ifp->drvr;
 s32 err;
 u32 buflen;

 mutex_lock(&drvr->proto_block);

 buflen = brcmf_create_bsscfg(ifp->bsscfgidx, name, data, len,
         drvr->proto_buf, sizeof(drvr->proto_buf));
 if (buflen) {
  err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
      buflen, false);
  if (err == 0)
   memcpy(data, drvr->proto_buf, len);
 } else {
  err = -EPERM;
  bphy_err(drvr, "Creating bsscfg failed\n");
 }
 brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d, err=%d\n",
    ifp->ifidx, ifp->bsscfgidx, name, len, err);
 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
      min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");

 mutex_unlock(&drvr->proto_block);
 return err;
}
BRCMF_EXPORT_SYMBOL_GPL(brcmf_fil_bsscfg_data_get);

static u32 brcmf_create_xtlv(const char *name, u16 id, char *data, u32 len,
        char *buf, u32 buflen)
{
 u32 iolen;
 u32 nmlen;

 nmlen = strlen(name) + 1;
 iolen = nmlen + brcmf_xtlv_data_size(len, BRCMF_XTLV_OPTION_ALIGN32);

 if (iolen > buflen) {
  brcmf_err("buffer is too short\n");
  return 0;
 }

 memcpy(buf, name, nmlen);
 brcmf_xtlv_pack_header((void *)(buf + nmlen), id, len, data,
          BRCMF_XTLV_OPTION_ALIGN32);

 return iolen;
}

s32 brcmf_fil_xtlv_data_set(struct brcmf_if *ifp, const char *name, u16 id,
       void *data, u32 len)
{
 struct brcmf_pub *drvr = ifp->drvr;
 s32 err;
 u32 buflen;

 mutex_lock(&drvr->proto_block);

 brcmf_dbg(FIL, "ifidx=%d, name=%s, id=%u, len=%u\n", ifp->ifidx, name,
    id, len);
 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
      min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");

 buflen = brcmf_create_xtlv(name, id, data, len,
       drvr->proto_buf, sizeof(drvr->proto_buf));
 if (buflen) {
  err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
      buflen, true);
 } else {
  err = -EPERM;
  bphy_err(drvr, "Creating xtlv failed\n");
 }

 mutex_unlock(&drvr->proto_block);
 return err;
}
BRCMF_EXPORT_SYMBOL_GPL(brcmf_fil_xtlv_data_set);

s32 brcmf_fil_xtlv_data_get(struct brcmf_if *ifp, const char *name, u16 id,
       void *data, u32 len)
{
 struct brcmf_pub *drvr = ifp->drvr;
 s32 err;
 u32 buflen;

 mutex_lock(&drvr->proto_block);

 buflen = brcmf_create_xtlv(name, id, data, len,
       drvr->proto_buf, sizeof(drvr->proto_buf));
 if (buflen) {
  err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
      buflen, false);
  if (err == 0)
   memcpy(data, drvr->proto_buf, len);
 } else {
  err = -EPERM;
  bphy_err(drvr, "Creating bsscfg failed\n");
 }
 brcmf_dbg(FIL, "ifidx=%d, name=%s, id=%u, len=%u, err=%d\n",
    ifp->ifidx, name, id, len, err);
 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
      min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");

 mutex_unlock(&drvr->proto_block);
 return err;
}
BRCMF_EXPORT_SYMBOL_GPL(brcmf_fil_xtlv_data_get);

Messung V0.5
C=99 H=98 G=98

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge