version 1.79, 2008/03/01 14:16:51 |
version 1.79.2.2, 2008/06/04 02:05:20 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
|
|
/* |
/* |
* Copyright (c) 1998, 2004 The NetBSD Foundation, Inc. |
* Copyright (c) 1998, 2004, 2008 The NetBSD Foundation, Inc. |
* All rights reserved. |
* All rights reserved. |
* |
* |
* This code is derived from software contributed to The NetBSD Foundation |
* This code is derived from software contributed to The NetBSD Foundation |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
|
* must display the following acknowledgement: |
|
* This product includes software developed by the NetBSD |
|
* Foundation, Inc. and its contributors. |
|
* 4. Neither the name of The NetBSD Foundation nor the names of its |
|
* contributors may be used to endorse or promote products derived |
|
* from this software without specific prior written permission. |
|
* |
* |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
Line 60 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 53 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/proc.h> |
#include <sys/proc.h> |
#include <sys/vnode.h> |
#include <sys/vnode.h> |
#include <sys/poll.h> |
#include <sys/poll.h> |
|
#include <sys/intr.h> |
|
|
#include <dev/usb/usb.h> |
#include <dev/usb/usb.h> |
#include <dev/usb/usbhid.h> |
#include <dev/usb/usbhid.h> |
Line 93 struct uhid_softc { |
|
Line 87 struct uhid_softc { |
|
struct clist sc_q; |
struct clist sc_q; |
struct selinfo sc_rsel; |
struct selinfo sc_rsel; |
usb_proc_ptr sc_async; /* process that wants SIGIO */ |
usb_proc_ptr sc_async; /* process that wants SIGIO */ |
|
void *sc_sih; |
u_char sc_state; /* driver state */ |
u_char sc_state; /* driver state */ |
#define UHID_ASLP 0x01 /* waiting for device data */ |
#define UHID_ASLP 0x01 /* waiting for device data */ |
#define UHID_IMMED 0x02 /* return read data immediately */ |
#define UHID_IMMED 0x02 /* return read data immediately */ |
Line 119 const struct cdevsw uhid_cdevsw = { |
|
Line 114 const struct cdevsw uhid_cdevsw = { |
|
}; |
}; |
|
|
Static void uhid_intr(struct uhidev *, void *, u_int len); |
Static void uhid_intr(struct uhidev *, void *, u_int len); |
|
Static void uhid_softintr(void *); |
|
|
Static int uhid_do_read(struct uhid_softc *, struct uio *uio, int); |
Static int uhid_do_read(struct uhid_softc *, struct uio *uio, int); |
Static int uhid_do_write(struct uhid_softc *, struct uio *uio, int); |
Static int uhid_do_write(struct uhid_softc *, struct uio *uio, int); |
Line 127 Static int uhid_do_ioctl(struct uhid_sof |
|
Line 123 Static int uhid_do_ioctl(struct uhid_sof |
|
USB_DECLARE_DRIVER(uhid); |
USB_DECLARE_DRIVER(uhid); |
|
|
int |
int |
uhid_match(struct device *parent, struct cfdata *match, |
uhid_match(device_t parent, cfdata_t match, void *aux) |
void *aux) |
|
{ |
{ |
#ifdef UHID_DEBUG |
#ifdef UHID_DEBUG |
struct uhidev_attach_arg *uha = aux; |
struct uhidev_attach_arg *uha = aux; |
Line 143 uhid_match(struct device *parent, struct |
|
Line 138 uhid_match(struct device *parent, struct |
|
} |
} |
|
|
void |
void |
uhid_attach(struct device *parent, struct device *self, void *aux) |
uhid_attach(device_t parent, device_t self, void *aux) |
{ |
{ |
struct uhid_softc *sc = (struct uhid_softc *)self; |
struct uhid_softc *sc = device_private(self); |
struct uhidev_attach_arg *uha = aux; |
struct uhidev_attach_arg *uha = aux; |
int size, repid; |
int size, repid; |
void *desc; |
void *desc; |
|
|
|
sc->sc_hdev.sc_dev = self; |
selinit(&sc->sc_rsel); |
selinit(&sc->sc_rsel); |
sc->sc_hdev.sc_intr = uhid_intr; |
sc->sc_hdev.sc_intr = uhid_intr; |
sc->sc_hdev.sc_parent = uha->parent; |
sc->sc_hdev.sc_parent = uha->parent; |
sc->sc_hdev.sc_report_id = uha->reportid; |
sc->sc_hdev.sc_report_id = uha->reportid; |
|
sc->sc_sih = softint_establish(SOFTINT_MPSAFE | SOFTINT_CLOCK, |
|
uhid_softintr, sc); |
|
|
uhidev_get_report_desc(uha->parent, &desc, &size); |
uhidev_get_report_desc(uha->parent, &desc, &size); |
repid = uha->reportid; |
repid = uha->reportid; |
Line 161 uhid_attach(struct device *parent, struc |
|
Line 159 uhid_attach(struct device *parent, struc |
|
sc->sc_osize = hid_report_size(desc, size, hid_output, repid); |
sc->sc_osize = hid_report_size(desc, size, hid_output, repid); |
sc->sc_fsize = hid_report_size(desc, size, hid_feature, repid); |
sc->sc_fsize = hid_report_size(desc, size, hid_feature, repid); |
|
|
printf(": input=%d, output=%d, feature=%d\n", |
aprint_naive("\n"); |
|
aprint_normal(": input=%d, output=%d, feature=%d\n", |
sc->sc_isize, sc->sc_osize, sc->sc_fsize); |
sc->sc_isize, sc->sc_osize, sc->sc_fsize); |
|
|
if (!pmf_device_register(self, NULL, NULL)) |
if (!pmf_device_register(self, NULL, NULL)) |
Line 173 uhid_attach(struct device *parent, struc |
|
Line 172 uhid_attach(struct device *parent, struc |
|
int |
int |
uhid_activate(device_ptr_t self, enum devact act) |
uhid_activate(device_ptr_t self, enum devact act) |
{ |
{ |
struct uhid_softc *sc = (struct uhid_softc *)self; |
struct uhid_softc *sc = device_private(self); |
|
|
switch (act) { |
switch (act) { |
case DVACT_ACTIVATE: |
case DVACT_ACTIVATE: |
Line 187 uhid_activate(device_ptr_t self, enum de |
|
Line 186 uhid_activate(device_ptr_t self, enum de |
|
} |
} |
|
|
int |
int |
uhid_detach(struct device *self, int flags) |
uhid_detach(device_t self, int flags) |
{ |
{ |
struct uhid_softc *sc = (struct uhid_softc *)self; |
struct uhid_softc *sc = device_private(self); |
int s; |
int s; |
int maj, mn; |
int maj, mn; |
|
|
Line 227 uhid_detach(struct device *self, int fla |
|
Line 226 uhid_detach(struct device *self, int fla |
|
USBDEV(sc->sc_hdev.sc_dev)); |
USBDEV(sc->sc_hdev.sc_dev)); |
#endif |
#endif |
seldestroy(&sc->sc_rsel); |
seldestroy(&sc->sc_rsel); |
|
softint_disestablish(sc->sc_sih); |
|
|
return (0); |
return (0); |
} |
} |
Line 257 uhid_intr(struct uhidev *addr, void *dat |
|
Line 257 uhid_intr(struct uhidev *addr, void *dat |
|
selnotify(&sc->sc_rsel, 0, 0); |
selnotify(&sc->sc_rsel, 0, 0); |
if (sc->sc_async != NULL) { |
if (sc->sc_async != NULL) { |
DPRINTFN(3, ("uhid_intr: sending SIGIO %p\n", sc->sc_async)); |
DPRINTFN(3, ("uhid_intr: sending SIGIO %p\n", sc->sc_async)); |
mutex_enter(&proclist_mutex); |
softint_schedule(sc->sc_sih); |
psignal(sc->sc_async, SIGIO); |
|
mutex_exit(&proclist_mutex); |
|
} |
} |
} |
} |
|
|
|
void |
|
uhid_softintr(void *cookie) |
|
{ |
|
struct uhid_softc *sc; |
|
|
|
sc = cookie; |
|
|
|
mutex_enter(proc_lock); |
|
if (sc->sc_async != NULL) |
|
psignal(sc->sc_async, SIGIO); |
|
mutex_exit(proc_lock); |
|
} |
|
|
int |
int |
uhidopen(dev_t dev, int flag, int mode, |
uhidopen(dev_t dev, int flag, int mode, |
struct lwp *l) |
struct lwp *l) |
Line 287 uhidopen(dev_t dev, int flag, int mode, |
|
Line 298 uhidopen(dev_t dev, int flag, int mode, |
|
} |
} |
sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK); |
sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK); |
sc->sc_state &= ~UHID_IMMED; |
sc->sc_state &= ~UHID_IMMED; |
|
mutex_enter(proc_lock); |
sc->sc_async = NULL; |
sc->sc_async = NULL; |
|
mutex_exit(proc_lock); |
|
|
return (0); |
return (0); |
} |
} |
Line 304 uhidclose(dev_t dev, int flag, int mode, |
|
Line 317 uhidclose(dev_t dev, int flag, int mode, |
|
|
|
clfree(&sc->sc_q); |
clfree(&sc->sc_q); |
free(sc->sc_obuf, M_USBDEV); |
free(sc->sc_obuf, M_USBDEV); |
|
mutex_enter(proc_lock); |
sc->sc_async = NULL; |
sc->sc_async = NULL; |
|
mutex_exit(proc_lock); |
uhidev_close(&sc->sc_hdev); |
uhidev_close(&sc->sc_hdev); |
|
|
return (0); |
return (0); |
Line 447 uhid_do_ioctl(struct uhid_softc *sc, u_l |
|
Line 462 uhid_do_ioctl(struct uhid_softc *sc, u_l |
|
break; |
break; |
|
|
case FIOASYNC: |
case FIOASYNC: |
|
mutex_enter(proc_lock); |
if (*(int *)addr) { |
if (*(int *)addr) { |
if (sc->sc_async != NULL) |
if (sc->sc_async != NULL) |
return (EBUSY); |
return (EBUSY); |
Line 454 uhid_do_ioctl(struct uhid_softc *sc, u_l |
|
Line 470 uhid_do_ioctl(struct uhid_softc *sc, u_l |
|
DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", l->l_proc)); |
DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", l->l_proc)); |
} else |
} else |
sc->sc_async = NULL; |
sc->sc_async = NULL; |
|
mutex_exit(proc_lock); |
break; |
break; |
|
|
/* XXX this is not the most general solution. */ |
/* XXX this is not the most general solution. */ |
case TIOCSPGRP: |
case TIOCSPGRP: |
if (sc->sc_async == NULL) |
mutex_enter(proc_lock); |
|
if (sc->sc_async == NULL) { |
|
mutex_exit(proc_lock); |
return (EINVAL); |
return (EINVAL); |
if (*(int *)addr != sc->sc_async->p_pgid) |
} |
|
if (*(int *)addr != sc->sc_async->p_pgid) { |
|
mutex_exit(proc_lock); |
return (EPERM); |
return (EPERM); |
|
} |
|
mutex_exit(proc_lock); |
break; |
break; |
|
|
case FIOSETOWN: |
case FIOSETOWN: |
if (sc->sc_async == NULL) |
mutex_enter(proc_lock); |
|
if (sc->sc_async == NULL) { |
|
mutex_exit(proc_lock); |
return (EINVAL); |
return (EINVAL); |
|
} |
if (-*(int *)addr != sc->sc_async->p_pgid |
if (-*(int *)addr != sc->sc_async->p_pgid |
&& *(int *)addr != sc->sc_async->p_pid) |
&& *(int *)addr != sc->sc_async->p_pid) { |
|
mutex_exit(proc_lock); |
return (EPERM); |
return (EPERM); |
|
} |
|
mutex_exit(proc_lock); |
break; |
break; |
|
|
case USB_GET_REPORT_DESC: |
case USB_GET_REPORT_DESC: |