This source file includes following definitions.
- udsbr_match
- udsbr_attach
- udsbr_detach
- udsbr_activate
- udsbr_req
- udsbr_start
- udsbr_stop
- udsbr_setfreq
- udsbr_status
- udsbr_get_info
- udsbr_set_info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/kernel.h>
51 #include <sys/device.h>
52
53 #include <sys/radioio.h>
54 #include <dev/radio_if.h>
55
56 #include <dev/usb/usb.h>
57 #include <dev/usb/usbdi.h>
58 #include <dev/usb/usbdi_util.h>
59
60 #include <dev/usb/usbdevs.h>
61
62 #ifdef UDSBR_DEBUG
63 #define DPRINTF(x) do { if (udsbrdebug) printf x; } while (0)
64 #define DPRINTFN(n,x) do { if (udsbrdebug>(n)) printf x; } while (0)
65 int udsbrdebug = 0;
66 #else
67 #define DPRINTF(x)
68 #define DPRINTFN(n,x)
69 #endif
70
71 #define UDSBR_CONFIG_NO 1
72
73 int udsbr_get_info(void *, struct radio_info *);
74 int udsbr_set_info(void *, struct radio_info *);
75
76 struct radio_hw_if udsbr_hw_if = {
77 NULL,
78 NULL,
79 udsbr_get_info,
80 udsbr_set_info,
81 NULL
82 };
83
84 struct udsbr_softc {
85 struct device sc_dev;
86 usbd_device_handle sc_udev;
87
88 char sc_mute;
89 char sc_vol;
90 u_int32_t sc_freq;
91
92 struct device *sc_child;
93
94 char sc_dying;
95 };
96
97 int udsbr_req(struct udsbr_softc *sc, int ureq, int value, int index);
98 void udsbr_start(struct udsbr_softc *sc);
99 void udsbr_stop(struct udsbr_softc *sc);
100 void udsbr_setfreq(struct udsbr_softc *sc, int freq);
101 int udsbr_status(struct udsbr_softc *sc);
102
103 int udsbr_match(struct device *, void *, void *);
104 void udsbr_attach(struct device *, struct device *, void *);
105 int udsbr_detach(struct device *, int);
106 int udsbr_activate(struct device *, enum devact);
107
108 struct cfdriver udsbr_cd = {
109 NULL, "udsbr", DV_DULL
110 };
111
112 const struct cfattach udsbr_ca = {
113 sizeof(struct udsbr_softc),
114 udsbr_match,
115 udsbr_attach,
116 udsbr_detach,
117 udsbr_activate,
118 };
119
120 int
121 udsbr_match(struct device *parent, void *match, void *aux)
122 {
123 struct usb_attach_arg *uaa = aux;
124
125 DPRINTFN(50,("udsbr_match\n"));
126
127 if (uaa->iface != NULL)
128 return (UMATCH_NONE);
129
130 if (uaa->vendor != USB_VENDOR_CYPRESS ||
131 uaa->product != USB_PRODUCT_CYPRESS_FMRADIO)
132 return (UMATCH_NONE);
133 return (UMATCH_VENDOR_PRODUCT);
134 }
135
136 void
137 udsbr_attach(struct device *parent, struct device *self, void *aux)
138 {
139 struct udsbr_softc *sc = (struct udsbr_softc *)self;
140 struct usb_attach_arg *uaa = aux;
141 usbd_device_handle dev = uaa->device;
142 char *devinfop;
143 usbd_status err;
144
145 DPRINTFN(10,("udsbr_attach: sc=%p\n", sc));
146
147 devinfop = usbd_devinfo_alloc(dev, 0);
148 printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
149 usbd_devinfo_free(devinfop);
150
151 err = usbd_set_config_no(dev, UDSBR_CONFIG_NO, 1);
152 if (err) {
153 printf("%s: setting config no failed\n",
154 sc->sc_dev.dv_xname);
155 return;
156 }
157
158 sc->sc_udev = dev;
159
160 DPRINTFN(10, ("udsbr_attach: %p\n", sc->sc_udev));
161
162 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
163 &sc->sc_dev);
164
165 sc->sc_child = radio_attach_mi(&udsbr_hw_if, sc, &sc->sc_dev);
166 }
167
168 int
169 udsbr_detach(struct device *self, int flags)
170 {
171 struct udsbr_softc *sc = (struct udsbr_softc *)self;
172 int rv = 0;
173
174 if (sc->sc_child != NULL)
175 rv = config_detach(sc->sc_child, flags);
176
177 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
178 &sc->sc_dev);
179
180 return (rv);
181 }
182
183 int
184 udsbr_activate(struct device *self, enum devact act)
185 {
186 struct udsbr_softc *sc = (struct udsbr_softc *)self;
187 int rv = 0;
188
189 switch (act) {
190 case DVACT_ACTIVATE:
191 break;
192
193 case DVACT_DEACTIVATE:
194 sc->sc_dying = 1;
195 if (sc->sc_child != NULL)
196 rv = config_deactivate(sc->sc_child);
197 break;
198 }
199 return (rv);
200 }
201
202 int
203 udsbr_req(struct udsbr_softc *sc, int ureq, int value, int index)
204 {
205 usb_device_request_t req;
206 usbd_status err;
207 u_char data;
208
209 DPRINTFN(1,("udsbr_req: ureq=0x%02x value=0x%04x index=0x%04x\n",
210 ureq, value, index));
211 req.bmRequestType = UT_READ_VENDOR_DEVICE;
212 req.bRequest = ureq;
213 USETW(req.wValue, value);
214 USETW(req.wIndex, index);
215 USETW(req.wLength, 1);
216 err = usbd_do_request(sc->sc_udev, &req, &data);
217 if (err) {
218 printf("%s: request failed err=%d\n", sc->sc_dev.dv_xname,
219 err);
220 }
221 return !(data & 1);
222 }
223
224 void
225 udsbr_start(struct udsbr_softc *sc)
226 {
227 (void)udsbr_req(sc, 0x00, 0x0000, 0x00c7);
228 (void)udsbr_req(sc, 0x02, 0x0001, 0x0000);
229 }
230
231 void
232 udsbr_stop(struct udsbr_softc *sc)
233 {
234 (void)udsbr_req(sc, 0x00, 0x0016, 0x001c);
235 (void)udsbr_req(sc, 0x02, 0x0000, 0x0000);
236 }
237
238 void
239 udsbr_setfreq(struct udsbr_softc *sc, int freq)
240 {
241 DPRINTF(("udsbr_setfreq: setfreq=%d\n", freq));
242
243
244
245
246
247
248
249 freq = (freq * 1000 + 10700001) / 12500;
250 (void)udsbr_req(sc, 0x01, (freq >> 8) & 0xff, freq & 0xff);
251 (void)udsbr_req(sc, 0x00, 0x0096, 0x00b7);
252 usbd_delay_ms(sc->sc_udev, 240);
253 }
254
255 int
256 udsbr_status(struct udsbr_softc *sc)
257 {
258 return (udsbr_req(sc, 0x00, 0x0000, 0x0024));
259 }
260
261
262 int
263 udsbr_get_info(void *v, struct radio_info *ri)
264 {
265 struct udsbr_softc *sc = v;
266
267 ri->mute = sc->sc_mute;
268 ri->volume = sc->sc_vol ? 255 : 0;
269 ri->caps = RADIO_CAPS_DETECT_STEREO;
270 ri->rfreq = 0;
271 ri->lock = 0;
272 ri->freq = sc->sc_freq;
273 ri->info = udsbr_status(sc) ? RADIO_INFO_STEREO : 0;
274
275 return (0);
276 }
277
278 int
279 udsbr_set_info(void *v, struct radio_info *ri)
280 {
281 struct udsbr_softc *sc = v;
282
283 sc->sc_mute = ri->mute != 0;
284 sc->sc_vol = ri->volume != 0;
285 sc->sc_freq = ri->freq;
286 udsbr_setfreq(sc, sc->sc_freq);
287
288 if (sc->sc_mute || sc->sc_vol == 0)
289 udsbr_stop(sc);
290 else
291 udsbr_start(sc);
292
293 return (0);
294 }