Exemplo n.º 1
0
/*
 * Process a TLV from a 'state report'
 *
 * @i2400m: device descriptor
 * @tlv: pointer to the TLV header; it has been already validated for
 *     consistent size.
 * @tag: for error messages
 *
 * Act on the TLVs from a 'state report'.
 */
static
void i2400m_report_state_parse_tlv(struct i2400m *i2400m,
				   const struct i2400m_tlv_hdr *tlv,
				   const char *tag)
{
	struct device *dev = i2400m_dev(i2400m);
	const struct i2400m_tlv_media_status *ms;
	const struct i2400m_tlv_system_state *ss;
	const struct i2400m_tlv_rf_switches_status *rfss;

	if (0 == i2400m_tlv_match(tlv, I2400M_TLV_SYSTEM_STATE, sizeof(*ss))) {
		ss = container_of(tlv, typeof(*ss), hdr);
		d_printf(2, dev, "%s: system state TLV "
			 "found (0x%04x), state 0x%08x\n",
			 tag, I2400M_TLV_SYSTEM_STATE,
			 le32_to_cpu(ss->state));
		i2400m_report_tlv_system_state(i2400m, ss);
	}
	if (0 == i2400m_tlv_match(tlv, I2400M_TLV_RF_STATUS, sizeof(*rfss))) {
		rfss = container_of(tlv, typeof(*rfss), hdr);
		d_printf(2, dev, "%s: RF status TLV "
			 "found (0x%04x), sw 0x%02x hw 0x%02x\n",
			 tag, I2400M_TLV_RF_STATUS,
			 le32_to_cpu(rfss->sw_rf_switch),
			 le32_to_cpu(rfss->hw_rf_switch));
		i2400m_report_tlv_rf_switches_status(i2400m, rfss);
	}
	if (0 == i2400m_tlv_match(tlv, I2400M_TLV_MEDIA_STATUS, sizeof(*ms))) {
		ms = container_of(tlv, typeof(*ms), hdr);
		d_printf(2, dev, "%s: Media Status TLV: %u\n",
			 tag, le32_to_cpu(ms->media_status));
		i2400m_report_tlv_media_status(i2400m, ms);
	}
}
Exemplo n.º 2
0
/*
 * Parse a 'state report' and extract carrier on/off information
 *
 * @i2400m: device descriptor
 * @l3l4_hdr: pointer to message; it has been already validated for
 *            consistent size.
 * @size: size of the message (header + payload). The header length
 *        declaration is assumed to be congruent with @size (as in
 *        sizeof(*l3l4_hdr) + l3l4_hdr->length == size)
 *
 * Extract from the report state the system state TLV and infer from
 * there if we have a carrier or not. Update our local state and tell
 * netdev.
 *
 * When setting the carrier, it's fine to set OFF twice (for example),
 * as netif_carrier_off() will not generate two OFF events (just on
 * the transitions).
 */
