Пример #1
0
const char *
ukbd_parse_desc(struct ukbd_softc *sc)
{
	struct hid_data *d;
	struct hid_item h;
	int size;
	void *desc;
	int imod;

	uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size);
	imod = 0;
	sc->sc_nkeycode = 0;
	d = hid_start_parse(desc, size, hid_input);
	while (hid_get_item(d, &h)) {
		/*printf("ukbd: id=%d kind=%d usage=0x%x flags=0x%x pos=%d size=%d cnt=%d\n",
		  h.report_ID, h.kind, h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count);*/
		if (h.kind != hid_input || (h.flags & HIO_CONST) ||
		    HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD ||
		    h.report_ID != sc->sc_hdev.sc_report_id)
			continue;
		DPRINTF(("ukbd: imod=%d usage=0x%x flags=0x%x pos=%d size=%d "
			 "cnt=%d\n", imod,
			 h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count));
		if (h.flags & HIO_VARIABLE) {
			if (h.loc.size != 1)
				return ("bad modifier size");
			/* Single item */
			if (imod < MAXMOD) {
				sc->sc_modloc[imod] = h.loc;
				sc->sc_mods[imod].mask = 1 << imod;
				sc->sc_mods[imod].key = HID_GET_USAGE(h.usage);
				imod++;
			} else
				return ("too many modifier keys");
		} else {
			/* Array */
			if (h.loc.size != 8)
				return ("key code size != 8");
			if (h.loc.count > MAXKEYCODE)
				return ("too many key codes");
			if (h.loc.pos % 8 != 0)
				return ("key codes not on byte boundary");
			if (sc->sc_nkeycode != 0)
				return ("multiple key code arrays\n");
			sc->sc_keycodeloc = h.loc;
			sc->sc_nkeycode = h.loc.count;
		}
	}
	sc->sc_nmod = imod;
	hid_end_parse(d);

	hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK),
		   sc->sc_hdev.sc_report_id, hid_output, &sc->sc_numloc, NULL);
	hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK),
		   sc->sc_hdev.sc_report_id, hid_output, &sc->sc_capsloc, NULL);
	hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK),
		   sc->sc_hdev.sc_report_id, hid_output, &sc->sc_scroloc, NULL);

	return (NULL);
}
Пример #2
0
int
ums_match(device_t parent, cfdata_t match, void *aux)
{
	struct uhidev_attach_arg *uha = aux;
	int size;
	void *desc;

	/*
	 * Some (older) Griffin PowerMate knobs may masquerade as a
	 * mouse, avoid treating them as such, they have only one axis.
	 */
	if (uha->uiaa->uiaa_vendor == USB_VENDOR_GRIFFIN &&
	    uha->uiaa->uiaa_product == USB_PRODUCT_GRIFFIN_POWERMATE)
		return UMATCH_NONE;

	uhidev_get_report_desc(uha->parent, &desc, &size);
	if (!hid_is_collection(desc, size, uha->reportid,
			       HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)) &&
	    !hid_is_collection(desc, size, uha->reportid,
			       HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_POINTER)) &&
	    !hid_is_collection(desc, size, uha->reportid,
			       HID_USAGE2(HUP_DIGITIZERS, 0x0002)))
		return UMATCH_NONE;

	return UMATCH_IFACECLASS;
}
Пример #3
0
void
utwitch_attach(struct device *parent, struct device *self, void *aux)
{
	struct utwitch_softc *sc = (struct utwitch_softc *)self;
	struct usb_attach_arg *uaa = aux;
	struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
	struct usbd_device *dev = uha->parent->sc_udev;
	int size, repid, err;
	void *desc;

	sc->sc_udev = dev;
	sc->sc_hdev.sc_intr = utwitch_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_report_id = uha->reportid;

	uhidev_get_report_desc(uha->parent, &desc, &size);
	repid = uha->reportid;
	sc->sc_ilen = hid_report_size(desc, size, hid_input, repid);
	sc->sc_olen = hid_report_size(desc, size, hid_output, repid);
	sc->sc_flen = hid_report_size(desc, size, hid_feature, repid);

	err = uhidev_open(&sc->sc_hdev);
	if (err) {
		printf("utwitch_open: uhidev_open %d\n", err);
		return;
	}
	sc->sc_ibuf = malloc(sc->sc_ilen, M_USBDEV, M_WAITOK);

	printf("\n");


	/* attach sensor */
	strlcpy(sc->sc_sensordev.xname, sc->sc_hdev.sc_dev.dv_xname,
	    sizeof(sc->sc_sensordev.xname));

	/* add BBU sensor */
	sc->sc_sensor_val.type = SENSOR_INTEGER;
	sensor_attach(&sc->sc_sensordev, &sc->sc_sensor_val);
	strlcpy(sc->sc_sensor_val.desc, "BBU",
		sizeof(sc->sc_sensor_val.desc));

	/* add BBU delta sensor */
	sc->sc_sensor_delta.type = SENSOR_INTEGER;
	sensor_attach(&sc->sc_sensordev, &sc->sc_sensor_delta);
	strlcpy(sc->sc_sensor_delta.desc, "mBBU/sec",
		sizeof(sc->sc_sensor_delta.desc));

	sc->sc_sensortask = sensor_task_register(sc, utwitch_refresh, UPDATE_TICK);
	if (sc->sc_sensortask == NULL) {
		printf(", unable to register update task\n");
		return;
	}
	sensordev_install(&sc->sc_sensordev);

	DPRINTF(("utwitch_attach: complete\n"));

	/* init device */ /* XXX */
	utwitch_set_mode(sc, 0);
}
Пример #4
0
int
ukbd_match(device_t parent, cfdata_t match, void *aux)
{
	struct uhidev_attach_arg *uha = aux;
	int size;
	void *desc;

	uhidev_get_report_desc(uha->parent, &desc, &size);
	if (!hid_is_collection(desc, size, uha->reportid,
			       HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
		return (UMATCH_NONE);

	return (UMATCH_IFACECLASS);
}
Пример #5
0
int
ums_match(struct device *parent, void *match, void *aux)
{
	struct usb_attach_arg *uaa = aux;
	struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
	int size;
	void *desc;

	uhidev_get_report_desc(uha->parent, &desc, &size);
	if (!hid_is_collection(desc, size, uha->reportid,
			       HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)))
		return (UMATCH_NONE);

	return (UMATCH_IFACECLASS);
}
Пример #6
0
void
ums_attach(struct device *parent, struct device *self, void *aux)
{
    struct ums_softc *sc = (struct ums_softc *)self;
    struct hidms *ms = &sc->sc_ms;
    struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
    struct usb_attach_arg *uaa = uha->uaa;
    int size, repid;
    void *desc;
    u_int32_t quirks;

    sc->sc_hdev.sc_intr = ums_intr;
    sc->sc_hdev.sc_parent = uha->parent;
    sc->sc_hdev.sc_udev = uaa->device;
    sc->sc_hdev.sc_report_id = uha->reportid;

    quirks = usbd_get_quirks(sc->sc_hdev.sc_udev)->uq_flags;
    uhidev_get_report_desc(uha->parent, &desc, &size);
    repid = uha->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, quirks, uha->reportid, desc, size) != 0)
        return;

    /*
     * The Microsoft Wireless Notebook Optical Mouse 3000 Model 1049 has
     * five Report IDs: 19, 23, 24, 17, 18 (in the order they appear in
     * report descriptor), it seems that report 17 contains the necessary
     * mouse information (3-buttons, X, Y, wheel) so we specify it
     * manually.
     */
    if (uaa->vendor == USB_VENDOR_MICROSOFT &&
            uaa->product == USB_PRODUCT_MICROSOFT_WLNOTEBOOK3) {
        ms->sc_flags = HIDMS_Z;
        ms->sc_num_buttons = 3;
        /* XXX change sc_hdev isize to 5? */
        ms->sc_loc_x.pos = 8;
        ms->sc_loc_y.pos = 16;
        ms->sc_loc_z.pos = 24;
        ms->sc_loc_btn[0].pos = 0;
        ms->sc_loc_btn[1].pos = 1;
        ms->sc_loc_btn[2].pos = 2;
    }

    hidms_attach(ms, &ums_accessops);
}
Пример #7
0
Static int
uts_match(device_t parent, cfdata_t match, void *aux)
{
	struct uhidev_attach_arg *uha = aux;
	int size;
	void *desc;

	uhidev_get_report_desc(uha->parent, &desc, &size);
	if (!hid_is_collection(desc, size, uha->reportid,
	    HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCH_SCREEN)) &&
	    !hid_is_collection(desc, size, uha->reportid,
	    HID_USAGE2(HUP_DIGITIZERS, HUD_FINGER)))
		return UMATCH_NONE;

	return UMATCH_IFACECLASS;
}
Пример #8
0
void
uhid_attach(struct device *parent, struct device *self, void *aux)
{
	struct uhid_softc *sc = (struct uhid_softc *)self;
	struct usb_attach_arg *uaa = aux;
	struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
	int size, repid;
	void *desc;

	sc->sc_hdev.sc_intr = uhid_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_report_id = uha->reportid;

	uhidev_get_report_desc(uha->parent, &desc, &size);
	repid = uha->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);

	printf(": input=%d, output=%d, feature=%d\n",
	    sc->sc_hdev.sc_isize, sc->sc_hdev.sc_osize, sc->sc_hdev.sc_fsize);
}
Пример #9
0
void
ums_attach(struct device *parent, struct device *self, void *aux)
{
	struct ums_softc *sc = (struct ums_softc *)self;
	struct usb_attach_arg *uaa = aux;
	struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
	struct wsmousedev_attach_args a;
	int size;
	void *desc;
	u_int32_t flags, quirks;
	int i, wheel, twheel;

	sc->sc_hdev.sc_intr = ums_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_report_id = uha->reportid;

	quirks = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
	if (quirks & UQ_MS_REVZ)
		sc->flags |= UMS_REVZ;
	if (quirks & UQ_SPUR_BUT_UP)
		sc->flags |= UMS_SPUR_BUT_UP;
	if (quirks & UQ_MS_LEADING_BYTE)
		sc->flags |= UMS_LEADINGBYTE;

	uhidev_get_report_desc(uha->parent, &desc, &size);

	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
	       uha->reportid, hid_input, &sc->sc_loc_x, &flags)) {
		printf("\n%s: mouse has no X report\n",
		       sc->sc_hdev.sc_dev.dv_xname);
		return;
	}
	if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
		printf("\n%s: X report 0x%04x not supported\n",
		       sc->sc_hdev.sc_dev.dv_xname, flags);
		return;
	}

	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
	       uha->reportid, hid_input, &sc->sc_loc_y, &flags)) {
		printf("\n%s: mouse has no Y report\n",
		       sc->sc_hdev.sc_dev.dv_xname);
		return;
	}
	if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
		printf("\n%s: Y report 0x%04x not supported\n",
		       sc->sc_hdev.sc_dev.dv_xname, flags);
		return;
	}

	/*
	 * Try to guess the Z activator: check WHEEL, TWHEEL, and Z,
	 * in that order.
	 */

	wheel = hid_locate(desc, size,
	    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
	    uha->reportid, hid_input, &sc->sc_loc_z, &flags);
	if (wheel == 0)
		twheel = hid_locate(desc, size,
		    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL),
		    uha->reportid, hid_input, &sc->sc_loc_z, &flags);
	else
		twheel = 0;

	if (wheel || twheel) {
		if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
			DPRINTF(("\n%s: Wheel report 0x%04x not supported\n",
				sc->sc_hdev.sc_dev.dv_xname, flags));
			sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
		} else {
			sc->flags |= UMS_Z;
			/* Wheels need the Z axis reversed. */
			sc->flags ^= UMS_REVZ;
		}
		/*
		 * We might have both a wheel and Z direction; in this case,
		 * report the Z direction on the W axis.
		*/
		if (hid_locate(desc, size,
		    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
		    uha->reportid, hid_input, &sc->sc_loc_w, &flags)) {
			if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
				DPRINTF(("\n%s: Z report 0x%04x not supported\n",
					sc->sc_hdev.sc_dev.dv_xname, flags));
				/* Bad Z coord, ignore it */
				sc->sc_loc_w.size = 0;
			}
			else
				sc->flags |= UMS_W;
		}
	} else if (hid_locate(desc, size,
	    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
	    uha->reportid, hid_input, &sc->sc_loc_z, &flags)) {
		if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
			DPRINTF(("\n%s: Z report 0x%04x not supported\n",
				sc->sc_hdev.sc_dev.dv_xname, flags));
			sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
		} else {
			sc->flags |= UMS_Z;
		}
	}

	/*
	 * The Microsoft Wireless Intellimouse 2.0 reports its wheel
	 * using 0x0048 (I've called it HUG_TWHEEL) and seems to expect
	 * us to know that the byte after the wheel is the tilt axis.
	 * There are no other HID axis descriptors other than X, Y and
	 * TWHEEL, so we report TWHEEL on the W axis.
	 */
	if (twheel) {
		sc->sc_loc_w = sc->sc_loc_z;
		sc->sc_loc_w.pos = sc->sc_loc_w.pos + 8;
		sc->flags |= UMS_W | UMS_LEADINGBYTE;
		/* Wheels need their axis reversed. */
		sc->flags ^= UMS_REVW;
	}

	/* figure out the number of buttons */
	for (i = 1; i <= MAX_BUTTONS; i++)
		if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
		    uha->reportid, hid_input, &sc->sc_loc_btn[i - 1], 0))
			break;
	sc->nbuttons = i - 1;

	/*
	 * The Microsoft Wireless Notebook Optical Mouse seems to be in worse
	 * shape than the Wireless Intellimouse 2.0, as its X, Y, wheel, and
	 * all of its other button positions are all off. It also reports that
	 * it has two addional buttons and a tilt wheel.
	 */
	if (quirks & UQ_MS_BAD_CLASS) {
		/* UMS_LEADINGBYTE cleared on purpose */
		sc->flags = UMS_Z | UMS_SPUR_BUT_UP;
		sc->nbuttons = 3;
		/* XXX change sc_hdev isize to 5? */
		/* 1st byte of descriptor report contains garbage */
		sc->sc_loc_x.pos = 16;
		sc->sc_loc_y.pos = 24;
		sc->sc_loc_z.pos = 32;
		sc->sc_loc_btn[0].pos = 8;
		sc->sc_loc_btn[1].pos = 9;
		sc->sc_loc_btn[2].pos = 10;
	}

	/*
	 * The Microsoft Wireless Notebook Optical Mouse 3000 Model 1049 has
	 * five Report IDs: 19, 23, 24, 17, 18 (in the order they appear in
	 * report descriptor), it seems that report 17 contains the necessary
	 * mouse information (3-buttons, X, Y, wheel) so we specify it
	 * manually.
	 */
	if (uaa->vendor == USB_VENDOR_MICROSOFT &&
	    uaa->product == USB_PRODUCT_MICROSOFT_WLNOTEBOOK3) {
		sc->flags = UMS_Z;
		sc->nbuttons = 3;
		/* XXX change sc_hdev isize to 5? */
		sc->sc_loc_x.pos = 8;
		sc->sc_loc_y.pos = 16;
		sc->sc_loc_z.pos = 24;
		sc->sc_loc_btn[0].pos = 0;
		sc->sc_loc_btn[1].pos = 1;
		sc->sc_loc_btn[2].pos = 2;
	}

	printf(": %d button%s",
	    sc->nbuttons, sc->nbuttons <= 1 ? "" : "s");
	switch (sc->flags & (UMS_Z | UMS_W)) {
	case UMS_Z:
		printf(", Z dir");
		break;
	case UMS_W:
		printf(", W dir");
		break;
	case UMS_Z | UMS_W:
		printf(", Z and W dir");
		break;
	}
	printf("\n");

