Example #1
0
static void
dumpdata(int f, report_desc_t rd, int loop)
{
	struct variable *var;
	int dlen, havedata, i, match, r, rid, use_rid;
	u_char *dbuf;
	enum hid_kind kind;

	kind = 0;
	rid = -1;
	use_rid = !!hid_get_report_id(f);
	do {
		if (kind < 3) {
			if (++rid >= 256) {
				rid = 0;
				kind++;
			}
			if (kind >= 3)
				rid = -1;
			for (var = vars; var; var = var->next) {
				if (rid == var->h.report_ID &&
				    kind == var->h.kind)
					break;
			}
			if (var == NULL)
				continue;
		}
		dlen = hid_report_size(rd, kind < 3 ? kind : hid_input, rid);
		if (dlen <= 0)
			continue;
		dbuf = malloc(dlen);
		memset(dbuf, 0, dlen);
		if (kind < 3) {
			dbuf[0] = rid;
			r = hid_get_report(f, kind, dbuf, dlen);
			if (r < 0)
				warn("hid_get_report(rid %d)", rid);
			havedata = !r && (rid == 0 || dbuf[0] == rid);
			if (rid != 0)
				dbuf[0] = rid;
		} else {
			r = read(f, dbuf, dlen);
			if (r < 1)
				err(1, "read error");
			havedata = 1;
		}
		if (verbose) {
			printf("Got %s report %d (%d bytes):",
			    kind == hid_output ? "output" :
			    kind == hid_feature ? "feature" : "input",
			    use_rid ? dbuf[0] : 0, dlen);
			if (havedata) {
				for (i = 0; i < dlen; i++)
					printf(" %02x", dbuf[i]);
			}
			printf("\n");
		}
		match = 0;
		for (var = vars; var; var = var->next) {
			if ((kind < 3 ? kind : hid_input) != var->h.kind)
				continue;
			if (var->h.report_ID != 0 &&
			    dbuf[0] != var->h.report_ID)
				continue;
			match = 1;
			if (!noname)
				printf("%s=", var->name);
			if (havedata)
				prdata(dbuf, &var->h);
			printf("\n");
		}
		if (match)
			printf("\n");
		free(dbuf);
	} while (loop || kind < 3);
}
Example #2
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;
}
Example #3
0
int
main (int argc, char **argv)
{
    char *device_file;
    int fd = -1;
    int report_id;
    report_desc_t report_desc;
    struct hid_data *data;
    hid_item_t item;
    boolean is_keyboard = FALSE;
    boolean is_keypad = FALSE;
    boolean is_mouse = FALSE;
    boolean is_joystick = FALSE;

    if (! hfp_init(argc, argv))
        goto end;

    device_file = getenv("HAL_PROP_HIDDEV_DEVICE");
    if (! device_file)
        goto end;

    fd = open(device_file, O_RDONLY);
    if (fd < 0)
        goto end;

    /* give a meaningful process title for ps(1) */
    setproctitle("%s", device_file);

#ifdef HAVE_LIBUSB20
    report_id = hid_get_report_id(fd);
    if (report_id == -1)
#else
    if (ioctl(fd, USB_GET_REPORT_ID, &report_id) < 0)
#endif
        goto end;

    hid_init(NULL);

    report_desc = hid_get_report_desc(fd);
    if (! report_desc)
        goto end;

    for (data = hid_start_parse(report_desc, ~0, report_id); hid_get_item(data, &item);)
        if (item.kind == hid_collection)
        {
            if (item.collection == HID_COLLECTION_APPLICATION)
            {
                const char *page;
                char *full_page;
                int i;

                page = hid_usage_page(HID_PAGE(item.usage));

                full_page = hfp_strdup_printf("%s Page", page);
                for (i = 0; full_page[i] != 0; i++)
                    if (full_page[i] == '_')
                        full_page[i] = ' ';

                libhal_device_property_strlist_append(hfp_ctx, hfp_udi, "hiddev.application_pages", full_page, &hfp_error);
                hfp_free(full_page);
            }

            switch (item.usage)
            {
            case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE):
                is_mouse = TRUE;
                break;

            case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_JOYSTICK):
            case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_GAME_PAD):
                is_joystick = TRUE;
                break;

            case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD):
                is_keyboard = TRUE;
                break;

            case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYPAD):
                is_keypad = TRUE;
                break;
            }
        }
    hid_end_parse(data);

    hid_dispose_report_desc(report_desc);

    if (is_keyboard || is_mouse || is_joystick || is_keypad)
    {
        libhal_device_add_capability(hfp_ctx, hfp_udi, "input", &hfp_error);
        libhal_device_set_property_string(hfp_ctx, hfp_udi, "info.category", "input", &hfp_error);
        libhal_device_set_property_string(hfp_ctx, hfp_udi, "input.device", device_file, &hfp_error);
    }
    if (is_keyboard)
        libhal_device_add_capability(hfp_ctx, hfp_udi, "input.keyboard", &hfp_error);
    if (is_keypad)
        libhal_device_add_capability(hfp_ctx, hfp_udi, "input.keypad", &hfp_error);
    if (is_keyboard || is_keypad)
        libhal_device_add_capability(hfp_ctx, hfp_udi, "input.keys", &hfp_error);
    if (is_mouse)
        libhal_device_add_capability(hfp_ctx, hfp_udi, "input.mouse", &hfp_error);
    if (is_joystick)
        libhal_device_add_capability(hfp_ctx, hfp_udi, "input.joystick", &hfp_error);

end:
    return 0;
}