1 1.3 pooka /* $NetBSD: ttyserv.c,v 1.3 2016/01/25 11:45:58 pooka Exp $ */ 2 1.1 pooka 3 1.1 pooka /* 4 1.1 pooka * Copyright (c) 2009, 2010 Antti Kantee. All Rights Reserved. 5 1.1 pooka * 6 1.1 pooka * Redistribution and use in source and binary forms, with or without 7 1.1 pooka * modification, are permitted provided that the following conditions 8 1.1 pooka * are met: 9 1.1 pooka * 1. Redistributions of source code must retain the above copyright 10 1.1 pooka * notice, this list of conditions and the following disclaimer. 11 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 pooka * notice, this list of conditions and the following disclaimer in the 13 1.1 pooka * documentation and/or other materials provided with the distribution. 14 1.1 pooka * 15 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 1.1 pooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 1.1 pooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 1.1 pooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 1.1 pooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 1.1 pooka * SUCH DAMAGE. 26 1.1 pooka */ 27 1.1 pooka 28 1.1 pooka /* 29 1.1 pooka * This is a [quick, simple & dirty] userspace tty/ucom server. 30 1.1 pooka * We probe USB devices using rump and attach them to the host kernel 31 1.1 pooka * using pud(4). 32 1.1 pooka */ 33 1.1 pooka 34 1.1 pooka #include <sys/types.h> 35 1.1 pooka #include <sys/syslimits.h> 36 1.1 pooka 37 1.1 pooka #include <dev/pud/pud_msgif.h> 38 1.1 pooka 39 1.1 pooka #include <rump/rump.h> 40 1.3 pooka #include <rump/rumpvnode_if.h> 41 1.1 pooka 42 1.1 pooka #include <assert.h> 43 1.1 pooka #include <err.h> 44 1.1 pooka #include <errno.h> 45 1.1 pooka #include <fcntl.h> 46 1.1 pooka #include <paths.h> 47 1.1 pooka #include <pthread.h> 48 1.1 pooka #include <stdio.h> 49 1.1 pooka #include <stdlib.h> 50 1.1 pooka #include <string.h> 51 1.1 pooka #include <unistd.h> 52 1.1 pooka 53 1.1 pooka /* 54 1.1 pooka * No devfs? No problem. We just hack a bit & wait for the dust to settle. 55 1.1 pooka */ 56 1.1 pooka #define MYMAJOR 412 57 1.1 pooka static int 58 1.1 pooka makenodes(void) 59 1.1 pooka { 60 1.1 pooka struct stat sb; 61 1.1 pooka int rv; 62 1.1 pooka 63 1.1 pooka if (stat("rumpttyU0", &sb) != 0) 64 1.1 pooka rv = mknod("rumpttyU0", S_IFCHR | 0666, makedev(MYMAJOR, 0)); 65 1.1 pooka if (rv != 0 && !(rv == -1 && errno == EEXIST)) 66 1.1 pooka return rv; 67 1.1 pooka 68 1.1 pooka if (stat("rumpttyU1", &sb) != 0) 69 1.1 pooka rv = mknod("rumpttyU1", S_IFCHR | 0666, makedev(MYMAJOR, 1)); 70 1.1 pooka if (rv != 0 && !(rv == -1 && errno == EEXIST)) 71 1.1 pooka return rv; 72 1.1 pooka 73 1.1 pooka return 0; 74 1.1 pooka } 75 1.1 pooka 76 1.1 pooka static struct vnode *devvps[2]; 77 1.1 pooka static kauth_cred_t rootcred; 78 1.1 pooka static int fd; 79 1.1 pooka 80 1.1 pooka static void * 81 1.1 pooka handlereq(void *arg) 82 1.1 pooka { 83 1.1 pooka struct vnode *devvp; 84 1.1 pooka struct pud_creq_open *pr_open; 85 1.1 pooka struct pud_creq_close *pr_close; 86 1.1 pooka struct pud_req_readwrite *pr_rw; 87 1.1 pooka struct pud_req_ioctl *pr_ioctl; 88 1.1 pooka struct uio *uio; 89 1.1 pooka size_t reslen; 90 1.1 pooka struct pud_req *pdr = arg; 91 1.1 pooka int minordev, rv; 92 1.1 pooka ssize_t n; 93 1.1 pooka 94 1.1 pooka minordev = minor(pdr->pdr_dev); 95 1.1 pooka if (minordev < 0 || minordev >= 8) { 96 1.1 pooka rv = ENXIO; 97 1.1 pooka goto sendresponse; 98 1.1 pooka } 99 1.1 pooka devvp = devvps[minordev]; 100 1.1 pooka 101 1.1 pooka switch (pdr->pdr_reqtype) { 102 1.1 pooka case PUD_CDEV_OPEN: 103 1.1 pooka pr_open = (void *)pdr; 104 1.1 pooka RUMP_VOP_LOCK(devvp, RUMP_LK_EXCLUSIVE); 105 1.1 pooka rv = RUMP_VOP_OPEN(devvp, pr_open->pm_fmt, rootcred); 106 1.2 hannken RUMP_VOP_UNLOCK(devvp); 107 1.1 pooka break; 108 1.1 pooka 109 1.1 pooka case PUD_CDEV_CLOSE: 110 1.1 pooka pr_close = (void *)pdr; 111 1.1 pooka RUMP_VOP_LOCK(devvp, RUMP_LK_EXCLUSIVE); 112 1.1 pooka rv = RUMP_VOP_CLOSE(devvp, pr_close->pm_fmt, rootcred); 113 1.2 hannken RUMP_VOP_UNLOCK(devvp); 114 1.1 pooka break; 115 1.1 pooka 116 1.1 pooka case PUD_CDEV_IOCTL: 117 1.1 pooka pr_ioctl = (void *)pdr; 118 1.1 pooka rv = RUMP_VOP_IOCTL(devvp, pr_ioctl->pm_iocmd, 119 1.1 pooka pr_ioctl->pm_data, pr_ioctl->pm_flag, rootcred); 120 1.1 pooka break; 121 1.1 pooka 122 1.1 pooka case PUD_CDEV_READ: 123 1.1 pooka pr_rw = (void *)pdr; 124 1.1 pooka assert(pr_rw->pm_resid <= 64*1024); 125 1.1 pooka uio = rump_pub_uio_setup(&pr_rw->pm_data[0], 126 1.1 pooka pr_rw->pm_resid, pr_rw->pm_offset, RUMPUIO_READ); 127 1.1 pooka RUMP_VOP_LOCK(devvp, RUMP_LK_SHARED); 128 1.1 pooka rv = RUMP_VOP_READ(devvp, uio, 0, rootcred); 129 1.2 hannken RUMP_VOP_UNLOCK(devvp); 130 1.1 pooka reslen = rump_pub_uio_free(uio); 131 1.1 pooka pdr->pdr_pth.pth_framelen -= reslen; 132 1.1 pooka pr_rw->pm_resid = reslen; 133 1.1 pooka break; 134 1.1 pooka 135 1.1 pooka case PUD_CDEV_WRITE: 136 1.1 pooka pr_rw = (void *)pdr; 137 1.1 pooka uio = rump_pub_uio_setup(&pr_rw->pm_data[0], 138 1.1 pooka pr_rw->pm_resid, pr_rw->pm_offset, RUMPUIO_WRITE); 139 1.1 pooka RUMP_VOP_LOCK(devvp, RUMP_LK_EXCLUSIVE); 140 1.1 pooka rv = RUMP_VOP_WRITE(devvp, uio, 0, rootcred); 141 1.2 hannken RUMP_VOP_UNLOCK(devvp); 142 1.1 pooka reslen = rump_pub_uio_free(uio); 143 1.1 pooka pr_rw->pm_resid = reslen; 144 1.1 pooka pdr->pdr_pth.pth_framelen=sizeof(struct pud_creq_write); 145 1.1 pooka rv = 0; 146 1.1 pooka break; 147 1.1 pooka default: 148 1.1 pooka printf("unknown request %d\n", pdr->pdr_reqtype); 149 1.1 pooka abort(); 150 1.1 pooka } 151 1.1 pooka 152 1.1 pooka sendresponse: 153 1.1 pooka printf("result %d\n", rv); 154 1.1 pooka pdr->pdr_rv = rv; 155 1.1 pooka n = write(fd, pdr, pdr->pdr_pth.pth_framelen); 156 1.1 pooka assert(n == (ssize_t)pdr->pdr_pth.pth_framelen); 157 1.1 pooka 158 1.1 pooka pthread_exit(NULL); 159 1.1 pooka } 160 1.1 pooka 161 1.1 pooka int 162 1.1 pooka main(int argc, char *argv[]) 163 1.1 pooka { 164 1.1 pooka struct pud_conf_reg pcr; 165 1.1 pooka struct pud_req *pdr; 166 1.1 pooka ssize_t n; 167 1.1 pooka int rv; 168 1.1 pooka 169 1.1 pooka if (makenodes() == -1) 170 1.1 pooka err(1, "makenodes"); 171 1.1 pooka 172 1.1 pooka fd = open(_PATH_PUD, O_RDWR); 173 1.1 pooka if (fd == -1) 174 1.1 pooka err(1, "open"); 175 1.1 pooka 176 1.1 pooka memset(&pcr, 0, sizeof(pcr)); 177 1.1 pooka pcr.pm_pdr.pdr_pth.pth_framelen = sizeof(struct pud_conf_reg); 178 1.1 pooka pcr.pm_version = PUD_DEVELVERSION | PUD_VERSION; 179 1.1 pooka pcr.pm_pdr.pdr_reqclass = PUD_REQ_CONF; 180 1.1 pooka pcr.pm_pdr.pdr_reqtype = PUD_CONF_REG; 181 1.1 pooka 182 1.1 pooka pcr.pm_regdev = makedev(MYMAJOR, 0); 183 1.1 pooka pcr.pm_flags = PUD_CONFFLAG_BDEV; 184 1.1 pooka strlcpy(pcr.pm_devname, "youmass", sizeof(pcr.pm_devname)); 185 1.1 pooka 186 1.1 pooka n = write(fd, &pcr, pcr.pm_pdr.pdr_pth.pth_framelen); 187 1.1 pooka if (n == -1) 188 1.1 pooka err(1, "configure"); /* XXX: doubles as protocol error */ 189 1.1 pooka 190 1.1 pooka rump_boot_sethowto(RUMP_AB_VERBOSE); 191 1.1 pooka rump_init(); 192 1.1 pooka 193 1.1 pooka if ((rv = rump_pub_namei(RUMP_NAMEI_LOOKUP, 0, "/dev/ttyU0", 194 1.1 pooka NULL, &devvps[0], NULL)) != 0) 195 1.1 pooka errx(1, "raw device 0 lookup failed %d", rv); 196 1.1 pooka if ((rv = rump_pub_namei(RUMP_NAMEI_LOOKUP, 0, "/dev/ttyU1", 197 1.1 pooka NULL, &devvps[1], NULL)) != 0) 198 1.1 pooka errx(1, "raw device 1 lookup failed %d", rv); 199 1.1 pooka 200 1.1 pooka rootcred = rump_pub_cred_create(0, 0, 0, NULL); 201 1.1 pooka 202 1.1 pooka /* process requests ad infinitum */ 203 1.1 pooka for (;;) { 204 1.1 pooka pthread_t pt; 205 1.1 pooka 206 1.1 pooka #define PDRSIZE (64*1024+1024) 207 1.1 pooka pdr = malloc(PDRSIZE); 208 1.1 pooka if (pdr == NULL) 209 1.1 pooka err(1, "malloc"); 210 1.1 pooka 211 1.1 pooka n = read(fd, pdr, PDRSIZE); 212 1.1 pooka if (n == -1) 213 1.1 pooka err(1, "read"); 214 1.1 pooka 215 1.1 pooka /* 216 1.1 pooka * tip & cu fork and read/write at the same time. hence, 217 1.1 pooka * we need a multithreaded server as otherwise read requests 218 1.1 pooka * will block eternally since no writes can be done. 219 1.1 pooka * 220 1.1 pooka * XXX: do this properly (detached threads, or pool) 221 1.1 pooka */ 222 1.1 pooka pthread_create(&pt, NULL, handlereq, pdr); 223 1.1 pooka } 224 1.1 pooka } 225