static
void i2400m_report_state_hook(struct i2400m *i2400m,
			      const struct i2400m_l3l4_hdr *l3l4_hdr,
			      size_t size, const char *tag)
{
	struct device *dev = i2400m_dev(i2400m);
	const struct i2400m_tlv_hdr *tlv;
	const struct i2400m_tlv_system_state *ss;
	const struct i2400m_tlv_rf_switches_status *rfss;
	const struct i2400m_tlv_media_status *ms;
	size_t tlv_size = le16_to_cpu(l3l4_hdr->length);

	d_fnstart(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s)\n",
		  i2400m, l3l4_hdr, size, tag);
	tlv = NULL;

	while ((tlv = i2400m_tlv_buffer_walk(i2400m, &l3l4_hdr->pl,
					     tlv_size, tlv))) {
		if (0 == i2400m_tlv_match(tlv, I2400M_TLV_SYSTEM_STATE,
					  sizeof(*ss))) {
			ss = container_of(tlv, typeof(*ss), hdr);
			d_printf(2, dev, "%s: system state TLV "
				 "found (0x%04x), state 0x%08x\n",
				 tag, I2400M_TLV_SYSTEM_STATE,
				 le32_to_cpu(ss->state));
			i2400m_report_tlv_system_state(i2400m, ss);
		}
		if (0 == i2400m_tlv_match(tlv, I2400M_TLV_RF_STATUS,
					  sizeof(*rfss))) {
			rfss = container_of(tlv, typeof(*rfss), hdr);
			d_printf(2, dev, "%s: RF status TLV "
				 "found (0x%04x), sw 0x%02x hw 0x%02x\n",
				 tag, I2400M_TLV_RF_STATUS,
				 le32_to_cpu(rfss->sw_rf_switch),
				 le32_to_cpu(rfss->hw_rf_switch));
			i2400m_report_tlv_rf_switches_status(i2400m, rfss);
		}
		if (0 == i2400m_tlv_match(tlv, I2400M_TLV_MEDIA_STATUS,
					  sizeof(*ms))) {
			ms = container_of(tlv, typeof(*ms), hdr);
			d_printf(2, dev, "%s: Media Status TLV: %u\n",
				 tag, le32_to_cpu(ms->media_status));
			i2400m_report_tlv_media_status(i2400m, ms);
		}
	}
	d_fnend(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s) = void\n",
		i2400m, l3l4_hdr, size, tag);
}
Exemplo n.º 3
0
/**
 * Find a TLV by type (and maybe length) in a buffer of TLVs
 *
 * @param tlv_hdr pointer to the first TLV in the sequence
 *
 * @param size size of the buffer in bytes; all TLVs are assumed to fit
 *     fully in the buffer (otherwise we'll complain).
 *
 * @param tlv_type type of the TLV we are looking for
 *
 * @param tlv_size expected size of the TLV we are looking for (if -1,
 *     don't check the size). This includes the header
 *
 * @returns NULL if the TLV is not found, otherwise a pointer to
 *     it. If the sizes don't match, an error is printed and NULL
 *     returned.
 *
 * @ingroup i2400m_group
 */
const struct i2400m_tlv_hdr *i2400m_tlv_find(
	const struct i2400m_tlv_hdr *tlv_hdr, size_t size,
	enum i2400m_tlv tlv_type, ssize_t tlv_size)
{
	ssize_t match;
	const struct i2400m_tlv_hdr *tlv = NULL;
	while ((tlv = i2400m_tlv_buffer_walk(tlv_hdr, size, tlv))) {
		match = i2400m_tlv_match(tlv, tlv_type, tlv_size);
		if (match == 0)		/* found it :) */
			break;
		if (match > 0)
			wimaxll_msg(NULL,
				    "TLV type 0x%04x found with size "
				    "mismatch (%zu vs %zu needed)\n",
				    tlv_type, match, tlv_size);
	}
	return tlv;
}
Exemplo n.º 4
0
/*
 * Find a TLV in a buffer of sequential TLVs
 *
 * @i2400m: device descriptor
 * @tlv_hdr: pointer to the first TLV in the sequence
 * @size: size of the buffer in bytes; all TLVs are assumed to fit
 *        fully in the buffer (otherwise we'll complain).
 * @tlv_type: type of the TLV we are looking for
 * @tlv_size: expected size of the TLV we are looking for (if -1,
 *            don't check the size). This includes the header
 *
 * Returns: NULL if the TLV is not found, otherwise a pointer to
 *          it. If the sizes don't match, an error is printed and NULL
 *          returned.
 */
static
const struct i2400m_tlv_hdr *i2400m_tlv_find(
	struct i2400m *i2400m,
	const struct i2400m_tlv_hdr *tlv_hdr, size_t size,
	enum i2400m_tlv tlv_type, ssize_t tlv_size)
{
	ssize_t match;
	struct device *dev = i2400m_dev(i2400m);
	const struct i2400m_tlv_hdr *tlv = NULL;
	while ((tlv = i2400m_tlv_buffer_walk(i2400m, tlv_hdr, size, tlv))) {
		match = i2400m_tlv_match(tlv, tlv_type, tlv_size);
		if (match == 0)		/* found it :) */
			break;
		if (match > 0)
			dev_warn(dev, "TLV type 0x%04x found with size "
				 "mismatch (%zu vs %zu needed)\n",
				 tlv_type, match, tlv_size);
	}
	return tlv;
}