Zephyr API Documentation 4.2.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
cmux.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Trackunit Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7/*
8 * This library uses CMUX to create multiple data channels, called DLCIs, on a single serial bus.
9 * Each DLCI has an address from 1 to 63. DLCI address 0 is reserved for control commands.
10 *
11 * Design overview:
12 *
13 * DLCI1 <-----------+ +-------> DLCI1
14 * v v
15 * DLCI2 <---> CMUX instance <--> Serial bus <--> Client <--> DLCI2
16 * ^ ^
17 * DLCI3 <-----------+ +-------> DLCI3
18 *
19 * Writing to and from the CMUX instances is done using the modem_pipe API.
20 */
21
22#include <zephyr/kernel.h>
23#include <zephyr/types.h>
25#include <zephyr/sys/atomic.h>
26
27#include <zephyr/modem/pipe.h>
28#include <zephyr/modem/stats.h>
29
30#ifndef ZEPHYR_MODEM_CMUX_
31#define ZEPHYR_MODEM_CMUX_
32
33#ifdef __cplusplus
34extern "C" {
35#endif
36
45
46struct modem_cmux;
47
52
53typedef void (*modem_cmux_callback)(struct modem_cmux *cmux, enum modem_cmux_event event,
54 void *user_data);
55
59
60#if CONFIG_MODEM_CMUX_MTU > 127
61#define MODEM_CMUX_HEADER_SIZE 7
62#else
63#define MODEM_CMUX_HEADER_SIZE 6
64#endif
65
66
67/* Total size of the CMUX work buffers */
68#define MODEM_CMUX_WORK_BUFFER_SIZE (CONFIG_MODEM_CMUX_MTU + MODEM_CMUX_HEADER_SIZE + \
69 CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE_EXTRA)
70
71enum modem_cmux_state {
72 MODEM_CMUX_STATE_DISCONNECTED = 0,
73 MODEM_CMUX_STATE_CONNECTING,
74 MODEM_CMUX_STATE_CONNECTED,
75 MODEM_CMUX_STATE_DISCONNECTING,
76};
77
78enum modem_cmux_receive_state {
79 MODEM_CMUX_RECEIVE_STATE_SOF = 0,
80 MODEM_CMUX_RECEIVE_STATE_RESYNC,
81 MODEM_CMUX_RECEIVE_STATE_ADDRESS,
82 MODEM_CMUX_RECEIVE_STATE_ADDRESS_CONT,
83 MODEM_CMUX_RECEIVE_STATE_CONTROL,
84 MODEM_CMUX_RECEIVE_STATE_LENGTH,
85 MODEM_CMUX_RECEIVE_STATE_LENGTH_CONT,
86 MODEM_CMUX_RECEIVE_STATE_DATA,
87 MODEM_CMUX_RECEIVE_STATE_FCS,
88 MODEM_CMUX_RECEIVE_STATE_EOF,
89};
90
91enum modem_cmux_dlci_state {
92 MODEM_CMUX_DLCI_STATE_CLOSED,
93 MODEM_CMUX_DLCI_STATE_OPENING,
94 MODEM_CMUX_DLCI_STATE_OPEN,
95 MODEM_CMUX_DLCI_STATE_CLOSING,
96};
97
98struct modem_cmux_dlci {
99 sys_snode_t node;
100
101 /* Pipe */
102 struct modem_pipe pipe;
103
104 /* Context */
105 uint16_t dlci_address;
106 struct modem_cmux *cmux;
107
108 /* Receive buffer */
109 struct ring_buf receive_rb;
110 struct k_mutex receive_rb_lock;
111
112 /* Work */
113 struct k_work_delayable open_work;
114 struct k_work_delayable close_work;
115
116 /* State */
117 enum modem_cmux_dlci_state state;
118
119 /* Statistics */
120#if CONFIG_MODEM_STATS
121 struct modem_stats_buffer receive_buf_stats;
122#endif
123 /* Flow control */
124 bool flow_control : 1;
125 bool rx_full : 1;
126 bool msc_sent : 1;
127};
128
129struct modem_cmux_frame {
130 uint8_t dlci_address;
131 bool cr;
132 bool pf;
133 uint8_t type;
134 const uint8_t *data;
135 uint16_t data_len;
136};
137
138struct modem_cmux_work {
139 struct k_work_delayable dwork;
140 struct modem_cmux *cmux;
141};
142
143struct modem_cmux {
144 /* Bus pipe */
145 struct modem_pipe *pipe;
146
147 /* Event handler */
148 modem_cmux_callback callback;
149 void *user_data;
150
151 /* DLCI channel contexts */
152 sys_slist_t dlcis;
153
154 /* State */
155 enum modem_cmux_state state;
156 bool flow_control_on : 1;
157 bool initiator : 1;
158
159 /* Work lock */
160 bool attached : 1;
161 struct k_spinlock work_lock;
162
163 /* Receive state*/
164 enum modem_cmux_receive_state receive_state;
165
166 /* Receive buffer */
167 uint8_t *receive_buf;
168 uint16_t receive_buf_size;
169 uint16_t receive_buf_len;
170
171 uint8_t work_buf[MODEM_CMUX_WORK_BUFFER_SIZE];
172
173 /* Transmit buffer */
174 struct ring_buf transmit_rb;
175 struct k_mutex transmit_rb_lock;
176
177 /* Received frame */
178 struct modem_cmux_frame frame;
179 uint8_t frame_header[5];
180 uint16_t frame_header_len;
181
182 /* Work */
183 struct k_work_delayable receive_work;
184 struct k_work_delayable transmit_work;
185 struct k_work_delayable connect_work;
186 struct k_work_delayable disconnect_work;
187
188 /* Synchronize actions */
189 struct k_event event;
190
191 /* Statistics */
192#if CONFIG_MODEM_STATS
193 struct modem_stats_buffer receive_buf_stats;
194 struct modem_stats_buffer transmit_buf_stats;
195#endif
196};
197
201
219
225void modem_cmux_init(struct modem_cmux *cmux, const struct modem_cmux_config *config);
226
238
246struct modem_pipe *modem_cmux_dlci_init(struct modem_cmux *cmux, struct modem_cmux_dlci *dlci,
247 const struct modem_cmux_dlci_config *config);
248
255int modem_cmux_attach(struct modem_cmux *cmux, struct modem_pipe *pipe);
256
267int modem_cmux_connect(struct modem_cmux *cmux);
268
279int modem_cmux_connect_async(struct modem_cmux *cmux);
280
291int modem_cmux_disconnect(struct modem_cmux *cmux);
292
303int modem_cmux_disconnect_async(struct modem_cmux *cmux);
304
315void modem_cmux_release(struct modem_cmux *cmux);
316
320
321#ifdef __cplusplus
322}
323#endif
324
325#endif /* ZEPHYR_MODEM_CMUX_ */
int modem_cmux_connect(struct modem_cmux *cmux)
Connect CMUX instance.
int modem_cmux_disconnect(struct modem_cmux *cmux)
Close down and disconnect CMUX instance.
int modem_cmux_disconnect_async(struct modem_cmux *cmux)
Close down and disconnect CMUX instance asynchronously.
void(* modem_cmux_callback)(struct modem_cmux *cmux, enum modem_cmux_event event, void *user_data)
Definition cmux.h:53
int modem_cmux_connect_async(struct modem_cmux *cmux)
Connect CMUX instance asynchronously.
modem_cmux_event
Definition cmux.h:48
int modem_cmux_attach(struct modem_cmux *cmux, struct modem_pipe *pipe)
Attach CMUX instance to pipe.
struct modem_pipe * modem_cmux_dlci_init(struct modem_cmux *cmux, struct modem_cmux_dlci *dlci, const struct modem_cmux_dlci_config *config)
Initialize DLCI instance and register it with CMUX instance.
void modem_cmux_init(struct modem_cmux *cmux, const struct modem_cmux_config *config)
Initialize CMUX instance.
void modem_cmux_release(struct modem_cmux *cmux)
Release CMUX instance from pipe.
@ MODEM_CMUX_EVENT_DISCONNECTED
Definition cmux.h:50
@ MODEM_CMUX_EVENT_CONNECTED
Definition cmux.h:49
struct _slist sys_slist_t
Single-linked list structure.
Definition slist.h:49
struct _snode sys_snode_t
Single-linked list node structure.
Definition slist.h:39
Public kernel APIs.
state
Definition parser_state.h:29
__UINT8_TYPE__ uint8_t
Definition stdint.h:88
__UINT16_TYPE__ uint16_t
Definition stdint.h:89
Contains CMUX instance configuration data.
Definition cmux.h:205
uint8_t * receive_buf
Receive buffer.
Definition cmux.h:211
modem_cmux_callback callback
Invoked when event occurs.
Definition cmux.h:207
uint16_t receive_buf_size
Size of receive buffer in bytes [127, ...].
Definition cmux.h:213
void * user_data
Free to use pointer passed to event handler when invoked.
Definition cmux.h:209
uint8_t * transmit_buf
Transmit buffer.
Definition cmux.h:215
uint16_t transmit_buf_size
Size of transmit buffer in bytes [149, ...].
Definition cmux.h:217
CMUX DLCI configuration.
Definition cmux.h:230
uint8_t dlci_address
DLCI channel address.
Definition cmux.h:232
uint8_t * receive_buf
Receive buffer used by pipe.
Definition cmux.h:234
uint16_t receive_buf_size
Size of receive buffer used by pipe [127, ...].
Definition cmux.h:236