/** * 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 #include #include #include #include #include #include #include #include #include #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; }