1 /* $NetBSD: irframe.c,v 1.43 2009/01/11 14:21:48 mlelstv Exp $ */
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net).
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: irframe.c,v 1.43 2009/01/11 14:21:48 mlelstv Exp $");
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/ioctl.h>
40 #include <sys/kernel.h>
41 #include <sys/device.h>
43 #include <sys/malloc.h>
45 #include <sys/select.h>
46 #include <sys/vnode.h>
48 #include <dev/ir/ir.h>
49 #include <dev/ir/irdaio.h>
50 #include <dev/ir/irframevar.h>
53 #define DPRINTF(x) if (irframedebug) printf x
61 dev_type_open(irframeopen
);
62 dev_type_close(irframeclose
);
63 dev_type_read(irframeread
);
64 dev_type_write(irframewrite
);
65 dev_type_ioctl(irframeioctl
);
66 dev_type_poll(irframepoll
);
67 dev_type_kqfilter(irframekqfilter
);
69 const struct cdevsw irframe_cdevsw
= {
70 irframeopen
, irframeclose
, irframeread
, irframewrite
, irframeioctl
,
71 nostop
, notty
, irframepoll
, nommap
, irframekqfilter
, D_OTHER
,
74 int irframe_match(device_t parent
, cfdata_t match
, void *aux
);
76 Static
int irf_set_params(struct irframe_softc
*sc
, struct irda_params
*p
);
77 Static
int irf_reset_params(struct irframe_softc
*sc
);
80 /* In case we just have tty attachment. */
81 CFDRIVER_DECL(irframe
, DV_DULL
, NULL
);
84 CFATTACH_DECL_NEW(irframe
, sizeof(struct irframe_softc
),
85 irframe_match
, irframe_attach
, irframe_detach
, NULL
);
87 extern struct cfdriver irframe_cd
;
89 #define IRFRAMEUNIT(dev) (minor(dev))
92 irframe_match(device_t parent
, cfdata_t match
, void *aux
)
94 struct ir_attach_args
*ia
= aux
;
96 return (ia
->ia_type
== IR_TYPE_IRFRAME
);
100 irframe_attach(device_t parent
, device_t self
, void *aux
)
102 struct irframe_softc
*sc
= device_private(self
);
103 struct ir_attach_args
*ia
= aux
;
108 sc
->sc_methods
= ia
->ia_methods
;
109 sc
->sc_handle
= ia
->ia_handle
;
112 if (sc
->sc_methods
->im_read
== NULL
||
113 sc
->sc_methods
->im_write
== NULL
||
114 sc
->sc_methods
->im_poll
== NULL
||
115 sc
->sc_methods
->im_kqfilter
== NULL
||
116 sc
->sc_methods
->im_set_params
== NULL
||
117 sc
->sc_methods
->im_get_speeds
== NULL
||
118 sc
->sc_methods
->im_get_turnarounds
== NULL
)
119 panic("%s: missing methods", device_xname(self
));
122 (void)sc
->sc_methods
->im_get_speeds(sc
->sc_handle
, &speeds
);
123 sc
->sc_speedmask
= speeds
;
125 if (speeds
& IRDA_SPEEDS_SIR
) {
126 printf("%s SIR", delim
);
129 if (speeds
& IRDA_SPEEDS_MIR
) {
130 printf("%s MIR", delim
);
133 if (speeds
& IRDA_SPEEDS_FIR
) {
134 printf("%s FIR", delim
);
137 if (speeds
& IRDA_SPEEDS_VFIR
) {
138 printf("%s VFIR", delim
);
143 if (!pmf_device_register(self
, NULL
, NULL
))
144 aprint_error_dev(self
, "couldn't establish power handler\n");
148 irframe_detach(device_t self
, int flags
)
150 /*struct irframe_softc *sc = device_private(self);*/
153 pmf_device_deregister(self
);
155 /* XXX needs reference count */
157 /* locate the major number */
158 maj
= cdevsw_lookup_major(&irframe_cdevsw
);
160 /* Nuke the vnodes for any open instances (calls close). */
161 mn
= device_unit(self
);
162 vdevgone(maj
, mn
, mn
, VCHR
);
168 irframeopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
170 struct irframe_softc
*sc
;
173 sc
= device_lookup_private(&irframe_cd
, IRFRAMEUNIT(dev
));
176 if (!device_is_active(sc
->sc_dev
))
180 if (sc
->sc_methods
->im_open
!= NULL
) {
181 error
= sc
->sc_methods
->im_open(sc
->sc_handle
, flag
, mode
, l
);
187 sc
->sc_speed
= IRDA_DEFAULT_SPEED
;
189 (void)irf_reset_params(sc
);
194 irframeclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
196 struct irframe_softc
*sc
;
199 sc
= device_lookup_private(&irframe_cd
, IRFRAMEUNIT(dev
));
203 if (sc
->sc_methods
->im_close
!= NULL
)
204 error
= sc
->sc_methods
->im_close(sc
->sc_handle
, flag
, mode
, l
);
211 irframeread(dev_t dev
, struct uio
*uio
, int flag
)
213 struct irframe_softc
*sc
;
215 sc
= device_lookup_private(&irframe_cd
, IRFRAMEUNIT(dev
));
218 if (!device_is_active(sc
->sc_dev
) || !sc
->sc_open
)
220 if (uio
->uio_resid
< sc
->sc_params
.maxsize
) {
222 printf("irframeread: short read %ld < %d\n",
223 (long)uio
->uio_resid
, sc
->sc_params
.maxsize
);
227 return (sc
->sc_methods
->im_read(sc
->sc_handle
, uio
, flag
));
231 irframewrite(dev_t dev
, struct uio
*uio
, int flag
)
233 struct irframe_softc
*sc
;
235 sc
= device_lookup_private(&irframe_cd
, IRFRAMEUNIT(dev
));
238 if (!device_is_active(sc
->sc_dev
) || !sc
->sc_open
)
240 if (uio
->uio_resid
> sc
->sc_params
.maxsize
) {
242 printf("irframeread: long write %ld > %d\n",
243 (long)uio
->uio_resid
, sc
->sc_params
.maxsize
);
247 return (sc
->sc_methods
->im_write(sc
->sc_handle
, uio
, flag
));
251 irf_set_params(struct irframe_softc
*sc
, struct irda_params
*p
)
255 DPRINTF(("irf_set_params: set params speed=%u ebofs=%u maxsize=%u "
256 "speedmask=0x%x\n", p
->speed
, p
->ebofs
, p
->maxsize
,
259 if (p
->maxsize
> IRDA_MAX_FRAME_SIZE
) {
261 printf("irf_set_params: bad maxsize=%u\n", p
->maxsize
);
266 if (p
->ebofs
> IRDA_MAX_EBOFS
) {
268 printf("irf_set_params: bad maxsize=%u\n", p
->maxsize
);
273 #define CONC(x,y) x##y
274 #define CASE(s) case s: if (!(sc->sc_speedmask & CONC(IRDA_SPEED_,s))) return (EINVAL); break
286 default: return (EINVAL
);
291 error
= sc
->sc_methods
->im_set_params(sc
->sc_handle
, p
);
294 DPRINTF(("irf_set_params: ok\n"));
296 if (p
->speed
!= sc
->sc_speed
) {
297 sc
->sc_speed
= p
->speed
;
298 aprint_verbose_dev(sc
->sc_dev
, "set speed %u\n",
304 printf("irf_set_params: error=%d\n", error
);
311 irf_reset_params(struct irframe_softc
*sc
)
313 struct irda_params params
;
315 params
.speed
= IRDA_DEFAULT_SPEED
;
316 params
.ebofs
= IRDA_DEFAULT_EBOFS
;
317 params
.maxsize
= IRDA_DEFAULT_SIZE
;
318 return (irf_set_params(sc
, ¶ms
));
322 irframeioctl(dev_t dev
, u_long cmd
, void *addr
, int flag
,
325 struct irframe_softc
*sc
;
329 sc
= device_lookup_private(&irframe_cd
, IRFRAMEUNIT(dev
));
332 if (!device_is_active(sc
->sc_dev
) || !sc
->sc_open
)
337 /* All handled in the upper FS layer. */
341 case IRDA_SET_PARAMS
:
342 error
= irf_set_params(sc
, vaddr
);
345 case IRDA_RESET_PARAMS
:
346 error
= irf_reset_params(sc
);
349 case IRDA_GET_SPEEDMASK
:
350 error
= sc
->sc_methods
->im_get_speeds(sc
->sc_handle
, vaddr
);
353 case IRDA_GET_TURNAROUNDMASK
:
354 error
= sc
->sc_methods
->im_get_turnarounds(sc
->sc_handle
,vaddr
);
365 irframepoll(dev_t dev
, int events
, struct lwp
*l
)
367 struct irframe_softc
*sc
;
369 sc
= device_lookup_private(&irframe_cd
, IRFRAMEUNIT(dev
));
372 if (!device_is_active(sc
->sc_dev
) || !sc
->sc_open
)
375 return (sc
->sc_methods
->im_poll(sc
->sc_handle
, events
, l
));
379 irframekqfilter(dev_t dev
, struct knote
*kn
)
381 struct irframe_softc
*sc
;
383 sc
= device_lookup_private(&irframe_cd
, IRFRAMEUNIT(dev
));
384 if (!device_is_active(sc
->sc_dev
) || !sc
->sc_open
)
387 return (sc
->sc_methods
->im_kqfilter(sc
->sc_handle
, kn
));