xref: /netbsd-src/share/examples/rump/ttyserv/ttyserv.c (revision d35b86acad83e0ac06b9bb041ea23ab3c4f42d20)
1*d35b86acSpooka /*	$NetBSD: ttyserv.c,v 1.3 2016/01/25 11:45:58 pooka Exp $	*/
260ab2ca5Spooka 
360ab2ca5Spooka /*
460ab2ca5Spooka  * Copyright (c) 2009, 2010 Antti Kantee.  All Rights Reserved.
560ab2ca5Spooka  *
660ab2ca5Spooka  * Redistribution and use in source and binary forms, with or without
760ab2ca5Spooka  * modification, are permitted provided that the following conditions
860ab2ca5Spooka  * are met:
960ab2ca5Spooka  * 1. Redistributions of source code must retain the above copyright
1060ab2ca5Spooka  *    notice, this list of conditions and the following disclaimer.
1160ab2ca5Spooka  * 2. Redistributions in binary form must reproduce the above copyright
1260ab2ca5Spooka  *    notice, this list of conditions and the following disclaimer in the
1360ab2ca5Spooka  *    documentation and/or other materials provided with the distribution.
1460ab2ca5Spooka  *
1560ab2ca5Spooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
1660ab2ca5Spooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1760ab2ca5Spooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1860ab2ca5Spooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1960ab2ca5Spooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2060ab2ca5Spooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2160ab2ca5Spooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2260ab2ca5Spooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2360ab2ca5Spooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2460ab2ca5Spooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2560ab2ca5Spooka  * SUCH DAMAGE.
2660ab2ca5Spooka  */
2760ab2ca5Spooka 
2860ab2ca5Spooka /*
2960ab2ca5Spooka  * This is a [quick, simple & dirty] userspace tty/ucom server.
3060ab2ca5Spooka  * We probe USB devices using rump and attach them to the host kernel
3160ab2ca5Spooka  * using pud(4).
3260ab2ca5Spooka  */
3360ab2ca5Spooka 
3460ab2ca5Spooka #include <sys/types.h>
3560ab2ca5Spooka #include <sys/syslimits.h>
3660ab2ca5Spooka 
3760ab2ca5Spooka #include <dev/pud/pud_msgif.h>
3860ab2ca5Spooka 
3960ab2ca5Spooka #include <rump/rump.h>
40*d35b86acSpooka #include <rump/rumpvnode_if.h>
4160ab2ca5Spooka 
4260ab2ca5Spooka #include <assert.h>
4360ab2ca5Spooka #include <err.h>
4460ab2ca5Spooka #include <errno.h>
4560ab2ca5Spooka #include <fcntl.h>
4660ab2ca5Spooka #include <paths.h>
4760ab2ca5Spooka #include <pthread.h>
4860ab2ca5Spooka #include <stdio.h>
4960ab2ca5Spooka #include <stdlib.h>
5060ab2ca5Spooka #include <string.h>
5160ab2ca5Spooka #include <unistd.h>
5260ab2ca5Spooka 
5360ab2ca5Spooka /*
5460ab2ca5Spooka  * No devfs?  No problem.  We just hack a bit & wait for the dust to settle.
5560ab2ca5Spooka  */
5660ab2ca5Spooka #define MYMAJOR 412
5760ab2ca5Spooka static int
makenodes(void)5860ab2ca5Spooka makenodes(void)
5960ab2ca5Spooka {
6060ab2ca5Spooka 	struct stat sb;
6160ab2ca5Spooka 	int rv;
6260ab2ca5Spooka 
6360ab2ca5Spooka 	if (stat("rumpttyU0", &sb) != 0)
6460ab2ca5Spooka 		rv = mknod("rumpttyU0", S_IFCHR | 0666, makedev(MYMAJOR, 0));
6560ab2ca5Spooka 	if (rv != 0 && !(rv == -1 && errno == EEXIST))
6660ab2ca5Spooka 		return rv;
6760ab2ca5Spooka 
6860ab2ca5Spooka 	if (stat("rumpttyU1", &sb) != 0)
6960ab2ca5Spooka 		rv = mknod("rumpttyU1", S_IFCHR | 0666, makedev(MYMAJOR, 1));
7060ab2ca5Spooka 	if (rv != 0 && !(rv == -1 && errno == EEXIST))
7160ab2ca5Spooka 		return rv;
7260ab2ca5Spooka 
7360ab2ca5Spooka 	return 0;
7460ab2ca5Spooka }
7560ab2ca5Spooka 
7660ab2ca5Spooka static struct vnode *devvps[2];
7760ab2ca5Spooka static kauth_cred_t rootcred;
7860ab2ca5Spooka static int fd;
7960ab2ca5Spooka 
8060ab2ca5Spooka static void *
handlereq(void * arg)8160ab2ca5Spooka handlereq(void *arg)
8260ab2ca5Spooka {
8360ab2ca5Spooka 	struct vnode *devvp;
8460ab2ca5Spooka 	struct pud_creq_open *pr_open;
8560ab2ca5Spooka 	struct pud_creq_close *pr_close;
8660ab2ca5Spooka 	struct pud_req_readwrite *pr_rw;
8760ab2ca5Spooka 	struct pud_req_ioctl *pr_ioctl;
8860ab2ca5Spooka 	struct uio *uio;
8960ab2ca5Spooka 	size_t reslen;
9060ab2ca5Spooka 	struct pud_req *pdr = arg;
9160ab2ca5Spooka 	int minordev, rv;
9260ab2ca5Spooka 	ssize_t n;
9360ab2ca5Spooka 
9460ab2ca5Spooka 	minordev = minor(pdr->pdr_dev);
9560ab2ca5Spooka 	if (minordev < 0 || minordev >= 8) {
9660ab2ca5Spooka 		rv = ENXIO;
9760ab2ca5Spooka 		goto sendresponse;
9860ab2ca5Spooka 	}
9960ab2ca5Spooka 	devvp = devvps[minordev];
10060ab2ca5Spooka 
10160ab2ca5Spooka 	switch (pdr->pdr_reqtype) {
10260ab2ca5Spooka 	case PUD_CDEV_OPEN:
10360ab2ca5Spooka 		pr_open = (void *)pdr;
10460ab2ca5Spooka 		RUMP_VOP_LOCK(devvp, RUMP_LK_EXCLUSIVE);
10560ab2ca5Spooka 		rv = RUMP_VOP_OPEN(devvp, pr_open->pm_fmt, rootcred);
1061423e65bShannken 		RUMP_VOP_UNLOCK(devvp);
10760ab2ca5Spooka 		break;
10860ab2ca5Spooka 
10960ab2ca5Spooka 	case PUD_CDEV_CLOSE:
11060ab2ca5Spooka 		pr_close = (void *)pdr;
11160ab2ca5Spooka 		RUMP_VOP_LOCK(devvp, RUMP_LK_EXCLUSIVE);
11260ab2ca5Spooka 		rv = RUMP_VOP_CLOSE(devvp, pr_close->pm_fmt, rootcred);
1131423e65bShannken 		RUMP_VOP_UNLOCK(devvp);
11460ab2ca5Spooka 		break;
11560ab2ca5Spooka 
11660ab2ca5Spooka 	case PUD_CDEV_IOCTL:
11760ab2ca5Spooka 		pr_ioctl = (void *)pdr;
11860ab2ca5Spooka 		rv = RUMP_VOP_IOCTL(devvp, pr_ioctl->pm_iocmd,
11960ab2ca5Spooka 		    pr_ioctl->pm_data, pr_ioctl->pm_flag, rootcred);
12060ab2ca5Spooka 		break;
12160ab2ca5Spooka 
12260ab2ca5Spooka 	case PUD_CDEV_READ:
12360ab2ca5Spooka 		pr_rw = (void *)pdr;
12460ab2ca5Spooka 		assert(pr_rw->pm_resid <= 64*1024);
12560ab2ca5Spooka 		uio = rump_pub_uio_setup(&pr_rw->pm_data[0],
12660ab2ca5Spooka 		    pr_rw->pm_resid, pr_rw->pm_offset, RUMPUIO_READ);
12760ab2ca5Spooka 		RUMP_VOP_LOCK(devvp, RUMP_LK_SHARED);
12860ab2ca5Spooka 		rv = RUMP_VOP_READ(devvp, uio, 0, rootcred);
1291423e65bShannken 		RUMP_VOP_UNLOCK(devvp);
13060ab2ca5Spooka 		reslen = rump_pub_uio_free(uio);
13160ab2ca5Spooka 		pdr->pdr_pth.pth_framelen -= reslen;
13260ab2ca5Spooka 		pr_rw->pm_resid = reslen;
13360ab2ca5Spooka 		break;
13460ab2ca5Spooka 
13560ab2ca5Spooka 	case PUD_CDEV_WRITE:
13660ab2ca5Spooka 		pr_rw = (void *)pdr;
13760ab2ca5Spooka 		uio = rump_pub_uio_setup(&pr_rw->pm_data[0],
13860ab2ca5Spooka 		    pr_rw->pm_resid, pr_rw->pm_offset, RUMPUIO_WRITE);
13960ab2ca5Spooka 		RUMP_VOP_LOCK(devvp, RUMP_LK_EXCLUSIVE);
14060ab2ca5Spooka 		rv = RUMP_VOP_WRITE(devvp, uio, 0, rootcred);
1411423e65bShannken 		RUMP_VOP_UNLOCK(devvp);
14260ab2ca5Spooka 		reslen = rump_pub_uio_free(uio);
14360ab2ca5Spooka 		pr_rw->pm_resid = reslen;
14460ab2ca5Spooka 		pdr->pdr_pth.pth_framelen=sizeof(struct pud_creq_write);
14560ab2ca5Spooka 		rv = 0;
14660ab2ca5Spooka 		break;
14760ab2ca5Spooka 	default:
14860ab2ca5Spooka 		printf("unknown request %d\n", pdr->pdr_reqtype);
14960ab2ca5Spooka 		abort();
15060ab2ca5Spooka 	}
15160ab2ca5Spooka 
15260ab2ca5Spooka sendresponse:
15360ab2ca5Spooka 	printf("result %d\n", rv);
15460ab2ca5Spooka 	pdr->pdr_rv = rv;
15560ab2ca5Spooka 	n = write(fd, pdr, pdr->pdr_pth.pth_framelen);
15660ab2ca5Spooka 	assert(n == (ssize_t)pdr->pdr_pth.pth_framelen);
15760ab2ca5Spooka 
15860ab2ca5Spooka 	pthread_exit(NULL);
15960ab2ca5Spooka }
16060ab2ca5Spooka 
16160ab2ca5Spooka int
main(int argc,char * argv[])16260ab2ca5Spooka main(int argc, char *argv[])
16360ab2ca5Spooka {
16460ab2ca5Spooka 	struct pud_conf_reg pcr;
16560ab2ca5Spooka 	struct pud_req *pdr;
16660ab2ca5Spooka 	ssize_t n;
16760ab2ca5Spooka 	int rv;
16860ab2ca5Spooka 
16960ab2ca5Spooka 	if (makenodes() == -1)
17060ab2ca5Spooka 		err(1, "makenodes");
17160ab2ca5Spooka 
17260ab2ca5Spooka 	fd = open(_PATH_PUD, O_RDWR);
17360ab2ca5Spooka 	if (fd == -1)
17460ab2ca5Spooka 		err(1, "open");
17560ab2ca5Spooka 
17660ab2ca5Spooka 	memset(&pcr, 0, sizeof(pcr));
17760ab2ca5Spooka 	pcr.pm_pdr.pdr_pth.pth_framelen = sizeof(struct pud_conf_reg);
17860ab2ca5Spooka 	pcr.pm_version = PUD_DEVELVERSION | PUD_VERSION;
17960ab2ca5Spooka 	pcr.pm_pdr.pdr_reqclass = PUD_REQ_CONF;
18060ab2ca5Spooka 	pcr.pm_pdr.pdr_reqtype = PUD_CONF_REG;
18160ab2ca5Spooka 
18260ab2ca5Spooka 	pcr.pm_regdev = makedev(MYMAJOR, 0);
18360ab2ca5Spooka 	pcr.pm_flags = PUD_CONFFLAG_BDEV;
18460ab2ca5Spooka 	strlcpy(pcr.pm_devname, "youmass", sizeof(pcr.pm_devname));
18560ab2ca5Spooka 
18660ab2ca5Spooka 	n = write(fd, &pcr, pcr.pm_pdr.pdr_pth.pth_framelen);
18760ab2ca5Spooka 	if (n == -1)
18860ab2ca5Spooka 		err(1, "configure"); /* XXX: doubles as protocol error */
18960ab2ca5Spooka 
19060ab2ca5Spooka 	rump_boot_sethowto(RUMP_AB_VERBOSE);
19160ab2ca5Spooka 	rump_init();
19260ab2ca5Spooka 
19360ab2ca5Spooka 	if ((rv = rump_pub_namei(RUMP_NAMEI_LOOKUP, 0, "/dev/ttyU0",
19460ab2ca5Spooka 	    NULL, &devvps[0], NULL)) != 0)
19560ab2ca5Spooka 		errx(1, "raw device 0 lookup failed %d", rv);
19660ab2ca5Spooka 	if ((rv = rump_pub_namei(RUMP_NAMEI_LOOKUP, 0, "/dev/ttyU1",
19760ab2ca5Spooka 	    NULL, &devvps[1], NULL)) != 0)
19860ab2ca5Spooka 		errx(1, "raw device 1 lookup failed %d", rv);
19960ab2ca5Spooka 
20060ab2ca5Spooka 	rootcred = rump_pub_cred_create(0, 0, 0, NULL);
20160ab2ca5Spooka 
20260ab2ca5Spooka 	/* process requests ad infinitum */
20360ab2ca5Spooka 	for (;;) {
20460ab2ca5Spooka 		pthread_t pt;
20560ab2ca5Spooka 
20660ab2ca5Spooka #define PDRSIZE (64*1024+1024)
20760ab2ca5Spooka 		pdr = malloc(PDRSIZE);
20860ab2ca5Spooka 		if (pdr == NULL)
20960ab2ca5Spooka 			err(1, "malloc");
21060ab2ca5Spooka 
21160ab2ca5Spooka 		n = read(fd, pdr, PDRSIZE);
21260ab2ca5Spooka 		if (n == -1)
21360ab2ca5Spooka 			err(1, "read");
21460ab2ca5Spooka 
21560ab2ca5Spooka 		/*
21660ab2ca5Spooka 		 * tip & cu fork and read/write at the same time.  hence,
21760ab2ca5Spooka 		 * we need a multithreaded server as otherwise read requests
21860ab2ca5Spooka 		 * will block eternally since no writes can be done.
21960ab2ca5Spooka 		 *
22060ab2ca5Spooka 		 * XXX: do this properly (detached threads, or pool)
22160ab2ca5Spooka 		 */
22260ab2ca5Spooka 		pthread_create(&pt, NULL, handlereq, pdr);
22360ab2ca5Spooka 	}
22460ab2ca5Spooka }
225