aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-octphy/octpkt.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2015-09-06 16:04:32 +0200
committerHarald Welte <laforge@gnumonks.org>2016-01-16 17:23:10 +0100
commitb92100ad36f40d3125ff945fbd38aece873d1718 (patch)
tree3723ca47d14219f3ab78f24a3e219e0dbfaca1c4 /src/osmo-bts-octphy/octpkt.c
parente9f12acbeb5a369282719f8e0deecc88034a5488 (diff)
Add support for Octasic OCTSDR-2G GSM PHY
This adds support for a new PHY to OsmoBTS, the Octasic OCTSDR-2G PHY. This is a proprietary GSM PHY running on a familty of Octasic DSPs.
Diffstat (limited to 'src/osmo-bts-octphy/octpkt.c')
-rw-r--r--src/osmo-bts-octphy/octpkt.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/src/osmo-bts-octphy/octpkt.c b/src/osmo-bts-octphy/octpkt.c
new file mode 100644
index 00000000..a6167f50
--- /dev/null
+++ b/src/osmo-bts-octphy/octpkt.c
@@ -0,0 +1,190 @@
+/* Utility routines for dealing with OCTPKT/OCTVC1 in msgb */
+
+/* Copyright (c) 2015 Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <errno.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
+
+#include <osmocom/core/select.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/socket.h>
+
+#include <osmo-bts/gsm_data.h>
+
+#include <octphy/octpkt/octpkt_hdr.h>
+#include <octphy/octpkt/octpkt_hdr_swap.h>
+#include <octphy/octvc1/octvocnet_pkt.h>
+#include <octphy/octvc1/octvc1_msg.h>
+#include <octphy/octvc1/octvc1_msg_swap.h>
+#include <octphy/octvc1/gsm/octvc1_gsm_api.h>
+
+#include "l1_if.h"
+#include "octpkt.h"
+
+/* push a common header (1 dword) to the start of a msgb */
+void octpkt_push_common_hdr(struct msgb *msg, uint8_t format,
+ uint8_t trace, uint32_t ptype)
+{
+ uint32_t ch;
+ uint32_t *chptr;
+ uint32_t tot_len = msgb_length(msg) + sizeof(ch);
+
+ ch = ((format & cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_FORMAT_BIT_MASK)
+ << cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_FORMAT_BIT_OFFSET) |
+ ((trace & cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_TRACE_BIT_MASK)
+ << cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_TRACE_BIT_OFFSET) |
+ ((ptype & cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_CONTROL_PROTOCOL_TYPE_BIT_MASK)
+ << cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_CONTROL_PROTOCOL_TYPE_BIT_OFFSET) |
+ (tot_len & cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_LENGTH_BIT_MASK);
+
+ chptr = (uint32_t *) msgb_push(msg, sizeof(ch));
+ *chptr = htonl(ch);
+}
+
+/* push a control header (3 dwords) to the start of a msgb. This format
+ * is used for command and response packets */
+void octvocnet_push_ctl_hdr(struct msgb *msg, uint32_t dest_fifo_id,
+ uint32_t src_fifo_id, uint32_t socket_id)
+{
+ tOCTVOCNET_PKT_CTL_HEADER *ch;
+
+ ch = (tOCTVOCNET_PKT_CTL_HEADER *) msgb_push(msg, sizeof(*ch));
+
+ ch->ulDestFifoId = htonl(dest_fifo_id);
+ ch->ulSourceFifoId = htonl(src_fifo_id);
+ ch->ulSocketId = htonl(socket_id);
+}
+
+/* push a data header (3 dwords) to the start of a msgb. This format is
+ * used for event packets */
+static void octvocnet_push_data_hdr(struct msgb *msg,
+ uint32_t log_obj_hdl,
+ uint32_t log_obj_pkt_port,
+ uint32_t dest_fifo_id)
+{
+ tOCTVOCNET_PKT_DATA_HEADER *dh;
+
+ dh = (tOCTVOCNET_PKT_DATA_HEADER *) msgb_push(msg, sizeof(*dh));
+
+ dh->hLogicalObj = htonl(log_obj_hdl);
+ dh->ulLogicalObjPktPort = htonl(log_obj_pkt_port);
+ dh->ulDestFifoId = htonl(dest_fifo_id);
+}
+
+/* common msg_header shared by all control messages. host byte order! */
+void octvc1_fill_msg_hdr(tOCTVC1_MSG_HEADER *mh, uint32_t len,
+ uint32_t sess_id, uint32_t trans_id,
+ uint32_t user_info, uint32_t msg_type,
+ uint32_t flags, uint32_t api_cmd)
+{
+ uint32_t type_r_cmdid;
+ type_r_cmdid = ((msg_type & cOCTVC1_MSG_TYPE_BIT_MASK)
+ << cOCTVC1_MSG_TYPE_BIT_OFFSET) |
+ ((api_cmd & cOCTVC1_MSG_ID_BIT_MASK)
+ << cOCTVC1_MSG_ID_BIT_OFFSET);
+ /* Resync? Flags? */
+
+ mh->ulLength = len;
+ mh->ulTransactionId = trans_id;
+ mh->ul_Type_R_CmdId = type_r_cmdid;
+ mh->ulSessionId = sess_id;
+ mh->ulReturnCode = 0;
+ mh->ulUserInfo = user_info;
+}
+
+static void octvc1_push_msg_hdr(struct msgb *msg,
+ uint32_t sess_id,
+ uint32_t trans_id,
+ uint32_t user_info,
+ uint32_t msg_type,
+ uint32_t flags,
+ uint32_t api_cmd)
+{
+ tOCTVC1_MSG_HEADER *mh;
+ uint32_t len = msgb_length(msg);
+
+ mh = (tOCTVC1_MSG_HEADER *) msgb_push(msg, sizeof(*mh));
+
+ octvc1_fill_msg_hdr(mh, len, sess_id, trans_id, user_info, msg_type, flags, api_cmd);
+}
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <linux/if_packet.h>
+#include <net/ethernet.h>
+
+/*! \brief Initialize a packet socket
+ * \param[in] tye Socket type like SOCK_RAW or SOCK_DGRAM
+ * \param[in] proto The link-layer protocol in network byte order
+ * \param[in] bind_dev The name of the interface to bind to (if any)
+ * \param[in] flags flags like \ref OSMO_SOCK_F_BIND
+ *
+ * This function creates a new packet socket of \a type and \a proto
+ * and optionally bnds to it, if stated in the \a flags parameter.
+ */
+int osmo_sock_packet_init(uint16_t type, uint16_t proto, const char *bind_dev,
+ unsigned int flags)
+{
+ int sfd, rc, on = 1;
+
+ if (flags & OSMO_SOCK_F_CONNECT)
+ return -EINVAL;
+
+ sfd = socket(AF_PACKET, type, proto);
+ if (sfd < 0)
+ return -1;
+
+ if (flags & OSMO_SOCK_F_NONBLOCK) {
+ if (ioctl(sfd, FIONBIO, (unsigned char *)&on) < 0) {
+ perror("cannot set this socket unblocking");
+ close(sfd);
+ return -EINVAL;
+ }
+ }
+
+ if (bind_dev) {
+ struct sockaddr_ll sa;
+ struct ifreq ifr;
+
+ /* resolve the string device name to an ifindex */
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, bind_dev, sizeof(ifr.ifr_name));
+ rc = ioctl(sfd, SIOCGIFINDEX, &ifr);
+ if (rc < 0)
+ goto err;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sll_family = AF_PACKET;
+ sa.sll_protocol = htons(proto);
+ sa.sll_ifindex = ifr.ifr_ifindex;
+ /* according to the packet(7) man page, bind() will only
+ * use sll_protocol nad sll_ifindex */
+ rc = bind(sfd, (struct sockaddr *)&sa, sizeof(sa));
+ if (rc < 0)
+ goto err;
+ }
+
+ return sfd;
+err:
+ close(sfd);
+ return -1;
+}