Mac and Linux SDL2 binary snapshots
Edward Rudd
2019-04-09 9cd2e9ec8fc0127393dfce9c0359d500c8c238be
source/src/haptic/linux/SDL_syshaptic.c
@@ -1,6 +1,6 @@
/*
  Simple DirectMedia Layer
  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
@@ -49,7 +49,7 @@
static int MaybeAddDevice(const char *path);
#if SDL_USE_LIBUDEV
static int MaybeRemoveDevice(const char *path);
void haptic_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
static void haptic_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
#endif /* SDL_USE_LIBUDEV */
/*
@@ -59,6 +59,7 @@
{
    char *fname;                /* Dev path name (like /dev/input/event1) */
    SDL_Haptic *haptic;         /* Associated haptic. */
    dev_t dev_num;
    struct SDL_hapticlist_item *next;
} SDL_hapticlist_item;
@@ -180,13 +181,16 @@
        SDL_UDEV_Quit();
        return SDL_SetError("Could not setup haptic <-> udev callback");
    }
    /* Force a scan to build the initial device list */
    SDL_UDEV_Scan();
#endif /* SDL_USE_LIBUDEV */
    return numhaptics;
}
int
SDL_SYS_NumHaptics()
SDL_SYS_NumHaptics(void)
{
    return numhaptics;
}
@@ -210,7 +214,7 @@
}
#if SDL_USE_LIBUDEV
void haptic_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
static void haptic_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
{
    if (devpath == NULL || !(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
        return;
@@ -236,14 +240,10 @@
static int
MaybeAddDevice(const char *path)
{
    dev_t dev_nums[MAX_HAPTICS];
    struct stat sb;
    int fd;
    int k;
    int duplicate;
    int success;
    SDL_hapticlist_item *item;
    if (path == NULL) {
        return -1;
@@ -255,14 +255,10 @@
    }
    /* check for duplicates */
    duplicate = 0;
    for (k = 0; (k < numhaptics) && !duplicate; ++k) {
        if (sb.st_rdev == dev_nums[k]) {
            duplicate = 1;
    for (item = SDL_hapticlist; item != NULL; item = item->next) {
        if (item->dev_num == sb.st_rdev) {
            return -1;  /* duplicate. */
        }
    }
    if (duplicate) {
        return -1;
    }
    /* try to open */
@@ -288,11 +284,12 @@
    }
    item->fname = SDL_strdup(path);
    if ( (item->fname == NULL) ) {
        SDL_free(item->fname);
    if (item->fname == NULL) {
        SDL_free(item);
        return -1;
    }
    item->dev_num = sb.st_rdev;
    /* TODO: should we add instance IDs? */
    if (SDL_hapticlist_tail == NULL) {
@@ -301,8 +298,6 @@
        SDL_hapticlist_tail->next = item;
        SDL_hapticlist_tail = item;
    }
    dev_nums[numhaptics] = sb.st_rdev;
    ++numhaptics;
@@ -391,8 +386,8 @@
            /* No name found, return device character device */
            name = item->fname;
        }
        close(fd);
    }
    close(fd);
    return name;
}
@@ -441,7 +436,7 @@
  open_err:
    close(fd);
    if (haptic->hwdata != NULL) {
        free(haptic->hwdata);
        SDL_free(haptic->hwdata);
        haptic->hwdata = NULL;
    }
    return -1;
@@ -473,7 +468,7 @@
    }
    /* Set the fname. */
    haptic->hwdata->fname = item->fname;
    haptic->hwdata->fname = SDL_strdup( item->fname );
    return 0;
}
@@ -547,15 +542,15 @@
    int ret;
    SDL_hapticlist_item *item;
    /* Find the joystick in the haptic list. */
    for (item = SDL_hapticlist; item; item = item->next) {
        if (SDL_strcmp(item->fname, joystick->hwdata->fname) == 0) {
            haptic->index = device_index;
            break;
        }
        ++device_index;
    }
    haptic->index = device_index;
    if (device_index >= MAX_HAPTICS) {
        return SDL_SetError("Haptic: Joystick doesn't have Haptic capabilities");
    }
@@ -570,7 +565,8 @@
        return -1;
    }
    haptic->hwdata->fname = item->fname;
    haptic->hwdata->fname = SDL_strdup( joystick->hwdata->fname );
    return 0;
}
@@ -592,6 +588,7 @@
        close(haptic->hwdata->fd);
        /* Free */
        SDL_free(haptic->hwdata->fname);
        SDL_free(haptic->hwdata);
        haptic->hwdata = NULL;
    }