#ifdef USB_DEBUG
	DPRINTF(("ums_attach: sc=%p\n", sc));
	DPRINTF(("ums_attach: X\t%d/%d\n",
	     sc->sc_loc_x.pos, sc->sc_loc_x.size));
	DPRINTF(("ums_attach: Y\t%d/%d\n",
	    sc->sc_loc_y.pos, sc->sc_loc_y.size));
	if (sc->flags & UMS_Z)
		DPRINTF(("ums_attach: Z\t%d/%d\n",
		    sc->sc_loc_z.pos, sc->sc_loc_z.size));
	if (sc->flags & UMS_W)
		DPRINTF(("ums_attach: W\t%d/%d\n",
		    sc->sc_loc_w.pos, sc->sc_loc_w.size));
	for (i = 1; i <= sc->nbuttons; i++) {
		DPRINTF(("ums_attach: B%d\t%d/%d\n",
		    i, sc->sc_loc_btn[i - 1].pos, sc->sc_loc_btn[i - 1].size));
	}
#endif

	a.accessops = &ums_accessops;
	a.accesscookie = sc;

	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
}
Пример #10
0
void
uoakv_attach(struct device *parent, struct device *self, void *aux)
{
	struct uoakv_softc *sc = (struct uoakv_softc *)self;
	struct usb_attach_arg *uaa = aux;
	struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
	struct usbd_device *dev = uha->parent->sc_udev;

	struct uoak_softc *scc = &sc->sc_uoak_softc;
	int i, err, size, repid;
	void *desc;

	sc->sc_hdev.sc_intr = uoakv_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_report_id = uha->reportid;

	scc->sc_parent = sc;
	scc->sc_udev = dev;
	scc->sc_hdev = &sc->sc_hdev;
	scc->sc_methods = &uoakv_methods;
	scc->sc_sensordev = &sc->sc_sensordev;

	uhidev_get_report_desc(uha->parent, &desc, &size);
	repid = uha->reportid;
	scc->sc_ilen = hid_report_size(desc, size, hid_input, repid);
	scc->sc_olen = hid_report_size(desc, size, hid_output, repid);
	scc->sc_flen = hid_report_size(desc, size, hid_feature, repid);

	/* device initialize */
	(void)uoak_led_ctrl(scc, OAK_TARGET_RAM, OAK_LED_ON);
	err = uoak_set_sample_rate(scc, OAK_TARGET_RAM, UOAKV_SAMPLE_RATE);
	if (err) {
		printf("%s: could not set sampling rate. exit\n",
		    sc->sc_hdev.sc_dev.dv_xname);
		return;
	}

	/* query and print device setting */
	uoak_get_devinfo(scc);
	uoak_print_devinfo(scc);

	DPRINTF((" config in RAM\n"));
	uoak_get_setting(scc, OAK_TARGET_RAM);
	uoak_print_setting(scc, OAK_TARGET_RAM);
#ifdef UOAKV_DEBUG
	DPRINTF((" config in FRASH\n"));
	uoak_get_setting(scc, OAK_TARGET_FLASH);
	uoak_print_setting(scc, OAK_TARGET_FLASH);
#endif

	/* attach sensor */
	strlcpy(sc->sc_sensordev.xname, sc->sc_hdev.sc_dev.dv_xname,
	    sizeof(sc->sc_sensordev.xname));
	for (i = 0; i < OAK_V_MAXSENSORS; i++)
		uoak_sensor_attach(scc, &sc->sc_sensor[i].v, SENSOR_VOLTS_DC);

	/* start sensor */
	sc->sc_sensortask = sensor_task_register(sc, uoakv_refresh,
	    UOAKV_REFRESH_PERIOD);
	if (sc->sc_sensortask == NULL) {
		printf(", unable to register update task\n");
		return;
	}
	sensordev_install(&sc->sc_sensordev);

	err = uhidev_open(&sc->sc_hdev);
	if (err) {
		printf("%s: could not open interrupt pipe, quit\n",
		    sc->sc_hdev.sc_dev.dv_xname);
		return;
	}
	scc->sc_ibuf = malloc(scc->sc_ilen, M_USBDEV, M_WAITOK);

	DPRINTF(("uoakv_attach: complete\n"));
}
Пример #11
0
void
ums_attach(device_t parent, device_t self, void *aux)
{
	struct ums_softc *sc = device_private(self);
	struct uhidev_attach_arg *uha = aux;
	struct wsmousedev_attach_args a;
	int size;
	void *desc;
	uint32_t flags, quirks;
	int i, hl;
	struct hid_location *zloc;
	bool isdigitizer;

	aprint_naive("\n");

	sc->sc_hdev.sc_dev = self;
	sc->sc_hdev.sc_intr = ums_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_report_id = uha->reportid;

	quirks = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
	if (quirks & UQ_MS_REVZ)
		sc->flags |= UMS_REVZ;
	if (quirks & UQ_SPUR_BUT_UP)
		sc->flags |= UMS_SPUR_BUT_UP;

	uhidev_get_report_desc(uha->parent, &desc, &size);

	isdigitizer = hid_is_collection(desc, size, uha->reportid,
	    HID_USAGE2(HUP_DIGITIZERS, 0x0002));

	if (!pmf_device_register(self, NULL, NULL))
		aprint_error_dev(self, "couldn't establish power handler\n");

	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
	       uha->reportid, hid_input, &sc->sc_loc_x, &flags)) {
		aprint_error("\n%s: mouse has no X report\n",
		       device_xname(sc->sc_hdev.sc_dev));
		return;
	}
	switch (flags & MOUSE_FLAGS_MASK) {
	case 0:
		sc->flags |= UMS_ABS;
		break;
	case HIO_RELATIVE:
		break;
	default:
		aprint_error("\n%s: X report 0x%04x not supported\n",
		       device_xname(sc->sc_hdev.sc_dev), flags);
		return;
	}

	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
	       uha->reportid, hid_input, &sc->sc_loc_y, &flags)) {
		aprint_error("\n%s: mouse has no Y report\n",
		       device_xname(sc->sc_hdev.sc_dev));
		return;
	}
	switch (flags & MOUSE_FLAGS_MASK) {
	case 0:
		sc->flags |= UMS_ABS;
		break;
	case HIO_RELATIVE:
		break;
	default:
		aprint_error("\n%s: Y report 0x%04x not supported\n",
		       device_xname(sc->sc_hdev.sc_dev), flags);
		return;
	}

	/* Try the wheel first as the Z activator since it's tradition. */
	hl = hid_locate(desc,
			size,
			HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
			uha->reportid,
			hid_input,
			&sc->sc_loc_z,
			&flags);

	zloc = &sc->sc_loc_z;
	if (hl) {
		if ((flags & MOUSE_FLAGS_MASK) != HIO_RELATIVE) {
			aprint_verbose("\n%s: Wheel report 0x%04x not "
			    "supported\n", device_xname(sc->sc_hdev.sc_dev),
			    flags);
			sc->sc_loc_z.size = 0;	/* Bad Z coord, ignore it */
		} else {
			sc->flags |= UMS_Z;
			/* Wheels need the Z axis reversed. */
			sc->flags ^= UMS_REVZ;
			/* Put Z on the W coordinate */
			zloc = &sc->sc_loc_w;
		}
	}

	hl = hid_locate(desc,
			size,
			HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
			uha->reportid,
			hid_input,
			zloc,
			&flags);

	/*
	 * The horizontal component of the scrollball can also be given by
	 * Application Control Pan in the Consumer page, so if we didnt see
	 * any Z then check that.
	 */
	if (!hl) {
		hl = hid_locate(desc,
				size,
				HID_USAGE2(HUP_CONSUMER, HUC_AC_PAN),
				uha->reportid,
				hid_input,
				zloc,
				&flags);
	}

	if (hl) {
		if ((flags & MOUSE_FLAGS_MASK) != HIO_RELATIVE) {
			aprint_verbose("\n%s: Z report 0x%04x not supported\n",
			       device_xname(sc->sc_hdev.sc_dev), flags);
			zloc->size = 0;	/* Bad Z coord, ignore it */
		} else {
			if (sc->flags & UMS_Z)
				sc->flags |= UMS_W;
			else
				sc->flags |= UMS_Z;
		}
	}

	if (uha->uiaa->uiaa_vendor == USB_VENDOR_MICROSOFT) {
		int fixpos;
		/*
		 * The Microsoft Wireless Laser Mouse 6000 v2.0 and the
		 * Microsoft Comfort Mouse 2.0 report a bad position for
		 * the wheel and wheel tilt controls -- should be in bytes
		 * 3 & 4 of the report. Fix this if necessary.
		 */
		switch (uha->uiaa->uiaa_product) {
		case USB_PRODUCT_MICROSOFT_24GHZ_XCVR10:
		case USB_PRODUCT_MICROSOFT_24GHZ_XCVR20:
			fixpos = 24;
			break;
		case USB_PRODUCT_MICROSOFT_CM6000:
			fixpos = 40;
			break;
		default:
			fixpos = 0;
			break;
		}
		if (fixpos) {
			if ((sc->flags & UMS_Z) && sc->sc_loc_z.pos == 0)
				sc->sc_loc_z.pos = fixpos;
			if ((sc->flags & UMS_W) && sc->sc_loc_w.pos == 0)
				sc->sc_loc_w.pos = sc->sc_loc_z.pos + 8;
		}
	}

	/* figure out the number of buttons */
	for (i = 1; i <= MAX_BUTTONS; i++)
		if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
		    uha->reportid, hid_input, &sc->sc_loc_btn[i - 1], 0))
			break;

	if (isdigitizer) {
		for (size_t j = 0; j < __arraycount(digbut); j++) {
			if (hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS,
			    digbut[j].feature), uha->reportid, hid_input,
			    &sc->sc_loc_btn[i - 1], 0)) {
				if (i <= MAX_BUTTONS) {
					i++;
					sc->flags |= digbut[j].flag;
				} else
					aprint_error_dev(self,
					    "ran out of buttons\n");
			}
		}
	}
	sc->nbuttons = i - 1;

	aprint_normal(": %d button%s%s%s%s%s%s%s%s%s\n",
	    sc->nbuttons, sc->nbuttons == 1 ? "" : "s",
	    sc->flags & UMS_W ? ", W" : "",
	    sc->flags & UMS_Z ? " and Z dir" : "",
	    sc->flags & UMS_W ? "s" : "",
	    isdigitizer ? " digitizer"  : "",
	    sc->flags & UMS_TIP_SWITCH ? ", tip" : "",
	    sc->flags & UMS_SEC_TIP_SWITCH ? ", sec tip" : "",
	    sc->flags & UMS_BARREL_SWITCH ? ", barrel" : "",
	    sc->flags & UMS_ERASER ? ", eraser" : "");

