Пример #1
0
void epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
{
	unsigned char buf[16];
	struct sigaction sa;
	struct pollfd p;
	char addr[18];
	int i, fd, sk, len;

	sk = rfcomm_connect(src, dst, channel);
	if (sk < 0)
		return;

	fd = uinput_create("Bluetooth Presenter", 0, 1);
	if (fd < 0) {
		close(sk);
		return;
	}

	ba2str(dst, addr);

	printf("Connected to %s on channel %d\n", addr, channel);
	printf("Press CTRL-C for hangup\n");

	memset(&sa, 0, sizeof(sa));
	sa.sa_flags   = SA_NOCLDSTOP;
	sa.sa_handler = SIG_IGN;
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);

	sa.sa_handler = sig_term;
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT,  &sa, NULL);

	sa.sa_handler = sig_hup;
	sigaction(SIGHUP, &sa, NULL);

	p.fd = sk;
	p.events = POLLIN | POLLERR | POLLHUP;

	while (!__io_canceled) {
		p.revents = 0;
		if (poll(&p, 1, 100) < 1)
			continue;

		len = read(sk, buf, sizeof(buf));
		if (len < 0)
			break;

		for (i = 0; i < len; i++)
			epox_decode(fd, buf[i]);
	}

	printf("Disconnected\n");

	ioctl(fd, UI_DEV_DESTROY);

	close(fd);
	close(sk);
}
Пример #2
0
int main(int argc, char *argv[])
{
	GOptionContext *context;

	context = g_option_context_new(NULL);
	g_option_context_add_main_entries(context, options, NULL);

	if (!g_option_context_parse(context, &argc, &argv, NULL))
		exit(EXIT_FAILURE);

	g_option_context_free(context);

	printf("accept=%d reject=%d discon=%d defer=%d sec=%d update_sec=%d"
		" prio=%d voice=0x%04x\n", opt_accept, opt_reject, opt_disconn,
		opt_defer, opt_sec, opt_update_sec, opt_priority, opt_voice);

	if (opt_psm || opt_cid) {
		if (argc > 1)
			l2cap_connect(opt_dev, argv[1], opt_addr_type,
					opt_psm, opt_cid, opt_disconn,
					opt_sec, opt_priority);
		else
			l2cap_listen(opt_dev, opt_addr_type, opt_psm, opt_cid,
					opt_defer, opt_reject, opt_disconn,
					opt_accept, opt_sec, opt_master);
	}

	if (opt_channel != -1) {
		if (argc > 1)
			rfcomm_connect(opt_dev, argv[1], opt_channel,
							opt_disconn, opt_sec);
		else
			rfcomm_listen(opt_dev, opt_channel, opt_defer,
					opt_reject, opt_disconn, opt_accept,
					opt_sec, opt_master);
	}

	if (opt_sco) {
		if (argc > 1)
			sco_connect(opt_dev, argv[1], opt_disconn, opt_voice);
		else
			sco_listen(opt_dev, opt_defer, opt_reject,
					opt_disconn, opt_accept, opt_voice);
	}

	signal(SIGTERM, sig_term);
	signal(SIGINT, sig_term);

	main_loop = g_main_loop_new(NULL, FALSE);

	g_main_loop_run(main_loop);

	g_main_loop_unref(main_loop);

	printf("Exiting\n");

	exit(EXIT_SUCCESS);
}
Пример #3
0
bool rfcomm_repeated_connect() {
  static const int max_iterations = 128;

  for (int i = 0; i < max_iterations; ++i) {
    TASSERT(rfcomm_connect(), "Connection failed on attempt %d/%d", i, max_iterations);
  }

  return true;
}
Пример #4
0
/*
 * l2cap_connected():
 *
 * Called by L2CAP when a connection response was received.
 * Sends a L2CAP configuration request.
 * Initializes a search for other devices if the connection attempt failed.
 */
