Пример #1
0
void
cc_recv(struct hid_appcol *ha, struct hid_report *hr)
{
	struct hid_interface *hi;
	struct hid_field *hf;
	struct hid_key keycodes[MAX_KEYCODE];
	unsigned int usage, up;
	int i, value, cnt, flags, total;

	hi = hid_appcol_get_parser_private(ha);
	assert(hi != NULL);

	total = 0;
	cnt = 0;
	memset(keycodes, 0, sizeof(keycodes));

	hf = NULL;
	while ((hf = hid_report_get_next_field(hr, hf, HID_INPUT)) != NULL) {
		flags = hid_field_get_flags(hf);
		if (flags & HIO_CONST)
			continue;
		for (i = 0; i < hf->hf_count; i++) {
			up = hid_field_get_usage_page(hf);
			hid_field_get_usage_value(hf, i, &usage, &value);
			if (total >= MAX_KEYCODE)
				continue;
			total++;
			if (up == HUP_CONSUMER &&
			    HID_USAGE(usage) == HUG_VOLUME && value) {
				cc_process_volume_usage(ha, hr, value);
				continue;
			}
			if (value) {
				if (cnt >= MAX_KEYCODE)
					continue;
				keycodes[cnt].code = HID_USAGE(usage);
				keycodes[cnt].up = up;
				cnt++;
			}
		}
	}

	if (total > 0 && verbose > 1) {
		PRINT1("hid codes: ");
		if (cnt == 0)
			printf("none");
		for (i = 0; i < cnt; i++)
			printf("0x%02X ", keycodes[i].code);
		putchar('\n');
	}

	kbd_input(ha, 0, keycodes, total);
}
Пример #2
0
/*
 * return appropriate mode for HID descriptor
 */
const char *
hid_mode(prop_data_t desc)
{
	report_desc_t r;
	hid_data_t d;
	struct hid_item h;
	const char *mode;

	hid_init(NULL);

	mode = BTDEVauth;	/* default */

	r = hid_use_report_desc(prop_data_data_nocopy(desc),
				prop_data_size(desc));
	if (r == NULL)
		err(EXIT_FAILURE, "hid_use_report_desc");

	d = hid_start_parse(r, ~0, -1);
	while (hid_get_item(d, &h) > 0) {
		if (h.kind == hid_collection
		    && HID_PAGE(h.usage) == HUP_GENERIC_DESKTOP
		    && HID_USAGE(h.usage) == HUG_KEYBOARD)
			mode = BTDEVencrypt;
	}

	hid_end_parse(d);
	hid_dispose_report_desc(r);

	return mode;
}
Пример #3
0
const char *
hid_usage_in_page(unsigned int u)
{
	int page = HID_PAGE(u);
	int i = HID_USAGE(u);
	static char b[100];
	int j, k, us;

	for (k = 0; k < npages; k++)
		if (pages[k].usage == page)
			break;
	if (k >= npages)
		goto bad;
	for (j = 0; j < pages[k].pagesize; j++) {
		us = pages[k].page_contents[j].usage;
		if (us == -1) {
			sprintf(b,
			    fmtcheck(pages[k].page_contents[j].name, "%d"),
			    i);
			return b;
		}
		if (us == i)
			return pages[k].page_contents[j].name;
	}
 bad:
	sprintf(b, "0x%04x", i);
	return b;
}
Пример #4
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;
      }
    }
  }

}
Пример #5
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;
}
Пример #6
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;
}
Пример #7
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;
	}

	rep = &hw->inreport;
	if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
		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_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);
}
Пример #8
0
int32_t
kbd_status_changed(bthid_session_p s, uint8_t *data, int32_t len)
{
	vkbd_status_t	st;
	uint8_t		leds, report_id;
	hid_device_p	hid_device;
	hid_data_t	d;
	hid_item_t	h;

	assert(s != NULL);
	assert(len == sizeof(vkbd_status_t));

	memcpy(&st, data, sizeof(st));
	leds = 0;
	report_id = NO_REPORT_ID;

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

	for (d = hid_start_parse(hid_device->desc, 1 << hid_output, -1);
	     hid_get_item(d, &h) > 0; ) {
		if (HID_PAGE(h.usage) == HUP_LEDS) {
			if (report_id == NO_REPORT_ID)
				report_id = h.report_ID;
			else if (h.report_ID != report_id)
				syslog(LOG_WARNING, "Output HID report IDs " \
					"for %s do not match: %d vs. %d. " \
					"Please report",
					bt_ntoa(&s->bdaddr, NULL),
					h.report_ID, report_id);
			
			switch(HID_USAGE(h.usage)) {
			case 0x01: /* Num Lock LED */
				if (st.leds & LED_NUM)
					hid_set_data(&leds, &h, 1);
				break;

			case 0x02: /* Caps Lock LED */
				if (st.leds & LED_CAP)
					hid_set_data(&leds, &h, 1);
				break;

			case 0x03: /* Scroll Lock LED */
				if (st.leds & LED_SCR)
					hid_set_data(&leds, &h, 1);
				break;

			/* XXX add other LEDs ? */
			}
		}
	}
	hid_end_parse(d);

	data[0] = 0xa2; /* DATA output (HID output report) */

	if (report_id != NO_REPORT_ID) {
		data[1] = report_id;
		data[2] = leds;
		len = 3;
	} else {
		data[1] = leds;
		len = 2;
	}

	write(s->intr, data, len);

	return (0);
}
Пример #9
0
enum StringDescriptorId_t {
	StringDescriptorId_Language     = 0,
	StringDescriptorId_Manufacturer = 1,
	StringDescriptorId_Product      = 2
};

