Line data Source code
1 0 : /*
2 : * Copyright (c) 2020 Google LLC
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : #ifndef ZEPHYR_INCLUDE_MGMT_EC_HOST_CMD_EC_HOST_CMD_H_
8 : #define ZEPHYR_INCLUDE_MGMT_EC_HOST_CMD_EC_HOST_CMD_H_
9 :
10 : /**
11 : * @brief EC Host Command Interface
12 : * @defgroup ec_host_cmd_interface EC Host Command Interface
13 : * @since 2.4
14 : * @version 0.1.0
15 : * @ingroup io_interfaces
16 : * @{
17 : */
18 :
19 : #include <stdint.h>
20 : #include <zephyr/kernel.h>
21 : #include <zephyr/mgmt/ec_host_cmd/backend.h>
22 : #include <zephyr/sys/__assert.h>
23 : #include <zephyr/sys/iterable_sections.h>
24 :
25 : /**
26 : * @brief Host command response codes (16-bit).
27 : */
28 0 : enum ec_host_cmd_status {
29 : /** Host command was successful. */
30 : EC_HOST_CMD_SUCCESS = 0,
31 : /** The specified command id is not recognized or supported. */
32 : EC_HOST_CMD_INVALID_COMMAND = 1,
33 : /** Generic Error. */
34 : EC_HOST_CMD_ERROR = 2,
35 : /** One of more of the input request parameters is invalid. */
36 : EC_HOST_CMD_INVALID_PARAM = 3,
37 : /** Host command is not permitted. */
38 : EC_HOST_CMD_ACCESS_DENIED = 4,
39 : /** Response was invalid (e.g. not version 3 of header). */
40 : EC_HOST_CMD_INVALID_RESPONSE = 5,
41 : /** Host command id version unsupported. */
42 : EC_HOST_CMD_INVALID_VERSION = 6,
43 : /** Checksum did not match. */
44 : EC_HOST_CMD_INVALID_CHECKSUM = 7,
45 : /** A host command is currently being processed. */
46 : EC_HOST_CMD_IN_PROGRESS = 8,
47 : /** Requested information is currently unavailable. */
48 : EC_HOST_CMD_UNAVAILABLE = 9,
49 : /** Timeout during processing. */
50 : EC_HOST_CMD_TIMEOUT = 10,
51 : /** Data or table overflow. */
52 : EC_HOST_CMD_OVERFLOW = 11,
53 : /** Header is invalid or unsupported (e.g. not version 3 of header). */
54 : EC_HOST_CMD_INVALID_HEADER = 12,
55 : /** Did not receive all expected request data. */
56 : EC_HOST_CMD_REQUEST_TRUNCATED = 13,
57 : /** Response was too big to send within one response packet. */
58 : EC_HOST_CMD_RESPONSE_TOO_BIG = 14,
59 : /** Error on underlying communication bus. */
60 : EC_HOST_CMD_BUS_ERROR = 15,
61 : /** System busy. Should retry later. */
62 : EC_HOST_CMD_BUSY = 16,
63 : /** Header version invalid. */
64 : EC_HOST_CMD_INVALID_HEADER_VERSION = 17,
65 : /** Header CRC invalid. */
66 : EC_HOST_CMD_INVALID_HEADER_CRC = 18,
67 : /** Data CRC invalid. */
68 : EC_HOST_CMD_INVALID_DATA_CRC = 19,
69 : /** Can't resend response. */
70 : EC_HOST_CMD_DUP_UNAVAILABLE = 20,
71 :
72 : EC_HOST_CMD_MAX = UINT16_MAX /* Force enum to be 16 bits. */
73 : } __packed;
74 :
75 0 : enum ec_host_cmd_log_level {
76 : EC_HOST_CMD_DEBUG_OFF, /* No Host Command debug output */
77 : EC_HOST_CMD_DEBUG_NORMAL, /* Normal output mode; skips repeated commands */
78 : EC_HOST_CMD_DEBUG_EVERY, /* Print every command */
79 : EC_HOST_CMD_DEBUG_PARAMS, /* ... and print params for request/response */
80 : EC_HOST_CMD_DEBUG_MODES /* Number of host command debug modes */
81 : };
82 :
83 0 : enum ec_host_cmd_state {
84 : EC_HOST_CMD_STATE_DISABLED = 0,
85 : EC_HOST_CMD_STATE_RECEIVING,
86 : EC_HOST_CMD_STATE_PROCESSING,
87 : EC_HOST_CMD_STATE_SENDING,
88 : };
89 :
90 0 : typedef void (*ec_host_cmd_user_cb_t)(const struct ec_host_cmd_rx_ctx *rx_ctx, void *user_data);
91 : typedef enum ec_host_cmd_status (*ec_host_cmd_in_progress_cb_t)(void *user_data);
92 :
93 0 : struct ec_host_cmd {
94 0 : struct ec_host_cmd_rx_ctx rx_ctx;
95 0 : struct ec_host_cmd_tx_buf tx;
96 0 : struct ec_host_cmd_backend *backend;
97 : /**
98 : * The backend gives rx_ready (by calling the ec_host_cmd_send_receive function),
99 : * when data in rx_ctx are ready. The handler takes rx_ready to read data in rx_ctx.
100 : */
101 1 : struct k_sem rx_ready;
102 : /** Status of the rx data checked in the ec_host_cmd_send_received function. */
103 1 : enum ec_host_cmd_status rx_status;
104 : /**
105 : * User callback after receiving a command. It is called by the ec_host_cmd_send_received
106 : * function.
107 : */
108 1 : ec_host_cmd_user_cb_t user_cb;
109 0 : void *user_data;
110 0 : enum ec_host_cmd_state state;
111 : #ifdef CONFIG_EC_HOST_CMD_DEDICATED_THREAD
112 : struct k_thread thread;
113 : #endif /* CONFIG_EC_HOST_CMD_DEDICATED_THREAD */
114 : };
115 :
116 : /**
117 : * @brief Arguments passed into every installed host command handler
118 : */
119 1 : struct ec_host_cmd_handler_args {
120 : /** Reserved for compatibility. */
121 1 : void *reserved;
122 : /** Command identifier. */
123 1 : uint16_t command;
124 : /**
125 : * The version of the host command that is being requested. This will
126 : * be a value that has been static registered as valid for the handler.
127 : */
128 1 : uint8_t version;
129 : /** The incoming data that can be cast to the handlers request type. */
130 1 : const void *input_buf;
131 : /** The number of valid bytes that can be read from @a input_buf. */
132 1 : uint16_t input_buf_size;
133 : /** The data written to this buffer will be send to the host. */
134 1 : void *output_buf;
135 : /** Maximum number of bytes that can be written to the @a output_buf. */
136 1 : uint16_t output_buf_max;
137 : /** Number of bytes of @a output_buf to send to the host. */
138 1 : uint16_t output_buf_size;
139 : };
140 :
141 : typedef enum ec_host_cmd_status (*ec_host_cmd_handler_cb)(struct ec_host_cmd_handler_args *args);
142 : /**
143 : * @brief Structure use for statically registering host command handlers
144 : */
145 1 : struct ec_host_cmd_handler {
146 : /** Callback routine to process commands that match @a id. */
147 1 : ec_host_cmd_handler_cb handler;
148 : /** The numerical command id used as the lookup for commands. */
149 1 : uint16_t id;
150 : /**
151 : * The bitfield of all versions that the @a handler supports, where
152 : * each bit value represents that the @a handler supports that version.
153 : * E.g. BIT(0) corresponds to version 0.
154 : */
155 1 : uint16_t version_mask;
156 : /**
157 : * The minimum @a input_buf_size enforced by the framework before
158 : * passing to the handler.
159 : */
160 1 : uint16_t min_rqt_size;
161 : /**
162 : * The minimum @a output_buf_size enforced by the framework before
163 : * passing to the handler.
164 : */
165 1 : uint16_t min_rsp_size;
166 : };
167 :
168 : /**
169 : * @brief Statically define and register a host command handler.
170 : *
171 : * Helper macro to statically define and register a host command handler that
172 : * has a compile-time-fixed sizes for its both request and response structures.
173 : *
174 : * @param _id Id of host command to handle request for.
175 : * @param _function Name of handler function.
176 : * @param _version_mask The bitfield of all versions that the @a _function
177 : * supports. E.g. BIT(0) corresponds to version 0.
178 : * @param _request_type The datatype of the request parameters for @a _function.
179 : * @param _response_type The datatype of the response parameters for
180 : * @a _function.
181 : */
182 1 : #define EC_HOST_CMD_HANDLER(_id, _function, _version_mask, _request_type, _response_type) \
183 : const STRUCT_SECTION_ITERABLE(ec_host_cmd_handler, __cmd##_id) = { \
184 : .handler = _function, \
185 : .id = _id, \
186 : .version_mask = _version_mask, \
187 : .min_rqt_size = sizeof(_request_type), \
188 : .min_rsp_size = sizeof(_response_type), \
189 : }
190 :
191 : /**
192 : * @brief Statically define and register a host command handler without sizes.
193 : *
194 : * Helper macro to statically define and register a host command handler whose
195 : * request or response structure size is not known as compile time.
196 : *
197 : * @param _id Id of host command to handle request for.
198 : * @param _function Name of handler function.
199 : * @param _version_mask The bitfield of all versions that the @a _function
200 : * supports. E.g. BIT(0) corresponds to version 0.
201 : */
202 1 : #define EC_HOST_CMD_HANDLER_UNBOUND(_id, _function, _version_mask) \
203 : const STRUCT_SECTION_ITERABLE(ec_host_cmd_handler, __cmd##_id) = { \
204 : .handler = _function, \
205 : .id = _id, \
206 : .version_mask = _version_mask, \
207 : .min_rqt_size = 0, \
208 : .min_rsp_size = 0, \
209 : }
210 :
211 : /**
212 : * @brief Header for requests from host to embedded controller
213 : *
214 : * Represent the over-the-wire header in LE format for host command requests.
215 : * This represent version 3 of the host command header. The requests are always
216 : * sent from host to embedded controller.
217 : */
218 1 : struct ec_host_cmd_request_header {
219 : /**
220 : * Should be 3. The EC will return EC_HOST_CMD_INVALID_HEADER if it
221 : * receives a header with a version it doesn't know how to parse.
222 : */
223 1 : uint8_t prtcl_ver;
224 : /**
225 : * Checksum of response and data; sum of all bytes including checksum.
226 : * Should total to 0.
227 : */
228 1 : uint8_t checksum;
229 : /** Id of command that is being sent. */
230 1 : uint16_t cmd_id;
231 : /**
232 : * Version of the specific @a cmd_id being requested. Valid
233 : * versions start at 0.
234 : */
235 1 : uint8_t cmd_ver;
236 : /** Unused byte in current protocol version; set to 0. */
237 1 : uint8_t reserved;
238 : /** Length of data which follows this header. */
239 1 : uint16_t data_len;
240 : } __packed;
241 :
242 : /**
243 : * @brief Header for responses from embedded controller to host
244 : *
245 : * Represent the over-the-wire header in LE format for host command responses.
246 : * This represent version 3 of the host command header. Responses are always
247 : * sent from embedded controller to host.
248 : */
249 1 : struct ec_host_cmd_response_header {
250 : /** Should be 3. */
251 1 : uint8_t prtcl_ver;
252 : /**
253 : * Checksum of response and data; sum of all bytes including checksum.
254 : * Should total to 0.
255 : */
256 1 : uint8_t checksum;
257 : /** A @a ec_host_cmd_status response code for specific command. */
258 1 : uint16_t result;
259 : /** Length of data which follows this header. */
260 1 : uint16_t data_len;
261 : /** Unused bytes in current protocol version; set to 0. */
262 1 : uint16_t reserved;
263 : } __packed;
264 :
265 : /**
266 : * @brief Initialize the host command subsystem
267 : *
268 : * This routine initializes the host command subsystem. It includes initialization
269 : * of a backend and the handler.
270 : * When the application configures the zephyr,host-cmd-espi-backend/zephyr,host-cmd-shi-backend/
271 : * zephyr,host-cmd-uart-backend chosen node and @kconfig{CONFIG_EC_HOST_CMD_INITIALIZE_AT_BOOT} is
272 : * set, the chosen backend automatically calls this routine at
273 : * @kconfig{CONFIG_EC_HOST_CMD_INIT_PRIORITY}. Applications that require a run-time selection of the
274 : * backend must set @kconfig{CONFIG_EC_HOST_CMD_INITIALIZE_AT_BOOT} to n and must explicitly call
275 : * this routine.
276 : *
277 : * @param[in] backend Pointer to the backend structure to initialize.
278 : *
279 : * @retval 0 if successful
280 : */
281 1 : int ec_host_cmd_init(struct ec_host_cmd_backend *backend);
282 :
283 : /**
284 : * @brief Send the host command response
285 : *
286 : * This routine sends the host command response. It should be used to send IN_PROGRESS status or
287 : * if the host command handler doesn't return e.g. reboot command.
288 : *
289 : * @param[in] status Host command status to be sent.
290 : * @param[in] args Pointer of a structure passed to the handler.
291 : *
292 : * @retval 0 if successful.
293 : */
294 1 : int ec_host_cmd_send_response(enum ec_host_cmd_status status,
295 : const struct ec_host_cmd_handler_args *args);
296 :
297 : /**
298 : * @brief Signal a new host command
299 : *
300 : * Signal that a new host command has been received. The function should be called by a backend
301 : * after copying data to the rx buffer and setting the length.
302 : */
303 1 : void ec_host_cmd_rx_notify(void);
304 :
305 : /**
306 : * @brief Install a user callback for receiving a host command
307 : *
308 : * It allows installing a custom procedure needed by a user after receiving a command.
309 : *
310 : * @param[in] cb A callback to be installed.
311 : * @param[in] user_data User data to be passed to the callback.
312 : */
313 1 : void ec_host_cmd_set_user_cb(ec_host_cmd_user_cb_t cb, void *user_data);
314 :
315 : /**
316 : * @brief Get the main ec host command structure
317 : *
318 : * This routine returns a pointer to the main host command structure.
319 : * It allows the application code to get inside information for any reason e.g.
320 : * the host command thread id.
321 : *
322 : * @retval A pointer to the main host command structure
323 : */
324 1 : const struct ec_host_cmd *ec_host_cmd_get_hc(void);
325 :
326 : #ifndef CONFIG_EC_HOST_CMD_DEDICATED_THREAD
327 : /**
328 : * @brief The thread function for Host Command subsystem
329 : *
330 : * This routine calls the Host Command thread entry function. If
331 : * @kconfig{CONFIG_EC_HOST_CMD_DEDICATED_THREAD} is not defined, a new thread is not created,
332 : * and this function has to be called by application code. It doesn't return.
333 : */
334 1 : FUNC_NORETURN void ec_host_cmd_task(void);
335 : #endif
336 :
337 : #ifdef CONFIG_EC_HOST_CMD_IN_PROGRESS_STATUS
338 : /**
339 : * @brief Check if a Host Command that sent EC_HOST_CMD_IN_PROGRESS status has ended.
340 : *
341 : * A Host Command that sends EC_HOST_CMD_IN_PROGRESS status doesn't send a final result.
342 : * The final result can be get with the ec_host_cmd_send_in_progress_status function.
343 : *
344 : * @retval true if the Host Command endded
345 : */
346 : bool ec_host_cmd_send_in_progress_ended(void);
347 :
348 : /**
349 : * @brief Get final result of a last Host Command that has sent EC_HOST_CMD_IN_PROGRESS status.
350 : *
351 : * A Host Command that sends EC_HOST_CMD_IN_PROGRESS status doesn't send a final result.
352 : * Get the saved status with this function. The status can be get only once. Further calls return
353 : * EC_HOST_CMD_UNAVAILABLE.
354 : *
355 : * Saving status of Host Commands that send response data is not supported.
356 : *
357 : * @retval The final status or EC_HOST_CMD_UNAVAILABLE if not available.
358 : */
359 : enum ec_host_cmd_status ec_host_cmd_send_in_progress_status(void);
360 :
361 : /**
362 : * @brief Continue processing a handler in callback after returning EC_HOST_CMD_IN_PROGRESS.
363 : *
364 : * A Host Command handler may return the EC_HOST_CMD_IN_PROGRESS, but needs to continue work.
365 : * This function should be called before returning EC_HOST_CMD_IN_PROGRESS with a callback that
366 : * will be executed. The return status of the callback will be stored and can be get with the
367 : * ec_host_cmd_send_in_progress_status function. The ec_host_cmd_send_in_progress_ended function
368 : * can be used to check if the callback has ended.
369 : *
370 : * @param[in] cb A callback to be called after returning from a command handler.
371 : * @param[in] user_data User data to be passed to the callback.
372 : *
373 : * @retval EC_HOST_CMD_BUSY if any command is already in progress, EC_HOST_CMD_SUCCESS otherwise
374 : */
375 : enum ec_host_cmd_status ec_host_cmd_send_in_progress_continue(ec_host_cmd_in_progress_cb_t cb,
376 : void *user_data);
377 : #endif /* CONFIG_EC_HOST_CMD_IN_PROGRESS_STATUS */
378 :
379 : /**
380 : * @brief Add a suppressed command.
381 : *
382 : * Suppressed commands are not logged. Add a command to be suppressed.
383 : *
384 : * @param[in] cmd_id A command id to be suppressed.
385 : *
386 : * @retval 0 if successful, -EIO if exceeded max number of suppressed commands.
387 : */
388 1 : int ec_host_cmd_add_suppressed(uint16_t cmd_id);
389 :
390 : /**
391 : * @}
392 : */
393 :
394 : #endif /* ZEPHYR_INCLUDE_MGMT_EC_HOST_CMD_EC_HOST_CMD_H_ */
|