err_t l2cap_connected(void *arg, struct l2cap_pcb *l2cappcb, u16_t result, u16_t status)
{
	struct sdp_pcb *sdppcb;
	struct rfcomm_pcb *rfcommpcb;

	u8_t ssp[] = {0x35, 0x03, 0x19, 0x11, 0x02}; /* Service search pattern with LAP UUID is default */ 
	err_t ret;

	u8_t attrids[] = {0x35, 0x03, 0x09, 0x00, 0x04}; /* Attribute IDs to search for in data element 
														sequence form */

	if(result == L2CAP_CONN_SUCCESS) {
		LWIP_DEBUGF(BT_SPP_DEBUG, ("l2cap_connected: L2CAP connected pcb->state = %d\n", l2cappcb->state));
		/* Tell L2CAP that we wish to be informed of a disconnection request */
		l2cap_disconnect_ind(l2cappcb, l2cap_disconnected_ind);
		switch(l2cap_psm(l2cappcb)) {
			case SDP_PSM:
				LWIP_DEBUGF(BT_SPP_DEBUG, ("l2cap_connected: SDP L2CAP configured. Result = %d\n", result));
				if((sdppcb = sdp_new(l2cappcb)) == NULL) {
					LWIP_DEBUGF(BT_SPP_DEBUG, ("l2cap_connected: Failed to create a SDP PCB\n"));
					return ERR_MEM;
				}

				l2cap_recv(l2cappcb, sdp_recv);

				ret = sdp_service_search_attrib_req(sdppcb, 0xFFFF, ssp, sizeof(ssp),
						attrids, sizeof(attrids), sdp_attributes_recv);
				return ret;

			case RFCOMM_PSM:
				LWIP_DEBUGF(BT_SPP_DEBUG, ("l2cap_connected: RFCOMM L2CAP configured. Result = %d CN = %d\n", result, bt_spp_state.cn));
				l2cap_recv(l2cappcb, rfcomm_input);

				if((rfcommpcb = rfcomm_new(l2cappcb)) == NULL) {
					LWIP_DEBUGF(BT_SPP_DEBUG, ("l2cap_connected: Failed to create a RFCOMM PCB\n"));
					return ERR_MEM;
				}

				hci_link_key_not(link_key_not); /* Set function to be called if a new link key is created */

				return rfcomm_connect(rfcommpcb, bt_spp_state.cn, rfcomm_connected); /* Connect with DLCI 0 */
			default:
				return ERR_VAL;
		}
	} else {
		LWIP_DEBUGF(BT_SPP_DEBUG, ("l2cap_connected: L2CAP not connected. Redo inquiry\n"));
		l2cap_close(l2cappcb);
		bt_spp_start();
	}

	return ERR_OK;
}
Пример #5
0
static GIOChannel *bluetooth_connect(GObexTransportType transport)
{
	GIOChannel *io;
	GError *err = NULL;

	if (option_dest == NULL || option_channel < 0)
		return NULL;

	if (option_channel > 31)
		io = l2cap_connect(transport, &err);
	else
		io = rfcomm_connect(transport, &err);

	if (io != NULL)
		return io;

	g_printerr("%s\n", err->message);
	g_error_free(err);
	return NULL;
}
Пример #6
0
static int session_connect(struct obc_session *session,
						struct callback_data *callback)
{
	int err;

	if (session->obex) {
		g_idle_add(connection_complete, callback);
		err = 0;
	} else if (session->channel > 0) {
		session->io = rfcomm_connect(&session->src, &session->dst,
							session->channel,
							rfcomm_callback,
							callback);
		err = (session->io == NULL) ? -EINVAL : 0;
	} else {
		callback->sdp = service_connect(&session->src, &session->dst,
						service_callback, callback);
		err = (callback->sdp == NULL) ? -ENOMEM : 0;
	}

