コード例 #1
0
ファイル: btsco.c プロジェクト: goroutines/rumprun
/*
 * Handle private ioctl. We pass information out about how to talk
 * to the device and mixer.
 */
static int
btsco_dev_ioctl(void *hdl, u_long cmd, void *addr, int flag,
    struct lwp *l)
{
	struct btsco_softc *sc = hdl;
	struct btsco_info *bi = (struct btsco_info *)addr;
	int err = 0;

	DPRINTF("%s cmd 0x%lx flag %d\n", sc->sc_name, cmd, flag);

	switch (cmd) {
	case BTSCO_GETINFO:
		memset(bi, 0, sizeof(*bi));
		bdaddr_copy(&bi->laddr, &sc->sc_laddr);
		bdaddr_copy(&bi->raddr, &sc->sc_raddr);
		bi->channel = sc->sc_channel;
		bi->vgs = BTSCO_VGS;
		bi->vgm = BTSCO_VGM;
		break;

	default:
		err = EPASSTHROUGH;
		break;
	}

	return err;
}
コード例 #2
0
ファイル: sco_upper.c プロジェクト: kusumi/DragonFlyBSD
/*
 * sco_connect(pcb, sockaddr)
 *
 *	Initiate a SCO connection to the destination address.
 */
int
sco_connect(struct sco_pcb *pcb, struct sockaddr_bt *dest)
{
	hci_add_sco_con_cp cp;
	struct hci_unit *unit;
	struct hci_link *acl, *sco;
	int err;

	if (pcb->sp_flags & SP_LISTENING)
		return EINVAL;

	bdaddr_copy(&pcb->sp_raddr, &dest->bt_bdaddr);

	if (bdaddr_any(&pcb->sp_raddr))
		return EDESTADDRREQ;

	if (bdaddr_any(&pcb->sp_laddr)) {
		err = hci_route_lookup(&pcb->sp_laddr, &pcb->sp_raddr);
		if (err)
			return err;
	}

	unit = hci_unit_lookup(&pcb->sp_laddr);
	if (unit == NULL)
		return ENETDOWN;

	/*
	 * We must have an already open ACL connection before we open the SCO
	 * connection, and since SCO connections dont happen on their own we
	 * will not open one, the application wanting this should have opened
	 * it previously.
	 */
	acl = hci_link_lookup_bdaddr(unit, &pcb->sp_raddr, HCI_LINK_ACL);
	if (acl == NULL || acl->hl_state != HCI_LINK_OPEN)
		return EHOSTUNREACH;

	sco = hci_link_alloc(unit);
	if (sco == NULL)
		return ENOMEM;

	sco->hl_type = HCI_LINK_SCO;
	bdaddr_copy(&sco->hl_bdaddr, &pcb->sp_raddr);

	sco->hl_link = hci_acl_open(unit, &pcb->sp_raddr);
	KKASSERT(sco->hl_link == acl);

	cp.con_handle = htole16(acl->hl_handle);
	cp.pkt_type = htole16(0x00e0);		/* HV1, HV2, HV3 */
	err = hci_send_cmd(unit, HCI_CMD_ADD_SCO_CON, &cp, sizeof(cp));
	if (err) {
		hci_link_free(sco, err);
		return err;
	}

	sco->hl_sco = pcb;
	pcb->sp_link = sco;

	pcb->sp_mtu = unit->hci_max_sco_size;
	return 0;
}
コード例 #3
0
ファイル: bthidev.c プロジェクト: Tommmster/netbsd-avr32
static void
bthidev_ctl_connected(void *arg)
{
	struct sockaddr_bt sa;
	struct bthidev_softc *sc = arg;
	int err;

	if (sc->sc_state != BTHID_WAIT_CTL)
		return;

	KASSERT(sc->sc_ctl != NULL);
	KASSERT(sc->sc_int == NULL);

	if (sc->sc_flags & BTHID_CONNECTING) {
		/* initiate connect on interrupt PSM */
		err = l2cap_attach(&sc->sc_int, &bthidev_int_proto, sc);
		if (err)
			goto fail;

		err = l2cap_setopt(sc->sc_int, &sc->sc_mode);
		if (err)
			goto fail;

		memset(&sa, 0, sizeof(sa));
		sa.bt_len = sizeof(sa);
		sa.bt_family = AF_BLUETOOTH;
		bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);

		err = l2cap_bind(sc->sc_int, &sa);
		if (err)
			goto fail;

		sa.bt_psm = sc->sc_intpsm;
		bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr);
		err = l2cap_connect(sc->sc_int, &sa);
		if (err)
			goto fail;
	}

	sc->sc_state = BTHID_WAIT_INT;
	return;

fail:
	l2cap_detach(&sc->sc_ctl);
	sc->sc_ctl = NULL;

	aprint_error_dev(sc->sc_dev, "connect failed (%d)\n", err);
}
コード例 #4
0
ファイル: server.c プロジェクト: ryo/netbsd-src
/*
 * Accept new client connection and register it with index
 */
static void
server_accept_client(server_t *srv, int fd)
{
	struct sockaddr_bt	sa;
	socklen_t		len;
	int			cfd;
	uint16_t		omtu;

	do {
		cfd = accept(fd, NULL, NULL);
	} while (cfd == -1 && errno == EINTR);

	if (cfd == -1) {
		log_err("Could not accept connection on %s socket. %s (%d)",
		    srv->fdidx[fd].control ? "control" : "L2CAP",
		    strerror(errno), errno);

		return;
	}

	if (cfd >= FD_SETSIZE) {
		log_crit("File descriptor too large");
		close(cfd);
		return;
	}

	assert(!FD_ISSET(cfd, &srv->fdset));
	assert(!srv->fdidx[cfd].valid);

	memset(&sa, 0, sizeof(sa));
	omtu = srv->omtu;

	if (!srv->fdidx[fd].control) {
		len = sizeof(sa);
		if (getsockname(cfd, (struct sockaddr *)&sa, &len) == -1)
			log_warning("getsockname failed, using BDADDR_ANY");

		len = sizeof(omtu);
	        if (getsockopt(cfd, BTPROTO_L2CAP, SO_L2CAP_OMTU, &omtu, &len) == -1)
			log_warning("Could not get L2CAP OMTU, using %d", omtu);
		else
			omtu -= sizeof(sdp_pdu_t);
	}

	/* Add client descriptor to the index */
	if (cfd > srv->fdmax)
		srv->fdmax = cfd;

	FD_SET(cfd, &srv->fdset);
	srv->fdidx[cfd].valid = true;
	srv->fdidx[cfd].server = false;
	srv->fdidx[cfd].control = srv->fdidx[fd].control;
	srv->fdidx[cfd].priv = false;
	srv->fdidx[cfd].omtu = (omtu > srv->omtu) ? srv->omtu : omtu;
	srv->fdidx[cfd].offset = 0;
	bdaddr_copy(&srv->fdidx[cfd].bdaddr, &sa.bt_bdaddr);

	log_debug("new %s client on fd#%d",
	    srv->fdidx[cfd].control ? "control" : "L2CAP", cfd);
}
コード例 #5
0
/*
 * sco_bind(pcb, sockaddr)
 *
 *	Bind SCO pcb to local address
 */
