changeset 0:e70ea46d6073

Initial import from http://wouhanegaine.free.fr/dev/DSPad02b_neo07.zip
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Sun, 22 Feb 2015 01:38:06 +0100
parents
children 05c8e0aef77d
files COPYING DSPad_server.xml XML.c XML.h configure ds.c ds.h dspad.c makefile restartOp.c restartOp.h service.c service.h uinput.c uinput.h
diffstat 15 files changed, 1816 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          59 Temple Place - Suite 330, Boston, MA
+                          02111-1307, USA.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
new file mode 100755
--- /dev/null
+++ b/DSPad_server.xml
@@ -0,0 +1,5 @@
+<DSPad_server>
+    <base_port>16150</base_port>
+    <nb_pad>2</nb_pad>
+    <uinput_dev>/dev/misc/uinput</uinput_dev>
+</DSPad_server>
new file mode 100644
--- /dev/null
+++ b/XML.c
@@ -0,0 +1,110 @@
+/*      XML.c     */
+/*      ROUSSEL Cedric - TOINON Veran    */
+
+#include "XML.h"
+
+/*Lit un fichier et retourne son contenu dans une chaine de caractère*/
+char* LoadFile(char* location){
+    int n=0;
+    int i=0;
+    char* m;
+    FILE* f=fopen(location,"r");
+    if(f==NULL){
+        fprintf(stderr, "Could not open \"%s\"\n", location);
+        return NULL;
+    }
+    while (fgetc(f) != EOF) {n++;}
+    m=(char*)malloc(n*sizeof(char));
+    if (m==NULL) {return NULL;};
+    rewind(f);
+    for(i=0;i<(n-1);i++){
+        *(m+i)=(char)fgetc(f);
+    }
+    *(m+n-1)='\0';
+    fclose(f);
+    return m;
+}
+
+/*begin et end pointent dans une chaine de caracteres.
+MakeString retourne une nouvelle chaine */
+char* MakeString(char* begin, char* end){
+    char* r;
+    char* a;
+    int n=0;
+    a=begin;
+    while (a != end) {n++;a++;}
+    r=(char*)malloc((n+1)*sizeof(char));
+    if (r==NULL) {return NULL;}
+    strncpy(r,begin,n);
+    *(r+n)='\0';
+    return r;
+}
+
+
+/*Retourne le premier tag trouvé(sans les < >)
+Retourne NULL si aucun tag trouvé*/
+char* FindTag(char* text){
+    char* a;
+    char* b;
+    a=strchr(text,'<');
+    if (a==NULL) {return NULL;}
+    b=strchr(text,'>');
+    if (b==NULL) {return NULL;}
+    return MakeString(a+1,b);
+}
+
+/*Retourne le contenu du tag (sans < >)de la chaine pointée par mark.
+Repositione mark à la fin du tag de fermeture.
+Penser à supprimer avec free la chaine retournée.
+*/
+char* TagContent(char* tag,char** mark){
+    char* a;
+    char* b;
+    char* tagd;
+    char* tagf;
+    
+    tagd=(char*)malloc((strlen(tag)+3)*sizeof(char));
+    tagf=(char*)malloc((strlen(tag)+4)*sizeof(char));
+    if (tagd==NULL || tagf==NULL) {return NULL;}
+    
+    strcpy(tagd,"<");    strcat(tagd,tag);    strcat(tagd,">");
+    strcpy(tagf,"</");    strcat(tagf,tag);    strcat(tagf,">");
+
+    a=strstr(*mark,tagd)+strlen(tagd);
+    *mark=a;
+    b=strstr(*mark,tagf);
+    if (b == NULL){
+        free(tagd);
+        free(tagf);
+        return NULL;
+    }               //Si il n'y a pas de tag de fermeture
+    *mark=b+strlen(tagf);
+
+    free(tagd);
+    free(tagf);
+
+    return MakeString(a,b);
+}
+
+/* Lit la chaine XML pour initialiser l'élément pointé par pt grace à la
+fonction TreatTag */
+int ReadXML(void* pt,int(*TreatTag)(void*,char*,char*),char* mark){
+    int ok;
+    char* content;
+    char* tag;
+    tag=FindTag(mark);
+    while(tag!=NULL){
+        content = TagContent(tag,&mark);
+        if (content != NULL){
+            ok = TreatTag(pt,tag,content);
+            if(ok==0){
+                printf("Probleme dans le traitement de <%s>\n",tag);
+                return 0;
+            }
+            free(content);
+        }
+        free(tag);
+        tag=FindTag(mark);
+    }
+    return 1;
+}
new file mode 100644
--- /dev/null
+++ b/XML.h
@@ -0,0 +1,32 @@
+/*      XML.h     */
+/*      ROUSSEL Cedric - TOINON Veran    */
+
+#ifndef _XML
+#define _XML 1
+
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+
+extern char* LoadFile(char* location);
+
+/*begin et end pointent dans une chaine de caracteres.
+MakeString retourne une nouvelle chaine */
+extern char* MakeString(char* begin, char* end);
+
+
+/*Retourne le premier tag trouvé(sans les < >)
+Retourne NULL si aucun tag trouvé*/
+extern char* FindTag(char* text);
+
+/*Retourne le contenu du tag (sans < >)de la chaine pointée par mark.
+Repositione mark à la fin du tag de fermeture.
+Penser à supprimer avec free la chaine retournée.
+*/
+extern char* TagContent(char* tag,char** mark);
+
+/*Lit la chaine mark (XML) en initialisant la structure pointée par pt grace
+à la fonction TreatTag*/
+extern int ReadXML(void* pt,int(*TreatTag)(void*,char*,char*),char* mark);
+
+#endif /* _XML */
new file mode 100755
--- /dev/null
+++ b/configure
@@ -0,0 +1,311 @@
+#!/bin/sh
+
+#----------------- Fichiers et librairies -----------
+
+TARGET='dspad_server'
+
+#FILESdspad='dspad.c ds.c uinput.c service.c'
+FILESdspad_server=`ls *.c`
+LDFLAGSdspad_server=''
+
+#----------------- Options de compilation -----------
+
+INCDIR='.'
+CCFLAGS='-I$(INCDIR) -D_REENTRANT -g'
+
+#------- Options de compilation  propres au systeme -----------
+
+systeme=`uname`
+
+if test $systeme = "IRIX"
+then
+
+#---- SGI - IRIX ----
+
+CCFLAGS='-fullwarn '$CCFLAGS
+
+LDFLAGS='-Wl,-woff,15,-woff,84,-woff,85'
+
+DEPOPT='-M'
+
+CCC='cc'
+ 
+elif test $systeme = "Linux"
+then
+
+#---- Linux ----
+
+CCFLAGS='-W -Wall -Werror '$CCFLAGS
+#CCFLAGS=$CCFLAGS' -pedantic'
+
+LDFLAGS=''
+
+DEPOPT='-MM'
+
+CCC='cc'
+
+else echo "System $systeme inconnu"
+     exit 1
+fi
+ 
+#----------------- L'option -e de echo existe ?  ----------------
+
+recho=`echo -e`
+
+if test "$recho" = "-e"
+then echoOptionForTab=''    # echo "\t" permet d'afficher tab
+else echoOptionForTab='-e'  # echo -e "\t" permet d'afficher tab
+fi
+
+#----------------- Nom du fichier genere ------------------------
+
+makefile=makefile
+
+#----------------- Extension des fichiers -----------------------
+
+extension=".c"
+
+#----------------- Au moins une cible existe ? ------------------
+
+if test -z "$TARGET"
+then echo
+     echo "Attention, aucune cible (TARGET) n'est indiquee !"
+     exit 1;
+fi
+
+#----------------- INCDIR (ou trouver les .h) ? -----------------
+if test -z "$INCDIR"
+then echo
+     echo "Attention, INCDIR non indique, par defaut : INCDIR='.'"
+     INCDIR='.'
+fi
+
+#-------- Il ne faut pas de cible avec extension .c  -----------
+
+error=0
+for i in $TARGET
+do
+     if test $i != `basename $i $extension`
+     then echo "Attention, la cible $i est un fichier source !!"
+          error=1
+     fi
+done
+if test $error -ne 0
+then exit 1
+fi
+
+#--- Pour chaque cible,
+#--- il faut verifier si la variable FILEScible est vide ---
+#---                            ET
+#--- il faut verifier la variable FILEScible n'est composee que de .c ---
+printFilesList()
+{
+ #nbEspaces=`expr index $1 =`
+     strLocal=`expr $1 : '\(.*\)='`
+     nbEspaces=`expr length $strLocal`
+     nbEspaces=`expr $nbEspaces + 1`
+
+ strLocalEspaces=" "
+ iLocal=0
+
+ while test $iLocal -ne $nbEspaces
+ do
+    strLocalEspaces=$strLocalEspaces" "
+    iLocal=`expr $iLocal + 1`
+ done
+
+ echo $1
+ shift
+ while test $# -ne 0
+ do
+   echo "$strLocalEspaces"$1           # Il faut mettre les "" !!
+   shift
+ done
+}                 # Fin de printFilesList()
+
+for i in $TARGET
+do
+     echo "--------------- FILES$i ---------------"
+
+     findFileList="echo \$`echo FILES$i`"
+     fileList=`eval $findFileList`
+
+     if test -z "$fileList"
+     then echo "Attention, FILES$i est vide => FILES$i=$i$extension"
+          com="FILES$i=$i$extension"
+          eval $com
+     fi
+
+     findFileList="echo \$`echo FILES$i`"
+     fileList=`eval $findFileList`
+
+     realFileList=""
+     for j in $fileList
+     do
+        if test $j = `basename $j $extension`
+        then echo "Attention, dans FILES$i, $j est ignore (!= $extension)... "
+        else 
+             if test -z "$realFileList"
+             then realFileList=$j
+             else realFileList=$realFileList" "$j
+             fi
+        fi
+     done
+     if test -z "$realFileList"
+     then 
+          echo "... Donc , FILES$i est vide => FILES$i=$i$extension"
+          realFileList="$i$extension"
+     fi
+
+     echo
+     com="FILES$i=\"$realFileList\""
+     printFilesList $com                # Avant : echo $com
+     echo
+     echo "---------------------------------------"
+     eval $com
+done
+
+#-------- Pour generer les dependances, il faut des fichiers ! --------------
+
+sourceList=`ls *$extension`
+
+if test -z "$sourceList"
+then echo "Il n'y a aucun source ($extension) dans le repertoire courant"
+     exit 1
+fi
+
+#----------------- generation automatique  -------------------
+putFilesListInMakefile()
+{
+ strLocal=""
+ for iLocal in $1
+ do
+     strLocal=$strLocal" "$iLocal
+ done
+ set $strLocal
+ echo -n $1                                                       >> $makefile
+ shift
+ while test $# -ne 0
+ do
+   echo " \\"                                                     >> $makefile
+   echo $echoOptionForTab -n "\t$1"                               >> $makefile
+   shift
+ done
+ echo                                                             >> $makefile
+}                 # Fin de printFilesList()
+
+if test -f $makefile
+then make -f $makefile clear
+fi
+rm -f $makefile
+
+echo
+echo "============= GENERATION D'UN FICHIER $makefile ============"
+echo
+echo Generation pour $systeme
+echo
+
+
+echo "#----- Fichier genere automatiquement sous `uname` ------"  >> $makefile
+echo "#----- `date`"                                              >> $makefile
+echo                                                              >> $makefile
+
+echo "#-----"                                                     >> $makefile
+echo "INCDIR=$INCDIR"                                             >> $makefile
+echo "CCFLAGS=$CCFLAGS"                                           >> $makefile
+echo "LDFLAGS=$LDFLAGS"                                           >> $makefile
+echo "DEPOPT=$DEPOPT"                                             >> $makefile
+echo "CCC=$CCC"                                                   >> $makefile
+echo "#-----"                                                     >> $makefile
+echo                                                              >> $makefile
+
+echo "#-------------  Appli  --------------"                      >> $makefile
+echo                                                              >> $makefile
+
+
+putFilesListInMakefile "TARGET=$TARGET"
+echo                                                              >> $makefile
+
+for i in $TARGET
+do
+    findFileList="echo \$`echo FILES$i`"
+    fileList=`eval $findFileList`
+
+    putFilesListInMakefile "FILES$i=$fileList"                    >> $makefile
+    echo                                                          >> $makefile
+    findFalgList="echo \$`echo LDFLAGS$i`"
+    falgList=`eval $findFalgList`
+    echo "LDFLAGS$i=\$(LDFLAGS) $falgList"                        >> $makefile
+    echo                                                          >> $makefile
+done
+
+for i in $TARGET
+do
+    echo "OBJECTS$i=\$(FILES$i:$extension=.o)"                    >> $makefile
+    echo                                                          >> $makefile
+done
+
+echo "#-------------  Appli  --------------"                      >> $makefile
+echo                                                              >> $makefile
+
+echo "all: \$(TARGET)"                                            >> $makefile
+echo                                                              >> $makefile
+
+echo "#-------------  Appli  --------------"                      >> $makefile
+echo                                                              >> $makefile
+
+for i in $TARGET
+do
+
+cat << !                                                          >> $makefile
+$i : \$(OBJECTS$i)
+	\$(CCC) \$(OBJECTS$i) \\
+		-o $i \$(LDFLAGS$i)
+!
+
+done
+
+echo "#------------------------------------"                      >> $makefile
+echo                                                              >> $makefile
+
+cat << !                                                          >> $makefile
+.c.o :
+	\$(CCC) \$(CCFLAGS) -c \$< \\
+		-o \$*.o
+ 
+dep :
+	@echo "======== Mise a jour des dependances : .depend ========"
+	@rm -f .depend
+	@for i in *$extension ; do \\
+	echo \$\$i ; \\
+	\$(CCC) \$(DEPOPT) \$(CCFLAGS) \$\$i > .tmpdepend ; \\
+	OBJNAME=\`echo \$\$i | sed -e s%\\\\\\$extension%.o% \` ; \\
+	cat .tmpdepend | \\
+	sed -e s%\`basename \$\$i $extension\`\\\\\.o%\$\$OBJNAME% \
+        >> .depend ; \\
+	echo  >> .depend ; \\
+	done
+	@rm -f .tmpdepend
+ 
+CLEANING=rm -f *.o core a.out \$(TARGET) .depend
+CONSEIL=echo Penser a faire : make -f $makefile dep
+ 
+clear :
+	@\$(CLEANING)
+	@echo
+	@\$(CONSEIL)
+	@echo
+clean :
+	\$(CLEANING)
+	@echo
+	@\$(CONSEIL)
+	@echo
+
+sinclude .depend
+
+!
+
+echo
+echo "Et execution de : make -f $makefile dep"
+echo
+make -f $makefile dep
new file mode 100644
--- /dev/null
+++ b/ds.c
@@ -0,0 +1,80 @@
+#include "ds.h"
+#include "uinput.h"
+#include <stdint.h>
+#include <string.h>
+
+
+#include <stdio.h>
+
+
+/*
+    Throws events according to ds keys status
+*/
+void ds_process_evt(ds_t* ds, int uinput_fd){
+
+    static ds_t previous;
+
+    /* Fear the evil copy/paste!! */
+
+
+    /* BUTTONS: */
+    if( !previous.A && ds->A )    /* pressed */
+        do_uinput(uinput_fd, BTN_A, 1, EV_KEY);
+    else if( previous.A && !ds->A )   /* released */
+        do_uinput(uinput_fd, BTN_A, 0, EV_KEY);
+
+
+    if( !previous.B && ds->B )
+        do_uinput(uinput_fd, BTN_B, 1, EV_KEY);
+    else if( previous.B && !ds->B )
+        do_uinput(uinput_fd, BTN_B, 0, EV_KEY);
+
+
+    if( !previous.X && ds->X )
+        do_uinput(uinput_fd, BTN_X, 1, EV_KEY);
+    else if( previous.X && !ds->X )
+        do_uinput(uinput_fd, BTN_X, 0, EV_KEY);
+
+
+    if( !previous.Y && ds->Y )
+        do_uinput(uinput_fd, BTN_Y, 1, EV_KEY);
+    else if( previous.Y && !ds->Y )
+        do_uinput(uinput_fd, BTN_Y, 0, EV_KEY);
+
+
+    if( !previous.L && ds->L )
+        do_uinput(uinput_fd, BTN_TL, 1, EV_KEY);
+    else if( (previous.L) && !(ds->L) )
+        do_uinput(uinput_fd, BTN_TL, 0, EV_KEY);
+
+
+    if( !previous.R && ds->R )
+        do_uinput(uinput_fd, BTN_TR, 1, EV_KEY);
+    else if( previous.R && !ds->R )
+        do_uinput(uinput_fd, BTN_TR, 0, EV_KEY);
+
+
+    if( !previous.Start && ds->Start )
+        do_uinput(uinput_fd, BTN_START, 1, EV_KEY);
+    else if( previous.Start && !ds->Start )
+        do_uinput(uinput_fd, BTN_START, 0, EV_KEY);
+
+
+    if( !previous.Select && ds->Select )
+        do_uinput(uinput_fd, BTN_SELECT, 1, EV_KEY);
+    else if( previous.Select && !ds->Select )
+        do_uinput(uinput_fd, BTN_SELECT, 0, EV_KEY);
+
+
+    /* DIRECTIONS */
+    
+    if(previous.aX != ds->aX)
+        do_uinput(uinput_fd, ABS_X, ds->aX, EV_ABS);
+    
+    if(previous.aY != ds->aY)
+        do_uinput(uinput_fd, ABS_Y, ds->aY, EV_ABS);
+        
+    memcpy(&previous, ds, sizeof(ds_t));
+    
+    return;
+}
new file mode 100644
--- /dev/null
+++ b/ds.h
@@ -0,0 +1,28 @@
+#ifndef DS_H
+#define DS_H
+
+#include <stdint.h>
+
+
+/* Describe Device */
+typedef struct ds_s{
+    uint8_t A:1;      /* Pressed or held buttons */
+    uint8_t B:1;
+    uint8_t X:1;
+    uint8_t Y:1;
+    uint8_t L:1;
+    uint8_t R:1;
+    uint8_t Start:1;
+    uint8_t Select:1;   
+    uint8_t aX;
+    uint8_t aY;
+} __attribute__((packed)) ds_t;
+
+
+/* 
+    Throws events according to ds keys status
+*/
+extern void ds_process_evt(ds_t* ds, int uinput_fd);
+
+
+#endif /* DS_H */
new file mode 100644
--- /dev/null
+++ b/dspad.c
@@ -0,0 +1,138 @@
+/*
+    DSPad
+    Convert Nintendo DS keypress into joystick events
+*/
+
+#define __MAIN_FILE__
+
+#include "ds.h"
+#include "uinput.h"
+#include "service.h" 
+#include "restartOp.h"
+#include "XML.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+
+
+#define DEFAULT_PATH "~/DSPad_server.xml"
+
+
+/*
+    Process xml atoms
+*/
+int dspad_process_xml(void* elem, char* tag, char* content){
+
+    (void)elem;
+
+    if(tag != NULL && content != NULL){
+        if(strcmp(content, "")){
+        
+            /* process atom: */
+            if(!strcmp(tag, "base_port")){
+                base_port = atoi(content);
+                return 1;
+            }
+            
+            else if(!strcmp(tag, "uinput_dev")){
+                if(uinput_dev != NULL) free(uinput_dev);
+                uinput_dev = (char*)malloc(strlen(content)+1);
+                strcpy(uinput_dev, content);
+                return 1;
+            }
+
+            else if(!strcmp(tag, "nb_pad")){
+                nbdev = atoi(content);
+                return 1;
+            }
+    
+            return ReadXML(elem, dspad_process_xml, content);
+        }
+    }
+    
+    /* Should not happend... (compiler warning) */
+    return 0;
+}
+
+
+
+/*
+    Read config file
+    returns 1 OK
+            0 error
+*/
+int config_read(char* path){
+    int ok = 0;
+    char* text = NULL;
+    
+    text = LoadFile(path);
+    if(text){
+        ok = ReadXML(NULL, dspad_process_xml, text);
+        free(text);
+        if(ok){
+            fprintf(stderr, "Reading \"%s\" OK\n", path);
+        }
+        else{
+            fprintf(stderr, "Reading \"%s\" FAILED\n", path);
+        }
+    }
+    return ok;
+}
+
+
+
+
+int main(int argc, char** argv){
+    /* -- gcc -Werror satisfaction... -- */
+    (void)argc;
+    (void)argv;
+    /* --------------------------------- */
+    
+    curdev = 0;
+
+    fprintf(stdout, "\n--- Starting DSPad Server v0.2 ---\n");
+    
+    pid_t pid = 0;
+    
+    if(argc == 3 && !strcmp("-f", argv[1])){
+        fprintf(stderr, "Loading \"%s\"\n", argv[2]);
+        config_read(argv[2]);
+    }
+    else{
+        fprintf(stderr, "Loading \"%s\"\n", DEFAULT_PATH);
+        config_read(DEFAULT_PATH);
+    }
+    
+        
+    
+    /* fork servers */
+    while(curdev < nbdev){
+        pid = fork_rs();
+        switch(pid){
+            case 0:
+                curdev++;
+                // Wait 2 seconds before next because
+                // of kernel dev creation latency
+                sleep_rs(2);
+                break;
+            case -1:
+                fprintf(stderr, " [%d] Creation of service: failed\n", curdev);
+                exit(EXIT_FAILURE);
+                break;
+            default:
+                start_service();
+                sleep(5);
+                fprintf(stdout, " [%d] Service finished\n", curdev);
+                waitpid(-1, NULL, 0);
+                exit(EXIT_SUCCESS);
+                break;
+        } /* switch */
+    }    
+    
+    return 0;
+}
+
new file mode 100644
--- /dev/null
+++ b/makefile
@@ -0,0 +1,70 @@
+#----- Fichier genere automatiquement sous Linux ------
+#----- sam fév 24 17:16:55 CET 2007
+
+#-----
+INCDIR=.
+CCFLAGS=-W -Wall -Werror -I$(INCDIR) -D_REENTRANT -g
+LDFLAGS=
+DEPOPT=-MM
+CCC=cc
+#-----
+
+#-------------  Appli  --------------
+
+TARGET=dspad_server
+
+FILESdspad_server=ds.c \
+	dspad.c \
+	restartOp.c \
+	service.c \
+	uinput.c \
+	XML.c
+
+LDFLAGSdspad_server=$(LDFLAGS) 
+
+OBJECTSdspad_server=$(FILESdspad_server:.c=.o)
+
+#-------------  Appli  --------------
+
+all: $(TARGET)
+
+#-------------  Appli  --------------
+
+dspad_server : $(OBJECTSdspad_server)
+	$(CCC) $(OBJECTSdspad_server) \
+		-o dspad_server $(LDFLAGSdspad_server)
+#------------------------------------
+
+.c.o :
+	$(CCC) $(CCFLAGS) -c $< \
+		-o $*.o
+ 
+dep :
+	@echo "======== Mise a jour des dependances : .depend ========"
+	@rm -f .depend
+	@for i in *.c ; do \
+	echo $$i ; \
+	$(CCC) $(DEPOPT) $(CCFLAGS) $$i > .tmpdepend ; \
+	OBJNAME=`echo $$i | sed -e s%\\\.c%.o% ` ; \
+	cat .tmpdepend | \
+	sed -e s%`basename $$i .c`\\\.o%$$OBJNAME%         >> .depend ; \
+	echo  >> .depend ; \
+	done
+	@rm -f .tmpdepend
+ 
+CLEANING=rm -f *.o core a.out $(TARGET) .depend
+CONSEIL=echo Penser a faire : make -f makefile dep
+ 
+clear :
+	@$(CLEANING)
+	@echo
+	@$(CONSEIL)
+	@echo
+clean :
+	$(CLEANING)
+	@echo
+	@$(CONSEIL)
+	@echo
+
+sinclude .depend
+
new file mode 100644
--- /dev/null
+++ b/restartOp.c
@@ -0,0 +1,270 @@
+/*
+    Signal interruptible fonctions handlers
+*/
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/msg.h>
+#include <errno.h>
+
+#include "restartOp.h"
+
+/********************************************************/
+/*                        fork                          */
+/********************************************************/
+pid_t fork_rs(void){
+    pid_t result;
+
+    do{
+        result = fork();
+    }while((result == -1) && (errno == EAGAIN));
+
+    return result;
+}
+
+/********************************************************/
+/*                   wait, waitpid                      */
+/********************************************************/
+/*
+pid_t wait_rs(int *status)
+{
+ pid_t endPid;
+
+ do {
+      endPid=wait(status);
+ } while ((endPid==-1) && (errno==EINTR));
+ 
+ return endPid;
+}
+*/
+/*
+pid_t waitpid_rs(pid_t pid, int *status, int options)
+{
+ pid_t endPid;
+
+ do {
+      endPid=waitpid(pid,status,options);
+ } while ((endPid==-1) && (errno==EINTR));
+ 
+ return endPid;
+}
+*/
+
+/********************************************************/
+/*                         sleep                        */
+/********************************************************/
+ 
+unsigned int sleep_rs(unsigned int seconds)
+{
+ int nbSecondsElapsed = 0;
+ 
+ do {
+ 
+     seconds = seconds -  nbSecondsElapsed;
+ 
+     nbSecondsElapsed = sleep(seconds);
+ 
+ } while (nbSecondsElapsed!=0);
+ 
+ return 0;       //  Zero  if  the requested time has elapsed
+}
+
+
+/********************************************************/
+/*                   read, write, close                 */
+/********************************************************/
+/*
+ssize_t read_rs(int fd, void *buf, size_t len)
+{
+ ssize_t returnValue = 0;
+
+ do {
+      returnValue = read(fd,buf,len);
+ } while ((returnValue==-1) && (errno==EINTR));
+
+ return returnValue;
+}
+*/
+/*
+ssize_t write_rs(int fd, const void *buf, size_t count)
+{
+ ssize_t returnValue = 0;
+
+ do {
+      returnValue = write(fd,buf,count);
+ } while ((returnValue==-1) && (errno==EINTR));
+
+ return returnValue;
+}
+*/
+/*
+int     close_rs(int fd)
+{
+ int returnValue = 0;
+
+ do {
+      returnValue = close(fd);
+ } while ((returnValue==-1) && (errno==EINTR));
+
+ return returnValue;
+}
+*/
+
+/********************************************************/
+/*                        dup, dup2                     */
+/********************************************************/
+/*
+int dup_rs(int oldfd)
+{
+ int returnValue = 0;
+
+ do {
+      returnValue = dup(oldfd);
+ } while ((returnValue==-1) && (errno==EINTR));
+
+ return returnValue;
+}
+*/
+/*
+int dup2_rs(int oldfd, int newfd)
+{
+ int returnValue = 0;
+
+ do {
+      returnValue = dup2(oldfd,newfd);
+ } while ((returnValue==-1) && (errno==EINTR));
+
+ return returnValue;
+}
+*/
+
+/********************************************************/
+/*                        semop                         */
+/********************************************************/
+/*
+int semop_rs(int semid, struct sembuf *sops,unsigned nsops)
+{
+ int returnValue = 0;
+
+ do {
+      returnValue = semop(semid,sops,nsops);
+ } while ((returnValue==-1) && (errno==EINTR));
+
+ return returnValue;
+}
+*/
+
+/********************************************************/
+/*                      msgsnd, msgrcv                  */
+/********************************************************/
+/* 
+int msgsnd_rs(int msqid, void *msgp, int msgsz, int msgflg)
+{
+ int returnValue = 0;
+
+ do {
+      returnValue = msgsnd(msqid,msgp,msgsz,msgflg);
+ } while ((returnValue==-1) && (errno==EINTR)); 
+ 
+ return returnValue;
+}
+*/
+/*
+int msgrcv_rs(int msqid, void *msgp, int msgsz,long msgtyp,int msgflg)
+{
+ int returnValue = 0;
+
+ do {
+      returnValue = msgrcv(msqid,msgp,msgsz,msgtyp,msgflg);
+ } while ((returnValue==-1) && (errno==EINTR)); 
+ 
+ return returnValue;
+}
+*/
+
+/********************************************************/
+/*                     connect, accept                  */
+/********************************************************/
+/*
+int connect_rs(int sockfd, struct sockaddr *serv_addr, socklen_t addrlen)
+{
+  int returnValue = 0;
+
+  do {
+      returnValue = connect(sockfd,serv_addr,addrlen);
+  } while ((returnValue==-1) && (errno==EINTR));
+
+  return returnValue;
+}
+*/
+/*
+int accept_rs(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+ int returnValue  = 0;
+ int addrlenSaved = *addrlen;
+
+ do {
+      *addrlen = addrlenSaved;
+      returnValue = accept(sockfd,addr,addrlen);
+  } while ((returnValue==-1) && (errno==EINTR));
+
+  return returnValue;
+}
+*/
+
+/********************************************************/
+/*      recv, send  (TCP ou UDP avec pseudo-connexions) */
+/********************************************************/
+/*
+ssize_t recv_rs(int sockfd, void *buf, size_t len, int flags)
+{
+ int returnValue = 0;
+
+ do {
+     returnValue = recv(sockfd,buf,len,flags);
+ } while ((returnValue==-1) && (errno==EINTR));
+
+ return returnValue;
+}
+*/
+/*
+ssize_t send_rs(int sockfd, const void *buf, size_t count, int flags)
+{
+ int returnValue = 0;
+
+ do {
+     returnValue = send(sockfd,buf,count,flags);
+ } while ((returnValue==-1) && (errno==EINTR));
+
+ return returnValue;
+}
+*/
+
+/********************************************************/
+/*               recvfrom, sendto  (UDP)                */
+/********************************************************/
+
+ssize_t recvfrom_rs(int sockfd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen){
+    ssize_t returnValue = 0;
+    do{
+        returnValue = recvfrom(sockfd, buf, len, flags, from, fromlen);
+    }while( (returnValue == -1) && (errno == EINTR) );
+
+    return returnValue;
+}
+
+/*
+ssize_t sendto_rs(int sockfd, const void *msg, size_t count, int flags,
+                  const struct sockaddr *to, socklen_t tolen)
+{
+ ssize_t returnValue = 0;
+ do {
+      returnValue = sendto(sockfd,msg,count,flags,to,tolen);
+  } while ((returnValue==-1) && (errno==EINTR));
+
+ return returnValue;
+}
+*/
new file mode 100644
--- /dev/null
+++ b/restartOp.h
@@ -0,0 +1,80 @@
+/*
+    Signal interruptible fonctions handlers
+*/
+
+
+
+#ifndef    RESTARTOP_H
+#define    RESTARTOP_H
+
+#include <sys/types.h>
+#include <sys/sem.h>
+#include <sys/socket.h>
+
+/********************************************************/
+/*                        fork                          */
+/********************************************************/
+
+extern pid_t fork_rs(void);
+
+/********************************************************/
+/*                   wait, waitpid                      */
+/********************************************************/
+
+//extern pid_t wait_rs(int *status);
+//extern pid_t waitpid_rs(pid_t pid, int *status, int options);
+
+/********************************************************/
+/*                         sleep                        */
+/********************************************************/
+ 
+extern unsigned int sleep_rs(unsigned int seconds);
+
+/********************************************************/
+/*                   read, write, close                 */
+/********************************************************/
+
+//extern ssize_t read_rs(int fd, void *buf, size_t len);
+//extern ssize_t write_rs(int fd, const void *buf, size_t count);
+//extern int     close_rs(int fd);
+
+/********************************************************/
+/*                        dup, dup2                     */
+/********************************************************/
+
+//extern int dup_rs(int oldfd);
+//extern int dup2_rs(int oldfd, int newfd);
+
+/********************************************************/
+/*                        semop                         */
+/********************************************************/
+//extern int semop_rs(int semid, struct sembuf *sops,unsigned nsops);
+
+/********************************************************/
+/*                      msgsnd, msgrcv                  */
+/********************************************************/
+
+//extern int msgsnd_rs(int msqid, /* const */ void* msgp, int msgsz, int msgflg);
+//extern int msgrcv_rs(int msqid, void* msgp, int msgsz, long msgtyp,int msgflg);
+
+/********************************************************/
+/*                     connect, accept                  */
+/********************************************************/
+
+//extern int connect_rs(int sockfd, struct sockaddr *serv_addr,socklen_t addrlen);
+//extern int accept_rs(int sockfd, struct sockaddr *addr,socklen_t *addrlen);
+
+/********************************************************/
+/*                     recv, send                       */
+/********************************************************/
+
+//extern ssize_t recv_rs(int sockfd, void *buf, size_t len, int flags);
+//extern ssize_t send_rs(int sockfd, const void *buf, size_t count, int flags);
+
+/********************************************************/
+/*                   recvfrom, sendto                   */
+/********************************************************/
+extern ssize_t recvfrom_rs(int sockfd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
+//extern ssize_t sendto_rs(int sockfd, const void *msg, size_t count, int flags, const struct sockaddr *to, socklen_t tolen);
+
+#endif  /* RESTARTOP_H */
new file mode 100644
--- /dev/null
+++ b/service.c
@@ -0,0 +1,134 @@
+#include "service.h"
+#include "uinput.h"
+#include "ds.h"
+#include "restartOp.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*
+    Create a socket
+    Returns socket descriptor (-1 if error)
+*/
+int create_socket(unsigned short *port, int type){
+    int sock, autorisation , ok;
+    struct sockaddr_in  add;
+    socklen_t l = sizeof(struct sockaddr_in);
+
+    sock = socket(PF_INET, type, 0);
+    if(sock == -1){
+        perror("socket");
+        return -1;
+    }
+
+    /* Pour pouvoir relancer immediatement un serveur TCP  */
+    /* ou lancer, sur une meme machine,                    */
+    /*    plusieurs recepteurs UDP sur                     */
+    /*    le meme port de diffusion (broadcast, multicast) */
+    autorisation = 1;
+    ok = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &autorisation, sizeof(int));
+    if(ok == -1){
+        perror("setsockopt");
+        return -1;
+    }
+
+    memset(&add, 0, l) ;
+    add.sin_family      = AF_INET ;
+    add.sin_port        = htons(*port);
+    add.sin_addr.s_addr = htonl(INADDR_ANY);
+
+    ok = bind(sock, (struct sockaddr*)&add, l);
+    if(ok == -1){
+        perror("bind");
+        return -1;
+    }
+
+    ok = getsockname(sock, (struct sockaddr*)&add, &l);
+    if(ok == -1){
+        perror("getsockname");
+        return -1;
+    }
+
+    *port = ntohs(add.sin_port);
+    return sock;
+}
+
+
+
+/*
+    Receive a DS datagram
+    Returns size read or -1
+*/
+ssize_t receive_ds_info(int socket, ds_t* ds){
+	struct sockaddr_in add;
+	socklen_t l = sizeof(struct sockaddr_in);
+	
+	ssize_t result;
+	
+ 	result = recvfrom_rs(socket, ds, sizeof(ds_t), 0, (struct sockaddr*)&add, &l);
+ 	if(result == -1) perror("recvfrom_rs");
+ 	return result;
+}
+
+
+/*
+    Start the listening service yeah!
+*/
+void start_service(void){
+
+    int uinput_fd;
+    int sock_fd;
+    uint16_t udp_port = base_port + curdev;
+    
+    ds_t ds;
+    ssize_t result;
+
+
+    fprintf(stdout, " [%d] Creation of service:\n", curdev);
+
+    // Create joystick dev
+    uinput_fd = init_uinput_device();
+    if(uinput_fd == -1){
+        fprintf(stderr, " [%d]  Joystick device failed\n", curdev);
+        exit(EXIT_FAILURE);
+    }
+    fprintf(stdout, " [%d]  Joystick device OK\n", curdev);
+    
+
+    // Create udp socket
+    sock_fd = create_socket(&udp_port, SOCK_DGRAM);
+    if(sock_fd == -1){
+        fprintf(stderr, " [%d]  Socket failed\n", curdev);
+        exit(EXIT_FAILURE);
+    }
+    fprintf(stdout, " [%d]  Socket on port %d OK\n", curdev, udp_port);
+
+    
+    // Device and Socket are ok :-D
+    fprintf(stdout, " [%d] Creation of service: OK\n", curdev);
+
+
+    /* Center device axis when created */
+    do_uinput(uinput_fd, ABS_Y, DS_MAX_Y/2, EV_ABS);
+    do_uinput(uinput_fd, ABS_X, DS_MAX_X/2, EV_ABS);
+
+    while(1){
+        result = receive_ds_info(sock_fd, &ds);
+        if(result == -1){
+            fprintf(stderr, " [%d]  DS Info receive failed\n", curdev);            
+        }
+        if(result > 0){
+            ds_process_evt(&ds, uinput_fd);
+        }
+    }
+
+    return;
+}
+
+
+
new file mode 100644
--- /dev/null
+++ b/service.h
@@ -0,0 +1,51 @@
+#ifndef SERVICE_H
+#define SERVICE_H
+
+#include "uinput.h"
+#include "ds.h"
+#include "restartOp.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DEFAULT_DEV_QTY 2       /* How many jsX devices */
+#define DEFAULT_BASE_UDP_PORT   16150   /* Listen DS datagrams */
+
+
+/* Globals... */
+#ifndef __MAIN_FILE__
+    extern uint8_t nbdev;
+    extern uint8_t curdev;
+    extern uint16_t base_port;
+    extern char* uinput_dev;
+#else
+    uint8_t nbdev = DEFAULT_DEV_QTY;
+    uint8_t curdev;
+    uint16_t base_port = DEFAULT_BASE_UDP_PORT;
+    char* uinput_dev = NULL;
+#endif
+
+
+/*
+    Create a socket
+    Returns socket descriptor (-1 if error)
+*/
+extern int create_socket(unsigned short *port, int type);
+
+/*
+    Receive a DS datagram
+*/
+extern ssize_t receive_ds_info(int socket, ds_t* ds);
+
+/*
+    Start the listening service yeah!
+*/
+extern void start_service(void);
+
+
+
+#endif /* SERVICE_H */
new file mode 100644
--- /dev/null
+++ b/uinput.c
@@ -0,0 +1,134 @@
+#include "uinput.h"
+#include "ds.h"
+#include "service.h"
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+
+#define DS_NAME     "NintendoDS Wireless Gamepad"
+
+/* Not found these values... but it's not important! */
+#define DS_VENDOR   0xdead
+#define DS_PRODUCT  0xbeef
+#define DS_VERSION  0x00
+
+
+
+/* 
+    Create a new uinput device
+    Returns: file descriptor (-1 if error)
+ */
+int init_uinput_device(void){
+    struct uinput_user_dev dev;
+    int fd = -1;
+
+    if(uinput_dev == NULL){
+        fd = open("/dev/uinput", O_RDWR);
+         
+        if(fd < 0)
+            fd = open("/dev/misc/uinput", O_RDWR);
+            
+        if(fd < 0)
+            fd = open("/dev/input/uinput", O_RDWR);
+    }
+    else fd = open(uinput_dev, O_RDWR); //from xml
+    
+    if(fd < 0){
+        fprintf(stderr, " [%d]  Unable to open uinput device ; hint: 'modprobe uinput' ?!\n", curdev);
+        return -1;
+    }
+    
+    
+
+    memset(&dev, 0, sizeof(dev));
+    strncpy(dev.name, DS_NAME, UINPUT_MAX_NAME_SIZE);
+    dev.id.bustype = 0;
+    dev.id.vendor  = DS_VENDOR;
+    dev.id.product = DS_PRODUCT;
+    dev.id.version = DS_VERSION;
+
+    dev.absmax[ABS_X]  = DS_MAX_X;
+    dev.absmin[ABS_X]  = DS_MIN_X;
+    dev.absfuzz[ABS_X] = 4;
+    dev.absflat[ABS_X] = 2;    
+    
+    dev.absmax[ABS_Y]  = DS_MAX_Y;
+    dev.absmin[ABS_Y]  = DS_MIN_Y;
+    dev.absfuzz[ABS_X] = 4;
+    dev.absflat[ABS_X] = 2;
+
+
+    if(write(fd, &dev, sizeof(dev)) < (ssize_t)sizeof(dev)){
+        fprintf(stderr, " [%d]  Registering device at uinput failed\n", curdev);
+        return -1;
+    }
+    
+    /* Keys [01] (found in <linux/input.h>) */
+    if( ioctl(fd, UI_SET_EVBIT,  EV_KEY)    ) return -1; 
+    if( ioctl(fd, UI_SET_KEYBIT, BTN_A)     ) return -1;
+    if( ioctl(fd, UI_SET_KEYBIT, BTN_B)     ) return -1;
+    if( ioctl(fd, UI_SET_KEYBIT, BTN_X)     ) return -1;
+    if( ioctl(fd, UI_SET_KEYBIT, BTN_Y)     ) return -1;
+    if( ioctl(fd, UI_SET_KEYBIT, BTN_TL)    ) return -1;
+    if( ioctl(fd, UI_SET_KEYBIT, BTN_TR)    ) return -1;
+    if( ioctl(fd, UI_SET_KEYBIT, BTN_START) ) return -1;
+    if( ioctl(fd, UI_SET_KEYBIT, BTN_SELECT)) return -1;
+    
+    /* D-Pad [-0xFFFF - 0xFFFF] */
+    if( ioctl(fd, UI_SET_EVBIT,  EV_ABS)    ) return -1;
+    if( ioctl(fd, UI_SET_ABSBIT, ABS_X)     ) return -1;
+    if( ioctl(fd, UI_SET_ABSBIT, ABS_Y)     ) return -1;
+
+
+    /* Register device */
+    if( ioctl(fd, UI_DEV_CREATE)            ) return -1;
+       
+    return fd;
+}
+
+
+/*
+    Send an event into the uinput device
+    Returns: TRUE, FALSE
+*/
+int do_uinput(int fd, unsigned short key, int pressed, unsigned short event_type){
+    struct input_event event;
+    memset(&event, 0 , sizeof(event));
+	
+    event.type = event_type;
+    event.code = key;
+    event.value = pressed;
+	
+    if(write(fd,&event,sizeof(event)) != sizeof(event)){
+        fprintf(stderr, "  [%d] Writing event to uinput driver failed ; Aborting\n", curdev);
+        return false;
+    }
+    return true;
+}
+
+
+/*
+    Synchonize events
+*/
+void flush_uinput(int fd){
+    struct input_event event;
+    memset(&event, 0 , sizeof(event));
+    
+    event.type = EV_SYN;
+    event.code = SYN_REPORT;
+
+    if(fd){
+        if(write(fd, &event, sizeof(event) != sizeof(event)))
+            fprintf(stderr, "  [%d] Flushing uinput failed\n", curdev);
+    }
+}
+
+
+
+
+
new file mode 100644
--- /dev/null
+++ b/uinput.h
@@ -0,0 +1,33 @@
+#ifndef UINPUT_H
+#define UINPUT_H
+
+
+#include <linux/input.h>
+#include <linux/uinput.h>
+
+#define DS_MIN_X    0
+#define DS_MAX_X    255
+#define DS_MIN_Y    0
+#define DS_MAX_Y    191
+
+
+/* 
+    Create a new uinput device
+    Returns: device descriptor
+ */
+extern int init_uinput_device(void);
+
+
+/*
+    Send an event into the uinput device
+    Returns: TRUE, FALSE
+*/
+extern int do_uinput(int fd, unsigned short key, int pressed, unsigned short event_type);
+
+
+/*
+    Synchonize events
+*/
+extern void flush_uinput(int fd);
+
+#endif /* UINPUT_H */