	return err;
}
Пример #7
0
int main(int argc, char *argv[])
{
	int dev;
	int card;
	struct sigaction sa;

#ifdef TEST
	int rlen;
#endif
	int bt_dev = 0;

	struct pollfd pfds[16];

	int err;

	char hwdep_name[16];
	struct s_headset *akt_headset;

	atexit(cleanup);

	/* detect the audio device */
	if (find_hwdep_device(&card, &dev)) {
		perror("Can't find device. Bail");
		return 1;
	}
	printf("Device is %d:%d\n", card, dev);
	sprintf(hwdep_name, "hw:%i,%i", card, dev);

	if (check_bt_voice(bt_dev) < 0)
		return -1;

	/* find bdaddr */
	switch (argc) {
	case 2:
		akt_headset = headset_new();
		hci_devba(bt_dev, &akt_headset->local);
		str2ba(argv[1], &akt_headset->bdaddr);
		akt_headset->channel = detect_channel(&akt_headset->bdaddr);
		/* open hwdep on audio device */
		if ((err = snd_hwdep_open(&akt_headset->handle, hwdep_name, O_RDWR)) < 0) {
			fprintf(stderr, "btsco open (%i-%i): %s\n", card, dev, snd_strerror(err));
			return -1;
		}
		break;
	case 3:
		akt_headset = headset_new();
		hci_devba(bt_dev, &akt_headset->local);
		str2ba(argv[1], &akt_headset->bdaddr);
		akt_headset->channel = atoi(argv[2]);
		/* open hwdep on audio device */
		if ((err = snd_hwdep_open(&akt_headset->handle, hwdep_name, O_RDWR)) < 0) {
			fprintf(stderr, "btsco open (%i-%i): %s\n", card, dev, snd_strerror(err));
			return -1;
		}
		break;
	default:
		usage();
		exit(-1);
	}

	/* setup sigterm handler. we must make sure to do a clean disconnect */
	memset(&sa, 0, sizeof(sa));
	sa.sa_flags = SA_NOCLDSTOP;
	sa.sa_handler = sig_term;
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT, &sa, NULL);

	sa.sa_handler = SIG_IGN;
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);

	/* we are not yet connected */
	while (!terminate) {
		unsigned short revents;
		int nfds;
		nfds = 0;
		/* set up data polling description */
		for (akt_headset = first; akt_headset != NULL; akt_headset = akt_headset->next) { 
			if (akt_headset->rfcomm_fd == -1) {
				/* connect rfcomm control channel */
				if ((akt_headset->rfcomm_fd = rfcomm_connect(
						&akt_headset->local,
						&akt_headset->bdaddr,
						akt_headset->channel)) < 0)
					fprintf(stderr, "Can't connect RFCOMM channel");
				else
					fprintf(stderr, "RFCOMM channel %i connected\n", akt_headset->channel);
			}
			if (akt_headset->rfcomm_fd != -1) {
				pfds[nfds].fd = akt_headset->rfcomm_fd;
				pfds[nfds++].events = POLLIN;
			}
			if (akt_headset->handle != NULL) {
				/* polling data from hwdep interface */
				nfds += snd_hwdep_poll_descriptors(akt_headset->handle, &pfds[nfds], 1);
			}
		} 
		/*printf("outer loop\n"); */
		if (nfds == 0) {
			sleep(3);
			continue;
		}
		if (poll(pfds, nfds, 1000) <= 0) 
			continue;

		for (akt_headset = first; akt_headset != NULL; akt_headset = akt_headset->next) {
			int j;
			for (j = 0; j < nfds; j++) {
				if (pfds[j].fd == akt_headset->rfcomm_fd) {
					if (pfds[j].revents & POLLIN)
						headset_from_bt(akt_headset);
					continue;
				}
#ifdef TEST
				if (pfds[j].fd == akt_headset->sco_fd) {
					/* Just for testing; handled by kernel driver */
					fd_set rfds;
					if (0 && FD_ISSET(akt_headset->sco_fd, &rfds)) {
						int i;
						unsigned char buf[2048];

						memset(buf, 0, sizeof(buf));
						rlen = read(akt_headset->sco_fd, buf, sizeof(buf));
						write(akt_headset->sco_fd, buf, rlen);
						i++;
						if (i % 15 == 0) printf("rlen: %d\n", rlen);
					}
					continue;
				}
#endif
				/* Volume polling (sound card) */
				if (!snd_hwdep_poll_descriptors_revents (akt_headset->handle, &pfds[j], 1, &revents) && revents & POLLIN) 
					headset_volume_fromcard (akt_headset);
			}
		}
	}

	return 0;
}
Пример #8
0
int main(int argc, char *argv[])
{
	struct sigaction sa;

	fd_set rfds;
	struct timeval timeout;
	unsigned char buf[2048], *p;
	int maxfd, sel, rlen, wlen;

	bdaddr_t local;
	bdaddr_t bdaddr;
	uint8_t channel;

	char *filename;
	mode_t filemode;
	int err, mode = 0;
	int dd, rd, sd, fd;
	uint16_t sco_handle, sco_mtu, vs;

	switch (argc) {
	case 4:
		str2ba(argv[3], &bdaddr);
		channel = 6;
		break;
	case 5:
		str2ba(argv[3], &bdaddr);
		channel = atoi(argv[4]);
		break;
	default:
		usage();
		exit(-1);
	}

	if (strncmp(argv[1], "play", 4) == 0) {
		mode = PLAY;
		filemode = O_RDONLY;
	} else if (strncmp(argv[1], "rec", 3) == 0) {
		mode = RECORD;
		filemode = O_WRONLY | O_CREAT | O_TRUNC;
	} else {
		usage();
		exit(-1);
	}

	filename = argv[2];

	hci_devba(0, &local);
	dd = hci_open_dev(0);
	hci_read_voice_setting(dd, &vs, 1000);
	vs = htobs(vs);
	fprintf(stderr, "Voice setting: 0x%04x\n", vs);
	close(dd);
	if (vs != 0x0060) {
		fprintf(stderr, "The voice setting must be 0x0060\n");
		return -1;
	}

	if (strcmp(filename, "-") == 0) {
		switch (mode) {
		case PLAY:
			fd = 0;
			break;
		case RECORD:
			fd = 1;
			break;
		default:
			return -1;
		}
	} else {
		if ((fd = open(filename, filemode)) < 0) {
			perror("Can't open input/output file");
			return -1;
		}
	}

	memset(&sa, 0, sizeof(sa));
	sa.sa_flags = SA_NOCLDSTOP;
	sa.sa_handler = sig_term;
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT,  &sa, NULL);

	sa.sa_handler = SIG_IGN;
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);

	if ((rd = rfcomm_connect(&local, &bdaddr, channel)) < 0) {
		perror("Can't connect RFCOMM channel");
		return -1;
	}

	fprintf(stderr, "RFCOMM channel connected\n");

	if ((sd = sco_connect(&local, &bdaddr, &sco_handle, &sco_mtu)) < 0) {
		perror("Can't connect SCO audio channel");
		close(rd);
		return -1;
	}

	fprintf(stderr, "SCO audio channel connected (handle %d, mtu %d)\n", sco_handle, sco_mtu);

	if (mode == RECORD)
		err = write(rd, "RING\r\n", 6);

	maxfd = (rd > sd) ? rd : sd;

	while (!terminate) {

		FD_ZERO(&rfds);
		FD_SET(rd, &rfds);
		FD_SET(sd, &rfds);

		timeout.tv_sec = 0;
		timeout.tv_usec = 10000;

		if ((sel = select(maxfd + 1, &rfds, NULL, NULL, &timeout)) > 0) {

			if (FD_ISSET(rd, &rfds)) {
				memset(buf, 0, sizeof(buf));
				rlen = read(rd, buf, sizeof(buf));
				if (rlen > 0) {
					fprintf(stderr, "%s\n", buf);
					wlen = write(rd, "OK\r\n", 4);
				}
			}

			if (FD_ISSET(sd, &rfds)) {
				memset(buf, 0, sizeof(buf));
				rlen = read(sd, buf, sizeof(buf));
				if (rlen > 0)
					switch (mode) {
					case PLAY:
						rlen = read(fd, buf, rlen);

						wlen = 0;
						p = buf;
						while (rlen > sco_mtu) {
						        wlen += write(sd, p, sco_mtu);
						        rlen -= sco_mtu;
						        p += sco_mtu;
						}
						wlen += write(sd, p, rlen);
						break;
					case RECORD:
						wlen = write(fd, buf, rlen);
						break;
					default:
						break;
					}
			}

		}

	}

	close(sd);
	sleep(5);
	close(rd);

	close(fd);

	return 0;
}
Пример #9
0
/*
 * User Request.
 * up is socket
 * m is either
 *	optional mbuf chain containing message
 *	ioctl command (PRU_CONTROL)
 * nam is either
 *	optional mbuf chain containing an address
 *	ioctl data (PRU_CONTROL)
 *	optionally protocol number (PRU_ATTACH)
 *	message flags (PRU_RCVD)
 * ctl is either
 *	optional mbuf chain containing socket options
 *	optional interface pointer (PRU_CONTROL, PRU_PURGEIF)
 * l is pointer to process requesting action (if any)
 *
 * we are responsible for disposing of m and ctl if
 * they are mbuf chains
 */
