/* ioctl interface to hermes_read_ltv() * To use with iwpriv, pass the RID as the token argument, e.g. * iwpriv get_rid [0xfc00] * At least Wireless Tools 25 is required to use iwpriv. * For Wireless Tools 25 and 26 append "dummy" are the end. */ static int orinoco_ioctl_getrid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra) { struct orinoco_private *priv = ndev_priv(dev); hermes_t *hw = &priv->hw; int rid = data->flags; u16 length; int err; unsigned long flags; /* It's a "get" function, but we don't want users to access the * WEP key and other raw firmware data */ if (!capable(CAP_NET_ADMIN)) return -EPERM; if (rid < 0xfc00 || rid > 0xffff) return -EINVAL; if (orinoco_lock(priv, &flags) != 0) return -EBUSY; err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length, extra); if (err) goto out; data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length), MAX_RID_LEN); out: orinoco_unlock(priv, &flags); return err; }
/* Read a Length-Type-Value record from the card. * * If length is NULL, we ignore the length read from the card, and * read the entire buffer regardless. This is useful because some of * the configuration records appear to have incorrect lengths in * practice. * * Callable from user or bh context. */ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, u16 *length, void *buf) { int err = 0; int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; u16 rlength, rtype; unsigned nwords; if ( (bufsize < 0) || (bufsize % 2) ) return -EINVAL; err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, NULL); if (err) return err; err = hermes_bap_seek(hw, bap, rid, 0); if (err) return err; rlength = hermes_read_reg(hw, dreg); if (! rlength) return -ENOENT; rtype = hermes_read_reg(hw, dreg); if (length) *length = rlength; if (rtype != rid) printk(KERN_WARNING "hermes @ %s0x%lx: " "hermes_read_ltv(): rid (0x%04x) does not match type (0x%04x)\n", IO_TYPE(hw), hw->iobase, rid, rtype); if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize) printk(KERN_WARNING "hermes @ %s0x%lx: " "Truncating LTV record from %d to %d bytes. " "(rid=0x%04x, len=0x%04x)\n", IO_TYPE(hw), hw->iobase, HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength); nwords = min((unsigned)rlength - 1, bufsize / 2); hermes_read_words(hw, dreg, buf, nwords); return 0; }
/* Read a Length-Type-Value record from the card. * * If length is NULL, we ignore the length read from the card, and * read the entire buffer regardless. This is useful because some of * the configuration records appear to have incorrect lengths in * practice. * * Callable from user or bh context. */ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, int bufsize, u16 *length, void *buf) { int err = 0; int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; u16 rlength, rtype; hermes_response_t resp; if (bufsize % 2) return -EINVAL; err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, &resp); if (err) goto out; err = hermes_bap_seek(hw, bap, rid, 0); if (err) goto out; rlength = hermes_read_reg(hw, dreg); rtype = hermes_read_reg(hw, dreg); if (length) *length = rlength; if (rtype != rid) printk(KERN_WARNING "hermes_read_ltv(): rid (0x%04x) does " "not match type (0x%04x)\n", rid, rtype); if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize) printk(KERN_WARNING "hermes @ 0x%x: Truncating LTV record from %d to %d bytes. " "(rid=0x%04x, len=0x%04x)\n", hw->iobase, HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength); /* FIXME: we should read the min of the requested length and the actual record length */ hermes_read_words(hw, dreg, buf, bufsize / 2); out: return err; }