#ifdef UMS_DEBUG
	DPRINTF(("ums_attach: sc=%p\n", sc));
	DPRINTF(("ums_attach: X\t%d/%d\n",
		 sc->sc_loc_x.pos, sc->sc_loc_x.size));
	DPRINTF(("ums_attach: Y\t%d/%d\n",
		 sc->sc_loc_y.pos, sc->sc_loc_y.size));
	if (sc->flags & UMS_Z)
		DPRINTF(("ums_attach: Z\t%d/%d\n",
			 sc->sc_loc_z.pos, sc->sc_loc_z.size));
	if (sc->flags & UMS_W)
		DPRINTF(("ums_attach: W\t%d/%d\n",
			 sc->sc_loc_w.pos, sc->sc_loc_w.size));
	for (i = 1; i <= sc->nbuttons; i++) {
		DPRINTF(("ums_attach: B%d\t%d/%d\n",
			 i, sc->sc_loc_btn[i-1].pos,sc->sc_loc_btn[i-1].size));
	}
#endif

	a.accessops = &ums_accessops;
	a.accesscookie = sc;

	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);

	return;
}
Пример #12
0
void 
uyurex_attach(device_t parent, device_t self, void *aux)
{
	struct uyurex_softc *sc = device_private(self);
	struct usb_attach_arg *uaa = aux;
	struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
	usbd_device_handle dev = uha->parent->sc_udev;
	int size, repid, err;
	void *desc;

	sc->sc_udev = dev;
	sc->sc_hdev.sc_dev = self;
	sc->sc_hdev.sc_intr = uyurex_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_report_id = uha->reportid;

	uhidev_get_report_desc(uha->parent, &desc, &size);
	repid = uha->reportid;
	sc->sc_ilen = hid_report_size(desc, size, hid_input, repid);
	sc->sc_olen = hid_report_size(desc, size, hid_output, repid);
	sc->sc_flen = hid_report_size(desc, size, hid_feature, repid);

	aprint_normal("\n");
	aprint_naive("\n");

	err = uhidev_open(&sc->sc_hdev);
	if (err) {
		aprint_error_dev(self, "uyurex_open: uhidev_open %d\n", err);
		return;
	}
	sc->sc_ibuf = malloc(sc->sc_ilen, M_USBDEV, M_WAITOK);

	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
	    sc->sc_hdev.sc_dev);

	/* attach sensor */
	sc->sc_sme = sysmon_envsys_create();
	/* error handling? XXX */
	sc->sc_sme->sme_name = device_xname(self);

	/* add BBU sensor */
	sc->sc_sensor_val.units = ENVSYS_INTEGER;
	sc->sc_sensor_val.state = ENVSYS_SINVALID;
	sc->sc_sensor_val.flags = ENVSYS_FMONCRITICAL;	/* abuse XXX */
	strlcpy(sc->sc_sensor_val.desc, "BBU",
		sizeof(sc->sc_sensor_val.desc));
	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor_val);

	/* add BBU delta sensor */
	sc->sc_sensor_delta.units = ENVSYS_INTEGER;
	sc->sc_sensor_delta.state = ENVSYS_SINVALID;
	strlcpy(sc->sc_sensor_delta.desc, "mBBU/sec",
		sizeof(sc->sc_sensor_delta.desc));
	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor_delta);

	sc->sc_sme->sme_cookie = sc;
	sc->sc_sme->sme_refresh = uyurex_refresh;
	sc->sc_sme->sme_events_timeout = UPDATE_TICK;
	sc->sc_sme->sme_flags = SME_INIT_REFRESH;
	if (sysmon_envsys_register(sc->sc_sme)) {
		aprint_error_dev(self, "unable to register with sysmon\n");
		sysmon_envsys_destroy(sc->sc_sme);
	}

	callout_init(&sc->sc_deltach, 0);
	callout_reset(&sc->sc_deltach, UPDATE_TICK * hz, uyurex_delta, sc);

	DPRINTF(("uyurex_attach: complete\n"));

	/* init device */ /* XXX */
	uyurex_set_mode(sc, 0);
}
Пример #13
0
void
uslhcom_attach(struct device *parent, struct device *self, void *aux)
{
	struct uslhcom_softc *sc = (struct uslhcom_softc *)self;
	struct uhidev_attach_arg *uha = aux;
	struct usbd_device *dev = uha->parent->sc_udev;
	struct ucom_attach_args uca;
	struct uslhcom_version_info version;
	int err, repid, size, rsize;
	void *desc;

	sc->sc_udev = dev;
	sc->sc_lsr = sc->sc_msr = 0;
	sc->sc_hdev.sc_intr = uslhcom_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_report_id = uha->reportid;
	sc->sc_hdev.sc_isize = sc->sc_hdev.sc_osize = sc->sc_hdev.sc_fsize = 0;

	uhidev_get_report_desc(uha->parent, &desc, &size);
	for (repid = 0; repid < uha->parent->sc_nrepid; repid++) {
		rsize = hid_report_size(desc, size, hid_input, repid);
		if (sc->sc_hdev.sc_isize < rsize) sc->sc_hdev.sc_isize = rsize;
		rsize = hid_report_size(desc, size, hid_output, repid);
		if (sc->sc_hdev.sc_osize < rsize) sc->sc_hdev.sc_osize = rsize;
		rsize = hid_report_size(desc, size, hid_feature, repid);
		if (sc->sc_hdev.sc_fsize < rsize) sc->sc_hdev.sc_fsize = rsize;
	}

	printf("\n");

	err = uhidev_open(&sc->sc_hdev);
	if (err) {
		DPRINTF(("uslhcom_attach: uhidev_open %d\n", err));
		return;
	}

	DPRINTF(("uslhcom_attach: sc %p opipe %p ipipe %p report_id %d\n",
		 sc, sc->sc_hdev.sc_parent->sc_opipe,
		 sc->sc_hdev.sc_parent->sc_ipipe, uha->reportid));
	DPRINTF(("uslhcom_attach: isize %d osize %d fsize %d\n",
		 sc->sc_hdev.sc_isize, sc->sc_hdev.sc_osize,
		 sc->sc_hdev.sc_fsize));

	uslhcom_uart_endis(sc, UART_DISABLE);
	uslhcom_get_version(sc, &version);
	printf("%s: pid %#x rev %#x\n", sc->sc_hdev.sc_dev.dv_xname,
	       version.product_id, version.product_revision);

	/* setup ucom layer */
	uca.portno = UCOM_UNK_PORTNO;
	uca.bulkin = uca.bulkout = -1;
	uca.ibufsize = uca.ibufsizepad = 0;
	uca.obufsize = sc->sc_hdev.sc_osize;
	uca.opkthdrlen = USLHCOM_TX_HEADER_SIZE;
	uca.uhidev = sc->sc_hdev.sc_parent;
	uca.device = uha->uaa->device;
	uca.iface = uha->uaa->iface;
	uca.methods = &uslhcom_methods;
	uca.arg = sc;
	uca.info = NULL;

	sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
}
Пример #14
0
int
uhidev_ioctl(struct uhidev *sc, u_long cmd, caddr_t addr, int flag,
    struct proc *p)
{
	struct usb_ctl_report_desc *rd;
	struct usb_ctl_report *re;
	int size, extra;
	usbd_status err;
	void *desc;