int
rfcomm_usrreq(struct socket *up, int req, struct mbuf *m,
		struct mbuf *nam, struct mbuf *ctl, struct lwp *l)
{
	struct rfcomm_dlc *pcb = up->so_pcb;
	struct sockaddr_bt *sa;
	struct mbuf *m0;
	int err = 0;

	DPRINTFN(2, "%s\n", prurequests[req]);

	switch (req) {
	case PRU_CONTROL:
		return EPASSTHROUGH;

	case PRU_PURGEIF:
		return EOPNOTSUPP;

	case PRU_ATTACH:
		if (up->so_lock == NULL) {
			mutex_obj_hold(bt_lock);
			up->so_lock = bt_lock;
			solock(up);
		}
		KASSERT(solocked(up));
		if (pcb != NULL)
			return EINVAL;
		/*
		 * Since we have nothing to add, we attach the DLC
		 * structure directly to our PCB pointer.
		 */
		err = soreserve(up, rfcomm_sendspace, rfcomm_recvspace);
		if (err)
			return err;

		err = rfcomm_attach((struct rfcomm_dlc **)&up->so_pcb,
					&rfcomm_proto, up);
		if (err)
			return err;

		err = rfcomm_rcvd(up->so_pcb, sbspace(&up->so_rcv));
		if (err) {
			rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb);
			return err;
		}

