/************************************************************************** * driver_close */ LRESULT driver_close(DWORD_PTR dwDevID) { WINE_JSTCK* jstck = JSTCK_drvGet(dwDevID); if (jstck == NULL) return 0; jstck->in_use = FALSE; if (jstck->dev > 0) { close(jstck->dev); jstck->dev = 0; } return 1; }
/************************************************************************** * JSTCK_drvClose [internal] */ static LRESULT JSTCK_drvClose(DWORD_PTR dwDevID) { WINE_JSTCK* jstck = JSTCK_drvGet(dwDevID); if (jstck == NULL) return 0; jstck->in_use = 0; if (jstck->dev > 0) { close(jstck->dev); jstck->dev = 0; } return 1; }
/************************************************************************** * driver_joyGetPos */ LRESULT driver_joyGetPosEx(DWORD_PTR dwDevID, LPJOYINFOEX lpInfo) { WINE_JSTCK* jstck; int dev; #ifdef HAVE_LINUX_22_JOYSTICK_API struct js_event ev; #else struct js_status js; int dev_stat; #endif if ((jstck = JSTCK_drvGet(dwDevID)) == NULL) return MMSYSERR_NODRIVER; if ((dev = JSTCK_OpenDevice(jstck)) < 0) return JOYERR_PARMS; #ifdef HAVE_LINUX_22_JOYSTICK_API while ((read(dev, &ev, sizeof(struct js_event))) > 0) { if (ev.type == (JS_EVENT_AXIS)) { switch (jstck->axesMap[ev.number]) { case 0: /* X */ jstck->x = ev.value; break; case 1: /* Y */ jstck->y = ev.value; break; case 2: /* Z */ case 6: /* Throttle */ jstck->z = ev.value; break; case 5: /* Rz */ case 7: /* Rudder */ jstck->r = ev.value; break; case 3: /* Rx */ jstck->u = ev.value; break; case 4: /* Ry */ jstck->v = ev.value; break; case 16: /* Hat 0 X */ jstck->pov_x = ev.value; break; case 17: /* Hat 0 Y */ jstck->pov_y = ev.value; break; default: FIXME("Unknown joystick event '%d'\n", ev.number); } } else if (ev.type == (JS_EVENT_BUTTON)) { if (ev.value) { jstck->buttons |= (1 << ev.number); /* FIXME: what to do for this field when * multiple buttons are depressed ? */ if (lpInfo->dwFlags & JOY_RETURNBUTTONS) lpInfo->dwButtonNumber = ev.number + 1; } else jstck->buttons &= ~(1 << ev.number); } } /* EAGAIN is returned when the queue is empty */ if (errno != EAGAIN) { /* FIXME: error should not be ignored */ ERR("Error while reading joystick state (%s)\n", strerror(errno)); } /* Now, copy the cached values into Window's structure... */ if (lpInfo->dwFlags & JOY_RETURNBUTTONS) lpInfo->dwButtons = jstck->buttons; if (lpInfo->dwFlags & JOY_RETURNX) lpInfo->dwXpos = jstck->x + 32767; if (lpInfo->dwFlags & JOY_RETURNY) lpInfo->dwYpos = jstck->y + 32767; if (lpInfo->dwFlags & JOY_RETURNZ) lpInfo->dwZpos = jstck->z + 32767; if (lpInfo->dwFlags & JOY_RETURNR) lpInfo->dwRpos = jstck->r + 32767; # ifdef BODGE_THE_HAT else if (lpInfo->dwFlags & JOY_RETURNBUTTONS) { if (jstck->r > 0) lpInfo->dwButtons |= 1<<7; else if (jstck->r < 0) lpInfo->dwButtons |= 1<<8; } # endif if (lpInfo->dwFlags & JOY_RETURNU) lpInfo->dwUpos = jstck->u + 32767; # ifdef BODGE_THE_HAT else if (lpInfo->dwFlags & JOY_RETURNBUTTONS) { if (jstck->u > 0) lpInfo->dwButtons |= 1<<9; else if (jstck->u < 0) lpInfo->dwButtons |= 1<<10; } # endif if (lpInfo->dwFlags & JOY_RETURNV) lpInfo->dwVpos = jstck->v + 32767; if (lpInfo->dwFlags & JOY_RETURNPOV) { if (jstck->pov_y > 0) { if (jstck->pov_x < 0) lpInfo->dwPOV = 22500; /* SW */ else if (jstck->pov_x > 0) lpInfo->dwPOV = 13500; /* SE */ else lpInfo->dwPOV = 18000; /* S, JOY_POVBACKWARD */ } else if (jstck->pov_y < 0) { if (jstck->pov_x < 0) lpInfo->dwPOV = 31500; /* NW */ else if (jstck->pov_x > 0) lpInfo->dwPOV = 4500; /* NE */ else lpInfo->dwPOV = 0; /* N, JOY_POVFORWARD */ } else if (jstck->pov_x < 0) lpInfo->dwPOV = 27000; /* W, JOY_POVLEFT */ else if (jstck->pov_x > 0) lpInfo->dwPOV = 9000; /* E, JOY_POVRIGHT */ else lpInfo->dwPOV = JOY_POVCENTERED; /* Center */ } #else dev_stat = read(dev, &js, sizeof(js)); if (dev_stat != sizeof(js)) { return JOYERR_UNPLUGGED; /* FIXME: perhaps wrong, but what should I return else ? */ } js.x = js.x<<8; js.y = js.y<<8; if (lpInfo->dwFlags & JOY_RETURNX) lpInfo->dwXpos = js.x; /* FIXME: perhaps multiply it somehow ? */ if (lpInfo->dwFlags & JOY_RETURNY) lpInfo->dwYpos = js.y; if (lpInfo->dwFlags & JOY_RETURNBUTTONS) lpInfo->dwButtons = js.buttons; #endif TRACE("x: %d, y: %d, z: %d, r: %d, u: %d, v: %d, buttons: 0x%04x, flags: 0x%04x (fd %d)\n", lpInfo->dwXpos, lpInfo->dwYpos, lpInfo->dwZpos, lpInfo->dwRpos, lpInfo->dwUpos, lpInfo->dwVpos, lpInfo->dwButtons, lpInfo->dwFlags, dev ); return JOYERR_NOERROR; }
/************************************************************************** * JoyGetDevCaps [MMSYSTEM.102] */ LRESULT driver_joyGetDevCaps(DWORD_PTR dwDevID, LPJOYCAPSW lpCaps, DWORD dwSize) { WINE_JSTCK* jstck; #ifdef HAVE_LINUX_22_JOYSTICK_API int dev; char nrOfAxes; char nrOfButtons; char identString[MAXPNAMELEN]; int i; int driverVersion; #else static const WCHAR ini[] = {'W','i','n','e',' ','J','o','y','s','t','i','c','k',' ','D','r','i','v','e','r',0}; #endif if ((jstck = JSTCK_drvGet(dwDevID)) == NULL) return MMSYSERR_NODRIVER; #ifdef HAVE_LINUX_22_JOYSTICK_API if ((dev = JSTCK_OpenDevice(jstck)) < 0) return JOYERR_PARMS; ioctl(dev, JSIOCGAXES, &nrOfAxes); ioctl(dev, JSIOCGBUTTONS, &nrOfButtons); ioctl(dev, JSIOCGVERSION, &driverVersion); ioctl(dev, JSIOCGNAME(sizeof(identString)), identString); TRACE("Driver: 0x%06x, Name: %s, #Axes: %d, #Buttons: %d\n", driverVersion, identString, nrOfAxes, nrOfButtons); lpCaps->wMid = MM_MICROSOFT; lpCaps->wPid = MM_PC_JOYSTICK; MultiByteToWideChar(CP_UNIXCP, 0, identString, -1, lpCaps->szPname, MAXPNAMELEN); lpCaps->szPname[MAXPNAMELEN-1] = '\0'; lpCaps->wXmin = 0; lpCaps->wXmax = 0xFFFF; lpCaps->wYmin = 0; lpCaps->wYmax = 0xFFFF; lpCaps->wZmin = 0; lpCaps->wZmax = (nrOfAxes >= 3) ? 0xFFFF : 0; #ifdef BODGE_THE_HAT /* Half-Life won't allow you to map an axis event to things like "next weapon" and "use". Linux reports the hat on my stick as axis U and V. So, IFF BODGE_THE_HAT is defined, lie through our teeth and say we have 32 buttons, and we will map the axes to the high buttons. Really, perhaps this should be a registry entry, or even a parameter to the Linux joystick driver (which would completely remove the need for this.) */ lpCaps->wNumButtons = 32; #else lpCaps->wNumButtons = nrOfButtons; #endif if (dwSize == sizeof(JOYCAPSW)) { /* complete 95 structure */ lpCaps->wRmin = 0; lpCaps->wRmax = 0xFFFF; lpCaps->wUmin = 0; lpCaps->wUmax = 0xFFFF; lpCaps->wVmin = 0; lpCaps->wVmax = 0xFFFF; lpCaps->wMaxAxes = 6; /* same as MS Joystick Driver */ lpCaps->wNumAxes = 0; /* nr of axes in use */ lpCaps->wMaxButtons = 32; /* same as MS Joystick Driver */ lpCaps->szRegKey[0] = 0; lpCaps->szOEMVxD[0] = 0; lpCaps->wCaps = 0; for (i = 0; i < nrOfAxes; i++) { switch (jstck->axesMap[i]) { case 0: /* X */ case 1: /* Y */ lpCaps->wNumAxes++; break; case 2: /* Z */ case 6: /* Throttle */ lpCaps->wNumAxes++; lpCaps->wCaps |= JOYCAPS_HASZ; break; case 5: /* Rz */ case 7: /* Rudder */ lpCaps->wNumAxes++; lpCaps->wCaps |= JOYCAPS_HASR; break; case 3: /* Rx */ lpCaps->wNumAxes++; lpCaps->wCaps |= JOYCAPS_HASU; break; case 4: /* Ry */ lpCaps->wNumAxes++; lpCaps->wCaps |= JOYCAPS_HASV; break; case 16: /* Hat 0 X */ case 17: /* Hat 0 Y */ lpCaps->wCaps |= JOYCAPS_HASPOV | JOYCAPS_POV4DIR; /* TODO: JOYCAPS_POVCTS handling */ break; default: WARN("Unknown axis %hhu(%u). Skipped.\n", jstck->axesMap[i], i); } } } #else lpCaps->wMid = MM_MICROSOFT; lpCaps->wPid = MM_PC_JOYSTICK; strcpyW(lpCaps->szPname, ini); /* joystick product name */ lpCaps->wXmin = 0; lpCaps->wXmax = 0xFFFF; lpCaps->wYmin = 0; lpCaps->wYmax = 0xFFFF; lpCaps->wZmin = 0; lpCaps->wZmax = 0; lpCaps->wNumButtons = 2; if (dwSize == sizeof(JOYCAPSW)) { /* complete 95 structure */ lpCaps->wRmin = 0; lpCaps->wRmax = 0; lpCaps->wUmin = 0; lpCaps->wUmax = 0; lpCaps->wVmin = 0; lpCaps->wVmax = 0; lpCaps->wCaps = 0; lpCaps->wMaxAxes = 2; lpCaps->wNumAxes = 2; lpCaps->wMaxButtons = 4; lpCaps->szRegKey[0] = 0; lpCaps->szOEMVxD[0] = 0; } #endif return JOYERR_NOERROR; }