Edit

IABSD.fr/xenocara/driver/xf86-input-joystick/src/backend_bsd.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2011-11-05 14:01:47
    Hash : 0e181385
    Message : Update to xf86-input-joystick 1.6.0 for good now.

  • driver/xf86-input-joystick/src/backend_bsd.c
  • /*
     * Copyright 2007-2008 by Sascha Hlusiak. <saschahlusiak@freedesktop.org>     
     *                                                                            
     * Permission to use, copy, modify, distribute, and sell this software and its
     * documentation for any purpose is  hereby granted without fee, provided that
     * the  above copyright   notice appear  in   all  copies and  that both  that
     * copyright  notice   and   this  permission   notice  appear  in  supporting
     * documentation, and that   the  name of  Sascha   Hlusiak  not  be  used  in
     * advertising or publicity pertaining to distribution of the software without
     * specific,  written      prior  permission.     Sascha   Hlusiak   makes  no
     * representations about the suitability of this software for any purpose.  It
     * is provided "as is" without express or implied warranty.                   
     *                                                                            
     * SASCHA  HLUSIAK  DISCLAIMS ALL   WARRANTIES WITH REGARD  TO  THIS SOFTWARE,
     * INCLUDING ALL IMPLIED   WARRANTIES OF MERCHANTABILITY  AND   FITNESS, IN NO
     * EVENT  SHALL SASCHA  HLUSIAK  BE   LIABLE   FOR ANY  SPECIAL, INDIRECT   OR
     * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     * DATA  OR PROFITS, WHETHER  IN  AN ACTION OF  CONTRACT,  NEGLIGENCE OR OTHER
     * TORTIOUS  ACTION, ARISING    OUT OF OR   IN  CONNECTION  WITH THE USE    OR
     * PERFORMANCE OF THIS SOFTWARE.
     *
     */
    
    /**
     * This provides the backend for USB-HIDs for NetBSD, OpenBSD and FreeBSD
     * Needs the uhid module loaded. Device names are /dev/uhid?
     **/
    
    #ifdef HAVE_CONFIG_H
    #include "config.h"
    #endif
    
    #include <xorg-server.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/ioctl.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <stdlib.h>
    
    #include <xf86.h>
    #include <xf86_OSproc.h>
    
    #include <usbhid.h>
    #include <dev/usb/usb.h>
    #include <dev/usb/usbhid.h>
    #ifdef HAVE_DEV_USB_USB_IOCTL_H
        #include <dev/usb/usb_ioctl.h>
    #endif
    
    #include "jstk.h"
    #include "backend_bsd.h"
    
    
    struct jstk_bsd_hid_data {
        int dlen;                                /* Length of one data chunk */
        char *data_buf;                          /* Data buffer with right size */
        struct hid_item axis_item[MAXAXES];      /* Axis HID items */
        struct hid_item button_item[MAXBUTTONS]; /* Button HID items */
        struct hid_item hat_item[MAXAXES];       /* HID items for hats */
        int hats;                                /* Number of hats */
        int hotdata;                             /* Is unprocessed data available
                                                    in data_buf? */
    };
    
    static void jstkCloseDevice_bsd(JoystickDevPtr joystick);
    static int jstkReadData_bsd(JoystickDevPtr joystick,
                                JOYSTICKEVENT *event,
                                int *number);
    
    
    
    /***********************************************************************
     *
     * jstkOpenDevice --
     *
     * Open and initialize a joystick device
     * Returns the filedescriptor, or -1 in case of error
     *
     ***********************************************************************
     */
    
    int
    jstkOpenDevice_bsd(JoystickDevPtr joystick, Bool probe)
    {
        int cur_axis;
        int is_joystick, report_id = 0;
        int got_something;
        struct hid_data *d;
        struct hid_item h;
        report_desc_t rd;
        struct jstk_bsd_hid_data *bsddata;
    
        if ((joystick->fd = open(joystick->device, O_RDWR | O_NDELAY, 0)) < 0) {
            xf86Msg(X_ERROR, "Cannot open joystick '%s' (%s)\n", joystick->device,
                    strerror(errno));
            return -1;
        }
    
        if ((rd = hid_get_report_desc(joystick->fd)) == 0) {
            xf86Msg(X_ERROR, "Joystick: hid_get_report_desc failed: %s\n",
                    strerror(errno));
            close(joystick->fd);
            joystick->fd = -1;
            return -1;
        }
    
        if (ioctl(joystick->fd, USB_GET_REPORT_ID, &report_id) < 0) {
            xf86Msg(X_ERROR, "Joystick: ioctl USB_GET_REPORT_ID failed: %s\n",
                    strerror(errno));
            close(joystick->fd);
            joystick->fd = -1;
            return -1;
        }
    
        bsddata = (struct jstk_bsd_hid_data*)
                  malloc(sizeof(struct jstk_bsd_hid_data));
        bsddata->dlen = hid_report_size(rd, hid_input, report_id);
    
        if ((bsddata->data_buf = malloc(bsddata->dlen)) == NULL) {
            fprintf(stderr, "error: couldn't malloc %d bytes\n", bsddata->dlen);
            hid_dispose_report_desc(rd);
            free(bsddata);
            close(joystick->fd);
            joystick->fd = -1;
            return -1;
        }
    
        is_joystick = 0;
        got_something = 0;
        cur_axis = 0;
        bsddata->hats = 0;
        joystick->num_axes = 0;
        joystick->num_buttons = 0;
    
        for (d = hid_start_parse(rd, 1 << hid_input, report_id);
             hid_get_item(d, &h); )
        {
            int usage, page;
    
            page = HID_PAGE(h.usage);
            usage = HID_USAGE(h.usage);
    
            is_joystick = is_joystick ||
                          (h.kind == hid_collection &&
                           page == HUP_GENERIC_DESKTOP &&
                           (usage == HUG_JOYSTICK || usage == HUG_GAME_PAD));
    
            if (h.kind != hid_input)
                continue;
    
            if (!is_joystick)
                continue;
    
            if (page == HUP_GENERIC_DESKTOP) {
                if (usage == HUG_HAT_SWITCH) {
                    if ((bsddata->hats < MAXAXES) && (joystick->num_axes <= MAXAXES-2)) {
                        got_something = 1;
                        memcpy(&bsddata->hat_item[bsddata->hats], &h, sizeof(h));
                        bsddata->hats++;
                        joystick->num_axes += 2;
                    }
                } else {
                    if (joystick->num_axes < MAXAXES) {
                        got_something = 1;
                        memcpy(&bsddata->axis_item[cur_axis], &h, sizeof(h));
                        cur_axis++;
                        joystick->num_axes++;
                    }
                }
            } else if (page == HUP_BUTTON) {
                if (joystick->num_buttons < MAXBUTTONS) {
                    got_something = 1;
                    memcpy(&bsddata->button_item[joystick->num_buttons], &h, sizeof(h));
                    joystick->num_buttons++;
                }
    	}
        }
        hid_end_parse(d);
    
        if (!got_something) {
            free(bsddata->data_buf);
            xf86Msg(X_ERROR, "Joystick: Didn't find any usable axes.\n");
            free(bsddata);
            close(joystick->fd);
            joystick->fd = -1;
            return -1;
        }
    
        bsddata->hotdata = 0;
        joystick->devicedata = (void*) bsddata;
        if (probe == TRUE) {
            xf86Msg(X_INFO, "Joystick: %d buttons, %d axes\n", 
                    joystick->num_buttons, joystick->num_axes);
        }
    
        joystick->open_proc = jstkOpenDevice_bsd;
        joystick->read_proc = jstkReadData_bsd;
        joystick->close_proc = jstkCloseDevice_bsd;
    
        return joystick->fd;
    }
    
    
    /***********************************************************************
     *
     * jstkCloseDevice --
     *
     * close the handle.
     *
     ***********************************************************************
     */
    
    static void
    jstkCloseDevice_bsd(JoystickDevPtr joystick)
    {
        if ((joystick->fd >= 0)) {
          xf86CloseSerial(joystick->fd);
          joystick->fd = -1;
        }
        if (joystick->devicedata != NULL) {
            if (((struct jstk_bsd_hid_data*)joystick->devicedata)->data_buf)
                free(((struct jstk_bsd_hid_data*)joystick->devicedata)->data_buf);
            free(joystick->devicedata);
        }
    }
    
    
    /***********************************************************************
     *
     * jstkReadData --
     *
     * Reads data from fd and stores it in the JoystickDevRec struct
     * fills in the type of event and the number of the button/axis
     * return 1 if success, 0 otherwise. Success does not neccessarily
     * mean that there is a new event waiting.
     *
     ***********************************************************************
     */
    
    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;
    }