ssh_msgb.h 5.5 KB

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