Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

synled38.patch

By: a guest on Mar 19th, 2011  |  syntax: Diff  |  size: 6.20 KB  |  views: 557  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. From: Takashi Iwai <tiwai@suse.de>
  2. Subject: [PATCH 2/2] input: Add LED support to Synaptics device
  3. Patch-mainline: Submitted
  4. References: bnc#547370,bnc#582529,bnc#589014
  5.  
  6. The new Synaptics devices have an LED on the top-left corner.
  7. This patch adds a new LED class device to control it.  It's created
  8. dynamically upon synaptics device probing.
  9.  
  10. The LED is controlled via the command 0x0a with parameters 0x88 or 0x10.
  11. This seems only on/off control although other value might be accepted.
  12.  
  13. The detection of the LED isn't clear yet.  It should have been the new
  14. capability bits that indicate the presence, but on real machines, it
  15. doesn't fit.  So, for the time being, the driver checks the product id
  16. in the ext capability bits and assumes that LED exists on the known
  17. devices.
  18.  
  19. Signed-off-by: Takashi Iwai <tiwai@suse.de>
  20.  
  21. ---
  22. drivers/input/mouse/Kconfig     |    9 +++
  23.  drivers/input/mouse/synaptics.c |  111 ++++++++++++++++++++++++++++++++++++++++
  24.  drivers/input/mouse/synaptics.h |    3 +
  25.  3 files changed, 123 insertions(+)
  26.  
  27. --- a/drivers/input/mouse/Kconfig
  28. +++ b/drivers/input/mouse/Kconfig
  29. @@ -19,6 +19,7 @@
  30.         select SERIO_LIBPS2
  31.         select SERIO_I8042 if X86
  32.         select SERIO_GSCPS2 if GSC
  33. +       select LEDS_CLASS if MOUSE_PS2_SYNAPICS_LED
  34.         help
  35.           Say Y here if you have a PS/2 mouse connected to your system. This
  36.           includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
  37. @@ -68,6 +69,14 @@
  38.  
  39.           If unsure, say Y.
  40.  
  41. +config MOUSE_PS2_SYNAPTICS_LED
  42. +       bool "Support embedded LED on Synaptics devices"
  43. +       depends on MOUSE_PS2_SYNAPTICS
  44. +       select NEW_LEDS
  45. +       help
  46. +         Say Y here if you have a Synaptics device with an embedded LED.
  47. +         This will enable LED class driver to control the LED device.
  48. +
  49.  config MOUSE_PS2_LIFEBOOK
  50.         bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT
  51.         default y
  52. --- a/drivers/input/mouse/synaptics.c
  53. +++ b/drivers/input/mouse/synaptics.c
  54. @@ -28,6 +28,7 @@
  55.  #include <linux/input/mt.h>
  56.  #include <linux/serio.h>
  57.  #include <linux/libps2.h>
  58. +#include <linux/leds.h>
  59.  #include <linux/slab.h>
  60.  #include "psmouse.h"
  61.  #include "synaptics.h"
  62. @@ -395,6 +396,110 @@
  63.         serio_register_port(serio);
  64.  }
  65.  
  66. +#ifdef CONFIG_MOUSE_PS2_SYNAPTICS_LED
  67. +/*
  68. + * LED handling:
  69. + * Some Synaptics devices have an embeded LED at the top-left corner.
  70. + */
  71. +
  72. +struct synaptics_led {
  73. +       struct psmouse *psmouse;
  74. +       struct work_struct work;
  75. +       struct led_classdev cdev;
  76. +};
  77. +
  78. +static void synaptics_set_led(struct psmouse *psmouse, int on)
  79. +{
  80. +       int i;
  81. +       unsigned char cmd = on ? 0x88 : 0x10;
  82. +
  83. +       ps2_begin_command(&psmouse->ps2dev);
  84. +       if (__ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11))
  85. +               goto out;
  86. +       for (i = 6; i >= 0; i -= 2) {
  87. +               unsigned char d = (cmd >> i) & 3;
  88. +               if (__ps2_command(&psmouse->ps2dev, &d, PSMOUSE_CMD_SETRES))
  89. +                       goto out;
  90. +       }
  91. +       cmd = 0x0a;
  92. +       __ps2_command(&psmouse->ps2dev, &cmd, PSMOUSE_CMD_SETRATE);
  93. + out:
  94. +       ps2_end_command(&psmouse->ps2dev);
  95. +}
  96. +
  97. +static void synaptics_led_work(struct work_struct *work)
  98. +{
  99. +       struct synaptics_led *led;
  100. +
  101. +       led = container_of(work, struct synaptics_led, work);
  102. +       synaptics_set_led(led->psmouse, led->cdev.brightness);
  103. +}
  104. +
  105. +static void synaptics_led_cdev_brightness_set(struct led_classdev *cdev,
  106. +                                             enum led_brightness value)
  107. +{
  108. +       struct synaptics_led *led;
  109. +
  110. +       led = container_of(cdev, struct synaptics_led, cdev);
  111. +       schedule_work(&led->work);
  112. +}
  113. +
  114. +static void synaptics_sync_led(struct psmouse *psmouse)
  115. +{
  116. +       struct synaptics_data *priv = psmouse->private;
  117. +
  118. +       if (priv->led)
  119. +               synaptics_set_led(psmouse, priv->led->cdev.brightness);
  120. +}
  121. +
  122. +static int synaptics_init_led(struct psmouse *psmouse)
  123. +{
  124. +       struct synaptics_data *priv = psmouse->private;
  125. +       struct synaptics_led *led;
  126. +       int err;
  127. +
  128. +       /* FIXME: LED is supposedly detectable in cap0c[1] 0x20, but it seems
  129. +        * not working on real machines.
  130. +        * So we check the product id to be sure.
  131. +        */
  132. +       if (!priv->ext_cap_0c || SYN_CAP_PRODUCT_ID(priv->ext_cap) != 0xe4)
  133. +               return 0;
  134. +
  135. +       printk(KERN_INFO "synaptics: support LED control\n");
  136. +       led = kzalloc(sizeof(struct synaptics_led), GFP_KERNEL);
  137. +       if (!led)
  138. +               return -ENOMEM;
  139. +       led->psmouse = psmouse;
  140. +       INIT_WORK(&led->work, synaptics_led_work);
  141. +       led->cdev.name = "psmouse::synaptics";
  142. +       led->cdev.brightness_set = synaptics_led_cdev_brightness_set;
  143. +       led->cdev.flags = LED_CORE_SUSPENDRESUME;
  144. +       err = led_classdev_register(NULL, &led->cdev);
  145. +       if (err < 0) {
  146. +               kfree(led);
  147. +               return err;
  148. +       }
  149. +       priv->led = led;
  150. +       return 0;
  151. +}
  152. +
  153. +static void synaptics_free_led(struct psmouse *psmouse)
  154. +{
  155. +       struct synaptics_data *priv = psmouse->private;
  156. +
  157. +       if (!priv->led)
  158. +               return;
  159. +       cancel_work_sync(&priv->led->work);
  160. +       synaptics_set_led(psmouse, 0);
  161. +       led_classdev_unregister(&priv->led->cdev);
  162. +       kfree(priv->led);
  163. +}
  164. +#else
  165. +#define synaptics_init_led(ps) 0
  166. +#define synaptics_free_led(ps) do {} while (0)
  167. +#define synaptics_sync_led(ps) do {} while (0)
  168. +#endif
  169. +
  170.  /*****************************************************************************
  171.   *     Functions to interpret the absolute mode packets
  172.   ****************************************************************************/
  173. @@ -746,6 +851,7 @@
  174.  
  175.  static void synaptics_disconnect(struct psmouse *psmouse)
  176.  {
  177. +       synaptics_free_led(psmouse);
  178.         synaptics_reset(psmouse);
  179.         kfree(psmouse->private);
  180.         psmouse->private = NULL;
  181. @@ -798,6 +904,8 @@
  182.                 return -1;
  183.         }
  184.  
  185. +       synaptics_sync_led(psmouse);
  186. +
  187.         return 0;
  188.  }
  189.  
  190. @@ -907,6 +1015,9 @@
  191.                 SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
  192.                 priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c);
  193.  
  194. +       if (synaptics_init_led(psmouse) < 0)
  195. +               goto init_fail;
  196. +
  197.         set_input_params(psmouse->dev, priv);
  198.  
  199.         /*
  200. --- a/drivers/input/mouse/synaptics.h
  201. +++ b/drivers/input/mouse/synaptics.h
  202. @@ -122,6 +122,8 @@
  203.         signed char scroll;
  204.  };
  205.  
  206. +struct synaptics_led;
  207. +
  208.  struct synaptics_data {
  209.         /* Data read from the touchpad */
  210.         unsigned long int model_id;             /* Model-ID */
  211. @@ -135,6 +137,7 @@
  212.         unsigned char pkt_type;                 /* packet type - old, new, etc */
  213.         unsigned char mode;                     /* current mode byte */
  214.         int scroll;
  215. +       struct synaptics_led *led;
  216.  
  217.         struct serio *pt_port;                  /* Pass-through serio port */