1 /* 2 * Copyright (c) 2022 Trackunit Corporation 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include <zephyr/kernel.h> 8 #include <zephyr/types.h> 9 #include <zephyr/net/net_if.h> 10 #include <zephyr/net/net_pkt.h> 11 #include <zephyr/sys/ring_buffer.h> 12 #include <zephyr/sys/atomic.h> 13 14 #include <zephyr/modem/pipe.h> 15 #include <zephyr/modem/stats.h> 16 17 #ifndef ZEPHYR_MODEM_PPP_ 18 #define ZEPHYR_MODEM_PPP_ 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /** 25 * @brief Modem PPP 26 * @defgroup modem_ppp Modem PPP 27 * @ingroup modem 28 * @{ 29 */ 30 31 /** L2 network interface init callback */ 32 typedef void (*modem_ppp_init_iface)(struct net_if *iface); 33 34 /** 35 * @cond INTERNAL_HIDDEN 36 */ 37 38 enum modem_ppp_receive_state { 39 /* Searching for start of frame and header */ 40 MODEM_PPP_RECEIVE_STATE_HDR_SOF = 0, 41 MODEM_PPP_RECEIVE_STATE_HDR_FF, 42 MODEM_PPP_RECEIVE_STATE_HDR_7D, 43 MODEM_PPP_RECEIVE_STATE_HDR_23, 44 /* Writing bytes to network packet */ 45 MODEM_PPP_RECEIVE_STATE_WRITING, 46 /* Unescaping next byte before writing to network packet */ 47 MODEM_PPP_RECEIVE_STATE_UNESCAPING, 48 }; 49 50 enum modem_ppp_transmit_state { 51 /* Idle */ 52 MODEM_PPP_TRANSMIT_STATE_IDLE = 0, 53 /* Writing header */ 54 MODEM_PPP_TRANSMIT_STATE_SOF, 55 MODEM_PPP_TRANSMIT_STATE_HDR_FF, 56 MODEM_PPP_TRANSMIT_STATE_HDR_7D, 57 MODEM_PPP_TRANSMIT_STATE_HDR_23, 58 /* Writing protocol */ 59 MODEM_PPP_TRANSMIT_STATE_PROTOCOL_HIGH, 60 MODEM_PPP_TRANSMIT_STATE_ESCAPING_PROTOCOL_HIGH, 61 MODEM_PPP_TRANSMIT_STATE_PROTOCOL_LOW, 62 MODEM_PPP_TRANSMIT_STATE_ESCAPING_PROTOCOL_LOW, 63 /* Writing data */ 64 MODEM_PPP_TRANSMIT_STATE_DATA, 65 MODEM_PPP_TRANSMIT_STATE_ESCAPING_DATA, 66 /* Writing FCS */ 67 MODEM_PPP_TRANSMIT_STATE_FCS_LOW, 68 MODEM_PPP_TRANSMIT_STATE_ESCAPING_FCS_LOW, 69 MODEM_PPP_TRANSMIT_STATE_FCS_HIGH, 70 MODEM_PPP_TRANSMIT_STATE_ESCAPING_FCS_HIGH, 71 /* Writing end of frame */ 72 MODEM_PPP_TRANSMIT_STATE_EOF, 73 }; 74 75 struct modem_ppp { 76 /* Network interface instance is bound to */ 77 struct net_if *iface; 78 79 /* Hook for PPP L2 network interface initialization */ 80 modem_ppp_init_iface init_iface; 81 82 atomic_t state; 83 84 /* Buffers used for processing partial frames */ 85 uint8_t *receive_buf; 86 uint8_t *transmit_buf; 87 uint16_t buf_size; 88 89 /* Wrapped PPP frames are sent and received through this pipe */ 90 struct modem_pipe *pipe; 91 92 /* Receive PPP frame state */ 93 enum modem_ppp_receive_state receive_state; 94 95 /* Allocated network packet being created */ 96 struct net_pkt *rx_pkt; 97 98 /* Packet being sent */ 99 enum modem_ppp_transmit_state transmit_state; 100 struct net_pkt *tx_pkt; 101 uint8_t tx_pkt_escaped; 102 uint16_t tx_pkt_protocol; 103 uint16_t tx_pkt_fcs; 104 105 /* Ring buffer used for transmitting partial PPP frame */ 106 struct ring_buf transmit_rb; 107 108 struct k_fifo tx_pkt_fifo; 109 110 /* Work */ 111 struct k_work send_work; 112 struct k_work process_work; 113 114 #if defined(CONFIG_NET_STATISTICS_PPP) 115 struct net_stats_ppp stats; 116 #endif 117 118 #if CONFIG_MODEM_STATS 119 struct modem_stats_buffer receive_buf_stats; 120 struct modem_stats_buffer transmit_buf_stats; 121 #endif 122 }; 123 124 /** 125 * @endcond 126 */ 127 128 /** 129 * @brief Attach pipe to instance and connect 130 * 131 * @param ppp Modem PPP instance 132 * @param pipe Pipe to attach to modem PPP instance 133 */ 134 int modem_ppp_attach(struct modem_ppp *ppp, struct modem_pipe *pipe); 135 136 /** 137 * @brief Get network interface modem PPP instance is bound to 138 * 139 * @param ppp Modem PPP instance 140 * @returns Pointer to network interface modem PPP instance is bound to 141 */ 142 struct net_if *modem_ppp_get_iface(struct modem_ppp *ppp); 143 144 /** 145 * @brief Release pipe from instance 146 * 147 * @param ppp Modem PPP instance 148 */ 149 void modem_ppp_release(struct modem_ppp *ppp); 150 151 /** 152 * @cond INTERNAL_HIDDEN 153 */ 154 155 /** 156 * @brief Initialize modem PPP instance device 157 * @param dev Device instance associated with network interface 158 * @warning Should not be used directly 159 */ 160 int modem_ppp_init_internal(const struct device *dev); 161 162 /** 163 * @endcond 164 */ 165 166 /** 167 * @brief Define a modem PPP module and bind it to a network interface 168 * 169 * @details This macro defines the modem_ppp instance, initializes a PPP L2 170 * network device instance, and binds the modem_ppp instance to the PPP L2 171 * instance. 172 * 173 * @param _name Name of the statically defined modem_ppp instance 174 * @param _init_iface Hook for the PPP L2 network interface init function 175 * @param _prio Initialization priority of the PPP L2 net iface 176 * @param _mtu Max size of net_pkt data sent and received on PPP L2 net iface 177 * @param _buf_size Size of partial PPP frame transmit and receive buffers 178 */ 179 #define MODEM_PPP_DEFINE(_name, _init_iface, _prio, _mtu, _buf_size) \ 180 extern const struct ppp_api modem_ppp_ppp_api; \ 181 \ 182 static uint8_t _CONCAT(_name, _receive_buf)[_buf_size]; \ 183 static uint8_t _CONCAT(_name, _transmit_buf)[_buf_size]; \ 184 \ 185 static struct modem_ppp _name = { \ 186 .init_iface = _init_iface, \ 187 .receive_buf = _CONCAT(_name, _receive_buf), \ 188 .transmit_buf = _CONCAT(_name, _transmit_buf), \ 189 .buf_size = _buf_size, \ 190 }; \ 191 \ 192 NET_DEVICE_INIT(_CONCAT(ppp_net_dev_, _name), "modem_ppp_" # _name, \ 193 modem_ppp_init_internal, NULL, &_name, NULL, _prio, &modem_ppp_ppp_api, \ 194 PPP_L2, NET_L2_GET_CTX_TYPE(PPP_L2), _mtu) 195 196 /** 197 * @} 198 */ 199 200 #ifdef __cplusplus 201 } 202 #endif 203 204 #endif /* ZEPHYR_MODEM_PPP_ */ 205