#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/ioctl.h>
#include <dev/i2c/i2cvar.h>
#include <dev/i2c/ihidev.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsmousevar.h>
#include <dev/hid/hid.h>
#include <dev/hid/hidmsvar.h>
struct ims_softc {
struct ihidev sc_hdev;
struct hidms sc_ms;
};
void ims_intr(struct ihidev *addr, void *ibuf, u_int len);
int ims_enable(void *);
void ims_disable(void *);
int ims_ioctl(void *, u_long, caddr_t, int, struct proc *);
const struct wsmouse_accessops ims_accessops = {
ims_enable,
ims_ioctl,
ims_disable,
};
int ims_match(struct device *, void *, void *);
void ims_attach(struct device *, struct device *, void *);
int ims_detach(struct device *, int);
struct cfdriver ims_cd = {
NULL, "ims", DV_DULL
};
const struct cfattach ims_ca = {
sizeof(struct ims_softc),
ims_match,
ims_attach,
ims_detach
};
int
ims_match(struct device *parent, void *match, void *aux)
{
struct ihidev_attach_arg *iha = (struct ihidev_attach_arg *)aux;
int size;
void *desc;
ihidev_get_report_desc(iha->parent, &desc, &size);
if (hid_is_collection(desc, size, iha->reportid,
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_POINTER)))
return (IMATCH_IFACECLASS);
if (hid_is_collection(desc, size, iha->reportid,
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)))
return (IMATCH_IFACECLASS);
if (hid_is_collection(desc, size, iha->reportid,
HID_USAGE2(HUP_DIGITIZERS, HUD_PEN)))
return (IMATCH_IFACECLASS);
if (hid_is_collection(desc, size, iha->reportid,
HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCHSCREEN)) &&
hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
iha->reportid, hid_input, NULL, NULL))
return (IMATCH_IFACECLASS);
return (IMATCH_NONE);
}
void
ims_attach(struct device *parent, struct device *self, void *aux)
{
struct ims_softc *sc = (struct ims_softc *)self;
struct hidms *ms = &sc->sc_ms;
struct ihidev_attach_arg *iha = (struct ihidev_attach_arg *)aux;
int size, repid;
void *desc;
sc->sc_hdev.sc_intr = ims_intr;
sc->sc_hdev.sc_parent = iha->parent;
sc->sc_hdev.sc_report_id = iha->reportid;
ihidev_get_report_desc(iha->parent, &desc, &size);
repid = iha->reportid;
sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid);
sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid);
sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid);
if (hidms_setup(self, ms, 0, iha->reportid, desc, size) != 0)
return;
hidms_attach(ms, &ims_accessops);
}
int
ims_detach(struct device *self, int flags)
{
struct ims_softc *sc = (struct ims_softc *)self;
struct hidms *ms = &sc->sc_ms;
return hidms_detach(ms, flags);
}
void
ims_intr(struct ihidev *addr, void *buf, u_int len)
{
struct ims_softc *sc = (struct ims_softc *)addr;
struct hidms *ms = &sc->sc_ms;
if (ms->sc_enabled != 0)
hidms_input(ms, (uint8_t *)buf, len);
}
int
ims_enable(void *v)
{
struct ims_softc *sc = v;
struct hidms *ms = &sc->sc_ms;
int rv;
if ((rv = hidms_enable(ms)) != 0)
return rv;
return ihidev_open(&sc->sc_hdev);
}
void
ims_disable(void *v)
{
struct ims_softc *sc = v;
struct hidms *ms = &sc->sc_ms;
hidms_disable(ms);
ihidev_close(&sc->sc_hdev);
}
int
ims_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
{
struct ims_softc *sc = v;
struct hidms *ms = &sc->sc_ms;
int rc;
#if 0
rc = ihidev_ioctl(&sc->sc_hdev, cmd, data, flag, p);
if (rc != -1)
return rc;
#endif
rc = hidms_ioctl(ms, cmd, data, flag, p);
if (rc != -1)
return rc;
switch (cmd) {
case WSMOUSEIO_GTYPE:
*(u_int *)data = WSMOUSE_TYPE_TOUCHPAD;
return 0;
default:
return -1;
}
}