qcom: Add userspace tools to talk to dsp and modem

cherry-picked from upstream device/linaro/dragonboard project.

Add Qcom userspace tools and their respective sepolicy rules.

Userspace tools are downloaded from following github:

To trigger loading of wlan firmware on SDM845
git clone https://github.com/andersson/pd-mapper

Userspace reference for net/qrtr in the Linux kernel
git clone https://github.com/andersson/qrtr

Qualcomm Remote Filesystem Service Implementation
git clone https://github.com/andersson/rmtfs

Trivial File Transfer Protocol server over AF_QIPCRTR
git clone https://github.com/andersson/tqftpserv

Change-Id: Ic466af6fef010a9b71c90e38205f49a876b001e2
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Amit Pundir <pundiramit@gmail.com>
diff --git a/qcom/qrtr/src/waiter.c b/qcom/qrtr/src/waiter.c
new file mode 100644
index 0000000..f21896f
--- /dev/null
+++ b/qcom/qrtr/src/waiter.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2013-2014, Sony Mobile Communications Inc.
+ * Copyright (c) 2014, Courtney Cavin
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  - Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright notice,
+ *  this list of conditions and the following disclaimer in the documentation
+ *  and/or other materials provided with the distribution.
+ *
+ *  - Neither the name of the organization nor the names of its contributors
+ *  may be used to endorse or promote products derived from this software
+ *  without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <poll.h>
+
+#include "list.h"
+#include "waiter.h"
+#include "util.h"
+
+struct pollset {
+	int nfds;
+	int cause;
+};
+
+static struct pollset *pollset_create(int count)
+{
+	struct pollset *ps;
+
+	ps = calloc(1, sizeof(*ps) + sizeof(struct pollfd) * count);
+	if (ps == NULL)
+		return NULL;
+
+	return ps;
+}
+
+static void pollset_destroy(struct pollset *ps)
+{
+	free(ps);
+}
+
+static void pollset_reset(struct pollset *ps)
+{
+	ps->nfds = 0;
+}
+
+static void pollset_add_fd(struct pollset *ps, int fd)
+{
+	struct pollfd *pfd = (struct pollfd *)(ps + 1);
+	pfd[ps->nfds].fd = fd;
+	pfd[ps->nfds].events = POLLERR | POLLIN;
+	ps->nfds++;
+}
+
+static int pollset_wait(struct pollset *ps, int ms)
+{
+	struct pollfd *pfd = (struct pollfd *)(ps + 1);
+	int rc;
+	int i;
+
+	rc = poll(pfd, ps->nfds, ms);
+	if (rc <= 0)
+		return rc;
+
+	ps->cause = -1;
+	for (i = 0; i < ps->nfds; ++i) {
+		if (pfd[i].revents & (POLLERR | POLLIN)) {
+			ps->cause = i;
+			break;
+		}
+	}
+	return rc;
+
+}
+
+static int pollset_cause_fd(struct pollset *ps, int fd)
+{
+	struct pollfd *pfd = (struct pollfd *)(ps + 1);
+	return (ps->cause >= 0 && pfd[ps->cause].fd == fd);
+}
+
+enum waiter_type {
+	WATCH_TYPE_NULL,
+	WATCH_TYPE_FD,
+	WATCH_TYPE_TIMEOUT,
+};
+
+struct waiter_ticket {
+	enum waiter_type type;
+	union {
+		int filedes;
+		unsigned int event;
+		unsigned int interval;
+	};
+	struct {
+		void (* fn)(void *data, struct waiter_ticket *);
+		void *data;
+	} callback;
+
+	uint64_t start;
+	int updated;
+	struct waiter *waiter;
+	struct list_item list_item;
+};
+
+struct waiter {
+	struct list tickets;
+	struct pollset *pollset;
+	int count;
+};
+
+struct waiter *waiter_create(void)
+{
+	struct waiter *w;
+
+	w = calloc(1, sizeof(*w));
+	if (w == NULL)
+		return NULL;
+
+	list_init(&w->tickets);
+	return w;
+}
+
+void waiter_destroy(struct waiter *w)
+{
+	struct waiter_ticket *ticket;
+	struct list_item *safe;
+	struct list_item *node;
+
+	list_for_each_safe(&w->tickets, node, safe) {
+		ticket = list_entry(node, struct waiter_ticket, list_item);
+		free(ticket);
+	}
+
+	if (w->pollset)
+		pollset_destroy(w->pollset);
+	free(w);
+}
+
+void waiter_synchronize(struct waiter *w)
+{
+	struct waiter_ticket *oticket;
+	struct waiter_ticket *ticket;
+	struct list_item *node;
+
+	list_for_each(&w->tickets, node) {
+		struct list_item *onode;
+		ticket = list_entry(node, struct waiter_ticket, list_item);
+
+		if (ticket->type != WATCH_TYPE_TIMEOUT)
+			continue;
+
+		list_for_each_after(node, onode) {
+			oticket = list_entry(onode, struct waiter_ticket, list_item);
+			if (oticket->type != WATCH_TYPE_TIMEOUT)
+				continue;
+
+			if (oticket->interval == ticket->interval) {
+				oticket->start = ticket->start;
+				break;
+			}
+		}
+	}
+}
+
+void waiter_wait(struct waiter *w)
+{
+	struct pollset *ps = w->pollset;
+	struct waiter_ticket *ticket;
+	struct list_item *node;
+	uint64_t term_time;
+	uint64_t now;
+	int rc;
+
+	pollset_reset(ps);
+
+	term_time = (uint64_t)-1;
+	list_for_each(&w->tickets, node) {
+		ticket = list_entry(node, struct waiter_ticket, list_item);
+		switch (ticket->type) {
+		case WATCH_TYPE_TIMEOUT:
+			if (ticket->start + ticket->interval < term_time)
+				term_time = ticket->start + ticket->interval;
+			break;
+		case WATCH_TYPE_FD:
+			pollset_add_fd(ps, ticket->filedes);
+			break;
+		case WATCH_TYPE_NULL:
+			break;
+		}
+	}
+
+	if (term_time == (uint64_t)-1) { /* wait forever */
+		rc = pollset_wait(ps, -1);
+	} else {
+		now = time_ms();
+		if (now >= term_time) { /* already past timeout, skip poll */
+			rc = 0;
+		} else {
+			uint64_t delta;
+
+			delta = term_time - now;
+			if (delta > ((1u << 31) - 1))
+				delta = ((1u << 31) - 1);
+			rc = pollset_wait(ps, (int)delta);
+		}
+	}
+
+	if (rc < 0)
+		return;
+
+	now = time_ms();
+	list_for_each(&w->tickets, node) {
+		int fresh = 0;
+
+		ticket = list_entry(node, struct waiter_ticket, list_item);
+		switch (ticket->type) {
+		case WATCH_TYPE_TIMEOUT:
+			if (now >= ticket->start + ticket->interval) {
+				ticket->start = now;
+				fresh = !ticket->updated;
+			}
+			break;
+		case WATCH_TYPE_FD:
+			if (rc == 0) /* timed-out */
+				break;
+			if (pollset_cause_fd(ps, ticket->filedes))
+				fresh = !ticket->updated;
+			break;
+		case WATCH_TYPE_NULL:
+			break;
+		}
+		if (fresh) {
+			ticket->updated = 1;
+			if (ticket->callback.fn)
+				(* ticket->callback.fn)(
+						ticket->callback.data,
+						ticket
+				);
+		}
+	}
+}
+
+int waiter_wait_timeout(struct waiter *w, unsigned int ms)
+{
+	struct waiter_ticket ticket;
+	int rc;
+
+	memset(&ticket, 0, sizeof(ticket));
+	waiter_ticket_set_timeout(&ticket, ms);
+	list_append(&w->tickets, &ticket.list_item);
+	w->count++;
+
+	waiter_wait(w);
+	rc = waiter_ticket_check(&ticket);
+
+	list_remove(&w->tickets, &ticket.list_item);
+	w->count--;
+
+	return -!rc;
+}
+
+void waiter_ticket_set_null(struct waiter_ticket *ticket)
+{
+	ticket->type = WATCH_TYPE_NULL;
+}
+
+void waiter_ticket_set_fd(struct waiter_ticket *ticket, int fd)
+{
+	ticket->type = WATCH_TYPE_FD;
+	ticket->filedes = fd;
+}
+
+void waiter_ticket_set_timeout(struct waiter_ticket *ticket, unsigned int ms)
+{
+	ticket->type = WATCH_TYPE_TIMEOUT;
+	ticket->interval = ms;
+	ticket->start = time_ms();
+}
+
+struct waiter_ticket *waiter_add_null(struct waiter *w)
+{
+	struct waiter_ticket *ticket;
+
+	ticket = calloc(1, sizeof(*ticket));
+	if (ticket == NULL)
+		return NULL;
+	ticket->waiter = w;
+
+	list_append(&w->tickets, &ticket->list_item);
+	if ((w->count % 32) == 0) {
+		if (w->pollset)
+			pollset_destroy(w->pollset);
+		w->pollset = pollset_create(w->count + 33);
+		if (w->pollset == NULL)
+			return NULL;
+	}
+	w->count++;
+
+	waiter_ticket_set_null(ticket);
+
+	return ticket;
+}
+
+struct waiter_ticket *waiter_add_fd(struct waiter *w, int fd)
+{
+	struct waiter_ticket *ticket;
+
+	ticket = waiter_add_null(w);
+	if (ticket == NULL)
+		return NULL;
+
+	waiter_ticket_set_fd(ticket, fd);
+
+	return ticket;
+}
+
+struct waiter_ticket *waiter_add_timeout(struct waiter *w, unsigned int ms)
+{
+	struct waiter_ticket *ticket;
+
+	ticket = waiter_add_null(w);
+	if (ticket == NULL)
+		return NULL;
+
+	waiter_ticket_set_timeout(ticket, ms);
+
+	return ticket;
+}
+
+void waiter_ticket_delete(struct waiter_ticket *ticket)
+{
+	struct waiter *w = ticket->waiter;
+	list_remove(&w->tickets, &ticket->list_item);
+	w->count--;
+	free(ticket);
+}
+
+void waiter_ticket_callback(struct waiter_ticket *ticket, waiter_ticket_cb_t cb_fn, void *data)
+{
+	ticket->callback.fn = cb_fn;
+	ticket->callback.data = data;
+}
+
+int waiter_ticket_check(const struct waiter_ticket *ticket)
+{
+	return -(ticket->updated == 0);
+}
+
+int waiter_ticket_clear(struct waiter_ticket *ticket)
+{
+	int ret;
+
+	ret = waiter_ticket_check(ticket);
+	ticket->updated = 0;
+
+	return ret;
+}