Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/* SPDX-License-Identifier: GPL-2.0+ */
  2/*
  3 * SSH message builder functions.
  4 *
  5 * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  6 */
  7
  8#ifndef _SURFACE_AGGREGATOR_SSH_MSGB_H
  9#define _SURFACE_AGGREGATOR_SSH_MSGB_H
 10
 11#include <linux/unaligned.h>
 12#include <linux/types.h>
 13
 14#include <linux/surface_aggregator/controller.h>
 15#include <linux/surface_aggregator/serial_hub.h>
 16
 17/**
 18 * struct msgbuf - Buffer struct to construct SSH messages.
 19 * @begin: Pointer to the beginning of the allocated buffer space.
 20 * @end:   Pointer to the end (one past last element) of the allocated buffer
 21 *         space.
 22 * @ptr:   Pointer to the first free element in the buffer.
 23 */
 24struct msgbuf {
 25	u8 *begin;
 26	u8 *end;
 27	u8 *ptr;
 28};
 29
 30/**
 31 * msgb_init() - Initialize the given message buffer struct.
 32 * @msgb: The buffer struct to initialize
 33 * @ptr:  Pointer to the underlying memory by which the buffer will be backed.
 34 * @cap:  Size of the underlying memory.
 35 *
 36 * Initialize the given message buffer struct using the provided memory as
 37 * backing.
 38 */
 39static inline void msgb_init(struct msgbuf *msgb, u8 *ptr, size_t cap)
 40{
 41	msgb->begin = ptr;
 42	msgb->end = ptr + cap;
 43	msgb->ptr = ptr;
 44}
 45
 46/**
 47 * msgb_bytes_used() - Return the current number of bytes used in the buffer.
 48 * @msgb: The message buffer.
 49 */
 50static inline size_t msgb_bytes_used(const struct msgbuf *msgb)
 51{
 52	return msgb->ptr - msgb->begin;
 53}
 54
 55static inline void __msgb_push_u8(struct msgbuf *msgb, u8 value)
 56{
 57	*msgb->ptr = value;
 58	msgb->ptr += sizeof(u8);
 59}
 60
 61static inline void __msgb_push_u16(struct msgbuf *msgb, u16 value)
 62{
 63	put_unaligned_le16(value, msgb->ptr);
 64	msgb->ptr += sizeof(u16);
 65}
 66
 67/**
 68 * msgb_push_u16() - Push a u16 value to the buffer.
 69 * @msgb:  The message buffer.
 70 * @value: The value to push to the buffer.
 71 */
 72static inline void msgb_push_u16(struct msgbuf *msgb, u16 value)
 73{
 74	if (WARN_ON(msgb->ptr + sizeof(u16) > msgb->end))
 75		return;
 76
 77	__msgb_push_u16(msgb, value);
 78}
 79
 80/**
 81 * msgb_push_syn() - Push SSH SYN bytes to the buffer.
 82 * @msgb: The message buffer.
 83 */
 84static inline void msgb_push_syn(struct msgbuf *msgb)
 85{
 86	msgb_push_u16(msgb, SSH_MSG_SYN);
 87}
 88
 89/**
 90 * msgb_push_buf() - Push raw data to the buffer.
 91 * @msgb: The message buffer.
 92 * @buf:  The data to push to the buffer.
 93 * @len:  The length of the data to push to the buffer.
 94 */
 95static inline void msgb_push_buf(struct msgbuf *msgb, const u8 *buf, size_t len)
 96{
 97	msgb->ptr = memcpy(msgb->ptr, buf, len) + len;
 98}
 99
