blob: ebfbc6c8b12492955e08ea19f71cc0e9bcb89fdf [file] [log] [blame]
/*
* This file is part of the UWB stack for linux.
*
* Copyright (c) 2020-2021 Qorvo US, Inc.
*
* This software is provided under the GNU General Public License, version 2
* (GPLv2), as well as under a Qorvo commercial license.
*
* You may choose to use this software under the terms of the GPLv2 License,
* version 2 ("GPLv2"), as published by the Free Software Foundation.
* You should have received a copy of the GPLv2 along with this program. If
* not, see <http://www.gnu.org/licenses/>.
*
* This program is distributed under the GPLv2 in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GPLv2 for more
* details.
*
* If you cannot meet the requirements of the GPLv2, you may not use this
* software for any purpose without first obtaining a commercial license from
* Qorvo. Please contact Qorvo to inquire about licensing terms.
*/
#ifndef NET_MCPS802154_FRAME_H
#define NET_MCPS802154_FRAME_H
#include <linux/skbuff.h>
#define IEEE802154_FC_NO_SEQ_SHIFT 8
#define IEEE802154_FC_NO_SEQ (1 << IEEE802154_FC_NO_SEQ_SHIFT)
#define IEEE802154_FC_IE_PRESENT_SHIFT 9
#define IEEE802154_FC_IE_PRESENT (1 << IEEE802154_FC_IE_PRESENT_SHIFT)
#define IEEE802154_SCF_LEN 1
#define IEEE802154_SCF_NO_FRAME_COUNTER (1 << 5)
#define IEEE802154_IE_HEADER_LEN 2
#define IEEE802154_IE_HEADER_TYPE_SHIFT 15
#define IEEE802154_IE_HEADER_TYPE (1 << IEEE802154_IE_HEADER_TYPE_SHIFT)
#define IEEE802154_HEADER_IE_HEADER_LENGTH 0x7f
#define IEEE802154_HEADER_IE_HEADER_ELEMENT_ID (0xff << 7)
#define IEEE802154_HEADER_IE_HEADER_TYPE (0 << IEEE802154_IE_HEADER_TYPE_SHIFT)
#define IEEE802154_PAYLOAD_IE_HEADER_LENGTH 0x7ff
#define IEEE802154_PAYLOAD_IE_HEADER_GROUP_ID (0xf << 11)
#define IEEE802154_PAYLOAD_IE_HEADER_TYPE (1 << IEEE802154_IE_HEADER_TYPE_SHIFT)
#define IEEE802154_LONG_NESTED_IE_HEADER_LENGTH 0x7ff
#define IEEE802154_LONG_NESTED_IE_HEADER_SUB_ID (0xf << 11)
#define IEEE802154_LONG_NESTED_IE_HEADER_TYPE \
(1 << IEEE802154_IE_HEADER_TYPE_SHIFT)
#define IEEE802154_SHORT_NESTED_IE_HEADER_LENGTH 0xff
#define IEEE802154_SHORT_NESTED_IE_HEADER_SUB_ID (0x7f << 8)
#define IEEE802154_SHORT_NESTED_IE_HEADER_TYPE \
(0 << IEEE802154_IE_HEADER_TYPE_SHIFT)
#define IEEE802154_IE_NESTED_SHORT_MIN_SID 0x10
#define IEEE802154_IE_HEADER_VENDOR_ID 0x00
#define IEEE802154_IE_HEADER_TERMINATION_1_ID 0x7e
#define IEEE802154_IE_HEADER_TERMINATION_2_ID 0x7f
#define IEEE802154_IE_PAYLOAD_MLME_GID 0x1
#define IEEE802154_IE_PAYLOAD_VENDOR_GID 0x2
#define IEEE802154_IE_PAYLOAD_TERMINATION_GID 0xf
struct mcps802154_llhw;
/**
* enum mcps802154_ie_get_kind - Kind of IE, or none.
* @MCPS802154_IE_GET_KIND_NONE: No IE decoded (at end of frame).
* @MCPS802154_IE_GET_KIND_HEADER: Header IE decoded.
* @MCPS802154_IE_GET_KIND_PAYLOAD: Payload IE decoded.
* @MCPS802154_IE_GET_KIND_MLME_NESTED:
* Nested IE inside a MLME payload IE decoded.
*/
enum mcps802154_ie_get_kind {
MCPS802154_IE_GET_KIND_NONE,
MCPS802154_IE_GET_KIND_HEADER,
MCPS802154_IE_GET_KIND_PAYLOAD,
MCPS802154_IE_GET_KIND_MLME_NESTED,
};
/**
* struct mcps802154_ie_get_context - Context for IE decoding, to be used with
* mcps802154_ie_get(). Initialize to zero.
*/
struct mcps802154_ie_get_context {
/**
* @in_payload: If true, next decoding is in payload.
*/
bool in_payload;
/**
* @kind: Kind of decoded IE.
*/
enum mcps802154_ie_get_kind kind;
/**
* @id: Element identifier, group identifier or sub identifier of the
* decoded IE.
*/
int id;
/**
* @len: Length of the decoded IE.
*/
unsigned int len;
/**
* @mlme_len: While an MLME IE is decoded, length of data still in the
* frame buffer for this IE. Set this to 0 if you pulled all the MLME
* payload.
*/
unsigned int mlme_len;
};
/**
* mcps802154_frame_alloc() - Allocate a buffer for TX.
* @llhw: Low-level device pointer.
* @size: Header and payload size.
* @flags: Allocation mask.
*
* This is to allocate a buffer for sending a frame to the low-level driver
* directly. Additional space is reserved for low-level driver headroom and for
* checksum.
*
* Return: Allocated buffer, or NULL.
*/
struct sk_buff *mcps802154_frame_alloc(struct mcps802154_llhw *llhw,
unsigned int size, gfp_t flags);
/**
* mcps802154_ie_put_begin() - Begin writing information elements.
* @skb: Frame buffer.
*
* Prepare a frame buffer for writing IEs. The buffer control buffer is used to
* store state information.
*/
void mcps802154_ie_put_begin(struct sk_buff *skb);
/**
* mcps802154_ie_put_end() - End writing information elements.
* @skb: Frame buffer.
* @data_payload: True if data will be appended to the buffer after the IEs. In
* this case, a terminator IE may be needed.
*
* This function appends a terminator IE if needed.
*
* Return: Length of frame header or -ENOBUFS in case of error.
*/
int mcps802154_ie_put_end(struct sk_buff *skb, bool data_payload);
/**
* mcps802154_ie_put_header_ie() - Add a header IE.
* @skb: Frame buffer.
* @element_id: Header IE element identifier.
* @len: Header IE payload length.
*
* This adds the IE header and reserves room to write your payload. This works
* like skb_put, you must write at the returned address.
*
* Return: Address of reserved space to write payload, or NULL in case of error.
*/
void *mcps802154_ie_put_header_ie(struct sk_buff *skb, int element_id,
unsigned int len);
/**
* mcps802154_ie_put_payload_ie() - Add a payload IE.
* @skb: Frame buffer.
* @group_id: Payload IE group identifier.
* @len: Payload IE payload length.
*
* This adds the IE header and reserves room to write your payload. This works
* like skb_put, you must write at the returned address.
*
* Return: Address of reserved space to write payload, or NULL in case of error.
*/
void *mcps802154_ie_put_payload_ie(struct sk_buff *skb, int group_id,
unsigned int len);
/**
* mcps802154_ie_put_nested_mlme_ie() - Add a nested IE, inside a MLME IE.
* @skb: Frame buffer.
* @sub_id: Nested IE element identifier.
* @len: Nested IE payload length.
*
* This adds the IE header and reserves room to write your payload. This works
* like skb_put, you must write at the returned address.
*
* The MLME payload IE is added automatically if needed and its length is
* incremented if present yet.
*
* Return: Address of reserved space to write payload, or NULL in case of error.
*/
void *mcps802154_ie_put_nested_mlme_ie(struct sk_buff *skb, int sub_id,
unsigned int len);
/**
* mcps802154_ie_get() - Parse one IE and fill context.
* @skb: Frame buffer.
* @context: Parse context, should be zero initialized at first call.
*
* This should only be called if the buffer contains IEs. This can be determined
* using the IE_PRESENT bit in the frame control.
*
* On successful parsing, the context structure is filled with information about
* the read IE. The IE payload can be read at the head of the frame buffer,
* headers are consumed.
*
* On last return, 1 is returned and a termination IE can be present in the
* context, it usually can be ignored.
*
* When an MLME IE is found, you have two options:
* - ignore it and call again to parse nested IE.
* - pull nested payload from the frame buffer, in this case you should set
* mlme_len to zero to proceed with the next IE.
*
* Return: 1 if last IE, 0 on successfully decoded IE, else negative error code.
*/
int mcps802154_ie_get(struct sk_buff *skb,
struct mcps802154_ie_get_context *context);
/**
* mcps802154_get_extended_addr() - Get current extended address.
* @llhw: Low-level device pointer.
*
* Return: Extended address.
*/
__le64 mcps802154_get_extended_addr(struct mcps802154_llhw *llhw);
/**
* mcps802154_get_pan_id() - Get current PAN identifier.
* @llhw: Low-level device pointer.
*
* Return: PAN ID.
*/
__le16 mcps802154_get_pan_id(struct mcps802154_llhw *llhw);
/**
* mcps802154_get_short_addr() - Get current short address.
* @llhw: Low-level device pointer.
*
* Return: Short address.
*/
__le16 mcps802154_get_short_addr(struct mcps802154_llhw *llhw);
/**
* mcps802154_get_current_channel() - Get current channel.
* @llhw: Low-level device pointer.
*
* Return: Channel parameters.
*/
const struct mcps802154_channel *
mcps802154_get_current_channel(struct mcps802154_llhw *llhw);
/**
* mcps802154_get_current_timestamp_dtu() - Get current timestamp in device time
* unit.
* @llhw: Low-level device pointer.
* @timestamp_dtu: Pointer to timestamp to write.
*
* Return: 0 or error.
*/
int mcps802154_get_current_timestamp_dtu(struct mcps802154_llhw *llhw,
u32 *timestamp_dtu);
/**
* mcps802154_tx_timestamp_dtu_to_rmarker_rctu() - Compute the RMARKER timestamp
* in ranging counter time unit for a frame transmitted at given timestamp in
* device time unit (RDEV only).
* @llhw: Low-level device pointer.
* @tx_timestamp_dtu: TX timestamp in device time unit.
* @ant_id: Antenna used to transmit.
*
* Return: RMARKER timestamp in ranging count time unit.
*/
u64 mcps802154_tx_timestamp_dtu_to_rmarker_rctu(struct mcps802154_llhw *llhw,
u32 tx_timestamp_dtu,
int ant_id);
/**
* mcps802154_difference_timestamp_rctu() - Compute the difference between two
* timestamp values.
* @llhw: Low-level device pointer.
* @timestamp_a_rctu: Timestamp A value.
* @timestamp_b_rctu: Timestamp B value.
*
* Return: Difference between A and B.
*/
s64 mcps802154_difference_timestamp_rctu(struct mcps802154_llhw *llhw,
u64 timestamp_a_rctu,
u64 timestamp_b_rctu);
/**
* mcps802154_vendor_cmd() - Run a driver vendor specific command.
* @llhw: Low-level device pointer.
* @vendor_id: Vendor identifier as an OUI.
* @subcmd: Command identifier.
* @data: Data to be passed to driver, can be in/out.
* @data_len: Data length.
*
* The valid moment to call this function is driver and command specific.
*
* Return: 0 or error.
*/
int mcps802154_vendor_cmd(struct mcps802154_llhw *llhw, u32 vendor_id,
u32 subcmd, void *data, size_t data_len);
#endif /* NET_MCPS802154_FRAME_H */