aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/surface/aggregator/ssh_parser.h
blob: 63c38d35098845e61a24f4580149ee4ff7deaedf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * SSH message parser.
 *
 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
 */

#ifndef _SURFACE_AGGREGATOR_SSH_PARSER_H
#define _SURFACE_AGGREGATOR_SSH_PARSER_H

#include <linux/device.h>
#include <linux/kfifo.h>
#include <linux/slab.h>
#include <linux/types.h>

#include <linux/surface_aggregator/serial_hub.h>

/**
 * struct sshp_buf - Parser buffer for SSH messages.
 * @ptr: Pointer to the beginning of the buffer.
 * @len: Number of bytes used in the buffer.
 * @cap: Maximum capacity of the buffer.
 */
struct sshp_buf {
	u8    *ptr;
	size_t len;
	size_t cap;
};

/**
 * sshp_buf_init() - Initialize a SSH parser buffer.
 * @buf: The buffer to initialize.
 * @ptr: The memory backing the buffer.
 * @cap: The length of the memory backing the buffer, i.e. its capacity.
 *
 * Initializes the buffer with the given memory as backing and set its used
 * length to zero.
 */
static inline void sshp_buf_init(struct sshp_buf *buf, u8 *ptr, size_t cap)
{
	buf->ptr = ptr;
	buf->len = 0;
	buf->cap = cap;
}

/**
 * sshp_buf_alloc() - Allocate and initialize a SSH parser buffer.
 * @buf:   The buffer to initialize/allocate to.
 * @cap:   The desired capacity of the buffer.
 * @flags: The flags used for allocating the memory.
 *
 * Allocates @cap bytes and initializes the provided buffer struct with the
 * allocated memory.
 *
 * Return: Returns zero on success and %-ENOMEM if allocation failed.
 */
static inline int sshp_buf_alloc(struct sshp_buf *buf, size_t cap, gfp_t flags)
{
	u8 *ptr;

	ptr = kzalloc(cap, flags);
	if (!ptr)
		return -ENOMEM;

	sshp_buf_init(buf, ptr, cap);
	return 0;
}

/**
 * sshp_buf_free() - Free a SSH parser buffer.
 * @buf: The buffer to free.
 *
 * Frees a SSH parser buffer by freeing the memory backing it and then
 * resetting its pointer to %NULL and length and capacity to zero. Intended to
 * free a buffer previously allocated with sshp_buf_alloc().
 */
static inline void sshp_buf_free(struct sshp_buf *buf)
{
	kfree(buf->ptr);
	buf->ptr = NULL;
	buf->len = 0;
	buf->cap = 0;
}

/**
 * sshp_buf_drop() - Drop data from the beginning of the buffer.
 * @buf: The buffer to drop data from.
 * @n:   The number of bytes to drop.
 *
 * Drops the first @n bytes from the buffer. Re-aligns any remaining data to
 * the beginning of the buffer.
 */
static inline void sshp_buf_drop(struct sshp_buf *buf, size_t n)
{
	memmove(buf->ptr, buf->ptr + n, buf->len - n);
	buf->len -= n;
}

/**
 * sshp_buf_read_from_fifo() - Transfer data from a fifo to the buffer.
 * @buf:  The buffer to write the data into.
 * @fifo: The fifo to read the data from.
 *
 * Transfers the data contained in the fifo to the buffer, removing it from
 * the fifo. This function will try to transfer as much data as possible,
 * limited either by the remaining space in the buffer or by the number of
 * bytes available in the fifo.
 *
 * Return: Returns the number of bytes transferred.
 */
static inline size_t sshp_buf_read_from_fifo(struct sshp_buf *buf,
					     struct kfifo *fifo)
{
	size_t n;

	n =  kfifo_out(fifo, buf->ptr + buf->len, buf->cap - buf->len);
	buf->len += n;

	return n;
}

/**
 * sshp_buf_span_from() - Initialize a span from the given buffer and offset.
 * @buf:    The buffer to create the span from.
 * @offset: The offset in the buffer at which the span should start.
 * @span:   The span to initialize (output).
 *
 * Initializes the provided span to point to the memory at the given offset in
 * the buffer, with the length of the span being capped by the number of bytes
 * used in the buffer after the offset (i.e. bytes remaining after the
 * offset).
 *
 * Warning: This function does not validate that @offset is less than or equal
 * to the number of bytes used in the buffer or the buffer capacity. This must
 * be guaranteed by the caller.
 */
static inline void sshp_buf_span_from(struct sshp_buf *buf, size_t offset,
				      struct ssam_span *span)
{
	span->ptr = buf->ptr + offset;
	span->len = buf->len - offset;
}

bool sshp_find_syn(const struct ssam_span *src, struct ssam_span *rem);

int sshp_parse_frame(const struct device *dev, const struct ssam_span *source,
		     struct ssh_frame **frame, struct ssam_span *payload,
		     size_t maxlen);

int sshp_parse_command(const struct device *dev, const struct ssam_span *source,
		       struct ssh_command **command,
		       struct ssam_span *command_data);

#endif /* _SURFACE_AGGREGATOR_SSH_PARSER_h */