Line data Source code
1 0 : /*
2 : * Copyright (c) 2024 NXP
3 : * Copyright (c) 2025 Croxel Inc.
4 : * Copyright (c) 2025 CogniPilot Foundation
5 : *
6 : * SPDX-License-Identifier: Apache-2.0
7 : */
8 :
9 : #include <zephyr/kernel.h>
10 : #include <zephyr/types.h>
11 : #include <zephyr/sys/atomic.h>
12 :
13 : #include <zephyr/modem/pipe.h>
14 : #include <zephyr/modem/ubx/protocol.h>
15 :
16 : #ifndef ZEPHYR_MODEM_UBX_
17 0 : #define ZEPHYR_MODEM_UBX_
18 :
19 : #ifdef __cplusplus
20 : extern "C" {
21 : #endif
22 :
23 : /**
24 : * @brief Modem Ubx
25 : * @defgroup modem_ubx Modem Ubx
26 : * @since 3.7
27 : * @version 1.0.0
28 : * @ingroup modem
29 : * @{
30 : */
31 :
32 : struct modem_ubx;
33 :
34 0 : typedef void (*modem_ubx_match_callback)(struct modem_ubx *ubx,
35 : const struct ubx_frame *frame,
36 : size_t len,
37 : void *user_data);
38 :
39 0 : struct modem_ubx_match {
40 0 : struct ubx_frame_match filter;
41 0 : modem_ubx_match_callback handler;
42 : };
43 :
44 0 : #define MODEM_UBX_MATCH_ARRAY_DEFINE(_name, ...) \
45 : struct modem_ubx_match _name[] = {__VA_ARGS__};
46 :
47 0 : #define MODEM_UBX_MATCH_DEFINE(_class_id, _msg_id, _handler) \
48 : { \
49 : .filter = { \
50 : .class = _class_id, \
51 : .id = _msg_id, \
52 : }, \
53 : .handler = _handler, \
54 : }
55 :
56 0 : struct modem_ubx_script {
57 : struct {
58 0 : const void *buf;
59 0 : uint16_t len;
60 0 : } request;
61 : struct {
62 0 : uint8_t *buf;
63 0 : uint16_t buf_len;
64 0 : uint16_t received_len;
65 0 : } response;
66 0 : struct modem_ubx_match match;
67 0 : uint16_t retry_count;
68 0 : k_timeout_t timeout;
69 : };
70 :
71 0 : struct modem_ubx {
72 0 : void *user_data;
73 0 : atomic_t attached;
74 0 : uint8_t *receive_buf;
75 0 : uint16_t receive_buf_size;
76 0 : uint16_t receive_buf_offset;
77 0 : struct modem_ubx_script *script;
78 0 : struct modem_pipe *pipe;
79 0 : struct k_work process_work;
80 0 : struct k_sem script_stopped_sem;
81 0 : struct k_sem script_running_sem;
82 : struct {
83 0 : const struct modem_ubx_match *array;
84 0 : size_t size;
85 0 : } unsol_matches;
86 : };
87 :
88 0 : struct modem_ubx_config {
89 0 : void *user_data;
90 0 : uint8_t *receive_buf;
91 0 : uint16_t receive_buf_size;
92 : struct {
93 0 : const struct modem_ubx_match *array;
94 0 : size_t size;
95 0 : } unsol_matches;
96 : };
97 :
98 : /**
99 : * @brief Attach pipe to Modem Ubx
100 : *
101 : * @param ubx Modem Ubx instance
102 : * @param pipe Pipe instance to attach Modem Ubx instance to
103 : * @returns 0 if successful
104 : * @returns negative errno code if failure
105 : * @note Modem Ubx instance is enabled if successful
106 : */
107 1 : int modem_ubx_attach(struct modem_ubx *ubx, struct modem_pipe *pipe);
108 :
109 : /**
110 : * @brief Release pipe from Modem Ubx instance
111 : *
112 : * @param ubx Modem Ubx instance
113 : */
114 1 : void modem_ubx_release(struct modem_ubx *ubx);
115 :
116 : /**
117 : * @brief Initialize Modem Ubx instance
118 : * @param ubx Modem Ubx instance
119 : * @param config Configuration which shall be applied to the Modem Ubx instance
120 : * @note Modem Ubx instance must be attached to a pipe instance
121 : */
122 1 : int modem_ubx_init(struct modem_ubx *ubx, const struct modem_ubx_config *config);
123 :
124 : /**
125 : * @brief Writes the ubx frame in script.request and reads back its response (if available)
126 : * @details For each ubx frame sent, the device responds in 0, 1 or both of the following ways:
127 : * 1. The device sends back a UBX-ACK frame to denote 'acknowledge' and 'not-acknowledge'.
128 : * Note: the message id of UBX-ACK frame determines whether the device acknowledged.
129 : * Ex: when we send a UBX-CFG frame, the device responds with a UBX-ACK frame.
130 : * 2. The device sends back the same frame that we sent to it, with it's payload populated.
131 : * It's used to get the current configuration corresponding to the frame that we sent.
132 : * Ex: frame types such as "get" or "poll" ubx frames respond this way.
133 : * This response (if received) is written to script.response.
134 : *
135 : * This function writes the ubx frame in script.request then reads back it's response.
136 : * If script.match is not NULL, then every ubx frame received from the device is compared with
137 : * script.match to check if a match occurred. This could be used to match UBX-ACK frame sent
138 : * from the device by populating script.match with UBX-ACK that the script expects to receive.
139 : *
140 : * The script terminates when either of the following happens:
141 : * 1. script.match is successfully received and matched.
142 : * 2. timeout (denoted by script.timeout) occurs.
143 : * @param ubx Modem Ubx instance
144 : * @param script Script to be executed
145 : * @note The length of ubx frame in the script.request should not exceed UBX_FRAME_SZ_MAX
146 : * @note Modem Ubx instance must be attached to a pipe instance
147 : * @returns 0 if successful
148 : * @returns negative errno code if failure
149 : */
150 1 : int modem_ubx_run_script(struct modem_ubx *ubx, struct modem_ubx_script *script);
151 :
152 0 : int modem_ubx_run_script_for_each(struct modem_ubx *ubx, struct modem_ubx_script *script,
153 : struct ubx_frame *array, size_t array_size);
154 :
155 : /**
156 : * @}
157 : */
158 :
159 : #ifdef __cplusplus
160 : }
161 : #endif
162 :
163 : #endif /* ZEPHYR_MODEM_UBX_ */
|