drivers/platform/surface/aggregator/ssh_parser.c

Source file repositories/reference/linux-study-clean/drivers/platform/surface/aggregator/ssh_parser.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/surface/aggregator/ssh_parser.c
Extension
.c
Size
7467 bytes
Lines
229
Domain
Driver Families
Bucket
drivers/platform
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (likely(get_unaligned_le16(src->ptr + i) == SSH_MSG_SYN)) {
			rem->ptr = src->ptr + i;
			rem->len = src->len - i;
			return true;
		}
	}

	if (unlikely(src->ptr[src->len - 1] == (SSH_MSG_SYN & 0xff))) {
		rem->ptr = src->ptr + src->len - 1;
		rem->len = 1;
		return false;
	}

	rem->ptr = src->ptr + src->len;
	rem->len = 0;
	return false;
}

/**
 * sshp_parse_frame() - Parse SSH frame.
 * @dev: The device used for logging.
 * @source: The source to parse from.
 * @frame: The parsed frame (output).
 * @payload: The parsed payload (output).
 * @maxlen: The maximum supported message length.
 *
 * Parses and validates a SSH frame, including its payload, from the given
 * source. Sets the provided @frame pointer to the start of the frame and
 * writes the limits of the frame payload to the provided @payload span
 * pointer.
 *
 * This function does not copy any data, but rather only validates the message
 * data and sets pointers (and length values) to indicate the respective parts.
 *
 * If no complete SSH frame could be found, the frame pointer will be set to
 * the %NULL pointer and the payload span will be set to the null span (start
 * pointer %NULL, size zero).
 *
 * Return: Returns zero on success or if the frame is incomplete, %-ENOMSG if
 * the start of the message is invalid, %-EBADMSG if any (frame-header or
 * payload) CRC is invalid, or %-EMSGSIZE if the SSH message is bigger than
 * the maximum message length specified in the @maxlen parameter.
 */
int sshp_parse_frame(const struct device *dev, const struct ssam_span *source,
		     struct ssh_frame **frame, struct ssam_span *payload,
		     size_t maxlen)
{
	struct ssam_span sf;
	struct ssam_span sp;

	/* Initialize output. */
	*frame = NULL;
	payload->ptr = NULL;
	payload->len = 0;

	if (!sshp_starts_with_syn(source)) {
		dev_warn(dev, "rx: parser: invalid start of frame\n");
		return -ENOMSG;
	}

	/* Check for minimum packet length. */
	if (unlikely(source->len < SSH_MESSAGE_LENGTH(0))) {
		dev_dbg(dev, "rx: parser: not enough data for frame\n");
		return 0;
	}

	/* Pin down frame. */
	sf.ptr = source->ptr + sizeof(u16);
	sf.len = sizeof(struct ssh_frame);

	/* Validate frame CRC. */
	if (unlikely(!sshp_validate_crc(&sf, sf.ptr + sf.len))) {
		dev_warn(dev, "rx: parser: invalid frame CRC\n");
		return -EBADMSG;
	}

	/* Ensure packet does not exceed maximum length. */
	sp.len = get_unaligned_le16(&((struct ssh_frame *)sf.ptr)->len);
	if (unlikely(SSH_MESSAGE_LENGTH(sp.len) > maxlen)) {
		dev_warn(dev, "rx: parser: frame too large: %llu bytes\n",
			 SSH_MESSAGE_LENGTH(sp.len));
		return -EMSGSIZE;
	}

	/* Pin down payload. */
	sp.ptr = sf.ptr + sf.len + sizeof(u16);

	/* Check for frame + payload length. */
	if (source->len < SSH_MESSAGE_LENGTH(sp.len)) {
		dev_dbg(dev, "rx: parser: not enough data for payload\n");

Annotation

Implementation Notes