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