/*
	Note that the key report is split into several similar items, because:

	An item field cannot span more than 4 bytes in a report. For example, a 32-bit
	item must start on a byte boundary to satisfy this condition.
		- USB HID 1.11 Specification, p. 57
*/
local const u8 PROGMEM NkroKeyboardReportDescriptor[] = {
	HID_USAGE_PAGE      (8, HID_USAGE_PAGE_GENERIC_DESKTOP_CONTROLS),
	HID_USAGE           (8, HID_DESKTOP_KEYBOARD),
	HID_COLLECTION      (8, HID_COLLECTION_APPLICATION),

	HID_USAGE_PAGE      (8, HID_USAGE_PAGE_KEYBOARD_KEYPAD),
	HID_LOGICAL_MINIMUM (8, 0x00),
	HID_LOGICAL_MAXIMUM (8, 0x01),
	HID_REPORT_SIZE     (8, 0x01),
	HID_REPORT_COUNT    (8, 0x20),
	HID_USAGE_MINIMUM   (8, 0x00),
	HID_USAGE_MAXIMUM   (8, 0x1F),
	HID_INPUT           (8, HID_DATA | HID_VARIABLE | HID_ABSOLUTE),

	HID_USAGE_MINIMUM   (8, 0x20),
	HID_USAGE_MAXIMUM   (8, 0x3F),
	HID_INPUT           (8, HID_DATA | HID_VARIABLE | HID_ABSOLUTE),
Пример #10
0
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);
}
Пример #11
0
  .bDeviceClass = 0,
  .bDeviceSubClass = 0,
  .bDeviceProtocol = 0,
  .bMaxPacketSize0 = 64,
  .idVendor = 0x1209,
  .idProduct = 0xCC86,
  .bcdDevice = 0x0100,
  .iManufacturer = 1,
  .iProduct = 2,
  .iSerialNumber = 3,
  .bNumConfigurations = 1,
};

