#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/ioctl.h>
#include <sys/conf.h>
#include <sys/tty.h>
#include <sys/fcntl.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/uhidev.h>
#include <dev/usb/uhid.h>
int ujoy_match(struct device *, void *, void *);
struct cfdriver ujoy_cd = {
NULL, "ujoy", DV_DULL
};
const struct cfattach ujoy_ca = {
sizeof(struct uhid_softc),
ujoy_match,
uhid_attach,
uhid_detach,
};
int
ujoy_hid_is_collection(const void *desc, int size, uint8_t id, int32_t usage)
{
struct hid_data *hd;
struct hid_item hi;
uint32_t coll_usage = ~0;
hd = hid_start_parse(desc, size, hid_input);
if (hd == NULL)
return (0);
while (hid_get_item(hd, &hi)) {
if (hi.kind == hid_collection &&
hi.collection == HCOLL_APPLICATION)
coll_usage = hi.usage;
if (hi.kind == hid_endcollection)
coll_usage = ~0;
if (hi.kind == hid_input &&
coll_usage == usage &&
hi.report_ID == id) {
hid_end_parse(hd);
return (1);
}
}
hid_end_parse(hd);
return (0);
}
int
ujoy_match(struct device *parent, void *match, void *aux)
{
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
int size;
void *desc;
int ret = UMATCH_NONE;
if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha))
return (ret);
uhidev_get_report_desc(uha->parent, &desc, &size);
if (ujoy_hid_is_collection(desc, size, uha->reportid,
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_JOYSTICK)))
ret = UMATCH_IFACECLASS;
if (ujoy_hid_is_collection(desc, size, uha->reportid,
HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_GAME_PAD)))
ret = UMATCH_IFACECLASS;
return (ret);
}
int
ujoyopen(dev_t dev, int flag, int mode, struct proc *p)
{
if ((flag & FWRITE))
return (EPERM);
return (uhid_do_open(dev, flag, mode, p));
}
int
ujoyioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
{
switch (cmd) {
case FIOASYNC:
case USB_GET_DEVICEINFO:
case USB_GET_REPORT:
case USB_GET_REPORT_DESC:
case USB_GET_REPORT_ID:
break;
default:
return (EPERM);
}
return (uhidioctl(dev, cmd, addr, flag, p));
}