OpenGrok

Cross Reference: hal-hotplug.patch
xref: /fox/fox-7-4-merge/XW_NV/open-src/driver/xf86-input-keyboard/hal-hotplug.patch
Home | History | Annotate | Line # | Download | only in xf86-input-keyboard
      1 From 2bc18590e6b7b403dcec22a09820010748c48972 Mon Sep 17 00:00:00 2001
      2 From: Alan Coopersmith <alan.coopersmith (a] sun.com>
      3 Date: Thu, 30 Apr 2009 16:26:23 -0700
      4 Subject: [PATCH] Solaris keyboard fixes for HAL hotplugging support
      5 
      6 - Handle hot-unplug by checking for ENODEV on read and removing device
      7 - Make sure to re-push streams module on resume
      8 
      9 Signed-off-by: Alan Coopersmith <alan.coopersmith (a] sun.com>
     10 ---
     11  src/sun_kbd.c |  114 ++++++++++++++++++++++++++++++++++++++++++++++++---------
     12  src/sun_kbd.h |    1 +
     13  2 files changed, 97 insertions(+), 18 deletions(-)
     14 
     15 diff --git a/src/sun_kbd.c b/src/sun_kbd.c
     16 index a222d38..b4ebc57 100644
     17 --- a/src/sun_kbd.c
     18 +++ b/src/sun_kbd.c
     19 @@ -22,7 +22,7 @@
     20   * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     21   * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     22   */
     23 -/* Copyright 2004-2007 Sun Microsystems, Inc.  All rights reserved.
     24 +/* Copyright 2004-2009 Sun Microsystems, Inc.  All rights reserved.
     25   *
     26   * Permission is hereby granted, free of charge, to any person obtaining a
     27   * copy of this software and associated documentation files (the
     28 @@ -64,6 +64,8 @@
     29  #include <sys/vuid_event.h>
     30  #include <sys/kbd.h>
     31  
     32 +static int KbdOn(InputInfoPtr pInfo, int what);
     33 +
     34  static void
     35  sunKbdSetLeds(InputInfoPtr pInfo, int leds)
     36  {
     37 @@ -105,6 +107,7 @@ KbdInit(InputInfoPtr pInfo, int what)
     38      int	ktype, klayout, i;
     39      const char *ktype_name;
     40  
     41 +    priv->kbdActive	= FALSE;
     42      priv->otranslation 	= -1;
     43      priv->odirect 	= -1;
     44  
     45 @@ -114,15 +117,11 @@ KbdInit(InputInfoPtr pInfo, int what)
     46  	priv->strmod 		= NULL;
     47      }
     48  
     49 -    if (priv->strmod) {
     50 -	SYSCALL(i = ioctl(pInfo->fd, I_PUSH, priv->strmod));
     51 -	if (i < 0) {
     52 -	    xf86Msg(X_ERROR,
     53 -		    "%s: cannot push module '%s' onto keyboard device: %s\n",
     54 -		    pInfo->name, priv->strmod, strerror(errno));
     55 -	}
     56 +    i = KbdOn(pInfo, DEVICE_INIT);
     57 +    if (i != Success) {
     58 +	return i;
     59      }
     60 -    
     61 +
     62      SYSCALL(i = ioctl(pInfo->fd, KIOCTYPE, &ktype));
     63      if (i < 0) {
     64  	xf86Msg(X_ERROR, "%s: Unable to determine keyboard type: %s\n", 
     65 @@ -155,7 +154,6 @@ KbdInit(InputInfoPtr pInfo, int what)
     66      xf86Msg(X_PROBED, "%s: Keyboard layout: %d\n", pInfo->name, klayout);
     67  
     68      priv->ktype 	= ktype;
     69 -    priv->oleds 	= sunKbdGetLeds(pInfo);
     70  
     71      return Success;
     72  }
     73 @@ -169,6 +167,19 @@ KbdOn(InputInfoPtr pInfo, int what)
     74  
     75      int	ktrans, kdirect, i;
     76  
     77 +    if (priv->kbdActive) {
     78 +	return Success;
     79 +    }
     80 +
     81 +    if (priv->strmod) {
     82 +	SYSCALL(i = ioctl(pInfo->fd, I_PUSH, priv->strmod));
     83 +	if (i < 0) {
     84 +	    xf86Msg(X_ERROR,
     85 +		    "%s: cannot push module '%s' onto keyboard device: %s\n",
     86 +		    pInfo->name, priv->strmod, strerror(errno));
     87 +	}
     88 +    }
     89 +
     90      SYSCALL(i = ioctl(pInfo->fd, KIOCGDIRECT, &kdirect));
     91      if (i < 0) {
     92  	xf86Msg(X_ERROR, 
     93 @@ -207,6 +218,13 @@ KbdOn(InputInfoPtr pInfo, int what)
     94  	return BadImplementation;
     95      }
     96  
     97 +    priv->oleds	= sunKbdGetLeds(pInfo);
     98 +
     99 +    /* Allocate here so we don't alloc in ReadInput which may be called
    100 +       from SIGIO handler. */
    101 +    priv->remove_timer = TimerSet(priv->remove_timer, 0, 0, NULL, NULL);
    102 +
    103 +    priv->kbdActive = TRUE;
    104      return Success;
    105  }
    106  
    107 @@ -218,6 +236,20 @@ KbdOff(InputInfoPtr pInfo, int what)
    108  
    109      int i;
    110  
    111 +    if (!priv->kbdActive) {
    112 +	return Success;
    113 +    }
    114 +
    115 +    if (pInfo->fd == -1) {
    116 +	priv->kbdActive = FALSE;
    117 +	return Success;
    118 +    }
    119 +
    120 +    if (priv->remove_timer) {
    121 +	TimerFree(priv->remove_timer);
    122 +	priv->remove_timer = NULL;
    123 +    }
    124 +
    125      /* restore original state */
    126  
    127      if (priv->oleds != -1) {
    128 @@ -254,9 +286,9 @@ KbdOff(InputInfoPtr pInfo, int what)
    129  		    "%s: cannot pop module '%s' off keyboard device: %s\n",
    130  		    pInfo->name, priv->strmod, strerror(errno));
    131  	}
    132 -	priv->strmod = NULL;
    133      }
    134  
    135 +    priv->kbdActive = FALSE;
    136      return Success;
    137  }
    138  
    139 @@ -353,20 +385,66 @@ SetKbdRepeat(InputInfoPtr pInfo, char rad)
    140      /* Nothing to do */
    141  }
    142  
    143 +/* Called from OsTimer callback, since removing a device from the device
    144 +   list or changing pInfo->fd while xf86Wakeup is looping through the list
    145 +   causes server crashes */
    146 +static CARD32
    147 +RemoveKeyboard(OsTimerPtr timer, CARD32 time, pointer arg)
    148 +{
    149 +    InputInfoPtr pInfo = (InputInfoPtr) arg;
    150 +    KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
    151 +    sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private;
    152 +
    153 +    close(pInfo->fd);
    154 +    pInfo->fd = -1;
    155 +    priv->kbdActive = FALSE;
    156 +
    157 +    xf86DisableDevice(pInfo->dev, TRUE);
    158 +
    159 +    return 0;  /* All done, don't set to run again */
    160 +}
    161 +
    162  static void
    163  ReadInput(InputInfoPtr pInfo)
    164  {
    165      KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
    166 +    sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private;
    167      Firm_event event[64];
    168      int        nBytes, i;
    169  
    170 -    /* I certainly hope its not possible to read partial events */
    171 -
    172 -    if ((nBytes = read(pInfo->fd, (char *)event, sizeof(event))) > 0)
    173 -    {
    174 -        for (i = 0; i < (nBytes / sizeof(Firm_event)); i++) {
    175 -	    pKbd->PostEvent(pInfo, event[i].id & 0xFF,
    176 -			    event[i].value == VKEY_DOWN ? TRUE : FALSE);
    177 +    while (TRUE) {
    178 +	/* I certainly hope it's not possible to read partial events */
    179 +	nBytes = read(pInfo->fd, (char *)event, sizeof(event));
    180 +	if (nBytes > 0) {
    181 +	    for (i = 0; i < (nBytes / sizeof(Firm_event)); i++) {
    182 +		pKbd->PostEvent(pInfo, event[i].id & 0xFF,
    183 +				event[i].value == VKEY_DOWN ? TRUE : FALSE);
    184 +	    }
    185 +	} else if (nBytes == -1) {
    186 +	    switch (errno) {
    187 +		case EAGAIN: /* Nothing to read now */
    188 +		    return;
    189 +		case EINTR:  /* Interrupted, try again */
    190 +		    break;
    191 +		case ENODEV: /* May happen when USB kbd is unplugged */
    192 +		    /* We use X_NONE here because it doesn't alloc since we
    193 +		       may be called from SIGIO handler */
    194 +		    xf86MsgVerb(X_NONE, 0,
    195 +				"%s: Device no longer present - removing.\n",
    196 +				pInfo->name);
    197 +		    xf86RemoveEnabledDevice(pInfo);
    198 +		    priv->remove_timer = TimerSet(priv->remove_timer, 0, 1,
    199 +						  RemoveKeyboard, pInfo);
    200 +		    return;
    201 +		default:     /* All other errors */
    202 +		    /* We use X_NONE here because it doesn't alloc since we
    203 +		       may be called from SIGIO handler */
    204 +		    xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name,
    205 +				strerror(errno));
    206 +		    return;
    207 +	    }
    208 +	} else { /* nBytes == 0, so nothing more to read */
    209 +	    return;
    210  	}
    211      }
    212  }
    213 diff --git a/src/sun_kbd.h b/src/sun_kbd.h
    214 index a73e201..080cbb5 100644
    215 --- a/src/sun_kbd.h
    216 +++ b/src/sun_kbd.h
    217 @@ -36,6 +36,7 @@ typedef struct {
    218      int 		odirect;	/* Original "direct" mode setting */
    219      int			oleds;		/* Original LED state */
    220      const char *	strmod;		/* Streams module pushed on kbd device */
    221 +    OsTimerPtr		remove_timer;	/* Callback for removal on ENODEV */
    222  } sunKbdPrivRec, *sunKbdPrivPtr;
    223  
    224  /* sun_kbdMap.c */
    225 -- 
    226 1.5.6.5
    227 
    228