예제 #1
0
static void
btms_input(struct bthidev *self, uint8_t *data, int len)
{
	struct btms_softc *sc = (struct btms_softc *)self;
	int dx, dy, dz, dw;
	uint32_t buttons;
	int i, s;

	if (sc->sc_wsmouse == NULL || sc->sc_enabled == 0)
		return;

	dx =  hid_get_data(data, &sc->sc_loc_x);
	dy = -hid_get_data(data, &sc->sc_loc_y);
	dz =  hid_get_data(data, &sc->sc_loc_z);
	dw =  hid_get_data(data, &sc->sc_loc_w);

	if (sc->sc_flags & BTMS_REVZ)
		dz = -dz;

	buttons = 0;
	for (i = 0 ; i < sc->sc_num_buttons ; i++)
		if (hid_get_data(data, &sc->sc_loc_button[i]))
			buttons |= BUTTON(i);

	if (dx != 0 || dy != 0 || dz != 0 || dw != 0 || buttons != sc->sc_buttons) {
		sc->sc_buttons = buttons;

		s = spltty();
		wsmouse_input(sc->sc_wsmouse,
				buttons,
				dx, dy, dz, dw,
				WSMOUSE_INPUT_DELTA);
		splx(s);
	}
}
예제 #2
0
void
ums_intr(struct uhidev *addr, void *buf, u_int len)
{
	struct ums_softc *sc = (struct ums_softc *)addr;
	u_char *ibuf = (u_char *)buf;
	int dx, dy, dz, dw;
	u_int32_t buttons = 0;
	int i;
	int s;

	DPRINTFN(5,("ums_intr: len=%d\n", len));

	/*
	 * The Microsoft Wireless Intellimouse 2.0 sends one extra leading
	 * byte of data compared to most USB mice.  This byte frequently
	 * switches from 0x01 (usual state) to 0x02.  It may be used to
	 * report non-standard events (such as battery life).  However,
	 * at the same time, it generates a left click event on the
	 * button byte, where there shouldn't be any.  We simply discard
	 * the packet in this case.
	 *
	 * This problem affects the MS Wireless Notebook Optical Mouse, too.
	 * However, the leading byte for this mouse is normally 0x11, and
	 * the phantom mouse click occurs when it's 0x14.
	 */
	if (sc->flags & UMS_LEADINGBYTE) {
		if (*ibuf++ == 0x02)
			return;
		/* len--; */
	} else if (sc->flags & UMS_SPUR_BUT_UP) {
		if (*ibuf == 0x14 || *ibuf == 0x15)
			return;
	}

	dx =  hid_get_data(ibuf, &sc->sc_loc_x);
	dy = -hid_get_data(ibuf, &sc->sc_loc_y);
	dz =  hid_get_data(ibuf, &sc->sc_loc_z);
	dw =  hid_get_data(ibuf, &sc->sc_loc_w);
	if (sc->flags & UMS_REVZ)
		dz = -dz;
	if (sc->flags & UMS_REVW)
		dw = -dw;
	for (i = 0; i < sc->nbuttons; i++)
		if (hid_get_data(ibuf, &sc->sc_loc_btn[i]))
			buttons |= (1 << UMS_BUT(i));

	if (dx != 0 || dy != 0 || dz != 0 || dw != 0 ||
	    buttons != sc->sc_buttons) {
		DPRINTFN(10, ("ums_intr: x:%d y:%d z:%d w:%d buttons:0x%x\n",
			dx, dy, dz, dw, buttons));
		sc->sc_buttons = buttons;
		if (sc->sc_wsmousedev != NULL) {
			s = spltty();
			wsmouse_input(sc->sc_wsmousedev, buttons,
			    dx, dy, dz, dw, WSMOUSE_INPUT_DELTA);
			splx(s);
		}
	}
}
예제 #3
0
파일: ums.c 프로젝트: MarginC/kame
void
ums_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
{
	struct ums_softc *sc = addr;
	u_char *ibuf;
	int dx, dy, dz;
	u_int32_t buttons = 0;
	int i;
	int s;

	DPRINTFN(5, ("ums_intr: sc=%p status=%d\n", sc, status));
	DPRINTFN(5, ("ums_intr: data = %02x %02x %02x\n",
		     sc->sc_ibuf[0], sc->sc_ibuf[1], sc->sc_ibuf[2]));

	if (status == USBD_CANCELLED)
		return;

	if (status) {
		DPRINTF(("ums_intr: status=%d\n", status));
		usbd_clear_endpoint_stall_async(sc->sc_intrpipe);
		return;
	}

	ibuf = sc->sc_ibuf;
	if (sc->sc_iid != 0) {
		if (*ibuf++ != sc->sc_iid)
			return;
	}
	dx =  hid_get_data(ibuf, &sc->sc_loc_x);
	dy = -hid_get_data(ibuf, &sc->sc_loc_y);
	dz =  hid_get_data(ibuf, &sc->sc_loc_z);
	if (sc->flags & UMS_REVZ)
		dz = -dz;
	for (i = 0; i < sc->nbuttons; i++)
		if (hid_get_data(ibuf, &sc->sc_loc_btn[i]))
			buttons |= (1 << UMS_BUT(i));

	if (dx != 0 || dy != 0 || dz != 0 || buttons != sc->sc_buttons) {
		DPRINTFN(10, ("ums_intr: x:%d y:%d z:%d buttons:0x%x\n",
			dx, dy, dz, buttons));
		sc->sc_buttons = buttons;
		if (sc->sc_wsmousedev != NULL) {
			s = spltty();
			wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, dz,
				      WSMOUSE_INPUT_DELTA);
			splx(s);
		}
	}
}
예제 #4
0
파일: btms.c 프로젝트: goroutines/rumprun
static void
btms_input(struct bthidev *hidev, uint8_t *data, int len)
{
	struct btms_softc *sc = (struct btms_softc *)hidev;
	int dx, dy, dz, dw;
	uint32_t buttons;
	int i, s;

	if (sc->sc_wsmouse == NULL || sc->sc_enabled == 0)
		return;

#ifdef BTMS_DEBUG
	if (btms_debug > 9) {
		printf("%s: data: ", __func__);
		for (i = 0; i < len; ++i) {
			printf("%02x", data[i]);
		}
		printf("\n");
	}
#endif

	dx =  hid_get_data(data, &sc->sc_loc_x);
	dy = -hid_get_data(data, &sc->sc_loc_y);
	dz =  hid_get_data(data, &sc->sc_loc_z);
	dw =  hid_get_data(data, &sc->sc_loc_w);

	if (sc->sc_flags & BTMS_REVZ)
		dz = -dz;

	buttons = 0;
	for (i = 0 ; i < sc->sc_num_buttons ; i++)
		if (hid_get_data(data, &sc->sc_loc_button[i]))
			buttons |= BUTTON(i);

	BTMSDBGN(9,("%s: dx=%d, dy=%d, dz=%d, dw=%d, buttons=0x%08x\n",
	    __func__, dx, dy, dz, dw, buttons));
	if (dx != 0 || dy != 0 || dz != 0 || dw != 0 || buttons != sc->sc_buttons) {
		sc->sc_buttons = buttons;

		s = spltty();
		wsmouse_input(sc->sc_wsmouse,
				buttons,
				dx, dy, dz, dw,
				WSMOUSE_INPUT_DELTA);
		splx(s);
	}
}
예제 #5
0
파일: uts.c 프로젝트: ryo/netbsd-src
Static void
uts_intr(struct uhidev *addr, void *ibuf, u_int len)
{
	struct uts_softc *sc = (struct uts_softc *)addr;
	int dx, dy, dz;
	uint32_t buttons = 0;
	int flags, s;

	DPRINTFN(5,("uts_intr: len=%d\n", len));

	flags = WSMOUSE_INPUT_DELTA | WSMOUSE_INPUT_ABSOLUTE_Z;

	dx = hid_get_data(ibuf, &sc->sc_loc_x);
	if (sc->flags & UTS_ABS) {
		flags |= (WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
		dy = hid_get_data(ibuf, &sc->sc_loc_y);
		tpcalib_trans(&sc->sc_tpcalib, dx, dy, &dx, &dy);
	} else
		dy = -hid_get_data(ibuf, &sc->sc_loc_y);

	dz = hid_get_data(ibuf, &sc->sc_loc_z);

	if (hid_get_data(ibuf, &sc->sc_loc_btn))
		buttons |= 1;

	if (dx != 0 || dy != 0 || dz != 0 || buttons != sc->sc_buttons) {
		DPRINTFN(10,("uts_intr: x:%d y:%d z:%d buttons:0x%x\n",
		    dx, dy, dz, buttons));
		sc->sc_buttons = buttons;
		if (sc->sc_wsmousedev != NULL) {
			s = spltty();
			wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, dz, 0,
			    flags);
			splx(s);
		}
	}
}
예제 #6
0
파일: ukbd.c 프로젝트: appleorange1/bitrig
void
ukbd_apple_munge(void *vsc, uint8_t *ibuf, u_int ilen)
{
	struct ukbd_softc *sc = vsc;
	struct hidkbd *kbd = &sc->sc_kbd;
	uint8_t *pos, *spos, *epos, xlat;

	static const struct ukbd_translation apple_fn_trans[] = {
		{ 40, 73 },	/* return -> insert */
		{ 42, 76 },	/* backspace -> delete */
#ifdef notyet
		{ 58, 0 },	/* F1 -> screen brightness down */
		{ 59, 0 },	/* F2 -> screen brightness up */
		{ 60, 0 },	/* F3 */
		{ 61, 0 },	/* F4 */
		{ 62, 0 },	/* F5 -> keyboard backlight down */
		{ 63, 0 },	/* F6 -> keyboard backlight up */
		{ 64, 0 },	/* F7 -> audio back */
		{ 65, 0 },	/* F8 -> audio pause/play */
		{ 66, 0 },	/* F9 -> audio next */
#endif
#ifdef __macppc__
		{ 60, 127 },	/* F3 -> audio mute */
		{ 61, 129 },	/* F4 -> audio lower */
		{ 62, 128 },	/* F5 -> audio raise */
#else
		{ 67, 127 },	/* F10 -> audio mute */
		{ 68, 129 },	/* F11 -> audio lower */
		{ 69, 128 },	/* F12 -> audio raise */
#endif
		{ 79, 77 },	/* right -> end */
		{ 80, 74 },	/* left -> home */
		{ 81, 78 },	/* down -> page down */
		{ 82, 75 }	/* up -> page up */
	};

	if (!hid_get_data(ibuf, &sc->sc_apple_fn))
		return;

	spos = ibuf + kbd->sc_keycodeloc.pos / 8;
	epos = spos + kbd->sc_nkeycode;

	for (pos = spos; pos != epos; pos++) {
		xlat = ukbd_translate(apple_fn_trans,
		    nitems(apple_fn_trans), *pos);
		if (xlat != 0)
			*pos = xlat;
	}
}
예제 #7
0
void
ukbd_intr(struct uhidev *addr, void *ibuf, u_int len)
{
	struct ukbd_softc *sc = (struct ukbd_softc *)addr;
	struct ukbd_data *ud = &sc->sc_ndata;
	int i;

#ifdef UKBD_DEBUG
	if (ukbddebug > 5) {
		printf("ukbd_intr: data");
		for (i = 0; i < len; i++)
			printf(" 0x%02x", ((u_char *)ibuf)[i]);
		printf("\n");
	}
#endif

	ud->modifiers = 0;
	for (i = 0; i < sc->sc_nmod; i++)
		if (hid_get_data(ibuf, &sc->sc_modloc[i]))
			ud->modifiers |= sc->sc_mods[i].mask;
	memcpy(ud->keycode, (char *)ibuf + sc->sc_keycodeloc.pos / 8,
	       sc->sc_nkeycode);

	if (sc->sc_debounce && !sc->sc_polling) {
		/*
		 * Some keyboards have a peculiar quirk.  They sometimes
		 * generate a key up followed by a key down for the same
		 * key after about 10 ms.
		 * We avoid this bug by holding off decoding for 20 ms.
		 */
		sc->sc_data = *ud;
		timeout_add(&sc->sc_delay, hz / 50);
#ifdef DDB
	} else if (sc->sc_console_keyboard && !sc->sc_polling) {
		/*
		 * For the console keyboard we can't deliver CTL-ALT-ESC
		 * from the interrupt routine.  Doing so would start
		 * polling from inside the interrupt routine and that
		 * loses bigtime.
		 */
		sc->sc_data = *ud;
		timeout_add(&sc->sc_delay, 1);
#endif
	} else {
		ukbd_decode(sc, ud);
	}
}
예제 #8
0
static void
prdata(u_char *buf, struct hid_item *h)
{
	u_int data;
	int i, pos;

	pos = h->pos;
	for (i = 0; i < h->report_count; i++) {
		data = hid_get_data(buf, h);
		if (i > 0)
			printf(" ");
		if (h->logical_minimum < 0)
			printf("%d", (int)data);
		else
			printf("%u", data);
                if (hexdump)
			printf(" [0x%x]", data);
		h->pos += h->report_size;
	}
	h->pos = pos;
}
예제 #9
0
void USBJoystick::poll() 
{
  int len;

/*
* The device will buffer a lot of deltas. This can lead to a lot of
* latency. To avoid this, we will empty the buffer every time.
* It's possible the device may report only changed entries, so we
* must process all of the frames to avoid dropping buttons (for example).
*/
  while ((len = read(fd, data_buf, data_buf_size)) == data_buf_size) {

    struct hid_item *h;

    for (h = hids; h; h = h->next) {
      int d = hid_get_data(data_buf + data_buf_offset, h);
      int page = HID_PAGE(h->usage);
      int usage = HID_USAGE(h->usage);

      int which_axis;
      if (page == HUP_GENERIC_DESKTOP) {
	switch (usage) {
	  case HUG_X:
	  case HUG_RX: which_axis = 0; break;
	  case HUG_Y:
	  case HUG_RY: which_axis = 1; break;
	  case HUG_Z:
	  case HUG_RZ: which_axis = 2; break;
	}
	axis[which_axis] = d;
      } else if (page == HUP_BUTTON) {
	buttons &= ~ (1 << (usage - 1));
	buttons |= (d == h->logical_maximum)?1 << (usage - 1):0;
      }
    }
  }

}
예제 #10
0
파일: ums.c 프로젝트: ycui1984/netbsd-src
void
ums_intr(struct uhidev *addr, void *ibuf, u_int len)
{
	struct ums_softc *sc = (struct ums_softc *)addr;
	int dx, dy, dz, dw;
	uint32_t buttons = 0;
	int i, flags, s;

	DPRINTFN(5,("ums_intr: len=%d\n", len));

	flags = WSMOUSE_INPUT_DELTA;	/* equals 0 */

	dx =  hid_get_data(ibuf, &sc->sc_loc_x);
	if (sc->flags & UMS_ABS) {
		flags |= (WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
		dy = hid_get_data(ibuf, &sc->sc_loc_y);
	} else
		dy = -hid_get_data(ibuf, &sc->sc_loc_y);
	dz =  hid_get_data(ibuf, &sc->sc_loc_z);
	dw =  hid_get_data(ibuf, &sc->sc_loc_w);

	if (sc->flags & UMS_REVZ)
		dz = -dz;
	for (i = 0; i < sc->nbuttons; i++)
		if (hid_get_data(ibuf, &sc->sc_loc_btn[i]))
			buttons |= (1 << UMS_BUT(i));

	if (dx != 0 || dy != 0 || dz != 0 || dw != 0 ||
	    buttons != sc->sc_buttons) {
		DPRINTFN(10, ("ums_intr: x:%d y:%d z:%d w:%d buttons:0x%x\n",
			dx, dy, dz, dw, buttons));
		sc->sc_buttons = buttons;
		if (sc->sc_wsmousedev != NULL) {
			s = spltty();
			wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, dz,
			    dw, flags);
			splx(s);
		}
	}
}
예제 #11
0
int
SDL_SYS_JoystickOpen(SDL_Joystick *joy)
{
	char *path = joynames[joy->index];
	struct joystick_hwdata *hw;
	struct hid_item hitem;
	struct hid_data *hdata;
	struct report *rep;
	int fd;
	int i;

	fd = open(path, O_RDONLY);
	if (fd == -1) {
		SDL_SetError("%s: %s", path, strerror(errno));
		return (-1);
	}

	hw = (struct joystick_hwdata *)SDL_malloc(sizeof(struct joystick_hwdata));
	if (hw == NULL) {
		SDL_OutOfMemory();
		close(fd);
		return (-1);
	}
	joy->hwdata = hw;
	hw->fd = fd;
	hw->path = strdup(path);
	hw->x = 0;
	hw->y = 0;
	hw->xmin = 0xffff;
	hw->ymin = 0xffff;
	hw->xmax = 0;
	hw->ymax = 0;
	if (! SDL_strncmp(path, "/dev/joy", 8)) {
		hw->type = BSDJOY_JOY;
		joy->naxes = 2;
		joy->nbuttons = 2;
		joy->nhats = 0;
		joy->nballs = 0;
		joydevnames[joy->index] = strdup("Gameport joystick");
		goto usbend;
	} else {
		hw->type = BSDJOY_UHID;
	}

	{
	    int ax;
	    for (ax = 0; ax < JOYAXE_count; ax++)
		hw->axis_map[ax] = -1;
	}
	hw->repdesc = hid_get_report_desc(fd);
	if (hw->repdesc == NULL) {
		SDL_SetError("%s: USB_GET_REPORT_DESC: %s", hw->path,
		    strerror(errno));
		goto usberr;
	}
#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)
       rep->rid = hid_get_report_id(fd);
       if (rep->rid < 0) {
#else
	rep = &hw->inreport;
	if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
#endif
		rep->rid = -1; /* XXX */
	}
	if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
		goto usberr;
	}
	if (rep->size <= 0) {
		SDL_SetError("%s: Input report descriptor has invalid length",
		    hw->path);
		goto usberr;
	}

