Line data Source code
1 : /* $OpenBSD: radio.c,v 1.11 2016/09/22 00:47:19 jsg 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/errno.h>
34 : #include <sys/ioctl.h>
35 : #include <sys/fcntl.h>
36 : #include <sys/device.h>
37 : #include <sys/vnode.h>
38 : #include <sys/radioio.h>
39 : #include <sys/conf.h>
40 :
41 : #include <dev/audio_if.h>
42 : #include <dev/radio_if.h>
43 : #include <dev/radiovar.h>
44 :
45 : int radioprobe(struct device *, void *, void *);
46 : void radioattach(struct device *, struct device *, void *);
47 : int radiodetach(struct device *, int);
48 : int radioactivate(struct device *, int);
49 : int radioprint(void *, const char *);
50 :
51 : struct cfattach radio_ca = {
52 : sizeof(struct radio_softc), radioprobe, radioattach,
53 : radiodetach, radioactivate
54 : };
55 :
56 : struct cfdriver radio_cd = {
57 : NULL, "radio", DV_DULL
58 : };
59 :
60 : int
61 0 : radioprobe(struct device *parent, void *match, void *aux)
62 : {
63 0 : struct audio_attach_args *sa = aux;
64 0 : return (sa->type == AUDIODEV_TYPE_RADIO) ? 1 : 0;
65 : }
66 :
67 : void
68 0 : radioattach(struct device *parent, struct device *self, void *aux)
69 : {
70 0 : struct radio_softc *sc = (void *) self;
71 0 : struct audio_attach_args *sa = aux;
72 :
73 0 : printf("\n");
74 0 : sc->hw_if = sa->hwif;
75 0 : sc->hw_hdl = sa->hdl;
76 0 : sc->sc_dev = parent;
77 0 : }
78 :
79 : int
80 0 : radioopen(dev_t dev, int flags, int fmt, struct proc *p)
81 : {
82 : int unit;
83 : struct radio_softc *sc;
84 :
85 0 : unit = RADIOUNIT(dev);
86 0 : if (unit >= radio_cd.cd_ndevs ||
87 0 : (sc = radio_cd.cd_devs[unit]) == NULL ||
88 0 : sc->hw_if == NULL)
89 0 : return (ENXIO);
90 :
91 0 : if (sc->hw_if->open != NULL)
92 0 : return (sc->hw_if->open(sc->hw_hdl, flags, fmt, p));
93 : else
94 0 : return (0);
95 0 : }
96 :
97 : int
98 0 : radioclose(dev_t dev, int flags, int fmt, struct proc *p)
99 : {
100 : struct radio_softc *sc;
101 :
102 0 : sc = radio_cd.cd_devs[RADIOUNIT(dev)];
103 :
104 0 : if (sc->hw_if->close != NULL)
105 0 : return (sc->hw_if->close(sc->hw_hdl, flags, fmt, p));
106 : else
107 0 : return (0);
108 0 : }
109 :
110 : int
111 0 : radioioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
112 : {
113 : struct radio_softc *sc;
114 : int unit, error;
115 :
116 0 : unit = RADIOUNIT(dev);
117 0 : if (unit >= radio_cd.cd_ndevs ||
118 0 : (sc = radio_cd.cd_devs[unit]) == NULL || sc->hw_if == NULL)
119 0 : return (ENXIO);
120 :
121 : error = EOPNOTSUPP;
122 0 : switch (cmd) {
123 : case RIOCGINFO:
124 0 : if (sc->hw_if->get_info)
125 0 : error = (sc->hw_if->get_info)(sc->hw_hdl,
126 0 : (struct radio_info *)data);
127 : break;
128 : case RIOCSINFO:
129 0 : if (!(flags & FWRITE))
130 0 : return (EACCES);
131 0 : if (sc->hw_if->set_info)
132 0 : error = (sc->hw_if->set_info)(sc->hw_hdl,
133 0 : (struct radio_info *)data);
134 : break;
135 : case RIOCSSRCH:
136 0 : if (!(flags & FWRITE))
137 0 : return (EACCES);
138 0 : if (sc->hw_if->search)
139 0 : error = (sc->hw_if->search)(sc->hw_hdl,
140 0 : *(int *)data);
141 : break;
142 : default:
143 : error = (ENOTTY);
144 0 : }
145 :
146 0 : return (error);
147 0 : }
148 :
149 : /*
150 : * Called from hardware driver. This is where the MI radio driver gets
151 : * probed/attached to the hardware driver
152 : */
153 :
154 : struct device *
155 0 : radio_attach_mi(struct radio_hw_if *rhwp, void *hdlp, struct device *dev)
156 : {
157 0 : struct audio_attach_args arg;
158 :
159 0 : arg.type = AUDIODEV_TYPE_RADIO;
160 0 : arg.hwif = rhwp;
161 0 : arg.hdl = hdlp;
162 0 : return (config_found(dev, &arg, radioprint));
163 0 : }
164 :
165 : int
166 0 : radioprint(void *aux, const char *pnp)
167 : {
168 0 : if (pnp != NULL)
169 0 : printf("radio at %s", pnp);
170 0 : return (UNCONF);
171 : }
172 :
173 : int
174 0 : radiodetach(struct device *self, int flags)
175 : {
176 : /*struct radio_softc *sc = (struct radio_softc *)self;*/
177 : int maj, mn;
178 :
179 : /* locate the major number */
180 0 : for (maj = 0; maj < nchrdev; maj++)
181 0 : if (cdevsw[maj].d_open == radioopen)
182 : break;
183 :
184 : /* Nuke the vnodes for any open instances (calls close). */
185 0 : mn = self->dv_unit;
186 0 : vdevgone(maj, mn, mn, VCHR);
187 :
188 0 : return (0);
189 : }
190 :
191 : int
192 0 : radioactivate(struct device *self, int act)
193 : {
194 0 : struct radio_softc *sc = (struct radio_softc *)self;
195 :
196 0 : switch (act) {
197 : case DVACT_DEACTIVATE:
198 0 : sc->sc_dying = 1;
199 0 : break;
200 : }
201 0 : return (0);
202 : }
|