int
sco_bind(struct sco_pcb *pcb, struct sockaddr_bt *addr)
{

	bdaddr_copy(&pcb->sp_laddr, &addr->bt_bdaddr);
	return 0;
}
コード例 #6
0
ファイル: bthidev.c プロジェクト: appleorange1/bitrig
/*
 * start connecting to our device
 */
int
bthidev_connect(struct bthidev_softc *sc)
{
	struct sockaddr_bt sa;
	int err;

	if (sc->sc_attempts++ > 0)
		printf("%s: connect (#%d)\n",
		    sc->sc_btdev.sc_dev.dv_xname, sc->sc_attempts);

	memset(&sa, 0, sizeof(sa));
	sa.bt_len = sizeof(sa);
	sa.bt_family = AF_BLUETOOTH;

	err = l2cap_attach(&sc->sc_ctl, &bthidev_ctl_proto, sc);
	if (err) {
		printf("%s: l2cap_attach failed (%d)\n",
		    sc->sc_btdev.sc_dev.dv_xname, err);
		return err;
	}

	err = l2cap_setlinkmode(sc->sc_ctl, sc->sc_mode);
	if (err)
		return err;

	bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);
	err = l2cap_bind(sc->sc_ctl, &sa);
	if (err) {
		printf("%s: l2cap_bind failed (%d)\n",
		    sc->sc_btdev.sc_dev.dv_xname, err);
		return err;
	}

	sa.bt_psm = sc->sc_ctlpsm;
	bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr);
	err = l2cap_connect(sc->sc_ctl, &sa);
	if (err) {
		printf("%s: l2cap_connect failed (%d)\n",
		    sc->sc_btdev.sc_dev.dv_xname, err);
		return err;
	}

	sc->sc_state = BTHID_WAIT_CTL;
	return 0;
}
コード例 #7
0
ファイル: server.c プロジェクト: ryo/netbsd-src
/*
 * Open L2CAP server socket
 */
static bool
server_open_l2cap(server_t *srv)
{
	struct sockaddr_bt	sa;
	int			fd;

	fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
	if (fd == -1) {
		log_crit("Could not create L2CAP socket. %s (%d)",
		    strerror(errno), errno);

		return false;
	}

        if (setsockopt(fd, BTPROTO_L2CAP, SO_L2CAP_IMTU,
	    &srv->imtu, sizeof(srv->imtu)) == -1) {
		log_crit("Could not set L2CAP Incoming MTU. %s (%d)",
		    strerror(errno), errno);

		close(fd);
		return false;
        }

	memset(&sa, 0, sizeof(sa));
	sa.bt_len = sizeof(sa);
	sa.bt_family = AF_BLUETOOTH;
	sa.bt_psm = L2CAP_PSM_SDP;
	bdaddr_copy(&sa.bt_bdaddr, BDADDR_ANY);

	if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
		log_crit("Could not bind L2CAP socket. %s (%d)",
		    strerror(errno), errno);

		close(fd);
		return false;
	}

	if (listen(fd, 5) == -1) {
		log_crit("Could not listen on L2CAP socket. %s (%d)",
		    strerror(errno), errno);

		close(fd);
		return false;
	}

	/* Add L2CAP descriptor to index */
	if (fd > srv->fdmax)
		srv->fdmax = fd;

	FD_SET(fd, &srv->fdset);
	srv->fdidx[fd].valid = true;
	srv->fdidx[fd].server = true;
	srv->fdidx[fd].control = false;
	srv->fdidx[fd].priv = false;
	return true;
}
コード例 #8
0
/*
 * sco_peeraddr(pcb, sockaddr)
 *
 *	Copy remote address of SCO pcb to sockaddr
 */
int
sco_peeraddr(struct sco_pcb *pcb, struct sockaddr_bt *addr)
{

	memset(addr, 0, sizeof(struct sockaddr_bt));
	addr->bt_len = sizeof(struct sockaddr_bt);
	addr->bt_family = AF_BLUETOOTH;
	bdaddr_copy(&addr->bt_bdaddr, &pcb->sp_raddr);
	return 0;
}
コード例 #9
0
ファイル: bthidev.c プロジェクト: goroutines/rumprun
/*
 * start connecting to our device
 */
static int
bthidev_connect(struct bthidev_softc *sc)
{
	struct sockaddr_bt sa;
	int err;

	if (sc->sc_attempts++ > 0)
		aprint_verbose_dev(sc->sc_dev, "connect (#%d)\n", sc->sc_attempts);

	memset(&sa, 0, sizeof(sa));
	sa.bt_len = sizeof(sa);
	sa.bt_family = AF_BLUETOOTH;

	err = l2cap_attach_pcb(&sc->sc_ctl, &bthidev_ctl_proto, sc);
	if (err) {
		aprint_error_dev(sc->sc_dev, "l2cap_attach failed (%d)\n", err);
		return err;
	}

	err = l2cap_setopt(sc->sc_ctl, &sc->sc_mode);
	if (err) {
		aprint_error_dev(sc->sc_dev, "l2cap_setopt failed (%d)\n", err);
		return err;
	}

	bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);
	err = l2cap_bind_pcb(sc->sc_ctl, &sa);
	if (err) {
		aprint_error_dev(sc->sc_dev, "l2cap_bind_pcb failed (%d)\n", err);
		return err;
	}

	sa.bt_psm = sc->sc_ctlpsm;
	bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr);
	err = l2cap_connect_pcb(sc->sc_ctl, &sa);
	if (err) {
		aprint_error_dev(sc->sc_dev, "l2cap_connect_pcb failed (%d)\n", err);
		return err;
	}

	sc->sc_state = BTHID_WAIT_CTL;
	return 0;
}
コード例 #10
0
ファイル: bthidev.c プロジェクト: Tommmster/netbsd-avr32
/*
 * listen for our device
 */