#if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111)
	hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
#else
	hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
#endif
	if (hdata == NULL) {
		SDL_SetError("%s: Cannot start HID parser", hw->path);
		goto usberr;
	}
	joy->naxes = 0;
	joy->nbuttons = 0;
	joy->nhats = 0;
	joy->nballs = 0;
	for (i=0; i<JOYAXE_count; i++)
		hw->axis_map[i] = -1;

	while (hid_get_item(hdata, &hitem) > 0) {
		char *sp;
		const char *s;

		switch (hitem.kind) {
		case hid_collection:
			switch (HID_PAGE(hitem.usage)) {
			case HUP_GENERIC_DESKTOP:
				switch (HID_USAGE(hitem.usage)) {
				case HUG_JOYSTICK:
				case HUG_GAME_PAD:
					s = hid_usage_in_page(hitem.usage);
					sp = SDL_malloc(SDL_strlen(s) + 5);
					SDL_snprintf(sp, SDL_strlen(s) + 5, "%s (%d)", s,
					    joy->index);
					joydevnames[joy->index] = sp;
				}
			}
			break;
		case hid_input:
			switch (HID_PAGE(hitem.usage)) {
			case HUP_GENERIC_DESKTOP: {
			    unsigned usage = HID_USAGE(hitem.usage);
			    int joyaxe = usage_to_joyaxe(usage);
			    if (joyaxe >= 0) {
				hw->axis_map[joyaxe] = 1;
			    } else if (usage == HUG_HAT_SWITCH) {
				joy->nhats++;
			    }
			    break;
			}
			case HUP_BUTTON:
				joy->nbuttons++;
				break;
			default:
				break;
			}
			break;
		default:
			break;
		}
	}
	hid_end_parse(hdata);
	for (i=0; i<JOYAXE_count; i++)
		if (hw->axis_map[i] > 0)
			hw->axis_map[i] = joy->naxes++;

