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.6 2004/01/02 12:11:24 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 {
00059     int bus;
00060     int vendor;
00061     int product;
00062     int version;
00063 
00064     dbus_uint32_t evbit;
00065     dbus_uint32_t ledbit;
00066     dbus_uint32_t relbit;
00067     dbus_uint32_t absbit;
00068 
00069     char name[128];
00070     char phys_name[128];
00071     char handlers[128];
00072     char keybit[128];
00073 
00074     struct input_proc_info_s* next; 
00075 } input_proc_info;
00076 
00081 static input_proc_info* get_input_proc_cur_info_obj()
00082 {
00083     input_proc_info* i;
00084 
00085     i = malloc(sizeof(input_proc_info));
00086     if( i==NULL )
00087         DIE(("Cannot allocated memory"));
00088 
00089     (i->name)[0] = '\0';
00090     (i->phys_name)[0] = '\0';
00091     (i->handlers)[0] = '\0';
00092     (i->keybit)[0] = '\0';
00093     i->evbit = 0;
00094     i->ledbit = 0;
00095     i->relbit = 0;
00096     i->absbit = 0;
00097     i->bus = 0;
00098     i->vendor = 0;
00099     i->product = 0;
00100     i->version = 0;
00101 
00102     return i;
00103 }
00104 
00105 
00107 static input_proc_info* input_proc_head = NULL;
00108 
00110 static input_proc_info* input_proc_cur_info = NULL;
00111 
00112 
00119 static void input_proc_handle_interface(input_proc_info* info, char* s)
00120 {
00121     info->bus = find_num("Bus=", s, 16);
00122     info->vendor = find_num("Vendor=", s, 16);
00123     info->product = find_num("Product=", s, 16);
00124     info->version = find_num("Version=", s, 16);
00125 }
00126 
00133 static void input_proc_handle_name(input_proc_info* info, char* s)
00134 {
00135     char* str;
00136     /* grr, the kernel puts quotes in the name */
00137     str = find_string("Name=\"", s);
00138 
00139     if( str!=NULL )
00140     {
00141         strncpy(info->name, str, 128);
00142         /* remove the trailing quote */
00143         (info->name)[strlen(info->name)-1] = '\0';
00144     }
00145     else
00146         (info->name)[0]='\0';
00147 
00148     
00149 }
00150 
00157 static void input_proc_handle_phys(input_proc_info* info, char* s)
00158 {
00159     char* str;
00160     str = find_string("Phys=", s);
00161     if( str!=NULL )
00162         strncpy(info->phys_name, str, 128);
00163     else
00164         (info->phys_name)[0]='\0';
00165 }
00166 
00173 static void input_proc_handle_handlers(input_proc_info* info, char* s)
00174 {
00175     char* str;
00176     str = find_string("Handlers=", s);
00177     if( str!=NULL )
00178         strncpy(info->handlers, str, 128);
00179     else
00180         (info->handlers)[0]='\0';
00181 }
00182 
00189 static void input_proc_handle_bits(input_proc_info* info, char* s)
00190 {
00191     int num;
00192 
00193     if( (num=find_num("EV=", s, 16))!=LONG_MAX )
00194     {
00195         info->evbit = num;
00196         return;
00197     }
00198 
00199     if( (num=find_num("LED=", s, 16))!=LONG_MAX )
00200     {
00201         info->ledbit = num;
00202         return;
00203     }
00204 
00205     if( (num=find_num("REL=", s, 16))!=LONG_MAX )
00206     {
00207         info->relbit = num;
00208         return;
00209     }
00210 
00211     if( (num=find_num("ABS=", s, 16))!=LONG_MAX )
00212     {
00213         info->absbit = num;
00214         return;
00215     }
00216 
00217     if( strncmp("B: KEY=", s, 7)==0 )
00218     {
00219         strncpy(info->keybit, s+7, 128);
00220         /* remove trailing newline */
00221         info->keybit[strlen(info->keybit)-1] = '\0';
00222     }
00223 }
00224 
00225 
00226 
00231 static void 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 input_proc_parse_line(char* s)
00243 {
00244     /* See drivers/input/input.c, function input_devices_read() in 
00245      * the Linux kernel for details.
00246      */
00247 
00248     switch( s[0] )
00249     {
00250     case 'I': /* interface; always present, indicates a new device */
00251         if( input_proc_cur_info!=NULL )
00252         {
00253             // beginning of a new device, done with current
00254             input_proc_device_done(input_proc_cur_info);
00255         }
00256 
00257         input_proc_cur_info = get_input_proc_cur_info_obj();
00258 
00259         input_proc_handle_interface(input_proc_cur_info, s);
00260         break;
00261 
00262     case 'N': /* Name */
00263         input_proc_handle_name(input_proc_cur_info, s);
00264         break;
00265 
00266     case 'P': /* Phyiscal information */
00267         input_proc_handle_phys(input_proc_cur_info, s);
00268         break;
00269 
00270     case 'H': /* Handlers */
00271         input_proc_handle_handlers(input_proc_cur_info, s);
00272         break;
00273 
00274     case 'B': /* Bits */
00275         input_proc_handle_bits(input_proc_cur_info, s);
00276         break;
00277 
00278 
00279     default:
00280         break;
00281     }
00282 }
00283 
00286 static void 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     {
00294         DIE(("Couldn't open /proc/bus/input/devices"));
00295     }
00296 
00297     while( !feof(f) )
00298     {
00299         fgets(buf, 256, f);
00300         input_proc_parse_line(buf);
00301     }
00302     input_proc_device_done(input_proc_cur_info);
00303 
00304     {
00305         input_proc_info* i;
00306         for(i=input_proc_head; i!=NULL; i=i->next)
00307         {
00308 /*
00309             printf("/p/b/i/d entry\n");
00310             printf("  bus               %d\n", i->bus);
00311             printf("  vendor            %d\n", i->vendor);
00312             printf("  product           %d\n", i->product);
00313             printf("  version           %d\n", i->version);
00314             printf("  evbit             0x%08x\n", i->evbit);
00315             printf("  name              '%s'\n", i->name);
00316             printf("  phys_name         '%s'\n", i->phys_name);
00317             printf("  handlers          '%s'\n", i->handlers);
00318             printf("\n");
00319 */
00320         }
00321     }
00322 }
00323 
00324 
00325     /*
00326 
00327 This is an example input event
00328 
00329 ----------------------------------------
00330 Sat Nov 29 14:32:55 CET 2003
00331 ----------------------------------------
00332 input
00333 ----------------------------------------
00334 EV=7
00335 NAME=Logitech USB-PS/2 Optical Mouse
00336 PATH=/sbin:/bin:/usr/sbin:/usr/bin
00337 ACTION=add
00338 PWD=/
00339 KEY=f0000 0 0 0 0 0 0 0 0
00340 REL=103
00341 HOME=/
00342 SHLVL=2
00343 PHYS=usb-0000:00:07.2-1.1.2/input0
00344 PRODUCT=3/46d/c012/1320
00345 _=/bin/env
00346 ----------------------------------------
00347 ----------------------------------------
00348 
00349 This is /proc/bus/input/devices                                                                                
00350 I: Bus=0011 Vendor=0002 Product=0001 Version=0000
00351 N: Name="PS/2 Generic Mouse"
00352 P: Phys=isa0060/serio1/input0
00353 H: Handlers=mouse0
00354 B: EV=7
00355 B: KEY=70000 0 0 0 0 0 0 0 0
00356 B: REL=3
00357  
00358 I: Bus=0011 Vendor=0001 Product=0002 Version=ab02
00359 N: Name="AT Translated Set 2 keyboard"
00360 P: Phys=isa0060/serio0/input0
00361 H: Handlers=kbd
00362 B: EV=120003
00363 B: KEY=4 2200000 c061f9 fbc9d621 efdfffdf ffefffff ffffffff fffffffe
00364 B: LED=7
00365  
00366 I: Bus=0003 Vendor=04b3 Product=3005 Version=0100
00367 N: Name="Silitek IBM USB HUB KEYBOARD"
00368 P: Phys=usb-0000:00:07.2-1.2.1/input0
00369 H: Handlers=kbd
00370 B: EV=120003
00371 B: KEY=10000 7f ffe7207a c14057ff ffbeffdf ffffffff ffffffff fffffffe
00372 B: LED=1f
00373  
00374 I: Bus=0003 Vendor=046d Product=c012 Version=1320
00375 N: Name="Logitech USB-PS/2 Optical Mouse"
00376 P: Phys=usb-0000:00:07.2-1.2.2/input0
00377 H: Handlers=mouse1
00378 B: EV=7
00379 B: KEY=f0000 0 0 0 0 0 0 0 0
00380 B: REL=103
00381 
00382      */
00383 
00384 
00385 /* fwd decl */
00386 static void input_got_sysdevice(HalDevice* device, 
00387                                 void* data1, void* data2);
00388 
00393 static void process_input_proc_info(input_proc_info* i)
00394 {
00395     int n;
00396     HalDevice* d;
00397     char phys[128];
00398 
00399     /* First extract physical name */
00400     for(n=0; n<128; n++)
00401     {
00402         if( i->phys_name[n]=='/' )
00403             break;
00404         phys[n] = i->phys_name[n];
00405     }
00406     phys[n] = '\0';
00407     
00408 /*
00409   if( sscanf(i->phys_name+n+1, "input%d", &in_num)!=1 )
00410   {
00411       printf("Error parsing %s\n", i->phys_name+n+1);
00412       continue;
00413   }
00414 */
00415 
00416     d = ds_device_new();
00417     
00418     ds_property_set_string(d, "input.linux.phys", 
00419                                    i->phys_name);
00420     ds_property_set_string(d, "input.linux.handlers", 
00421                                    i->handlers);
00422     ds_property_set_int(d, "input.linux.evbit", 
00423                                 i->evbit);
00424     ds_property_set_int(d, "input.linux.ledbit", 
00425                                 i->ledbit);
00426     ds_property_set_int(d, "input.linux.relbit", 
00427                                 i->relbit);
00428     ds_property_set_int(d, "input.linux.absbit", 
00429                                 i->absbit);
00430     ds_property_set_string(d, "input.linux.keybit", 
00431                                    i->keybit);
00432         
00433     /* The "USB HID for Linux USB" document provides good information
00434      * http://www.frogmouth.net/hid-doco/linux-hid.html
00435      *
00436      */
00437     ds_property_set_bool(d, "input.key", 
00438                                  i->evbit&(1<<EV_KEY));
00439     ds_property_set_bool(d, "input.relative", 
00440                                  i->evbit&(1<<EV_REL));
00441     ds_property_set_bool(d, "input.absolute", 
00442                                  i->evbit&(1<<EV_ABS));
00443     ds_property_set_bool(d, "input.led", 
00444                                  i->evbit&(1<<EV_LED));
00445     ds_property_set_bool(d, "input.sound", 
00446                                  i->evbit&(1<<EV_SND));
00447     ds_property_set_bool(d, "input.repeat", 
00448                                  i->evbit&(1<<EV_REP));
00449     ds_property_set_bool(d, "input.force_feedback", 
00450                                  i->evbit&(1<<EV_FF));
00451     ds_property_set_bool(d, "input.misc", 
00452                                  i->evbit&(1<<EV_MSC));
00453 #ifdef EV_RST
00454     ds_property_set_bool(d, "input.rst", 
00455                                  i->evbit&(1<<EV_RST));
00456 #elif EV_SYN
00457     ds_property_set_bool(d, "input.rst", 
00458                                  i->evbit&(1<<EV_SYN));
00459 #endif
00460     
00461     if( i->evbit&(1<<EV_LED) )
00462     {
00463         ds_property_set_bool(d, "input.led.numlock", 
00464                                      i->ledbit&(1<<LED_NUML));
00465         ds_property_set_bool(d, "input.led.capslock", 
00466                                      i->ledbit&(1<<LED_CAPSL));
00467         ds_property_set_bool(d, "input.led.scrolllock", 
00468                                      i->ledbit&(1<<LED_SCROLLL));
00469         ds_property_set_bool(d, "input.led.compose", 
00470                                      i->ledbit&(1<<LED_COMPOSE));
00471         ds_property_set_bool(d, "input.led.kana", 
00472                                      i->ledbit&(1<<LED_KANA));
00473         ds_property_set_bool(d, "input.led.sleep", 
00474                                      i->ledbit&(1<<LED_SLEEP));
00475         ds_property_set_bool(d, "input.led.suspend", 
00476                                      i->ledbit&(1<<LED_SUSPEND));
00477         ds_property_set_bool(d, "input.led.mute", 
00478                                      i->ledbit&(1<<LED_MUTE));
00479         ds_property_set_bool(d, "input.led.misc", 
00480                                      i->ledbit&(1<<LED_MISC));
00481         ds_property_set_bool(d, "input.led.max", 
00482                                      i->ledbit&(1<<LED_MAX));
00483     }
00484     
00485     if( i->evbit&(1<<EV_REL) )
00486     {
00487         ds_property_set_bool(d, "input.relative.x", 
00488                                      i->relbit&(1<<REL_X));
00489         ds_property_set_bool(d, "input.relative.y", 
00490                                      i->relbit&(1<<REL_Y));
00491         ds_property_set_bool(d, "input.relative.z", 
00492                                      i->relbit&(1<<REL_Z));
00493         ds_property_set_bool(d, "input.relative.hwheel", 
00494                                      i->relbit&(1<<REL_HWHEEL));
00495         ds_property_set_bool(d, "input.relative.dial", 
00496                                      i->relbit&(1<<REL_DIAL));
00497         ds_property_set_bool(d, "input.relative.wheel", 
00498                                      i->relbit&(1<<REL_WHEEL));
00499         ds_property_set_bool(d, "input.relative.misc", 
00500                                      i->relbit&(1<<REL_MISC));
00501     }
00502     
00503     if( i->evbit&(1<<EV_ABS) )
00504     {
00505         ds_property_set_bool(d, "input.absolute.x", 
00506                                      i->absbit&(1<<ABS_X));
00507         ds_property_set_bool(d, "input.absolute.y", 
00508                                      i->absbit&(1<<ABS_Y));
00509         ds_property_set_bool(d, "input.absolute.z", 
00510                                      i->absbit&(1<<ABS_Z));
00511         ds_property_set_bool(d, "input.absolute.rx", 
00512                                      i->absbit&(1<<ABS_RX));
00513         ds_property_set_bool(d, "input.absolute.ry", 
00514                                      i->absbit&(1<<ABS_RY));
00515         ds_property_set_bool(d, "input.absolute.rz", 
00516                                      i->absbit&(1<<ABS_RZ));
00517         ds_property_set_bool(d, "input.absolute.throttle", 
00518                                      i->absbit&(1<<ABS_THROTTLE));
00519         ds_property_set_bool(d, "input.absolute.rudder", 
00520                                      i->absbit&(1<<ABS_RUDDER));
00521         ds_property_set_bool(d, "input.absolute.wheel", 
00522                                      i->absbit&(1<<ABS_WHEEL));
00523         ds_property_set_bool(d, "input.absolute.gas", 
00524                                      i->absbit&(1<<ABS_GAS));
00525         ds_property_set_bool(d, "input.absolute.brake", 
00526                                      i->absbit&(1<<ABS_BRAKE));
00527         ds_property_set_bool(d, "input.absolute.hat0x", 
00528                                      i->absbit&(1<<ABS_HAT0X));
00529         ds_property_set_bool(d, "input.absolute.hat0y", 
00530                                      i->absbit&(1<<ABS_HAT0Y));
00531         ds_property_set_bool(d, "input.absolute.hat1x", 
00532                                      i->absbit&(1<<ABS_HAT1X));
00533         ds_property_set_bool(d, "input.absolute.hat1y", 
00534                                      i->absbit&(1<<ABS_HAT1Y));
00535         ds_property_set_bool(d, "input.absolute.hat2x", 
00536                                      i->absbit&(1<<ABS_HAT2X));
00537         ds_property_set_bool(d, "input.absolute.hat2y", 
00538                                      i->absbit&(1<<ABS_HAT2Y));
00539         ds_property_set_bool(d, "input.absolute.pressure", 
00540                                      i->absbit&(1<<ABS_PRESSURE));
00541         ds_property_set_bool(d, "input.absolute.distance", 
00542                                      i->absbit&(1<<ABS_DISTANCE));
00543         ds_property_set_bool(d, "input.absolute.tilt_x", 
00544                                      i->absbit&(1<<ABS_TILT_X));
00545         ds_property_set_bool(d, "input.absolute.tilt_Y", 
00546                                      i->absbit&(1<<ABS_TILT_Y));
00547         ds_property_set_bool(d, "input.absolute.misc", 
00548                                      i->absbit&(1<<ABS_MISC));
00549     }
00550 
00551     /* Either way, we're an input device */
00552     ds_add_capability(d, "input");
00553 
00558     if( i->relbit!=0 )
00559     {
00560         ds_add_capability(d, "input.mouse");
00561         ds_property_set_string(d, "info.category", "input.mouse");
00562     }
00563     else
00564     {
00565         ds_add_capability(d, "input.keyboard");
00566         ds_property_set_string(d, "info.category", "input.keyboard");
00567     }
00568     
00574     /* Find phys device; this happens asynchronously as it might
00575      * be added later. If we are probing this can't happen so the
00576      * timeout is set to zero in that event..
00577      */
00578     ds_device_async_find_by_key_value_string("linux.kernel_devname",
00579                                              phys, 
00580                                              FALSE, /* note: doesn't need to be in GDL */
00581                                              input_got_sysdevice,
00582                                              (void*) d, NULL, 
00583                                              is_probing ? 0 :
00584                                              HAL_LINUX_HOTPLUG_TIMEOUT);
00585 }
00586 
00594 static void input_got_sysdevice(HalDevice* sysdevice, 
00595                                 void* data1, void* data2)
00596 {
00597     HalDevice* d = (HalDevice*) data1;
00598 
00599     if( sysdevice==NULL )
00600     {
00601         HAL_WARNING(("Sysdevice for a class input device never appeared!"));
00602     }
00603     else
00604     {
00605         /* merge information from temporary device into the physical
00606          * device 
00607          */
00608         ds_device_merge(sysdevice, d);
00609     }
00610 
00611     /* get rid of tempoary device; it was only a placeholder after all */
00612     ds_device_destroy(d);
00613 }
00614 
00615 
00620 void linux_class_input_probe()
00621 {
00622     input_proc_info* i;
00623     
00624     input_proc_parse();    
00625 
00626     for(i=input_proc_head; i!=NULL; i=i->next)
00627         process_input_proc_info(i);
00628 }
00629 
00630 
00641 void linux_class_input_handle_hotplug_add(char* name, char* phys, char* key,
00642                                           int ev, int rel, int abs, int led)
00643 {
00644     char* s;
00645     input_proc_info* i;
00646 
00647     i = get_input_proc_cur_info_obj();
00648 
00651     strncpy(i->name, name, 128);
00652     strncpy(i->phys_name, phys, 128);
00653     strncpy(i->keybit, key, 128);
00654     i->evbit = ev;
00655     i->relbit = rel;
00656     i->absbit = abs;
00657     i->ledbit = led;
00658 
00659     process_input_proc_info(i);
00660 }
00661 
00665 void linux_class_input_init()
00666 {
00667 }
00668 
00673 void linux_class_input_detection_done()
00674 {
00675 }
00676 
00680 void linux_class_input_shutdown()
00681 {
00682 }
00683 

Generated on Sat Feb 7 22:11:47 2004 for HAL by doxygen 1.3.5