	switch (cmd) {
	case USB_GET_REPORT_DESC:
		uhidev_get_report_desc(sc->sc_parent, &desc, &size);
		rd = (struct usb_ctl_report_desc *)addr;
		size = min(size, sizeof rd->ucrd_data);
		rd->ucrd_size = size;
		memcpy(rd->ucrd_data, desc, size);
		break;
	case USB_GET_REPORT:
		re = (struct usb_ctl_report *)addr;
		switch (re->ucr_report) {
		case UHID_INPUT_REPORT:
			size = sc->sc_isize;
			break;
		case UHID_OUTPUT_REPORT:
			size = sc->sc_osize;
			break;
		case UHID_FEATURE_REPORT:
			size = sc->sc_fsize;
			break;
		default:
			return EINVAL;
		}
		extra = sc->sc_report_id != 0;
		err = uhidev_get_report(sc, re->ucr_report, re->ucr_data,
		    size + extra);
		if (extra)
			memcpy(re->ucr_data, re->ucr_data + 1, size);
		if (err)
			return EIO;
		break;
	case USB_SET_REPORT:
		re = (struct usb_ctl_report *)addr;
		switch (re->ucr_report) {
		case UHID_INPUT_REPORT:
			size = sc->sc_isize;
			break;
		case UHID_OUTPUT_REPORT:
			size = sc->sc_osize;
			break;
		case UHID_FEATURE_REPORT:
			size = sc->sc_fsize;
			break;
		default:
			return EINVAL;
		}
		err = uhidev_set_report(sc, re->ucr_report, re->ucr_data, size);
		if (err)
			return EIO;
		break;
	case USB_GET_REPORT_ID:
		*(int *)addr = sc->sc_report_id;
		break;
	default:
		return -1;
	}
	return 0;
}
Пример #15
0
void
ukbd_attach(struct device *parent, struct device *self, void *aux)
{
	struct ukbd_softc *sc = (struct ukbd_softc *)self;
	struct hidkbd *kbd = &sc->sc_kbd;
	struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
	struct usb_hid_descriptor *hid;
	u_int32_t qflags;
	int dlen, repid;
	void *desc;
	kbd_t layout = (kbd_t)-1;

	sc->sc_hdev.sc_intr = ukbd_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_udev = uha->uaa->device;
	sc->sc_hdev.sc_report_id = uha->reportid;

	uhidev_get_report_desc(uha->parent, &desc, &dlen);
	repid = uha->reportid;
	sc->sc_hdev.sc_isize = hid_report_size(desc, dlen, hid_input, repid);
	sc->sc_hdev.sc_osize = hid_report_size(desc, dlen, hid_output, repid);
	sc->sc_hdev.sc_fsize = hid_report_size(desc, dlen, hid_feature, repid);

	qflags = usbd_get_quirks(sc->sc_hdev.sc_udev)->uq_flags;
	if (hidkbd_attach(self, kbd, 1, qflags, repid, desc, dlen) != 0)
		return;

	if (uha->uaa->vendor == USB_VENDOR_APPLE) {
		int iso = 0;

		if ((uha->uaa->product == USB_PRODUCT_APPLE_FOUNTAIN_ISO) ||
 		    (uha->uaa->product == USB_PRODUCT_APPLE_GEYSER_ISO))
 		    	iso = 1;

		if (hid_locate(desc, dlen, HID_USAGE2(HUP_APPLE, HUG_FN_KEY),
		    uha->reportid, hid_input, &sc->sc_apple_fn, &qflags)) {
			if (qflags & HIO_VARIABLE) {
				if (iso)
					sc->sc_munge = ukbd_apple_iso_munge;
				else
					sc->sc_munge = ukbd_apple_munge;
			}
		}
	}

	if (uha->uaa->vendor == USB_VENDOR_TOPRE &&
	    uha->uaa->product == USB_PRODUCT_TOPRE_HHKB) {
		/* ignore country code on purpose */
	} else {
		hid = usbd_get_hid_descriptor(uha->uaa->iface);

		if (hid->bCountryCode <= HCC_MAX)
			layout = ukbd_countrylayout[hid->bCountryCode];
#ifdef DIAGNOSTIC
		if (hid->bCountryCode != 0)
			printf(", country code %d", hid->bCountryCode);
#endif
	}
	if (layout == (kbd_t)-1) {
#ifdef UKBD_LAYOUT
		layout = UKBD_LAYOUT;
#else
		layout = KB_US | KB_DEFAULT;
#endif
	}

	printf("\n");

#ifdef __loongson__
	if (uha->uaa->vendor == USB_VENDOR_CYPRESS &&
	    uha->uaa->product == USB_PRODUCT_CYPRESS_LPRDK)
		sc->sc_munge = ukbd_gdium_munge;
#endif

	if (kbd->sc_console_keyboard) {
		extern struct wskbd_mapdata ukbd_keymapdata;

		DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc));
		ukbd_keymapdata.layout = layout;
		wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata);
		ukbd_enable(sc, 1);
	}

	/* Flash the leds; no real purpose, just shows we're alive. */
	ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM |
		          WSKBD_LED_CAPS | WSKBD_LED_COMPOSE);
	usbd_delay_ms(sc->sc_hdev.sc_udev, 400);
	ukbd_set_leds(sc, 0);

	hidkbd_attach_wskbd(kbd, layout, &ukbd_accessops);
}
Пример #16
0
Static void
uts_attach(device_t parent, device_t self, void *aux)
{
	struct uts_softc *sc = device_private(self);
	struct uhidev_attach_arg *uha = aux;
	struct wsmousedev_attach_args a;
	int size;
	void *desc;
	uint32_t flags;
	struct hid_data * d;
	struct hid_item item;

	aprint_naive("\n");

	sc->sc_hdev.sc_dev = self;
	sc->sc_hdev.sc_intr = uts_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_report_id = uha->reportid;

	uhidev_get_report_desc(uha->parent, &desc, &size);

	if (!pmf_device_register(self, NULL, NULL))
		aprint_error_dev(self, "couldn't establish power handler\n");

	/* requires HID usage Generic_Desktop:X */
	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
		uha->reportid, hid_input, &sc->sc_loc_x, &flags)) {
		aprint_error_dev(sc->sc_hdev.sc_dev,
		    "touchscreen has no X report\n");
		return;
	}
	switch (flags & TSCREEN_FLAGS_MASK) {
	case 0:
		sc->flags |= UTS_ABS;
		break;
	case HIO_RELATIVE:
		break;
	default:
		aprint_error_dev(sc->sc_hdev.sc_dev,
		    "X report 0x%04x not supported\n", flags);
		return;
	}

	/* requires HID usage Generic_Desktop:Y */
	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
		uha->reportid, hid_input, &sc->sc_loc_y, &flags)) {
		aprint_error_dev(sc->sc_hdev.sc_dev,
		    "touchscreen has no Y report\n");
		return;
	}
	switch (flags & TSCREEN_FLAGS_MASK) {
	case 0:
		sc->flags |= UTS_ABS;
		break;
	case HIO_RELATIVE:
		break;
	default:
		aprint_error_dev(sc->sc_hdev.sc_dev,
		    "Y report 0x%04x not supported\n", flags);
		return;
	}

	/* requires HID usage Digitizer:Tip_Switch */
	if (!hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_SWITCH),
	    uha->reportid, hid_input, &sc->sc_loc_btn, 0)) {
		aprint_error_dev(sc->sc_hdev.sc_dev,
		    "touchscreen has no tip switch report\n");
		return;
	}

	/* requires HID usage Digitizer:In_Range */
	if (!hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS, HUD_IN_RANGE),
		uha->reportid, hid_input, &sc->sc_loc_z, &flags)) {
		aprint_error_dev(sc->sc_hdev.sc_dev,
		    "touchscreen has no range report\n");
		return;
	}

	/* multi-touch support would need HUD_CONTACTID and HUD_CONTACTMAX */