usbend:
	/* The poll blocks the event thread. */
	fcntl(fd, F_SETFL, O_NONBLOCK);

	return (0);
usberr:
	close(hw->fd);
	SDL_free(hw->path);
	SDL_free(hw);
	return (-1);
}

void
SDL_SYS_JoystickUpdate(SDL_Joystick *joy)
{
	struct hid_item hitem;
	struct hid_data *hdata;
	struct report *rep;
	int nbutton, naxe = -1;
	Sint32 v;

#if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
	struct joystick gameport;
 
	if (joy->hwdata->type == BSDJOY_JOY) {
		if (read(joy->hwdata->fd, &gameport, sizeof gameport) != sizeof gameport)
			return;
		if (abs(joy->hwdata->x - gameport.x) > 8) {
			joy->hwdata->x = gameport.x;
			if (joy->hwdata->x < joy->hwdata->xmin) {
				joy->hwdata->xmin = joy->hwdata->x;
			}
			if (joy->hwdata->x > joy->hwdata->xmax) {
				joy->hwdata->xmax = joy->hwdata->x;
			}
			if (joy->hwdata->xmin == joy->hwdata->xmax) {
				joy->hwdata->xmin--;
				joy->hwdata->xmax++;
			}
			v = (Sint32)joy->hwdata->x;
			v -= (joy->hwdata->xmax + joy->hwdata->xmin + 1)/2;
			v *= 32768/((joy->hwdata->xmax - joy->hwdata->xmin + 1)/2);
			SDL_PrivateJoystickAxis(joy, 0, v);
		}
		if (abs(joy->hwdata->y - gameport.y) > 8) {
			joy->hwdata->y = gameport.y;
			if (joy->hwdata->y < joy->hwdata->ymin) {
				joy->hwdata->ymin = joy->hwdata->y;
			}
			if (joy->hwdata->y > joy->hwdata->ymax) {
				joy->hwdata->ymax = joy->hwdata->y;
			}
			if (joy->hwdata->ymin == joy->hwdata->ymax) {
				joy->hwdata->ymin--;
				joy->hwdata->ymax++;
			}
			v = (Sint32)joy->hwdata->y;
			v -= (joy->hwdata->ymax + joy->hwdata->ymin + 1)/2;
			v *= 32768/((joy->hwdata->ymax - joy->hwdata->ymin + 1)/2);
			SDL_PrivateJoystickAxis(joy, 1, v);
		}
		if (gameport.b1 != joy->buttons[0]) {
			SDL_PrivateJoystickButton(joy, 0, gameport.b1);
		}
		if (gameport.b2 != joy->buttons[1]) {
			SDL_PrivateJoystickButton(joy, 1, gameport.b2);
		}
		return;
	}
#endif /* defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H */
	
	rep = &joy->hwdata->inreport;

	if (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) != rep->size) {
		return;
	}
#if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111)
	hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
#else
	hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