static const uint8_t hid_report_descriptor[] = {
  0x06, 0x00, 0xff,
  HID_USAGE   (0x01),
  HID_COLLECTION    (HID_COLLECTION_APPLICATION),
    HID_REPORT_ID(1),
    HID_LOGICAL_MINIMUM     (0),
    HID_LOGICAL_MAXIMUM     (255),
    HID_REPORT_SIZE   (8),
    HID_REPORT_COUNT  (9),
    HID_USAGE   (0x01),
    HID_INPUT (0x02),
  HID_END_COLLECTION,
  0x06, 0x00, 0xff,
  HID_USAGE   (0x01),
  HID_COLLECTION    (HID_COLLECTION_APPLICATION),
    HID_REPORT_ID(2),
    HID_LOGICAL_MINIMUM     (0),
    HID_LOGICAL_MAXIMUM     (255),
int
jstkOpenDevice_bsd(JoystickDevPtr joystick, Bool probe)
{
    int cur_axis;
    int is_joystick, report_id = 0;
    int got_something;
    struct hid_data *d;
    struct hid_item h;
    report_desc_t rd;
    struct jstk_bsd_hid_data *bsddata;

    if (joystick->fd == -1) {
        if ((joystick->fd = open(joystick->device, O_RDWR | O_NDELAY, 0)) < 0) {
            xf86Msg(X_ERROR, "Cannot open joystick '%s' (%s)\n",
                    joystick->device, strerror(errno));
            return -1;
        }
    }

    if ((rd = hid_get_report_desc(joystick->fd)) == 0) {
        xf86Msg(X_ERROR, "Joystick: hid_get_report_desc failed: %s\n",
                strerror(errno));
        jstkCloseDevice_bsd(joystick);
        return -1;
    }

    if (ioctl(joystick->fd, USB_GET_REPORT_ID, &report_id) < 0) {
        xf86Msg(X_ERROR, "Joystick: ioctl USB_GET_REPORT_ID failed: %s\n",
                strerror(errno));
        jstkCloseDevice_bsd(joystick);
        return -1;
    }

    bsddata = (struct jstk_bsd_hid_data*)
              malloc(sizeof(struct jstk_bsd_hid_data));
    joystick->devicedata = (void*) bsddata;

    bsddata->dlen = hid_report_size(rd, hid_input, report_id);

    if ((bsddata->data_buf = malloc(bsddata->dlen)) == NULL) {
        fprintf(stderr, "error: couldn't malloc %d bytes\n", bsddata->dlen);
        hid_dispose_report_desc(rd);
        jstkCloseDevice_bsd(joystick);
        return -1;
    }

    is_joystick = 0;
    got_something = 0;
    cur_axis = 0;
    bsddata->hats = 0;
    joystick->num_axes = 0;
    joystick->num_buttons = 0;

    for (d = hid_start_parse(rd, 1 << hid_input, report_id);
         hid_get_item(d, &h); )
    {
        int usage, page;

        page = HID_PAGE(h.usage);
        usage = HID_USAGE(h.usage);

        is_joystick = is_joystick ||
                      (h.kind == hid_collection &&
                       page == HUP_GENERIC_DESKTOP &&
                       (usage == HUG_JOYSTICK || usage == HUG_GAME_PAD));

        if (h.kind != hid_input)
            continue;

        if (!is_joystick)
            continue;

        if (page == HUP_GENERIC_DESKTOP) {
            if (usage == HUG_HAT_SWITCH) {
                if ((bsddata->hats < MAXAXES) && (joystick->num_axes <= MAXAXES-2)) {
                    got_something = 1;
                    memcpy(&bsddata->hat_item[bsddata->hats], &h, sizeof(h));
                    bsddata->hats++;
                    joystick->num_axes += 2;
                }
            } else {
                if (joystick->num_axes < MAXAXES) {
                    got_something = 1;
                    memcpy(&bsddata->axis_item[cur_axis], &h, sizeof(h));
                    cur_axis++;
                    joystick->num_axes++;
                }
            }
        } else if (page == HUP_BUTTON) {
            if (joystick->num_buttons < MAXBUTTONS) {
                got_something = 1;
                memcpy(&bsddata->button_item[joystick->num_buttons], &h, sizeof(h));
                joystick->num_buttons++;
            }
	}
    }
    hid_end_parse(d);

    if (!got_something) {
        free(bsddata->data_buf);
        xf86Msg(X_ERROR, "Joystick: Didn't find any usable axes.\n");
        jstkCloseDevice_bsd(joystick);
        return -1;
    }

    bsddata->hotdata = 0;
    if (probe == TRUE) {
        xf86Msg(X_INFO, "Joystick: %d buttons, %d axes\n", 
                joystick->num_buttons, joystick->num_axes);
    }

    joystick->open_proc = jstkOpenDevice_bsd;
    joystick->read_proc = jstkReadData_bsd;
    joystick->close_proc = jstkCloseDevice_bsd;

    return joystick->fd;
}
Пример #13
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
}
Пример #14
0
void USBJoystick::initJoystick(const char *name)
{
  report_desc_t rd;
  hid_data *d;
  hid_item h;
  int report_id;

  status = false;
  hids = NULL;
  num_axis = 0;

  if ((fd = open(name, O_RDONLY | O_NONBLOCK)) < 0)
    return;

  if ((rd = hid_get_report_desc(fd)) == 0) {
    close(fd);
    return;
  }

  data_buf_size = hid_report_size(rd, hid_input, &report_id);
  if ((data_buf = (char *)malloc(data_buf_size)) == NULL) {
    hid_dispose_report_desc(rd);
  }
  data_buf_offset = (report_id != 0);

  int is_joystick = 0;
  int interesting_hid = FALSE;
  for (d = hid_start_parse(rd, 1 << hid_input); hid_get_item(d, &h); ) {
    int page = HID_PAGE(h.usage);
    int usage = HID_USAGE(h.usage);
    is_joystick = is_joystick ||
      (h.kind == hid_collection && page == HUP_GENERIC_DESKTOP &&
      (usage == HUG_JOYSTICK || usage == HUG_GAME_PAD));

    if (h.kind != hid_input)
      continue;

    if (!is_joystick)
      continue;

    interesting_hid = TRUE;
    if (page == HUP_GENERIC_DESKTOP) {
      int which_axis;
      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;
	default: interesting_hid = FALSE;
      }
      if (interesting_hid) {
	axis_const[which_axis] = 1000 + (2000 * h.logical_maximum) / 
	  (h.logical_minimum - h.logical_maximum);
	axis_scale[which_axis] = (2000 * 10000) / 
	  (h.logical_maximum - h.logical_minimum);
	axis[which_axis] = (h.logical_minimum + h.logical_maximum) / 2;
	if (num_axis < (which_axis + 1))
	  num_axis = which_axis + 1;
      }
    }
    if (interesting_hid) {
      struct hid_item *newhid = new struct hid_item;
      if (newhid == NULL) {
	close(fd);
	return;
      }
      *newhid = h;
      newhid->next = hids;
      hids = newhid;
    }
  }
  hid_end_parse(d);

  status = true;
}
Пример #15
0
void
mouse_recv(struct hid_appcol *ha, struct hid_report *hr)
{
	struct hid_interface *hi;
	struct hid_field *hf;
	struct mouse_dev *md;
	struct mouse_info mi;
	unsigned int usage, up;
	int has_wheel, has_twheel, has_fake_twheel, has_z, flags;
	int b, btn, dx, dy, dw, dt, df, dz, i;

	hi = hid_appcol_get_parser_private(ha);
	assert(hi != NULL);
	md = hid_appcol_get_private(ha);
	assert(md != NULL);

	dx = dy = dw = dt = df = dz = 0;
	has_wheel = has_twheel = has_fake_twheel = has_z = 0;
	btn = 0;
	hf = NULL;
	while ((hf = hid_report_get_next_field(hr, hf, HID_INPUT)) != NULL) {
		flags = hid_field_get_flags(hf);
		if (flags & HIO_CONST || (flags & HIO_VARIABLE) == 0)
			continue;
		for (i = 0; i < hf->hf_count; i++) {
			usage = HID_USAGE(hf->hf_usage[i]);
			up = HID_PAGE(hf->hf_usage[i]);
			if (up == HUP_BUTTON) {
				if (usage < BUTTON_MAX && hf->hf_value[i]) {
					b = usage - 1;
					if (b == 1)
						b = 2;
					else if (b == 2)
						b = 1;
					btn |= (1 << b);
				}
				continue;
			}

			switch (hf->hf_usage[i]) {
			case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X):
				dx = hf->hf_value[i];
				break;
			case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y):
				dy = hf->hf_value[i];
				break;
			case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL):
				/*
				 * HUG_WHEEL is the most common place for
				 * mouse wheel.
				 */
				has_wheel = 1;
				dw = -hf->hf_value[i];
				break;
			case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL):
				/*
				 * Some older Microsoft mouse (e.g. Microsoft
				 * Wireless Intellimouse 2.0) used
				 * HUG_TWHEEL(0x48) to report its wheel. Note
				 * that HUG_TWHEEL seems to be a temporary thing
				 * at the time. (The name TWHEEL is also a
				 * non-standard name) Later new HID usage spec
				 * defined 0x48 as usage "Resolution Multiplier"
				 * and newer M$ mouse stopped using 0x48 for
				 * mouse wheel.
				 */
				has_fake_twheel = 1;
				df = -hf->hf_value[i];
				break;
			case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z):
				/* Some mouse use HUG_Z to report its wheel. */
				has_z = 1;
				dz = -hf->hf_value[i];
				break;
			case HID_USAGE2(HUP_CONSUMER, HUC_AC_PAN):
				/* Tilt wheel. */
				has_twheel = 1;
				dt = -hf->hf_value[i];
				break;
			}
		}
	}

	if (verbose > 1)
		PRINT1("mouse received data: dx(%d) dy(%d) dw(%d) dt(%d) "
		    "btn(%#x)\n", dx, dy, dw, dt, btn);

	/*
	 * There is no way to report tilt wheel to the kernel, for now
	 * translate them to button #8 and #9.
	 */
	if (has_twheel) {
		if (dt > 0)
			btn |= (1 << 8);
		else if (dt < 0)
			btn |= (1 << 9);
	}

	/* Push the data to console device. (and sysmouse) */
	mi.operation = MOUSE_ACTION;
	mi.u.data.x = dx;
	mi.u.data.y = dy;
	mi.u.data.buttons = btn;
	if (has_wheel)
		mi.u.data.z = dw;
	else if (has_fake_twheel)
		mi.u.data.z = df;
	else if (has_z)
		mi.u.data.z = dz;
	else
		mi.u.data.z = 0;

	if (ioctl(md->cons_fd, CONS_MOUSECTL, &mi) < 0)
		syslog(LOG_ERR, "%s[%d] could not submit mouse data:"
		    " ioctl failed: %m", basename(hi->dev), hi->ndx);
}
Пример #16
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;
}