100/**
101 * msgb_push_crc() - Compute CRC and push it to the buffer.
102 * @msgb: The message buffer.
103 * @buf:  The data for which the CRC should be computed.
104 * @len:  The length of the data for which the CRC should be computed.
105 */
106static inline void msgb_push_crc(struct msgbuf *msgb, const u8 *buf, size_t len)
107{
108	msgb_push_u16(msgb, ssh_crc(buf, len));
109}
110
111/**
112 * msgb_push_frame() - Push a SSH message frame header to the buffer.
113 * @msgb: The message buffer
114 * @ty:   The type of the frame.
115 * @len:  The length of the payload of the frame.
116 * @seq:  The sequence ID of the frame/packet.
117 */
118static inline void msgb_push_frame(struct msgbuf *msgb, u8 ty, u16 len, u8 seq)
119{
120	u8 *const begin = msgb->ptr;
121
122	if (WARN_ON(msgb->ptr + sizeof(struct ssh_frame) > msgb->end))
123		return;
124
125	__msgb_push_u8(msgb, ty);	/* Frame type. */
126	__msgb_push_u16(msgb, len);	/* Frame payload length. */
127	__msgb_push_u8(msgb, seq);	/* Frame sequence ID. */
128
129	msgb_push_crc(msgb, begin, msgb->ptr - begin);
130}
131
132/**
133 * msgb_push_ack() - Push a SSH ACK frame to the buffer.
134 * @msgb: The message buffer
135 * @seq:  The sequence ID of the frame/packet to be ACKed.
136 */
137static inline void msgb_push_ack(struct msgbuf *msgb, u8 seq)
138{
139	/* SYN. */
140	msgb_push_syn(msgb);
141
142	/* ACK-type frame + CRC. */
143	msgb_push_frame(msgb, SSH_FRAME_TYPE_ACK, 0x00, seq);
144
145	/* Payload CRC (ACK-type frames do not have a payload). */
146	msgb_push_crc(msgb, msgb->ptr, 0);
147}
148
149/**
150 * msgb_push_nak() - Push a SSH NAK frame to the buffer.
151 * @msgb: The message buffer
152 */
153static inline void msgb_push_nak(struct msgbuf *msgb)
154{
155	/* SYN. */
156	msgb_push_syn(msgb);
157
158	/* NAK-type frame + CRC. */
159	msgb_push_frame(msgb, SSH_FRAME_TYPE_NAK, 0x00, 0x00);
160
161	/* Payload CRC (ACK-type frames do not have a payload). */
162	msgb_push_crc(msgb, msgb->ptr, 0);
163}
164
165/**
166 * msgb_push_cmd() - Push a SSH command frame with payload to the buffer.
167 * @msgb: The message buffer.
168 * @seq:  The sequence ID (SEQ) of the frame/packet.
169 * @rqid: The request ID (RQID) of the request contained in the frame.
170 * @rqst: The request to wrap in the frame.
171 */
172static inline void msgb_push_cmd(struct msgbuf *msgb, u8 seq, u16 rqid,
173				 const struct ssam_request *rqst)
174{
175	const u8 type = SSH_FRAME_TYPE_DATA_SEQ;
176	u8 *cmd;
177
178	/* SYN. */
179	msgb_push_syn(msgb);
180
181	/* Command frame + CRC. */
182	msgb_push_frame(msgb, type, sizeof(struct ssh_command) + rqst->length, seq);
183
184	/* Frame payload: Command struct + payload. */
185	if (WARN_ON(msgb->ptr + sizeof(struct ssh_command) > msgb->end))
186		return;
187
188	cmd = msgb->ptr;
189
190	__msgb_push_u8(msgb, SSH_PLD_TYPE_CMD);		/* Payload type. */
191	__msgb_push_u8(msgb, rqst->target_category);	/* Target category. */
192	__msgb_push_u8(msgb, rqst->target_id);		/* Target ID. */
193	__msgb_push_u8(msgb, SSAM_SSH_TID_HOST);	/* Source ID. */
194	__msgb_push_u8(msgb, rqst->instance_id);	/* Instance ID. */
195	__msgb_push_u16(msgb, rqid);			/* Request ID. */
196	__msgb_push_u8(msgb, rqst->command_id);		/* Command ID. */
197
198	/* Command payload. */
199	msgb_push_buf(msgb, rqst->payload, rqst->length);
200
201	/* CRC for command struct + payload. */
202	msgb_push_crc(msgb, cmd, msgb->ptr - cmd);
203}
204
205#endif /* _SURFACE_AGGREGATOR_SSH_MSGB_H */