#endif
	if (hdata == NULL) {
		fprintf(stderr, "%s: Cannot start HID parser\n",
		    joy->hwdata->path);
		return;
	}

	for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
		switch (hitem.kind) {
		case hid_input:
			switch (HID_PAGE(hitem.usage)) {
			case HUP_GENERIC_DESKTOP: {
			    unsigned usage = HID_USAGE(hitem.usage);
			    int joyaxe = usage_to_joyaxe(usage);
			    if (joyaxe >= 0) {
				naxe = joy->hwdata->axis_map[joyaxe];
				/* scaleaxe */
				v = (Sint32)hid_get_data(REP_BUF_DATA(rep),
							 &hitem);
				v -= (hitem.logical_maximum + hitem.logical_minimum + 1)/2;
				v *= 32768/((hitem.logical_maximum - hitem.logical_minimum + 1)/2);
				if (v != joy->axes[naxe]) {
				    SDL_PrivateJoystickAxis(joy, naxe, v);
				}
			    } else if (usage == HUG_HAT_SWITCH) {
				v = (Sint32)hid_get_data(REP_BUF_DATA(rep),
							 &hitem);
				SDL_PrivateJoystickHat(joy, 0,
					hatval_to_sdl(v)-hitem.logical_minimum);
			    }
			    break;
			}
			case HUP_BUTTON:
				v = (Sint32)hid_get_data(REP_BUF_DATA(rep),
				    &hitem);
				if (joy->buttons[nbutton] != v) {
					SDL_PrivateJoystickButton(joy,
					    nbutton, v);
				}
				nbutton++;
				break;
			default:
				continue;
			}
			break;
		default:
			break;
		}
	}
	hid_end_parse(hdata);

	return;
}

/* Function to close a joystick after use */
void
SDL_SYS_JoystickClose(SDL_Joystick *joy)
{
	if (SDL_strncmp(joy->hwdata->path, "/dev/joy", 8))	{
		report_free(&joy->hwdata->inreport);
		hid_dispose_report_desc(joy->hwdata->repdesc);
	}
	close(joy->hwdata->fd);
	SDL_free(joy->hwdata->path);
	SDL_free(joy->hwdata);

	return;
}

void
SDL_SYS_JoystickQuit(void)
{
	int i;

	for (i = 0; i < MAX_JOYS; i++) {
		if (joynames[i] != NULL)
			SDL_free(joynames[i]);
		if (joydevnames[i] != NULL)
			SDL_free(joydevnames[i]);
	}

	return;
}
예제 #12
0
void
SDL_SYS_JoystickUpdate(SDL_Joystick *joy)
{
	struct hid_item hitem;
	struct hid_data *hdata;
	struct report *rep;
	int nbutton, naxe = -1;
	Sint32 v;
	
	rep = &joy->hwdata->inreport;

	if (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) != rep->size) {
		return;
	}
#if defined(USBHID_NEW) || (defined(__FreeBSD__) && __FreeBSD_version >= 500111)
	hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
#else
	hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
#endif
	if (hdata == NULL) {
		fprintf(stderr, "%s: Cannot start HID parser\n",
		    joy->hwdata->path);
		return;
	}

	for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
		switch (hitem.kind) {
		case hid_input:
			switch (HID_PAGE(hitem.usage)) {
			case HUP_GENERIC_DESKTOP: {
			    unsigned usage = HID_USAGE(hitem.usage);
			    int joyaxe = usage_to_joyaxe(usage);
			    if (joyaxe >= 0) {
				naxe = joy->hwdata->axis_map[joyaxe];
				/* scaleaxe */
				v = (Sint32)hid_get_data(REP_BUF_DATA(rep),
							 &hitem);
				v -= (hitem.logical_maximum + hitem.logical_minimum + 1)/2;
				v *= 32768/((hitem.logical_maximum - hitem.logical_minimum + 1)/2);
				if (v != joy->axes[naxe]) {
				    SDL_PrivateJoystickAxis(joy, naxe, v);
				}
			    } else if (usage == HUG_HAT_SWITCH) {
				v = (Sint32)hid_get_data(REP_BUF_DATA(rep),
							 &hitem);
				SDL_PrivateJoystickHat(joy, 0, hatval_to_sdl(v));
			    }
			    break;
			}
			case HUP_BUTTON:
				v = (Sint32)hid_get_data(REP_BUF_DATA(rep),
				    &hitem);
				if (joy->buttons[nbutton] != v) {
					SDL_PrivateJoystickButton(joy,
					    nbutton, v);
				}
				nbutton++;
				break;
			default:
				continue;
			}
			break;
		default:
			break;
		}
	}
	hid_end_parse(hdata);

	return;
}
예제 #13
0
void
SDL_SYS_JoystickUpdate(SDL_Joystick *joy)
{
	struct hid_item hitem;
	struct hid_data *hdata;
	struct report *rep;
	int nbutton, naxe = -1;
	Sint32 v;

#if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
	struct joystick gameport;
 
	if (joy->hwdata->type == BSDJOY_JOY) {
		if (read(joy->hwdata->fd, &gameport, sizeof gameport) != sizeof gameport)
			return;
		if (abs(joy->hwdata->x - gameport.x) > 8) {
			joy->hwdata->x = gameport.x;
			if (joy->hwdata->x < joy->hwdata->xmin) {
				joy->hwdata->xmin = joy->hwdata->x;
			}
			if (joy->hwdata->x > joy->hwdata->xmax) {
				joy->hwdata->xmax = joy->hwdata->x;
			}
			if (joy->hwdata->xmin == joy->hwdata->xmax) {
				joy->hwdata->xmin--;
				joy->hwdata->xmax++;
			}
			v = (Sint32)joy->hwdata->x;
			v -= (joy->hwdata->xmax + joy->hwdata->xmin + 1)/2;
			v *= 32768/((joy->hwdata->xmax - joy->hwdata->xmin + 1)/2);
			SDL_PrivateJoystickAxis(joy, 0, v);
		}
		if (abs(joy->hwdata->y - gameport.y) > 8) {
			joy->hwdata->y = gameport.y;
			if (joy->hwdata->y < joy->hwdata->ymin) {
				joy->hwdata->ymin = joy->hwdata->y;
			}
			if (joy->hwdata->y > joy->hwdata->ymax) {
				joy->hwdata->ymax = joy->hwdata->y;
			}
			if (joy->hwdata->ymin == joy->hwdata->ymax) {
				joy->hwdata->ymin--;
				joy->hwdata->ymax++;
			}
			v = (Sint32)joy->hwdata->y;
			v -= (joy->hwdata->ymax + joy->hwdata->ymin + 1)/2;
			v *= 32768/((joy->hwdata->ymax - joy->hwdata->ymin + 1)/2);
			SDL_PrivateJoystickAxis(joy, 1, v);
		}
		if (gameport.b1 != joy->buttons[0]) {
			SDL_PrivateJoystickButton(joy, 0, gameport.b1);
		}
		if (gameport.b2 != joy->buttons[1]) {
			SDL_PrivateJoystickButton(joy, 1, gameport.b2);
		}
		return;
	}
#endif /* defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H */
	
	rep = &joy->hwdata->inreport;

	if (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) != rep->size) {
		return;
	}
#if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_version >= 500111)
	hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
#else
	hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