@@ -615,7 +612,7 @@
        /* Opened and not closed haptics are leaked, this is on purpose.
         * Close your haptic devices after usage. */
        SDL_free(item->fname);
        item->fname = NULL;
        SDL_free(item);
    }
#if SDL_USE_LIBUDEV
@@ -624,6 +621,8 @@
#endif /* SDL_USE_LIBUDEV */
    numhaptics = 0;
    SDL_hapticlist = NULL;
    SDL_hapticlist_tail = NULL;
}
@@ -650,15 +649,14 @@
/*
 * Returns the ff_effect usable direction from a SDL_HapticDirection.
 * Initializes the ff_effect usable direction from a SDL_HapticDirection.
 */
static Uint16
SDL_SYS_ToDirection(SDL_HapticDirection * dir)
static int
SDL_SYS_ToDirection(Uint16 *dest, SDL_HapticDirection * src)
{
    Uint32 tmp;
    float f;                    /* Ideally we'd use fixed point math instead of floats... */
    switch (dir->type) {
    switch (src->type) {
    case SDL_HAPTIC_POLAR:
        /* Linux directions start from south.
                (and range from 0 to 0xFFFF)
@@ -668,25 +666,34 @@
                        90 deg -> 0x4000 (left)
                        180 deg -> 0x8000 (up)
                        270 deg -> 0xC000 (right)
                   The force pulls into the direction specified by Linux directions,
                   i.e. the opposite convention of SDL directions.
                    */
        tmp = (((18000 + dir->dir[0]) % 36000) * 0xFFFF) / 36000; /* convert to range [0,0xFFFF] */
        return (Uint16) tmp;
        tmp = ((src->dir[0] % 36000) * 0x8000) / 18000; /* convert to range [0,0xFFFF] */
        *dest = (Uint16) tmp;
        break;
       case SDL_HAPTIC_SPHERICAL:
    case SDL_HAPTIC_SPHERICAL:
            /*
                We convert to polar, because that's the only supported direction on Linux.
                The first value of a spherical direction is practically the same as a
                Polar direction, except that we have to add 90 degrees. It is the angle
                from EAST {1,0} towards SOUTH {0,1}.
                --> add 9000
                --> finally add 18000 and convert to [0,0xFFFF] as in case SDL_HAPTIC_POLAR.
                --> finally convert to [0,0xFFFF] as in case SDL_HAPTIC_POLAR.
            */
            tmp = ((dir->dir[0]) + 9000) % 36000;    /* Convert to polars */
        tmp = (((18000 + tmp) % 36000) * 0xFFFF) / 36000; /* convert to range [0,0xFFFF] */
        return (Uint16) tmp;
            tmp = ((src->dir[0]) + 9000) % 36000;    /* Convert to polars */
        tmp = (tmp * 0x8000) / 18000; /* convert to range [0,0xFFFF] */
        *dest = (Uint16) tmp;
        break;
    case SDL_HAPTIC_CARTESIAN:
        f = atan2(dir->dir[1], dir->dir[0]);
        if (!src->dir[1])
            *dest = (src->dir[0] >= 0 ? 0x4000 : 0xC000);
        else if (!src->dir[0])
            *dest = (src->dir[1] >= 0 ? 0x8000 : 0);
        else {
            float f = SDL_atan2(src->dir[1], src->dir[0]);    /* Ideally we'd use fixed point math instead of floats... */
                    /*
                      atan2 takes the parameters: Y-axis-value and X-axis-value (in that order)
                       - Y-axis-value is the second coordinate (from center to SOUTH)
@@ -695,14 +702,16 @@
                        have the first spherical value. Therefore we proceed as in case
                        SDL_HAPTIC_SPHERICAL and add another 9000 to get the polar value.
                      --> add 45000 in total
                      --> finally add 18000 and convert to [0,0xFFFF] as in case SDL_HAPTIC_POLAR.
                      --> finally convert to [0,0xFFFF] as in case SDL_HAPTIC_POLAR.
                    */
                tmp = (((int) (f * 18000. / M_PI)) + 45000) % 36000;
        tmp = (((18000 + tmp) % 36000) * 0xFFFF) / 36000; /* convert to range [0,0xFFFF] */
        return (Uint16) tmp;
                tmp = (((Sint32) (f * 18000. / M_PI)) + 45000) % 36000;
            tmp = (tmp * 0x8000) / 18000; /* convert to range [0,0xFFFF] */
            *dest = (Uint16) tmp;
        }
        break;
    default:
        return (Uint16) SDL_SetError("Haptic: Unsupported direction type.");
        return SDL_SetError("Haptic: Unsupported direction type.");
    }
    return 0;
@@ -717,7 +726,6 @@
static int
SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
{
    Uint32 tmp;
    SDL_HapticConstant *constant;
    SDL_HapticPeriodic *periodic;
    SDL_HapticCondition *condition;
@@ -733,8 +741,7 @@
        /* Header */
        dest->type = FF_CONSTANT;
        dest->direction = SDL_SYS_ToDirection(&constant->direction);
        if (dest->direction == (Uint16) - 1)
        if (SDL_SYS_ToDirection(&dest->direction, &constant->direction) == -1)
            return -1;
        /* Replay */
@@ -769,8 +776,7 @@
        /* Header */
        dest->type = FF_PERIODIC;
        dest->direction = SDL_SYS_ToDirection(&periodic->direction);
        if (dest->direction == (Uint16) - 1)
        if (SDL_SYS_ToDirection(&dest->direction, &periodic->direction) == -1)
            return -1;
        /* Replay */
@@ -795,11 +801,11 @@
        else if (periodic->type == SDL_HAPTIC_SAWTOOTHDOWN)
            dest->u.periodic.waveform = FF_SAW_DOWN;
        dest->u.periodic.period = CLAMP(periodic->period);
        dest->u.periodic.magnitude = periodic->magnitude;
        /* Linux expects 0-65535, so multiply by 2 */
        dest->u.periodic.magnitude = CLAMP(periodic->magnitude) * 2;
        dest->u.periodic.offset = periodic->offset;
        /* Phase is calculated based of offset from period and then clamped. */
        tmp = ((periodic->phase % 36000) * dest->u.periodic.period) / 36000;
        dest->u.periodic.phase = CLAMP(tmp);
        /* Linux phase is defined in interval "[0x0000, 0x10000[", corresponds with "[0deg, 360deg[" phase shift. */
        dest->u.periodic.phase = ((Uint32)periodic->phase * 0x10000U) / 36000;
        /* Envelope */
        dest->u.periodic.envelope.attack_length =
@@ -839,20 +845,18 @@
        /* Condition */
        /* X axis */
        dest->u.condition[0].right_saturation =
            CLAMP(condition->right_sat[0]);
        dest->u.condition[0].left_saturation = CLAMP(condition->left_sat[0]);
        dest->u.condition[0].right_saturation = condition->right_sat[0];
        dest->u.condition[0].left_saturation = condition->left_sat[0];
        dest->u.condition[0].right_coeff = condition->right_coeff[0];
        dest->u.condition[0].left_coeff = condition->left_coeff[0];
        dest->u.condition[0].deadband = CLAMP(condition->deadband[0]);
        dest->u.condition[0].deadband = condition->deadband[0];
        dest->u.condition[0].center = condition->center[0];
        /* Y axis */
        dest->u.condition[1].right_saturation =
            CLAMP(condition->right_sat[1]);
        dest->u.condition[1].left_saturation = CLAMP(condition->left_sat[1]);
        dest->u.condition[1].right_saturation = condition->right_sat[1];
        dest->u.condition[1].left_saturation = condition->left_sat[1];
        dest->u.condition[1].right_coeff = condition->right_coeff[1];
        dest->u.condition[1].left_coeff = condition->left_coeff[1];
        dest->u.condition[1].deadband = CLAMP(condition->deadband[1]);
        dest->u.condition[1].deadband = condition->deadband[1];
        dest->u.condition[1].center = condition->center[1];
        /*
@@ -866,8 +870,7 @@
        /* Header */
        dest->type = FF_RAMP;
        dest->direction = SDL_SYS_ToDirection(&ramp->direction);
        if (dest->direction == (Uint16) - 1)
        if (SDL_SYS_ToDirection(&dest->direction, &ramp->direction) == -1)
            return -1;
        /* Replay */
@@ -906,9 +909,9 @@
        dest->trigger.button = 0;
        dest->trigger.interval = 0;
        /* Rumble */
        dest->u.rumble.strong_magnitude = leftright->large_magnitude;
        dest->u.rumble.weak_magnitude = leftright->small_magnitude;
        /* Rumble (Linux expects 0-65535, so multiply by 2) */
        dest->u.rumble.strong_magnitude = CLAMP(leftright->large_magnitude) * 2;
        dest->u.rumble.weak_magnitude = CLAMP(leftright->small_magnitude) * 2;
        break;
@@ -954,7 +957,7 @@
    return 0;
  new_effect_err:
    free(effect->hweffect);
    SDL_free(effect->hweffect);
    effect->hweffect = NULL;
    return -1;
}
@@ -1158,5 +1161,6 @@
    return 0;
}
#endif /* SDL_HAPTIC_LINUX */
/* vi: set ts=4 sw=4 expandtab: */