# HG changeset patch # User Emmanuel Gil Peyrot # Date 1424565486 -3600 # Node ID e70ea46d60734aa3411de597a47f9db9988442a4 Initial import from http://wouhanegaine.free.fr/dev/DSPad02b_neo07.zip diff --git a/COPYING b/COPYING 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. + + + Copyright (C) 19yy + + 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. + + , 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. diff --git a/DSPad_server.xml b/DSPad_server.xml new file mode 100755 --- /dev/null +++ b/DSPad_server.xml @@ -0,0 +1,5 @@ + + 16150 + 2 + /dev/misc/uinput + diff --git a/XML.c b/XML.c 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,""); + + 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; +} diff --git a/XML.h b/XML.h 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 +#include +#include + +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 */ diff --git a/configure b/configure 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 diff --git a/ds.c b/ds.c new file mode 100644 --- /dev/null +++ b/ds.c @@ -0,0 +1,80 @@ +#include "ds.h" +#include "uinput.h" +#include +#include + + +#include + + +/* + 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; +} diff --git a/ds.h b/ds.h new file mode 100644 --- /dev/null +++ b/ds.h @@ -0,0 +1,28 @@ +#ifndef DS_H +#define DS_H + +#include + + +/* 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 */ diff --git a/dspad.c b/dspad.c 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 +#include +#include +#include +#include +#include + + +#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; +} + diff --git a/makefile b/makefile 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 + diff --git a/restartOp.c b/restartOp.c new file mode 100644 --- /dev/null +++ b/restartOp.c @@ -0,0 +1,270 @@ +/* + Signal interruptible fonctions handlers +*/ + +#include +#include +#include +#include +#include +#include +#include + +#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; +} +*/ diff --git a/restartOp.h b/restartOp.h new file mode 100644 --- /dev/null +++ b/restartOp.h @@ -0,0 +1,80 @@ +/* + Signal interruptible fonctions handlers +*/ + + + +#ifndef RESTARTOP_H +#define RESTARTOP_H + +#include +#include +#include + +/********************************************************/ +/* 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 */ diff --git a/service.c b/service.c 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 +#include +#include +#include +#include +#include + + +/* + 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; +} + + + diff --git a/service.h b/service.h 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 +#include +#include +#include +#include +#include + +#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 */ diff --git a/uinput.c b/uinput.c new file mode 100644 --- /dev/null +++ b/uinput.c @@ -0,0 +1,134 @@ +#include "uinput.h" +#include "ds.h" +#include "service.h" + +#include +#include +#include +#include +#include +#include + + +#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 ) */ + 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); + } +} + + + + + diff --git a/uinput.h b/uinput.h new file mode 100644 --- /dev/null +++ b/uinput.h @@ -0,0 +1,33 @@ +#ifndef UINPUT_H +#define UINPUT_H + + +#include +#include + +#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 */