#endif
	if (hdata == NULL) {
		fprintf(stderr, "%s: Cannot start HID parser\n",
		    joy->hwdata->path);
		return;
	}

	for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
		switch (hitem.kind) {
		case hid_input:
			switch (HID_PAGE(hitem.usage)) {
			case HUP_GENERIC_DESKTOP: {
			    unsigned usage = HID_USAGE(hitem.usage);
			    int joyaxe = usage_to_joyaxe(usage);
			    if (joyaxe >= 0) {
				naxe = joy->hwdata->axis_map[joyaxe];
				/* scaleaxe */
				v = (Sint32)hid_get_data(REP_BUF_DATA(rep),
							 &hitem);
				v -= (hitem.logical_maximum + hitem.logical_minimum + 1)/2;
				v *= 32768/((hitem.logical_maximum - hitem.logical_minimum + 1)/2);
				if (v != joy->axes[naxe]) {
				    SDL_PrivateJoystickAxis(joy, naxe, v);
				}
			    } else if (usage == HUG_HAT_SWITCH) {
				v = (Sint32)hid_get_data(REP_BUF_DATA(rep),
							 &hitem);
				SDL_PrivateJoystickHat(joy, 0,
					hatval_to_sdl(v)-hitem.logical_minimum);
			    }
			    break;
			}
			case HUP_BUTTON:
				v = (Sint32)hid_get_data(REP_BUF_DATA(rep),
				    &hitem);
				if (joy->buttons[nbutton] != v) {
					SDL_PrivateJoystickButton(joy,
					    nbutton, v);
				}
				nbutton++;
				break;
			default:
				continue;
			}
			break;
		default:
			break;
		}
	}
	hid_end_parse(hdata);

	return;
}
예제 #14
0
int
main(int argc, char **argv)
{
	const char *conf = NULL;
	const char *dev = NULL;
	const char *table = NULL;
	int fd, fp, ch, n, val, i;
	size_t sz, sz1;
	int demon, ignore, dieearly;
	report_desc_t repd;
	char buf[100];
	char devnamebuf[PATH_MAX];
	struct command *cmd;
	int reportid = -1;

	demon = 1;
	ignore = 0;
	dieearly = 0;
	while ((ch = getopt(argc, argv, "c:def:ip:r:t:v")) != -1) {
		switch(ch) {
		case 'c':
			conf = optarg;
			break;
		case 'd':
			demon ^= 1;
			break;
		case 'e':
			dieearly = 1;
			break;
		case 'i':
			ignore++;
			break;
		case 'f':
			dev = optarg;
			break;
		case 'p':
			pidfile = optarg;
			break;
		case 'r':
			reportid = atoi(optarg);
			break;
		case 't':
			table = optarg;
			break;
		case 'v':
			demon = 0;
			verbose++;
			break;
		case '?':
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (conf == NULL || dev == NULL)
		usage();

	hid_init(table);

	if (dev[0] != '/') {
		snprintf(devnamebuf, sizeof(devnamebuf), "/dev/%s%s",
			 isdigit(dev[0]) ? "uhid" : "", dev);
		dev = devnamebuf;
	}

	fd = open(dev, O_RDWR);
	if (fd < 0)
		err(1, "%s", dev);
	repd = hid_get_report_desc(fd);
	if (repd == NULL)
		err(1, "hid_get_report_desc() failed");

	commands = parse_conf(conf, repd, reportid, ignore);

	sz = (size_t)hid_report_size(repd, hid_input, -1);

	if (verbose)
		printf("report size %zu\n", sz);
	if (sz > sizeof buf)
		errx(1, "report too large");

	(void)signal(SIGHUP, sighup);

	if (demon) {
		fp = open(pidfile, O_WRONLY|O_CREAT, S_IRUSR|S_IRGRP|S_IROTH);
		if (fp < 0)
			err(1, "%s", pidfile);
		if (daemon(0, 0) < 0)
			err(1, "daemon()");
		snprintf(buf, sizeof(buf), "%ld\n", (long)getpid());
		sz1 = strlen(buf);
		if (write(fp, buf, sz1) < 0)
			err(1, "%s", pidfile);
		close(fp);
		isdemon = 1;
	}

	for(;;) {
		n = read(fd, buf, sz);
		if (verbose > 2) {
			printf("read %d bytes:", n);
			for (i = 0; i < n; i++)
				printf(" %02x", buf[i]);
			printf("\n");
		}
		if (n < 0) {
			if (verbose)
				err(1, "read");
			else
				exit(1);
		}
#if 0
		if (n != sz) {
			err(2, "read size");
		}
#endif
		for (cmd = commands; cmd; cmd = cmd->next) {
			if (cmd->item.report_ID != 0 &&
			    buf[0] != cmd->item.report_ID)
				continue;
			if (cmd->item.flags & HIO_VARIABLE)
				val = hid_get_data(buf, &cmd->item);
			else {
				uint32_t pos = cmd->item.pos;
				for (i = 0; i < cmd->item.report_count; i++) {
					val = hid_get_data(buf, &cmd->item);
					if (val == cmd->value)
						break;
					cmd->item.pos += cmd->item.report_size;
				}
				cmd->item.pos = pos;
				val = (i < cmd->item.report_count) ?
				    cmd->value : -1;
			}
			if (cmd->value != val && cmd->anyvalue == 0)
				goto next;
			if ((cmd->debounce == 0) ||
			    ((cmd->debounce == 1) && ((cmd->lastseen == -1) ||
					       (cmd->lastseen != val)))) {
				docmd(cmd, val, dev, argc, argv);
				goto next;
			}
			if ((cmd->debounce > 1) &&
			    ((cmd->lastused == -1) ||
			     (abs(cmd->lastused - val) >= cmd->debounce))) {
				docmd(cmd, val, dev, argc, argv);
				cmd->lastused = val;
				goto next;
			}
next:
			cmd->lastseen = val;
		}

		if (dieearly)
			exit(0);

		if (reparse) {
			struct command *cmds =
			    parse_conf(conf, repd, reportid, ignore);
			if (cmds) {
				freecommands(commands);
				commands = cmds;
			}
			reparse = 0;
		}
	}

	exit(0);
}
예제 #15
0
파일: hidms.c 프로젝트: ajinkya93/OpenBSD
void
hidms_input(struct hidms *ms, uint8_t *data, u_int len)
{
	int dx, dy, dz, dw;
	u_int32_t buttons = 0;
	int flags;
	int i, s;

	DPRINTFN(5,("hidms_input: len=%d\n", len));

	/*
	 * The Microsoft Wireless Intellimouse 2.0 sends one extra leading
	 * byte of data compared to most USB mice.  This byte frequently
	 * switches from 0x01 (usual state) to 0x02.  It may be used to
	 * report non-standard events (such as battery life).  However,
	 * at the same time, it generates a left click event on the
	 * button byte, where there shouldn't be any.  We simply discard
	 * the packet in this case.
	 *
	 * This problem affects the MS Wireless Notebook Optical Mouse, too.
	 * However, the leading byte for this mouse is normally 0x11, and
	 * the phantom mouse click occurs when it's 0x14.
	 */
	if (ms->sc_flags & HIDMS_LEADINGBYTE) {
		if (*data++ == 0x02)
			return;
		/* len--; */
	} else if (ms->sc_flags & HIDMS_SPUR_BUT_UP) {
		if (*data == 0x14 || *data == 0x15)
			return;
	}

	flags = WSMOUSE_INPUT_DELTA;
	if (ms->sc_flags & HIDMS_ABSX)
		flags |= WSMOUSE_INPUT_ABSOLUTE_X;
	if (ms->sc_flags & HIDMS_ABSY)
		flags |= WSMOUSE_INPUT_ABSOLUTE_Y;

	dx =  hid_get_data(data, len, &ms->sc_loc_x);
	dy = -hid_get_data(data, len, &ms->sc_loc_y);
	dz =  hid_get_data(data, len, &ms->sc_loc_z);
	dw =  hid_get_data(data, len, &ms->sc_loc_w);

	if (ms->sc_flags & HIDMS_ABSY)
		dy = -dy;
	if (ms->sc_flags & HIDMS_REVZ)
		dz = -dz;
	if (ms->sc_flags & HIDMS_REVW)
		dw = -dw;

	if (ms->sc_tsscale.swapxy && !ms->sc_rawmode) {
		int tmp = dx;
		dx = dy;
		dy = tmp;
	}

	if (!ms->sc_rawmode &&
	    (ms->sc_tsscale.maxx - ms->sc_tsscale.minx) != 0 &&
	    (ms->sc_tsscale.maxy - ms->sc_tsscale.miny) != 0) {
		/* Scale down to the screen resolution. */
		dx = ((dx - ms->sc_tsscale.minx) * ms->sc_tsscale.resx) /
		    (ms->sc_tsscale.maxx - ms->sc_tsscale.minx);
		dy = ((dy - ms->sc_tsscale.miny) * ms->sc_tsscale.resy) /
		    (ms->sc_tsscale.maxy - ms->sc_tsscale.miny);
	}

	for (i = 0; i < ms->sc_num_buttons; i++)
		if (hid_get_data(data, len, &ms->sc_loc_btn[i]))
			buttons |= (1 << HIDMS_BUT(i));

	if (dx != 0 || dy != 0 || dz != 0 || dw != 0 ||
	    buttons != ms->sc_buttons) {
		DPRINTFN(10, ("hidms_input: x:%d y:%d z:%d w:%d buttons:0x%x\n",
			dx, dy, dz, dw, buttons));
		ms->sc_buttons = buttons;
		if (ms->sc_wsmousedev != NULL) {
			s = spltty();
			wsmouse_input(ms->sc_wsmousedev, buttons,
			    dx, dy, dz, dw, flags);
			splx(s);
		}
	}
}
예제 #16
0
int
main(int argc, char **argv)
{
	const char *conf = NULL;
	const char *dev = NULL;
	int fd, ch, sz, n, val, i;
	int demon, ignore;
	report_desc_t repd;
	char buf[100];
	char devnamebuf[PATH_MAX];
	struct command *cmd;
	int reportid;

	demon = 1;
	ignore = 0;
	while ((ch = getopt(argc, argv, "c:df:iv")) != -1) {
		switch(ch) {
		case 'c':
			conf = optarg;
			break;
		case 'd':
			demon ^= 1;
			break;
		case 'i':
			ignore++;
			break;
		case 'f':
			dev = optarg;
			break;
		case 'v':
			demon = 0;
			verbose++;
			break;
		case '?':
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (conf == NULL || dev == NULL)
		usage();

	if (hid_start(NULL) == -1)
		errx(1, "hid_init");

	if (dev[0] != '/') {
		snprintf(devnamebuf, sizeof(devnamebuf), "/dev/%s%s",
		    isdigit((unsigned char)dev[0]) ? "uhid" : "", dev);
		dev = devnamebuf;
	}

	if (demon && conf[0] != '/')
		errx(1, "config file must have an absolute path, %s", conf);

	fd = open(dev, O_RDWR | O_CLOEXEC);
	if (fd < 0)
		err(1, "%s", dev);

	if (ioctl(fd, USB_GET_REPORT_ID, &reportid) < 0)
		reportid = -1;
	repd = hid_get_report_desc(fd);
	if (repd == NULL)
		err(1, "hid_get_report_desc() failed");

	commands = parse_conf(conf, repd, reportid, ignore);

	sz = hid_report_size(repd, hid_input, reportid);

	if (verbose)
		printf("report size %d\n", sz);
	if (sz > sizeof buf)
		errx(1, "report too large");

	(void)signal(SIGHUP, sighup);

	/* we do not care about the children, so ignore them */
	(void)signal(SIGCHLD, SIG_IGN);

	if (demon) {
		if (daemon(0, 0) < 0)
			err(1, "daemon()");
		isdemon = 1;
	}

	for(;;) {
		n = read(fd, buf, sz);
		if (verbose > 2) {
			printf("read %d bytes:", n);
			for (i = 0; i < n; i++)
				printf(" %02x", buf[i]);
			printf("\n");
		}
		if (n < 0) {
			if (verbose)
				err(1, "read");
			else
				exit(1);
		}
		if (n != sz) {
			err(2, "read size");
		}
		for (cmd = commands; cmd; cmd = cmd->next) {
			val = hid_get_data(buf, &cmd->item);
			if (cmd->value == val || cmd->anyvalue)
				docmd(cmd, val, dev, argc, argv);
		}
		if (reparse) {
			struct command *cmds =
			    parse_conf(conf, repd, reportid, ignore);
			if (cmds) {
				freecommands(commands);
				commands = cmds;
			}
			reparse = 0;
		}
	}

	exit(0);
}
예제 #17
0
파일: hid.c 프로젝트: jamesbjackson/src
int32_t
hid_interrupt(bthid_session_p s, uint8_t *data, int32_t len)
{
	hid_device_p	hid_device;
	hid_data_t	d;
	hid_item_t	h;
	int32_t		report_id, usage, page, val,
			mouse_x, mouse_y, mouse_z, mouse_butt,
			mevents, kevents, i;

	assert(s != NULL);
	assert(s->srv != NULL);
	assert(data != NULL);

	if (len < 3) {
		syslog(LOG_ERR, "Got short message (%d bytes) on Interrupt " \
			"channel from %s", len, bt_ntoa(&s->bdaddr, NULL));
		return (-1);
	}

	if (data[0] != 0xa1) {
		syslog(LOG_ERR, "Got unexpected message 0x%x on " \
			"Interrupt channel from %s",
			data[0], bt_ntoa(&s->bdaddr, NULL));
		return (-1);
	}

	report_id = data[1];
	data ++;
	len --;

	hid_device = get_hid_device(&s->bdaddr);
	assert(hid_device != NULL);

	mouse_x = mouse_y = mouse_z = mouse_butt = mevents = kevents = 0;

	for (d = hid_start_parse(hid_device->desc, 1 << hid_input, -1);
	     hid_get_item(d, &h) > 0; ) {
		if ((h.flags & HIO_CONST) || (h.report_ID != report_id) ||
		    (h.kind != hid_input))
			continue;

		page = HID_PAGE(h.usage);
		val = hid_get_data(data, &h);

		/*
		 * When the input field is an array and the usage is specified
		 * with a range instead of an ID, we have to derive the actual
		 * usage by using the item value as an index in the usage range
		 * list.
		 */
		if ((h.flags & HIO_VARIABLE)) {
			usage = HID_USAGE(h.usage);
		} else {
			const uint32_t usage_offset = val - h.logical_minimum;
			usage = HID_USAGE(h.usage_minimum + usage_offset);
		}

		switch (page) {
		case HUP_GENERIC_DESKTOP:
			switch (usage) {
			case HUG_X:
				mouse_x = val;
				mevents ++;
				break;

			case HUG_Y:
				mouse_y = val;
				mevents ++;
				break;

			case HUG_WHEEL:
				mouse_z = -val;
				mevents ++;
				break;

			case HUG_SYSTEM_SLEEP:
				if (val)
					syslog(LOG_NOTICE, "Sleep button pressed");
				break;
			}
			break;

		case HUP_KEYBOARD:
			kevents ++;

			if (h.flags & HIO_VARIABLE) {
				if (val && usage < kbd_maxkey())
					bit_set(s->keys1, usage);
			} else {
				if (val && val < kbd_maxkey())
					bit_set(s->keys1, val);

				for (i = 1; i < h.report_count; i++) {
					h.pos += h.report_size;
					val = hid_get_data(data, &h);
					if (val && val < kbd_maxkey())
						bit_set(s->keys1, val);
				}
			}
			break;

		case HUP_BUTTON:
			if (usage != 0) {
				if (usage == 2)
					usage = 3;
				else if (usage == 3)
					usage = 2;
				
				mouse_butt |= (val << (usage - 1));
				mevents ++;
			}
			break;

		case HUP_CONSUMER:
			if (!val)
				break;

			switch (usage) {
			case HUC_AC_PAN:
				/* Horizontal scroll */
				if (val < 0)
					mouse_butt |= (1 << 5);
				else
					mouse_butt |= (1 << 6);

				mevents ++;
				val = 0;
				break;

			case 0xb5: /* Scan Next Track */
				val = 0x19;
				break;

			case 0xb6: /* Scan Previous Track */
				val = 0x10;
				break;

			case 0xb7: /* Stop */
				val = 0x24;
				break;

			case 0xcd: /* Play/Pause */
				val = 0x22;
				break;

			case 0xe2: /* Mute */
				val = 0x20;
				break;

			case 0xe9: /* Volume Up */
				val = 0x30;
				break;

			case 0xea: /* Volume Down */
				val = 0x2E;
				break;

			case 0x183: /* Media Select */
				val = 0x6D;
				break;

			case 0x018a: /* Mail */
				val = 0x6C;
				break;

			case 0x192: /* Calculator */
				val = 0x21;
				break;

			case 0x194: /* My Computer */
				val = 0x6B;
				break;

			case 0x221: /* WWW Search */
				val = 0x65;
				break;

			case 0x223: /* WWW Home */
				val = 0x32;
				break;

			case 0x224: /* WWW Back */
				val = 0x6A;
				break;

			case 0x225: /* WWW Forward */
				val = 0x69;
				break;

			case 0x226: /* WWW Stop */
				val = 0x68;
				break;

			case 0x227: /* WWW Refresh */
				val = 0x67;
				break;

			case 0x22a: /* WWW Favorites */
				val = 0x66;
				break;

			default:
				val = 0;
				break;
			}

			/* XXX FIXME - UGLY HACK */
			if (val != 0) {
				if (hid_device->keyboard) {
					int32_t	buf[4] = { 0xe0, val,
							   0xe0, val|0x80 };

					assert(s->vkbd != -1);
					write(s->vkbd, buf, sizeof(buf));
				} else
					syslog(LOG_ERR, "Keyboard events " \
						"received from non-keyboard " \
						"device %s. Please report",
						bt_ntoa(&s->bdaddr, NULL));
			}
			break;

		case HUP_MICROSOFT:
			switch (usage) {
			case 0xfe01:
				if (!hid_device->battery_power)
					break;

				switch (val) {
				case 1:
					syslog(LOG_INFO, "Battery is OK on %s",
						bt_ntoa(&s->bdaddr, NULL));
					break;

				case 2:
					syslog(LOG_NOTICE, "Low battery on %s",
						bt_ntoa(&s->bdaddr, NULL));
					break;

				case 3:
					syslog(LOG_WARNING, "Very low battery "\
                                                "on %s",
						bt_ntoa(&s->bdaddr, NULL));
					break;
                                }
				break;
			}
			break;
		}
	}
	hid_end_parse(d);

	/*
	 * XXX FIXME Feed keyboard events into kernel.
	 * The code below works, bit host also needs to track
	 * and handle repeat.
	 *
	 * Key repeat currently works in X, but not in console.
	 */

	if (kevents > 0) {
		if (hid_device->keyboard) {
			assert(s->vkbd != -1);
			kbd_process_keys(s);
		} else
			syslog(LOG_ERR, "Keyboard events received from " \
				"non-keyboard device %s. Please report",
				bt_ntoa(&s->bdaddr, NULL));
	}

	/* 
	 * XXX FIXME Feed mouse events into kernel.
	 * The code block below works, but it is not good enough.
	 * Need to track double-clicks etc.
	 *
	 * Double click currently works in X, but not in console.
	 */

	if (mevents > 0) {
		struct mouse_info	mi;

		mi.operation = MOUSE_ACTION;
		mi.u.data.x = mouse_x;
		mi.u.data.y = mouse_y;
		mi.u.data.z = mouse_z;
		mi.u.data.buttons = mouse_butt;

		if (ioctl(s->srv->cons, CONS_MOUSECTL, &mi) < 0)
			syslog(LOG_ERR, "Could not process mouse events from " \
				"%s. %s (%d)", bt_ntoa(&s->bdaddr, NULL),
				strerror(errno), errno);
	}

	return (0);
}
예제 #18
0
static void
btkbd_input(struct bthidev *hidev, uint8_t *data, int len)
{
	struct btkbd_softc *sc = (struct btkbd_softc *)hidev;
	struct btkbd_data *ud = &sc->sc_ndata;
	uint16_t ibuf[MAXKEYS];
	uint32_t mod, omod;
	int nkeys, i, j;
	int key;
	int s;

	if (sc->sc_wskbd == NULL || sc->sc_enabled == 0)
		return;

	/* extract key modifiers */
	ud->modifiers = 0;
	for (i = 0 ; i < sc->sc_nmod ; i++)
		if (hid_get_data(data, &sc->sc_modloc[i]))
			ud->modifiers |= sc->sc_mods[i].mask;

	/* extract keycodes */
	memcpy(ud->keycode, data + (sc->sc_keycodeloc.pos / 8),
	       sc->sc_nkeycode);

	if (ud->keycode[0] == KEY_ERROR)
		return;		/* ignore  */

	nkeys = 0;
	mod = ud->modifiers;
	omod = sc->sc_odata.modifiers;
	if (mod != omod)
		for (i = 0 ; i < sc->sc_nmod ; i++)
			if ((mod & sc->sc_mods[i].mask) !=
			    (omod & sc->sc_mods[i].mask))
				ADDKEY(sc->sc_mods[i].key |
				       (mod & sc->sc_mods[i].mask
					  ? PRESS : RELEASE));

	if (memcmp(ud->keycode, sc->sc_odata.keycode, sc->sc_nkeycode) != 0) {
		/* Check for released keys. */
		for (i = 0 ; i < sc->sc_nkeycode ; i++) {
			key = sc->sc_odata.keycode[i];
			if (key == 0)
				continue;

			for (j = 0 ; j < sc->sc_nkeycode ; j++)
				if (key == ud->keycode[j])
					goto rfound;

			ADDKEY(key | RELEASE);

		rfound:
			;
		}

		/* Check for pressed keys. */
		for (i = 0 ; i < sc->sc_nkeycode ; i++) {
			key = ud->keycode[i];
			if (key == 0)
				continue;

			for (j = 0; j < sc->sc_nkeycode; j++)
				if (key == sc->sc_odata.keycode[j])
					goto pfound;

			ADDKEY(key | PRESS);
		pfound:
			;
		}
	}
	sc->sc_odata = *ud;

	if (nkeys == 0)
		return;

#ifdef WSDISPLAY_COMPAT_RAWKBD
	if (sc->sc_rawkbd) {
		u_char cbuf[MAXKEYS * 2];
		int c;
		int npress;

		for (npress = i = j = 0 ; i < nkeys ; i++) {
			key = ibuf[i];
			c = btkbd_trtab[key & CODEMASK];
			if (c == NN)
				continue;

			if (c & 0x80)
				cbuf[j++] = 0xe0;

			cbuf[j] = c & 0x7f;
			if (key & RELEASE)
				cbuf[j] |= 0x80;
#ifdef BTKBD_REPEAT
			else {
				/* remember pressed keys for autorepeat */
				if (c & 0x80)
					sc->sc_rep[npress++] = 0xe0;

				sc->sc_rep[npress++] = c & 0x7f;
			}
#endif

			j++;
		}

		s = spltty();
		wskbd_rawinput(sc->sc_wskbd, cbuf, j);
		splx(s);
#ifdef BTKBD_REPEAT
		callout_stop(&sc->sc_repeat);
		if (npress != 0) {
			sc->sc_nrep = npress;
			callout_schedule(&sc->sc_repeat, hz * REP_DELAY1 / 1000);
		}
#endif
		return;
	}
#endif

	s = spltty();
	for (i = 0 ; i < nkeys ; i++) {
		key = ibuf[i];
		wskbd_input(sc->sc_wskbd,
		    key & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
		    key & CODEMASK);
	}
	splx(s);
}
static int
jstkReadData_bsd(JoystickDevPtr joystick,
             JOYSTICKEVENT *event,
             int *number)
{
    int j,d;
    struct jstk_bsd_hid_data *bsddata = 
        (struct jstk_bsd_hid_data*)(joystick->devicedata);

    if (event != NULL) *event = EVENT_NONE;
    if (bsddata->hotdata == 0) {
        j= xf86ReadSerial(joystick->fd,
                          bsddata->data_buf,
                          bsddata->dlen);
        if (j != bsddata->dlen) {
            ErrorF("Read: %d byte! Should be %d\n",j,bsddata->dlen);
            return 0;
        }
        bsddata->hotdata = 1;
    }

    for (j=0; j<joystick->num_axes - (bsddata->hats * 2); j++) {
        d = hid_get_data(bsddata->data_buf, &bsddata->axis_item[j]);
        /* Scale the range to our expected range of -32768 to 32767 */
        d = d - (bsddata->axis_item[j].logical_maximum 
                 - bsddata->axis_item[j].logical_minimum) / 2;
        d = d * 65536 / (bsddata->axis_item[j].logical_maximum 
                         - bsddata->axis_item[j].logical_minimum);
        if (abs(d) < joystick->axis[j].deadzone) d = 0;
        if (d != joystick->axis[j].value) {
            joystick->axis[j].value = d;
            if (event != NULL) *event = EVENT_AXIS;
            if (number != NULL) *number = j;
            return 2;
        }
    }

    for (j=0; j<bsddata->hats; j++) {
        int a;
        int v1_data[9] = 
            { 0, 32767, 32767, 32767, 0, -32768, -32768, -32768, 0 };
        int v2_data[9] =
            { -32768, -32768, 0, 32767, 32767, 32767, 0, -32767, 0 };

        a = j*2 + joystick->num_axes - bsddata->hats *2;
        d = hid_get_data(bsddata->data_buf, &bsddata->hat_item[j]) 
            - bsddata->hat_item[j].logical_minimum;
        if (joystick->axis[a].value != v1_data[d]) {
            joystick->axis[a].value = v1_data[d];
            if (event != NULL) *event = EVENT_AXIS;
            if (number != NULL) *number = a;
            return 2;
        }
        if (joystick->axis[a+1].value != v2_data[d]) {
            joystick->axis[a+1].value = v2_data[d];
            if (event != NULL) *event = EVENT_AXIS;
            if (number != NULL) *number = a+1;
            return 2;
        }
    }

    for (j=0; j<joystick->num_buttons; j++) {
        int pressed;
        d = hid_get_data(bsddata->data_buf, &bsddata->button_item[j]);
        pressed = (d == bsddata->button_item[j].logical_minimum) ? 0 : 1;
        if (pressed != joystick->button[j].pressed) {
            joystick->button[j].pressed = pressed;
            if (event != NULL) *event = EVENT_BUTTON;
            if (number != NULL) *number = j;
            return 2;
        }
    }

    bsddata->hotdata = 0;
    return 1;
}
예제 #20
0
void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
{
    int status;

#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
    int len;

    if ( joy->pJoystick.os->is_analog )
    {
        int status = read ( joy->pJoystick.os->fd, &joy->pJoystick.os->ajs, sizeof(joy->pJoystick.os->ajs) );
        if ( status != sizeof(joy->pJoystick.os->ajs) ) {
            perror ( joy->pJoystick.os->fname );
            joy->error = GL_TRUE;
            return;
        }
        if ( buttons != NULL )
            *buttons = ( joy->pJoystick.os->ajs.b1 ? 1 : 0 ) | ( joy->pJoystick.os->ajs.b2 ? 2 : 0 );

        if ( axes != NULL )
        {
            axes[0] = (float) joy->pJoystick.os->ajs.x;
            axes[1] = (float) joy->pJoystick.os->ajs.y;
        }

        return;
    }

#  ifdef HAVE_USB_JS
    while ( ( len = read ( joy->pJoystick.os->fd, joy->pJoystick.os->hid_data_buf, joy->pJoystick.os->hid_dlen ) ) == joy->pJoystick.os->hid_dlen )
    {
        struct hid_item *h;

        for  ( h = joy->pJoystick.os->hids; h; h = h->next )
        {
            int d = hid_get_data ( joy->pJoystick.os->hid_data_buf, h );

            int page = HID_PAGE ( h->usage );
            int usage = HID_USAGE ( h->usage );

            if ( page == HUP_GENERIC_DESKTOP )
            {
                int i;
                for ( i = 0; i < joy->num_axes; i++ )
                    if (joy->pJoystick.os->axes_usage[i] == usage)
                    {
                        if (usage == HUG_HAT_SWITCH)
                        {
                            if (d < 0 || d > 8)
                                d = 0;  /* safety */
                            joy->pJoystick.os->cache_axes[i] = (float)hatmap_x[d];
                            joy->pJoystick.os->cache_axes[i + 1] = (float)hatmap_y[d];
                        }
                        else
                        {
                            joy->pJoystick.os->cache_axes[i] = (float)d;
                        }
                        break;
                    }
            }
            else if (page == HUP_BUTTON)
            {
               if (usage > 0 && usage < _JS_MAX_BUTTONS + 1)
               {
                   if (d)
                       joy->pJoystick.os->cache_buttons |=  (1 << ( usage - 1 ));
                   else
                       joy->pJoystick.os->cache_buttons &= ~(1 << ( usage - 1 ));
               }
            }
        }
    }
#    ifdef HAVE_ERRNO_H
    if ( len < 0 && errno != EAGAIN )
#    else
    if ( len < 0 )
#    endif
    {
        perror( joy->pJoystick.os->fname );
        joy->error = 1;
    }
    if ( buttons != NULL ) *buttons = joy->pJoystick.os->cache_buttons;
    if ( axes    != NULL )
        memcpy ( axes, joy->pJoystick.os->cache_axes, sizeof(float) * joy->num_axes );
#  endif
#endif

#ifdef JS_NEW

    while ( 1 )
    {
        status = read ( joy->pJoystick.fd, &joy->pJoystick.js, sizeof(struct js_event) );

        if ( status != sizeof( struct js_event ) )
        {
#  ifdef HAVE_ERRNO_H
            if ( errno == EAGAIN )
            {
                /* Use the old values */
                if ( buttons )
                    *buttons = joy->pJoystick.tmp_buttons;
                if ( axes )
                    memcpy( axes, joy->pJoystick.tmp_axes,
                            sizeof( float ) * joy->num_axes );
                return;
            }
#  endif

            fgWarning ( "%s", joy->pJoystick.fname );
            joy->error = GL_TRUE;
            return;
        }

        switch ( joy->pJoystick.js.type & ~JS_EVENT_INIT )
        {
        case JS_EVENT_BUTTON:
            if( joy->pJoystick.js.value == 0 ) /* clear the flag */
                joy->pJoystick.tmp_buttons &= ~( 1 << joy->pJoystick.js.number );
            else
                joy->pJoystick.tmp_buttons |= ( 1 << joy->pJoystick.js.number );
            break;

        case JS_EVENT_AXIS:
            if ( joy->pJoystick.js.number < joy->num_axes )
            {
                joy->pJoystick.tmp_axes[ joy->pJoystick.js.number ] = ( float )joy->pJoystick.js.value;

                if( axes )
                    memcpy( axes, joy->pJoystick.tmp_axes, sizeof(float) * joy->num_axes );
            }
            break;

        default:
            fgWarning ( "PLIB_JS: Unrecognised /dev/js return!?!" );

            /* use the old values */

            if ( buttons != NULL ) *buttons = joy->pJoystick.tmp_buttons;
            if ( axes    != NULL )
                memcpy ( axes, joy->pJoystick.tmp_axes, sizeof(float) * joy->num_axes );

            return;
        }

        if( buttons )
            *buttons = joy->pJoystick.tmp_buttons;
    }
#else

    status = read( joy->pJoystick.fd, &joy->pJoystick.js, JS_RETURN );

    if ( status != JS_RETURN )
    {
        fgWarning( "%s", joy->pJoystick.fname );
        joy->error = GL_TRUE;
        return;
    }

    if ( buttons )
#    if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ )
        *buttons = ( joy->pJoystick.js.b1 ? 1 : 0 ) | ( joy->pJoystick.js.b2 ? 2 : 0 );  /* XXX Should not be here -- BSD is handled earlier */
#    else
        *buttons = joy->pJoystick.js.buttons;
#    endif

    if ( axes )
    {
        axes[ 0 ] = (float) joy->pJoystick.js.x;
        axes[ 1 ] = (float) joy->pJoystick.js.y;
    }
#endif
}