Hi,

attached is a patch to use uevent to get kernel notifications for 'usb-cable-changed' in QtExtended on recent kernels (>=2.6.28). On 'older' kernels (<2.6.28), this information was comming in trough /dev/input/event4 but this is no longer working (there is a ticket for this at https://docs.openmoko.org/trac/ticket/2254 ). With this patch my FR switches correctly from battery power savings scheme to online pwoer scheme, and usb networking goes up/down as expected.
Same mechanism could be used to re-implement an event based neobattery.

This patch should not break 2.6.24 compatibility.

Cheers,

Filip.
>From 367a7ec014442b47be615ccbde8dc7441bfb466c Mon Sep 17 00:00:00 2001
From: Filip Onkelinx <fi...@dev.linux4.be>
Date: Tue, 31 Mar 2009 22:28:22 +0200
Subject: [PATCH] using uevent to get kernel notifications for usb cable changed

Signed-off-by: Filip Onkelinx <fi...@dev.linux4.be>
---
 devices/neo/server/neohardware.cpp                |   79 ++
 devices/neo/server/neohardware.h                  |    6 +-
 2 files changed, 85 insertions(+), 1 deletions(-)

diff --git a/devices/neo/server/neohardware.cpp 
b/devices/neo/server/neohardware.cpp
index e259094..fca61bc 100644
--- a/devices/neo/server/neohardware.cpp
+++ b/devices/neo/server/neohardware.cpp
@@ -44,6 +44,16 @@
 #include <linux/input.h>
 
 #include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <linux/types.h>
+#include <linux/netlink.h>
+#include <QTcpSocket>
+#include <QtDebug>
 
 QTOPIA_TASK(NeoHardware, NeoHardware);
 
@@ -52,10 +62,31 @@ NeoHardware::NeoHardware()
       vsoUsbCable("/Hardware/UsbGadget"),
       vsoNeoHardware("/Hardware/Neo")
 {
+    struct sockaddr_nl snl;
     adaptor = new QtopiaIpcAdaptor("QPE/NeoHardware");
 
     qLog(Hardware) << "neohardware";
 
+    memset(&snl, 0x00, sizeof(struct sockaddr_nl));
+    snl.nl_family = AF_NETLINK;
+    snl.nl_pid = getpid();
+    snl.nl_groups = 1;
+    snl.nl_groups = 0x1;
+
+    int hotplug_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+    if (hotplug_sock == -1) {
+        qLog(Hardware) << "error getting uevent socket: "<< strerror(errno);
+    }else{ 
+      if ( bind(hotplug_sock, (struct sockaddr *) &snl, sizeof(struct 
sockaddr_nl)) < 0) {
+        qLog(Hardware) << "uevent bind failed: "<< strerror(errno);
+        hotplug_sock = -1;
+      }else{
+           ueventSocket = new QTcpSocket(this);
+           ueventSocket->setSocketDescriptor(hotplug_sock);
+           connect(ueventSocket, SIGNAL(readyRead()), this, SLOT(uevent()));
+      }
+    }
+
     cableConnected(getCableStatus());
 
     vsoPortableHandsfree.setAttribute("Present", false);
@@ -77,6 +108,54 @@ NeoHardware::~NeoHardware()
 {
 }
 
+char *NeoHardware::findAttribute(char *buf, int len, const char *token)
+{
+int pos=0;
+
+  while (pos<len)
+  {
+    if(strncmp(&buf[pos],token,strlen(token))==0)
+       return(&buf[pos+strlen(token)]);
+    pos=pos+strlen(&buf[pos])+1;
+  }
+  return(buf);
+}
+
+void NeoHardware::uevent()
+{
+#define UEVENT_BUFFER_SIZE 1024
+char buffer[UEVENT_BUFFER_SIZE];
+char *value;
+
+  int bytesAvail = ueventSocket->bytesAvailable();
+  int readCount = UEVENT_BUFFER_SIZE;
+  if (bytesAvail < readCount)
+      readCount = bytesAvail;
+  ueventSocket->read(&buffer[0],readCount);
+  if(strcmp(buffer,"change@/class/power_supply/usb")==0)
+  {
+    value=findAttribute(buffer,readCount,"POWER_SUPPLY_ONLINE=");
+    qDebug()<<"usb change event; online='"<<value<<"'";
+    cableConnected(atoi(value));
+  }else if(strcmp(buffer,"change@/class/power_supply/ac")==0)
+  {
+    value=findAttribute(buffer,readCount,"POWER_SUPPLY_ONLINE=");
+    qDebug()<<"ac change event; online="<<value;
+  }else if(strcmp(buffer,"change@/class/power_supply/adapter")==0)
+  {
+    value=findAttribute(buffer,readCount,"POWER_SUPPLY_ONLINE=");
+    qDebug()<<"power_supply change event; online="<<value;
+  }else if(strcmp(buffer,"change@/class/power_supply/battery")==0)
+  {
+    value=findAttribute(buffer,readCount,"POWER_SUPPLY_CAPACITY=");
+    qDebug()<<"battery change event charge%="<<value<<"%";
+  }else if(strcmp(buffer,"change@/class/switch/headset")==0)
+  {
+    value=findAttribute(buffer,readCount,"SWITCH_STATE=");
+    qDebug()<<"headset change event, switch_state="<<value;
+ }
+}
+
 void NeoHardware::findHardwareVersion()
 {
     QFile cpuinfo( "/proc/cpuinfo");
diff --git a/devices/neo/server/neohardware.h b/devices/neo/server/neohardware.h
index f52b232..0d70f72 100644
--- a/devices/neo/server/neohardware.h
+++ b/devices/neo/server/neohardware.h
@@ -24,6 +24,7 @@
 
 #include <QObject>
 #include <QProcess>
+#include <QTcpSocket>
 
 #include <qvaluespace.h>
 #include <linux/input.h>
@@ -48,15 +49,18 @@ private:
      QValueSpaceObject vsoUsbCable;
      QValueSpaceObject vsoNeoHardware;
      QtopiaIpcAdaptor *adaptor;
+     QTcpSocket *ueventSocket;
 
      void findHardwareVersion();
      QtopiaIpcAdaptor *audioMgr;
-      
+     char *findAttribute(char *buf, int len, const char *token);
+ 
 private slots:
      void headphonesInserted(bool);
      void cableConnected(bool);
      void shutdownRequested();
      bool getCableStatus();
+     void uevent();
 
 };
 
-- 
1.4.4.4
_______________________________________________
Openmoko community mailing list
community@lists.openmoko.org
http://lists.openmoko.org/mailman/listinfo/community

Reply via email to