|
|
|
@@ -862,7 +862,7 @@ static ControllerStatus listControllers(Controllers *controllers)
|
|
|
|
|
int controller = open(controllers->controller[i].path, O_RDONLY);
|
|
|
|
|
if (controller < 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(controllers->controller[i].name, "Unknown");
|
|
|
|
|
strncpy(controllers->controller[i].name, "Unknown", SIZE);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -912,16 +912,26 @@ static ControllerStatus listControllers(Controllers *controllers)
|
|
|
|
|
{
|
|
|
|
|
if (test_bit(code, bit[EV_KEY]))
|
|
|
|
|
{
|
|
|
|
|
if(controllers->controller[i].inputCount >= MAX_INPUTS) { // the number of input is limited
|
|
|
|
|
fprintf(stderr, "warning, maximum number of inputs reached !\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
controllers->controller[i].enabled = 1;
|
|
|
|
|
ControllerInput *controllerInput =
|
|
|
|
|
&controllers->controller[i].inputs[controllers->controller[i].inputCount++];
|
|
|
|
|
controllerInput->evType = EV_KEY;
|
|
|
|
|
controllerInput->evCode = code;
|
|
|
|
|
controllerInput->specialFunction = NO_SPECIAL_FUNCTION;
|
|
|
|
|
strcpy(controllerInput->inputName, controllers->controller[i].name);
|
|
|
|
|
strncpy(controllerInput->inputName, controllers->controller[i].name, SIZE);
|
|
|
|
|
strcat(controllerInput->inputName, "_");
|
|
|
|
|
strcat(controllerInput->inputName, codename(EV_KEY, code));
|
|
|
|
|
normaliseName(controllerInput->inputName);
|
|
|
|
|
if (snprintf(controllerInput->inputTechName, SIZE, "%s:KEY:%i", controllers->controller[i].path, code) >= 1024)
|
|
|
|
|
{
|
|
|
|
|
// hum ok, truncated value
|
|
|
|
|
}
|
|
|
|
|
strncpy(controllerInput->inputTechNegName, "-", SIZE); // unassignable value (not "" while some conf are empty)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -939,31 +949,70 @@ static ControllerStatus listControllers(Controllers *controllers)
|
|
|
|
|
controllerInput->evType = EV_ABS;
|
|
|
|
|
controllerInput->evCode = code;
|
|
|
|
|
controllerInput->specialFunction = NO_SPECIAL_FUNCTION;
|
|
|
|
|
strcpy(controllerInput->inputName, controllers->controller[i].name);
|
|
|
|
|
strncpy(controllerInput->inputName, controllers->controller[i].name, SIZE);
|
|
|
|
|
strcat(controllerInput->inputName, "_");
|
|
|
|
|
strcat(controllerInput->inputName, codename(EV_ABS, code));
|
|
|
|
|
normaliseName(controllerInput->inputName);
|
|
|
|
|
if (snprintf(controllerInput->inputTechName, SIZE, "%s:ABS:%i", controllers->controller[i].path, code) >= 1024)
|
|
|
|
|
{
|
|
|
|
|
// hum ok, truncated value
|
|
|
|
|
}
|
|
|
|
|
if (snprintf(controllerInput->inputTechNegName, SIZE, "%s:ABS_NEG:%i", controllers->controller[i].path, code) >= 1024)
|
|
|
|
|
{
|
|
|
|
|
// hum ok, truncated value
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ControllerInput *minControllerInput =
|
|
|
|
|
&controllers->controller[i].inputs[controllers->controller[i].inputCount++];
|
|
|
|
|
minControllerInput->evType = EV_ABS;
|
|
|
|
|
minControllerInput->evCode = code;
|
|
|
|
|
minControllerInput->specialFunction = ANALOGUE_TO_DIGITAL_MIN;
|
|
|
|
|
strcpy(minControllerInput->inputName, controllerInput->inputName);
|
|
|
|
|
strncpy(minControllerInput->inputName, controllerInput->inputName, SIZE);
|
|
|
|
|
strcat(minControllerInput->inputName, "_MIN");
|
|
|
|
|
if (snprintf(minControllerInput->inputTechName, SIZE, "%s:ABS:%i:MIN", controllers->controller[i].path, code) >= 1024)
|
|
|
|
|
{
|
|
|
|
|
// hum ok, truncated value
|
|
|
|
|
}
|
|
|
|
|
if (snprintf(minControllerInput->inputTechNegName, SIZE, "%s:ABS_NEG:%i:MIN", controllers->controller[i].path, code) >=
|
|
|
|
|
1024)
|
|
|
|
|
{
|
|
|
|
|
// hum ok, truncated value
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ControllerInput *maxControllerInput =
|
|
|
|
|
&controllers->controller[i].inputs[controllers->controller[i].inputCount++];
|
|
|
|
|
maxControllerInput->evType = EV_ABS;
|
|
|
|
|
maxControllerInput->evCode = code;
|
|
|
|
|
maxControllerInput->specialFunction = ANALOGUE_TO_DIGITAL_MAX;
|
|
|
|
|
strcpy(maxControllerInput->inputName, controllerInput->inputName);
|
|
|
|
|
strncpy(maxControllerInput->inputName, controllerInput->inputName, SIZE);
|
|
|
|
|
strcat(maxControllerInput->inputName, "_MAX");
|
|
|
|
|
if (snprintf(maxControllerInput->inputTechName, SIZE, "%s:ABS:%i:MAX", controllers->controller[i].path, code) >= 1024)
|
|
|
|
|
{
|
|
|
|
|
// hum ok, truncated value
|
|
|
|
|
}
|
|
|
|
|
if (snprintf(maxControllerInput->inputTechNegName, SIZE, "%s:ABS_NEG:%i:MAX", controllers->controller[i].path, code) >=
|
|
|
|
|
1024)
|
|
|
|
|
{
|
|
|
|
|
// hum ok, truncated value
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ControllerInput *shakeControllerInput = &controllers->controller[i].inputs[controllers->controller[i].inputCount++];
|
|
|
|
|
shakeControllerInput->evType = EV_ABS;
|
|
|
|
|
shakeControllerInput->evCode = code;
|
|
|
|
|
shakeControllerInput->specialFunction = ANALOGUE_SHAKE;
|
|
|
|
|
strncpy(shakeControllerInput->inputName, controllerInput->inputName, SIZE);
|
|
|
|
|
strcat(shakeControllerInput->inputName, "_SHAKE");
|
|
|
|
|
if (snprintf(shakeControllerInput->inputTechName, SIZE, "%s:ABS:%i:SHAKE", controllers->controller[i].path, code) >=
|
|
|
|
|
1024)
|
|
|
|
|
{
|
|
|
|
|
// hum ok, truncated value
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct input_absinfo absoluteFeatures;
|
|
|
|
|
ioctl(controller, EVIOCGABS(code), &absoluteFeatures);
|
|
|
|
|
controllers->controller[i].absMin[code] = absoluteFeatures.minimum;
|
|
|
|
|
controllers->controller[i].absMax[code] = absoluteFeatures.maximum;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -1066,31 +1115,67 @@ void *controllerThread(void *_args)
|
|
|
|
|
((double)event.value - (double)args->controller->absMin[event.code]) /
|
|
|
|
|
((double)args->controller->absMax[event.code] - (double)args->controller->absMin[event.code]);
|
|
|
|
|
|
|
|
|
|
if(args->controller->absTriggers[event.code].isNeg == 1) {
|
|
|
|
|
scaled = 1.0 - scaled;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (args->controller->absTriggers[event.code].enabled)
|
|
|
|
|
{
|
|
|
|
|
int channel = args->controller->absTriggers[event.code].channel;
|
|
|
|
|
// Deadzone handling
|
|
|
|
|
if (scaled < analogue_deadzones[channel].start_max)
|
|
|
|
|
|
|
|
|
|
if (args->controller->absTriggers[event.code].isAnalogue) {
|
|
|
|
|
// Deadzone handling
|
|
|
|
|
if (scaled < analogue_deadzones[channel].start_max)
|
|
|
|
|
scaled = 0.0;
|
|
|
|
|
if (scaled > analogue_deadzones[channel].middle_min && scaled < analogue_deadzones[channel].middle_max)
|
|
|
|
|
if (scaled > analogue_deadzones[channel].middle_min && scaled < analogue_deadzones[channel].middle_max)
|
|
|
|
|
scaled = 0.5;
|
|
|
|
|
if (scaled > analogue_deadzones[channel].end_min)
|
|
|
|
|
if (scaled > analogue_deadzones[channel].end_min)
|
|
|
|
|
scaled = 1.0;
|
|
|
|
|
|
|
|
|
|
setAnalogue(channel, scaled * (pow(2, jvsBits) - 1));
|
|
|
|
|
setAnalogue(channel, scaled * (pow(2, jvsBits) - 1));
|
|
|
|
|
} else {
|
|
|
|
|
setSwitch(args->controller->absTriggers[event.code].player,
|
|
|
|
|
args->controller->absTriggers[event.code].channel, scaled < 0.8 ? 0 : 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (args->controller->absTriggers[event.code].minEnabled)
|
|
|
|
|
{
|
|
|
|
|
setSwitch(args->controller->absTriggers[event.code].minPlayer,
|
|
|
|
|
args->controller->absTriggers[event.code].minChannel, scaled < 0.2);
|
|
|
|
|
if(event.value <= ((args->controller->absMin[event.code] + args->controller->absMax[event.code]) / 2)) {
|
|
|
|
|
if (args->controller->absTriggers[event.code].minEnabled)
|
|
|
|
|
{
|
|
|
|
|
int channel = args->controller->absTriggers[event.code].minChannel;
|
|
|
|
|
|
|
|
|
|
if (args->controller->absTriggers[event.code].isAnalogue) {
|
|
|
|
|
setAnalogue(channel, scaled < 0.2 ? 0.0 : pow(2, jvsBits) * 1.0);
|
|
|
|
|
} else {
|
|
|
|
|
setSwitch(args->controller->absTriggers[event.code].minPlayer,
|
|
|
|
|
args->controller->absTriggers[event.code].minChannel, scaled < 0.2 ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (args->controller->absTriggers[event.code].maxEnabled)
|
|
|
|
|
{
|
|
|
|
|
setSwitch(args->controller->absTriggers[event.code].maxPlayer,
|
|
|
|
|
args->controller->absTriggers[event.code].maxChannel, scaled > 0.8);
|
|
|
|
|
if(event.value >= ((args->controller->absMin[event.code] + args->controller->absMax[event.code]) / 2)) {
|
|
|
|
|
if (args->controller->absTriggers[event.code].maxEnabled)
|
|
|
|
|
{
|
|
|
|
|
int channel = args->controller->absTriggers[event.code].maxChannel;
|
|
|
|
|
|
|
|
|
|
if (args->controller->absTriggers[event.code].isAnalogue) {
|
|
|
|
|
setAnalogue(channel, scaled > 0.8 ? pow(2, jvsBits) : 0.0);
|
|
|
|
|
} else {
|
|
|
|
|
setSwitch(args->controller->absTriggers[event.code].maxPlayer,
|
|
|
|
|
args->controller->absTriggers[event.code].maxChannel, scaled > 0.8 ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (args->controller->absTriggers[event.code].shakeEnabled)
|
|
|
|
|
{
|
|
|
|
|
int channel = args->controller->absTriggers[event.code].shakeChannel;
|
|
|
|
|
if( (scaled > args->controller->absTriggers[event.code].shakePreviousScaled && scaled - args->controller->absTriggers[event.code].shakePreviousScaled > 0.1) ||
|
|
|
|
|
(scaled < args->controller->absTriggers[event.code].shakePreviousScaled && -scaled + args->controller->absTriggers[event.code].shakePreviousScaled > 0.1)) {
|
|
|
|
|
setAnalogue(channel, 0);
|
|
|
|
|
} else {
|
|
|
|
|
setAnalogue(channel, pow(2, jvsBits) / 2);
|
|
|
|
|
}
|
|
|
|
|
args->controller->absTriggers[event.code].shakePreviousScaled = scaled;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@@ -1215,7 +1300,7 @@ ControllerStatus getArcadeInputByName(char *name, ArcadeInput *input)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(tempName, name) == 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(input->name, arcadeInputs[index].name);
|
|
|
|
|
strncpy(input->name, arcadeInputs[index].name, SIZE);
|
|
|
|
|
input->channel = arcadeInputs[index].channel;
|
|
|
|
|
input->player = arcadeInputs[index].player;
|
|
|
|
|
return CONTROLLER_STATUS_SUCCESS;
|
|
|
|
@@ -1243,6 +1328,9 @@ ControllerStatus startControllerThreads(Controllers *controllers)
|
|
|
|
|
controllers->controller[i].absTriggers[j].enabled = 0;
|
|
|
|
|
controllers->controller[i].absTriggers[j].minEnabled = 0;
|
|
|
|
|
controllers->controller[i].absTriggers[j].maxEnabled = 0;
|
|
|
|
|
controllers->controller[i].absTriggers[j].shakeEnabled = 0;
|
|
|
|
|
controllers->controller[i].absTriggers[j].isNeg = 0;
|
|
|
|
|
controllers->controller[i].absTriggers[j].isAnalogue = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < KEY_MAX; j++)
|
|
|
|
@@ -1255,8 +1343,20 @@ ControllerStatus startControllerThreads(Controllers *controllers)
|
|
|
|
|
for (int j = 0; j < controllers->controller[i].inputCount; j++)
|
|
|
|
|
{
|
|
|
|
|
char *mapping = getMapping(controllers->controller[i].inputs[j].inputName);
|
|
|
|
|
if (mapping == NULL)
|
|
|
|
|
continue;
|
|
|
|
|
int negabs = 0;
|
|
|
|
|
|
|
|
|
|
if (mapping == NULL) {
|
|
|
|
|
// give a 2nd chance with a techninal mapping
|
|
|
|
|
mapping = getMapping(controllers->controller[i].inputs[j].inputTechName);
|
|
|
|
|
if (mapping == NULL) {
|
|
|
|
|
// give a 3rd change with negativ technical mapping
|
|
|
|
|
mapping = getMapping(controllers->controller[i].inputs[j].inputTechNegName);
|
|
|
|
|
negabs = 1;
|
|
|
|
|
if (mapping == NULL) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ArcadeInput input = {0};
|
|
|
|
|
ControllerStatus status = getArcadeInputByName(mapping, &input);
|
|
|
|
@@ -1277,10 +1377,13 @@ ControllerStatus startControllerThreads(Controllers *controllers)
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].enabled = 1;
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].channel =
|
|
|
|
|
input.channel;
|
|
|
|
|
strcpy(controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].name,
|
|
|
|
|
input.name);
|
|
|
|
|
strncpy(controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].name,
|
|
|
|
|
input.name, SIZE);
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].player =
|
|
|
|
|
input.player;
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].isNeg = negabs;
|
|
|
|
|
if (strstr(input.name, "ANALOGUE") == NULL)
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].isAnalogue = 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@@ -1289,10 +1392,13 @@ ControllerStatus startControllerThreads(Controllers *controllers)
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].maxEnabled = 1;
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].maxChannel =
|
|
|
|
|
input.channel;
|
|
|
|
|
strcpy(controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].maxName,
|
|
|
|
|
input.name);
|
|
|
|
|
strncpy(controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].maxName,
|
|
|
|
|
input.name, SIZE);
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].maxPlayer =
|
|
|
|
|
input.player;
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].isNeg = negabs;
|
|
|
|
|
if (strstr(input.name, "ANALOGUE") == NULL)
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].isAnalogue = 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@@ -1301,10 +1407,25 @@ ControllerStatus startControllerThreads(Controllers *controllers)
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].minEnabled = 1;
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].minChannel =
|
|
|
|
|
input.channel;
|
|
|
|
|
strcpy(controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].minName,
|
|
|
|
|
input.name);
|
|
|
|
|
strncpy(controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].minName,
|
|
|
|
|
input.name, SIZE);
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].minPlayer =
|
|
|
|
|
input.player;
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].isNeg = negabs;
|
|
|
|
|
if (strstr(input.name, "ANALOGUE") == NULL)
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].isAnalogue = 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ANALOGUE_SHAKE:
|
|
|
|
|
{
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].shakeEnabled = 1;
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].shakeChannel =
|
|
|
|
|
input.channel;
|
|
|
|
|
strncpy(controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].shakeName,
|
|
|
|
|
input.name, SIZE);
|
|
|
|
|
controllers->controller[i].absTriggers[controllers->controller[i].inputs[j].evCode].shakePlayer =
|
|
|
|
|
input.player;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@@ -1319,8 +1440,8 @@ ControllerStatus startControllerThreads(Controllers *controllers)
|
|
|
|
|
controllers->controller[i].keyTriggers[controllers->controller[i].inputs[j].evCode].enabled = 1;
|
|
|
|
|
controllers->controller[i].keyTriggers[controllers->controller[i].inputs[j].evCode].channel =
|
|
|
|
|
input.channel;
|
|
|
|
|
strcpy(controllers->controller[i].keyTriggers[controllers->controller[i].inputs[j].evCode].name,
|
|
|
|
|
input.name);
|
|
|
|
|
strncpy(controllers->controller[i].keyTriggers[controllers->controller[i].inputs[j].evCode].name,
|
|
|
|
|
input.name, SIZE);
|
|
|
|
|
controllers->controller[i].keyTriggers[controllers->controller[i].inputs[j].evCode].player =
|
|
|
|
|
input.player;
|
|
|
|
|
|
|
|
|
|