Difference between revisions of "Hidd"

From WebOS Internals
Jump to navigation Jump to search
Line 297: Line 297:
  
 
You'll see its socket get registered and then some printf's when getcallback and init get called.
 
You'll see its socket get registered and then some printf's when getcallback and init get called.
Next steps will be to call init and suspend and resume from libhid's generic functions, and then to actually communicate with hidd. :)
+
Next steps will be to fix to figure out gPluginPrvInfo since we probably need to put more things in it, and then to actually communicate with hidd. :)

Revision as of 21:46, 25 November 2010

Intro

This is a research page on hidd -- how to examine what it does, how it works, etc.

Files

Hidd is started from upstart (/etc/event.d/hidd) with a -f option to load a given configuration file. On the emulator, this is /etc/hidd/HidPluginsVbox.xml. On a pre, this is /etc/hidd/HidPlugins.xml. There's also something called casper there, not sure what that is as of yet

Architecture

Hidd seems to use a modular plugin-style architecture where each plugin is a shared library.

Default files are:

libhid.so libhidavrcp.so libhidlight.so libhidqemukeypad.so libhidtouchpanel.so libhidaccelerometer.so libhidkeypad.so libhidproximity.so libhidqemutouchpanel.so

Plugin definition in config file

<source lang=xml>

   <plugin>
       <name>HidKeypad</name>
       <eventsDeferIdle>true</eventsDeferIdle>
       <eventSocketAddress>/var/tmp/hidd/KeypadEventSocket</eventSocketAddress>
       <cmdSocketAddress>/var/tmp/hidd/KeypadCmdSocket</cmdSocketAddress>
       <path>/usr/lib/libhidkeypad.so</path>
   </plugin>

</source>

Starting the daemon

A lot of debug information can be obtained by starting the daemon like so (on a pre, on an emulator add Vbox before .xml)

/usr/bin/hidd -vvv -f /etc/hidd/HidPlugins.xml

Example trace

/usr/bin/hidd -vvv -f /etc/hidd/HidPlugins-keypadonly.xml

Verbosity level set to 7


root@castle:/etc/hidd# hidd -vvvv -f /etc/hidd/HidPlugins-test.xml Verbosity level set to 7 Plugin: 0

 Name: HidKeypad
 Path: /usr/lib/libhidkeypad.so
 Event Socket Address: /var/tmp/hidd/KeypadEventSocket
 Cmd Socket Address: /var/tmp/hidd/KeypadCmdSocket

_SetupPluginTransport:

 Socket created successfully

_SetupPluginTransport:

 --> Event socket address: /var/tmp/hidd/KeypadEventSocket

_SetupPluginTransport:

 --> Command socket address: /var/tmp/hidd/KeypadCmdSocket

Init:

 HidKeypad: init function called!

HidKeypadIpc.c:104 : GetSwitchStates: Bad file descriptor ReportEvent:

 kInputEvent received 1 events, fd: 7

_ReportStandardEvent:

 Event: 0.0, type=EV_SYN, code=8, value=0

HidPluginStartReaderThread:

 HidKeypad: starting reader thread

main:

 Setting up power management...

ReportEvent:

 kInputEvent received 2 events, fd: 7

_ReportStandardEvent:

 Event: 85906.791100, type=EV_KEY, code=19, value=1

_ReportStandardEvent:

 Event: 85906.791130, type=EV_SYN, code=0, value=0

ReportEvent:

 kInputEvent received 2 events, fd: 7

_ReportStandardEvent:

 Event: 85906.999809, type=EV_KEY, code=19, value=0

_ReportStandardEvent:

 Event: 85906.999840, type=EV_SYN, code=0, value=0


Listening to Hidd event

The libSDL patch provided by Palm provides good examples of listening to events via hidd. Based upon this I created a simple example program to listen to the HidKeypad events and print them to stdout. Listening directly to HidKeypad events we can observe all the keys including power button, volume keys and center gesture-area button. I built using WIDK. WARNING: After running this program, I cannot get the screen to come back on after sleeping via a key press. It only turns back on after reconnecting USB cable

hidTest.c

#include <stdio.h>
#include <linux/input.h>
#include "HidLib.h"
//#include "hid/IncsPublic/HidLib.h"

#define XML_FILE     "/etc/hidd/HidPlugins.xml"

static HidPluginSettings_t* pSettings = NULL;
static int numPlugins = 0;

