1 /* $OpenBSD: radio.c,v 1.9 2011/07/03 15:47:16 matthew Exp $ */ 2 /* $RuOBSD: radio.c,v 1.7 2001/12/04 06:03:05 tm Exp $ */ 3 4 /* 5 * Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* This is /dev/radio driver for OpenBSD */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/proc.h> 34 #include <sys/errno.h> 35 #include <sys/ioctl.h> 36 #include <sys/fcntl.h> 37 #include <sys/device.h> 38 #include <sys/vnode.h> 39 #include <sys/radioio.h> 40 #include <sys/conf.h> 41 42 #include <dev/audio_if.h> 43 #include <dev/radio_if.h> 44 #include <dev/radiovar.h> 45 46 int radioprobe(struct device *, void *, void *); 47 void radioattach(struct device *, struct device *, void *); 48 int radiodetach(struct device *, int); 49 int radioactivate(struct device *, int); 50 int radioprint(void *, const char *); 51 52 struct cfattach radio_ca = { 53 sizeof(struct radio_softc), radioprobe, radioattach, 54 radiodetach, radioactivate 55 }; 56 57 struct cfdriver radio_cd = { 58 NULL, "radio", DV_DULL 59 }; 60 61 int 62 radioprobe(struct device *parent, void *match, void *aux) 63 { 64 struct audio_attach_args *sa = aux; 65 return (sa->type == AUDIODEV_TYPE_RADIO) ? 1 : 0; 66 } 67 68 void 69 radioattach(struct device *parent, struct device *self, void *aux) 70 { 71 struct radio_softc *sc = (void *) self; 72 struct audio_attach_args *sa = aux; 73 74 printf("\n"); 75 sc->hw_if = sa->hwif; 76 sc->hw_hdl = sa->hdl; 77 sc->sc_dev = parent; 78 } 79 80 int 81 radioopen(dev_t dev, int flags, int fmt, struct proc *p) 82 { 83 int unit; 84 struct radio_softc *sc; 85 86 unit = RADIOUNIT(dev); 87 if (unit >= radio_cd.cd_ndevs || 88 (sc = radio_cd.cd_devs[unit]) == NULL || 89 sc->hw_if == NULL) 90 return (ENXIO); 91 92 if (sc->hw_if->open != NULL) 93 return (sc->hw_if->open(sc->hw_hdl, flags, fmt, p)); 94 else 95 return (0); 96 } 97 98 int 99 radioclose(dev_t dev, int flags, int fmt, struct proc *p) 100 { 101 struct radio_softc *sc; 102 103 sc = radio_cd.cd_devs[RADIOUNIT(dev)]; 104 105 if (sc->hw_if->close != NULL) 106 return (sc->hw_if->close(sc->hw_hdl, flags, fmt, p)); 107 else 108 return (0); 109 } 110 111 int 112 radioioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 113 { 114 struct radio_softc *sc; 115 int unit, error; 116 117 unit = RADIOUNIT(dev); 118 if (unit >= radio_cd.cd_ndevs || 119 (sc = radio_cd.cd_devs[unit]) == NULL || sc->hw_if == NULL) 120 return (ENXIO); 121 122 error = EOPNOTSUPP; 123 switch (cmd) { 124 case RIOCGINFO: 125 if (sc->hw_if->get_info) 126 error = (sc->hw_if->get_info)(sc->hw_hdl, 127 (struct radio_info *)data); 128 break; 129 case RIOCSINFO: 130 if (!(flags & FWRITE)) 131 return (EACCES); 132 if (sc->hw_if->set_info) 133 error = (sc->hw_if->set_info)(sc->hw_hdl, 134 (struct radio_info *)data); 135 break; 136 case RIOCSSRCH: 137 if (!(flags & FWRITE)) 138 return (EACCES); 139 if (sc->hw_if->search) 140 error = (sc->hw_if->search)(sc->hw_hdl, 141 *(int *)data); 142 break; 143 default: 144 error = (ENOTTY); 145 } 146 147 return (error); 148 } 149 150 /* 151 * Called from hardware driver. This is where the MI radio driver gets 152 * probed/attached to the hardware driver 153 */ 154 155 struct device * 156 radio_attach_mi(struct radio_hw_if *rhwp, void *hdlp, struct device *dev) 157 { 158 struct audio_attach_args arg; 159 160 arg.type = AUDIODEV_TYPE_RADIO; 161 arg.hwif = rhwp; 162 arg.hdl = hdlp; 163 return (config_found(dev, &arg, radioprint)); 164 } 165 166 int 167 radioprint(void *aux, const char *pnp) 168 { 169 if (pnp != NULL) 170 printf("radio at %s", pnp); 171 return (UNCONF); 172 } 173 174 int 175 radiodetach(struct device *self, int flags) 176 { 177 /*struct radio_softc *sc = (struct radio_softc *)self;*/ 178 int maj, mn; 179 180 /* locate the major number */ 181 for (maj = 0; maj < nchrdev; maj++) 182 if (cdevsw[maj].d_open == radioopen) 183 break; 184 185 /* Nuke the vnodes for any open instances (calls close). */ 186 mn = self->dv_unit; 187 vdevgone(maj, mn, mn, VCHR); 188 189 return (0); 190 } 191 192 int 193 radioactivate(struct device *self, int act) 194 { 195 struct radio_softc *sc = (struct radio_softc *)self; 196 197 switch (act) { 198 case DVACT_DEACTIVATE: 199 sc->sc_dying = 1; 200 break; 201 } 202 return (0); 203 } 204