Exemple #1
0
static void
hid_dump_descriptor(report_desc_t r)
{
	struct hid_data	*d = NULL;
	struct hid_item	 h;

	for (d = hid_start_parse(r, ~0, -1); hid_get_item(d, &h); ) {
		switch (h.kind) {
		case hid_collection:
			fprintf(stdout,
"Collection page=%s usage=%s\n", hid_usage_page(HID_PAGE(h.usage)),
				 hid_usage_in_page(h.usage));
			break;

		case hid_endcollection:
			fprintf(stdout, "End collection\n");
			break;

		case hid_input:
			hid_dump_item("Input  ", &h);
			break;

		case hid_output:
			hid_dump_item("Output ", &h);
			break;

		case hid_feature:
			hid_dump_item("Feature", &h);
			break;
		}
	}

	hid_end_parse(d);
}
Exemple #2
0
static void
dumpitem(const char *label, struct hid_item *h)
{
	if ((h->flags & HIO_CONST) && !verbose)
		return;
	printf("%s rid=%d size=%d count=%d page=%s usage=%s%s%s", label,
	       h->report_ID, h->report_size, h->report_count,
	       hid_usage_page(HID_PAGE(h->usage)),
	       hid_usage_in_page(h->usage),
	       h->flags & HIO_CONST ? " Const" : "",
	       h->flags & HIO_VARIABLE ? "" : " Array");
	printf(", logical range %d..%d",
	       h->logical_minimum, h->logical_maximum);
	if (h->physical_minimum != h->physical_maximum)
		printf(", physical range %d..%d",
		       h->physical_minimum, h->physical_maximum);
	if (h->unit)
		printf(", unit=0x%02x exp=%d", h->unit, h->unit_exponent);
	printf("\n");
}
Exemple #3
0
static void
dumpitems(report_desc_t r)
{
	struct hid_data *d;
	struct hid_item h;
	int size;

	for (d = hid_start_parse(r, ~0, -1); hid_get_item(d, &h); ) {
		switch (h.kind) {
		case hid_collection:
			printf("Collection type=%s page=%s usage=%s\n",
			       hid_collection_type(h.collection),
			       hid_usage_page(HID_PAGE(h.usage)),
			       hid_usage_in_page(h.usage));
			break;
		case hid_endcollection:
			printf("End collection\n");
			break;
		case hid_input:
			dumpitem("Input  ", &h);
			break;
		case hid_output:
			dumpitem("Output ", &h);
			break;
		case hid_feature:
			dumpitem("Feature", &h);
			break;
		}
	}
	hid_end_parse(d);
	size = hid_report_size(r, hid_input, -1);
	printf("Total   input size %d bytes\n", size);

	size = hid_report_size(r, hid_output, -1);
	printf("Total  output size %d bytes\n", size);

	size = hid_report_size(r, hid_feature, -1);
	printf("Total feature size %d bytes\n", size);
}
Exemple #4
0
static void
hid_dump_item(char const *label, struct hid_item *h)
{
	if ((h->flags & HIO_CONST) && !verbose)
		return;

	fprintf(stdout,
"%s id=%u size=%u count=%u page=%s usage=%s%s%s%s%s%s%s%s%s%s",
		label, (uint8_t) h->report_ID, h->report_size, h->report_count,
		hid_usage_page(HID_PAGE(h->usage)),
		hid_usage_in_page(h->usage),
		h->flags & HIO_CONST ? " Const" : "",
		h->flags & HIO_VARIABLE ? " Variable" : "",
		h->flags & HIO_RELATIVE ? " Relative" : "",
		h->flags & HIO_WRAP ? " Wrap" : "",
		h->flags & HIO_NONLINEAR ? " NonLinear" : "",
		h->flags & HIO_NOPREF ? " NoPref" : "",
		h->flags & HIO_NULLSTATE ? " NullState" : "",
		h->flags & HIO_VOLATILE ? " Volatile" : "",
		h->flags & HIO_BUFBYTES ? " BufBytes" : "");

	fprintf(stdout,
", logical range %d..%d",
		h->logical_minimum, h->logical_maximum);

	if (h->physical_minimum != h->physical_maximum)
		fprintf(stdout,
", physical range %d..%d",
			h->physical_minimum, h->physical_maximum);

	if (h->unit)
		fprintf(stdout,
", unit=0x%02x exp=%d", h->unit, h->unit_exponent);

	fprintf(stdout, "\n");
}
Exemple #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;
}
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);
}
Exemple #7
0
struct command *
parse_conf(const char *conf, report_desc_t repd, int reportid, int ignore)
{
	FILE *f;
	char *p;
	int line;
	char buf[SIZE], name[SIZE], value[SIZE], debounce[SIZE], action[SIZE];
	char usbuf[SIZE], coll[SIZE], *tmp;
	struct command *cmd, *cmds;
	struct hid_data *d;
	struct hid_item h;
	int inst, cinst, u, lo, hi, range, t;

	f = fopen(conf, "r");
	if (f == NULL)
		err(1, "%s", conf);

	cmds = NULL;
	for (line = 1; ; line++) {
		if (fgets(buf, sizeof buf, f) == NULL)
			break;
		if (buf[0] == '#' || buf[0] == '\n')
			continue;
		p = strchr(buf, '\n');
		while (p && isspace(peek(f))) {
			if (fgets(p, sizeof buf - strlen(buf), f) == NULL)
				break;
			p = strchr(buf, '\n');
		}
		if (p)
			*p = 0;
		if (sscanf(buf, "%s %s %s %[^\n]",
			   name, value, debounce, action) != 4) {
			if (isdemon) {
				syslog(LOG_WARNING, "config file `%s', line %d"
				       ", syntax error: %s", conf, line, buf);
				freecommands(cmds);
				return (NULL);
			} else {
				errx(1, "config file `%s', line %d,"
				     ", syntax error: %s", conf, line, buf);
			}
		}
		tmp = strchr(name, '#');
		if (tmp != NULL) {
			*tmp = 0;
			inst = atoi(tmp + 1);
		} else
			inst = 0;

		cmd = malloc(sizeof *cmd);
		if (cmd == NULL)
			err(1, "malloc failed");
		cmd->next = cmds;
		cmds = cmd;
		cmd->line = line;

		if (strcmp(value, "*") == 0) {
			cmd->anyvalue = 1;
		} else {
			cmd->anyvalue = 0;
			if (sscanf(value, "%d", &cmd->value) != 1) {
				if (isdemon) {
					syslog(LOG_WARNING,
					       "config file `%s', line %d, "
					       "bad value: %s (should be * or a number)\n",
					       conf, line, value);
					freecommands(cmds);
					return (NULL);
				} else {
					errx(1, "config file `%s', line %d, "
					     "bad value: %s (should be * or a number)\n",
					     conf, line, value);
				}
			}
		}

		if (sscanf(debounce, "%d", &cmd->debounce) != 1) {
			if (isdemon) {
				syslog(LOG_WARNING,
				       "config file `%s', line %d, "
				       "bad value: %s (should be a number >= 0)\n",
				       conf, line, debounce);
				freecommands(cmds);
				return (NULL);
			} else {
				errx(1, "config file `%s', line %d, "
				     "bad value: %s (should be a number >= 0)\n",
				     conf, line, debounce);
			}
		}

		coll[0] = 0;
		cinst = 0;
		for (d = hid_start_parse(repd, 1 << hid_input, reportid);
		     hid_get_item(d, &h); ) {
			if (verbose > 2)
				printf("kind=%d usage=%x\n", h.kind, h.usage);
			if (h.flags & HIO_CONST)
				continue;
			switch (h.kind) {
			case hid_input:
				if (h.usage_minimum != 0 ||
				    h.usage_maximum != 0) {
					lo = h.usage_minimum;
					hi = h.usage_maximum;
					range = 1;
				} else {
					lo = h.usage;
					hi = h.usage;
					range = 0;
				}
				for (u = lo; u <= hi; u++) {
					if (coll[0]) {
						snprintf(usbuf, sizeof usbuf,
						  "%s.%s:%s", coll+1,
						  hid_usage_page(HID_PAGE(u)),
						  hid_usage_in_page(u));
					} else {
						snprintf(usbuf, sizeof usbuf,
						  "%s:%s",
						  hid_usage_page(HID_PAGE(u)),
						  hid_usage_in_page(u));
					}
					if (verbose > 2)
						printf("usage %s\n", usbuf);
					t = strlen(usbuf) - strlen(name);
					if (t > 0) {
						if (strcmp(usbuf + t, name))
							continue;
						if (usbuf[t - 1] != '.')
							continue;
					} else if (strcmp(usbuf, name))
						continue;
					if (inst == cinst++)
						goto foundhid;
				}
				break;
			case hid_collection:
				snprintf(coll + strlen(coll),
				    sizeof coll - strlen(coll),  ".%s:%s",
				    hid_usage_page(HID_PAGE(h.usage)), 
				    hid_usage_in_page(h.usage));
				break;
			case hid_endcollection:
				if (coll[0])
					*strrchr(coll, '.') = 0;
				break;
			default:
				break;
			}
		}
		if (ignore) {
			if (verbose)
				warnx("ignore item '%s'", name);
			continue;
		}
		if (isdemon) {
			syslog(LOG_WARNING, "config file `%s', line %d, HID "
			       "item not found: `%s'\n", conf, line, name);
			freecommands(cmds);
			return (NULL);
		} else {
			errx(1, "config file `%s', line %d, HID item "
			     "not found: `%s'\n", conf, line, name);
		}

	foundhid:
		hid_end_parse(d);
		cmd->lastseen = -1;
		cmd->lastused = -1;
		cmd->item = h;
		cmd->name = strdup(name);
		cmd->action = strdup(action);
		if (range) {
			if (cmd->value == 1)
				cmd->value = u - lo;
			else
				cmd->value = -1;
		}

		if (verbose)
			printf("PARSE:%d %s, %d, '%s'\n", cmd->line, name,
			       cmd->value, cmd->action);
	}
	fclose(f);
	return (cmds);
}
Exemple #8
0
static void
parceargs(report_desc_t r, int all, int nnames, char **names)
{
	struct hid_data *d;
	struct hid_item h;
	char colls[1000];
	char hname[1000], *tmp1, *tmp2;
	struct variable *var, **pnext;
	int i, instance, cp, t;

	pnext = &vars;
	if (all) {
		if (wflag)
			errx(1, "Must not specify -w to read variables");
		cp = 0;
		for (d = hid_start_parse(r,
		    1<<hid_input | 1<<hid_output | 1<<hid_feature, -1);
		    hid_get_item(d, &h); ) {
			if (h.kind == hid_collection) {
				cp += sprintf(&colls[cp], "%s%s:%s",
				    cp != 0 ? "." : "",
				    hid_usage_page(HID_PAGE(h.usage)),
				    hid_usage_in_page(h.usage));
			} else if (h.kind == hid_endcollection) {
				tmp1 = strrchr(colls, '.');
				if (tmp1 != NULL) {
					cp -= strlen(tmp1);
					tmp1[0] = 0;
				} else {
					cp = 0;
					colls[0] = 0;
				}
			}
			if ((h.kind != hid_input && h.kind != hid_output &&
			    h.kind != hid_feature) || (h.flags & HIO_CONST))
				continue;
			var = malloc(sizeof(*var));
			memset(var, 0, sizeof(*var));
			asprintf(&var->name, "%s%s%s:%s",
			    colls, colls[0] != 0 ? "." : "",
			    hid_usage_page(HID_PAGE(h.usage)),
			    hid_usage_in_page(h.usage));
			var->h = h;
			*pnext = var;
			pnext = &var->next;
		}
		hid_end_parse(d);
		return;
	}
	for (i = 0; i < nnames; i++) {
		var = malloc(sizeof(*var));
		memset(var, 0, sizeof(*var));
		tmp1 = tmp2 = strdup(names[i]);
		strsep(&tmp2, "=");
		var->name = strsep(&tmp1, "#");
		if (tmp1 != NULL)
			var->instance = atoi(tmp1);
		if (tmp2 != NULL) {
			if (!wflag)
				errx(1, "Must specify -w to write variables");
			var->val = atoi(tmp2);
		} else
			if (wflag)
				errx(1, "Must not specify -w to read variables");
		*pnext = var;
		pnext = &var->next;

		instance = 0;
		cp = 0;
		for (d = hid_start_parse(r,
		    1<<hid_input | 1<<hid_output | 1<<hid_feature, -1);
		    hid_get_item(d, &h); ) {
			if (h.kind == hid_collection) {
				cp += sprintf(&colls[cp], "%s%s:%s",
				    cp != 0 ? "." : "",
				    hid_usage_page(HID_PAGE(h.usage)),
				    hid_usage_in_page(h.usage));
			} else if (h.kind == hid_endcollection) {
				tmp1 = strrchr(colls, '.');
				if (tmp1 != NULL) {
					cp -= strlen(tmp1);
					tmp1[0] = 0;
				} else {
					cp = 0;
					colls[0] = 0;
				}
			}
			if ((h.kind != hid_input && h.kind != hid_output &&
			    h.kind != hid_feature) || (h.flags & HIO_CONST))
				continue;
			snprintf(hname, sizeof(hname), "%s%s%s:%s",
			    colls, colls[0] != 0 ? "." : "",
			    hid_usage_page(HID_PAGE(h.usage)),
			    hid_usage_in_page(h.usage));
			t = strlen(hname) - strlen(var->name);
			if (t > 0) {
				if (strcmp(hname + t, var->name) != 0)
					continue;
				if (hname[t - 1] != '.')
					continue;
			} else if (strcmp(hname, var->name) != 0)
				continue;
			if (var->instance != instance++)
				continue;
			var->h = h;
			break;
		}
		hid_end_parse(d);
		if (var->h.usage == 0)
			errx(1, "Unknown item '%s'", var->name);
	}
}
Exemple #9
0
void
dumpdata(int f, report_desc_t rd, int loop)
{
	struct hid_data *d;
	struct hid_item h, *hids, *n;
	int r, dlen;
	u_char *dbuf;
	u_int32_t colls[100];
	int sp = 0;
	char namebuf[10000], *namep;

	hids = 0;
	for (d = hid_start_parse(rd, 1<<hid_input, -1);
	     hid_get_item(d, &h); ) {
		if (h.kind == hid_collection)
			colls[++sp] = h.usage;
		else if (h.kind == hid_endcollection)
			--sp;
		if (h.kind != hid_input || (h.flags & HIO_CONST))
			continue;
		h.next = hids;
		h.collection = colls[sp];
		hids = malloc(sizeof *hids);
		*hids = h;
	}
	hid_end_parse(d);
	rev(&hids);
	dlen = hid_report_size(rd, hid_input, -1);
	dbuf = malloc(dlen);
	if (!loop)
		if (hid_set_immed(f, 1) < 0) {
			if (errno == EOPNOTSUPP)
				warnx("device does not support immediate mode, only changes reported.");
			else
				err(1, "USB_SET_IMMED");
		}
	do {
		r = read(f, dbuf, dlen);
		if (r < 1) {
			err(1, "read error");
		}
		for (n = hids; n; n = n->next) {
			if (n->report_ID != 0 && dbuf[0] != n->report_ID)
				continue;
			namep = namebuf;
			namep += sprintf(namep, "%s:%s.",
					 hid_usage_page(HID_PAGE(n->collection)),
					 hid_usage_in_page(n->collection));
			namep += sprintf(namep, "%s:%s",
					 hid_usage_page(HID_PAGE(n->usage)),
					 hid_usage_in_page(n->usage));
			if (all || gotname(namebuf)) {
				if (!noname)
					printf("%s=", namebuf);
				prdata(dbuf, n);
				printf("\n");
			}
		}
		if (loop)
			printf("\n");
	} while (loop);
	free(dbuf);
}