		return 0;
	}

	if (pcb == NULL) {
		err = EINVAL;
		goto release;
	}

	switch(req) {
	case PRU_DISCONNECT:
		soisdisconnecting(up);
		return rfcomm_disconnect(pcb, up->so_linger);

	case PRU_ABORT:
		rfcomm_disconnect(pcb, 0);
		soisdisconnected(up);
		/* fall through to */
	case PRU_DETACH:
		return rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb);

	case PRU_BIND:
		KASSERT(nam != NULL);
		sa = mtod(nam, struct sockaddr_bt *);

		if (sa->bt_len != sizeof(struct sockaddr_bt))
			return EINVAL;

		if (sa->bt_family != AF_BLUETOOTH)
			return EAFNOSUPPORT;

		return rfcomm_bind(pcb, sa);

	case PRU_CONNECT:
		KASSERT(nam != NULL);
		sa = mtod(nam, struct sockaddr_bt *);

		if (sa->bt_len != sizeof(struct sockaddr_bt))
			return EINVAL;

		if (sa->bt_family != AF_BLUETOOTH)
			return EAFNOSUPPORT;

		soisconnecting(up);
		return rfcomm_connect(pcb, sa);

	case PRU_PEERADDR:
		KASSERT(nam != NULL);
		sa = mtod(nam, struct sockaddr_bt *);
		nam->m_len = sizeof(struct sockaddr_bt);
		return rfcomm_peeraddr(pcb, sa);

	case PRU_SOCKADDR:
		KASSERT(nam != NULL);
		sa = mtod(nam, struct sockaddr_bt *);
		nam->m_len = sizeof(struct sockaddr_bt);
		return rfcomm_sockaddr(pcb, sa);

	case PRU_SHUTDOWN:
		socantsendmore(up);
		break;

	case PRU_SEND:
		KASSERT(m != NULL);

		if (ctl)	/* no use for that */
			m_freem(ctl);

		m0 = m_copypacket(m, M_DONTWAIT);
		if (m0 == NULL)
			return ENOMEM;

		sbappendstream(&up->so_snd, m);

		return rfcomm_send(pcb, m0);

	case PRU_SENSE:
		return 0;		/* (no release) */

	case PRU_RCVD:
		return rfcomm_rcvd(pcb, sbspace(&up->so_rcv));

	case PRU_RCVOOB:
		return EOPNOTSUPP;	/* (no release) */

	case PRU_LISTEN:
		return rfcomm_listen(pcb);

	case PRU_ACCEPT:
		KASSERT(nam != NULL);
		sa = mtod(nam, struct sockaddr_bt *);
		nam->m_len = sizeof(struct sockaddr_bt);
		return rfcomm_peeraddr(pcb, sa);

	case PRU_CONNECT2:
	case PRU_SENDOOB:
	case PRU_FASTTIMO:
	case PRU_SLOWTIMO:
	case PRU_PROTORCV:
	case PRU_PROTOSEND:
		err = EOPNOTSUPP;
		break;

	default:
		UNKNOWN(req);
		err = EOPNOTSUPP;
		break;
	}