#ifdef UTS_DEBUG
	DPRINTF(("uts_attach: sc=%p\n", sc));
	DPRINTF(("uts_attach: X\t%d/%d\n",
		sc->sc_loc_x.pos, sc->sc_loc_x.size));
	DPRINTF(("uts_attach: Y\t%d/%d\n",
		sc->sc_loc_y.pos, sc->sc_loc_y.size));
	DPRINTF(("uts_attach: Z\t%d/%d\n",
		sc->sc_loc_z.pos, sc->sc_loc_z.size));
#endif

	a.accessops = &uts_accessops;
	a.accesscookie = sc;

	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);

	/* calibrate the touchscreen */
	memset(&sc->sc_calibcoords, 0, sizeof(sc->sc_calibcoords));
	sc->sc_calibcoords.maxx = 4095;
	sc->sc_calibcoords.maxy = 4095;
	sc->sc_calibcoords.samplelen = WSMOUSE_CALIBCOORDS_RESET;
	d = hid_start_parse(desc, size, hid_input);
	while (hid_get_item(d, &item)) {
		if (item.kind != hid_input
		    || HID_GET_USAGE_PAGE(item.usage) != HUP_GENERIC_DESKTOP
		    || item.report_ID != sc->sc_hdev.sc_report_id)
			continue;
		if (HID_GET_USAGE(item.usage) == HUG_X) {
			sc->sc_calibcoords.minx = item.logical_minimum;
			sc->sc_calibcoords.maxx = item.logical_maximum;
		}
		if (HID_GET_USAGE(item.usage) == HUG_Y) {
			sc->sc_calibcoords.miny = item.logical_minimum;
			sc->sc_calibcoords.maxy = item.logical_maximum;
		}
	}
	hid_end_parse(d);

	tpcalib_init(&sc->sc_tpcalib);
	tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
	    (void *)&sc->sc_calibcoords, 0, 0);

	return;
}