Path: blob/main/usr.sbin/bluetooth/hccontrol/send_recv.c
106138 views
/*-1* send_recv.c2*3* SPDX-License-Identifier: BSD-2-Clause4*5* Copyright (c) 2001-2002 Maksim Yevmenkin <[email protected]>6* All rights reserved.7*8* Redistribution and use in source and binary forms, with or without9* modification, are permitted provided that the following conditions10* are met:11* 1. Redistributions of source code must retain the above copyright12* notice, this list of conditions and the following disclaimer.13* 2. Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in the15* documentation and/or other materials provided with the distribution.16*17* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND18* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE19* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE20* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE21* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL22* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS23* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)24* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT25* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY26* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF27* SUCH DAMAGE.28*29* $Id: send_recv.c,v 1.2 2003/05/21 22:40:30 max Exp $30*/3132#include <sys/types.h>33#include <sys/socket.h>34#include <sys/time.h>35#include <sys/endian.h>36#include <assert.h>37#include <errno.h>38#include <netgraph/bluetooth/include/ng_hci.h>39#include <string.h>40#include <unistd.h>41#include "hccontrol.h"4243/* Send HCI request to the unit */44int45hci_request(int s, int opcode, char const *cp, int cp_size, char *rp, int *rp_size)46{47char buffer[512];48int n;49ng_hci_cmd_pkt_t *c = (ng_hci_cmd_pkt_t *) buffer;50ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) buffer;5152assert(rp != NULL);53assert(rp_size != NULL);54assert(*rp_size > 0);5556c->type = NG_HCI_CMD_PKT;57c->opcode = (uint16_t) opcode;58c->opcode = htole16(c->opcode);5960if (cp != NULL) {61assert(0 < cp_size && cp_size <= NG_HCI_CMD_PKT_SIZE);6263c->length = (uint8_t) cp_size;64memcpy(buffer + sizeof(*c), cp, cp_size);65} else66c->length = 0;6768if (hci_send(s, buffer, sizeof(*c) + cp_size) == ERROR)69return (ERROR);7071again:72n = sizeof(buffer);73if (hci_recv(s, buffer, &n) == ERROR)74return (ERROR);7576if (n < sizeof(*e)) {77errno = EMSGSIZE;78return (ERROR);79}8081if (e->type != NG_HCI_EVENT_PKT) {82errno = EIO;83return (ERROR);84}8586switch (e->event) {87case NG_HCI_EVENT_COMMAND_COMPL: {88ng_hci_command_compl_ep *cc =89(ng_hci_command_compl_ep *)(e + 1);9091cc->opcode = le16toh(cc->opcode);9293if (cc->opcode == 0x0000 || cc->opcode != opcode)94goto again;9596n -= (sizeof(*e) + sizeof(*cc));97if (n < *rp_size)98*rp_size = n;99100memcpy(rp, buffer + sizeof(*e) + sizeof(*cc), *rp_size);101} break;102103case NG_HCI_EVENT_COMMAND_STATUS: {104ng_hci_command_status_ep *cs =105(ng_hci_command_status_ep *)(e + 1);106107cs->opcode = le16toh(cs->opcode);108109if (cs->opcode == 0x0000 || cs->opcode != opcode)110goto again;111112*rp_size = 1;113*rp = cs->status;114} break;115116default:117goto again;118}119120return (OK);121} /* hci_request */122123/* Send simple HCI request - Just HCI command packet (no parameters) */124int125hci_simple_request(int s, int opcode, char *rp, int *rp_size)126{127return (hci_request(s, opcode, NULL, 0, rp, rp_size));128} /* hci_simple_request */129130/* Send HCI data to the unit */131int132hci_send(int s, char const *buffer, int size)133{134assert(buffer != NULL);135assert(size >= sizeof(ng_hci_cmd_pkt_t));136assert(size <= sizeof(ng_hci_cmd_pkt_t) + NG_HCI_CMD_PKT_SIZE);137138if (send(s, buffer, size, 0) < 0)139return (ERROR);140141return (OK);142} /* hci_send */143144/* Receive HCI data from the unit */145int146hci_recv(int s, char *buffer, int *size)147{148struct timeval tv;149fd_set rfd;150int n;151152assert(buffer != NULL);153assert(size != NULL);154assert(*size > sizeof(ng_hci_event_pkt_t));155156again:157FD_ZERO(&rfd);158FD_SET(s, &rfd);159160tv.tv_sec = timeout;161tv.tv_usec = 0;162163n = select(s + 1, &rfd, NULL, NULL, &tv);164if (n <= 0) {165if (n < 0) {166if (errno == EINTR)167goto again;168} else169errno = ETIMEDOUT;170171return (ERROR);172}173174assert(FD_ISSET(s, &rfd));175176n = recv(s, buffer, *size, 0);177if (n < 0)178return (ERROR);179180*size = n;181182return (OK);183} /* hci_recv */184185186187