Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

linux_class_input.c

00001 /***************************************************************************
00002  * CVSID: $Id: linux_class_input.c,v 1.7 2004/03/03 17:56:56 david Exp $
00003  *
00004  * hal_input.c : Input device functions for sysfs-agent on Linux 2.6
00005  *
00006  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
00007  *
00008  * Licensed under the Academic Free License version 2.0
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  **************************************************************************/
00025 
00026 #ifdef HAVE_CONFIG_H
00027 #  include <config.h>
00028 #endif
00029 
00030 #include <ctype.h>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <getopt.h>
00035 #include <assert.h>
00036 #include <unistd.h>
00037 #include <stdarg.h>
00038 #include <limits.h>
00039 
00040 #include <linux/input.h>    /* for EV_* etc. */
00041 
00042 #include "../logger.h"
00043 #include "../device_store.h"
00044 #include "linux_class_input.h"
00045 
00057 typedef struct input_proc_info_s {
00058     int bus;
00059     int vendor;
00060     int product;
00061     int version;
00062 
00063     dbus_uint32_t evbit;
00064     dbus_uint32_t ledbit;
00065     dbus_uint32_t relbit;
00066     dbus_uint32_t absbit;
00067 
00068     char name[128];
00069     char phys_name[128];
00070     char handlers[128];
00071     char keybit[128];
00072 
00073     struct input_proc_info_s *next;
00075 } input_proc_info;
00076 
00081 static input_proc_info *
00082 get_input_proc_cur_info_obj ()
00083 {
00084     input_proc_info *i;
00085 
00086     i = malloc (sizeof (input_proc_info));
00087     if (i == NULL)
00088         DIE (("Cannot allocated memory"));
00089 
00090     (i->name)[0] = '\0';
00091     (i->phys_name)[0] = '\0';
00092     (i->handlers)[0] = '\0';
00093     (i->keybit)[0] = '\0';
00094     i->evbit = 0;
00095     i->ledbit = 0;
00096     i->relbit = 0;
00097     i->absbit = 0;
00098     i->bus = 0;
00099     i->vendor = 0;
00100     i->product = 0;
00101     i->version = 0;
00102 
00103     return i;
00104 }
00105 
00106 
00108 static input_proc_info *input_proc_head = NULL;
00109 
00111 static input_proc_info *input_proc_cur_info = NULL;
00112 
00113 
00120 static void
00121 input_proc_handle_interface (input_proc_info * info, char *s)
00122 {
00123     info->bus = find_num ("Bus=", s, 16);
00124     info->vendor = find_num ("Vendor=", s, 16);
00125     info->product = find_num ("Product=", s, 16);
00126     info->version = find_num ("Version=", s, 16);
00127 }
00128 
00135 static void
00136 input_proc_handle_name (input_proc_info * info, char *s)
00137 {
00138     char *str;
00139     /* grr, the kernel puts quotes in the name */
00140     str = find_string ("Name=\"", s);
00141 
00142     if (str != NULL) {
00143         strncpy (info->name, str, 128);
00144         /* remove the trailing quote */
00145         (info->name)[strlen (info->name) - 1] = '\0';
00146     } else
00147         (info->name)[0] = '\0';
00148 
00149 
00150 }
00151 
00158 static void
00159 input_proc_handle_phys (input_proc_info * info, char *s)
00160 {
00161     char *str;
00162     str = find_string ("Phys=", s);
00163     if (str != NULL)
00164         strncpy (info->phys_name, str, 128);
00165     else
00166         (info->phys_name)[0] = '\0';
00167 }
00168 
00175 static void
00176 input_proc_handle_handlers (input_proc_info * info, char *s)
00177 {
00178     char *str;
00179     str = find_string ("Handlers=", s);
00180     if (str != NULL)
00181         strncpy (info->handlers, str, 128);
00182     else
00183         (info->handlers)[0] = '\0';
00184 }
00185 
00192 static void
00193 input_proc_handle_bits (input_proc_info * info, char *s)
00194 {
00195     int num;
00196 
00197     if ((num = find_num ("EV=", s, 16)) != LONG_MAX) {
00198         info->evbit = num;
00199         return;
00200     }
00201 
00202     if ((num = find_num ("LED=", s, 16)) != LONG_MAX) {
00203         info->ledbit = num;
00204         return;
00205     }
00206 
00207     if ((num = find_num ("REL=", s, 16)) != LONG_MAX) {
00208         info->relbit = num;
00209         return;
00210     }
00211 
00212     if ((num = find_num ("ABS=", s, 16)) != LONG_MAX) {
00213         info->absbit = num;
00214         return;
00215     }
00216 
00217     if (strncmp ("B: KEY=", s, 7) == 0) {
00218         strncpy (info->keybit, s + 7, 128);
00219         /* remove trailing newline */
00220         info->keybit[strlen (info->keybit) - 1] = '\0';
00221     }
00222 }
00223 
00224 
00225 
00230 static void
00231 input_proc_device_done (input_proc_info * info)
00232 {
00233     info->next = input_proc_head;
00234     input_proc_head = info;
00235 }
00236 
00237 
00242 static void
00243 input_proc_parse_line (char *s)
00244 {
00245     /* See drivers/input/input.c, function input_devices_read() in 
00246      * the Linux kernel for details.
00247      */
00248 
00249     switch (s[0]) {
00250     case 'I':       /* interface; always present, indicates a new device */
00251         if (input_proc_cur_info != NULL) {
00252             /* beginning of a new device, done with current */
00253             input_proc_device_done (input_proc_cur_info);
00254         }
00255 
00256         input_proc_cur_info = get_input_proc_cur_info_obj ();
00257 
00258         input_proc_handle_interface (input_proc_cur_info, s);
00259         break;
00260 
00261     case 'N':       /* Name */
00262         input_proc_handle_name (input_proc_cur_info, s);
00263         break;
00264 
00265     case 'P':       /* Phyiscal information */
00266         input_proc_handle_phys (input_proc_cur_info, s);
00267         break;
00268 
00269     case 'H':       /* Handlers */
00270         input_proc_handle_handlers (input_proc_cur_info, s);
00271         break;
00272 
00273     case 'B':       /* Bits */
00274         input_proc_handle_bits (input_proc_cur_info, s);
00275         break;
00276 
00277 
00278     default:
00279         break;
00280     }
00281 }
00282 
00285 static void
00286 input_proc_parse ()
00287 {
00288     FILE *f;
00289     char buf[256];
00290 
00291     f = fopen ("/proc/bus/input/devices", "r");
00292     if (f == NULL) {
00293         DIE (("Couldn't open /proc/bus/input/devices"));
00294     }
00295 
00296     while (!feof (f)) {
00297         fgets (buf, 256, f);
00298         input_proc_parse_line (buf);
00299     }
00300     input_proc_device_done (input_proc_cur_info);
00301 
00302     {
00303         input_proc_info *i;
00304         for (i = input_proc_head; i != NULL; i = i->next) {
00305 /*
00306             printf("/p/b/i/d entry\n");
00307             printf("  bus               %d\n", i->bus);
00308             printf("  vendor            %d\n", i->vendor);
00309             printf("  product           %d\n", i->product);
00310             printf("  version           %d\n", i->version);
00311             printf("  evbit             0x%08x\n", i->evbit);
00312             printf("  name              '%s'\n", i->name);
00313             printf("  phys_name         '%s'\n", i->phys_name);
00314             printf("  handlers          '%s'\n", i->handlers);
00315             printf("\n");
00316 */
00317         }
00318     }
00319 }
00320 
00321 
00322     /*
00323 
00324        This is an example input event
00325 
00326        ----------------------------------------
00327        Sat Nov 29 14:32:55 CET 2003
00328        ----------------------------------------
00329        input
00330        ----------------------------------------
00331        EV=7
00332        NAME=Logitech USB-PS/2 Optical Mouse
00333        PATH=/sbin:/bin:/usr/sbin:/usr/bin
00334        ACTION=add
00335        PWD=/
00336        KEY=f0000 0 0 0 0 0 0 0 0
00337        REL=103
00338        HOME=/
00339        SHLVL=2
00340        PHYS=usb-0000:00:07.2-1.1.2/input0
00341        PRODUCT=3/46d/c012/1320
00342        _=/bin/env
00343        ----------------------------------------
00344        ----------------------------------------
00345 
00346        This is /proc/bus/input/devices                                                                                
00347        I: Bus=0011 Vendor=0002 Product=0001 Version=0000
00348        N: Name="PS/2 Generic Mouse"
00349        P: Phys=isa0060/serio1/input0
00350        H: Handlers=mouse0
00351        B: EV=7
00352        B: KEY=70000 0 0 0 0 0 0 0 0
00353        B: REL=3
00354 
00355        I: Bus=0011 Vendor=0001 Product=0002 Version=ab02
00356        N: Name="AT Translated Set 2 keyboard"
00357        P: Phys=isa0060/serio0/input0
00358        H: Handlers=kbd
00359        B: EV=120003
00360        B: KEY=4 2200000 c061f9 fbc9d621 efdfffdf ffefffff ffffffff fffffffe
00361        B: LED=7
00362 
00363        I: Bus=0003 Vendor=04b3 Product=3005 Version=0100
00364        N: Name="Silitek IBM USB HUB KEYBOARD"
00365        P: Phys=usb-0000:00:07.2-1.2.1/input0
00366        H: Handlers=kbd
00367        B: EV=120003
00368        B: KEY=10000 7f ffe7207a c14057ff ffbeffdf ffffffff ffffffff fffffffe
00369        B: LED=1f
00370 
00371        I: Bus=0003 Vendor=046d Product=c012 Version=1320
00372        N: Name="Logitech USB-PS/2 Optical Mouse"
00373        P: Phys=usb-0000:00:07.2-1.2.2/input0
00374        H: Handlers=mouse1
00375        B: EV=7
00376        B: KEY=f0000 0 0 0 0 0 0 0 0
00377        B: REL=103
00378 
00379      */
00380 
00381 
00382 /* fwd decl */
00383 static void input_got_sysdevice (HalDevice * device,
00384                  void *data1, void *data2);
00385 
00390 static void
00391 process_input_proc_info (input_proc_info * i)
00392 {
00393     int n;
00394     HalDevice *d;
00395     char phys[128];
00396 
00397     /* First extract physical name */
00398     for (n = 0; n < 128; n++) {
00399         if (i->phys_name[n] == '/')
00400             break;
00401         phys[n] = i->phys_name[n];
00402     }
00403     phys[n] = '\0';
00404 
00405 /*
00406   if( sscanf(i->phys_name+n+1, "input%d", &in_num)!=1 )
00407   {
00408       printf("Error parsing %s\n", i->phys_name+n+1);
00409       continue;
00410   }
00411 */
00412 
00413     d = ds_device_new ();
00414 
00415     ds_property_set_string (d, "input.linux.phys", i->phys_name);
00416     ds_property_set_string (d, "input.linux.handlers", i->handlers);
00417     ds_property_set_int (d, "input.linux.evbit", i->evbit);
00418     ds_property_set_int (d, "input.linux.ledbit", i->ledbit);
00419     ds_property_set_int (d, "input.linux.relbit", i->relbit);
00420     ds_property_set_int (d, "input.linux.absbit", i->absbit);
00421     ds_property_set_string (d, "input.linux.keybit", i->keybit);
00422 
00423     /* The "USB HID for Linux USB" document provides good information
00424      * http://www.frogmouth.net/hid-doco/linux-hid.html
00425      *
00426      */
00427     ds_property_set_bool (d, "input.key", i->evbit & (1 << EV_KEY));
00428     ds_property_set_bool (d, "input.relative",
00429                   i->evbit & (1 << EV_REL));
00430     ds_property_set_bool (d, "input.absolute",
00431                   i->evbit & (1 << EV_ABS));
00432     ds_property_set_bool (d, "input.led", i->evbit & (1 << EV_LED));
00433     ds_property_set_bool (d, "input.sound", i->evbit & (1 << EV_SND));
00434     ds_property_set_bool (d, "input.repeat", i->evbit & (1 << EV_REP));
00435     ds_property_set_bool (d, "input.force_feedback",
00436                   i->evbit & (1 << EV_FF));
00437     ds_property_set_bool (d, "input.misc", i->evbit & (1 << EV_MSC));
00438 #ifdef EV_RST
00439     ds_property_set_bool (d, "input.rst", i->evbit & (1 << EV_RST));
00440 #elif EV_SYN
00441     ds_property_set_bool (d, "input.rst", i->evbit & (1 << EV_SYN));
00442 #endif
00443 
00444     if (i->evbit & (1 << EV_LED)) {
00445         ds_property_set_bool (d, "input.led.numlock",
00446                       i->ledbit & (1 << LED_NUML));
00447         ds_property_set_bool (d, "input.led.capslock",
00448                       i->ledbit & (1 << LED_CAPSL));
00449         ds_property_set_bool (d, "input.led.scrolllock",
00450                       i->ledbit & (1 << LED_SCROLLL));
00451         ds_property_set_bool (d, "input.led.compose",
00452                       i->ledbit & (1 << LED_COMPOSE));
00453         ds_property_set_bool (d, "input.led.kana",
00454                       i->ledbit & (1 << LED_KANA));
00455         ds_property_set_bool (d, "input.led.sleep",
00456                       i->ledbit & (1 << LED_SLEEP));
00457         ds_property_set_bool (d, "input.led.suspend",
00458                       i->ledbit & (1 << LED_SUSPEND));
00459         ds_property_set_bool (d, "input.led.mute",
00460                       i->ledbit & (1 << LED_MUTE));
00461         ds_property_set_bool (d, "input.led.misc",
00462                       i->ledbit & (1 << LED_MISC));
00463         ds_property_set_bool (d, "input.led.max",
00464                       i->ledbit & (1 << LED_MAX));
00465     }
00466 
00467     if (i->evbit & (1 << EV_REL)) {
00468         ds_property_set_bool (d, "input.relative.x",
00469                       i->relbit & (1 << REL_X));
00470         ds_property_set_bool (d, "input.relative.y",
00471                       i->relbit & (1 << REL_Y));
00472         ds_property_set_bool (d, "input.relative.z",
00473                       i->relbit & (1 << REL_Z));
00474         ds_property_set_bool (d, "input.relative.hwheel",
00475                       i->relbit & (1 << REL_HWHEEL));
00476         ds_property_set_bool (d, "input.relative.dial",
00477                       i->relbit & (1 << REL_DIAL));
00478         ds_property_set_bool (d, "input.relative.wheel",
00479                       i->relbit & (1 << REL_WHEEL));
00480         ds_property_set_bool (d, "input.relative.misc",
00481                       i->relbit & (1 << REL_MISC));
00482     }
00483 
00484     if (i->evbit & (1 << EV_ABS)) {
00485         ds_property_set_bool (d, "input.absolute.x",
00486                       i->absbit & (1 << ABS_X));
00487         ds_property_set_bool (d, "input.absolute.y",
00488                       i->absbit & (1 << ABS_Y));
00489         ds_property_set_bool (d, "input.absolute.z",
00490                       i->absbit & (1 << ABS_Z));
00491         ds_property_set_bool (d, "input.absolute.rx",
00492                       i->absbit & (1 << ABS_RX));
00493         ds_property_set_bool (d, "input.absolute.ry",
00494                       i->absbit & (1 << ABS_RY));
00495         ds_property_set_bool (d, "input.absolute.rz",
00496                       i->absbit & (1 << ABS_RZ));
00497         ds_property_set_bool (d, "input.absolute.throttle",
00498                       i->absbit & (1 << ABS_THROTTLE));
00499         ds_property_set_bool (d, "input.absolute.rudder",
00500                       i->absbit & (1 << ABS_RUDDER));
00501         ds_property_set_bool (d, "input.absolute.wheel",
00502                       i->absbit & (1 << ABS_WHEEL));
00503         ds_property_set_bool (d, "input.absolute.gas",
00504                       i->absbit & (1 << ABS_GAS));
00505         ds_property_set_bool (d, "input.absolute.brake",
00506                       i->absbit & (1 << ABS_BRAKE));
00507         ds_property_set_bool (d, "input.absolute.hat0x",
00508                       i->absbit & (1 << ABS_HAT0X));
00509         ds_property_set_bool (d, "input.absolute.hat0y",
00510                       i->absbit & (1 << ABS_HAT0Y));
00511         ds_property_set_bool (d, "input.absolute.hat1x",
00512                       i->absbit & (1 << ABS_HAT1X));
00513         ds_property_set_bool (d, "input.absolute.hat1y",
00514                       i->absbit & (1 << ABS_HAT1Y));
00515         ds_property_set_bool (d, "input.absolute.hat2x",
00516                       i->absbit & (1 << ABS_HAT2X));
00517         ds_property_set_bool (d, "input.absolute.hat2y",
00518                       i->absbit & (1 << ABS_HAT2Y));
00519         ds_property_set_bool (d, "input.absolute.pressure",
00520                       i->absbit & (1 << ABS_PRESSURE));
00521         ds_property_set_bool (d, "input.absolute.distance",
00522                       i->absbit & (1 << ABS_DISTANCE));
00523         ds_property_set_bool (d, "input.absolute.tilt_x",
00524                       i->absbit & (1 << ABS_TILT_X));
00525         ds_property_set_bool (d, "input.absolute.tilt_Y",
00526                       i->absbit & (1 << ABS_TILT_Y));
00527         ds_property_set_bool (d, "input.absolute.misc",
00528                       i->absbit & (1 << ABS_MISC));
00529     }
00530 
00531     /* Either way, we're an input device */
00532     ds_add_capability (d, "input");
00533 
00538     if (i->relbit != 0) {
00539         ds_add_capability (d, "input.mouse");
00540         ds_property_set_string (d, "info.category", "input.mouse");
00541     } else {
00542         ds_add_capability (d, "input.keyboard");
00543         ds_property_set_string (d, "info.category",
00544                     "input.keyboard");
00545     }
00546 
00552     /* Find phys device; this happens asynchronously as it might
00553      * be added later. If we are probing this can't happen so the
00554      * timeout is set to zero in that event..
00555      */
00556     ds_device_async_find_by_key_value_string ("linux.kernel_devname", phys, FALSE,  /* note: doesn't need to be in GDL */
00557                           input_got_sysdevice,
00558                           (void *) d, NULL,
00559                           is_probing ? 0 :
00560                           HAL_LINUX_HOTPLUG_TIMEOUT);
00561 }
00562 
00570 static void
00571 input_got_sysdevice (HalDevice * sysdevice, void *data1, void *data2)
00572 {
00573     HalDevice *d = (HalDevice *) data1;
00574 
00575     if (sysdevice == NULL) {
00576         HAL_WARNING (("Sysdevice for a class input device never appeared!"));
00577     } else {
00578         /* merge information from temporary device into the physical
00579          * device 
00580          */
00581         ds_device_merge (sysdevice, d);
00582     }
00583 
00584     /* get rid of tempoary device; it was only a placeholder after all */
00585     ds_device_destroy (d);
00586 }
00587 
00588 
00593 void
00594 linux_class_input_probe ()
00595 {
00596     input_proc_info *i;
00597 
00598     input_proc_parse ();
00599 
00600     for (i = input_proc_head; i != NULL; i = i->next)
00601         process_input_proc_info (i);
00602 }
00603 
00604 
00615 void
00616 linux_class_input_handle_hotplug_add (char *name, char *phys, char *key,
00617                       int ev, int rel, int abs, int led)
00618 {
00619     char *s;
00620     input_proc_info *i;
00621 
00622     i = get_input_proc_cur_info_obj ();
00623 
00626     strncpy (i->name, name, 128);
00627     strncpy (i->phys_name, phys, 128);
00628     strncpy (i->keybit, key, 128);
00629     i->evbit = ev;
00630     i->relbit = rel;
00631     i->absbit = abs;
00632     i->ledbit = led;
00633 
00634     process_input_proc_info (i);
00635 }
00636 
00640 void
00641 linux_class_input_init ()
00642 {
00643 }
00644 
00649 void
00650 linux_class_input_detection_done ()
00651 {
00652 }
00653 
00657 void
00658 linux_class_input_shutdown ()
00659 {
00660 }
00661 

Generated on Thu Mar 11 21:32:22 2004 for HAL by doxygen 1.3.6-20040222