int HidEventInit(void)
{
    PmErr retVal = kPmErrorUnknown;
    
    if (pSettings == NULL) {
        retVal = HidAllocPluginSettings(XML_FILE, &pSettings, &numPlugins);

        if (kPmErrorNone != retVal)
        {
            pSettings = NULL;
            return -1;
        }
    }

    return 0;
}

void HidEventDeInit(void)
{
    if (NULL != pSettings)
    {
        HidFreePluginSettings(&pSettings, numPlugins);
        pSettings = NULL;
    }
}

void *HidEventOpen(int Device)
{
    PmErr retVal = kPmErrorUnknown;
    HidHandle_t* pHandle = NULL;    
    
    if (pSettings == NULL) {
        // Ensure plugin settings are initialized.
        if (HidEventInit() != 0) {
            return NULL;
        }
    }

    static const char* PluginName[] = { 
            HID_KEYPAD,
            HID_ACCELEROMETER,
            HID_TOUCHPANEL
    };

    retVal = HidInitPluginTransport(PluginName[Device], pSettings, numPlugins, &pHandle);

    if (kPmErrorNone != retVal)
    {
        HidFreePluginSettings(&pSettings, numPlugins);
        pSettings = NULL;
        return NULL;
    }

    return pHandle;
}  

void HidEventClose(void *Handle)
{
    if (NULL != Handle)
    {
        HidDestroyPluginTransport((HidHandle_t**)&Handle);
    } 
}

int HidEventGetFd(void *Handle)
{
    return HidHandleGetFd((HidHandle_t*)Handle);
}

int HidEventRead(void *Handle, struct input_event* Events, int MaxEvents)
{
    return HidHandleReadInputEvent((HidHandle_t*)Handle, (InputEvent_t*)Events, MaxEvents);
}

int main() {
  void *pHandle;
  struct input_event myevent;
  int ret = 0;

  pHandle = HidEventOpen(0);

  while (1) {
    ret = HidEventRead(pHandle, &myevent, 1);

    printf("return %d, type %d, code %d, value %d\n", 
        ret, myevent.type, myevent.code, myevent.value);

    // q for quit
    if (myevent.code == 16) {
      HidEventDeInit();
      HidEventClose(pHandle);
      break;
    }
  }

  return 0;
}

HidLib.h

typedef int HidPluginSettings_t;
typedef int HidHandle_t;
typedef int PmErr;
typedef struct input_event InputEvent_t;

#define kPmErrorNone 0
#define kPmErrorUnknown -1
#define HID_KEYPAD "HidKeypad"
#define HID_ACCELEROMETER "HidAccelerometer"
#define HID_TOUCHPANEL "HidTouchpanel"

Makefile

CC      = arm-none-linux-gnueabi-gcc
CFLAGS  = -g -O2 -I/usr/local/include
LIBS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lhid
DEMOS = hidTest

$(DEMOS):
	$(CC) -o $@ $@.c $(CFLAGS) $(LIBS)

clean:
	rm -f $(DEMOS)



Silly hidd plugin

#include <stdio.h>

typedef struct PluginTable_t { 
    int (*GetEventCallBack)() ;
    int (*Init)() ;
    int (*Exit)() ;
    int (*Suspend)() ;
    int (*Resume)() ;
    int (*Poll)() ;
} PluginTable_t; 

extern PluginTable_t PluginTable;

void *gPluginPrvInfo[21];

int GetEventCallBack(void *a1) {
    printf( "Silly GetEventCallBack()\n" ) ;
    gPluginPrvInfo[0] = a1;
    return 0;
}

int Init(a1) {
    printf( "Silly Init\n" ) ;
    return HidPluginGenericInit(a1, gPluginPrvInfo);
}

int Exit() {
    printf( "Silly Exit\n" ) ;
    return HidPluginGenericExit(gPluginPrvInfo);
}

int Suspend() {
    printf( "Silly Suspend\n" ) ;
    return HidPluginGenericSuspend(gPluginPrvInfo);
}

int Resume() {
    printf( "Silly Resume\n" ) ;
    return HidPluginGenericResume(gPluginPrvInfo);
}

int Poll() {
    printf( "Silly Poll\n" ) ;
    return HidPluginGenericGetEvents(gPluginPrvInfo);
}

PluginTable_t PluginTable = { 
    *GetEventCallBack,
    *Init,
    *Exit,
    *Suspend,
    *Resume,
    *Poll
} ;

You'll see its socket get registered and then some printf's when getcallback and init get called. Next steps will be to fix to figure out gPluginPrvInfo since we probably need to put more things in it, and then to actually communicate with hidd. :)