release:
	if (m) m_freem(m);
	if (ctl) m_freem(ctl);
	return err;
}
Пример #10
0
struct session_data *session_create(const char *source,
			const char *destination, const char *target,
			uint8_t channel, session_callback_t function,
			void *user_data)
{
	struct session_data *session;
	struct callback_data *callback;
	int err;

	if (destination == NULL)
		return NULL;

	session = g_try_malloc0(sizeof(*session));
	if (session == NULL)
		return NULL;

	session->refcount = 1;
	session->channel = channel;

	session->conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
	if (session->conn == NULL) {
		session_free(session);
		return NULL;
	}

	if (source == NULL)
		bacpy(&session->src, BDADDR_ANY);
	else
		str2ba(source, &session->src);

	str2ba(destination, &session->dst);

	if (!g_ascii_strncasecmp(target, "OPP", 3)) {
		sdp_uuid16_create(&session->uuid, OBEX_OBJPUSH_SVCLASS_ID);
	} else if (!g_ascii_strncasecmp(target, "FTP", 3)) {
		sdp_uuid16_create(&session->uuid, OBEX_FILETRANS_SVCLASS_ID);
		session->target = OBEX_FTP_UUID;
		session->target_len = OBEX_FTP_UUID_LEN;
	} else if (!g_ascii_strncasecmp(target, "PBAP", 4)) {
		sdp_uuid16_create(&session->uuid, PBAP_PSE_SVCLASS_ID);
		session->target = OBEX_PBAP_UUID;
		session->target_len = OBEX_PBAP_UUID_LEN;
	} else if (!g_ascii_strncasecmp(target, "SYNC", 4)) {
		sdp_uuid16_create(&session->uuid, IRMC_SYNC_SVCLASS_ID);
		session->target = OBEX_SYNC_UUID;
		session->target_len = OBEX_SYNC_UUID_LEN;
	} else if (!g_ascii_strncasecmp(target, "PCSUITE", 7)) {
		sdp_uuid128_create(&session->uuid, pcsuite_uuid);
	} else {
		return NULL;
	}

	callback = g_try_malloc0(sizeof(*callback));
	if (callback == NULL) {
		session_free(session);
		return NULL;
	}

	callback->session = session_ref(session);
	callback->func = function;
	callback->data = user_data;

	if (session->channel > 0) {
		session->io = rfcomm_connect(&session->src, &session->dst,
							session->channel,
							rfcomm_callback,
							callback);
		err = (session->io == NULL) ? -EINVAL : 0;
	} else {
		callback->sdp = service_connect(&session->src, &session->dst,
						service_callback, callback);
		err = (callback->sdp == NULL) ? -ENOMEM : 0;
	}

	if (err < 0) {
		session_free(session);
		g_free(callback);
		return NULL;
	}

	return session;
}
Пример #11
0
static void search_callback(uint8_t type, uint16_t status,
			uint8_t *rsp, size_t size, void *user_data)
{
	struct callback_data *callback = user_data;
	unsigned int scanned, bytesleft = size;
	int seqlen = 0;
	uint8_t dataType, channel = 0;
	GError *gerr = NULL;

	if (status || type != SDP_SVC_SEARCH_ATTR_RSP)
		goto failed;

	scanned = sdp_extract_seqtype(rsp, bytesleft, &dataType, &seqlen);
	if (!scanned || !seqlen)
		goto failed;

	rsp += scanned;
	bytesleft -= scanned;
	do {
		sdp_record_t *rec;
		sdp_list_t *protos;
		int recsize, ch = -1;

		recsize = 0;
		rec = sdp_extract_pdu(rsp, bytesleft, &recsize);
		if (!rec)
			break;

		if (!recsize) {
			sdp_record_free(rec);
			break;
		}

		if (!sdp_get_access_protos(rec, &protos)) {
			ch = sdp_get_proto_port(protos, RFCOMM_UUID);
			sdp_list_foreach(protos,
					(sdp_list_func_t) sdp_list_free, NULL);
			sdp_list_free(protos, NULL);
			protos = NULL;
		}

		sdp_record_free(rec);

		if (ch > 0) {
			channel = ch;
			break;
		}

		scanned += recsize;
		rsp += recsize;
		bytesleft -= recsize;
	} while (scanned < size && bytesleft > 0);

	if (channel == 0)
		goto failed;

	callback->session->channel = channel;

	callback->session->io = rfcomm_connect(&callback->session->src,
						&callback->session->dst,
						channel, rfcomm_callback,
						callback);
	if (callback->session->io != NULL) {
		sdp_close(callback->sdp);
		return;
	}

failed:
	sdp_close(callback->sdp);

	g_set_error(&gerr, OBEX_IO_ERROR, -EIO,
					"Unable to find service record");
	callback->func(callback->session, gerr, callback->data);
	g_clear_error(&gerr);

	session_unref(callback->session);
	g_free(callback);
}
Пример #12
0
int celluon_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
{
	unsigned char buf[16];
	struct sigaction sa;
	struct pollfd p;
	sigset_t sigs;
	char addr[18];
	int i, fd, sk, len;
	struct celluon_state s;

	sk = rfcomm_connect(src, dst, channel);
	if (sk < 0)
		return -1;

	fd = uinput_create("Celluon Keyboard", 1, 0);
	if (fd < 0) {
		close(sk);
		return -1;
	}

	ba2str(dst, addr);

	printf("Connected to %s on channel %d\n", addr, channel);
	printf("Press CTRL-C for hangup\n");

	memset(&sa, 0, sizeof(sa));
	sa.sa_flags   = SA_NOCLDSTOP;
	sa.sa_handler = SIG_IGN;
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);

	sa.sa_handler = sig_term;
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT,  &sa, NULL);

	sa.sa_handler = sig_hup;
	sigaction(SIGHUP, &sa, NULL);

	sigfillset(&sigs);
	sigdelset(&sigs, SIGCHLD);
	sigdelset(&sigs, SIGPIPE);
	sigdelset(&sigs, SIGTERM);
	sigdelset(&sigs, SIGINT);
	sigdelset(&sigs, SIGHUP);

	p.fd = sk;
	p.events = POLLIN | POLLERR | POLLHUP;

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

	while (!__io_canceled) {
		p.revents = 0;
		if (ppoll(&p, 1, NULL, &sigs) < 1)
			continue;

		len = read(sk, buf, sizeof(buf));
		if (len < 0)
			break;

		for (i = 0; i < len; i++)
			celluon_decode(fd, &s, buf[i]);
	}

	printf("Disconnected\n");

	ioctl(fd, UI_DEV_DESTROY);

	close(fd);
	close(sk);

	return 0;
}
Пример #13
0
int main(int argc, char *argv[])
{
	struct sigaction sa;

	fd_set rfds;
	struct timeval timeout;
	unsigned char buf[2048], *p;
	unsigned char cmp[2048];
	int maxfd, sel, wlen, rlen;
	int cnt=0;
	bdaddr_t local;
	bdaddr_t bdaddr;
	uint8_t channel;
	uint8_t hcidevno;

	char *infilename;
	char *outfilename;
	mode_t infilemode;
	mode_t outfilemode;
  	int scostarted=0;	
	int mode = 0;
	int dd, rd, sd, fdi, fdo;
	uint16_t sco_handle, sco_mtu, vs;

	switch (argc) {
	case 5:
		str2ba(argv[4], &bdaddr);
		channel = 1;
		hcidevno = 0;
		break;
	case 6:
		str2ba(argv[4], &bdaddr);
		channel = atoi(argv[5]);
		hcidevno = atoi(argv[1]);
		break;
	default:
		usage();
		exit(-1);
	}

	infilemode = O_RDONLY;
	outfilemode = O_WRONLY | O_CREAT | O_TRUNC;

	infilename = argv[2];
	outfilename = argv[3];

	hci_devba(0, &local);
	dd = hci_open_dev(hcidevno);
	hci_read_voice_setting(dd, &vs, 1000);
	vs = htobs(vs);
	printf("Voice setting: 0x%04x\n", vs);
	close(dd);
	if (vs != 0x0060) {
		perror("The voice setting must be 0x0060!\n");
		return -1;
	}
	
	// Hack by KF to enable realtime audio eavesdropping. Use stdout and pipe to sox. (see usage)
	if(strcmp(outfilename,"-") == 0)
	{	
		printf("Using stdout!");
		fdo = 1;
	}
	else
	{
		if ((fdo = open(outfilename, outfilemode)) < 0) {
			perror("Can't open output file!");
			return -1;
		}
	}

	if ((fdi = open(infilename, infilemode)) < 0) {
		perror("Can't open input file!");
		return -1;
	}
	
	memset(&sa, 0, sizeof(sa));
	sa.sa_flags = SA_NOCLDSTOP;
	sa.sa_handler = sig_term;
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT,  &sa, NULL);

	sa.sa_handler = SIG_IGN;
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);

	if ((rd = rfcomm_connect(&local, &bdaddr, channel)) < 0) {
		perror("Can't connect RFCOMM channel!");
		return -1;
	}

	printf("RFCOMM channel connected\n");
	
	// It is important that the RING message is sent before the SCO connection is established.
	// This way, the audio sent is interpreted as in-band ringtone and is displayed in most cases
	// immediately.
	
	// send 'RING' message in order to initiate fake phone call 
	wlen = write(rd, "RING\r\n", 6);
	
	usleep(1000);

	if ((sd = sco_connect(&local, &bdaddr, &sco_handle, &sco_mtu)) < 0) {
		perror("Can't connect SCO audio channel!");
		close(rd);
		return -1;
	}

	printf("SCO audio channel connected (handle %d, mtu %d)\n", sco_handle, sco_mtu);

	// wait for connection to be fully established