static int
bthidev_listen(struct bthidev_softc *sc)
{
	struct sockaddr_bt sa;
	int err;

	memset(&sa, 0, sizeof(sa));
	sa.bt_len = sizeof(sa);
	sa.bt_family = AF_BLUETOOTH;
	bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);

	/*
	 * Listen on control PSM
	 */
	err = l2cap_attach(&sc->sc_ctl_l, &bthidev_ctl_proto, sc);
	if (err)
		return err;

	err = l2cap_setopt(sc->sc_ctl_l, &sc->sc_mode);
	if (err)
		return err;

	sa.bt_psm = sc->sc_ctlpsm;
	err = l2cap_bind(sc->sc_ctl_l, &sa);
	if (err)
		return err;

	err = l2cap_listen(sc->sc_ctl_l);
	if (err)
		return err;

	/*
	 * Listen on interrupt PSM
	 */
	err = l2cap_attach(&sc->sc_int_l, &bthidev_int_proto, sc);
	if (err)
		return err;

	err = l2cap_setopt(sc->sc_int_l, &sc->sc_mode);
	if (err)
		return err;

	sa.bt_psm = sc->sc_intpsm;
	err = l2cap_bind(sc->sc_int_l, &sa);
	if (err)
		return err;

	err = l2cap_listen(sc->sc_int_l);
	if (err)
		return err;

	sc->sc_state = BTHID_WAIT_CTL;
	return 0;
}
コード例 #11
0
int
bt_devaddr(char const *devname, bdaddr_t *addr)
{
	struct bt_devinfo	di;

	strlcpy(di.devname, devname, sizeof(di.devname));

	if (bt_devinfo(&di) < 0)
		return (0);

	if (addr != NULL)
		bdaddr_copy(addr, &di.bdaddr);

	return (1);
}
コード例 #12
0
ファイル: server.c プロジェクト: 2asoft/freebsd
static void
server_open(void)
{
	struct sockaddr_l2cap sa;
	uint16_t mru;

	server_fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
	if (server_fd == -1) {
		log_err("Could not open L2CAP socket: %m");
		exit(EXIT_FAILURE);
	}

	memset(&sa, 0, sizeof(sa));
	sa.l2cap_family = AF_BLUETOOTH;
	sa.l2cap_len = sizeof(sa);
	sa.l2cap_psm = htole16(l2cap_psm);
	sa.l2cap_bdaddr_type = BDADDR_BREDR;
	sa.l2cap_cid = 0;
	
	bdaddr_copy(&sa.l2cap_bdaddr, &local_bdaddr);
	if (bind(server_fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
		log_err("Could not bind server socket: %m");
		exit(EXIT_FAILURE);
	}

	mru = BNEP_MTU_MIN;
	if (setsockopt(server_fd, SOL_L2CAP,
	    SO_L2CAP_IMTU, &mru, sizeof(mru)) == -1) {
		log_err("Could not set L2CAP IMTU (%d): %m", mru);
		exit(EXIT_FAILURE);
	}

	if (listen(server_fd, 0) == -1) {
		log_err("Could not listen on server socket: %m");
		exit(EXIT_FAILURE);
	}

	event_set(&server_ev, server_fd, EV_READ | EV_PERSIST, server_read, NULL);
	if (event_add(&server_ev, NULL) == -1) {
		log_err("Could not add server event: %m");
		exit(EXIT_FAILURE);
	}

	log_info("server socket open");
}
コード例 #13
0
ファイル: bthidev.c プロジェクト: Tommmster/netbsd-avr32
static void
bthidev_attach(device_t parent, device_t self, void *aux)
{
	struct bthidev_softc *sc = device_private(self);
	prop_dictionary_t dict = aux;
	prop_object_t obj;
	device_t dev;
	struct bthidev_attach_args bha;
	struct bthidev *hidev;
	struct hid_data *d;
	struct hid_item h;
	const void *desc;
	int locs[BTHIDBUSCF_NLOCS];
	int maxid, rep, dlen;

	/*
	 * Init softc
	 */
	sc->sc_dev = self;
	LIST_INIT(&sc->sc_list);
	callout_init(&sc->sc_reconnect, 0);
	callout_setfunc(&sc->sc_reconnect, bthidev_timeout, sc);
	sc->sc_state = BTHID_CLOSED;
	sc->sc_flags = BTHID_CONNECTING;
	sc->sc_ctlpsm = L2CAP_PSM_HID_CNTL;
	sc->sc_intpsm = L2CAP_PSM_HID_INTR;

	sockopt_init(&sc->sc_mode, BTPROTO_L2CAP, SO_L2CAP_LM, 0);

	/*
	 * extract config from proplist
	 */
	obj = prop_dictionary_get(dict, BTDEVladdr);
	bdaddr_copy(&sc->sc_laddr, prop_data_data_nocopy(obj));

	obj = prop_dictionary_get(dict, BTDEVraddr);
	bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj));

	obj = prop_dictionary_get(dict, BTDEVmode);
	if (prop_object_type(obj) == PROP_TYPE_STRING) {
		if (prop_string_equals_cstring(obj, BTDEVauth))
			sockopt_setint(&sc->sc_mode, L2CAP_LM_AUTH);
		else if (prop_string_equals_cstring(obj, BTDEVencrypt))
			sockopt_setint(&sc->sc_mode, L2CAP_LM_ENCRYPT);
		else if (prop_string_equals_cstring(obj, BTDEVsecure))
			sockopt_setint(&sc->sc_mode, L2CAP_LM_SECURE);
		else  {
			aprint_error(" unknown %s\n", BTDEVmode);
			return;
		}

		aprint_verbose(" %s %s", BTDEVmode,
					 prop_string_cstring_nocopy(obj));
	}

	obj = prop_dictionary_get(dict, BTHIDEVcontrolpsm);
	if (prop_object_type(obj) == PROP_TYPE_NUMBER) {
		sc->sc_ctlpsm = prop_number_integer_value(obj);
		if (L2CAP_PSM_INVALID(sc->sc_ctlpsm)) {
			aprint_error(" invalid %s\n", BTHIDEVcontrolpsm);
			return;
		}
	}

	obj = prop_dictionary_get(dict, BTHIDEVinterruptpsm);
	if (prop_object_type(obj) == PROP_TYPE_NUMBER) {
		sc->sc_intpsm = prop_number_integer_value(obj);
		if (L2CAP_PSM_INVALID(sc->sc_intpsm)) {
			aprint_error(" invalid %s\n", BTHIDEVinterruptpsm);
			return;
		}
	}

	obj = prop_dictionary_get(dict, BTHIDEVdescriptor);
	if (prop_object_type(obj) == PROP_TYPE_DATA) {
		dlen = prop_data_size(obj);
		desc = prop_data_data_nocopy(obj);
	} else {
		aprint_error(" no %s\n", BTHIDEVdescriptor);
		return;
	}

	obj = prop_dictionary_get(dict, BTHIDEVreconnect);
	if (prop_object_type(obj) == PROP_TYPE_BOOL
	    && !prop_bool_true(obj))
		sc->sc_flags |= BTHID_RECONNECT;

	/*
	 * Parse the descriptor and attach child devices, one per report.
	 */
	maxid = -1;
	h.report_ID = 0;
	d = hid_start_parse(desc, dlen, hid_none);
	while (hid_get_item(d, &h)) {
		if (h.report_ID > maxid)
			maxid = h.report_ID;
	}
	hid_end_parse(d);

	if (maxid < 0) {
		aprint_error(" no reports found\n");
		return;
	}

	aprint_normal("\n");

	for (rep = 0 ; rep <= maxid ; rep++) {
		if (hid_report_size(desc, dlen, hid_feature, rep) == 0
		    && hid_report_size(desc, dlen, hid_input, rep) == 0
		    && hid_report_size(desc, dlen, hid_output, rep) == 0)
			continue;

		bha.ba_desc = desc;
		bha.ba_dlen = dlen;
		bha.ba_input = bthidev_null;
		bha.ba_feature = bthidev_null;
		bha.ba_output = bthidev_output;
		bha.ba_id = rep;

		locs[BTHIDBUSCF_REPORTID] = rep;

		dev = config_found_sm_loc(self, "bthidbus",
					locs, &bha, bthidev_print, config_stdsubmatch);
		if (dev != NULL) {
			hidev = device_private(dev);
			hidev->sc_dev = dev;
			hidev->sc_parent = self;
			hidev->sc_id = rep;
			hidev->sc_input = bha.ba_input;
			hidev->sc_feature = bha.ba_feature;
			LIST_INSERT_HEAD(&sc->sc_list, hidev, sc_next);
		}
	}

	/*
	 * start bluetooth connections
	 */
	mutex_enter(bt_lock);
	if ((sc->sc_flags & BTHID_RECONNECT) == 0)
		bthidev_listen(sc);

	if (sc->sc_flags & BTHID_CONNECTING)
		bthidev_connect(sc);
	mutex_exit(bt_lock);
}
コード例 #14
0
ファイル: btpin.c プロジェクト: AhmadTux/DragonFlyBSD
int
main(int ac, char *av[])
{
	bthcid_pin_response_t rp;
	struct sockaddr_un un;
	char *pin = NULL;
	int ch, s, len;

	memset(&rp, 0, sizeof(rp));
	len = -1;

	memset(&un, 0, sizeof(un));
	un.sun_len = sizeof(un);
	un.sun_family = AF_LOCAL;
	strlcpy(un.sun_path, BTHCID_SOCKET_NAME, sizeof(un.sun_path));

	while ((ch = getopt(ac, av, "a:d:l:p:rs:")) != -1) {
		switch (ch) {
		case 'a':
			if (!bt_aton(optarg, &rp.raddr)) {
				struct hostent  *he = NULL;

				if ((he = bt_gethostbyname(optarg)) == NULL)
					errx(EXIT_FAILURE, "%s: %s", optarg,
							hstrerror(h_errno));

				bdaddr_copy(&rp.raddr, (bdaddr_t *)he->h_addr);
			}
			break;

		case 'd':
			if (!bt_devaddr(optarg, &rp.laddr))
				err(EXIT_FAILURE, "%s", optarg);

			break;

		case 'l':
			len = atoi(optarg);
			if (len < 1 || len > HCI_PIN_SIZE)
				errx(EXIT_FAILURE, "Invalid PIN length");

			break;

		case 'p':
			pin = optarg;
			break;

		case 'r':
			if (len == -1)
				len = 4;

			break;

		case 's':
			strlcpy(un.sun_path, optarg, sizeof(un.sun_path));
			break;

		default:
			usage();
		}
	}

	if (bdaddr_any(&rp.raddr))
		usage();

	if (pin == NULL) {
		if (len == -1)
			usage();

		srandom(time(NULL));

		pin = (char *)rp.pin;
		while (len-- > 0)
			*pin++ = '0' + (random() % 10);

		printf("PIN: %.*s\n", HCI_PIN_SIZE, rp.pin);
	} else {
		if (len != -1)
			usage();

		strncpy((char *)rp.pin, pin, HCI_PIN_SIZE);
	}

	s = socket(PF_LOCAL, SOCK_STREAM, 0);
	if (s < 0)
		err(EXIT_FAILURE, "socket");

	if (connect(s, (struct sockaddr *)&un, sizeof(un)) < 0)
		err(EXIT_FAILURE, "connect(\"%s\")", un.sun_path);
	
	if (send(s, &rp, sizeof(rp), 0) != sizeof(rp))
		err(EXIT_FAILURE, "send");

	close(s);
	exit(EXIT_SUCCESS);
}
コード例 #15
0
ファイル: bthidev.c プロジェクト: appleorange1/bitrig
void
bthidev_attach(struct device *parent, struct device *self, void *aux)
{
	struct bthidev_softc *sc = (struct bthidev_softc *)self;
	struct btdev_attach_args *bda = (struct btdev_attach_args *)aux;
	struct bthidev_attach_args bha;
	struct bthidev *hidev;
	struct hid_data *d;
	struct hid_item h;
	int maxid, rep;

	/*
	 * Init softc
	 */
	LIST_INIT(&sc->sc_list);
	timeout_set(&sc->sc_reconnect, bthidev_timeout, sc);
	sc->sc_state = BTHID_CLOSED;
	sc->sc_flags = BTHID_CONNECTING;
	sc->sc_ctlpsm = L2CAP_PSM_HID_CNTL;
	sc->sc_intpsm = L2CAP_PSM_HID_INTR;

	sc->sc_mode = 0;

	/*
	 * copy in our configuration info
	 */
	bdaddr_copy(&sc->sc_laddr, &bda->bd_laddr);
	bdaddr_copy(&sc->sc_raddr, &bda->bd_raddr);

	if (bda->bd_mode != BTDEV_MODE_NONE) {
		if (bda->bd_mode == BTDEV_MODE_AUTH) {
			sc->sc_mode = L2CAP_LM_AUTH;
			printf(" auth");
		} else if (bda->bd_mode == BTDEV_MODE_ENCRYPT) {
			sc->sc_mode = L2CAP_LM_ENCRYPT;
			printf(" encrypt");
		} else if (bda->bd_mode == BTDEV_MODE_SECURE) {
			sc->sc_mode = L2CAP_LM_SECURE;
			printf(" secure");
		} else {
			printf(" unknown link-mode: %d\n", bda->bd_mode);
			return;
		}
	}

	if (!L2CAP_PSM_INVALID(bda->bd_hid.hid_ctl))
		sc->sc_ctlpsm = bda->bd_hid.hid_ctl;

	if (!L2CAP_PSM_INVALID(bda->bd_hid.hid_int))
		sc->sc_intpsm = bda->bd_hid.hid_int;

	if (bda->bd_hid.hid_flags & BTHID_INITIATE)
		sc->sc_flags |= BTHID_RECONNECT;

	if (bda->bd_hid.hid_desc == NULL ||
	    bda->bd_hid.hid_dlen == 0 ||
	    bda->bd_hid.hid_dlen > MAX_DESCRIPTOR_LEN) {
		printf(": no descriptor\n");
		return;
	}
	sc->sc_dlen = bda->bd_hid.hid_dlen;
	sc->sc_desc = malloc(bda->bd_hid.hid_dlen, M_BTHIDEV,
	    M_WAITOK | M_CANFAIL);
	if (sc->sc_desc == NULL) {
		printf(": no memory\n");
		return;
	}
	if (copyin(bda->bd_hid.hid_desc, sc->sc_desc, bda->bd_hid.hid_dlen)) {
		free(sc->sc_desc, M_BTHIDEV);
		printf(": no descriptor");
		return;
	}

	/*
	 * Parse the descriptor and attach child devices, one per report.
	 */
	maxid = -1;
	h.report_ID = 0;
	d = hid_start_parse(sc->sc_desc, sc->sc_dlen, hid_none);
	while (hid_get_item(d, &h)) {
		if (h.report_ID > maxid)
			maxid = h.report_ID;
	}
	hid_end_parse(d);

	if (maxid < 0) {
		printf(": no reports found\n");
		return;
	}

	printf("\n");

	for (rep = 0 ; rep <= maxid ; rep++) {
		if (hid_report_size(sc->sc_desc, sc->sc_dlen, hid_feature, rep) == 0
		    && hid_report_size(sc->sc_desc, sc->sc_dlen, hid_input, rep) == 0
		    && hid_report_size(sc->sc_desc, sc->sc_dlen, hid_output, rep) == 0)
			continue;

		bha.ba_desc = sc->sc_desc;
		bha.ba_dlen = sc->sc_dlen;
		bha.ba_input = bthidev_null;
		bha.ba_feature = bthidev_null;
		bha.ba_output = bthidev_output;
		bha.ba_id = rep;

		hidev = (struct bthidev *)config_found_sm(self, &bha,
		    bthidev_print, bthidevsubmatch);
		if (hidev != NULL) {
			hidev->sc_parent = &sc->sc_btdev;
			hidev->sc_id = rep;
			hidev->sc_input = bha.ba_input;
			hidev->sc_feature = bha.ba_feature;
			LIST_INSERT_HEAD(&sc->sc_list, hidev, sc_next);
		}
	}

	/*
	 * start bluetooth connections
	 */
	mutex_enter(&bt_lock);
	if ((sc->sc_flags & BTHID_RECONNECT) == 0)
		bthidev_listen(sc);

	if (sc->sc_flags & BTHID_CONNECTING)
		bthidev_connect(sc);
	mutex_exit(&bt_lock);
}
コード例 #16
0
ファイル: btsco.c プロジェクト: goroutines/rumprun
static int
btsco_open(void *hdl, int flags)
{
	struct sockaddr_bt sa;
	struct btsco_softc *sc = hdl;
	struct sockopt sopt;
	int err, timo;

	DPRINTF("%s flags 0x%x\n", sc->sc_name, flags);
	/* flags FREAD & FWRITE? */

	if (sc->sc_sco != NULL || sc->sc_sco_l != NULL)
		return EIO;

	KASSERT(mutex_owned(bt_lock));

	memset(&sa, 0, sizeof(sa));
	sa.bt_len = sizeof(sa);
	sa.bt_family = AF_BLUETOOTH;
	bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);

	if (sc->sc_flags & BTSCO_LISTEN) {
		err = sco_attach_pcb(&sc->sc_sco_l, &btsco_sco_proto, sc);
		if (err)
			goto done;

		err = sco_bind_pcb(sc->sc_sco_l, &sa);
		if (err) {
			sco_detach_pcb(&sc->sc_sco_l);
			goto done;
		}

		err = sco_listen_pcb(sc->sc_sco_l);
		if (err) {
			sco_detach_pcb(&sc->sc_sco_l);
			goto done;
		}

		timo = 0;	/* no timeout */
	} else {
		err = sco_attach_pcb(&sc->sc_sco, &btsco_sco_proto, sc);
		if (err)
			goto done;

		err = sco_bind_pcb(sc->sc_sco, &sa);
		if (err) {
			sco_detach_pcb(&sc->sc_sco);
			goto done;
		}

		bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr);
		err = sco_connect_pcb(sc->sc_sco, &sa);
		if (err) {
			sco_detach_pcb(&sc->sc_sco);
			goto done;
		}

		timo = BTSCO_TIMEOUT;
	}

	sc->sc_state = BTSCO_WAIT_CONNECT;
	while (err == 0 && sc->sc_state == BTSCO_WAIT_CONNECT)
		err = cv_timedwait_sig(&sc->sc_connect, bt_lock, timo);

	switch (sc->sc_state) {
	case BTSCO_CLOSED:		/* disconnected */
		err = sc->sc_err;

		/* fall through to */
	case BTSCO_WAIT_CONNECT:	/* error */
		if (sc->sc_sco != NULL)
			sco_detach_pcb(&sc->sc_sco);

		if (sc->sc_sco_l != NULL)
			sco_detach_pcb(&sc->sc_sco_l);

		break;

	case BTSCO_OPEN:		/* hurrah */
		sockopt_init(&sopt, BTPROTO_SCO, SO_SCO_MTU, 0);
		(void)sco_getopt(sc->sc_sco, &sopt);
		(void)sockopt_get(&sopt, &sc->sc_mtu, sizeof(sc->sc_mtu));
		sockopt_destroy(&sopt);
		break;

	default:
		UNKNOWN(sc->sc_state);
		break;
	}

