#pragma once /* (C) 2021 by Harald Welte * (C) 2022 by Andreas Eversberg * * All Rights Reserved * * SPDX-License-Identifier: GPL-2.0+ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #include #include #include #include #include #include "ph_socket.h" /* Table 35/G.964 */ enum v5x_mph_prim { MPH_UBR, /* Unblock (req) */ MPH_UBI, /* Unblock (ind) */ MPH_BR, /* Block (req) */ MPH_BI, /* Block (ind) */ MPH_AR, /* Activate (req) */ MPH_AI, /* Activate (ind) */ MPH_AWI, /* Access activation by user (ind) */ MPH_DSAI, /* DS Activated (ind) */ MPH_DR, /* Deactivate (req) */ MPH_DI, /* Deactivate (ind) */ MPH_GI, /* Grading Information */ MPH_DB, /* Block D-Channel from user port */ MPH_DU, /* Unblock D-Channel from user port */ }; /* Table 3/G.964 */ enum v5x_fe_prim { FE_establish_req = 0x00, FE_establish_ack_ind = 0x03, FE_establish_ind = 0x01, FE_establish_ack_req = 0x02, FE_line_signal_req = 0x10, FE_line_signal_ind = 0x11, FE_protocol_param_req = 0x20, FE_disconnect_req = 0x30, FE_disconnect_compl_req = 0x32, FE_disconnect_compl_ind = 0x33, }; /* Table 3/G.964 */ enum v5x_mgmt_prim { MDU_CTRL_port_blocked, MDU_CTRL_port_unblocked, MDU_CTRL_port_restart_req, MDU_CTRL_port_restart_ack, MDU_CTRL_port_restart_compl, MDU_error_ind, }; struct osmo_fsm_inst; enum v5x_dialect { V5X_DIALECT_V51 = 1, V5X_DIALECT_V52 = 2, }; enum v5x_user_type { V5X_USER_TYPE_ISDN = 1, V5X_USER_TYPE_PSTN = 2, }; /* forward-declarations */ struct v5x_interface; struct v5x_instance; struct v5x_user_port; struct v5x_link; /* A C-channel is a 64k timeslot used for signalling */ struct v5x_c_channel { struct v5x_link *link; /* back-pointer */ struct v5x_timeslot *ts; /* E1 link timeslot. NULL = C-channel doesn't exist */ bool active; /* false == standby */ }; /* one physical E1 timeslot used on an E1 interface part of a V5.2 interface */ struct v5x_timeslot { uint8_t nr; struct v5x_link *link; /* back-pointer */ struct v5x_user_port *v5up; /* user port that this TS is assigned to */ uint16_t l3_address; }; /* one physical E1 interface used within a V5.2 interface */ struct v5x_link { uint8_t id; struct v5x_interface *interface; /* back-pointer */ struct v5x_timeslot ts[32]; /* 32 E1 slots; 0 not available */ struct v5x_c_channel c_channel[3]; /* 64k signaling possible on TS16, TS15 and TS31 */ struct osmo_fsm_inst *l1_link_fi; /* Layer 1 Link FSM instance */ }; /* one V5.x interface between AN (Access Network) and LE (Local Exchange) */ struct v5x_interface { struct llist_head list; /* instance.interfaces */ struct v5x_instance *instance; /* back-pointer */ enum v5x_dialect dialect; uint32_t id; /* interface id */ uint8_t variant; /* provitioning variant */ struct v5x_link *primary_link; /* one of the links below */ struct v5x_link *secondary_link; /* one of the links below */ /* 1..16 links in one interface */ struct v5x_link links[16]; struct { struct v5x_ctrl_proto *ctrl; /* common control protocol instance */ struct lapv5_instance *li; /* Control data link */ bool established; /* track if link is up or down */ struct v5x_c_channel *c_chan; /* pointer to active C-channel */ } control; struct { struct lapv5_instance *li; /* Link control data link */ struct v5x_c_channel *c_chan; /* pointer to active C-channel */ struct osmo_fsm_inst *fi; /* Link Control FSM instance */ } lcp; struct { struct lapv5_instance *li; /* PSTN data link */ struct v5x_c_channel *c_chan; /* pointer to active C-channel */ } pstn; struct { struct lapv5_instance *li; /* BCC data link */ struct v5x_c_channel *c_chan; /* pointer to active C-channel */ } bcc; struct { struct lapv5_instance *li; /* Protection data link 1 + 2 */ struct v5x_c_channel *c_chan; /* pointer to active C-channel */ } protection[2]; struct llist_head user_ports; /* list of v5x_user_port */ }; struct v5x_ctrl_proto { struct v5x_user_port *v5up; /* back pointer, if port control is used */ struct v5x_interface *v5if; /* back pointer, if common control is used */ struct osmo_fsm_inst *fi; /* control FSM */ struct llist_head tx_queue; /* list of message to be transmitted */ struct msgb *tx_msg; /* copy of unacked message, for second try */ }; struct v5x_pstn_proto { struct v5x_user_port *v5up; /* back pointer, if port control is used */ struct osmo_fsm_inst *fi; /* control FSM */ uint8_t S_s, S_a, S_r; /* sequence numbers */ struct msgb *tx_msg; /* copy of unacked message, for repitition */ int timeout_event; /* event when timer times out */ int timeout_count; /* how many times the timer was started/timed out */ struct osmo_timer_list timer_Tr; /* extra timer for receive sequence ack */ struct osmo_timer_list timer_Tt; /* extra timer for transmit sequence ack */ }; /* one user-facing port (subscriber line) */ struct v5x_user_port { struct llist_head list; /* part of v5x_instance.ports */ struct v5x_interface *inst; /* back-pointer to instance we're part of */ uint16_t nr; /* port-number in decoded form (0..32767) */ char ifname[64]; /* name of interface, also used for PH-socket */ enum v5x_user_type type; /* type of port (ISDN/PSTN) */ struct v5x_ctrl_proto *ctrl; /* port control protocol instance */ struct osmo_fsm_inst *port_fi; /* port FSM */ uint8_t ts_nr[2]; /* time slots used (one for PSTN, two for ISDN) */ uint8_t link_nr[2]; /* link used */ uint8_t ts_activated[2]; /* set if data stream is active */ struct { } isdn; struct { struct v5x_pstn_proto *proto; } pstn; ph_socket_t ph_socket; /* unix socket to connect port to */ bool le_unblocked; /* if port is not blocked by LE */ bool an_unblocked; /* if port is not blocked by AN */ }; struct v5x_instance { struct llist_head list; /* part of global list of instances */ struct llist_head interfaces; /* v5x_interface.list */ }; struct v5x_instance *v5x_instance_alloc(void *ctx); struct v5x_interface *v5x_interface_alloc(struct v5x_instance *v5i, enum v5x_dialect dialect, int (*ph_data_req_cb)(struct msgb *msg, void *cbdata)); struct v5x_user_port *v5x_user_port_create(struct v5x_interface *v5if, uint16_t nr, enum v5x_user_type, uint8_t ts1, uint8_t ts2); void v5x_interface_free(struct v5x_interface *v5if); struct v5x_user_port *v5x_user_port_find(struct v5x_interface *v5if, uint16_t nr, bool is_isdn); void v5x_user_port_destroy(struct v5x_user_port *v5up); //FIXME: move this void ph_socket_rx_cb(ph_socket_t *s, int channel, uint8_t prim, uint8_t *data, int length);