//	usleep(200);

	// turn up the speaker volume and the microphone gain to the highest level
	wlen = write(rd, "AT+VGS=15\r\n", 11);
	wlen = write(rd, "AT+VGM=15\r\n", 11);
	
	// send 'RING' message in order to initiate fake phone call 
	wlen = write(rd, "RING\r\n", 6);


	maxfd = (rd > sd) ? rd : sd;

	while (!terminate) {

		FD_ZERO(&rfds);
		FD_SET(rd, &rfds);
		FD_SET(sd, &rfds);

		timeout.tv_sec = 2;
		timeout.tv_usec = 0;

		if ((sel = select(maxfd + 1, &rfds, NULL, NULL, &timeout)) > 0) {
		
			if ((FD_ISSET(rd, &rfds))&&(scostarted!=0)) {
				memset(buf, 0, sizeof(buf));
				rlen = read(rd, buf, sizeof(buf));
				//buf[rlen++] = '\0';
				if (rlen > 0) {
					fprintf(stderr, "got:  %s\n",buf);
                                        if (strncmp(buf, "AT+BRSF=",8)==0) {
						wlen=write(rd,"+BRSF: 63\r\n",11);
						fprintf(stderr, "ansewered:  +BRSF: 63\n");
					} else if (strncmp(buf, "AT+CIND?",8)==0) { 
						wlen=write(rd,"+CIND: 0,1,0,0\r\n",16);
						fprintf(stderr, "ansewered: +CIND: 1\n");
					} else if (strncmp(buf, "AT+CIND=?",9)==0) { 
						wlen=write(rd,"+CIND: (\"call\",(0,1)),(\"service\",(0,1)),(\"call_setup\",(0-3)),(\"callsetup\",(0-3))\r\n",82);
						fprintf(stderr, "ansewered: +CIND: (\"call\",(0,1)),(\"service\",(0,1)),(\"call_setup\",(0-3)),(\"callsetup\",(0-3))\n");
					} else {
						// answer to anything else with an 'OK'
						wlen = write(rd, "OK\r\n", 4);
						fprintf(stderr, "ansewered:  OK\n");
					}
				} else {
					// check return value of read call
					if (rlen==-1) {
						// terminate loop
						wlen = write(rd, "AT+VGM=15\r\n", 11);
						terminate=1;
					}
				}
			}
			
			if (FD_ISSET(sd, &rfds)) {
				scostarted=1;
				memset(buf, 0, sizeof(buf));
				rlen = read(sd, buf, sizeof(buf));
				if (rlen > 0) {
					wlen = write(fdo, buf, rlen);
					rlen = read(fdi, buf, rlen);
					wlen = 0; 
					if (rlen > 0) p = buf;
					while (rlen > sco_mtu) {
					        wlen += write(sd, p, sco_mtu);
					        rlen -= sco_mtu;
					        p += sco_mtu;
					}
					wlen += write(sd, p, rlen);
				}
			}
			if (cnt++>800) {

				// keep tuning up the volume for speaker and microphone
				wlen = write(rd, "RING\r\n", 6);
				wlen = write(rd, "AT+VGS=15\r\n", 11);
				wlen = write(rd, "AT+VGM=15\r\n", 11);
				cnt=0;
				printf(".\n");
			}
		}
	}

	// close sockets 
	close(sd);
	close(rd);

	// close files
	close(fdi);
	close(fdo);

	return 0;
}