done:
	DPRINTF("done err=%d, sc_state=%d, sc_mtu=%d\n",
			err, sc->sc_state, sc->sc_mtu);
	return err;
}
コード例 #17
0
ファイル: btsco.c プロジェクト: goroutines/rumprun
static void
btsco_attach(device_t parent, device_t self, void *aux)
{
	struct btsco_softc *sc = device_private(self);
	prop_dictionary_t dict = aux;
	prop_object_t obj;

	/*
	 * Init softc
	 */
	sc->sc_vgs = 200;
	sc->sc_vgm = 200;
	sc->sc_state = BTSCO_CLOSED;
	sc->sc_name = device_xname(self);
	cv_init(&sc->sc_connect, "connect");
	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_NONE);

	/*
	 * copy in our configuration info
	 */
	obj = prop_dictionary_get(dict, BTDEVladdr);
	bdaddr_copy(&sc->sc_laddr, prop_data_data_nocopy(obj));

	obj = prop_dictionary_get(dict, BTDEVraddr);
	bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj));

	obj = prop_dictionary_get(dict, BTDEVservice);
	if (prop_string_equals_cstring(obj, "HF")) {
		sc->sc_flags |= BTSCO_LISTEN;
		aprint_verbose(" listen mode");
	}

	obj = prop_dictionary_get(dict, BTSCOchannel);
	if (prop_object_type(obj) != PROP_TYPE_NUMBER
	    || prop_number_integer_value(obj) < RFCOMM_CHANNEL_MIN
	    || prop_number_integer_value(obj) > RFCOMM_CHANNEL_MAX) {
		aprint_error(" invalid %s", BTSCOchannel);
		return;
	}
	sc->sc_channel = prop_number_integer_value(obj);

	aprint_verbose(" channel %d", sc->sc_channel);
	aprint_normal("\n");

	DPRINTF("sc=%p\n", sc);

	/*
	 * set up transmit interrupt
	 */
	sc->sc_intr = softint_establish(SOFTINT_NET, btsco_intr, sc);
	if (sc->sc_intr == NULL) {
		aprint_error_dev(self, "softint_establish failed\n");
		return;
	}

	/*
	 * attach audio device
	 */
	sc->sc_audio = audio_attach_mi(&btsco_if, sc, self);
	if (sc->sc_audio == NULL) {
		aprint_error_dev(self, "audio_attach_mi failed\n");
		return;
	}

	pmf_device_register(self, NULL, NULL);
}
コード例 #18
0
ファイル: server.c プロジェクト: AhmadTux/DragonFlyBSD
static void
server_accept_client(server_p srv, int32_t fd)
{
	uint8_t		*rsp = NULL;
	socklen_t	 size;
	int32_t		 cfd;
	uint16_t	 omtu;

	do {
		cfd = accept(fd, NULL, NULL);
	} while (cfd < 0 && errno == EINTR);

	if (cfd < 0) {
		log_err("Could not accept connection on %s socket. %s (%d)",
			srv->fdidx[fd].control? "control" : "L2CAP",
			strerror(errno), errno);
		return;
	}

	assert(!FD_ISSET(cfd, &srv->fdset));
	assert(!srv->fdidx[cfd].valid);

	if (!srv->fdidx[fd].control) {
		/* Get local BD_ADDR */
		size = sizeof(srv->req_sa);
		if (getsockname(cfd,(struct sockaddr*)&srv->req_sa, &size) < 0) {
			log_err("Could not get local BD_ADDR. %s (%d)",
				strerror(errno), errno);
			close(cfd);
			return;
		}

		/* Get outgoing MTU */
		size = sizeof(omtu);
	        if (getsockopt(cfd, BTPROTO_L2CAP, SO_L2CAP_OMTU, &omtu, &size) < 0) {
			log_err("Could not get L2CAP OMTU. %s (%d)",
				strerror(errno), errno);
			close(cfd);
			return;
		}

		/*
		 * The maximum size of the L2CAP packet is 65536 bytes.
		 * The minimum L2CAP MTU is 43 bytes. That means we need
		 * 65536 / 43 = ~1524 chunks to transfer maximum packet
		 * size with minimum MTU. The "rsp_cs" field in fd_idx_t
		 * is 11 bit wide that gives us upto 2048 chunks.
		 */

		if (omtu < L2CAP_MTU_MINIMUM) {
			log_err("L2CAP OMTU is too small (%d bytes)", omtu);
			close(cfd);
			return;
		}
	} else {
		bdaddr_copy(&srv->req_sa.bt_bdaddr, BDADDR_ANY);
		omtu = srv->fdidx[fd].omtu;
	}

	/*
	 * Allocate buffer. This is an overkill, but we can not know how
	 * big our reply is going to be.
	 */

	rsp = (uint8_t *) calloc(L2CAP_MTU_MAXIMUM, sizeof(rsp[0]));
	if (rsp == NULL) {
		log_crit("Could not allocate response buffer");
		close(cfd);
		return;
	}

	/* Add client descriptor to the index */
	FD_SET(cfd, &srv->fdset);
	if (srv->maxfd < cfd)
		srv->maxfd = cfd;
	srv->fdidx[cfd].valid = 1;
	srv->fdidx[cfd].server = 0;
	srv->fdidx[cfd].control = srv->fdidx[fd].control;
	srv->fdidx[cfd].priv = 0;
	srv->fdidx[cfd].rsp_cs = 0;
	srv->fdidx[cfd].rsp_size = 0;
	srv->fdidx[cfd].rsp_limit = 0;
	srv->fdidx[cfd].omtu = omtu;
	srv->fdidx[cfd].rsp = rsp;
}
コード例 #19
0
ファイル: server.c プロジェクト: AhmadTux/DragonFlyBSD
int32_t
server_init(server_p srv, char const *control, char const *sgroup)
{
	struct sockaddr_un	un;
	struct sockaddr_bt	l2;
	socklen_t		size;
	int32_t			unsock, l2sock;
	uint16_t		imtu;
	int			opt;

	assert(srv != NULL);
	assert(control != NULL);

	memset(srv, 0, sizeof(srv));
	srv->sgroup = sgroup;

	/* Open control socket */
	if (unlink(control) < 0 && errno != ENOENT) {
		log_crit("Could not unlink(%s). %s (%d)",
			control, strerror(errno), errno);
		return (-1);
	}

	unsock = socket(PF_LOCAL, SOCK_STREAM, 0);
	if (unsock < 0) {
		log_crit("Could not create control socket. %s (%d)",
			strerror(errno), errno);
		return (-1);
	}

	opt = 1;
#if 0
	if (setsockopt(unsock, 0, LOCAL_CREDS, &opt, sizeof(opt)) < 0)
		log_crit("Warning: No credential checks on control socket");
#endif
	memset(&un, 0, sizeof(un));
	un.sun_len = sizeof(un);
	un.sun_family = AF_LOCAL;
	strlcpy(un.sun_path, control, sizeof(un.sun_path));

	if (bind(unsock, (struct sockaddr *) &un, sizeof(un)) < 0) {
		log_crit("Could not bind control socket. %s (%d)",
			strerror(errno), errno);
		close(unsock);
		return (-1);
	}

	if (chmod(control, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) < 0) {
		log_crit("Could not change permissions on control socket. " \
			"%s (%d)", strerror(errno), errno);
		close(unsock);
		return (-1);
	}

	if (listen(unsock, 10) < 0) {
		log_crit("Could not listen on control socket. %s (%d)",
			strerror(errno), errno);
		close(unsock);
		return (-1);
	}

	/* Open L2CAP socket */
	l2sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
	if (l2sock < 0) {
		log_crit("Could not create L2CAP socket. %s (%d)",
			strerror(errno), errno);
		close(unsock);
		return (-1);
	}

	size = sizeof(imtu);
        if (getsockopt(l2sock, BTPROTO_L2CAP, SO_L2CAP_IMTU, &imtu, &size) < 0) {
		log_crit("Could not get L2CAP IMTU. %s (%d)",
			strerror(errno), errno);
		close(unsock);
		close(l2sock);
		return (-1);
        }

	memset(&l2, 0, sizeof(l2));
	l2.bt_len = sizeof(l2);
	l2.bt_family = AF_BLUETOOTH;
	l2.bt_psm = L2CAP_PSM_SDP;
	bdaddr_copy(&l2.bt_bdaddr, BDADDR_ANY);

	if (bind(l2sock, (struct sockaddr *) &l2, sizeof(l2)) < 0) {
		log_crit("Could not bind L2CAP socket. %s (%d)",
			strerror(errno), errno);
		close(unsock);
		close(l2sock);
		return (-1);
	}

	if (listen(l2sock, 10) < 0) {
		log_crit("Could not listen on L2CAP socket. %s (%d)",
			strerror(errno), errno);
		close(unsock);
		close(l2sock);
		return (-1);
	}

	/* Allocate incoming buffer */
	srv->imtu = (imtu > SDP_LOCAL_MTU)? imtu : SDP_LOCAL_MTU;
	srv->req = (uint8_t *) calloc(srv->imtu, sizeof(srv->req[0]));
	if (srv->req == NULL) {
		log_crit("Could not allocate request buffer");
		close(unsock);
		close(l2sock);
		return (-1);
	}

	/* Allocate memory for descriptor index */
	srv->fdidx = (fd_idx_p) calloc(FD_SETSIZE, sizeof(srv->fdidx[0]));
	if (srv->fdidx == NULL) {
		log_crit("Could not allocate fd index");
		free(srv->req);
		close(unsock);
		close(l2sock);
		return (-1);
	}

	/* Register Service Discovery profile (attach it to control socket) */
	if (provider_register_sd(unsock) < 0) {
		log_crit("Could not register Service Discovery profile");
		free(srv->fdidx);
		free(srv->req);
		close(unsock);
		close(l2sock);
		return (-1);
	}

	/*
	 * If we got here then everything is fine. Add both control sockets
	 * to the index.
	 */

	FD_ZERO(&srv->fdset);
	srv->maxfd = (unsock > l2sock)? unsock : l2sock;

	FD_SET(unsock, &srv->fdset);
	srv->fdidx[unsock].valid = 1;
	srv->fdidx[unsock].server = 1;
	srv->fdidx[unsock].control = 1;
	srv->fdidx[unsock].priv = 0;
	srv->fdidx[unsock].rsp_cs = 0;
	srv->fdidx[unsock].rsp_size = 0;
	srv->fdidx[unsock].rsp_limit = 0;
	srv->fdidx[unsock].omtu = SDP_LOCAL_MTU;
	srv->fdidx[unsock].rsp = NULL;

	FD_SET(l2sock, &srv->fdset);
	srv->fdidx[l2sock].valid = 1;
	srv->fdidx[l2sock].server = 1;
	srv->fdidx[l2sock].control = 0;
	srv->fdidx[l2sock].priv = 0;
	srv->fdidx[l2sock].rsp_cs = 0;
	srv->fdidx[l2sock].rsp_size = 0;
	srv->fdidx[l2sock].rsp_limit = 0;
	srv->fdidx[l2sock].omtu = 0; /* unknown */
	srv->fdidx[l2sock].rsp = NULL;

	return (0);
}
コード例 #20
0
ファイル: backend_bt.c プロジェクト: hselasky/virtual_oss
static int
bt_open(struct voss_backend *pbe, const char *devname, int samplerate, int bufsize,
    int *pchannels, int *pformat, struct bt_config *cfg,
    int service_class, int isSink)
{
	struct sockaddr_l2cap addr;
	struct l2cap_info info;
	socklen_t mtusize = sizeof(uint16_t);
	int tmpbitpool;
	int l2cap_psm;
	int temp;
	int err;

	memset(&info, 0, sizeof(info));

	if (strstr(devname, "/dev/bluetooth/") != devname) {
		printf("Invalid device name '%s'", devname);
		goto error;
	}
	/* skip prefix */
	devname += sizeof("/dev/bluetooth/") - 1;

	if (!bt_aton(devname, &info.raddr)) {
		struct hostent *he = NULL;

		if ((he = bt_gethostbyname(devname)) == NULL) {
			DPRINTF("Could not get host by name\n");
			goto error;
		}
		bdaddr_copy(&info.raddr, (bdaddr_t *)he->h_addr);
	}
retry:
	switch (samplerate) {
	case 8000:
		cfg->freq = FREQ_UNDEFINED;
		cfg->aacMode1 = 0x80;
		cfg->aacMode2 = 0x0C;
		break;
	case 11025:
		cfg->freq = FREQ_UNDEFINED;
		cfg->aacMode1 = 0x40;
		cfg->aacMode2 = 0x0C;
		break;
	case 12000:
		cfg->freq = FREQ_UNDEFINED;
		cfg->aacMode1 = 0x20;
		cfg->aacMode2 = 0x0C;
		break;
	case 16000:
		cfg->freq = FREQ_16K;
		cfg->aacMode1 = 0x10;
		cfg->aacMode2 = 0x0C;
		break;
	case 22050:
		cfg->freq = FREQ_UNDEFINED;
		cfg->aacMode1 = 0x08;
		cfg->aacMode2 = 0x0C;
		break;
	case 24000:
		cfg->freq = FREQ_UNDEFINED;
		cfg->aacMode1 = 0x04;
		cfg->aacMode2 = 0x0C;
		break;
	case 32000:
		cfg->freq = FREQ_32K;
		cfg->aacMode1 = 0x02;
		cfg->aacMode2 = 0x0C;
		break;
	case 44100:
		cfg->freq = FREQ_44_1K;
		cfg->aacMode1 = 0x01;
		cfg->aacMode2 = 0x0C;
		break;
	case 48000:
		cfg->freq = FREQ_48K;
		cfg->aacMode1 = 0;
		cfg->aacMode2 = 0x8C;
		break;
	case 64000:
		cfg->freq = FREQ_UNDEFINED;
		cfg->aacMode1 = 0;
		cfg->aacMode2 = 0x4C;
		break;
	case 88200:
		cfg->freq = FREQ_UNDEFINED;
		cfg->aacMode1 = 0;
		cfg->aacMode2 = 0x2C;
		break;
	case 96000:
		cfg->freq = FREQ_UNDEFINED;
		cfg->aacMode1 = 0;
		cfg->aacMode2 = 0x1C;
		break;
	default:
		DPRINTF("Invalid samplerate %d", samplerate);
		goto error;
	}
	cfg->bands = BANDS_8;
	cfg->bitpool = 0;

	switch (*pchannels) {
	case 1:
		cfg->aacMode2 &= 0xF8;
		cfg->chmode = MODE_MONO;
		break;
	default:
		cfg->aacMode2 &= 0xF4;
		cfg->chmode = MODE_STEREO;
		break;
	}

	cfg->allocm = ALLOC_LOUDNESS;

	if (cfg->chmode == MODE_MONO || cfg->chmode == MODE_DUAL)
		tmpbitpool = 16;
	else
		tmpbitpool = 32;

	if (cfg->bands == BANDS_8)
		tmpbitpool *= 8;
	else
		tmpbitpool *= 4;

	if (tmpbitpool > DEFAULT_MAXBPOOL)
		tmpbitpool = DEFAULT_MAXBPOOL;

	cfg->bitpool = tmpbitpool;

	if (bt_set_format(pformat)) {
		DPRINTF("Unsupported sample format\n");
		goto error;
	}
	l2cap_psm = bt_query(&info, service_class);
	DPRINTF("PSM=0x%02x\n", l2cap_psm);
	if (l2cap_psm < 0) {
		DPRINTF("PSM not found\n");
		goto error;
	}
	cfg->hc = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
	if (cfg->hc < 0) {
		DPRINTF("Could not create BT socket\n");
		goto error;
	}
	memset(&addr, 0, sizeof(addr));
	addr.l2cap_len = sizeof(addr);
	addr.l2cap_family = AF_BLUETOOTH;
	bdaddr_copy(&addr.l2cap_bdaddr, &info.laddr);

	if (bind(cfg->hc, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		DPRINTF("Could not bind to HC\n");
		goto error;
	}
	bdaddr_copy(&addr.l2cap_bdaddr, &info.raddr);
	addr.l2cap_psm = l2cap_psm;
	if (connect(cfg->hc, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		DPRINTF("Could not connect to HC: %d\n", errno);
		goto error;
	}
	if (avdtpDiscoverAndConfig(cfg, isSink)) {
		DPRINTF("DISCOVER FAILED\n");
		goto error;
	}
	if (avdtpOpen(cfg->hc, cfg->sep)) {
		DPRINTF("OPEN FAILED\n");
		goto error;
	}
	cfg->fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
	if (cfg->fd < 0) {
		DPRINTF("Could not create BT socket\n");
		goto error;
	}
	memset(&addr, 0, sizeof(addr));

	addr.l2cap_len = sizeof(addr);
	addr.l2cap_family = AF_BLUETOOTH;
	bdaddr_copy(&addr.l2cap_bdaddr, &info.laddr);

	if (bind(cfg->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		DPRINTF("Could not bind\n");
		goto error;
	}
	bdaddr_copy(&addr.l2cap_bdaddr, &info.raddr);
	addr.l2cap_psm = l2cap_psm;
	if (connect(cfg->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		DPRINTF("Could not connect: %d\n", errno);
		goto error;
	}
	if (isSink) {
		if (getsockopt(cfg->fd, SOL_L2CAP, SO_L2CAP_OMTU, &cfg->mtu, &mtusize) == -1) {
			DPRINTF("Could not get MTU\n");
			goto error;
		}
		temp = cfg->mtu * 2;
		if (setsockopt(cfg->fd, SOL_SOCKET, SO_SNDBUF, &temp, sizeof(temp)) == -1) {
			DPRINTF("Could not set send buffer size\n");
			goto error;
		}
		temp = cfg->mtu;
		if (setsockopt(cfg->fd, SOL_SOCKET, SO_SNDLOWAT, &temp, sizeof(temp)) == -1) {
			DPRINTF("Could not set low water mark\n");
			goto error;
		}
	} else {
		if (getsockopt(cfg->fd, SOL_L2CAP, SO_L2CAP_IMTU, &cfg->mtu, &mtusize) == -1) {
			DPRINTF("Could not get MTU\n");
			goto error;
		}
		temp = cfg->mtu * 16;
		if (setsockopt(cfg->fd, SOL_SOCKET, SO_RCVBUF, &temp, sizeof(temp)) == -1) {
			DPRINTF("Could not set receive buffer size\n");
			goto error;
		}
		temp = 1;
		if (setsockopt(cfg->fd, SOL_SOCKET, SO_RCVLOWAT, &temp, sizeof(temp)) == -1) {
			DPRINTF("Could not set low water mark\n");
			goto error;
		}
	}

	if (avdtpStart(cfg->hc, cfg->sep)) {
		DPRINTF("START FAILED\n");
		goto error;
	}
	switch (cfg->chmode) {
	case MODE_MONO:
		*pchannels = 1;
		break;
	default:
		*pchannels = 2;
		break;
	}
	return (0);

error:
	if (cfg->hc > 0) {
		close(cfg->hc);
		cfg->hc = -1;
	}
	if (cfg->fd > 0) {
		close(cfg->fd);
		cfg->fd = -1;
	}
	return (-1);
}
コード例 #21
0
ファイル: client.c プロジェクト: hmatyschok/MeshBSD
void
client_init(void)
{
	struct sockaddr_l2cap sa;
	channel_t *chan;
	socklen_t len;
	int fd, n;
	uint16_t mru, mtu;

	if (bdaddr_any(&remote_bdaddr))
		return;

	if (service_name)
		client_query();

	fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
	if (fd == -1) {
		log_err("Could not open L2CAP socket: %m");
		exit(EXIT_FAILURE);
	}

	memset(&sa, 0, sizeof(sa));
	sa.l2cap_family = AF_BLUETOOTH;
	sa.l2cap_len = sizeof(sa);
	sa.l2cap_bdaddr_type = BDADDR_BREDR;
	sa.l2cap_cid = 0;
	 
	bdaddr_copy(&sa.l2cap_bdaddr, &local_bdaddr);
	if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
		log_err("Could not bind client socket: %m");
		exit(EXIT_FAILURE);
	}

	mru = BNEP_MTU_MIN;
	if (setsockopt(fd, SOL_L2CAP, SO_L2CAP_IMTU, &mru, sizeof(mru)) == -1) {
		log_err("Could not set L2CAP IMTU (%d): %m", mru);
		exit(EXIT_FAILURE);
	}

	log_info("Opening connection to service 0x%4.4x at %s",
	    service_class, bt_ntoa(&remote_bdaddr, NULL));

	sa.l2cap_psm = htole16(l2cap_psm);
	bdaddr_copy(&sa.l2cap_bdaddr, &remote_bdaddr);
	if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
		log_err("Could not connect: %m");
		exit(EXIT_FAILURE);
	}

	len = sizeof(mru);
	if (getsockopt(fd, SOL_L2CAP, SO_L2CAP_IMTU, &mru, &len) == -1) {
		log_err("Could not get IMTU: %m");
		exit(EXIT_FAILURE);
	}
	if (mru < BNEP_MTU_MIN) {
		log_err("L2CAP IMTU too small (%d)", mru);
		exit(EXIT_FAILURE);
	}

	len = sizeof(n);
	if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &n, &len) == -1) {
		log_err("Could not read SO_RCVBUF");
		exit(EXIT_FAILURE);
	}
	if (n < (mru * 10)) {
		n = mru * 10;
		if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1)
			log_info("Could not increase SO_RCVBUF (from %d)", n);
	}

	len = sizeof(mtu);
	if (getsockopt(fd, SOL_L2CAP, SO_L2CAP_OMTU, &mtu, &len) == -1) {
		log_err("Could not get L2CAP OMTU: %m");
		exit(EXIT_FAILURE);
	}
	if (mtu < BNEP_MTU_MIN) {
		log_err("L2CAP OMTU too small (%d)", mtu);
		exit(EXIT_FAILURE);
	}

	len = sizeof(n);
	if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &n, &len) == -1) {
		log_err("Could not get socket send buffer size: %m");
		close(fd);
		return;
	}
	if (n < (mtu * 2)) {
		n = mtu * 2;
		if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)) == -1) {
			log_err("Could not set socket send buffer size (%d): %m", n);
			close(fd);
			return;
		}
	}
	n = mtu;
	if (setsockopt(fd, SOL_SOCKET, SO_SNDLOWAT, &n, sizeof(n)) == -1) {
		log_err("Could not set socket low water mark (%d): %m", n);
		close(fd);
		return;
	}

	chan = channel_alloc();
	if (chan == NULL)
		exit(EXIT_FAILURE);

	chan->send = bnep_send;
	chan->recv = bnep_recv;
	chan->mru = mru;
	chan->mtu = mtu;
	b2eaddr(chan->raddr, &remote_bdaddr);
	b2eaddr(chan->laddr, &local_bdaddr);
	chan->state = CHANNEL_WAIT_CONNECT_RSP;
	channel_timeout(chan, 10);
	if (!channel_open(chan, fd))
		exit(EXIT_FAILURE);

	bnep_send_control(chan, BNEP_SETUP_CONNECTION_REQUEST,
	    2, service_class, SDP_SERVICE_CLASS_PANU);
}