blob: 38b0a0b2908cf76e7d35f8cf21256fc8e3582e59 [file] [log] [blame]
/**
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* "Bottom"/Linux/Host side of the userchannel driver. This file is built in the native_simulator
* runner context with the host libC, but it's functionality can be called from the "embedded" side
*/
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <poll.h>
#include <unistd.h>
#include <sys/socket.h>
#include <limits.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <nsi_errno.h>
#define BTPROTO_HCI 1
#define HCI_CHANNEL_USER 1
struct sockaddr_hci {
sa_family_t hci_family;
unsigned short hci_dev;
unsigned short hci_channel;
};
bool user_chan_rx_ready(int fd)
{
struct pollfd pollfd = {.fd = fd, .events = POLLIN};
return (poll(&pollfd, 1, 0) == 1);
}
int user_chan_is_ipaddr_ok(char ip_addr[])
{
struct in_addr addr;
return inet_pton(AF_INET, ip_addr, &addr);
}
int user_chan_socket_open(unsigned short bt_dev_index)
{
int fd;
struct sockaddr_hci addr;
fd = socket(PF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, BTPROTO_HCI);
if (fd < 0) {
return -nsi_errno_to_mid(errno);
}
(void)memset(&addr, 0, sizeof(addr));
addr.hci_family = AF_BLUETOOTH;
addr.hci_dev = bt_dev_index;
addr.hci_channel = HCI_CHANNEL_USER;
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
int err = -nsi_errno_to_mid(errno);
close(fd);
return err;
}
return fd;
}
int user_chan_net_connect(char ip_addr[], unsigned int port)
{
int fd;
struct sockaddr_in addr;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
return -nsi_errno_to_mid(errno);
}
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (inet_pton(AF_INET, ip_addr, &(addr.sin_addr)) <= 0) {
int err = -nsi_errno_to_mid(errno);
close(fd);
return err;
}
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
int err = -nsi_errno_to_mid(errno);
close(fd);
return err;
}
return fd;
}