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); } }
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); } } }
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); } } }
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); } }
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); } } }
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; } }
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); } }
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; }
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; } } } }
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); } } }
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; }
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; }
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; }
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); }
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); } } }
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); }
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); }
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; }
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 }