diff --git a/README b/README new file mode 100644 index 0000000000000000000000000000000000000000..d1477d165f76ba0ed51e6b7b5f913b9a0430bcec --- /dev/null +++ b/README @@ -0,0 +1,25 @@ +[ Smews version 1.5.0 ] + +License: CeCILL license, http://www.cecill.info +Date: 22-06-2010 +Contact: Simon Duquennoy -- simon.duquennoy@lifl.fr +Web page: smews.gforge.inria.fr +Contributors: + Simon Duquennoy -- is the main author of the Smews Software + Thomas So\"{e}te -- is the main contributor of the WSN430 port + Geoffroy Cogniaux -- is the main contributor of the FunCard7 port + Alex Negrea -- is the main author of this user guide and of the TLS support (not yet released) + Geoffrey Chavepeyer and Fabien Duchêne -- are the main authors of the IPv6 support + Jean-Fran\c{c}ois Hren -- designed the Smew (bird) in the Smews logo +Thanks to Gilles Grimaud for his kind supervision. + +Smews is an efficient embedded Web server for tiny devices, with high +resource constraints. + +This software includes parts of code from SOSSE (Simple Operating system for Smart cards) +http://www.mbsks.franken.de/sosse/, under GPL license : +targets/Funcard7/drivers/at_config.h +targets/Funcard7/drivers/eepromi2c.s +targets/Funcard7/drivers/io.s + +Please read the user guide to get started. diff --git a/SConscript b/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..06ba77b0e727e9b37cfab492cc90896f651e5441 --- /dev/null +++ b/SConscript @@ -0,0 +1,150 @@ +# Copyright or c or Copr. 2008, Simon Duquennoy +# +# Author e-mail: simon.duquennoy@lifl.fr +# +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + +import os +import GenApps + +# imports from SConstruct +Import('env libFileName elfFileName binDir coreDir driversDir genDir appBase toolsList chuncksNbits sourcesMap gzipped') + +# returns the list of .c and .s files in dir, prefixed by dstDir +def getAllSourceFiles(dir, dstDir): + cFiles = [] + sFiles = [] + for file in os.listdir(dir): + if file.endswith('.c'): + cFiles.append(os.path.join(dstDir,file)) + elif file.endswith('.s'): + sFiles.append(os.path.join(dstDir,file)) + return sFiles + cFiles + +# builders for web applicative resources creation +# used to generate both static and dynamic resources +def generateResource(target, source, env): + if propsFilesMap.has_key(str(source[0])): + GenApps.generateResource(str(source[0]),str(target[0]),chuncksNbits,gzipped,propsFilesMap[str(source[0])]) + else: + GenApps.generateResource(str(source[0]),str(target[0]),chuncksNbits,gzipped,None) + return None + +# builder used to generate the file index, with the URLs tree +def generateIndex(target, source, env): + GenApps.generateIndex(genDir,sourcesMap,str(target[0]),chuncksNbits,appBase,propsFilesMap) + return None + +# builder used to generate the channels header file +def generateChannelsH(target, source, env): + GenApps.generateChannelsH(str(target[0]),propsFilesMap) + return None + +# builder used to generate to synthetized properties of generator files +# a property file is created for each generator file, it synthetizes some of its XML information +# all information used to build the file-index.c file or the channel.h file MUST be included in the props file +def generateResourceProps(target, source, env): + GenApps.generateResourceProps(str(source[0]),propsFilesMap[str(source[0])]) + return None + +env['BUILDERS']['GenResource'] = Builder(action = generateResource) +env['BUILDERS']['GenIndex'] = Builder(action = generateIndex) +env['BUILDERS']['GenChannelsH'] = Builder(action = generateChannelsH) +env['BUILDERS']['GenResourceProps'] = Builder(action = generateResourceProps) + +# build directories settings, with no source duplication +BuildDir(os.path.join(binDir,'core'), coreDir, duplicate=0) +BuildDir(os.path.join(binDir,'drivers'), driversDir, duplicate=0) + +# applications files index and channel files settings +resourcesIndexO = os.path.join(binDir,'gen','resources_index') +resourcesIndexC = os.path.join(genDir,'resources_index.c') +channelsH = os.path.join(genDir,'channels.h') +appListName = os.path.join(genDir,'appList') + +# loop on each web resource in order to generate associated c files +# static resources generate pre-computed c files +# dynamic resources are enriched with new declarations (from their XML) +# other c and h files are simply copied +appFiles = [] +genObjects = [] +propsFilesList = [] +propsFilesMap = {} +for file in sourcesMap.keys(): + fileName = GenApps.getFileName(file,chuncksNbits,gzipped) + if fileName.startswith(genDir): + fileName = fileName[len(genDir)+1:] + if file.endswith('.h'): + cFile = os.path.join(genDir,fileName) + '.h' + else: + cFile = os.path.join(genDir,fileName) + '.c' + env.GenResource(cFile,file) + env.Depends(cFile,toolsList) + if file.endswith('.c'): # this is a generator or a c file to compile + propsFile = cFile + '.props' + env.GenResourceProps(propsFile,file) + env.Depends(propsFile,toolsList) + propsFilesList.append(propsFile) + propsFilesMap[file] = {'fileName' : propsFile} + elif file.endswith('.h'): # header files have not to be embedded + propsFilesMap[file] = {'fileName' : '', 'hasXml' : False, 'channel' : ''} + appFiles.append(file) + if not file.endswith('.h'): + objFile = os.path.join(binDir,'gen',fileName) + genObjects.append(env.Object(objFile,cFile)) + +# files index generated file dependencies management, via a appList file (for SCons dependencies tree) +# appList is a file that contains the list of the web applicative resources embedded with smews +appList = open(appListName,'w') +for source in sourcesMap.keys(): + appList.write(sourcesMap[source] + ' -> ' + source + '\n') +appList.close() + +# files index generation +env.GenIndex(resourcesIndexC,[]) +env.Depends(resourcesIndexC,appListName) +env.Depends(resourcesIndexC,toolsList) +env.Depends(resourcesIndexC,propsFilesList) +# files index object file +genObjects.append(env.Object(resourcesIndexO, resourcesIndexC)) +# channels header file +env.GenChannelsH(channelsH,propsFilesList) +env.Depends(channelsH,toolsList) + +# engine source code dependencies +coreFiles = getAllSourceFiles(coreDir, os.path.join(binDir,'core')) +# target drivers source code dependencies +targetFiles = getAllSourceFiles(driversDir, os.path.join(binDir,'drivers')) +# create a library from all sources +lib = env.Library(libFileName, targetFiles + coreFiles + genObjects) +# link the library into a elf file +final = env.Program(elfFileName, targetFiles + coreFiles + genObjects) +# clean +Clean([lib,final],[binDir,genDir]) diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000000000000000000000000000000000000..6a1c22824261e6fae35c401d21dffe049b6c5dd0 --- /dev/null +++ b/SConstruct @@ -0,0 +1,225 @@ +# Copyright or c or Copr. 2008, Simon Duquennoy +# +# Author e-mail: simon.duquennoy@lifl.fr +# +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + +import os +import sys +sys.path.append('tools') +import GenApps + +import sys, string + +import IPy +from IPy import IP + +def strVersion(version): + str = '.' + for i in version: + str += '.' + i + return str[2:] + +currVersion = string.split(string.split(sys.version)[0], ".") +minVersion = ['2', '5', '0'] +if currVersion < minVersion: + print 'Error: python version ' + strVersion(minVersion) + ' is required. Your current version is ' + strVersion(currVersion) + '.' + exit(1) + +# global names +# scons cache file +sconsCache = '.sconsign.dblite' +# base directories +targetBase = 'targets' +genBase = 'gen' +binBase = 'bin' +coreDir = 'core' +toolsDir = 'tools' +tmpBase = 'tmp' +appBase = 'apps' +httpCodesDir = 'httpCodes' +# the list of python files used by this SConstruct +toolsList = map(lambda x: os.path.join(toolsDir,x),filter(lambda x: x.endswith('.py'), os.listdir(toolsDir))) +projectName = 'smews' +elfName = projectName + '.elf' +libName = projectName + '.a' + +# options management +opts = Variables() +opts.Add(ListVariable('target', 'Set the target', 'none', filter(lambda x: not x.startswith('.'),os.listdir('targets')))) +opts.Add('apps', 'Set the Web applications directories:\na list of directories name in %s, possibly preceded by a replacement URL\nExample: inclusion of comet, generator (remplaced by gen in the URL), smews (as root of the file system):\napps=comet,gen:generator,:smews\n' %(appBase), None) +opts.Add(BoolVariable('gzip', 'Set to 1 to gzip (at compile time) static Web resources', True)) +opts.Add(BoolVariable('debug', 'Set to 1 to build for debug', False)) +opts.Add(BoolVariable('sdump', 'Set to 1 to include stack dump', False)) +opts.Add('ipaddr', 'Set the IP address of Smews', None) +# the list of disableable options +disabledHash = {} +disabledHash['timers'] = 'DISABLE_TIMERS' +disabledHash['comet'] = 'DISABLE_COMET' +disabledHash['arguments'] = 'DISABLE_ARGS' +opts.Add(ListVariable('disable', 'Disable smews functionnalities', 'none', disabledHash.keys())) +opts.Add(ListVariable('endian', 'Force endianness', 'none', ['little','big'])) +opts.Add('chuncksNbits', 'Set the checksum chuncks size', 5) + +# environment creation, options extraction +globalEnv = Environment(tools = ['gcc','as','ar','gnulink'], ENV = os.environ, options = opts) +Help(opts.GenerateHelpText(globalEnv)) + +# arguments are stored into variables +gzipped = globalEnv['gzip'] +debug = globalEnv['debug'] +sdump = globalEnv['sdump'] +chuncksNbits = int(globalEnv['chuncksNbits']) +toDisable = globalEnv['disable'] +endian = globalEnv['endian'] +if endian: + endian = endian[0] +targets = map(lambda x: os.path.normpath(str(x)),globalEnv['target']) + +# static configuration of the ip adress +if globalEnv.has_key('ipaddr'): + ipVersion = IP(globalEnv['ipaddr']).version(); + + if (ipVersion == 4): + parts = str(IP(globalEnv['ipaddr']).strFullsize()).split("."); + ipAdress = parts[3]+","+parts[2]+","+parts[1]+","+parts[0] + globalEnv.Append(CPPDEFINES = { 'IP_ADDR' : ipAdress }) + elif (ipVersion == 6): + hexIPAdress = str(IP(globalEnv['ipaddr']).strHex()); + globalEnv.Append(CPPDEFINES = { 'IPV6' : '1'}) + ipAdress = '' + low_index = 32 + high_index = 34 + + for i in range(15): + ipAdress += "0x"+hexIPAdress[low_index:high_index]+"," + low_index = low_index - 2 + high_index = high_index - 2 + + ipAdress += "0x"+hexIPAdress[low_index:high_index] + + globalEnv.Append(CPPDEFINES = { 'IP_ADDR' : ipAdress }) + +# applications to be embedded with smews +if globalEnv.has_key('apps'): + originalAppDirs = globalEnv['apps'] +else: + originalAppDirs = ':welcome' + +# clean rule used if no target: clean all +if len(targets) == 0: + pycFiles = [] + for file in os.listdir(toolsDir): + if file.endswith('.pyc'): + pycFiles.append(os.path.join(toolsDir,file)) + Clean('.',[binBase,genBase,sconsCache,pycFiles]) + +# the appDirs map contains associations between application URLs and real paths +# ex.: apps = :smews,myApp:myApplication,test +# will generate : +# / -> smews, myApp/ -> myApplication, test/ -> test +appDirs = originalAppDirs.split(',') +dirsMap = {} +for appDir in set(appDirs + [httpCodesDir]): + if appDir != '': + idx = appDir.find(':') + if idx != -1: + dirsMap[appDir[idx+1:]] = '/' + appDir[:idx] + else: + dirsMap[appDir] = '/' + appDir + +# association between web applicative resources and their final URLs +# appDir did only contain association of embedded applications +# here, we retrieve all the files of each application +sourcesMap = {} +for appDir in dirsMap.keys(): + appDirPath = os.path.join(appBase,appDir) + if not os.path.isdir(appDirPath): + Exit('Error: directory ' + appDirPath + ' does not exist') + appFiles = GenApps.getAppFiles(appDirPath) + for file in appFiles: + appSource = os.path.join(appBase,appDir,file) + sourcesMap[appSource] = os.path.join(dirsMap[appDir],file) + +# compilation options +globalEnv.Replace(CC = 'gcc') +globalEnv.Replace(AS = 'as') +globalEnv.Replace(AR = 'ar') +globalEnv.Append(CCFLAGS = '-Wall') +if sdump: + globalEnv.Append(CCFLAGS = '-DSTACK_DUMP') +if debug: + globalEnv.Append(CCFLAGS = '-O0 -g') +else: + globalEnv.Append(CCFLAGS = '-Os') +globalEnv.Append(CPPDEFINES = {'CHUNCKS_NBITS' : str(chuncksNbits)}) +for func in toDisable: + globalEnv.Append(CPPDEFINES = { disabledHash[func] : '1'}) +if endian: + if endian == 'little': + globalEnv.Append(CPPDEFINES = { 'ENDIANNESS' : 'LITTLE_ENDIAN'}) + if endian == 'big': + globalEnv.Append(CPPDEFINES = { 'ENDIANNESS' : 'BIG_ENDIAN'}) +sconsBasePath = os.path.abspath('.') + +# builds each target +for target in targets: + # target dependent directories / files + targetDir = os.path.join(targetBase,target) + driversDir = os.path.join(targetDir,'drivers') + binDir = os.path.join(binBase,target) + genDir = os.path.join(genBase,target) + elfFileName = os.path.join(binDir,elfName) + libFileName = os.path.join(binDir,libName) + + # target dependent compilation options + env = globalEnv.Clone() + env.Replace(CPPPATH = [coreDir,driversDir,genDir]) + + # required directories creation + if not env.GetOption('clean'): + for dir in [genBase,genDir,os.path.join(genDir,tmpBase)]: + if not os.path.isdir(dir): + os.mkdir(dir) + + # export variables for external SConscript files + Export('env libFileName elfFileName binDir coreDir driversDir genDir appBase toolsList chuncksNbits sourcesMap gzipped') + Export('env targetDir binDir projectName elfName') + Export('dirsMap sourcesMap target sconsBasePath httpCodesDir tmpBase') + # target dependent SConscript call + SConscript(os.path.join(targetDir,'SConscript'),build_dir = binDir,duplicate = 0) + # possible web applications SConscript calls + for appDir in dirsMap.keys(): + appSconsFile = os.path.join(appBase,appDir,'SConscript') + if os.path.isfile(appSconsFile): + ret = SConscript(appSconsFile) + sourcesMap.update(ret) + # main SConscript call + SConscript('SConscript') diff --git a/apps/calendar/cal_add.c b/apps/calendar/cal_add.c new file mode 100644 index 0000000000000000000000000000000000000000..1cf62f6c23e4de9dcc717b422984359024a675a0 --- /dev/null +++ b/apps/calendar/cal_add.c @@ -0,0 +1,77 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers doGet="doGet"/> + <properties persistence="persistent"/> + <args> + <arg name="id" type="uint8" /> + <arg name="field" type="str" size="31" /> + </args> +</generator> +*/ + +#include "cal_shared.h" + +static char doGet(struct args_t *args) { + if(args) { + unsigned char id = args->id; + if(id < MAX_EVENTS) { + uint16_t n = CONST_UI16(n_events); + char len = 0; + while(args->field[len]) { + len++; + } + if(n <= id) { + n = id + 1; + CONST_WRITE_NBYTES((void*)&n_events,(void*)&n,2); + } + CONST_WRITE_NBYTES((void*)events[id].message,(void*)args->field,len+1); + if(!len) { + unsigned char i; + len = -1; + for(i = 0; i<n ; i++) { + if(CONST_UI8(events[i].message[0])) { + len = i; + } + } + n = len + 1; + CONST_WRITE_NBYTES((void*)&n_events,(void*)&n,2); + } + } + } + return 1; +} diff --git a/apps/calendar/cal_get.c b/apps/calendar/cal_get.c new file mode 100644 index 0000000000000000000000000000000000000000..da5324ac5a612d8c880b28807c257f5f55cd18a3 --- /dev/null +++ b/apps/calendar/cal_get.c @@ -0,0 +1,73 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers doGet="doGet"/> + <properties persistence="idempotent"/> +</generator> +*/ + +#include "cal_shared.h" + +static CONST_VAR(unsigned char, str0[]) = "["; +static CONST_VAR(unsigned char, str1[]) = "\""; +static CONST_VAR(unsigned char, str2[]) = "\","; +static CONST_VAR(unsigned char, str3[]) = "]"; + +static void out_const_str(const unsigned char /*CONST_VAR*/ *str) { + const unsigned char *c = str; + unsigned char tmp; + while((tmp = CONST_READ_UI8(c++))!='\0') { + out_c(tmp); + } +} + +static char doGet(struct args_t *args) { + uint16_t i = 0; + uint16_t n = CONST_UI16(n_events); + + out_const_str(str0); + + for(i=0; i<n; i++) { + out_const_str(str1); + out_const_str(events[i].message); + out_const_str(str2); + } + + out_const_str(str3); + + return 1; +} diff --git a/apps/calendar/cal_shared.c b/apps/calendar/cal_shared.c new file mode 100644 index 0000000000000000000000000000000000000000..88fb50b4d29e9bd5453b75d8113ad0c1a0894848 --- /dev/null +++ b/apps/calendar/cal_shared.c @@ -0,0 +1,7 @@ +#include "cal_shared.h" + +PERSISTENT_VAR(struct event_t, events[MAX_EVENTS]) = { +}; + +PERSISTENT_VAR(uint16_t, n_events) = 0; + diff --git a/apps/calendar/cal_shared.h b/apps/calendar/cal_shared.h new file mode 100644 index 0000000000000000000000000000000000000000..bee254094ddffd47ec7a842d72df5b5ae1df4386 --- /dev/null +++ b/apps/calendar/cal_shared.h @@ -0,0 +1,12 @@ +#include "target.h" + +#define MAX_EVENTS 32 +#define FIELD_LENGTH 32 + +struct event_t { + unsigned char message[FIELD_LENGTH]; +}; + +extern PERSISTENT_VAR(struct event_t, events[MAX_EVENTS]); +extern PERSISTENT_VAR(uint16_t, n_events); + diff --git a/apps/calendar/index.html b/apps/calendar/index.html new file mode 100644 index 0000000000000000000000000000000000000000..f26517b7faf5ff52fe917f2f5ea2dc6a33aba6a5 --- /dev/null +++ b/apps/calendar/index.html @@ -0,0 +1,5 @@ +<html> +<head> +<meta http-equiv="refresh" content="0; url=http://www.google.com/calendar/"> +</head> +</html> diff --git a/apps/connectionsStats/index.html b/apps/connectionsStats/index.html new file mode 100644 index 0000000000000000000000000000000000000000..c4db714c11f7c3ecb920b6eef5b5701027721982 --- /dev/null +++ b/apps/connectionsStats/index.html @@ -0,0 +1,5 @@ +<html> +<head> +<meta HTTP-EQUIV="REFRESH" content="0; url=stats"> +</head> +</html> diff --git a/apps/connectionsStats/stats.c b/apps/connectionsStats/stats.c new file mode 100644 index 0000000000000000000000000000000000000000..9d37b48a317f2ea73a508b3a73a0529a3219513b --- /dev/null +++ b/apps/connectionsStats/stats.c @@ -0,0 +1,60 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers doGet="doGet"/> + <properties persistence="volatile"/> +</generator> +*/ + +#include "generators.h" +#include "connections.h" + +static char doGet(struct args_t *args) { + int cpt = 0; + FOR_EACH_CONN(conn, { + out_str("Connection: "); out_uint(cpt++); out_str("\n"); + out_str("\tport: "); out_uint(UI16(conn->port)); out_str("\n"); + out_str("\ttcp_state: "); out_uint(conn->tcp_state); out_str("\n"); + out_str("\toutput_handler: "); + if(conn->output_handler) + out_str("****\n"); + else + out_str("NULL\n"); + out_str("\tsomething to send: "); out_uint(something_to_send(conn)); out_str("\n"); + }) + return 1; +} diff --git a/apps/contactsBook/cb_add.c b/apps/contactsBook/cb_add.c new file mode 100755 index 0000000000000000000000000000000000000000..e788d9656dee9a76c15f5c9ef6f0a331a52d4b1a --- /dev/null +++ b/apps/contactsBook/cb_add.c @@ -0,0 +1,81 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers doGet="doGet"/> + <properties persistence="persistent"/> + <args> + <arg name="id" type="uint8" /> + <arg name="num" type="uint8" /> + <arg name="field" type="str" size="30" /> + </args> +</generator> +*/ + +#include "cb_shared.h" + +static char doGet(struct args_t *args) { + unsigned char id = 0; + uint16_t n = CONST_UI16(n_contacts); + if(args && args->num < 5) { + unsigned char len=0; + while(args->field[len]) { + len++; + } + id = args->id; + if(id >= n) { /* new contact */ + unsigned char i; + unsigned char zero = 0; + if(n == MAX_CONTACTS) + return 1; + id = n; + for(i=0; i<5 ; i++) + CONST_WRITE_NBYTES((void*)contacts[id].fields[i],&zero,1); + n++; + CONST_WRITE_NBYTES(&n_contacts,&n,2); + } + CONST_WRITE_NBYTES((void*)contacts[id].fields[args->num],(void*)args->field,len+1); + out_str(args->field); + } else { + if(n) { + n--; + CONST_WRITE_NBYTES(&n_contacts,&n,2); + } + out_uint(n); + } + return 1; +} + diff --git a/apps/contactsBook/cb_get.c b/apps/contactsBook/cb_get.c new file mode 100755 index 0000000000000000000000000000000000000000..e82d75c718887b4046cbf266d7bc783d6c69a387 --- /dev/null +++ b/apps/contactsBook/cb_get.c @@ -0,0 +1,89 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers doGet="doGet"/> + <properties persistence="idempotent"/> +</generator> +*/ + +#include "cb_shared.h" + +static CONST_VAR(unsigned char, fields_names[5][16]) = { + {"name"}, + {"email"}, + {"phone"}, + {"company"}, + {"address"}, +}; + +static CONST_VAR(unsigned char, str0[]) = "["; +static CONST_VAR(unsigned char, str1[]) = "{"; +static CONST_VAR(unsigned char, str2[]) = ":\""; +static CONST_VAR(unsigned char, str3[]) = "\","; +static CONST_VAR(unsigned char, str4[]) = "},"; +static CONST_VAR(unsigned char, str5[]) = "]"; + +static void out_const_str(const unsigned char /*CONST_VAR*/ *str) { + const unsigned char *c = str; + unsigned char tmp; + while((tmp = CONST_READ_UI8(c++))!='\0'){ + out_c(tmp); + } +} + +static char doGet(struct args_t *args) { + uint16_t i = 0; + uint16_t n = CONST_UI16(n_contacts); + + out_const_str(str0); + + for(i=0; i<n; i++) { + unsigned char j; + out_const_str(str1); + for(j=0; j<5; j++) { + out_const_str(fields_names[j]); + out_const_str(str2); + out_const_str(contacts[i].fields[j]); + out_const_str(str3); + } + out_const_str(str4); + } + + out_const_str(str5); + + return 1; +} diff --git a/apps/contactsBook/cb_shared.c b/apps/contactsBook/cb_shared.c new file mode 100644 index 0000000000000000000000000000000000000000..574c07dc51e402ee9619171baa9b7df9208f6bd8 --- /dev/null +++ b/apps/contactsBook/cb_shared.c @@ -0,0 +1,50 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "cb_shared.h" + +PERSISTENT_VAR(struct contact_t, contacts[MAX_CONTACTS]) = { + {"David%20Simplot-Ryl", "david.simplot-ryl@lifl.fr", "06 07 08 09 10", "POPS", "La Madeleine, 59"}, + {"Gilles%20Grimaud", "gilles.grimaud@lifl.fr", "06 07 08 09 11", "POPS", "Lille, 59"}, + {"Jean%20Carle", "jean.carle@lifl.fr", "06 07 08 09 12", "POPS", "La Madeleine, 59"}, + {"Michaël%20Hauspie", "michael.hauspie@lifl.fr", "06 07 08 09 13", "POPS", "Lille, 59"}, + {"Samuel%20Hym", "samuel.hym@lifl.fr", "06 07 08 09 14", "POPS", "Lille, 59"}, + {"Nathalie%20Mitton", "nathalie.mitton@lifl.fr", "06 07 08 09 15", "POPS", "Lille, 59"}, + {"Tahiry%20Razafindralambo", "tahiry.razafindralambo@lifl.fr", "06 07 08 09 16", "POPS", "Lille, 59"}, + {"Isabelle%20Simplot-Ryl", "isabelle.simplot-ryl@lifl.fr", "06 07 08 09 17", "POPS", "La Madeleine, 59"}, + {"Marie-Emilie%20Voge", "marie-emilie.voge@lifl.fr", "06 07 08 09 18", "POPS", "Lille, 59"}, +}; + +PERSISTENT_VAR(uint16_t, n_contacts) = 9; diff --git a/apps/contactsBook/cb_shared.h b/apps/contactsBook/cb_shared.h new file mode 100644 index 0000000000000000000000000000000000000000..6c4febea9a0aaff93d63bcf87da451c1dc1dd1e1 --- /dev/null +++ b/apps/contactsBook/cb_shared.h @@ -0,0 +1,51 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef _CB_SHARED_C_ +#define _CB_SHARED_C_ + +#include "target.h" + +#define MAX_CONTACTS 16 +#define FIELD_LENGTH 32 + +struct contact_t { + unsigned char fields[5][FIELD_LENGTH]; /* name, email, phone, company, address */ +}; + +extern PERSISTENT_VAR(struct contact_t, contacts[MAX_CONTACTS]); +extern PERSISTENT_VAR(uint16_t, n_contacts); + +#endif diff --git a/apps/contactsBook/index.html b/apps/contactsBook/index.html new file mode 100644 index 0000000000000000000000000000000000000000..222ced3e5294619c68af690ccb98c430549e4f61 --- /dev/null +++ b/apps/contactsBook/index.html @@ -0,0 +1,24 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + +<head> + <title>Contacts book manager</title> + <link rel="stylesheet" type="text/css" href="style.css" /> + <script language="Javascript" src="script.js"> </script> +</head> + +<body onload="init();"> + <a id="smewsLogo" href="http://www2.lifl.fr/~duquenno/Research/Smews/"><img src="/ressources/smews.jpg" alt="smews" title="" /></a> + <h1>Welcome to your personal contacts book manager</h1> + <table id="contactsTable"> + <tr> + <th>Name</th><th>E-mail</th><th>Phone</th><th>Company</th><th>Address</th> + </tr> + </table> + <div id="adddel"> + <span onclick="add();"> +</span><span onclick="del();"> -</span> + </div> +</body> + +</html> diff --git a/apps/contactsBook/sc.png b/apps/contactsBook/sc.png new file mode 100755 index 0000000000000000000000000000000000000000..61180f293525fd8d63b1d2bfcf24e3282060a72d Binary files /dev/null and b/apps/contactsBook/sc.png differ diff --git a/apps/contactsBook/script.js b/apps/contactsBook/script.js new file mode 100755 index 0000000000000000000000000000000000000000..42b0e1c7e70f2bb2ddfcfdfd3cf536f792d42c1d --- /dev/null +++ b/apps/contactsBook/script.js @@ -0,0 +1,138 @@ +var contactsBook = null; +var currSel = null; +var fields = ["name","email","phone","company","address"]; +var table = null; + +function add(){ + contactsBook.push({name: "",email: "",phone: "",company: "",address: ""}); + addTableLine(contactsBook.length-1); + ajaxGet("cb_add?id=" + (contactsBook.length-1) + "&num=0&field=",updateField,{i:contactsBook.length-1,j:0}); +} + +function del(){ + contactsBook.pop(); + var tr = document.getElementById("contact_" + contactsBook.length); + table.removeChild(tr); + ajaxGet("cb_add",null,null); +} + +function updateField(xhr,cell) { + if(xhr.readyState == 4 && xhr.status == 200) { + var cell = document.getElementById("td_" + cell.i + "_" + cell.j); + cell.className = "idleCell"; + if(xhr.responseText != "") + cell.innerHTML = unescape(xhr.responseText); + else + cell.innerHTML = " "; + addC = false; + } +} + +function setCellText(cell,cellValue) { + if(cellValue != "") { + var aText = document.createTextNode(cellValue); + cell.appendChild(aText); + } else { + cell.innerHTML = " "; + } +} + +function deSelectCell() { + if(currSel) { + var cell = document.getElementById("td_" + currSel.i + "_" + currSel.j); + var cellValue = cell.childNodes[0].value; + cell.removeChild((cell.childNodes[0])); + setCellText(cell,cellValue); + if(cellValue!=currSel.lastVal) { + cell.className = "busyCell"; + ajaxGet("cb_add?id=" + currSel.i + "&num=" + currSel.j + "&field=" + escape(cellValue),updateField,currSel); + } + currSel = null; + } +} + +function selectCell(i,j) { + if(!currSel || currSel.i != i|| currSel.j != j) { + deSelectCell(); + var cell = document.getElementById("td_" + i + "_" + j); + var anInput = document.createElement("input"); +// anInput.className = "fieldInput"; + anInput.style.width = "97%"; + anInput.type = "text"; + anInput.name = fields[j]; + if(cell.innerHTML != " ") + anInput.value = cell.innerHTML; + else + anInput.value = ""; + if(cell.hasChildNodes()) + cell.removeChild((cell.childNodes[0])); + cell.appendChild(anInput); + anInput.select(); + currSel = {i: i, j: j, lastVal: anInput.value}; + } +} + +function keyPressed(event) { + var key = event.keyCode; + if(key==13) { + deSelectCell(); + event.preventDefault(); + } else if(key==9) { + var i = currSel.i; + var j = currSel.j; + if(++j>=fields.length) { + j = 0; + if(++i>=contactsBook.length) + i = 0; + } + selectCell(i,j); + event.preventDefault(); + } +} + +function addTableLine(i) { + var tr = document.createElement("tr"); + tr.id = "contact_" + i; + table.appendChild(tr); + for (j in fields) { + var td = document.createElement("td"); + td.id = "td_" + i + "_" + j; + td.setAttribute("onClick","selectCell(" + i + "," + j + ");"); + td.setAttribute("onKeyDown","keyPressed(event);"); + var str = eval("contactsBook[i]." + fields[j]); + str = unescape(str); + setCellText(td,str); + tr.appendChild(td); + } +} + +function updateContacts() { + table = document.getElementById("contactsTable"); + for(var i in contactsBook) { + addTableLine(i); + } +} + +function initFields(xhr) { + if(xhr.readyState == 4 && xhr.status == 200) { + contactsBook = eval('(' + xhr.responseText + ')'); + updateContacts(); + } +} + +function ajaxGet(url,callBack,arg) { + var xhr; + var chart = this; + var xhrTimer; + try{ xhr = new XMLHttpRequest(); } + catch(e){ xhr = new ActiveXObject('Microsoft.XMLHTTP'); } + xhr.onreadystatechange = function(){ + if(callBack) callBack(xhr,arg); + }; + xhr.open("GET", url, true); + xhr.send(null); +} + +function init() { + ajaxGet('cb_get',initFields); +} diff --git a/apps/contactsBook/style.css b/apps/contactsBook/style.css new file mode 100755 index 0000000000000000000000000000000000000000..6ddb8657d8ffe1ec4c8c47b73558cdfc04619659 --- /dev/null +++ b/apps/contactsBook/style.css @@ -0,0 +1,19 @@ +body {fill: #333333; color: #333333; font-family: sans-serif; font-size: 12pt; } +h1 {text-align: center; font-weight: normal; font-size: 2em; } + +img { border: 0px; } +a { color: #000000; text-decoration: none; } +a:hover { color: #444466; text-decoration: underline; } + +#smewsLogo { display: block; text-align: center; } +#contactsTable { position: relative; margin: 0 auto; border: 3px solid #444466; border-collapse: collapse; } +#contactsTable td, #contactsTable th { padding: 5px; text-align: center; font-size: 0.9em; } +#contactsTable th { border: 3px solid #444466; } +#contactsTable td { border: 1px solid #666688; width: 10em; } +#contactsTable tr { height: 2.4em; } +#googleFrame { width: 450px; height: 250px; } +#googleLink { font-size: 0.8em; float: right; } +#smewsContact { position: absolute; background-color: #dddddd; padding: 6px; border: 2px solid black; } +.fieldInput { width: 97%; } +.busyCell { background-color: #bbffbb; } +#adddel { color: #444466; font-weight: bold; font-size: 18px; text-align: center; } diff --git a/apps/examples/demo1/hello.html b/apps/examples/demo1/hello.html new file mode 100755 index 0000000000000000000000000000000000000000..b0ae3dcc49ef33e153e9e506ce1d2475f7c0c2fa --- /dev/null +++ b/apps/examples/demo1/hello.html @@ -0,0 +1,8 @@ +<html> + <head> + <title>Hello World !</title> + </head> + <body> + Hello World ! + </body> +</html> diff --git a/apps/examples/demo2/demo.c b/apps/examples/demo2/demo.c new file mode 100755 index 0000000000000000000000000000000000000000..a700d68bbd1d14681a97f5d39d7e007c152fd8f6 --- /dev/null +++ b/apps/examples/demo2/demo.c @@ -0,0 +1,11 @@ +/* +<generator> + <handlers doGet="doGet"/> +</generator> +*/ + +/* simple contents generator */ +static char doGet(struct args_t *args) { + out_str("Generated Hello World ! "); + return 1; +} diff --git a/apps/examples/demo3/demo.c b/apps/examples/demo3/demo.c new file mode 100755 index 0000000000000000000000000000000000000000..2fe0e36672de4f90ee0fd52867344aaab876a0b1 --- /dev/null +++ b/apps/examples/demo3/demo.c @@ -0,0 +1,12 @@ +/* +<generator> + <handlers doGet="doGet"/> + <properties persistence="volatile"/> +</generator> +*/ + +/* generator possible properties are persistent (by default), idempotent and volatile */ +static char doGet(struct args_t *args) { + out_str("Volatile Hello World ! "); + return 1; +} diff --git a/apps/examples/demo4/demo.c b/apps/examples/demo4/demo.c new file mode 100644 index 0000000000000000000000000000000000000000..8a1ea2f8a2ef77263256cf194297954b59c496aa --- /dev/null +++ b/apps/examples/demo4/demo.c @@ -0,0 +1,26 @@ +/* +<generator> + <handlers doGet="doGet"/> + <args> + <arg name="i1" type="uint8" /> + <arg name="s" type="str" size="6" /> + <arg name="i2" type="uint16" /> + </args> +</generator> +*/ + +#include "generators.h" + +static char doGet(struct args_t *args) { + if(args) { + out_str("first int : "); + out_uint(args->i1); + out_str("\nstr : "); + out_str(args->s); + out_str("\nsecond int : "); + out_uint(args->i2); + } else { + out_str("no args"); + } + return 1; +} diff --git a/apps/examples/demo5/demo.c b/apps/examples/demo5/demo.c new file mode 100755 index 0000000000000000000000000000000000000000..50a277828fe9c9fc7386d105a21c3f20a9c5b194 --- /dev/null +++ b/apps/examples/demo5/demo.c @@ -0,0 +1,26 @@ +/* +<generator> + <handlers doGet="doGet"/> + <properties persistence="volatile"/> + <args> + <arg name="val" type="uint16" /> + </args> +</generator> +*/ + +#include "channels.h" + +uint16_t val; + +/* triggers the knockknock comet channel */ +static char doGet(struct args_t *args) { + if(args) { + val = args->val; + server_push(&knockknock); + out_str("knock knock: "); + out_uint(val); + } else { + out_str("no args"); + } + return 1; +} diff --git a/apps/examples/demo5/myChannel.c b/apps/examples/demo5/myChannel.c new file mode 100755 index 0000000000000000000000000000000000000000..b890b40a90427f7469359defb4ab2b40d3610906 --- /dev/null +++ b/apps/examples/demo5/myChannel.c @@ -0,0 +1,20 @@ +/* +<generator> + <handlers initGet="initGet" doGet="doGet"/> + <properties persistence="volatile" interaction="alert" channel="knockknock"/> +</generator> +*/ + +extern uint16_t val; + +/* launched when the GET request is received */ +static char initGet(struct args_t *args) { + return 1; +} + +/* launched when knockknock is triggered */ +static char doGet(struct args_t *args) { + out_str("somebody knocked: "); + out_uint(val); + return 1; +} diff --git a/apps/examples/demo6/demo.c b/apps/examples/demo6/demo.c new file mode 100644 index 0000000000000000000000000000000000000000..f56f53552bfb1e1b368be66a0c76bf03f2047442 --- /dev/null +++ b/apps/examples/demo6/demo.c @@ -0,0 +1,27 @@ +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile" interaction="stream" channel="myStreamedComet"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +/* timer callback function */ +static void timer() { + /* triggers the channel */ + server_push(&myStreamedComet); +} + +static char init(void) { + /* initilize a timer with a period of 1000 milliseconds */ + return set_timer(&timer,1000); +} + +static char doGet(struct args_t *args) { + /* outputs the current time in milliseconds */ + out_uint(TIME_MILLIS); + return 1; +} diff --git a/apps/gba/padComet/funcs.js b/apps/gba/padComet/funcs.js new file mode 100644 index 0000000000000000000000000000000000000000..2a8efcb51978dc1f643ed55da38cafe445d93f6f --- /dev/null +++ b/apps/gba/padComet/funcs.js @@ -0,0 +1,73 @@ +function getColor(on){ + return on?"green":"red"; +} + +function getCell(id){ + return document.getElementById(id); +} + +function styleOf(id){ + return document.getElementById(id).style; +} + +function setUp(on){ + styleOf("up").borderBottomColor=getColor(on); + getCell("tup").innerHTML=1-on; +} + +function setDown(on){ + styleOf("down").borderTopColor=getColor(on); + getCell("tdown").innerHTML=1-on; +} + +function setLeft(on){ + styleOf("left").borderRightColor=getColor(on); + getCell("tleft").innerHTML=1-on; +} + +function setRight(on){ + styleOf("right").borderLeftColor=getColor(on); + getCell("tright").innerHTML=1-on; +} + +function setA(on){ + styleOf("btnA").backgroundColor=getColor(on); + getCell("tA").innerHTML=1-on; +} + +function setB(on){ + styleOf("btnB").backgroundColor=getColor(on); + getCell("tB").innerHTML=1-on; +} + +function ajaxCallback(ajaxRet){ + document.getElementById("sample").innerHTML="Sample: " + ajaxRet; + if(ajaxRet != "") { + setA(ajaxRet & 1); + setB((ajaxRet & 2) >> 1); + setRight((ajaxRet & 4) >> 2); + setLeft((ajaxRet & 8) >> 3); + setUp((ajaxRet & 16) >> 4); + setDown((ajaxRet & 32) >> 5); + } + run() +} + +function run(){ + ajaxGet("pushPad"); +} + +function ajaxGet(url) { + var xhr; + try{ xhr = new XMLHttpRequest(); } + catch(e){ xhr = new ActiveXObject('Microsoft.XMLHTTP'); } + + xhr.onreadystatechange = function(){ + if(xhr.readyState == 4){ + if(ajaxRet=xhr.status==200) + ajaxCallback(xhr.responseText); + } + }; + xhr.open("GET", url, true); + xhr.send(null); +} diff --git a/apps/gba/padComet/index.html b/apps/gba/padComet/index.html new file mode 100644 index 0000000000000000000000000000000000000000..9ed98f5bbc93dec98d9a0965e1c038497bf221fb --- /dev/null +++ b/apps/gba/padComet/index.html @@ -0,0 +1,71 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html> +<head> +<title>AGB Pad served by dynWeb</title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<style type="text/css"> + BODY{ + font-family : sans-serif; + } + .triangle{ + position:absolute; + width:0; + height:0; + border:20px solid white; + } + .button{ + display:inline; + position:absolute; + width:50px; + height:50px; + text-align:center; + + } +</style> +<script src="funcs.js" type="text/javascript"></script> +</head> + +<body> +<!-- Up triangle --> +<div id="up" class="triangle" style="top:0px;left:50px;border-bottom-color:green;"></div> +<!-- Down triangle --> +<div id="down" class="triangle" style="top:100px;left:50px;border-top-color:green;"></div> +<!-- Left triangle --> +<div id="left" class="triangle" style="top:50px;left:0px;border-right-color:green;"></div> +<!-- Right triangle --> +<div id="right" class="triangle" style="top:50px;left:100px;border-left-color:green;"></div> +<!-- B button --> +<div id="btnB" class="button" style="top:50px;left:200px;background-color:green;"><br/>B</div> +<!-- A button --> +<div id="btnA" class="button" style="top:50px;left:300px;background-color:green;"><br/>A</div> + +<div id="sample" style="position:absolute;top:150px;left:30px;"></div> + +<div style="position:absolute;top:30px;left:450px;"> +<table border> +<tr> + <td width="80">Left</td><td id=tleft width="10"></td> +</tr> +<tr> + <td>Up</td><td id=tup></td> +</tr> +<tr> + <td>Right</td><td id=tright></td> +</tr> +<tr> + <td>Down</td><td id=tdown></td> +</tr> +<tr> + <td>A</td><td id=tA></td> +</tr> +<tr> + <td>B</td><td id=tB></td> +</tr> +</table> +</div> + +<script language="javascript"> +run(); +</script> +</body> +</html> diff --git a/apps/gba/padComet/pushPad.c b/apps/gba/padComet/pushPad.c new file mode 100644 index 0000000000000000000000000000000000000000..dca9a395b281db546d6d33a6178c5e66a2a88702 --- /dev/null +++ b/apps/gba/padComet/pushPad.c @@ -0,0 +1,69 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" initGet="initGet" doGet="doGet"/> + <properties persistence="volatile" interaction="alert" channel="padChannel"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +#define REG_KEY (*(volatile unsigned short *) 0x4000130) + +static uint16_t pushed_keys; +static uint16_t glob_keys; + +static void timer() { + uint16_t keys = (REG_KEY & 0x00f0) >> 2; + keys |= REG_KEY & 0x0003; + if(keys != pushed_keys) { + glob_keys = keys; + server_push(&padChannel); + } +} + +static char init(void) { + return set_timer(&timer,10); +} + +static char initGet(struct args_t *args) { + out_uint(glob_keys); + pushed_keys = glob_keys; + return 1; +} diff --git a/apps/gba/padPoll/funcs.js b/apps/gba/padPoll/funcs.js new file mode 100644 index 0000000000000000000000000000000000000000..917af2fd602f59b7a26dcd11f2f197071e8fbf3b --- /dev/null +++ b/apps/gba/padPoll/funcs.js @@ -0,0 +1,103 @@ +var freq = 8; +var inFlight = 0; + +function plusMinus(arg){ + if(arg == 1) { + freq++; + if(freq == 1) { + inFlight = 0; + run(); + } + } else if(arg == -1) { + if(freq > 0) + freq--; + } + document.getElementById("frequency").innerHTML="Frequency: " + freq + " / s"; +} + +function getColor(on){ + return on?"green":"red"; +} + +function getCell(id){ + return document.getElementById(id); +} + +function styleOf(id){ + return document.getElementById(id).style; +} + +function setUp(on){ + styleOf("up").borderBottomColor=getColor(on); + getCell("tup").innerHTML=1-on; +} + +function setDown(on){ + styleOf("down").borderTopColor=getColor(on); + getCell("tdown").innerHTML=1-on; +} + +function setLeft(on){ + styleOf("left").borderRightColor=getColor(on); + getCell("tleft").innerHTML=1-on; +} + +function setRight(on){ + styleOf("right").borderLeftColor=getColor(on); + getCell("tright").innerHTML=1-on; +} + +function setA(on){ + styleOf("btnA").backgroundColor=getColor(on); + getCell("tA").innerHTML=1-on; +} + +function setB(on){ + styleOf("btnB").backgroundColor=getColor(on); + getCell("tB").innerHTML=1-on; +} + +function ajaxGet(url) { + var xhr; + var xhrTimer; + try{ xhr = new XMLHttpRequest(); } + catch(e){ xhr = new ActiveXObject('Microsoft.XMLHTTP'); } + + xhr.onreadystatechange = function(){ + chart.sampleCallBack(xhr,xhrTimer); + }; + xhr.open("GET", url, true); + xhrTimer = setTimeout(function() { xhr.abort(); this.inFlight = 0;}, 1000); + xhr.send(null); +} + +function ajaxCallback(xhr,xhrTimer){ + if(xhr.readyState == 4) { + inFlight = 0; + if(xhr.status == 200 && xhr.responseText != "" && this.started) { + document.getElementById("sample").innerHTML="Sample: " + ajaxRet; + setA(ajaxRet & 1); + setB((ajaxRet & 2) >> 1); + setRight((ajaxRet & 4) >> 2); + setLeft((ajaxRet & 8) >> 3); + setUp((ajaxRet & 16) >> 4); + setDown((ajaxRet & 32) >> 5); + } + clearTimeout(xhrTimer); + } +} + +function run(){ + if(freq == 0) { + document.getElementById("alert").innerHTML=""; + return; + } + setTimeout("run()",1000 / freq); + if(inFlight == 1) { + document.getElementById("alert").innerHTML="<font color=\"red\">To high frequency</font>"; + return; + } + document.getElementById("alert").innerHTML=""; + inFlight = 1; + ajaxGet("getPad"); +} diff --git a/apps/gba/padPoll/getPad.c b/apps/gba/padPoll/getPad.c new file mode 100644 index 0000000000000000000000000000000000000000..23ddfab1bdf84b19ad9e7237abfdcae3f11a7add --- /dev/null +++ b/apps/gba/padPoll/getPad.c @@ -0,0 +1,54 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers doGet="doGet"/> + <properties persistence="volatile"/> +</generator> +*/ + +#include "generators.h" + +#define REG_KEY (*(volatile unsigned short *) 0x4000130) + +static char doGet(struct args_t *args) { + uint16_t keys = (REG_KEY & 0x00f0) >> 2; + keys |= REG_KEY & 0x0003; + + out_uint(keys); + + return 1; +} diff --git a/apps/gba/padPoll/index.html b/apps/gba/padPoll/index.html new file mode 100644 index 0000000000000000000000000000000000000000..748f00d39fcefbc3416996024b610231d6eb0316 --- /dev/null +++ b/apps/gba/padPoll/index.html @@ -0,0 +1,80 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html> +<head> +<title>AGB Pad served by dynWeb</title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<style type="text/css"> + BODY{ + font-family : sans-serif; + } + .triangle{ + position:absolute; + width:0; + height:0; + border:20px solid white; + } + .button{ + display:inline; + position:absolute; + width:50px; + height:50px; + text-align:center; + + } +</style> +<script src="funcs.js" type="text/javascript"></script> +</head> + +<body> +<!-- Up triangle --> +<div id="up" class="triangle" style="top:0px;left:50px;border-bottom-color:green;"></div> +<!-- Down triangle --> +<div id="down" class="triangle" style="top:100px;left:50px;border-top-color:green;"></div> +<!-- Left triangle --> +<div id="left" class="triangle" style="top:50px;left:0px;border-right-color:green;"></div> +<!-- Right triangle --> +<div id="right" class="triangle" style="top:50px;left:100px;border-left-color:green;"></div> +<!-- B button --> +<div id="btnB" class="button" style="top:50px;left:200px;background-color:green;"><br/>B</div> +<!-- A button --> +<div id="btnA" class="button" style="top:50px;left:300px;background-color:green;"><br/>A</div> + +<div id="sample" style="position:absolute;top:150px;left:30px;"></div> +<div id="frequency" style="position:absolute;top:170px;left:30px;"></div> +<div id="info" style="position:absolute;top:170px;left:180px;"> +<form method="get" name="ajax" action=""> + <input type="button" name="plus" value="+" onmousedown="plusMinus(1)" onmouseup="plusMinus(0)"> + <input type="button" name="minux" value="-" onmousedown="plusMinus(-1)" onmouseup="plusMinus(0)"> +</form> +</div> +<div id="alert" style="position:absolute;top:190px;left:30px;"></div> + +<div style="position:absolute;top:30px;left:450px;"> +<table border> +<tr> + <td width="80">Left</td><td id=tleft width="10"></td> +</tr> +<tr> + <td>Up</td><td id=tup></td> +</tr> +<tr> + <td>Right</td><td id=tright></td> +</tr> +<tr> + <td>Down</td><td id=tdown></td> +</tr> +<tr> + <td>A</td><td id=tA></td> +</tr> +<tr> + <td>B</td><td id=tB></td> +</tr> +</table> +</div> + +<script language="javascript"> +plusMinus(0); +run(); +</script> +</body> +</html> diff --git a/apps/gba/padPoll/not_found.html b/apps/gba/padPoll/not_found.html new file mode 100644 index 0000000000000000000000000000000000000000..159b8eb55807dfa64cf6ae34159c14842f1ff0b9 --- /dev/null +++ b/apps/gba/padPoll/not_found.html @@ -0,0 +1,7 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html> +<head/> +<title>Error 404: File not found</title> +Error 404: File not found +</body> +</html> diff --git a/apps/httpCodes/404.html b/apps/httpCodes/404.html new file mode 100644 index 0000000000000000000000000000000000000000..f270d7b1944a7fcd1e58f164d58cc937b20856bb --- /dev/null +++ b/apps/httpCodes/404.html @@ -0,0 +1,9 @@ +<html> +<head> +<meta http-equiv="content-type" content="text/html;charset=utf-8"> +<title>404 Not Found</title> +</head> +<body> +<H2>Error 404: Page not found</H2> +</body> +</html> diff --git a/apps/linux/cpuComet/ajaxLoader.gif b/apps/linux/cpuComet/ajaxLoader.gif new file mode 100644 index 0000000000000000000000000000000000000000..f2a1bc0c6f545e20e631a96e8e92f9822e75d046 Binary files /dev/null and b/apps/linux/cpuComet/ajaxLoader.gif differ diff --git a/apps/linux/cpuComet/comet_cpu.c b/apps/linux/cpuComet/comet_cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..84bdf3e458ac6c56df063bca2af6c791e627ebd2 --- /dev/null +++ b/apps/linux/cpuComet/comet_cpu.c @@ -0,0 +1,90 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" initGet="initGet" doGet="doGet"/> + <properties persitence="volatile" channel="cpuChannel"/> + <args> + <arg name="thres" type="uint16" /> + </args> +</generator> +*/ + +#include <stdio.h> + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +static uint16_t glob_load; +static int last_sum; +static int last_idle; +static int threshold = 512; + +static void timer() { + char tmp[32]; + int i1,i2,i3,i5,i6,i7,i8,idle; + int sum; + float ratio; + FILE *in = fopen("/proc/stat","r"); + fscanf(in, "%32s %d %d %d %d %d %d %d %d",tmp, &i1, &i2, &i3, &idle, &i5, &i6, &i7, &i8); + fclose(in); + sum = idle + i1 + i2 + i3 + i5 + i6 + i7 + i8; + if(sum != last_sum) { + ratio = 1024 * (1 - ((idle - last_idle) / (float)(sum - last_sum))); + last_sum = sum; + last_idle = idle; + if(ratio > threshold) { + glob_load = (uint16_t)ratio; + server_push(&cpuChannel); + } + } +} + +static char init(void) { + return set_timer(&timer,500); +} + +static char initGet(struct args_t *args) { + if(args) + threshold = args->thres; + return 1; +} + +static char doGet(struct args_t *args) { + out_uint(glob_load); + return 1; +} diff --git a/apps/linux/cpuComet/funcs.js b/apps/linux/cpuComet/funcs.js new file mode 100644 index 0000000000000000000000000000000000000000..34a271706d9e7b82ce12024c0a9270c586026d3f --- /dev/null +++ b/apps/linux/cpuComet/funcs.js @@ -0,0 +1,59 @@ +var ajaxTarget = 'comet_cpu'; + +function init(){ + document.getElementById("loader").style.visibility = "hidden"; +} + +function ajaxCallback(status,text){ + document.getElementById("loader").style.visibility = "hidden"; + document.getElementById("launch").style.visibility = "visible"; + if(status == 200 && text != "") { + text = parseInt(text/10.24); + document.getElementById("alert").innerHTML="CPU Usage: " + text + " %"; + } +} + +function run(){ + document.getElementById("loader").style.visibility = "visible"; + document.getElementById("launch").style.visibility = "hidden"; + document.getElementById("alert").innerHTML = ""; + threshold = Number(document.getElementById("htmlThres").value); + if(isNaN(threshold)) + threshold = 50; + threshold = parseInt(10.24 * threshold); + + doAjax(ajaxTarget+"?thres="+threshold,ajaxCallback,0,0); +} + +function doAjax(ajaxTarget,ajaxCallBack,timeout,timeoutCallBack){ + var xhr; + var xhrTimer; + try{ xhr = new XMLHttpRequest(); } + catch(e){ xhr = new ActiveXObject('Microsoft.XMLHTTP'); } + xhr.onreadystatechange = function(){ + if(xhr.readyState == 4) { + ajaxCallBack(xhr.status,xhr.responseText); + if(timeout > 0) + clearTimeout(xhrTimer); + } + }; + xhr.open("GET", ajaxTarget, true); + if(timeout > 0) + xhrTimer = setTimeout(function() { xhr.abort(); timeoutCallBack();}, timeout); + xhr.send(null); +} + +function ajaxGet(url) { + var xhr; + try{ xhr = new XMLHttpRequest(); } + catch(e){ xhr = new ActiveXObject('Microsoft.XMLHTTP'); } + + xhr.onreadystatechange = function(){ + if(xhr.readyState == 4){ + if(ajaxRet=xhr.status==200) + ajaxCallback(xhr.responseText); + } + }; + xhr.open("GET", url, true); + xhr.send(null); +} diff --git a/apps/linux/cpuComet/index.html b/apps/linux/cpuComet/index.html new file mode 100644 index 0000000000000000000000000000000000000000..778fbf3cb6d31df0538369d7131b9a45897b56e6 --- /dev/null +++ b/apps/linux/cpuComet/index.html @@ -0,0 +1,22 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + <head> + <script language="Javascript" src="funcs.js"></script> + <link rel="stylesheet" type="text/css" href="style.css" /> + </head> + +<body onload="init();"> + <div id="main"> + <a id="smewsLogo" href="http://www2.lifl.fr/~duquenno/Research/Smews/"><img src="/ressources/smews.jpg" alt="smews" title="" /></a> + <h1>CPU usage alert</h1> + <div id="infos"> + Threshold: <input id="htmlThres" value="50"></input> % <br /> + <input id="launch" type="button" value="Launch !" onclick="run()"> + <img id="loader" src="ajaxLoader.gif" /> + <div id="alert"></div> + </div> + </div> +</body> +</html> diff --git a/apps/linux/cpuComet/style.css b/apps/linux/cpuComet/style.css new file mode 100644 index 0000000000000000000000000000000000000000..7e6e5e7cd479723a933dc04f7955f5a8975c8911 --- /dev/null +++ b/apps/linux/cpuComet/style.css @@ -0,0 +1,14 @@ +#main {position: relative; margin: 0 auto;} + +body, svg, input {fill: #333333; color: #333333; font-family: sans-serif; } +body {font-size: 12pt;} + +h1 {text-align: center; font-weight: normal; font-size: 2em; } +img { border: 0px; } +#smewsLogo { display: block; text-align: center; } + +#main {width: 800px;} +#infos{text-align: center;} +#loader{position: relative; left: -2.7em;} +#htmlThres {text-align: center; width: 2em; padding: 0px; margin: 0px; font-size: 0.9em;} +#launch {text-align: center; width: 5em; padding: 0em; margin: 0.5em; font-size: 0.9em;} diff --git a/apps/linux/cpuPoll/CPUSample.c b/apps/linux/cpuPoll/CPUSample.c new file mode 100644 index 0000000000000000000000000000000000000000..48ccb2b06efffbbb19bc7853504f301f2cd9a687 --- /dev/null +++ b/apps/linux/cpuPoll/CPUSample.c @@ -0,0 +1,66 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers doGet="doGet"/> + <properties persistence="volatile"/> +</generator> +*/ + + +#include <stdio.h> +#include "generators.h" + +static int last_sum; +static int last_idle; + +static char doGet(struct args_t *args) { + char tmp[32]; + int i1,i2,i3,i5,i6,i7,i8,idle; + int sum; + float ratio; + FILE *in = fopen("/proc/stat","r"); + fscanf(in, "%32s %d %d %d %d %d %d %d %d",tmp, &i1, &i2, &i3, &idle, &i5, &i6, &i7, &i8); + fclose(in); + sum = idle + i1 + i2 + i3 + i5 + i6 + i7 + i8; + if(sum != last_sum) { + ratio = 1 - ((idle - last_idle) / (float)(sum - last_sum)); + last_sum = sum; + last_idle = idle; + } + out_uint(1024 * ratio); + return 1; +} diff --git a/apps/linux/cpuPoll/ajaxLoader.gif b/apps/linux/cpuPoll/ajaxLoader.gif new file mode 100644 index 0000000000000000000000000000000000000000..f2a1bc0c6f545e20e631a96e8e92f9822e75d046 Binary files /dev/null and b/apps/linux/cpuPoll/ajaxLoader.gif differ diff --git a/apps/linux/cpuPoll/chart.svg b/apps/linux/cpuPoll/chart.svg new file mode 100644 index 0000000000000000000000000000000000000000..da99aa6cdd0279005cdda4dd13570dc188d47251 --- /dev/null +++ b/apps/linux/cpuPoll/chart.svg @@ -0,0 +1,120 @@ +<?xml-stylesheet href="style.css" type="text/css"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800" height="260" onload="init(evt)"> +<script><![CDATA[ + +var svgns="http://www.w3.org/2000/svg"; +var ownDoc; +var node; +var circles = new Array(); + +var width=800; +var height=260; +var chartWidth = width - 80 - 20; +var chartHeight = height - 80; +var chartDuration = 60; + +function nodeSet(a,b) { + node.setAttributeNS(null,a,b); +} + +function init(evt) { + ownDoc=evt.target.ownerDocument; +} + +function drawCircle(x,y,r,class) { + node=ownDoc.createElementNS(svgns,"circle"); + nodeSet("cx",x); + nodeSet("cy",y); + nodeSet("r",r); + nodeSet("class",class); + ownDoc.documentElement.appendChild(node); +} + +function drawRect(x,y,w,h,class) { + node=ownDoc.createElementNS(svgns,"rect"); + nodeSet("x",x); + nodeSet("y",y); + nodeSet("width",w); + nodeSet("height",h); + nodeSet("class",class); + ownDoc.documentElement.appendChild(node); +} + +function drawLine(x,y,x2,y2,class) { + node=ownDoc.createElementNS(svgns ,"path"); + nodeSet("d","M" + x + " " + y + " L" + x2 + " " + y2); + nodeSet("class",class); + ownDoc.documentElement.appendChild(node); +} + +function drawText(root,x,y,text,anchor,class) { + tmpText=ownDoc.createTextNode(text); + node=ownDoc.createElementNS(svgns ,"text"); + nodeSet("x",x); + nodeSet("y",y); + nodeSet("text-anchor",anchor); + nodeSet("class",class); + node.appendChild(tmpText); + root.appendChild(node); +} + +function drawTextD(x,y,text,anchor,class) { + drawText(ownDoc.documentElement,x,y,text,anchor,class); +} + +function draw(yAxisName) { + drawRect(20 + 40,40,chartWidth,chartHeight,"back"); + drawTextD(-(height/2 + 40),20,yAxisName,"left","yAxisName"); + nodeSet("transform","rotate(-90)"); + drawTextD(20 + 20 + (chartWidth / 2),height,"time (s)","left","xAxisName"); + for(y=0;y<=100;y+=20){ + drawLine(20+40,height-40-y*(chartHeight/100),20 + chartWidth + 40,height-40-y*(chartHeight/100),"line"); + drawTextD(20+40-10,height-40-y*(chartHeight/100),y,"end","yTick"); + } + xAxis=ownDoc.createElementNS(svgns ,"g"); + ownDoc.documentElement.appendChild(xAxis); + for(x=0;x<=chartDuration;x+=10){ + drawLine(20+40 + x/chartDuration*(chartWidth),height-40,20+40 + x/chartDuration*(chartWidth),40,"line"); + drawText(xAxis,20+40 + x/chartDuration*(chartWidth),height-40+20,x,"middle","xTick"); + } + drawLine(20+40,40-1,20+40,height-40,"axis"); + drawLine(20+40+chartWidth,40-1,20+40+chartWidth,height-40,"axis"); + drawLine(20 + 40,height-40,20 + chartWidth + 40,height-40,"axis"); + drawLine(20 + 40,40,20 + chartWidth + 40,40,"axis"); + + node=ownDoc.createElementNS(svgns ,"path"); + nodeSet("id","samplesPath"); + nodeSet("d",""); + nodeSet("class","plot"); + nodeSet("fill","none"); + ownDoc.documentElement.appendChild(node); +} + +function drawSamples(firstPlutIsTrunked,samples) { + while(circles.length > 0) + ownDoc.documentElement.removeChild(circles.pop()); + circles = new Array(); + var tmpPath = ""; + var x = 0; + for(i=0;i<samples.length;i++){ + if(i > 0) + x += samples[i][0]/1000; + px = 20 + 40 + x * (chartWidth/chartDuration); + py = height-40-(samples[i][1]*(chartHeight/100)); + if(i==0) + tmpPath += "M"; + else + tmpPath += " L"; + tmpPath += px + " " + py; + if(firstPlutIsTrunked == 0 || i > 0) { + drawCircle(px,py,0.1,"plotCircle"); + circles.push(node); + } + } + nodeSet("class","lastPlotCircle"); + ownDoc.getElementById("samplesPath").setAttributeNS(null, "d", tmpPath); +} + +]]></script> + +</svg> diff --git a/apps/linux/cpuPoll/funcs.js b/apps/linux/cpuPoll/funcs.js new file mode 100644 index 0000000000000000000000000000000000000000..7d36acf58d3e8a4f9839cce276562446c0e9cf2c --- /dev/null +++ b/apps/linux/cpuPoll/funcs.js @@ -0,0 +1,103 @@ +var ajaxTarget = 'CPUSample'; +var svgWin; +var samples; +var pollInterval; +var inFlight; +var lastTime = new Date().getTime(); + +//~ currVal = 512; +function doAjax(ajaxTarget,ajaxCallBack,timeout,timeoutCallBack){ + var xhr; + var xhrTimer; + try{ xhr = new XMLHttpRequest(); } + catch(e){ xhr = new ActiveXObject('Microsoft.XMLHTTP'); } + xhr.onreadystatechange = function(){ + if(xhr.readyState == 4) { + ajaxCallBack(xhr.status,xhr.responseText); + if(timeout > 0) + clearTimeout(xhrTimer); + } + }; + xhr.open("GET", ajaxTarget, true); + if(timeout > 0) + xhrTimer = setTimeout(function() { xhr.abort(); timeoutCallBack();}, timeout); + xhr.send(null); +//~ currVal += 100 * (0.5 - Math.random()); +//~ currVal = Math.min(currVal,1024); +//~ currVal = Math.max(currVal,0); +//~ setTimeout(function() { ajaxCallBack(200,currVal); },100) +} + +function sampleTimeout(){ + inFlight = 0; + document.getElementById("loader").style.visibility = "hidden"; +} + +function sampleCallBack(status,text){ + inFlight = 0; + setTimeout(function() { if(inFlight == 0) document.getElementById("loader").style.visibility = "hidden"; }, 10); + if(status == 200 && text != "") + newSample(text/10.24); +} + +function newSample(val){ + newTime = new Date().getTime(); + chartDuration = 0; + maxDuration = svgWin.chartDuration * 1000; + toRemove = 0; + firstPlotIsTrunked = 0; + samples.push([newTime-lastTime,val]); + lastTime = newTime; + for(i=samples.length-1;i>=1;i--) { + if(chartDuration < maxDuration) { + chartDuration += samples[i][0]; + if(chartDuration > maxDuration) { + overLap = chartDuration - maxDuration; + interval = samples[i][0]; + newInterval = interval - overLap; + plotVal = samples[i][1]; + prevVal = samples[i-1][1]; + newVal = (prevVal * newInterval + plotVal * (overLap)) / interval; + samples[i-1][1] = newVal; + samples[i][0] = newInterval; + chartDuration = maxDuration; + firstPlotIsTrunked = 1; + } + } + if (chartDuration == maxDuration) { + toRemove = i - 1; + break; + } + } + for(i=0;i<toRemove;i++) + samples.shift(); + svgWin.drawSamples(firstPlotIsTrunked,samples); +} + +function setPollInterval(arg){ + argVal = Number(arg); + if(isNaN(argVal)) { + argVal = pollInterval; + } + pollInterval = argVal; + document.getElementById("htmlInterval").value = pollInterval; +} + +function onTimer(){ + setTimeout(onTimer,pollInterval); + if(inFlight == 0) { + inFlight = 1; + document.getElementById("loader").style.visibility = "visible"; + doAjax(ajaxTarget,sampleCallBack,1000,sampleTimeout); + } +} + +function init(){ + svgObject = document.getElementById("svgDoc0"); + svgWin = svgObject.contentDocument.defaultView; + svgWin.draw('CPU usage (%)'); + samples = new Array(); + setPollInterval(1000); + inFlight = 0; + onTimer(); +} diff --git a/apps/linux/cpuPoll/index.html b/apps/linux/cpuPoll/index.html new file mode 100644 index 0000000000000000000000000000000000000000..02eb69a8c24816f06b91d6603f622370dede7e78 --- /dev/null +++ b/apps/linux/cpuPoll/index.html @@ -0,0 +1,23 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + <head> + <script language="Javascript" src="funcs.js"></script> + <link rel="stylesheet" type="text/css" href="style.css" /> + </head> + +<body onload="init();"> + <div id="main"> + <a id="smewsLogo" href="http://www2.lifl.fr/~duquenno/Research/Smews/"><img src="/ressources/smews.jpg" alt="smews" title="" /></a> + <h1>Current CPU usage</h1> + <div id="infos"> + <img id="loader" src="ajaxLoader.gif" /> + Polling interval: <input id="htmlInterval" onKeyUp="setPollInterval(this.value);"></input> ms + </div> + <div id="svgDoc"> + <object id="svgDoc0" type="image/svg+xml" data="chart.svg" width="800" height="260" /> + </div> + </div> +</body> +</html> diff --git a/apps/linux/cpuPoll/style.css b/apps/linux/cpuPoll/style.css new file mode 100644 index 0000000000000000000000000000000000000000..357c3666d0bfdabf7d8c0dcfdaa5d77ee1dcbda7 --- /dev/null +++ b/apps/linux/cpuPoll/style.css @@ -0,0 +1,19 @@ +#main {position: relative; margin: 0 auto;} + +body, svg, input {fill: #333333; color: #333333; font-family: sans-serif; } +body {font-size: 12pt;} + +h1 {text-align: center; font-weight: normal; font-size: 2em; } +img { border: 0px; } +#smewsLogo { display: block; text-align: center; } + +.xTick, .yTick {font-size:1em;} +.back {fill: #ffffff} +.axis {stroke: #214478; stroke-width: 1.3pt;} +.line {stroke: #214478; stroke-width: 0.3pt;} +.plot {stroke: #5da666; stroke-width: 1.5pt;} +.plotCircle {stroke-width: 3pt; stroke: #5da666;} +.lastPlotCircle {stroke-width: 5pt; stroke: #214478;} +#main {width: 800px;} +#infos{text-align: center;} +input {text-align: right; width: 3.5em; padding: 0px; margin: 0px; font-size: 0.9em;} diff --git a/apps/sensor/photoComet/ajaxLoader.gif b/apps/sensor/photoComet/ajaxLoader.gif new file mode 100644 index 0000000000000000000000000000000000000000..f2a1bc0c6f545e20e631a96e8e92f9822e75d046 Binary files /dev/null and b/apps/sensor/photoComet/ajaxLoader.gif differ diff --git a/apps/sensor/photoComet/comet_alert.c b/apps/sensor/photoComet/comet_alert.c new file mode 100644 index 0000000000000000000000000000000000000000..8248df60faada7c6c31979e3d6d67cbf0595e978 --- /dev/null +++ b/apps/sensor/photoComet/comet_alert.c @@ -0,0 +1,75 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" initGet="initGet" doGet="doGet"/> + <properties persistence="volatile" interaction="alert" channel="alertChannel"/> + <args> + <arg name="thres" type="uint16" /> + </args> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +static int threshold = 512; + +static int16_t glob_sample; + +static void timer() { + int16_t tmp_result = GetADCVal(ADC_LIGHT); + if(tmp_result < threshold) { + glob_sample = tmp_result; + server_push(&alertChannel); + } +} + +static char init(void) { + return initADC(ADC_LIGHT) && set_timer(&timer,100); +} + +static char initGet(struct args_t *args) { + if(args) + threshold = args->thres; + return 1; +} + +static char doGet(struct args_t *args) { + out_uint(glob_sample); + return 1; +} diff --git a/apps/sensor/photoComet/funcs.js b/apps/sensor/photoComet/funcs.js new file mode 100644 index 0000000000000000000000000000000000000000..f89bb2a1e2b223926ef0ef529b00b6662036c926 --- /dev/null +++ b/apps/sensor/photoComet/funcs.js @@ -0,0 +1,59 @@ +var ajaxTarget = 'comet_alert'; + +function init(){ + document.getElementById("loader").style.visibility = "hidden"; +} + +function ajaxCallback(status,text){ + document.getElementById("loader").style.visibility = "hidden"; + document.getElementById("launch").style.visibility = "visible"; + if(status == 200 && text != "") { + text = parseInt(text/10.24); + document.getElementById("alert").innerHTML="Brightness: " + text + " %"; + } +} + +function run(){ + document.getElementById("loader").style.visibility = "visible"; + document.getElementById("launch").style.visibility = "hidden"; + document.getElementById("alert").innerHTML = ""; + threshold = Number(document.getElementById("htmlThres").value); + if(isNaN(threshold)) + threshold = 50; + threshold = parseInt(10.24 * threshold); + + doAjax(ajaxTarget+"?thres="+threshold,ajaxCallback,0,0); +} + +function doAjax(ajaxTarget,ajaxCallBack,timeout,timeoutCallBack){ + var xhr; + var xhrTimer; + try{ xhr = new XMLHttpRequest(); } + catch(e){ xhr = new ActiveXObject('Microsoft.XMLHTTP'); } + xhr.onreadystatechange = function(){ + if(xhr.readyState == 4) { + ajaxCallBack(xhr.status,xhr.responseText); + if(timeout > 0) + clearTimeout(xhrTimer); + } + }; + xhr.open("GET", ajaxTarget, true); + if(timeout > 0) + xhrTimer = setTimeout(function() { xhr.abort(); timeoutCallBack();}, timeout); + xhr.send(null); +} + +function ajaxGet(url) { + var xhr; + try{ xhr = new XMLHttpRequest(); } + catch(e){ xhr = new ActiveXObject('Microsoft.XMLHTTP'); } + + xhr.onreadystatechange = function(){ + if(xhr.readyState == 4){ + if(ajaxRet=xhr.status==200) + ajaxCallback(xhr.responseText); + } + }; + xhr.open("GET", url, true); + xhr.send(null); +} diff --git a/apps/sensor/photoComet/index.html b/apps/sensor/photoComet/index.html new file mode 100644 index 0000000000000000000000000000000000000000..64755f0d9c197ec105c6bcee77a9f1975f32f165 --- /dev/null +++ b/apps/sensor/photoComet/index.html @@ -0,0 +1,22 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + <head> + <script language="Javascript" src="funcs.js"></script> + <link rel="stylesheet" type="text/css" href="style.css" /> + </head> + +<body onload="init();"> + <div id="main"> + <a id="smewsLogo" href="http://www2.lifl.fr/~duquenno/Research/Smews/"><img src="/ressources/smews.jpg" alt="smews" title="" /></a> + <h1>Brightness alert</h1> + <div id="infos"> + Threshold: <input id="htmlThres" value="50"></input> % <br /> + <input id="launch" type="button" value="Launch !" onclick="run()"> + <img id="loader" src="ajaxLoader.gif" /> + <div id="alert"></div> + </div> + </div> +</body> +</html> diff --git a/apps/sensor/photoComet/style.css b/apps/sensor/photoComet/style.css new file mode 100644 index 0000000000000000000000000000000000000000..7e6e5e7cd479723a933dc04f7955f5a8975c8911 --- /dev/null +++ b/apps/sensor/photoComet/style.css @@ -0,0 +1,14 @@ +#main {position: relative; margin: 0 auto;} + +body, svg, input {fill: #333333; color: #333333; font-family: sans-serif; } +body {font-size: 12pt;} + +h1 {text-align: center; font-weight: normal; font-size: 2em; } +img { border: 0px; } +#smewsLogo { display: block; text-align: center; } + +#main {width: 800px;} +#infos{text-align: center;} +#loader{position: relative; left: -2.7em;} +#htmlThres {text-align: center; width: 2em; padding: 0px; margin: 0px; font-size: 0.9em;} +#launch {text-align: center; width: 5em; padding: 0em; margin: 0.5em; font-size: 0.9em;} diff --git a/apps/sensor/photoPoll/ajaxLoader.gif b/apps/sensor/photoPoll/ajaxLoader.gif new file mode 100644 index 0000000000000000000000000000000000000000..f2a1bc0c6f545e20e631a96e8e92f9822e75d046 Binary files /dev/null and b/apps/sensor/photoPoll/ajaxLoader.gif differ diff --git a/apps/sensor/photoPoll/chart.svg b/apps/sensor/photoPoll/chart.svg new file mode 100644 index 0000000000000000000000000000000000000000..da99aa6cdd0279005cdda4dd13570dc188d47251 --- /dev/null +++ b/apps/sensor/photoPoll/chart.svg @@ -0,0 +1,120 @@ +<?xml-stylesheet href="style.css" type="text/css"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800" height="260" onload="init(evt)"> +<script><![CDATA[ + +var svgns="http://www.w3.org/2000/svg"; +var ownDoc; +var node; +var circles = new Array(); + +var width=800; +var height=260; +var chartWidth = width - 80 - 20; +var chartHeight = height - 80; +var chartDuration = 60; + +function nodeSet(a,b) { + node.setAttributeNS(null,a,b); +} + +function init(evt) { + ownDoc=evt.target.ownerDocument; +} + +function drawCircle(x,y,r,class) { + node=ownDoc.createElementNS(svgns,"circle"); + nodeSet("cx",x); + nodeSet("cy",y); + nodeSet("r",r); + nodeSet("class",class); + ownDoc.documentElement.appendChild(node); +} + +function drawRect(x,y,w,h,class) { + node=ownDoc.createElementNS(svgns,"rect"); + nodeSet("x",x); + nodeSet("y",y); + nodeSet("width",w); + nodeSet("height",h); + nodeSet("class",class); + ownDoc.documentElement.appendChild(node); +} + +function drawLine(x,y,x2,y2,class) { + node=ownDoc.createElementNS(svgns ,"path"); + nodeSet("d","M" + x + " " + y + " L" + x2 + " " + y2); + nodeSet("class",class); + ownDoc.documentElement.appendChild(node); +} + +function drawText(root,x,y,text,anchor,class) { + tmpText=ownDoc.createTextNode(text); + node=ownDoc.createElementNS(svgns ,"text"); + nodeSet("x",x); + nodeSet("y",y); + nodeSet("text-anchor",anchor); + nodeSet("class",class); + node.appendChild(tmpText); + root.appendChild(node); +} + +function drawTextD(x,y,text,anchor,class) { + drawText(ownDoc.documentElement,x,y,text,anchor,class); +} + +function draw(yAxisName) { + drawRect(20 + 40,40,chartWidth,chartHeight,"back"); + drawTextD(-(height/2 + 40),20,yAxisName,"left","yAxisName"); + nodeSet("transform","rotate(-90)"); + drawTextD(20 + 20 + (chartWidth / 2),height,"time (s)","left","xAxisName"); + for(y=0;y<=100;y+=20){ + drawLine(20+40,height-40-y*(chartHeight/100),20 + chartWidth + 40,height-40-y*(chartHeight/100),"line"); + drawTextD(20+40-10,height-40-y*(chartHeight/100),y,"end","yTick"); + } + xAxis=ownDoc.createElementNS(svgns ,"g"); + ownDoc.documentElement.appendChild(xAxis); + for(x=0;x<=chartDuration;x+=10){ + drawLine(20+40 + x/chartDuration*(chartWidth),height-40,20+40 + x/chartDuration*(chartWidth),40,"line"); + drawText(xAxis,20+40 + x/chartDuration*(chartWidth),height-40+20,x,"middle","xTick"); + } + drawLine(20+40,40-1,20+40,height-40,"axis"); + drawLine(20+40+chartWidth,40-1,20+40+chartWidth,height-40,"axis"); + drawLine(20 + 40,height-40,20 + chartWidth + 40,height-40,"axis"); + drawLine(20 + 40,40,20 + chartWidth + 40,40,"axis"); + + node=ownDoc.createElementNS(svgns ,"path"); + nodeSet("id","samplesPath"); + nodeSet("d",""); + nodeSet("class","plot"); + nodeSet("fill","none"); + ownDoc.documentElement.appendChild(node); +} + +function drawSamples(firstPlutIsTrunked,samples) { + while(circles.length > 0) + ownDoc.documentElement.removeChild(circles.pop()); + circles = new Array(); + var tmpPath = ""; + var x = 0; + for(i=0;i<samples.length;i++){ + if(i > 0) + x += samples[i][0]/1000; + px = 20 + 40 + x * (chartWidth/chartDuration); + py = height-40-(samples[i][1]*(chartHeight/100)); + if(i==0) + tmpPath += "M"; + else + tmpPath += " L"; + tmpPath += px + " " + py; + if(firstPlutIsTrunked == 0 || i > 0) { + drawCircle(px,py,0.1,"plotCircle"); + circles.push(node); + } + } + nodeSet("class","lastPlotCircle"); + ownDoc.getElementById("samplesPath").setAttributeNS(null, "d", tmpPath); +} + +]]></script> + +</svg> diff --git a/apps/sensor/photoPoll/funcs.js b/apps/sensor/photoPoll/funcs.js new file mode 100644 index 0000000000000000000000000000000000000000..b3a1412996a79f2e4584a7eebdb3d930171963f9 --- /dev/null +++ b/apps/sensor/photoPoll/funcs.js @@ -0,0 +1,99 @@ +var ajaxTarget = 'photoSample'; +var svgWin; +var samples; +var pollInterval; +var inFlight; +var lastTime = new Date().getTime(); + +function doAjax(ajaxTarget,ajaxCallBack,timeout,timeoutCallBack){ + var xhr; + var xhrTimer; + try{ xhr = new XMLHttpRequest(); } + catch(e){ xhr = new ActiveXObject('Microsoft.XMLHTTP'); } + xhr.onreadystatechange = function(){ + if(xhr.readyState == 4) { + ajaxCallBack(xhr.status,xhr.responseText); + if(timeout > 0) + clearTimeout(xhrTimer); + } + }; + xhr.open("GET", ajaxTarget, true); + if(timeout > 0) + xhrTimer = setTimeout(function() { xhr.abort(); timeoutCallBack();}, timeout); + xhr.send(null); +} + +function sampleTimeout(){ + inFlight = 0; + document.getElementById("loader").style.visibility = "hidden"; +} + +function sampleCallBack(status,text){ + inFlight = 0; + setTimeout(function() { if(inFlight == 0) document.getElementById("loader").style.visibility = "hidden"; }, 10); + if(status == 200 && text != "") + newSample(text/10.24); +} + +function newSample(val){ + newTime = new Date().getTime(); + chartDuration = 0; + maxDuration = svgWin.chartDuration * 1000; + toRemove = 0; + firstPlotIsTrunked = 0; + samples.push([newTime-lastTime,val]); + lastTime = newTime; + for(i=samples.length-1;i>=1;i--) { + if(chartDuration < maxDuration) { + chartDuration += samples[i][0]; + if(chartDuration > maxDuration) { + overLap = chartDuration - maxDuration; + interval = samples[i][0]; + newInterval = interval - overLap; + plotVal = samples[i][1]; + prevVal = samples[i-1][1]; + newVal = (prevVal * newInterval + plotVal * (overLap)) / interval; + samples[i-1][1] = newVal; + samples[i][0] = newInterval; + chartDuration = maxDuration; + firstPlotIsTrunked = 1; + } + } + if (chartDuration == maxDuration) { + toRemove = i - 1; + break; + } + } + for(i=0;i<toRemove;i++) + samples.shift(); + svgWin.drawSamples(firstPlotIsTrunked,samples); +} + +function setPollInterval(arg){ + argVal = Number(arg); + if(isNaN(argVal)) { + argVal = lastPollInterval; + } + pollInterval = argVal; + document.getElementById("htmlInterval").value = pollInterval; +} + +function onTimer(){ + setTimeout(onTimer,pollInterval); + lastPollInterval = pollInterval; + if(inFlight == 0) { + inFlight = 1; + document.getElementById("loader").style.visibility = "visible"; + doAjax(ajaxTarget,sampleCallBack,1000,sampleTimeout); + } +} + +function init(){ + svgObject = document.getElementById("svgDoc0"); + svgWin = svgObject.contentDocument.defaultView; + svgWin.draw('Brigthness'); + samples = new Array(); + setPollInterval(1000); + inFlight = 0; + onTimer(); +} diff --git a/apps/sensor/photoPoll/index.html b/apps/sensor/photoPoll/index.html new file mode 100644 index 0000000000000000000000000000000000000000..9657d650844fcaad184ca49770a017bb7cc149c3 --- /dev/null +++ b/apps/sensor/photoPoll/index.html @@ -0,0 +1,23 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + <head> + <script language="Javascript" src="funcs.js"></script> + <link rel="stylesheet" type="text/css" href="style.css" /> + </head> + +<body onload="init();"> + <div id="main"> + <a id="smewsLogo" href="http://www2.lifl.fr/~duquenno/Research/Smews/"><img src="/ressources/smews.jpg" alt="smews" title="" /></a> + <h1>Current brightness</h1> + <div id="infos"> + <img id="loader" src="ajaxLoader.gif" /> + Polling interval: <input id="htmlInterval" onKeyUp="setPollInterval(this.value);"></input> ms + </div> + <div id="svgDoc"> + <object id="svgDoc0" type="image/svg+xml" data="chart.svg" width="800" height="260" /> + </div> + </div> +</body> +</html> diff --git a/apps/sensor/photoPoll/photoSample.c b/apps/sensor/photoPoll/photoSample.c new file mode 100644 index 0000000000000000000000000000000000000000..31858095d359906f32beefd63f21688ff97393a6 --- /dev/null +++ b/apps/sensor/photoPoll/photoSample.c @@ -0,0 +1,53 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile"/> +</generator> +*/ + + +#include "generators.h" + +static char init(void) { + return initADC(ADC_LIGHT); +} + +static char doGet(struct args_t *args) { + out_uint(GetADCVal(ADC_LIGHT)); + return 1; +} diff --git a/apps/sensor/photoPoll/style.css b/apps/sensor/photoPoll/style.css new file mode 100644 index 0000000000000000000000000000000000000000..357c3666d0bfdabf7d8c0dcfdaa5d77ee1dcbda7 --- /dev/null +++ b/apps/sensor/photoPoll/style.css @@ -0,0 +1,19 @@ +#main {position: relative; margin: 0 auto;} + +body, svg, input {fill: #333333; color: #333333; font-family: sans-serif; } +body {font-size: 12pt;} + +h1 {text-align: center; font-weight: normal; font-size: 2em; } +img { border: 0px; } +#smewsLogo { display: block; text-align: center; } + +.xTick, .yTick {font-size:1em;} +.back {fill: #ffffff} +.axis {stroke: #214478; stroke-width: 1.3pt;} +.line {stroke: #214478; stroke-width: 0.3pt;} +.plot {stroke: #5da666; stroke-width: 1.5pt;} +.plotCircle {stroke-width: 3pt; stroke: #5da666;} +.lastPlotCircle {stroke-width: 5pt; stroke: #214478;} +#main {width: 800px;} +#infos{text-align: center;} +input {text-align: right; width: 3.5em; padding: 0px; margin: 0px; font-size: 0.9em;} diff --git a/apps/test/comet.c b/apps/test/comet.c new file mode 100644 index 0000000000000000000000000000000000000000..baf1456158a85e7be85cb14df15d265b5ed4ad70 --- /dev/null +++ b/apps/test/comet.c @@ -0,0 +1,59 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile" interaction="alert"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +static void timer() { + server_push(&comet); +} + +static char init(void) { + return set_timer(&timer,1000); +} + +static char doGet(struct args_t *args) { + out_uint(TIME_MILLIS); + out_c('\n'); + return 1; +} diff --git a/apps/test/index.html b/apps/test/index.html new file mode 100644 index 0000000000000000000000000000000000000000..573541ac9702dd3969c9bc859d2b91ec1f7e6e56 --- /dev/null +++ b/apps/test/index.html @@ -0,0 +1 @@ +0 diff --git a/apps/test/large.c b/apps/test/large.c new file mode 100644 index 0000000000000000000000000000000000000000..1eea30a01f4d3ed2dec4b76019d126b9696d4069 --- /dev/null +++ b/apps/test/large.c @@ -0,0 +1,56 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" + +static char init(void) { + return 1; +} + +static char doGet(struct args_t *args) { + uint16_t i; + for(i=0 ; i<160; i++) + out_c('a' + i%26); + out_c('\n'); + return 1; +} diff --git a/apps/test/small.c b/apps/test/small.c new file mode 100644 index 0000000000000000000000000000000000000000..1171e338d2264de2960855fcf7ff73c4b6e88cae --- /dev/null +++ b/apps/test/small.c @@ -0,0 +1,54 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="persistent"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" + +static char init(void) { + return 1; +} + +static char doGet(struct args_t *args) { + static int i=0; + out_uint(i++); + return 1; +} diff --git a/apps/test/stream.c b/apps/test/stream.c new file mode 100644 index 0000000000000000000000000000000000000000..82a629bd41f27e462710593d0e239b59e0eae705 --- /dev/null +++ b/apps/test/stream.c @@ -0,0 +1,59 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile" interaction="streaming" channel="stream"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +static void timer() { + server_push(&stream); +} + +static char init(void) { + return set_timer(&timer,1000); +} + +static char doGet(struct args_t *args) { + out_uint(TIME_MILLIS); + out_c('\n'); + return 1; +} diff --git a/apps/time/comet15s.c b/apps/time/comet15s.c new file mode 100644 index 0000000000000000000000000000000000000000..6cf76c1244cc75121218ccca56d397c7daf447a0 --- /dev/null +++ b/apps/time/comet15s.c @@ -0,0 +1,61 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile" interaction="alert" channel="comet15"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +static uint32_t toPublish = 0; + +static void timer() { + toPublish = TIME_MILLIS; + server_push(&comet15); +} + +static char init(void) { + return set_timer(&timer,15000); +} + +static char doGet(struct args_t *args) { + out_uint(toPublish); + return 1; +} diff --git a/apps/time/comet1s.c b/apps/time/comet1s.c new file mode 100644 index 0000000000000000000000000000000000000000..0b24397c5ac932853ca3b7858c4b3097379db6fa --- /dev/null +++ b/apps/time/comet1s.c @@ -0,0 +1,61 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile" interaction="alert" channel="comet1"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +static uint32_t toPublish = 0; + +static void timer() { + toPublish = TIME_MILLIS; + server_push(&comet1); +} + +static char init(void) { + return set_timer(&timer,1000); +} + +static char doGet(struct args_t *args) { + out_uint(toPublish); + return 1; +} diff --git a/apps/time/comet30s.c b/apps/time/comet30s.c new file mode 100644 index 0000000000000000000000000000000000000000..d382e9fa29a09e3104c62015dd66aa1c7f0adcab --- /dev/null +++ b/apps/time/comet30s.c @@ -0,0 +1,60 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile" interaction="alert" channel="comet30"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" +static uint32_t toPublish = 0; + +static void timer() { + toPublish = TIME_MILLIS; + server_push(&comet30); +} + +static char init(void) { + return set_timer(&timer,30000); +} + +static char doGet(struct args_t *args) { + out_uint(toPublish); + return 1; +} diff --git a/apps/time/comet50s.c b/apps/time/comet50s.c new file mode 100644 index 0000000000000000000000000000000000000000..0be305829f245267cfab54af0d42d6318e45dad7 --- /dev/null +++ b/apps/time/comet50s.c @@ -0,0 +1,61 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile" interaction="alert" channel="comet50"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +static uint32_t toPublish = 0; + +static void timer() { + toPublish = TIME_MILLIS; + server_push(&comet50); +} + +static char init(void) { + return set_timer(&timer,50000); +} + +static char doGet(struct args_t *args) { + out_uint(toPublish); + return 1; +} diff --git a/apps/time/comet5s.c b/apps/time/comet5s.c new file mode 100644 index 0000000000000000000000000000000000000000..3c4161350af0e8fd80a1417a893200a3637f4b2f --- /dev/null +++ b/apps/time/comet5s.c @@ -0,0 +1,61 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile" interaction="alert" channel="comet5"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +static uint32_t toPublish = 0; + +static void timer() { + toPublish = TIME_MILLIS; + server_push(&comet5); +} + +static char init(void) { + return set_timer(&timer,5000); +} + +static char doGet(struct args_t *args) { + out_uint(toPublish); + return 1; +} diff --git a/apps/time/cometRand.c b/apps/time/cometRand.c new file mode 100644 index 0000000000000000000000000000000000000000..b1d13d950d45f293881bb10e381c3c92074ddc7b --- /dev/null +++ b/apps/time/cometRand.c @@ -0,0 +1,85 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" initGet="initGet" doGet="doGet"/> + <properties persistence="volatile" interaction="alert" channel="cometRand"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" +#include <math.h> + +#define MAX_RAND 50 + +static unsigned char initialized; +static char randInterval = 0; +static char currInterval = 0; +static uint16_t nPub = 0; +static uint32_t toPublish = 0; + +static void timer() { + if(initialized && --randInterval <= 0) { + nPub++; + toPublish = TIME_MILLIS; + currInterval = randInterval = 1 + ((unsigned char)rand())%MAX_RAND; + server_push(&cometRand); + } +} + +static char init(void) { + return set_timer(&timer,1000); +} + +static char initGet(struct args_t *args) { + if(!initialized) { + initialized = 1; + srand(TIME_MILLIS); + currInterval = randInterval = 1 + ((unsigned char)rand())%MAX_RAND; + } + return 1; +} + +static char doGet(struct args_t *args) { + out_uint(toPublish); + out_c('\n'); + out_uint(nPub); + out_c('\n'); + out_uint(currInterval); + return 2; +} diff --git a/apps/time/lp15s.c b/apps/time/lp15s.c new file mode 100644 index 0000000000000000000000000000000000000000..152def6cf39405b68ee9c9982196e67d2567d849 --- /dev/null +++ b/apps/time/lp15s.c @@ -0,0 +1,61 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile" interaction="streaming" channel="lp15"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +static uint32_t toPublish = 0; + +static void timer() { + toPublish = TIME_MILLIS; + server_push(&lp15); +} + +static char init(void) { + return set_timer(&timer,15000); +} + +static char doGet(struct args_t *args) { + out_uint(toPublish); + return 1; +} diff --git a/apps/time/lp1s.c b/apps/time/lp1s.c new file mode 100644 index 0000000000000000000000000000000000000000..90714aec9b751f619e131aa1941226db02fcd2c1 --- /dev/null +++ b/apps/time/lp1s.c @@ -0,0 +1,61 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile" interaction="streaming" channel="lp1"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +static uint32_t toPublish = 0; + +static void timer() { + toPublish = TIME_MILLIS; + server_push(&lp1); +} + +static char init(void) { + return set_timer(&timer,1000); +} + +static char doGet(struct args_t *args) { + out_uint(toPublish); + return 1; +} diff --git a/apps/time/lp30s.c b/apps/time/lp30s.c new file mode 100644 index 0000000000000000000000000000000000000000..faa8ecc889891a6bd582a41aa93202707ae26587 --- /dev/null +++ b/apps/time/lp30s.c @@ -0,0 +1,60 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile" interaction="streaming" channel="lp30"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" +static uint32_t toPublish = 0; + +static void timer() { + toPublish = TIME_MILLIS; + server_push(&lp30); +} + +static char init(void) { + return set_timer(&timer,30000); +} + +static char doGet(struct args_t *args) { + out_uint(toPublish); + return 1; +} diff --git a/apps/time/lp50s.c b/apps/time/lp50s.c new file mode 100644 index 0000000000000000000000000000000000000000..d8a7f70e229255b2fcbc299c0b98a92760d854f7 --- /dev/null +++ b/apps/time/lp50s.c @@ -0,0 +1,61 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile" interaction="streaming" channel="lp50"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +static uint32_t toPublish = 0; + +static void timer() { + toPublish = TIME_MILLIS; + server_push(&lp50); +} + +static char init(void) { + return set_timer(&timer,50000); +} + +static char doGet(struct args_t *args) { + out_uint(toPublish); + return 1; +} diff --git a/apps/time/lp5s.c b/apps/time/lp5s.c new file mode 100644 index 0000000000000000000000000000000000000000..bb34b8b8b09282cc9a711e58bc883e481f8e75cf --- /dev/null +++ b/apps/time/lp5s.c @@ -0,0 +1,61 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile" interaction="streaming" channel="lp5"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +static uint32_t toPublish = 0; + +static void timer() { + toPublish = TIME_MILLIS; + server_push(&lp5); +} + +static char init(void) { + return set_timer(&timer,5000); +} + +static char doGet(struct args_t *args) { + out_uint(toPublish); + return 1; +} diff --git a/apps/time/lpRand.c b/apps/time/lpRand.c new file mode 100644 index 0000000000000000000000000000000000000000..245cda0750fa3ec28754f2beca7b5cd675c51529 --- /dev/null +++ b/apps/time/lpRand.c @@ -0,0 +1,85 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" initGet="initGet" doGet="doGet"/> + <properties persistence="volatile" interaction="streaming" channel="lpRand"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" +#include <math.h> + +#define MAX_RAND 50 + +static unsigned char initialized; +static char randInterval = 0; +static char currInterval = 0; +static uint16_t nPub = 0; +static uint32_t toPublish = 0; + +static void timer() { + if(initialized && --randInterval <= 0) { + nPub++; + toPublish = TIME_MILLIS; + currInterval = randInterval = 1 + ((unsigned char)rand())%MAX_RAND; + server_push(&lpRand); + } +} + +static char init(void) { + return set_timer(&timer,1000); +} + +static char initGet(struct args_t *args) { + if(!initialized) { + initialized = 1; + srand(TIME_MILLIS); + currInterval = randInterval = 1 + ((unsigned char)rand())%MAX_RAND; + } + return 1; +} + +static char doGet(struct args_t *args) { + out_uint(toPublish); + out_c('\n'); + out_uint(nPub); + out_c('\n'); + out_uint(currInterval); + return 1; +} diff --git a/apps/time/time.c b/apps/time/time.c new file mode 100644 index 0000000000000000000000000000000000000000..1a9b638725340b0f8c7a12123e25c03c32a6e62a --- /dev/null +++ b/apps/time/time.c @@ -0,0 +1,49 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers doGet="doGet"/> + <properties persistence="volatile"/> +</generator> +*/ + + +#include "generators.h" + +static char doGet(struct args_t *args) { + out_uint(TIME_MILLIS); + return 1; +} diff --git a/apps/time/timeRand.c b/apps/time/timeRand.c new file mode 100644 index 0000000000000000000000000000000000000000..1cd002a5be8d862b07de8588d3b0ec7359bc2361 --- /dev/null +++ b/apps/time/timeRand.c @@ -0,0 +1,81 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* +<generator> + <handlers init="init" doGet="doGet"/> + <properties persistence="volatile"/> +</generator> +*/ + +#include "generators.h" +#include "timers.h" +#include "channels.h" + +#define MAX_RAND 50 + +static unsigned char initialized; +static char randInterval = 0; +static char currInterval = 0; +static uint16_t nPub = 0; +static uint32_t toPublish = 0; + +static void timer() { + if(initialized && --randInterval <= 0) { + nPub++; + toPublish = TIME_MILLIS; + currInterval = randInterval = 1 + ((unsigned char)rand())%MAX_RAND; + server_push(&cometRand); + } +} + +static char init(void) { + return set_timer(&timer,1000); +} + +static char doGet(struct args_t *args) { + if(!initialized) { + initialized = 1; + srand(TIME_MILLIS); + toPublish = TIME_MILLIS; + currInterval = randInterval = 1 + ((unsigned char)rand())%MAX_RAND; + } + out_uint(toPublish); + out_c('\n'); + out_uint(nPub); + out_c('\n'); + out_uint(currInterval); + return 1; +} diff --git a/apps/welcome/SConscript b/apps/welcome/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..d8ca593ba922cc75f223d63f1d62a9b68d007ebf --- /dev/null +++ b/apps/welcome/SConscript @@ -0,0 +1,90 @@ +# Copyright or c or Copr. 2008, Simon Duquennoy +# +# Author e-mail: simon.duquennoy@lifl.fr +# +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + +import os +import glob + +Import('env \ +genDir \ +dirsMap \ +tmpBase \ +target \ +sconsBasePath \ +httpCodesDir \ +appBase \ +') + +# used by getAppFiles +def getAppFilesRec(appPath,path): + files=[] + for file in glob.glob(path + '/*'): + if os.path.isdir(file): + files = files + (getAppFilesRec(appPath,file)) + else: + files.append(file[len(appPath)+1:]) + return files + +# returns all files contained in path (with recurssion) +def getAppFiles(path): + return getAppFilesRec(path,path) + +appListName = 'appList.js' + +appListPath = os.path.join(genDir,tmpBase,appListName) +appListAbsPath = os.path.join(sconsBasePath,appListPath) + +appList = open(appListAbsPath,'w') +if len(dirsMap.keys()) > 2: + appList.write('var appList = new Array();\n') + appsCount = 0 + for dir in dirsMap.keys(): + if dir != 'welcome' and dir != httpCodesDir: + subFiles = getAppFiles(os.path.join(sconsBasePath,appBase,dir)) + for subDir in map(lambda x: os.path.dirname(x),filter(lambda x: x == 'index.html' or x.endswith('/index.html'),subFiles)): + appsCount += 1 + if subDir != '': + appList.write('appList[\"' + os.path.join(dirsMap[dir],subDir) + '\"] = \"' + os.path.join(dir,subDir) + '/\"\n') + else: + appList.write('appList[\"' + dirsMap[dir] + '\"] = \"' + dir + '/\"\n') + if appsCount > 1: + appList.write('var appTitle = \"' + target.capitalize() + ' applications examples :\";\n') + elif appsCount > 0: + appList.write('var appTitle = \"' + target.capitalize() + ' application example :\";\n') + else: + appList.write('var appTitle = \"\";\n') +else: + appList.write('var appTitle = \"\";\n') +appList.close() + +ret = {appListPath: os.path.join(dirsMap['welcome'],appListName)} +Return('ret') diff --git a/apps/welcome/index.html b/apps/welcome/index.html new file mode 100644 index 0000000000000000000000000000000000000000..3db57547652e4c36f8cf61e3079a505754cdd0f0 --- /dev/null +++ b/apps/welcome/index.html @@ -0,0 +1,101 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + +<head> + <title>Smews embedded Web server presentation</title> + <link rel="stylesheet" type="text/css" href="ressources/style.css" /> + <script type="text/javascript" src="appList.js"></script> +</head> + +<body> + <a id="smewsLogo" href="http://www2.lifl.fr/~duquenno/Research/Smews/"> + <img src="ressources/smews.jpg" alt="smews" title="" /> + <h1>Smews: <em>Smart & Mobile Embedded Web Server</em></h1> + </a> + + <div id="mainText"> + <h2><em>Smews</em> is an embedded Web server with low memory footprint</h2> + <ul> + <li>Stand-alone Web server, without any underlaying OS</li> + <li>Down to 200 bytes of volatile memory</li> + <li>Down to 8 kB of persistent memory</li> + </ul> + + <h2><em>Smews</em> has high performances</h2> + <ul> + <li>Single process event-driven architecture</li> + <li>TCP stack dedicated to HTTP, allowing cross-layer optimizations</li> + <li>Off-line pre-calculations done on Web contents (protocol headers, checksums, parsing automatons)</li> + </ul> + <h2><em>Smews</em> is able to serve rich Web applications</h2> + <ul> + <li>Able to send static and dynamic contents</li> + <li>Comet support (server pushed data)</li> + <li>Advanced typing of dynamic Web contents (persitent, idempotent and volatile contents)</li> + </ul> + <div id="appList"> + <script type="text/javascript"> + if(appTitle != "") { + document.write("<h2>" + appTitle + "</h2>"); + document.write("<ul>") + for(app in appList) + document.write("<li><a href=" + app + "/>" + appList[app] + "</a></li>"); + document.write("</ul>") + } + </script> + </div> + </div> + + <div id="smewsPorts"> + <h2><em>Smews</em> has been ported to</h2> + + <ul> + <li> + <img src="ressources/micaz.jpg" alt="micaz" title="" width="80" /> + <ul> + <li><strong>MicaZ sensor board</strong></li> + <li>AVR 8 bits at 8 MHz, 16 bits bus</li> + <li>SLIP over serial line</li> + </ul> + </li> + + <li> + <img src="ressources/wsn430.jpg" alt="wsn430" title="" width="80" /> + <ul> + <li><strong>WSN430 sensor board</strong></li> + <li>MSP430 16 bits at 16 MHz, 16 bits bus</li> + <li>SLIP over serial line</li> + </ul> + </li> + + <li> + <img src="ressources/funcard7.jpg" alt="funcard7" title="" width="80" /> + <ul> + <li><strong>Funcard 7 smart card</strong></li> + <li>Funcard 7 smart card</li> + <li>APDU</li> + </ul> + </li> + + <li> + <img src="ressources/gba.jpg" alt="gba" title="" width="80" /> + <ul> + <li><strong>Game Boy Advance</strong></li> + <li>Arm7 32 bits at 16 MHz, 32 bits bus</li> + <li>SLIP over serial line</li> + </ul> + </li> + + <li> + <img src="ressources/linux.jpg" alt="linux" title="" width="60" /> + <ul> + <li><strong>Linux</strong></li> + <li>TUN virtual drivers</li> + </ul> + </li> + </ul> + </div> +</body> + +</html> diff --git a/apps/welcome/ressources/funcard7.jpg b/apps/welcome/ressources/funcard7.jpg new file mode 100644 index 0000000000000000000000000000000000000000..40b5bec7d4d1466a844b981ef194620be049427d Binary files /dev/null and b/apps/welcome/ressources/funcard7.jpg differ diff --git a/apps/welcome/ressources/gba.jpg b/apps/welcome/ressources/gba.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f252138eae26e627235efeaa0e4611ff038e6cec Binary files /dev/null and b/apps/welcome/ressources/gba.jpg differ diff --git a/apps/welcome/ressources/linux.jpg b/apps/welcome/ressources/linux.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e08c8bfec3e238092abebb54994477fce141cee7 Binary files /dev/null and b/apps/welcome/ressources/linux.jpg differ diff --git a/apps/welcome/ressources/micaz.jpg b/apps/welcome/ressources/micaz.jpg new file mode 100644 index 0000000000000000000000000000000000000000..49f12282e6837ce086dc6609e72c500015b1d12a Binary files /dev/null and b/apps/welcome/ressources/micaz.jpg differ diff --git a/apps/welcome/ressources/smews.jpg b/apps/welcome/ressources/smews.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eca9d166478c24480c7b29b641f65a060e28a979 Binary files /dev/null and b/apps/welcome/ressources/smews.jpg differ diff --git a/apps/welcome/ressources/style.css b/apps/welcome/ressources/style.css new file mode 100644 index 0000000000000000000000000000000000000000..87bd2258b5e588439d2a10e3f4379034173bfb53 --- /dev/null +++ b/apps/welcome/ressources/style.css @@ -0,0 +1,11 @@ +body { font-family: sans-serif; font-size: 12pt; color:#333333; } +img { border: 0px; } +a { color: #000000; text-decoration: none; } +a:hover { color: #555555; text-decoration: underline; } + +#mainText { float: left; width: 55%; margin-right: 5%; } +#smewsPorts{ float: right; width: 40%; } +#smewsPorts ul { padding: 0 0 2em 0; } +#smewsPorts ul ul { padding-left: 7em; } +#smewsPorts li { list-style-type: none; } +#smewsPorts img { float: left; } diff --git a/apps/welcome/ressources/wsn430.jpg b/apps/welcome/ressources/wsn430.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fdffceee00213162b4261a35462ea2e664321778 Binary files /dev/null and b/apps/welcome/ressources/wsn430.jpg differ diff --git a/changelogs.txt b/changelogs.txt new file mode 100644 index 0000000000000000000000000000000000000000..74ffb47b6e9f454133cdfaf16b3c27b46e190a46 --- /dev/null +++ b/changelogs.txt @@ -0,0 +1,125 @@ +1.5.0: + - added generic panManager with slip and apduip plugins + - added IPv6 support + - IP addresses are now configured via a SCons arguments + - changes in aplications XML data + - other minor changes in SConstruct arguments +1.4.0f: + - minor bug for targets using non-addressable memory to store persistent data + - minor SConsscripts modifications +1.4.0e: + - update doc + - debug in the smews example Web app sconscript + - clean .s compilation in bin directory +1.4.0d: + - cleaning TCP checksum calculation on inputs (pseudo-header) +1.4.0c: + - added -fno-strict-aliasing option in compilation +1.4.0b: + - minor correction in outpuc.c +1.4.0: + - added dynamic memory allocator (memory.c/.h) + - number of connections and timers, url arguments size are no more statically defined + - added coroutines for dynamic content generation + - all coroutines are executed in a single shared stack + - contexts are backuped using exactly the par of stack used by the coroutine (top -> sp) + - the event-driven engine is now never reenters + - added the implementation of Web contents taxonomy support + - in-flight segments are chained in memory + - we store either the data buffer or a coroutine context for each in-flight segment + - coroutines can have multiple states and be reran + - coroutines are ported to linux and msp430, but not yet to ARM and AVR +1.3.4b: + - Improved and more consistent implementation of dev_get16/32 and dev_put16/32 functions +1.3.4: + - Bug fix in the Funcard target (access of some CONST fields in output_handler_t) + - Change the way IP addresses are configured in targets +1.3.3b: + - Add documentation source in the doc directory + - Remove display bug in the svg javascript in the linux and sensor polling applications +1.3.3: + - Suppression of current_inack in the connection structure (the inflight field is sufficient) + - Demo Web applications improvements (linux, sensor, contactsBook) +1.3.2: + - Improvements in retransmissions management +1.3.1: + - Comet generators can now be streamed (using chunk encoding) + - Long generated contents are now served via chunked transfer, thus keeping the connection open +1.3.0: + - Source code has been massively refactored + - Receive/send scheduling improvements for better scallability (tested on hundreads of connections) + - Suppression of the "ENABLE_CHAINED" option + - HTTP/TCP automaton has been cleaned + - The SCons "install" option has been replaced by a "install" file in target directories if needed + - WSN430, MicaZ and GBA slip drivers have been redisigned + - Code size reduction +1.2.4b: + - Minor modifications in library generation + - Static contents compression (gzip) is an option in SCons +1.2.4: + - Smews can now be embedded in other software, by using smews.h and linking with libsmews.a +1.2.3c: + - check python version in SConstruct (version >= 2.5.0) +1.2.3b: + - minor improvement in the main loop step +1.2.3: + - SLEEP macros added for the targets + - better erros management in devices drivers + - improve SLIP drivers +1.2.2: + - SCons python files refactoring + - Changes on intermediate generated files + - It is now possible to use non-generators c/h files in Web apps +1.2.1: + - Web applications refactoring + - New application samples + - Smews sample web app. has been improved with automated sub-folders management +1.2.0: + - Generators typing management (persistent/idempotent/volatile) +1.1.1e: + - Minor changes +1.1.1d: + - The server IP address is now stored in volatile memory + - New Smews logo +1.1.1c: + - Final demos shown at Smart University 2008 +1.1.1b: + - Funcard7 demo applications +1.1.1: + - Mashup applications demo (contactsBook, google calendar) + - Static Web pages are now gzipped + - CONST_VAR and PERSISTENT_VAR qualifiers modifications + - EEPROM write for Funcard7 + - Funcard7 with fast IOs (115200 bauds) + - Funcard7: no MSS limitation + - Code and RAM size reductions +1.1.0b: + - Blob management improvements for Funcard7 +1.1.0: + - Arguments handling in URLs for generators + - Funcard7 port optimizations + - Code size reduction + - New organization for Web contents: + - common webContents folder + - SConscript are possible in webContents +1.0.0: + - Add commonContents dir and defaultContents option to SCons + - Add disable=comet and enable=chained + - Correct errorenous IP packets dropping (thanks to a local tmp_connection) + - TCP stack reorganization +0.9.9d: + - Debug: change to LISTEN state after FIN/ACK, FIN/ACK, ACK +0.9.9c: + - Debug: SYN flood correction +0.9.9b: + - Connections management: the oldest inactive connection is dropped if needed +0.9.9: + - Rename from DynaWeb to Smews +0.9.8c: + - Code size reduction for blob processing +0.9.8b: + - Debug of fast successive GET request on a same connection +0.9.8: + - Add Funcard 7 port + - Compact and efficient tree used to store URLs and references instead of an associative table + - RST packets sent in response to SYN packets if no more connections are available diff --git a/core/checksum.c b/core/checksum.c new file mode 100644 index 0000000000000000000000000000000000000000..b4c65d48df4ade7544b30332425146068fac5790 --- /dev/null +++ b/core/checksum.c @@ -0,0 +1,95 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "checksum.h" + +/* current checksum carry */ +static unsigned char checksum_carry; +/* index of the next checksum byte to compute (0/1) */ +static unsigned char checksum_flip; +/* current checksum */ +unsigned char current_checksum[2]; + +/*-----------------------------------------------------------------------------------*/ +void checksum_init() { + current_checksum[S0] = 0; + current_checksum[S1] = 0; + checksum_carry = 0; + checksum_flip = S0; +} + +/*-----------------------------------------------------------------------------------*/ +void checksum_add(unsigned char val) { + uint16_t tmp_sum; + + tmp_sum = current_checksum[checksum_flip] + val + checksum_carry; + current_checksum[checksum_flip] = tmp_sum; + checksum_carry = tmp_sum >> 8; + checksum_flip ^= 0x01; +} + +/* Te be used only with an even alignment */ +/*-----------------------------------------------------------------------------------*/ +void checksum_add16(const uint16_t val) { + uint16_t tmp_sum; + + tmp_sum = current_checksum[S0] + (val >> 8) + checksum_carry; + current_checksum[S0] = tmp_sum; + checksum_carry = tmp_sum >> 8; + + tmp_sum = current_checksum[S1] + (val & 0xff) + checksum_carry; + current_checksum[S1] = tmp_sum; + checksum_carry = tmp_sum >> 8; +} + +/* Te be used only with an even alignment */ +/*-----------------------------------------------------------------------------------*/ +void checksum_add32(const unsigned char val[]) { + uint16_t tmp_sum; + + tmp_sum = current_checksum[S0] + val[W0] + val[W2] + checksum_carry; + current_checksum[S0] = tmp_sum; + checksum_carry = tmp_sum >> 8; + + tmp_sum = current_checksum[S1] + val[W1] + val[W3] + checksum_carry; + current_checksum[S1] = tmp_sum; + checksum_carry = tmp_sum >> 8; +} + +/*-----------------------------------------------------------------------------------*/ +void checksum_end() { + while(checksum_carry) + checksum_add(0); +} diff --git a/core/checksum.h b/core/checksum.h new file mode 100644 index 0000000000000000000000000000000000000000..918f3401aaf24f0b8a6b91bd88f372bee49912a5 --- /dev/null +++ b/core/checksum.h @@ -0,0 +1,57 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __CHECKSUM_H__ +#define __CHECKSUM_H__ + +#include "types.h" + +/* Sums two checksums, taking in account the carry. To be used into other macros */ +#define CHK_SUM(a,b) ((((a)+(b)) & 0x0000ffff) + ((((a)+(b)) & 0xffff0000) >> 16)) + +/* Current checksum */ +extern unsigned char current_checksum[2]; + +/* Checksumming functions */ +extern void checksum_init(void); +extern void checksum_set(uint16_t val); +extern void checksum_end(void); +extern void checksum_add(unsigned char x); +/* Te be used only with an even alignment */ +void checksum_add16(const uint16_t x); +/* Te be used only with an even alignment */ +void checksum_add32(const unsigned char x[]); + +#endif /* __CHECKSUM_H__ */ diff --git a/core/connections.c b/core/connections.c new file mode 100644 index 0000000000000000000000000000000000000000..184ce6ccca9d2568542d7b9d87506be7199a5d28 --- /dev/null +++ b/core/connections.c @@ -0,0 +1,153 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "connections.h" +#include "memory.h" + +/* Local IP address */ +#ifdef IPV6 + +#ifndef IP_ADDR + #define IPV6_ADDR 0x00 +#endif + +unsigned char local_ip_addr[16] = { IP_ADDR }; +#else + +#ifndef IP_ADDR + #define IP_ADDR 4,1,168,192 +#endif + +unsigned char local_ip_addr[4] = { IP_ADDR }; +#endif + +/* Shared global connections structures */ +struct http_connection *all_connections; +struct http_rst_connection rst_connection; + +#ifdef IPV6 +/*-----------------------------------------------------------------------------------*/ + +char ipcmp(unsigned char source_addr[], unsigned char check_addr[]) { + uint16_t i; + + for (i=0; i < (17 - ((source_addr[0])&15)); i++) + if (source_addr[i] != check_addr[i]) + return 0; + + return 1; +} + +unsigned char * decompress_ip(unsigned char comp_ip_addr[], unsigned char full_ip_addr[], unsigned char indexes) { + uint16_t i, zeros_nb, start_index; + + start_index = indexes>>4; + zeros_nb = ((indexes)&15); + + for (i=0; i < start_index; i++) + full_ip_addr[i] = comp_ip_addr[i]; + + for (; i < start_index+zeros_nb; i++) + full_ip_addr[i] = 0; + + for (; i < 16; i++) + full_ip_addr[i] = comp_ip_addr[i-zeros_nb]; + + return full_ip_addr; +} + +unsigned char * compress_ip(unsigned char full_ip_addr[], unsigned char comp_ip_addr[], unsigned char * indexes) { + int32_t i, curr_index=0, max_index=0, curr_nb=0, max_nb=0; + + for (i = 0; i < 16; i++) { + comp_ip_addr[i] = 0; + if (full_ip_addr[i] == 00) { + if (!curr_nb) + curr_index = i; + curr_nb++; + } else { + if (curr_nb > max_nb) { + max_nb = curr_nb; + max_index = curr_index; + curr_nb = 0; + } + } + } + + for (i = 0; i < max_index; i++) + comp_ip_addr[i] = full_ip_addr[i]; + + for (; i < (16-max_nb); i++) + comp_ip_addr[i] = full_ip_addr[i+max_nb]; + + *indexes = max_index; + *indexes = *indexes<<4; + *indexes = *indexes|max_nb; + + return comp_ip_addr; +} +#endif +/*-----------------------------------------------------------------------------------*/ +char something_to_send(const struct http_connection *connection) { + if(!connection->output_handler) + return 0; + + if(CONST_UI8(connection->output_handler->handler_type) == type_control +#ifndef DISABLE_COMET + || connection->comet_send_ack == 1 +#endif + ) { + return 1; + } else { + return connection->tcp_state == tcp_established + && UI32(connection->next_outseqno) != UI32(connection->final_outseqno); + } +} + +/*-----------------------------------------------------------------------------------*/ +void free_connection(const struct http_connection *connection) { + connection->prev->next = connection->next; + connection->next->prev = connection->prev; + if(connection == connection->next) { + all_connections = NULL; + } else { + all_connections = connection->next; + } + if(connection->generator_service) { + clean_service(connection->generator_service, NULL); + } + mem_free(connection->generator_service, sizeof(struct generator_service_t)); + mem_free((void*)connection, sizeof(struct http_connection)); +} diff --git a/core/connections.h b/core/connections.h new file mode 100644 index 0000000000000000000000000000000000000000..a63771c03a64ad48bc618811881a37c46dfe7efc --- /dev/null +++ b/core/connections.h @@ -0,0 +1,134 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __CONNECTIONS_H__ +#define __CONNECTIONS_H__ + +#include "handlers.h" +#include "coroutines.h" + +/** TCP **/ + +/* TCP flags */ +#define TCP_FIN 0x01 +#define TCP_SYN 0x02 +#define TCP_RST 0x04 +#define TCP_PSH 0x08 +#define TCP_ACK 0x10 +#define TCP_URG 0x20 + +/** Connections **/ + +/* Connection structure */ +struct http_connection { + unsigned char next_outseqno[4]; + unsigned char final_outseqno[4]; + unsigned char current_inseqno[4]; +#ifndef IPV6 + unsigned char ip_addr[4]; +#endif + const struct output_handler_t * /*CONST_VAR*/ output_handler; + + unsigned char port[2]; + unsigned char cwnd[2]; + unsigned char inflight[2]; + + unsigned const char * /*CONST_VAR*/ blob; +#ifndef DISABLE_ARGS + struct args_t *args; + unsigned char *curr_arg; + unsigned char arg_ref_index; +#endif +#ifndef DISABLE_TIMERS + unsigned char transmission_time; +#endif + uint16_t tcp_mss: 12; + enum tcp_state_e {tcp_listen, tcp_syn_rcvd, tcp_established, tcp_closing, tcp_last_ack} tcp_state: 3; + enum parsing_state_e {parsing_out, parsing_cmd, parsing_url, parsing_end} parsing_state: 2; +#ifndef DISABLE_COMET + unsigned char comet_passive: 1; + unsigned char comet_send_ack: 1; + unsigned char comet_streaming: 1; +#endif + struct generator_service_t *generator_service; + + struct http_connection *next; + struct http_connection *prev; +#ifdef IPV6 + unsigned char ip_addr[0]; +#endif +}; + +/* Loop on each connection */ +#define FOR_EACH_CONN(item, code) \ + if(all_connections) { \ + struct http_connection *(item) = all_connections; \ + do { \ + {code} \ + (item) = (item)->next; \ + } while((item) != all_connections); \ + } \ + +/* Pseudo connection for RST */ +struct http_rst_connection { +#ifdef IPV6 + unsigned char ip_addr[16]; +#else + unsigned char ip_addr[4]; +#endif + unsigned char current_inseqno[4]; + unsigned char next_outseqno[4]; + unsigned char port[2]; +}; + +/* Shared global connections structures */ +extern struct http_connection *all_connections; +extern struct http_rst_connection rst_connection; + +/* Local IP address */ +#ifdef IPV6 +extern unsigned char local_ip_addr[16]; +extern char ipcmp(unsigned char source_addr[], unsigned char check_addr[]); +extern unsigned char * decompress_ip(unsigned char comp_ip_addr[], unsigned char full_ip_addr[], unsigned char indexes); +extern unsigned char * compress_ip(unsigned char full_ip_addr[], unsigned char comp_ip_addr[], unsigned char * indexes); +#else +extern unsigned char local_ip_addr[4]; +#endif + +/* Shared funuctions */ +extern char something_to_send(const struct http_connection *connection); +extern void free_connection(const struct http_connection *connection); + +#endif /* __CONNECTIONS_H__ */ diff --git a/core/coroutines.c b/core/coroutines.c new file mode 100644 index 0000000000000000000000000000000000000000..5998399bd0b5e4ff351b28e412329be78e8a3e62 --- /dev/null +++ b/core/coroutines.c @@ -0,0 +1,231 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "coroutines.h" +#include "output.h" +#include "connections.h" +#include "memory.h" + +/* Stack pointer of the main program */ +#ifdef USE_FRAME_POINTER +volatile void *main_sp[2]; +#else +volatile void *main_sp[1]; +#endif + +/* Shared stack used for the execution of all coroutines */ +static char shared_stack[STACK_SIZE]; +/* The coroutine currently using the stack */ +static struct coroutine_t *cr_in_stack; +/* Currently running coroutine. Null when the main program is running. */ +static volatile struct coroutine_t *current_cr; + +/* initialize a coroutine structure */ +void cr_init(struct coroutine_t *coroutine) { + coroutine->curr_context.status = cr_ready; + coroutine->curr_context.stack = NULL; + coroutine->curr_context.stack_size = 0; + /* the stack pointer starts at the end of the shared stack */ + coroutine->curr_context.sp[0] = shared_stack + STACK_SIZE; +#ifdef USE_FRAME_POINTER + coroutine->curr_context.sp[1] = shared_stack + STACK_SIZE; +#endif +} + +/* run a context or return to main program (if coroutine is NULL) */ +void cr_run(struct coroutine_t *coroutine) { + /* push all working registers */ + PUSHREGS; + /* backup current context stack pointer(s) */ + if(current_cr) { + BACKUP_CTX(current_cr->curr_context.sp); + } else { + BACKUP_CTX(main_sp); + } + /* set new current context */ + current_cr = coroutine; + if(current_cr) { + RESTORE_CTX(current_cr->curr_context.sp); + /* test if this is the first time we run this context */ + if(current_cr->curr_context.status == cr_ready) { + current_cr->curr_context.status = cr_active; + current_cr->func(current_cr->args); + current_cr->curr_context.status = cr_terminated; + current_cr = NULL; + } + } + if(current_cr == NULL) { + /* restore the main program stack pointer if needed */ + RESTORE_CTX(main_sp); + } + /* pop all working registers */ + POPREGS; + return; +} + +/* prepare a coroutine for usage: the context is copied in the shared stack + * (which information is possibly backuped in the coroutine using it) */ +struct coroutine_t *cr_prepare(struct coroutine_t *coroutine) { + if(cr_in_stack != coroutine) { + if(cr_in_stack != NULL) { /* is there a coroutine currently using the shared stack? */ + /* backup its context in a freshly allocated buffer of the exact needed size */ + char *sp = cr_in_stack->curr_context.sp[0]; + uint16_t stack_size = shared_stack + STACK_SIZE - sp; + cr_in_stack->curr_context.stack = mem_alloc(stack_size); /* test NULL: done */ + if(cr_in_stack->curr_context.stack == NULL) { + return NULL; + } + cr_in_stack->curr_context.stack_size = stack_size; + /* process the copy from (big) shared stack to the new (small) buffer */ + memcpy(cr_in_stack->curr_context.stack, sp, stack_size); + } + if(coroutine->curr_context.stack != NULL) { /* does the new coroutine already has an allocated stack? */ + /* restore its context to the (big) shared stack */ + memcpy(coroutine->curr_context.sp[0], coroutine->curr_context.stack, coroutine->curr_context.stack_size); + /* deallocate the (small) previously used stack */ + mem_free(coroutine->curr_context.stack, coroutine->curr_context.stack_size); + coroutine->curr_context.stack = NULL; + } + /* update the cr_in_stack pointer */ + cr_in_stack = coroutine; + } + return cr_in_stack; +} + +/* deallocate the memory used by a coroutine (not including in-flight segments) */ +void cr_clean(struct coroutine_t *coroutine) { + if(cr_in_stack == coroutine) { + cr_in_stack = NULL; + } + mem_free(coroutine->curr_context.stack, coroutine->curr_context.stack_size); +} + +/* deallocate all the memory used by in-flight segments that are now acknowledged (with out_seqno < inack) */ +void clean_service(struct generator_service_t *service, unsigned char inack[]) { + struct in_flight_infos_t *last_if_ok = NULL; + struct in_flight_infos_t *first_if_out = service->in_flight_infos; + if(first_if_out) { + /* look for the first in-flight segment to be free'd (segments are sorted) */ + if(inack) { + while(first_if_out && UI32(first_if_out->next_outseqno) >= UI32(inack)) { + last_if_ok = first_if_out; + first_if_out = first_if_out->next; + } + } + + /* shorten the list */ + if(last_if_ok) { + last_if_ok->next = NULL; + } else { + service->in_flight_infos = NULL; + } + + /* free all acknowledged segment information */ + while(first_if_out) { + struct in_flight_infos_t *next = first_if_out->next; + if(service->is_persistent) { + mem_free((void *)first_if_out->infos.buffer, OUTPUT_BUFFER_SIZE); + } else { + mem_free((void *)first_if_out->infos.context->stack, first_if_out->infos.context->stack_size); + mem_free((void *)first_if_out->infos.context, sizeof(struct cr_context_t)); + } + mem_free((void *)first_if_out, sizeof(struct in_flight_infos_t)); + first_if_out = next; + } + } +} + +/* select the in-flight segment related to a given sequence number */ +struct in_flight_infos_t *if_select(struct generator_service_t *service, unsigned char next_outseqno[]) { + struct in_flight_infos_t *if_infos = service->in_flight_infos; + while(if_infos && UI32(if_infos->next_outseqno) != UI32(next_outseqno)) { + if_infos = if_infos->next; + } + return if_infos; +} + +/* add a new in-flight segment, associate a context to it */ +struct cr_context_t *context_backup(struct generator_service_t *service, unsigned char next_outseqno[], struct in_flight_infos_t *new_if_infos) { + char *sp = service->coroutine.curr_context.sp[0]; + uint16_t stack_size = shared_stack + STACK_SIZE - sp; + char *new_stack = NULL; + + /* try to allocate a context and a stack (exactly fitting the coroutine stack usage) */ + struct cr_context_t *new_context = mem_alloc(sizeof(struct cr_context_t)); /* test NULL: done */ + if(new_context == NULL) { + return NULL; + } + if(stack_size) { + new_stack = mem_alloc(stack_size); /* test NULL: done */ + if(new_stack == NULL) { + mem_free(new_context, sizeof(struct cr_context_t)); + return NULL; + } + } + + /* process the context copy */ + memcpy(new_context, &service->coroutine.curr_context, sizeof(struct cr_context_t)); + + /* process the stack copy */ + new_context->stack_size = stack_size; + if(new_context->stack_size) { + new_context->stack = new_stack; + memcpy(new_stack, sp, stack_size); + } else { + new_context->stack = NULL; + } + + /* update the in-flight segments list */ + UI32(new_if_infos->next_outseqno) = UI32(next_outseqno); + new_if_infos->infos.context = new_context; + new_if_infos->next = service->in_flight_infos; + + service->in_flight_infos = new_if_infos; + + return new_context; +} + +/* restore the context of a given in-flight segment (related to its sequence number) */ +struct in_flight_infos_t *context_restore(struct generator_service_t *service, unsigned char next_outseqno[]) { + struct in_flight_infos_t *if_infos = if_select(service, next_outseqno); + if(if_infos) { + /* copy the (small) context in if-infos in the (big) shared stack */ + memcpy(&service->coroutine.curr_context, if_infos->infos.context, sizeof(struct cr_context_t)); + if(if_infos->infos.context->stack) { + memcpy(service->coroutine.curr_context.sp[0], if_infos->infos.context->stack, if_infos->infos.context->stack_size); + } + } + return if_infos; +} diff --git a/core/coroutines.h b/core/coroutines.h new file mode 100644 index 0000000000000000000000000000000000000000..4e162887aac811a17f142c899dbfa72352c73476 --- /dev/null +++ b/core/coroutines.h @@ -0,0 +1,121 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __COROUTINES_H__ +#define __COROUTINES_H__ + +#include "types.h" +#include "handlers.h" +#include "memory.h" + +/* This module provides the coroutines used for dynamic content generation. + * All coroutines are axecuted in a single shared context. + * Their context (part of stack used) can be backuped and restored. + * In-flight segments are managed here: informations about all unacknowledged + * segments are chained and contain enough information to resend the segment + * when needed: either the data buffer or the routine context before generation. + * */ + +/* Types used for coroutines */ + +typedef char (cr_func)(struct args_t *args); + +/* A context (possibly several per coroutine) */ +struct cr_context_t { +#ifdef USE_FRAME_POINTER + void *sp[2]; +#else + void *sp[1]; +#endif + void *stack; + unsigned stack_size: 14; + enum cr_status { cr_ready, cr_active, cr_terminated } status: 2; +}; + +/* A coroutine, including its current context (one per service) */ +struct coroutine_t { + cr_func *func; + struct args_t *args; + struct cr_context_t curr_context; +}; + +/* Types used for in-flight segments */ + +/* Possible http headers being used */ +enum service_header_e { header_none, header_standard, header_chunks }; + +/* Information about one in-flight segment (several per service) */ +struct in_flight_infos_t { + unsigned char next_outseqno[4]; /* associated sequence number */ + unsigned char checksum[2]; /* segment checksum */ + union if_infos_e { /* either a coroutine context or a data buffer */ + struct cr_context_t *context; + char *buffer; + } infos; + struct in_flight_infos_t *next; /* the next in-flight segment */ + enum service_header_e service_header: 2; /* http header infos */ +}; + +/* Structure used to store information about the service of a generator */ +struct generator_service_t { + unsigned char curr_outseqno[4]; + struct coroutine_t coroutine; + struct in_flight_infos_t *in_flight_infos; + enum service_header_e service_header: 2; + unsigned is_persistent: 1; +}; + +/* Functions and variables for coroutines */ + +/* initialize a coroutine structure */ +extern void cr_init(struct coroutine_t *coroutine); +/* prepare a coroutine for usage: the context is copied in the shared stack + * (which information is possibly backuped in the coroutine using it) */ +extern struct coroutine_t *cr_prepare(struct coroutine_t *coroutine); +/* run a context or return to main program (if coroutine is NULL) */ +extern void cr_run(struct coroutine_t *coroutine); +/* deallocate the memory used by a coroutine (not including in-flight segments) */ +extern void cr_clean(struct coroutine_t *coroutine); +/* deallocate all the memory used by in-flight segments that are now acknowledged (with out_seqno < inack) */ +extern void clean_service(struct generator_service_t *service, unsigned char inack[]); + +/* select the in-flight segment related to a given sequence number */ +extern struct in_flight_infos_t *if_select(struct generator_service_t *service, unsigned char next_outseqno[]); +/* add a new in-flight segment, associate a context to it */ +extern struct cr_context_t *context_backup(struct generator_service_t *service, unsigned char next_outseqno[], struct in_flight_infos_t *new_if_infos); +/* restore the context of a given in-flight segment (related to its sequence number) */ +extern struct in_flight_infos_t *context_restore(struct generator_service_t *service, unsigned char next_outseqno[]); + +#endif /* __COROUTINES_H__ */ diff --git a/core/generators.c b/core/generators.c new file mode 100644 index 0000000000000000000000000000000000000000..b5eeb824b328094b1031b9a5b492cf29d289ec71 --- /dev/null +++ b/core/generators.c @@ -0,0 +1,80 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "generators.h" +#include "output.h" +#include "connections.h" +#include "memory.h" + +#ifndef DISABLE_COMET +/*-----------------------------------------------------------------------------------*/ +char server_push(const struct output_handler_t *push_handler /*CONST_VAR*/) { + uint16_t x; + x = 0; + if(push_handler->handler_comet) { + FOR_EACH_CONN(conn, { + if(conn->output_handler == push_handler) { + conn->comet_send_ack = 0; + UI32(conn->final_outseqno) = UI32(conn->next_outseqno) - 1; + } + }) + return 1; + } else { + return 0; + } +} +#endif + +/*-----------------------------------------------------------------------------------*/ +void out_uint(uint16_t i) { + char buffer[6]; + char *c = buffer + 5; + buffer[5] = '\0'; + do { + *--c = (i % 10) + '0'; + i /= 10; + } while(i); + while(*c) { + out_c(*c++); + } +} + +/*-----------------------------------------------------------------------------------*/ +void out_str(const char str[]) { + const char *c = str; + while(*c) { + out_c(*c++); + } +} diff --git a/core/generators.h b/core/generators.h new file mode 100644 index 0000000000000000000000000000000000000000..bca090ce4e3bc0c8c7511a18b79470784900bfa8 --- /dev/null +++ b/core/generators.h @@ -0,0 +1,52 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __GENERATOR_H__ +#define __GENERATOR_H__ + +#include "types.h" +#include "handlers.h" +#include "memory.h" + +/* Triggers a Comet channel */ +#ifndef DISABLE_COMET +extern char server_push(const struct output_handler_t * /*CONST_VAR*/ push_handler); +#endif +/* Used to output a char, an unisnged int or a string */ +char out_c(char c); +extern void out_uint(uint16_t i); +extern void out_str(const char str[]); + +#endif /* __GENERATOR_H__ */ diff --git a/core/handlers.c b/core/handlers.c new file mode 100644 index 0000000000000000000000000000000000000000..41a54bc35adeb38e360bd91139dcfcbea4c9b916 --- /dev/null +++ b/core/handlers.c @@ -0,0 +1,75 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "handlers.h" +#include "connections.h" + +/* TCP control packets */ +CONST_VAR(struct output_handler_t, ref_synack) = { + .handler_type = type_control, + .handler_data = { + .control = { + .length = 4, + .flags = TCP_SYN | TCP_ACK + } + }, +}; +CONST_VAR(struct output_handler_t, ref_ack) = { + .handler_type = type_control, + .handler_data = { + .control = { + .length = 0, + .flags = TCP_ACK + } + }, +}; +CONST_VAR(struct output_handler_t, ref_finack) = { + .handler_type = type_control, + .handler_data = { + .control = { + .length = 0, + .flags = TCP_ACK | TCP_FIN + } + }, +}; +CONST_VAR(struct output_handler_t, ref_rst) = { + .handler_type = type_control, + .handler_data = { + .control = { + .length = 0, + .flags = TCP_RST | TCP_ACK + } + }, +}; diff --git a/core/handlers.h b/core/handlers.h new file mode 100644 index 0000000000000000000000000000000000000000..feacb25a7cf710e2f4b4ea2103d0651026e00d5a --- /dev/null +++ b/core/handlers.h @@ -0,0 +1,128 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __HANDLERS_H__ +#define __HANDLERS_H__ + +#include "types.h" + +/** Dynamic resources, static resources, TCP control **/ + +/* Args type */ +struct args_t; +/* Generator functions */ +typedef char (generator_init_func_t)(void); +typedef char (generator_initget_func_t)(struct args_t *); +typedef char (generator_doget_func_t)(struct args_t *); + +/* Generator: init and run functions */ +struct dynamic_resource { + generator_init_func_t *init; + generator_initget_func_t *initget; + generator_doget_func_t *doget; + enum prop_e { prop_persistent, prop_idempotent, prop_volatile } prop; +}; + +/* Static resource, including pre-calculated partiel checksums */ +struct static_resource { + uint32_t length; + CONST_VOID_P_VAR chk; + CONST_VOID_P_VAR data; +}; + +/* TCP control packet */ +struct tcp_control { + unsigned char length; + unsigned char flags; +}; + +/* External refs to TCP control packets */ +extern CONST_VAR(struct output_handler_t, ref_synack); +extern CONST_VAR(struct output_handler_t, ref_ack); +extern CONST_VAR(struct output_handler_t, ref_finack); +extern CONST_VAR(struct output_handler_t, ref_rst); + + +/** URLs arguments **/ + +#ifndef DISABLE_ARGS +/* Argument type */ +enum arg_type_e { + arg_str, arg_ui8, arg_ui16 +}; + +/* Argument reference */ +struct arg_ref_t { + enum arg_type_e arg_type; + unsigned char arg_size; + unsigned char arg_offset; +}; +#endif + + +/** Output handlers **/ + +/* handler structure to be served */ +struct output_handler_t { + enum handler_type_e {type_control, type_file, type_generator} handler_type; + unsigned char handler_comet; + unsigned char handler_stream; + union handler_data_u { + const struct tcp_control control; + const struct static_resource file; + const struct dynamic_resource generator; + } handler_data; +#ifndef DISABLE_ARGS + struct handler_args_t { + unsigned const char * /*CONST_VAR*/ args_tree; + const struct arg_ref_t * /*CONST_VAR*/ args_index; + uint16_t args_size; + } handler_args; +#endif +}; + +/* Macros for accessing output_handler structs */ +#define GET_CONTROL(r) ((r)->handler_data.control) +#define GET_FILE(r) ((r)->handler_data.file) +#define GET_GENERATOR(r) ((r)->handler_data.generator) +#define GET_FLAGS(r) (CONST_UI8((r)->handler_type) == type_control ? CONST_UI8(GET_CONTROL(r).flags) : (TCP_ACK | TCP_PSH)) + +/* Global output_handler table */ +extern CONST_VAR(const struct output_handler_t *, resources_index[]); + +/* URL tree: parsing an URL to retrieve an output_handler */ +extern CONST_VAR(unsigned char, urls_tree[]); + +#endif /* __HANDLERS_H__ */ diff --git a/core/input.c b/core/input.c new file mode 100644 index 0000000000000000000000000000000000000000..f4b4610f65bc0d7a380ba3b86c4a63a73a0e744b --- /dev/null +++ b/core/input.c @@ -0,0 +1,751 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "input.h" +#include "output.h" +#include "checksum.h" +#include "connections.h" +#include "timers.h" +#include "memory.h" +#include "coroutines.h" + +/* Used to dump the runtime stack */ +#ifdef STACK_DUMP + int16_t stack_i; + unsigned char *stack_base; +#endif + +/* "404 Not found" handler */ +#define http_404_handler apps_httpCodes_404_html_handler +extern CONST_VAR(struct output_handler_t, apps_httpCodes_404_html_handler); + +/* Maximal TCP MSS */ +#ifndef DEV_MTU + #define MAX_MSS 0xffff +#else + #define MAX_MSS (DEV_MTU - 40) +#endif + +/* IP and TCP constants */ +#define HTTP_PORT 80 +#define IP_PROTO_TCP 6 + +#ifndef IPV6 +#define IP_HEADER_SIZE 20 +#endif +#define TCP_HEADER_SIZE 20 + +/* TCP pre-calculated partial pseudo-header checksum (for incoming packets)*/ +#define TCP_PRECALC_CHECKSUM ((uint16_t)(0x0000ffff - (IP_PROTO_TCP - 0x15))) + +/* tcp constant checksum part: ip_proto_tcp from pseudoheader*/ +#define TCP_CHK_CONSTANT_PART (uint16_t)~IP_PROTO_TCP + +/* Initial sequence number */ +#define BASIC_SEQNO 0x42b7a491 + +/* Blob containing supported HTTP commands */ +static CONST_VAR(unsigned char, blob_http_rqt[]) = {'G','E','T',' ',128}; + +/* gets 16 bits and checks if nothing wrong appened */ +static char dev_get16(unsigned char *word) { + int16_t tmp; + DEV_GET(tmp); + if(tmp == -1) + return -1; + word[1] = tmp; + DEV_GET(tmp); + if(tmp == -1) + return -1; + word[0] = tmp; + return 1; +} + +/* gets 16 bits and checks if nothing wrong appened */ +static char dev_get32(unsigned char *dword) { + if(dev_get16(&dword[2]) == -1) + return -1; + if(dev_get16(&dword[0]) == -1) + return -1; + return 1; +} + +#ifdef IPV6 +/* gets 128 bits and checks if nothing wrong appened */ +static char dev_get128(unsigned char *dword) { + if(dev_get32(&dword[12]) == -1) + return -1; + if(dev_get32(&dword[8]) == -1) + return -1; + if(dev_get32(&dword[4]) == -1) + return -1; + if(dev_get32(&dword[0]) == -1) + return -1; + return 1; +} + +/* Get 2 bytes */ +#define DEV_GET16(c) { \ + if(dev_get16((unsigned char*)(c)) == -1) \ + return 1; \ +} +/* Get 4 bytes */ +#define DEV_GET32(c) { \ + if(dev_get32((unsigned char*)(c)) == -1) \ + return 1; \ +} + +/* Get 16 bytes */ +#define DEV_GET128(c) { \ + if(dev_get128((unsigned char*)(c)) == -1) \ + return 1; \ +} +#endif + +/* Get and checksum a byte */ +#define DEV_GETC(c) { int16_t getc; \ + DEV_GET(getc); \ + if(getc == -1) return 1; \ + c = getc; \ + checksum_add(c);} \ + +/* Get and checksum 2 bytes */ +#define DEV_GETC16(c) { \ + if(dev_get16((unsigned char*)(c)) == -1) \ + return 1; \ + checksum_add16(UI16(c)); \ +} + +/* Get and checksum 4 bytes */ +#define DEV_GETC32(c) { \ + if(dev_get32((unsigned char*)(c)) == -1) \ + return 1; \ + checksum_add32(c); \ +} + +#ifdef IPV6 +/* Get and checksum 16 bytes */ +#define DEV_GETC128(c) { \ + if(dev_get128((unsigned char*)(c)) == -1) \ + return 1; \ + checksum_add32(&c[12]); \ + checksum_add32(&c[8]); \ + checksum_add32(&c[4]); \ + checksum_add32(&c[0]); \ +} + +#endif + +/*-----------------------------------------------------------------------------------*/ +char smews_receive(void) { + /* local variables */ + unsigned char current_inseqno[4]; + unsigned char current_inack[4]; + unsigned char tmp_ui32[4]; + unsigned char tmp_ui16[2]; + uint16_t packet_length; + unsigned char tcp_header_length; + uint16_t segment_length; + struct http_connection *connection; + unsigned char tmp_char; + uint16_t x; + unsigned char new_tcp_data; + +#ifdef IPV6 + /* Full and compressed IPv6 adress of the received packet */ + unsigned char full_ipv6_addr[16]; + unsigned char comp_ipv6_addr[17]; /* 16 bytes (addr) + 1 byte (compression indexes) = 17 bytes */ +#endif + + /* variables used to defer processing with side effects until the incomming packet has been checked (with checksum) */ + unsigned char defer_clean_service = 0; + unsigned char defer_free_handler = 0; +#ifndef DISABLE_ARGS + struct args_t *defer_free_args; + uint16_t defer_free_args_size; +#endif + + /* tmp connection used to store the current state until checksums are checked */ + struct http_connection tmp_connection; + + if(!DEV_DATA_TO_READ) + return 0; + +#ifdef IPV6 + /* Get IP Version (and 4 bits of the traffic class) */ + DEV_GET(tmp_char); +#else + checksum_init(); + + /* get IP version & header length */ + DEV_GETC(tmp_char); +#endif + + +#ifdef SMEWS_RECEIVING + SMEWS_RECEIVING; +#endif + /* Starting to decode IP */ +#ifdef IPV6 + /* 0x06 : IPV6, 4 bits right because we don't care (yet?) + about the Traffic Class */ + if(tmp_char>>4 != 0x6) +#else + /* 0x45 : IPv4, no option in header */ + if(tmp_char != 0x45) +#endif + return 1; + +#ifdef IPV6 + /* Discard the rest of the traffic class and the Flow Label (still unused) */ + DEV_GET(tmp_char); + DEV_GET16(tmp_ui16); + + /* Get IP packet payload length in len */ + DEV_GET16(((uint16_t *)&packet_length)); + + /* What's the next header? It should (must!) be TCP... */ + DEV_GET(tmp_char); + if (tmp_char != IP_PROTO_TCP) + return 1; + + /* We don't care about the Hop Limit (TTL) */ + DEV_GET(tmp_char); + + /* get & store IP source address */ + DEV_GET128(&full_ipv6_addr[0]); + + /* Compress the received IPv6 adress + compress_ip(FullIPv6, IP's Offset, Indexe's offset) */ + compress_ip(full_ipv6_addr, comp_ipv6_addr+1, &comp_ipv6_addr[0]); + + /* discard the dest IP */ + DEV_GET32(tmp_ui32); + DEV_GET32(tmp_ui32); + DEV_GET32(tmp_ui32); + DEV_GET32(tmp_ui32); +#else + /* discard IP type of service */ + DEV_GETC(tmp_char); + + /* get IP packet length in len */ + DEV_GETC16(((uint16_t *)&packet_length)); + + /* discard IP ID */ + DEV_GETC16(tmp_ui16); + + /* get IP fragmentation flags (fragmentation is not supported) */ + DEV_GETC16(tmp_ui16); + if((tmp_ui16[S0] & 0x20) || (tmp_ui16[S0] & 0x1f) != 0) + return 1; + + /* get IP fragmentation offset */ + if(tmp_ui16[S1] != 0) + return 1; + + /* discard IP TTL */ + DEV_GETC16(tmp_ui16); + /* get IP protocol, only TCP is supported */ + if(tmp_ui16[S1] != IP_PROTO_TCP) + return 1; + + /* discard IP checksum */ + DEV_GETC16(tmp_ui16); + + /* get & store IP source address */ + DEV_GETC32(tmp_connection.ip_addr); + + /* discard the IP destination address 2*16*/ + DEV_GETC32(tmp_ui32); + + /* check IP checksum */ + checksum_end(); + + if(UI16(current_checksum) != 0xffff) + return 1; +#endif + + /* End of IP, starting TCP */ + checksum_init(); + + /* get TCP source port */ + DEV_GETC16(tmp_connection.port); + + /* current connection selection */ + connection = NULL; + /* search an existing TCP connection using the current port */ +#ifdef IPV6 + FOR_EACH_CONN(conn, { + if(UI16(conn->port) == UI16(tmp_connection.port) && + ipcmp(conn->ip_addr, comp_ipv6_addr)) { + /* connection already existing */ + connection = conn; + break; + } + }) +#else + FOR_EACH_CONN(conn, { + if(UI16(conn->port) == UI16(tmp_connection.port) && + UI32(conn->ip_addr) == UI32(tmp_connection.ip_addr)) { + /* connection already existing */ + connection = conn; + break; + } + }) +#endif + + if(connection) { + /* a connection has been found */ + tmp_connection = *connection; + } else { + tmp_connection.tcp_state = tcp_listen; + tmp_connection.output_handler = NULL; + UI32(tmp_connection.next_outseqno) = BASIC_SEQNO; + UI32(tmp_connection.current_inseqno) = 0; + tmp_connection.parsing_state = parsing_out; + UI16(tmp_connection.inflight) = 0; + tmp_connection.generator_service = NULL; +#ifndef DISABLE_COMET + tmp_connection.comet_send_ack = 0; + tmp_connection.comet_passive = 0; +#endif +#ifndef DISABLE_TIMERS + tmp_connection.transmission_time = last_transmission_time; +#endif + } + + /* get and check the destination port */ + + DEV_GETC16(tmp_ui16); + if(tmp_ui16[S1] != HTTP_PORT) { +#ifdef STACK_DUMP + DEV_PREPARE_OUTPUT(STACK_DUMP_SIZE); + for(stack_i = 0; stack_i < STACK_DUMP_SIZE ; stack_i++) { + DEV_PUT(stack_base[-stack_i]); + } + DEV_OUTPUT_DONE; +#endif + return 1; + } + + /* get TCP sequence number */ + DEV_GETC32(current_inseqno); + + /* get TCP ack */ + DEV_GETC32(current_inack); + + /* duplicate ACK: set nextoutseqno for retransmission */ + if(UI32(tmp_connection.next_outseqno) - UI16(tmp_connection.inflight) == UI32(current_inack)) { + UI32(tmp_connection.next_outseqno) = UI32(current_inack); + } + + /* TCP ack management */ + if(UI32(current_inack) && UI32(current_inack) <= UI32(tmp_connection.next_outseqno)) { + UI16(tmp_connection.inflight) = UI32(tmp_connection.next_outseqno) - UI32(current_inack); + if(tmp_connection.generator_service) { + /* deferred because current segment has not yet been checked */ + defer_clean_service = 1; + } + } + + /* clear output_handler if needed */ + if(tmp_connection.output_handler && UI16(tmp_connection.inflight) == 0 && !something_to_send(&tmp_connection)) { + if(tmp_connection.generator_service) { + /* deferred because current segment has not yet been checked */ + defer_free_handler = 1; +#ifndef DISABLE_ARGS + defer_free_args = tmp_connection.args; + defer_free_args_size = CONST_UI16(tmp_connection.output_handler->handler_args.args_size); +#endif + } + if(tmp_connection.comet_streaming == 0) { + tmp_connection.output_handler = NULL; + } + } + + /* get TCP offset and flags */ + DEV_GETC16(tmp_ui16); + tcp_header_length = (tmp_ui16[S0] >> 4) * 4; + + /* TCP segment length calculation */ +#ifdef IPV6 + segment_length = packet_length - tcp_header_length; + + if(packet_length - tcp_header_length > 0) + UI32(current_inseqno) += segment_length; +#else + segment_length = packet_length - IP_HEADER_SIZE - tcp_header_length; + + /* calculation of the next sequence number we have to acknowledge */ + if(packet_length - IP_HEADER_SIZE - tcp_header_length > 0) + UI32(current_inseqno) += segment_length; +#endif + + new_tcp_data = UI32(current_inseqno) > UI32(tmp_connection.current_inseqno); + + if(UI32(current_inseqno) >= UI32(tmp_connection.current_inseqno)) { + UI32(tmp_connection.current_inseqno) = UI32(current_inseqno); + /* TCP state machine management */ + switch(tmp_connection.tcp_state) { + case tcp_established: + if(tmp_ui16[S1] & TCP_FIN) { + tmp_connection.tcp_state = tcp_last_ack; + tmp_connection.output_handler = &ref_finack; + UI32(tmp_connection.current_inseqno)++; + } else if(tmp_ui16[S1] & TCP_RST) { + tmp_connection.tcp_state = tcp_listen; + } + break; + case tcp_listen: + if(tmp_ui16[S1] & TCP_SYN) { + tmp_connection.tcp_state = tcp_syn_rcvd; + tmp_connection.output_handler = &ref_synack; + UI32(tmp_connection.current_inseqno)++; + } + break; + case tcp_syn_rcvd: + if(UI16(tmp_connection.inflight) == 0) { + tmp_connection.tcp_state = tcp_established; + } else { + tmp_connection.output_handler = &ref_synack; + } + break; + case tcp_last_ack: + tmp_connection.tcp_state = tcp_listen; + break; + default: + break; + } + } + + /* get the advertissed TCP window in order to limit our sending rate if needed */ + DEV_GETC16(tmp_connection.cwnd); + + /* discard the checksum (which is checksummed as other data) and the urgent pointer */ + DEV_GETC32(tmp_ui32); + + /* add the changing part of the TCP pseudo header checksum */ +#ifdef IPV6 + checksum_add32(&local_ip_addr[0]); + checksum_add32(&local_ip_addr[4]); + checksum_add32(&local_ip_addr[8]); + checksum_add32(&local_ip_addr[12]); + + checksum_add32(&full_ipv6_addr[0]); + checksum_add32(&full_ipv6_addr[4]); + checksum_add32(&full_ipv6_addr[8]); + checksum_add32(&full_ipv6_addr[12]); + checksum_add16(packet_length); +#else + checksum_add32(local_ip_addr); + checksum_add32(tmp_connection.ip_addr); + checksum_add16(packet_length - IP_HEADER_SIZE); +#endif + + /* get TCP mss (for initial negociation) */ + tcp_header_length -= TCP_HEADER_SIZE; + if(tcp_header_length >= 4) { + tcp_header_length -= 4; + DEV_GETC16(tmp_ui16); + DEV_GETC16(tmp_ui16); + tmp_connection.tcp_mss = UI16(tmp_ui16) > MAX_MSS ? MAX_MSS : UI16(tmp_ui16); + } + + /* discard the remaining part of the TCP header */ + for(; tcp_header_length > 0; tcp_header_length-=4) { + DEV_GETC32(tmp_ui32); + } + + /* End of TCP, starting HTTP */ + x = 0; + if(segment_length && tmp_connection.tcp_state == tcp_established && (new_tcp_data || tmp_connection.output_handler == NULL)) { + const struct output_handler_t * /*CONST_VAR*/ output_handler = NULL; + + /* parse the eventual GET request */ + unsigned const char * /*CONST_VAR*/ blob; + unsigned char blob_curr; +#ifndef DISABLE_ARGS + struct arg_ref_t tmp_arg_ref = {0,0,0}; +#endif + + if(tmp_connection.parsing_state == parsing_out) { +#ifndef DISABLE_ARGS + tmp_connection.args = NULL; + tmp_connection.arg_ref_index = 128; +#endif + tmp_connection.blob = blob_http_rqt; + tmp_connection.parsing_state = parsing_cmd; + } + + blob = tmp_connection.blob; + +#ifndef DISABLE_ARGS + if(tmp_connection.arg_ref_index != 128) { + struct arg_ref_t * /*CONST_VAR*/ tmp_arg_ref_ptr; + tmp_arg_ref_ptr = &(((struct arg_ref_t*)CONST_ADDR(output_handler->handler_args.args_index))[tmp_connection.arg_ref_index]); + tmp_arg_ref.arg_type = CONST_UI8(tmp_arg_ref_ptr->arg_type); + tmp_arg_ref.arg_size = CONST_UI8(tmp_arg_ref_ptr->arg_size); + tmp_arg_ref.arg_offset = CONST_UI8(tmp_arg_ref_ptr->arg_offset); + } +#endif + + while(x < segment_length && output_handler != &http_404_handler) { + x++; + DEV_GETC(tmp_char); + blob_curr = CONST_READ_UI8(blob); + /* search for the web applicative resource to send */ + if(blob_curr >= 128 && output_handler != &http_404_handler) { + if(tmp_connection.parsing_state == parsing_cmd) { + tmp_connection.parsing_state = parsing_url; + blob = urls_tree; + } else { + if(tmp_char == ' ') { + if(!output_handler) + output_handler = (struct output_handler_t*)CONST_ADDR(resources_index[blob_curr - 128]); + break; + } else { +#ifndef DISABLE_ARGS + if(tmp_char == '?') { + uint16_t tmp_args_size; + output_handler = (struct output_handler_t*)CONST_ADDR(resources_index[blob_curr - 128]); + tmp_args_size = CONST_UI16(output_handler->handler_args.args_size); + if(tmp_args_size) { + uint16_t i; + blob = (const unsigned char *)CONST_ADDR(output_handler->handler_args.args_tree); + tmp_connection.args = mem_alloc(tmp_args_size); /* test NULL: done */ + if(tmp_connection.args == NULL) { + output_handler = &http_404_handler; + break; + } + for(i = 0; i < tmp_args_size ; i++) { + ((unsigned char *)tmp_connection.args)[i] = 0; + } + continue; + } + } else if(tmp_char == '=' && tmp_connection.args) { + struct arg_ref_t * /*CONST_VAR*/ tmp_arg_ref_ptr; + tmp_connection.arg_ref_index = blob_curr - 128; + tmp_arg_ref_ptr = &(((struct arg_ref_t*)CONST_ADDR(output_handler->handler_args.args_index))[tmp_connection.arg_ref_index]); + tmp_arg_ref.arg_type = CONST_UI8(tmp_arg_ref_ptr->arg_type); + tmp_arg_ref.arg_size = CONST_UI8(tmp_arg_ref_ptr->arg_size); + tmp_arg_ref.arg_offset = CONST_UI8(tmp_arg_ref_ptr->arg_offset); + tmp_connection.curr_arg = ((unsigned char*)tmp_connection.args) + tmp_arg_ref.arg_offset; + if(tmp_arg_ref.arg_type == arg_str) + (*((unsigned char*)tmp_connection.curr_arg + tmp_arg_ref.arg_size - 1)) = tmp_arg_ref.arg_size - 1; + continue; + } else if(tmp_char == '&') { + blob = (const unsigned char *)CONST_ADDR(output_handler->handler_args.args_tree); + } else { + blob++; + } +#else + blob++; +#endif + } + } + blob_curr = CONST_READ_UI8(blob); + } +#ifndef DISABLE_ARGS + if(tmp_connection.arg_ref_index != 128) { + if(tmp_char == '&') { + tmp_connection.arg_ref_index = 128; + blob = (const unsigned char *)CONST_ADDR(output_handler->handler_args.args_tree); + continue; + } else if(tmp_char == ' ') { + break; + } else { + switch(tmp_arg_ref.arg_type) { + case arg_str: { + unsigned char *tmp_size_ptr = ((unsigned char*)tmp_connection.curr_arg + tmp_arg_ref.arg_size - 1); + if(*tmp_size_ptr) { + *((unsigned char*)tmp_connection.curr_arg + (tmp_arg_ref.arg_size - *tmp_size_ptr - 1)) = tmp_char; + (*tmp_size_ptr)--; + } + break; + } + case arg_ui8: + *((unsigned char*)tmp_connection.curr_arg) *= 10; + *((unsigned char*)tmp_connection.curr_arg) += tmp_char - '0'; + break; + case arg_ui16: + *((uint16_t*)tmp_connection.curr_arg) *= 10; + *((uint16_t*)tmp_connection.curr_arg) += tmp_char - '0'; + break; + } + } + } else +#endif + { + do { + unsigned char offsetInf = 0; + unsigned char offsetEq = 0; + unsigned char blob_next; + blob_curr = CONST_READ_UI8(blob); + blob_next = CONST_READ_UI8(++blob); + if (tmp_char != blob_curr && blob_next >= 128) { + blob_next = CONST_READ_UI8(++blob); + } + if (blob_next < 32) { + offsetInf += ((blob_next>>2) & 1) + ((blob_next>>1) & 1) + (blob_next & 1); + offsetEq = offsetInf + ((blob_next & 2)?CONST_READ_UI8(blob+1):0); + } + if (tmp_char == blob_curr) { + if (blob_next < 32) { + if (blob_next & 2) { + blob += offsetEq; + } else { + output_handler = &http_404_handler; + break; + } + } + break; + } else if (tmp_char < blob_curr) { + if (blob_next < 32 && blob_next & 1) { + blob += offsetInf; + } else { + output_handler = &http_404_handler; + break; + } + } else { + if (blob_next < 32 && blob_next & 4) { + unsigned char offsetSup = offsetEq + ((blob_next & 3)?CONST_READ_UI8(blob+(offsetInf-1)):0); + blob += offsetSup; + } else { + output_handler = &http_404_handler; + break; + } + } + } while(1); + } + } + + if(!output_handler) { + tmp_connection.blob = blob; + } else { + if(tmp_connection.parsing_state != parsing_cmd) { + tmp_connection.output_handler = output_handler; + UI32(tmp_connection.next_outseqno) = UI32(current_inack); + if(CONST_UI8(output_handler->handler_type) == type_file) { + UI32(tmp_connection.final_outseqno) = UI32(tmp_connection.next_outseqno) + CONST_UI32(GET_FILE(output_handler).length); + } else { + UI32(tmp_connection.final_outseqno) = UI32(tmp_connection.next_outseqno) - 1; + } +#ifndef DISABLE_COMET + tmp_connection.comet_send_ack = CONST_UI8(output_handler->handler_comet) ? 1 : 0; + tmp_connection.comet_passive = 0; + tmp_connection.comet_streaming = 0; +#endif + } + tmp_connection.parsing_state = parsing_out; + tmp_connection.blob = blob_http_rqt; +#ifndef DISABLE_ARGS + tmp_connection.arg_ref_index = 128; +#endif + } + } + + /* drop remaining TCP data */ + while(x++ < segment_length) + DEV_GETC(tmp_char); + + /* acknowledge received and processed TCP data if no there is no current output_handler */ + if(!tmp_connection.output_handler && tmp_connection.tcp_state == tcp_established && segment_length) { + tmp_connection.output_handler = &ref_ack; + } + + /* check TCP checksum using the partially precalculated pseudo header checksum */ + checksum_end(); + if(UI16(current_checksum) == TCP_CHK_CONSTANT_PART) { + + if(defer_clean_service) { /* free in-flight segment information for acknowledged segments */ + clean_service(tmp_connection.generator_service, current_inack); + if(defer_free_handler) { /* free handler and generator service is the service is completely acknowledged */ + cr_clean(&tmp_connection.generator_service->coroutine); + mem_free(tmp_connection.generator_service, sizeof(struct generator_service_t)); + tmp_connection.generator_service = NULL; +#ifndef DISABLE_ARGS + mem_free(defer_free_args, defer_free_args_size); +#endif + } + } + + if(!connection && tmp_connection.tcp_state == tcp_syn_rcvd) { + /* allocate a new connection */ +#ifdef IPV6 + /* Size of a http_connection + size of the IPv6 adress (+ compression indexes) */ + connection = mem_alloc((sizeof(struct http_connection) + (17-((comp_ipv6_addr[0])&15))) * sizeof(unsigned char)); +#else + connection = mem_alloc(sizeof(struct http_connection)); /* test NULL: done */ +#endif + if(connection != NULL) { + /* insert the new connection */ + if(all_connections == NULL) { + tmp_connection.next = connection; + tmp_connection.prev = connection; + all_connections = connection; + } else { + tmp_connection.prev = all_connections->prev; + tmp_connection.prev->next = connection; + tmp_connection.next = all_connections; + all_connections->prev = connection; + } + } + } + + if(!connection) { + /* no valid connection has been found for this packet, send a reset */ + UI32(tmp_connection.next_outseqno) = UI32(current_inack); +#ifdef IPV6 + memcpy(rst_connection.ip_addr, full_ipv6_addr, 16); +#else + UI32(rst_connection.ip_addr) = UI32(tmp_connection.ip_addr); +#endif + UI16(rst_connection.port) = UI16(tmp_connection.port); + UI32(rst_connection.current_inseqno) = UI32(tmp_connection.current_inseqno); + UI32(rst_connection.next_outseqno) = UI32(tmp_connection.next_outseqno); + } else { + if(tmp_connection.tcp_state == tcp_listen) { + free_connection(connection); + } else { + /* update the current connection */ + *connection = tmp_connection; +#ifdef IPV6 + memcpy((*(connection)).ip_addr, comp_ipv6_addr, (17-((comp_ipv6_addr[0])&15))); +#endif + } + } + } + return 1; +} diff --git a/core/input.h b/core/input.h new file mode 100644 index 0000000000000000000000000000000000000000..b8641f63665406b2d1b9c066794b753288746195 --- /dev/null +++ b/core/input.h @@ -0,0 +1,52 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __RECEIVE_H__ +#define __RECEIVE_H__ + +#include "types.h" + +/* Used to dump the runtime stack */ +#ifdef STACK_DUMP + #define STACK_DUMP_SIZE 1024 + #define STACK_MAGIC 0x27 + extern int16_t stack_i; + extern unsigned char *stack_base; +#endif + +/* Receive and process a single packet. Returns 1 if a packet has been successfully processed, 0 else. */ +extern char smews_receive(void); + +#endif /* __RECEIVE_H__ */ diff --git a/core/main.c b/core/main.c new file mode 100644 index 0000000000000000000000000000000000000000..78d1c59b5e1c96f98989805e5773ee3a892b650f --- /dev/null +++ b/core/main.c @@ -0,0 +1,49 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* This file is the default main for libsmews.a. It simply runs Smews. An other +main function can be linked with libsmews.a, allowing to embed Smews in a third +party software. */ + +#include "smews.h" + +/*-----------------------------------------------------------------------------------*/ +int main(void) { + smews_init(); + while(1) { + smews_main_loop_step(); + } + return 0; +} diff --git a/core/memory.c b/core/memory.c new file mode 100644 index 0000000000000000000000000000000000000000..3260fa9397fcfddba130de8b8358413860aedd04 --- /dev/null +++ b/core/memory.c @@ -0,0 +1,141 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "target.h" + +struct free_bloc_s { + uint16_t size; + uint16_t to_next; +}; + +static uint32_t alloc_buffer[ALLOC_SIZE / 4 + 1]; +struct free_bloc_s *first_free; + +/* only used for monitoring/debugging purposes */ +int get_free_mem() { + int sum_free = 0; + struct free_bloc_s *curr_free = first_free; + while(curr_free->to_next) { + sum_free += curr_free->size; + curr_free += curr_free->to_next; + } + return sum_free * 4; +} + +/* reset the allocator (free all) */ +void mem_reset(void) { + first_free = (struct free_bloc_s *)alloc_buffer; + alloc_buffer[0] = (uint32_t)(ALLOC_SIZE/4) << 16 | (ALLOC_SIZE/4); +} + +/* try to allocate a bloc of at least size bytes (but multiple of 4) + * return NULL if failed */ +void *mem_alloc(uint16_t size) { + struct free_bloc_s *prev_free = NULL; + struct free_bloc_s *curr_free = first_free; + /* memory allocation internals work with 32 bits granularity */ + if(size % 4 > 0) { + size += 4; + } + size >>= 2; + /* look for a free bloc */ + while(curr_free->size && curr_free->size < size) { + prev_free = curr_free; + curr_free += curr_free->to_next; + } + /* update the free blocs chain */ + if(curr_free->size == size) { /* use the entire bloc */ + if(prev_free == NULL) { + first_free = curr_free + curr_free->to_next; + } else { + prev_free->to_next += curr_free->to_next; + } + } else if(curr_free->size >= size) { /* only use the beginning of the bloc */ + struct free_bloc_s *new_free = curr_free + size; + if(prev_free == NULL) { + first_free = new_free; + } else { + prev_free->to_next += size; + } + new_free->size = curr_free->size - size; + new_free->to_next = curr_free->to_next - size; + } else { /* no valid bloc has been found */ + + return NULL; + } + return curr_free; +} + +/* subroutine used to chain two consecutive (but not necessarly adjacent) blocs */ +static void chain_free_blocs(struct free_bloc_s *b1, struct free_bloc_s *b2) { + if(b1 + b1->size == b2) { + b1->to_next = b2->to_next + b1->size; + b1->size += b2->size; + } else { + b1->to_next = b2 - b1; + } +} + +/* free a bloc of at least size bytes (but multiple of 4). + * Only use on free data. */ +void mem_free(void *ptr, uint16_t size) { + if(ptr != NULL && size != 0) { + struct free_bloc_s *to_free = ptr; + struct free_bloc_s *prev_free = NULL; + struct free_bloc_s *curr_free = first_free; + /* memory allocation internals work with 32 bits granularity */ + if(size % 4 > 0) { + size += 4; + } + size >>= 2; + /* look for a free blocs around ptr */ + while(curr_free < to_free) { + prev_free = curr_free; + curr_free += curr_free->to_next; + } + to_free->size = size; + to_free->to_next = curr_free - to_free; + /* test if there is a bloc after ptr */ + if(curr_free->size) { + chain_free_blocs(to_free, curr_free); + } + /* test if there is a free bloc before ptr */ + if(prev_free) { + chain_free_blocs(prev_free, to_free); + } else { + first_free = to_free; + } + } +} diff --git a/core/memory.h b/core/memory.h new file mode 100644 index 0000000000000000000000000000000000000000..175119afb25fb65417e0abae2c842d9b41fc3400 --- /dev/null +++ b/core/memory.h @@ -0,0 +1,53 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* This module provides a simple dynamic memory allocator. Free blocs are + * chained, but no information is kept about allocated blocs. When freeing + * the size is required. Whatever the size argment, only multiple of + * 4 bytes are managed. + * BE CAREFULL: + * This memory allocator has been designed to be as small as possible, and + * has to be used only inside the Smews kernel. It has to be used only + * with corrects arguments (don't try to free non allocated data) +*/ + +/* reset the allocator (free all) */ +extern void mem_reset(void); +/* try to allocate a bloc of at least size bytes (but multiple of 4) + * return NULL if failed */ +extern void *mem_alloc(uint16_t size); +/* free a bloc of at least size bytes (but multiple of 4). + * Only use on free data. */ +extern void mem_free(void *ptr, uint16_t size); diff --git a/core/output.c b/core/output.c new file mode 100644 index 0000000000000000000000000000000000000000..71f4fe11841f8020d515f961b686b70f6f39e17b --- /dev/null +++ b/core/output.c @@ -0,0 +1,759 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "output.h" +#include "types.h" +#include "checksum.h" +#include "timers.h" +#include "coroutines.h" +#include "smews.h" +#include "connections.h" +#include "memory.h" + +/* IPV6 Common values */ +#ifdef IPV6 + +#define IP_VTRAFC_FLOWL ((uint32_t)0x60000000) +#define IP_NH_TTL ((uint16_t)0x0640) + +#endif + +/* Common values used for IP and TCP headers */ +#define MSS_OPT 0x0204 +#define IP_VHL_TOS ((uint16_t)0x4500) +#define IP_ID 0x0000 +#define IP_OFFSET 0x0000 +#define IP_TTL_PROTOCOL 0x4006 +#define TCP_SRC_PORT 0x0050 +#define TCP_WINDOW 0x1000 +#define TCP_URGP 0x0000 + +/* Pre-calculated partial IP checksum (for outgoing packets) */ +#define BASIC_IP_CHK 0x8506 +/* Pre-calculated partial TCP checksum (for outgoing packets) */ +#define BASIC_TCP_CHK 0x1056 + +/* Maximum output size depending on the MSS */ +#define MAX_OUT_SIZE(mss) ((mss) & (~0 << (CHUNCKS_NBITS))) + +/* Macros for static resources partial checksum blocks */ +#define CHUNCKS_SIZE (1 << CHUNCKS_NBITS) +#define DIV_BY_CHUNCKS_SIZE(l) ((l) >> CHUNCKS_NBITS) +#define MODULO_CHUNCKS_SIZE(l) ((l) & ~(~0 << (CHUNCKS_NBITS))) +#define GET_NB_BLOCKS(l) (DIV_BY_CHUNCKS_SIZE(l) + (MODULO_CHUNCKS_SIZE(l) != 0)) + +/* Connection handler callback */ +#ifndef DISABLE_ARGS +#define HANDLER_CALLBACK(connection,handler) { \ + if(CONST_ADDR(GET_GENERATOR((connection)->output_handler).handler) != NULL) \ + ((generator_ ## handler ## _func_t*)CONST_ADDR(GET_GENERATOR((connection)->output_handler).handler))((connection)->args);} +#else +#define HANDLER_CALLBACK(connection,handler) { \ + if(CONST_ADDR(GET_GENERATOR((connection)->output_handler).handler) != NULL) \ + ((handler generator_ ## handler ## _func_t*)CONST_ADDR(GET_GENERATOR((connection)->output_handler).handler))(NULL);} +#endif + +/* Partially pre-calculated HTTP/1.1 header with checksum */ +static CONST_VAR(char, serviceHttpHeader[]) = "HTTP/1.1 200 OK\r\nContent-Length:"; +static CONST_VAR(char, serviceHttpHeaderPart2[]) = "\r\nContent-Type: text/plain\r\n\r\n"; +static CONST_VAR(char, serviceHttpHeaderChunked[]) = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nTransfer-Encoding:chunked\r\n\r\n"; + +#define SERVICE_HTTP_HEADER_CHK 0x1871u +#define SERVICE_HTTP_HEADER_CHUNKED_CHK 0x2876u + +struct curr_output_t { + struct generator_service_t *service; + char *buffer; + unsigned char checksum[2]; + uint16_t content_length; + unsigned char next_outseqno[4]; + enum service_header_e service_header: 2; +}; +static struct curr_output_t curr_output; + +/* default DEV_PUT16 */ +#ifndef DEV_PUT16 +static void dev_put16(unsigned char *word) { + DEV_PUT(word[1]); + DEV_PUT(word[0]); +} + #define DEV_PUT16(w) dev_put16(w) +#endif + +static void dev_put16_val(uint16_t word) { + DEV_PUT(word >> 8); + DEV_PUT(word); +} +#define DEV_PUT16_VAL(w) dev_put16_val(w) + +/* default DEV_PUT32 */ +#ifndef DEV_PUT32 +static void dev_put32(unsigned char *dword) { + DEV_PUT16(dword+2); + DEV_PUT16(dword); +} + #define DEV_PUT32(dw) dev_put32(dw) +#endif + +#ifdef IPV6 +static void dev_put32_val(uint32_t word) { + DEV_PUT(word >> 24); + DEV_PUT(word >> 16); + DEV_PUT(word >> 8); + DEV_PUT(word); +} +#define DEV_PUT32_VAL(w) dev_put32_val(w) +#endif + +/* default DEV_PUTN */ +#ifndef DEV_PUTN + #define DEV_PUTN(ptr,n) { uint16_t i; \ + for(i = 0; i < (n); i++) { \ + DEV_PUT(ptr[i]); \ + } \ + } +#endif + +/* default DEV_PUTN_CONST */ +#ifndef DEV_PUTN_CONST + #define DEV_PUTN_CONST(ptr,n) { uint16_t i; \ + for(i = 0; i < (n); i++) { \ + DEV_PUT(CONST_READ_UI8((ptr) + i)); \ + } \ + } +#endif + +/*-----------------------------------------------------------------------------------*/ +char out_c(char c) { + if(curr_output.content_length == OUTPUT_BUFFER_SIZE) { + cr_run(NULL); + } + checksum_add(c); + curr_output.buffer[curr_output.content_length++] = c; + return 1; +} + +/*-----------------------------------------------------------------------------------*/ +void smews_send_packet(struct http_connection *connection) { + uint32_t index_in_file; + uint16_t segment_length; + unsigned char *ip_addr; + unsigned char *port; + unsigned char *next_outseqno; + unsigned char *current_inseqno; + const struct output_handler_t * /*CONST_VAR*/ output_handler; + enum handler_type_e handler_type; + /* buffer used to store the current content-length */ + #define CONTENT_LENGTH_SIZE 6 + #define CHUNK_LENGTH_SIZE 4 + char content_length_buffer[CONTENT_LENGTH_SIZE]; +#ifdef IPV6 + /* Full IPv6 adress of the packet */ + unsigned char full_ipv6_addr[16]; +#endif + +#ifdef SMEWS_SENDING + SMEWS_SENDING; +#endif + + if(connection) { +#ifndef DISABLE_TIMERS + connection->transmission_time = last_transmission_time; +#endif +#ifdef IPV6 + ip_addr = decompress_ip(connection->ip_addr+1,full_ipv6_addr,connection->ip_addr[0]); +#else + ip_addr = connection->ip_addr; +#endif + port = connection->port; + next_outseqno = connection->next_outseqno; + current_inseqno = connection->current_inseqno; + output_handler = connection->output_handler; + } else { + ip_addr = rst_connection.ip_addr; + port = rst_connection.port; + next_outseqno = rst_connection.next_outseqno; + current_inseqno = rst_connection.current_inseqno; + output_handler = &ref_rst; + } + handler_type = CONST_UI8(output_handler->handler_type); + + /* compute the length of the TCP segment to be sent */ + switch(handler_type) { + case type_control: + segment_length = CONST_UI8(GET_CONTROL(output_handler).length); + break; + case type_file: { + uint16_t max_out_size; + uint32_t file_remaining_bytes; + max_out_size = MAX_OUT_SIZE((uint16_t)connection->tcp_mss); + file_remaining_bytes = UI32(connection->final_outseqno) - UI32(next_outseqno); + segment_length = file_remaining_bytes > max_out_size ? max_out_size : file_remaining_bytes; + index_in_file = CONST_UI32(GET_FILE(output_handler).length) - file_remaining_bytes; + break; + } + case type_generator: + segment_length = curr_output.content_length; + switch(curr_output.service_header) { + case header_standard: + segment_length += sizeof(serviceHttpHeader) - 1 + sizeof(serviceHttpHeaderPart2) - 1 + CONTENT_LENGTH_SIZE; + break; + case header_chunks: + segment_length += sizeof(serviceHttpHeaderChunked) - 1; + case header_none: + segment_length += CHUNK_LENGTH_SIZE + 4; + break; + } + break; + } + + DEV_PREPARE_OUTPUT(segment_length + 40); + + /* start to send IP header */ +#ifdef IPV6 + + /* We are IPv6 (yeah!), without traffic class or flow label */ + DEV_PUT32_VAL(IP_VTRAFC_FLOWL); + + /* our payload length is */ + DEV_PUT16_VAL(segment_length + 20); + + /* We have TCP inside and Hop Limit is 64 */ + DEV_PUT16_VAL(IP_NH_TTL); + + /* Put source & dest IP */ + DEV_PUT32(&local_ip_addr[12]); + DEV_PUT32(&local_ip_addr[8]); + DEV_PUT32(&local_ip_addr[4]); + DEV_PUT32(&local_ip_addr[0]); + + DEV_PUT32(&ip_addr[12]); + DEV_PUT32(&ip_addr[8]); + DEV_PUT32(&ip_addr[4]); + DEV_PUT32(&ip_addr[0]); +#else + /* send vhl, tos, IP header length */ + DEV_PUT16_VAL(IP_VHL_TOS); + + /* send IP packet length */ + DEV_PUT16_VAL(segment_length + 40); + + /* send IP ID, offset, ttl and protocol (TCP) */ + DEV_PUT16_VAL(IP_ID); + DEV_PUT16_VAL(IP_OFFSET); + DEV_PUT16_VAL(IP_TTL_PROTOCOL); + + /* complete IP precalculated checksum */ + checksum_init(); + UI16(current_checksum) = BASIC_IP_CHK; + checksum_add32(local_ip_addr); + checksum_add16(segment_length + 40); + + checksum_add32(ip_addr); + checksum_end(); + + /* send IP checksum */ + DEV_PUT16_VAL(~UI16(current_checksum)); + + /* send IP source address */ + DEV_PUT32(local_ip_addr); + + /* send IP destination address */ + DEV_PUT32(ip_addr); +#endif + + /* start to send TCP header */ + + /* send TCP source port */ + DEV_PUT16_VAL(TCP_SRC_PORT); + + /* send TCP destination port */ + DEV_PUT16(port); + + /* send TCP sequence number */ + DEV_PUT32(next_outseqno); + + /* send TCP acknowledgement number */ + DEV_PUT32(current_inseqno); + + /* send TCP header length & flags */ + DEV_PUT(GET_FLAGS(output_handler) & TCP_SYN ? 0x60 : 0x50); + DEV_PUT(GET_FLAGS(output_handler)); + + /* send TCP window */ + DEV_PUT16_VAL(TCP_WINDOW); + + /* complete precalculated TCP checksum */ + + checksum_init(); + UI16(current_checksum) = BASIC_TCP_CHK; +#ifdef IPV6 + checksum_add32(&local_ip_addr[0]); + checksum_add32(&local_ip_addr[4]); + checksum_add32(&local_ip_addr[8]); + checksum_add32(&local_ip_addr[12]); +#else + checksum_add32(local_ip_addr); +#endif + + checksum_add16(segment_length + 20); + + checksum_add32(next_outseqno); + + checksum_add(GET_FLAGS(output_handler) & TCP_SYN ? 0x60 : 0x50); + checksum_add(GET_FLAGS(output_handler)); + +#ifdef IPV6 + checksum_add32(&ip_addr[0]); + checksum_add32(&ip_addr[4]); + checksum_add32(&ip_addr[8]); + checksum_add32(&ip_addr[12]); +#else + checksum_add32(ip_addr); +#endif + + checksum_add16(UI16(port)); + + checksum_add32(current_inseqno); + + /* HTTP contents checksum part */ + switch(handler_type) { + case type_generator: + /* add service checksum */ + checksum_add16(UI16(curr_output.checksum)); + /* add HTTP header checksum */ + switch(curr_output.service_header) { + uint16_t length; + int16_t i; + case header_standard: + checksum_add16(SERVICE_HTTP_HEADER_CHK); + /* create the HTTP Content-Length string on a even number of chars and start computing service checksum */ + checksum_add(0); /* odd bytes alignement */ + length = curr_output.content_length; + for(i = CONTENT_LENGTH_SIZE - 1; i >= 0; i--) { + unsigned char c = (length % 10) + '0'; + content_length_buffer[i]= c; + checksum_add(c); + length /= 10; + } + checksum_add(0); /* remove odd bytes alignement */ + break; + case header_chunks: + checksum_add16(SERVICE_HTTP_HEADER_CHUNKED_CHK); + case header_none: + checksum_add(0); /* odd bytes alignement */ + length = curr_output.content_length; + for(i = CHUNK_LENGTH_SIZE - 1; i >= 0; i--) { + unsigned char c = (length & 0x0f) + '0'; + if(c > '9') + c += -'0' + 'a' - 10; + content_length_buffer[i]= c; + checksum_add(c); + length >>= 4; + } + checksum_add(0); /* remove odd bytes alignement */ + checksum_add16(0x0d0a); + if(curr_output.content_length % 2) { + checksum_add16(0x0a0d); + } else { + checksum_add16(0x0d0a); + } + break; + } + break; + case type_control: + if(GET_FLAGS(output_handler) & TCP_SYN){ /* Checksum the syn ack tcp options (MSS) */ + checksum_add16(MSS_OPT); + checksum_add16((uint16_t)connection->tcp_mss); + } + break; + case type_file: { + uint16_t i; + uint32_t tmp_sum = 0; + uint16_t *tmpptr = (uint16_t *)CONST_ADDR(GET_FILE(output_handler).chk) + DIV_BY_CHUNCKS_SIZE(index_in_file); + + for(i = 0; i < GET_NB_BLOCKS(segment_length); i++) { + tmp_sum += CONST_READ_UI16(tmpptr++); + } + checksum_add32((const unsigned char*)&tmp_sum); + break; + } + } + + checksum_end(); + + /* send TCP checksum */ + DEV_PUT16_VAL(~UI16(current_checksum)); + + /* send TCP urgent pointer */ + DEV_PUT16_VAL(TCP_URGP); + + /* start sending HTTP contents */ + switch(handler_type) { + case type_generator: + switch(curr_output.service_header) { + case header_standard: + DEV_PUTN_CONST(serviceHttpHeader, sizeof(serviceHttpHeader)-1); + DEV_PUTN(content_length_buffer, CONTENT_LENGTH_SIZE); + DEV_PUTN_CONST(serviceHttpHeaderPart2, sizeof(serviceHttpHeaderPart2)-1); + break; + case header_chunks: + DEV_PUTN_CONST(serviceHttpHeaderChunked, sizeof(serviceHttpHeaderChunked)-1); + case header_none: + DEV_PUTN(content_length_buffer, CHUNK_LENGTH_SIZE); + DEV_PUT16_VAL(0x0d0a); + break; + } + DEV_PUTN(curr_output.buffer, curr_output.content_length); + if(curr_output.service_header != header_standard) { + DEV_PUT16_VAL(0x0d0a); + } + break; + case type_control: + if(GET_FLAGS(output_handler) & TCP_SYN) { + /* Send the syn ack tcp options (MSS) */ + DEV_PUT16_VAL(MSS_OPT); + DEV_PUT16_VAL((uint16_t)connection->tcp_mss); + } + break; + case type_file: { + /* Send the payload of the packet */ + const char *tmpptr = (const char*)(CONST_ADDR(GET_FILE(output_handler).data) + index_in_file); + DEV_PUTN_CONST(tmpptr, segment_length); + break; + } + } + + /* update next sequence number and inflight segments */ + if(GET_FLAGS(output_handler) & TCP_SYN) { + UI32(connection->next_outseqno)++; + } else if(connection) { + UI32(connection->next_outseqno) += segment_length; + UI16(connection->inflight) += segment_length; + if(handler_type == type_generator) { + if(curr_output.service_header == header_standard || curr_output.content_length == 0) { + /* set final_outseqno as soon as it is known */ + UI32(connection->final_outseqno) = UI32(connection->next_outseqno); + } + } + } + + DEV_OUTPUT_DONE; +} + +/*-----------------------------------------------------------------------------------*/ +static inline int32_t able_to_send(const struct http_connection *connection) { + return something_to_send(connection) + && UI16(connection->inflight) + (uint16_t)connection->tcp_mss <= UI16(connection->cwnd); +} + +/*-----------------------------------------------------------------------------------*/ +char smews_send(void) { + struct http_connection *connection = NULL; +#ifndef DISABLE_COMET + const struct output_handler_t * /*CONST_VAR*/ old_output_handler = NULL; +#endif + + /* sending reset has the highest priority */ + if(UI16(rst_connection.port)) { + smews_send_packet(NULL); + UI16(rst_connection.port) = 0; + return 1; + } + + /* we first choose a valid connection */ +#ifndef DISABLE_COMET + FOR_EACH_CONN(conn, { + if(able_to_send(conn) && conn->comet_passive == 0) { + connection = conn; + break; + } + }) +#else + FOR_EACH_CONN(conn, { + if(able_to_send(conn)) { + connection = conn; + break; + } + }) +#endif + + if(connection == NULL) { + return 0; + } + /* enable a round robin */ + all_connections = connection->next; + +#ifndef DISABLE_COMET + /* do we need to acknowledge a comet request without answering it? */ + if(connection->comet_send_ack == 1) { + old_output_handler = connection->output_handler; + connection->output_handler = &ref_ack; + } +#endif + + /* get the type of web applicative resource */ + switch(CONST_UI8(connection->output_handler->handler_type)) { + case type_control: + /* preparing to send TCP control data */ + smews_send_packet(connection); + connection->output_handler = NULL; + if(connection->tcp_state == tcp_closing) { + free_connection(connection); + } +#ifndef DISABLE_COMET + if(old_output_handler) { + /* restore the right old output handler */ + connection->output_handler = old_output_handler; + connection->comet_send_ack = 0; + UI32(connection->final_outseqno) = UI32(connection->next_outseqno); + /* call initget (which must not generate any data) */ + HANDLER_CALLBACK(connection,initget); + } +#endif + break; + case type_file: + smews_send_packet(connection); + break; + case type_generator: { + char is_persistent; + char is_retransmitting; + char has_ended; + struct in_flight_infos_t *if_infos = NULL; + + /* creation and initialization of the generator_service if needed */ + if(connection->generator_service == NULL) { + connection->generator_service = mem_alloc(sizeof(struct generator_service_t)); /* test NULL: done */ + if(connection->generator_service == NULL) { + return 1; + } + curr_output.service = connection->generator_service; + /* init generator service */ + curr_output.service->service_header = header_standard; + curr_output.service->in_flight_infos = NULL; + curr_output.service->is_persistent = CONST_UI8(GET_GENERATOR(connection->output_handler).prop) == prop_persistent; + UI32(curr_output.service->curr_outseqno) = UI32(connection->next_outseqno); + /* init coroutine */ + cr_init(&curr_output.service->coroutine); + curr_output.service->coroutine.func = CONST_ADDR(GET_GENERATOR(connection->output_handler).doget); +#ifndef DISABLE_ARGS + curr_output.service->coroutine.args = connection->args; +#endif + /* we don't know yet the final output sequence number for this service */ + UI32(connection->final_outseqno) = UI32(connection->next_outseqno) - 1; +#ifndef DISABLE_COMET + /* if this is a comet generator, manage all listenning clients */ + if(CONST_UI8(connection->output_handler->handler_comet)) { + const struct output_handler_t *current_handler = connection->output_handler; + /* if this is a comet handler, this connection is active, others are set as passive */ + FOR_EACH_CONN(conn, { + if(conn->output_handler == current_handler) { + conn->comet_passive = (conn != connection); + } + }) + } + /* manage streamed comet data */ + if(CONST_UI8(connection->output_handler->handler_stream)) { + if(connection->comet_streaming) { + curr_output.service->service_header = header_none; + } + connection->comet_streaming = 1; + } +#endif + } + + /* init the global curr_output structure (usefull for out_c) */ + curr_output.service = connection->generator_service; + UI32(curr_output.next_outseqno) = UI32(connection->next_outseqno); + + /* is the service persistent or not? */ + is_persistent = curr_output.service->is_persistent; + /* are we retransmitting a lost segment? */ + is_retransmitting = UI32(curr_output.next_outseqno) != UI32(curr_output.service->curr_outseqno); + + /* put the coroutine (little) stack in the shared (big) stack if needed. + * This step has to be done before before any context_restore or context_backup */ + if(cr_prepare(&curr_output.service->coroutine) == NULL) { /* test NULL: done */ + return 1; + } + + /* check if the segment need to be generated or can be resent from a buffer */ + if(!is_persistent || !is_retransmitting) { /* segment generation is needed */ + + /* setup the http header for this segment */ + if(!is_persistent && is_retransmitting) { + /* if the current context is not the right one, restore it */ + if_infos = context_restore(curr_output.service, connection->next_outseqno); + /* if_infos is NULL if the segment to be sent is the last void http chunck */ + if(if_infos != NULL) { + curr_output.service_header = if_infos->service_header; + } else { + curr_output.service_header = header_none; + } + } else { + curr_output.service_header = curr_output.service->service_header; + } + + /* initializations before generating the segment */ + curr_output.content_length = 0; + checksum_init(); + curr_output.buffer = NULL; + + has_ended = curr_output.service->coroutine.curr_context.status == cr_terminated; + /* is has_ended is true, the segment is a void chunk: no coroutine call is needed. + * else, run the coroutine to generate one segment */ + if(!has_ended) { + /* allocate buffer for data generation */ + curr_output.buffer = mem_alloc(OUTPUT_BUFFER_SIZE); /* test NULL: done */ + if(curr_output.buffer == NULL) { + return 1; + } + + /* we will generate a segment for the first time, so we will need to store new in-flight information */ + if(!is_retransmitting) { + if_infos = mem_alloc(sizeof(struct in_flight_infos_t)); /* test NULL: done */ + if(if_infos == NULL) { + mem_free(curr_output.buffer, OUTPUT_BUFFER_SIZE); + return 1; + } + } + + /* we generate new non persistent data. backup the context before running it */ + if(!is_persistent && !is_retransmitting) { + if_infos->service_header = curr_output.service_header; + if(context_backup(curr_output.service, curr_output.next_outseqno, if_infos) == NULL) { /* test NULL: done */ + mem_free(curr_output.buffer, OUTPUT_BUFFER_SIZE); + mem_free(if_infos, sizeof(struct in_flight_infos_t)); + return 1; + } + } + + /* run the coroutine (generate one segment) */ + cr_run(&curr_output.service->coroutine); + has_ended = curr_output.service->coroutine.curr_context.status == cr_terminated; + + /* save the generated buffer after generation if persistent */ + if(is_persistent) { + /* add it to the in-flight segments list */ + if_infos->service_header = curr_output.service_header; + UI32(if_infos->next_outseqno) = UI32(connection->next_outseqno); + if_infos->infos.buffer = curr_output.buffer; + if_infos->next = curr_output.service->in_flight_infos; + curr_output.service->in_flight_infos = if_infos; + + } + } + + /* finalizations after the segment generation */ + checksum_end(); + UI16(curr_output.checksum) = UI16(current_checksum); + /* save the current checksum in the in flight segment infos */ + if(if_infos) { + UI16(if_infos->checksum) = UI16(current_checksum); + } + } else { /* the segment has to be resent from a buffer: restore it */ + if_infos = if_select(curr_output.service, connection->next_outseqno); + curr_output.buffer = if_infos->infos.buffer; + curr_output.service_header = if_infos->service_header; + UI16(curr_output.checksum) = UI16(if_infos->checksum); + } + + /* select the right HTTP header */ + switch(curr_output.service_header) { + case header_standard: + if(!has_ended || CONST_UI8(connection->output_handler->handler_stream)) { + curr_output.service_header = header_chunks; + } + break; + case header_chunks: + curr_output.service_header = header_none; + break; + default: + break; + } + + /* send the segment */ +#ifndef DISABLE_COMET + /* if this is a comet handler, send the segment to all listenning clients */ + if(CONST_UI8(connection->output_handler->handler_comet)) { + const struct output_handler_t *current_handler = connection->output_handler; + FOR_EACH_CONN(conn, { + if(conn->output_handler == current_handler && able_to_send(conn)) { + if(!CONST_UI8(conn->output_handler->handler_stream)) { + smews_send_packet(conn); + } else { + if(curr_output.content_length > 0) { + smews_send_packet(conn); + } + if(has_ended) { + UI32(conn->final_outseqno) = UI32(conn->next_outseqno); + } + } + } + }) + } else +#endif + { + /* simply send the segment */ + smews_send_packet(connection); + } + + /* free the tmp buffer used for non persistent data generation */ + if(!is_persistent) { + mem_free(curr_output.buffer, OUTPUT_BUFFER_SIZE); + } + + if(!is_retransmitting) { + /* update next_outseqno for the current context */ + curr_output.service->service_header = curr_output.service_header; + UI32(curr_output.service->curr_outseqno) = UI32(connection->next_outseqno); + } + +#ifndef DISABLE_COMET + /* clean comet service here (this is quite dirty) */ + if(CONST_UI8(connection->output_handler->handler_stream) && has_ended && UI16(connection->inflight) == 0) { + clean_service(connection->generator_service, NULL); + mem_free(connection->generator_service, sizeof(struct generator_service_t)); + connection->generator_service = NULL; + } +#endif + break; + } + } +#ifdef SMEWS_ENDING + SMEWS_ENDING; +#endif + return 1; +} diff --git a/core/output.h b/core/output.h new file mode 100644 index 0000000000000000000000000000000000000000..fbe882f6847d7fdad128f97196f432f6135edde8 --- /dev/null +++ b/core/output.h @@ -0,0 +1,42 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __SEND_H__ +#define __SEND_H__ + +/* Select a connection, process and send data. Returns 1 something has been sent, 0 else. */ +extern char smews_send(void); + +#endif /* __SEND_H__ */ diff --git a/core/smews.c b/core/smews.c new file mode 100644 index 0000000000000000000000000000000000000000..20df015d19e6c9fdf805b2169e6451b91ae3b06c --- /dev/null +++ b/core/smews.c @@ -0,0 +1,55 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "types.h" +#include "timers.h" +#include "connections.h" +#include "coroutines.h" + +#ifndef DISABLE_TIMERS +/*-----------------------------------------------------------------------------------*/ +void smews_retransmit(void) { + last_transmission_time++; + + FOR_EACH_CONN(conn, { + if(conn->output_handler + && last_transmission_time - conn->transmission_time > 4 + && UI16(conn->inflight) > 0) { + UI32(conn->next_outseqno) -= UI16(conn->inflight); + UI16(conn->inflight) = 0; + } + }) +} +#endif diff --git a/core/smews.h b/core/smews.h new file mode 100644 index 0000000000000000000000000000000000000000..87d9329288b03d2c28af00f52c24d71e70e0f084 --- /dev/null +++ b/core/smews.h @@ -0,0 +1,103 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __SMEWS_H__ +#define __SMEWS_H__ + +#include "input.h" +#include "output.h" +#include "connections.h" +#include "coroutines.h" +#include "timers.h" +#include "memory.h" + +extern void smews_retransmit(void); + +/* Inlinged because used only once */ + +/*-----------------------------------------------------------------------------------*/ +/* Processes one step */ +static inline unsigned char smews_main_loop_step() { +#ifndef DISABLE_TIMERS + smews_timers(); +#endif + if(!smews_receive() && !smews_send()) { +#ifdef DEV_WAIT + DEV_WAIT; +#endif + return 0; + } else { + return 1; + } +} + +/*-----------------------------------------------------------------------------------*/ +/* Smews initialization */ +static inline void smews_init(void) { + uint16_t x; + const struct output_handler_t * /*CONST_VAR*/ output_handler; + +#ifdef STACK_DUMP + uint32_t first_var; + stack_base = (unsigned char *) &first_var; + for(stack_i = 0; stack_i < STACK_DUMP_SIZE ; stack_i++){ + stack_base[-stack_i] = STACK_MAGIC; + } +#endif + + mem_reset(); + + /* target-dependent inititialization */ + HARDWARE_INIT; + +#ifndef DISABLE_TIMERS + last_transmission_time = 1; +#endif + + x = 0; + while((output_handler = CONST_ADDR(resources_index[x])) != NULL) { + if(CONST_UI16(output_handler->handler_type) == type_generator) { + generator_init_func_t * init_handler = CONST_ADDR(GET_GENERATOR(output_handler).init); + if(init_handler) + init_handler(); + } + x++; + } +#ifndef DISABLE_TIMERS + set_timer(&smews_retransmit,1000); +#endif +} + +#endif /* __SMEWS_H__ */ diff --git a/core/timers.c b/core/timers.c new file mode 100644 index 0000000000000000000000000000000000000000..8c37848b9225dfb05fdee8355606cd32815ee4f1 --- /dev/null +++ b/core/timers.c @@ -0,0 +1,79 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef DISABLE_TIMERS + +#include "timers.h" +#include "output.h" +#include "connections.h" + +/* Shared global timer list */ +struct timer_t *all_timers; +/* Used to log connections transmission time */ +unsigned char last_transmission_time; + +/*-----------------------------------------------------------------------------------*/ +unsigned char set_timer(timer_func_t callback,uint16_t period_millis) { + struct timer_t *new_timer = mem_alloc(sizeof(struct timer_t)); /* test NULL: done */ + if(new_timer == NULL) { + return 0; + } else { + new_timer->next = all_timers; + all_timers = new_timer; + new_timer->callback = callback; + new_timer->period_millis = period_millis; + new_timer->last_time_millis = TIME_MILLIS; + return 1; + } +} + +/*-----------------------------------------------------------------------------------*/ +void smews_timers() { + struct timer_t *curr_timer = all_timers; + uint32_t curr_time_millis; +#ifdef SMEWS_WAITING + SMEWS_WAITING; +#endif + curr_time_millis = TIME_MILLIS; + while(curr_timer) { + while(curr_time_millis - curr_timer->last_time_millis > curr_timer->period_millis) { + curr_timer->last_time_millis += curr_timer->period_millis; + curr_timer->callback(); + } + curr_timer = curr_timer->next; + } +} + +#endif diff --git a/core/timers.h b/core/timers.h new file mode 100644 index 0000000000000000000000000000000000000000..50fc1bfc6b0e68579974db8ab881f5282e268bc7 --- /dev/null +++ b/core/timers.h @@ -0,0 +1,61 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef DISABLE_TIMERS + +#ifndef __TIMERS_H__ +#define __TIMERS_H__ + +#include "types.h" + +/* Shared types */ +typedef void (timer_func_t)(void); +struct timer_t { + timer_func_t *callback; + uint16_t period_millis; + uint32_t last_time_millis; + struct timer_t *next; +}; + +/* Used to log connections transmission time */ +extern unsigned char last_transmission_time; + +/* Timer functions */ +extern unsigned char set_timer(timer_func_t callback,uint16_t period_millis); +extern void smews_timers(void); + +#endif + +#endif diff --git a/core/types.h b/core/types.h new file mode 100644 index 0000000000000000000000000000000000000000..867441e332ca18aa02cfee54026da4559a8fb0db --- /dev/null +++ b/core/types.h @@ -0,0 +1,107 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __TYPES_H__ +#define __TYPES_H__ + +/* Allows to define ENDIANNESS as LITTLE_ENDIAN or BIG_ENDIAN */ +#ifndef BIG_ENDIAN + #define BIG_ENDIAN 0 +#endif +#ifndef LITTLE_ENDIAN + #define LITTLE_ENDIAN 1 +#endif + +/* Include the target dependent target.h file */ +#include "target.h" + +/* Define NULL is needed */ +#ifndef NULL + #define NULL ((void*)0) +#endif + +/* Constant declaration */ +#ifndef CONST_VOID_P_VAR + #define CONST_VOID_P_VAR const void * +#endif +#ifndef CONST_VAR + #define CONST_VAR(type,name) type const name +#endif + +/* Read constant "variables" */ +#ifndef CONST_READ_UI8 + #define CONST_READ_UI8(x) (*((uint8_t*)(x))) +#endif +#ifndef CONST_READ_UI16 + #define CONST_READ_UI16(x) (*((uint16_t*)(x))) +#endif +#ifndef CONST_READ_UI32 + #define CONST_READ_UI32(x) (*((uint32_t*)(x))) +#endif +#ifndef CONST_READ_ADDR + #define CONST_READ_ADDR(x) (*((void**)(x))) +#endif + +/* Endianness has to be defined */ +#if ENDIANNESS != LITTLE_ENDIAN && ENDIANNESS != BIG_ENDIAN + #error ENDIANNESS has to be defined in "target.h" as LITTLE_ENDIAN or BIG_ENDIAN +#endif + +/* Wn: weight of the n_th byte of a 32 bits integer */ +#if ENDIANNESS == LITTLE_ENDIAN + #define W0 3 + #define W1 2 + #define W2 1 + #define W3 0 +#else + #define W0 0 + #define W1 1 + #define W2 2 + #define W3 3 +#endif +/* Sn: weight of the n_th byte of a 16 bits integer */ +#if ENDIANNESS == LITTLE_ENDIAN + #define S0 1 + #define S1 0 +#else + #define S0 0 + #define S1 1 +#endif + +/* Cast variable as uint16_t or uint32_t */ +#define UI16(x) (*((uint16_t*)(x))) +#define UI32(x) (*((uint32_t*)(x))) + +#endif /* __TYPES_H__ */ diff --git a/doc/SConscript b/doc/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..36cda11085dc85995ca7af2da6a75980d7bb462e --- /dev/null +++ b/doc/SConscript @@ -0,0 +1,22 @@ +env = Environment() +bookname = 'userguide' +source = bookname + '.tex' +dviTarget = bookname + '.dvi' +psTarget = bookname + '.ps' +pdfTarget = bookname + '.pdf' +htmlToc = [bookname + '.htoc', bookname + '.haux'] +htmlTarget = bookname + '.html' +htmlIndex = 'index.html' + +#uncomment de below to lines to generate html +#heveaCommand = 'hevea -exec xxdate.exe -fix %s' +#hachaCommand = 'hacha -o %s %s' + +env.DVI(dviTarget, source) +env.PostScript(psTarget, dviTarget) +env.PDF(pdfTarget, psTarget) + +#uncomment de below to lines to generate html +#env.Command(htmlToc, dviTarget, heveaCommand % (source)) +#env.Command(htmlTarget, htmlToc, heveaCommand % (source)) +#env.Command(htmlIndex, htmlTarget, hachaCommand % (htmlIndex, htmlTarget)) diff --git a/doc/SConstruct b/doc/SConstruct new file mode 100644 index 0000000000000000000000000000000000000000..ece1002be089480ee59ab834929b3efb64d7e2e1 --- /dev/null +++ b/doc/SConstruct @@ -0,0 +1 @@ +SConscript('SConscript') diff --git a/doc/smewsLogo.png b/doc/smewsLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..6daba8a7aaf5cd1e553ff6e9e4980433311c0ea2 Binary files /dev/null and b/doc/smewsLogo.png differ diff --git a/doc/userguide.pdf b/doc/userguide.pdf new file mode 100644 index 0000000000000000000000000000000000000000..39107243a21fdbe0df9b1f782d47cf625b4f6a0e Binary files /dev/null and b/doc/userguide.pdf differ diff --git a/doc/userguide.tex b/doc/userguide.tex new file mode 100755 index 0000000000000000000000000000000000000000..799662adde1a6bbaaaaceecd8c19a845764ba997 --- /dev/null +++ b/doc/userguide.tex @@ -0,0 +1,703 @@ +\documentclass{report} + +\usepackage[utf8]{inputenc} +\usepackage[english]{babel} +\usepackage[babel=true,final]{microtype} +\usepackage{listings} +\usepackage{url} +\usepackage{geometry} +\usepackage{tikz} +\usetikzlibrary{shapes,snakes,arrows,calc,decorations,shadows} + +% listings +\lstset{ + %framerule=1pt, + frame=lines, + basicstyle=\small, +% commentstyle=\rm\color{color1!50!black}, +} + +% margins +\geometry{hmargin=3.4cm,vmargin=3.2cm} + +\newcommand{\ie}{{\it i.e.}~} +\newcommand{\eg}{{\it e.g.}~} +\newcommand{\cf}{{\it c.f.}~} +\newcommand{\etal}{~{\it et al.}} +\newcommand{\etc}{{\it etc.}} + +\newcommand{\rchap}[1]{Chapter~\ref{ch:#1}} +\newcommand{\rsec}[1]{Section~\ref{sec:#1}} +\newcommand{\rssec}[1]{Sub-section~\ref{ssec:#1}} +\newcommand{\rfig}[1]{Figure~\ref{fig:#1}} +\newcommand{\rtab}[1]{Table~\ref{tab:#1}} + +\newenvironment{example}{ +\begin{minipage}{0.7\textwidth} +{\em Example:} +}{ +\end{minipage} +\newline +} + +\sloppy + +\begin{document} + +\begin{titlepage} + +\begin{center} +\large +Alex Negrea \hspace{2cm} Simon Duquennoy +\end{center} + +\vspace{6cm} + +\begin{center} +\includegraphics{smewsLogo} +\end{center} + +\begin{center} +\LARGE +{\em Smart \& Mobile Embedded Web Server} + +User Guide +\end{center} + +\vfill + +\begin{center} +\em +Last revised: \today +\end{center} + +\end{titlepage} + +\tableofcontents + +\chapter{Introduction} + +\section{What is Smews?} + +Smews stands for \emph{Smart \& Mobile Embedded Web Server}. This research prototype is designed for hardware-constrained devices like smart cards, sensor boards and other small devices. It is a stand-alone software, working without any underlaying OS. It acts as the OS by itself, dedicated to the support of Web applications. Its kernel includes device drivers, TCP/IP stack, Web server and Web applications container. It is based on a event-driven architecture and its implementation is full of cross-layer optimizations. + +Web applications are pre-processed, compiled, linked with Smews then embedded in a device. Web applications are made of static and dynamic contents. Static contents are simple files; dynamic contents are linked to server-side code. During the pre-processing phase, plenty of optimizations are made on Web contents (pre-calculation of protocol headers, checksums, parsing. automatons). Smews supports Comet (server-pushed data) and provides an advanced typing of dynamic Web contents (persistent, idempotent and volatile contents). + +\section{About this guide} + +This document contains the necessary information to get started with Smews, understand its philosophy and master its usage. It should be read by both users willing to use Smews and developers wanting to be introduced to Smews functionalities. + +\rchap{gettingstarted} contains information about Smews compilation, installation and execution, giving detailed features descriptions and concrete examples. \rchap{creatingapp} explains how to build your own Web application for Smews. + +\chapter{Getting Started} +\label{ch:gettingstarted} + +\section{Preparing your environment} + +You can download the latest Smews release from its Web site: \url{http://smews.gforge.inria.fr/} + +In order to work with Smews, you will need: +\begin{itemize} + \item a valid C compilation environment, depending on your platform the target: + \begin{itemize} + \item \emph{for target MicaZ and Funcard7} you will need: \verb+gcc-avr+ (4.3 or above) and \verb+avr-libc+ packages; + \item \emph{for target MSP430} you will need the following packages: \verb+binutils-msp430+, \verb+msp430-libc+, \verb+gcc-msp430+. These packages can be found in \verb+deb+ \url{http://wyper.ca/debian/} \verb+i686+ repository; + \item \emph{for target GBA} you will need: DevKitAdvance (\url{http://devkitadv.sourceforge.net/}); + \end{itemize} + \item Python version 2.5 or above; + \item SCons version 0.96 or above. +\end{itemize} + +The Smews compilation process is based on SCons and Python. It has been tested on Linux, Windows (using MinGW) and Mac OS. + +\section{What's in the package?} + +In the Smews package you can find the following directories and files: +\begin{itemize} +\item \verb+SConstruct, SConscript+ +-- Smews general SCons files; +\item \verb+apps/+ +-- examples of Web applications to be served by Smews; +\item \verb+core/+ +-- Smews kernel C source code (portable files); +\item \verb+panManager/+ +-- Personal Area Network manager (setting device-computer link); +\item \verb+tools/+ +-- Python preprocessing tools (used by the SCons compilation chain); +\item \verb+targets/+ +-- Smews ports to different devices. +\end{itemize} + +Every port is made of a directory in \verb+targets/+. Target-dependent code is located in \verb+targets/$target/drivers+. The \verb+targets/$target/SConscript+ file defines target-specific compilation instructions. The \verb+targets/$target/install+ script is in charge of installing Smews on the target device. The following lines describe all existing Smews ports. +%$ + +\paragraph{WSN430} + +The WSN430 sensor board is based on a 16-bits msp430 processor at 8 MHz. Communications are done over a serial line by using the SLIP protocol. + +\paragraph{MicaZ} + +The MicaZ sensor board is based on a 8-bits AVR processor at 8 MHz. Communications are done over a serial line by using the SLIP protocol. + +\paragraph{Funcard7} + +The Funcard7 smart card is based on a 8-bits AVR processor at 4 MHz. Communications are done over a serial line using a custom "IP over APDU" protocol. + +\paragraph{GBA} + +The Game Boy Advance is based on a 32-bits Arm7 processor at 16 Mhz. Communications are done over a serial line by using the SLIP protocol. + +\paragraph{Linux} + +This target has been written for debug and development purposes. It allows to execute Smews as a linux process, communicating {\it via} the TUN virtual interface. + +\paragraph{Skeleton} + +This target is an empty one. It is a starting point for someone wanting to port Smews to a new device. + +\section{Compiling Smews} +\label{sec:compile} + +Smews uses SCons for building which allows to design complex build mechanism and dependencies. The multiple pre-processing steps help Smews to be more efficient in terms of memory consumption and processing speed. + +\subsection{Short description} + +When building Smews you can specify multiple targets and Web applications to be embedded with it. For example to build Smews for a destination target A and B (directories in \verb+targets/+) and embed in it Web Applications X and Y (directories in \verb+apps/+) you can type: + +\begin{verbatim} +$ scons target=A,B apps=X,Y +\end{verbatim} + +Files are compiled in the \verb+bin/$target+ directory. This contains the Smews executable file. It also contains a \verb+libsmews.a+ file, allowing to embed Smews in other software (see \verb+core/main.c+ provided as a sample main C code linked with the library \verb+libsmews.a+). + +To clean built files type: +\begin{verbatim} +$ scons -c +\end{verbatim} + +For a complete description of available arguments, type: +\begin{verbatim} +$ scons -h +\end{verbatim} + +\subsection{Exhaustive description} + +The Smews compilation chain has many arguments enabling different options. The only necessary argument for a build is \verb+target+. All other arguments are optional and have a default value. \rtab{sconsargs} synthesizes the list of available arguments. We give here a precise description of every argument. + +\begin{table} + \fbox{ + \colorbox{black!10}{ + \begin{minipage}{1\textwidth} +{\tt target=targetA,targetB,...} +\par\hspace{0.1\textwidth} targets on which to compile Smews + +{\tt apps=[urlA:]appA,[urlB:]appB,...} +\par\hspace{0.1\textwidth} applications to be embedded with Smews + +{\tt ipaddr=ip} +\par\hspace{0.1\textwidth} set the Smews IP address + +{\tt debug=true|false} +\par\hspace{0.1\textwidth} enable or disable debug mode + +{\tt gzip=true|false} +\par\hspace{0.1\textwidth} enable or disable static Web contents compression + +{\tt chuncksNbits=number} +\par\hspace{0.1\textwidth} size of the chuncks used for pre-calculated checksums + +{\tt endian=little|big} +\par\hspace{0.1\textwidth} data endianness + +{\tt disable=[arguments|comet|retransmit]+} +\par\hspace{0.1\textwidth} disable internal functionalities + + \end{minipage} + } + } +\caption{Smews compilation options} +\label{tab:sconsargs} +\end{table} + +\subsubsection{Option {\tt target=targetA,targetB,...}} + +Set the target(s) on which Smews is going to be compiled. Example: +\begin{verbatim} +$ scons target=linux,WSN430 +\end{verbatim} + +\subsubsection{Option {\tt apps=[urlA:]appA,[urlB:]appB,...}} + +Specifies the set of Web applications that will be linked and embedded with Smews. An application is a directory or sub-directory in the \verb+apps+ directory. Every application is made of simple files (static Web contents) and/or C files (dynamic Web contents). Contents are separated by comma and the name of the content can be preceded by a replacement URL. Default value: \verb+apps=:welcome+. Example: +\begin{verbatim} +$ scons target=linux apps=contactsBook,mycalendar:calendar,:welcome +\end{verbatim} + +Resources extracted from directories \verb+contactsBook+, \verb+calendar+ and \verb+smews+ will be respectively accessible at the following URLs: + +\url{http://$smewsip/contactsBook} + +\url{http://$smewsip/mycalendar} + +\url{http://$smewsip/} +%$ + +\subsubsection{Option {\tt ipaddr=ip}} + +Set the Smews IP address. Can be either a IPv4 or IPv6 address. Examples: +\begin{verbatim} +$ scons target=linux apps=:welcome ipaddr=192.168.1.2 +$ scons target=linux apps=:welcome ipaddr=2001::2 +\end{verbatim} + +\subsubsection{Option {\tt debug=true|false}} + +Allows to compile Smews in debug mode, without any optimization (\verb+gcc -g -O0+ options). Default value: \verb+debug=false+. Example: +\begin{verbatim} +$ scons target=linux apps=:welcome debug=true +\end{verbatim} + +\subsubsection{Option {\tt gzip=true|false}} + +Allows to compress static files at compile time. This reduces the target footprint, but the client browser must be able to unpack the content. Default value: \verb+gzip=true+. Example: +\begin{verbatim} +$ scons target=linux apps=:welcome gzip=false +\end{verbatim} + +\subsubsection{Option {\tt chuncksNbits=number}} + +In Smews, the checksums of static files are pre-calculated on chunks of data at compile time. The size of the chunks is computed as \verb+1<<chuncksNbits+. The size of outgoing segments is limitated by this size since it has to be multiple of it. Default value: \verb+chuncksNbits=5+. +\begin{verbatim} +$ scons target=linux apps=:welcome chunckNbits=5 +\end{verbatim} + +\subsubsection{Option {\tt endian=little|big}} + +Forces data little or big endianness. Default value depends on the target (\verb+ENDIANNESS+ C macro defined in the \verb+target/$target/target.h+ file). Example: +\begin{verbatim} +$ scons target=linux apps=:welcome endian=little +\end{verbatim} + +\subsubsection{Option {\tt disable=[arguments|comet|retransmit]+}} + +Allows to disable some internal functionalities, making the binary smaller and the execution faster: +\begin{itemize} +\item \texttt{arguments} -- URL arguments parsing will be removed from the source code; +\item \texttt{comet} -- removes comet support in the binary, which disallows the server to push data to the client; +\item \texttt{retransmit} -- disable TCP packets retransmission in case of lost segments. The generated web server will not be fully compliant with the TCP RFC. +\end{itemize} + +Example: +\begin{verbatim} +$ scons target=linux apps=:welcome disable=comet,arguments +\end{verbatim} + +\section{Installing Smews} +\label{sec:install} + +Once Smews has been compiled, it can be embedded in the target device. This step can be done by executing the \verb+target/$target/install+ script. +%$ + +Then, the panManager has to be launched. It enables the communication between a computer and a device, managing the link-layer protocol. When launching the panManager, two arguments are mandatory: + +\begin{description} +\item[Plugin] The first argument is the plugin, implementing the desired link-layer protocol. Currently, the two existing plugins are SLIP (Serial Line IP) and APDUIP (APDU supporting IP); +\item[IP configuration] The second argument is used to configure the computer routing table. It describes an IP address and a mask size by using the "slash" notation. The panManager supports either IPv4 and IPv6 addresses. +\end{description} + +Example: configuring a SLIP link with local address 192.168.1.1 and a 24-bits mask: +\begin{verbatim} +$ panManager slip 192.168.1.1/24 +\end{verbatim} + +Example: configuring a APDUIP link with local address 2001::1 and a 126-bits mask: +\begin{verbatim} +$ panManager apduip 2001::1/126 +\end{verbatim} + +After this step, you can reach Smews at its IP address by using any HTTP/1.1 compliant Web client. + +\section{Simple example, step by step} + +We synthesize the previous sections by giving a complete example where we compile, install and access Smews on a WSN430 sensor board. All commands are given from the main Smews directory. + +Compilation, embedding the welcome page and sensor application, with IPv4 address 192.168.1.2: +\begin{verbatim} +$ scons target=WSN430 apps=:welcome,sensor ipaddr=192.168.1.2 +\end{verbatim} + +Installation, \ie{} copy of the code in the EEPROM of the WSN430 board (as root): +\begin{verbatim} +$ ./targets/WSN430/install +\end{verbatim} + +PanManager configuration (as root): +\begin{verbatim} +$ panManager/bin/panManager slip 192.168.1.1/24 +\end{verbatim} + +\chapter{Creating your own Web Application} +\label{ch:creatingapp} + +Web applications are made of static (files) and dynamic (generated by the server at runtime) contents. Applications are identified by subdirectories of the \texttt{apps/} directory. The \texttt{apps/examples} contains application examples using various features of Smews. A folder identifies a particular Web Application or a set of Web applications which will be embedded in the web server (see \rsec{compile} for more details). Every application is made of a set of files, of various types : +\begin{description} +\item[.c and .h files] C and H files are used to embed server-side code, compiled and linked with Smews; +\item[.c files with XML] C files containing specific XML meta-data (as c comment) are associated to Web resources, \ie{} they are in charge of generating dynamic Web contents in response to client requests; +\item[other files] Other files are considered as static. They will be embedded and served by Smews "as is"; +\item[.c.embed files] The .embed extension is automatically removed. This allows to serve a C file as a static content. +\end{description} + +\section{Static Content} + +When embedding static file in Smews, the HTTP content-type field is automatically inferred from the file extension (the mappings list is contained in the file \texttt{toos/mimeList}). Furthermore, many optimizations occur off-line, including HTTP header and TCP checksums pre-calculation. As an example, create a new file containing the following code and save it in \texttt{apps/helloWorld/hello.html}: + +\lstset{language=html} +\begin{lstlisting} +<html> + <head> + <title>Hello World!</title> + </head> + <body> + Hello World! + </body> +</html> +\end{lstlisting} + +Compile Smews setting the target to \verb+linux+ and the content to be embedded \verb+helloWorld+ as below: +\begin{verbatim} +$ scons target=linux apps=helloWorld ipaddr=192.168.1.2 +\end{verbatim} + +Then run the ELF file from the \texttt{/bin/linux} directory. You can now access the server at \verb+http://192.168.1.2/helloWorld/hello.html+. Keep in mind that the linux target is a particular case where Smews binary file is a process, that is why it can be launched directly. If tested on different target, refer to the instructions in \rsec{install}. + +\section{Dynamic Content} + +Smews can serve content generated by native code, which we will refer to as \textit{Dynamic Content}. Any C file containing XML specific code (as C comment) will considered as a Web resource and associated to an URL. The XML meta-data are interpreted in the pre-processing phase, thus generating some C code. We describe here the role of the XML markers available (a detailed list is given in \rtab{appsxml}, page \pageref{tab:appsxml}). + +\subsection{Defining handlers} + +Web applications are scheduled by Smews {\it via} a pre-defined set of handler functions (a detailed list is given in \rtab{appscallbacks}, page \pageref{tab:appscallbacks}): +\begin{itemize} +\item \verb+init+ -- function executed during Smews initialization; +\item \verb+initGet+ -- function executed when a Get request is received ; +\item \verb+doGet+ -- function used to generate the HTTP response. +\end{itemize} + +The XML meta-data allows to associate C functions to these handlers. As an example, create a new file containing the following code and save it in \texttt{apps/helloWorld2/hello.c}: +\lstset{language=C} +\begin{lstlisting} +/* +<generator> + <handlers doGet="do_hello"/> +</generator> +*/ + +/* simple contents generator */ +static char do_hello(struct args_t *args) { + out_str("Generated Hello World!"); + return 1; +} +\end{lstlisting} + +You can now access the server at \verb+http://192.168.1.2/helloWorld2/hello+. On the server side, the \verb+doHello+ function will be called by Smews when a the response to the client request has to be generated. The \verb+out_str+ function outputs a string as the HTTP response (a detailed list of the functions provided by Smews to Web applications is given in \rtab{appssyscalls}, page \pageref{tab:appssyscalls}). + +\subsection{Parsing URL arguments} + +Smews allows to parse URL arguments before calling the \verb+doGet+ handler. This parsing is processed in the kernel, so it is quite efficient and requires few memory. The format of the arguments are defined statically. At compile-time, a parsing automaton is generated for every dynamic Web resources, allowing an efficient arguments parsing. Here is an example where URL arguments are parsed then sent as an HTTP response: + +\lstset{language=C} +\begin{lstlisting} +/* +<generator> + <handlers doGet="output_args"/> + <args> + <arg name="i1" type="uint8" /> + <arg name="s" type="str" size="6" /> + <arg name="i2" type="uint16" /> + </args> +</generator> +*/ + +static char output_args(struct args_t *args) { + if(args) { + out_str("first int : "); + out_uint(args->i1); + out_str("\nstr : "); + out_str(args->s); + out_str("\nsecond int : "); + out_uint(args->i2); + } else { + out_str("no args"); + } + return 1; +} +\end{lstlisting} + +The \verb+args+ parameter points to the values of the arguments that have been parsed by Smews. Every URL argument is directly accessible as a field of the \verb+struct args_t+ structure, with the name that has been described in the XML meta-data. The \verb+out_uint+ function is used to output an integer. + +\subsection{Persistence of the generated data} + +Smews provides an advanced typing of dynamic contents. The internal behavior of the Smews TCP/IP stack automatically adapts to this typing, allowing to output many simultaneous segments while keeping memory consumption as low as possible. Three types of persistence have been defined: +\begin{description} +\item[volatile] -- means that the content generated will not be stored in memory and will be regenerated in case of TCP NACK; +\item[idempotent] -- means that the function will return the same value no matter when you might call it (it is deterministic and has no side-effect). In the current implementation, idempotent data are managed is the same manner than volatile data; +\item[persistent] (default option) -- means that the output will be kept in memory and will be delivered from there in case of NACK. +\end{description} + +Here is an example of a volatile Hello World. In case of TCP loss, the HTTP response may generated several times by multiple calls of the \verb+doGet+ function: +\lstset{language=C} +\begin{lstlisting} +/* +<generator> + <handlers doGet="do_hello_v"/> + <properties persistence="volatile"/> +</generator> +*/ + +/* possible persitence are persistent (by default), idempotent and volatile */ +static char do_hello_v(struct args_t *args) { + out_str("Volatile Hello World!"); + return 1; +} +\end{lstlisting} + +\subsection{Interaction mode} + +Smews also supports Web push, often called \emph{Comet}. In Smews, Comet is implemented {\it via} channels. A channel is a way of sending data asynchronously by pushing it from server to a set of registered clients. To see how can you accomplish this take a look at the next example: +\lstset{language=C} +\begin{lstlisting} +/* +<generator> + <handlers doGet="waitknock"/> + <properties interaction="alert" channel="knockknock"/> +</generator> +*/ + +/* launched when knockknock is triggered */ +static char waitknock(struct args_t *args) { + out_str("somebody knocked"); + return 1; +} +\end{lstlisting} + +The above example set the interaction tag to \verb+alert+, and defines a channel named \verb+knockknock+. In alert mode, HTTP client requests are not answered as soon as they are received. Instead, they are simply registered as listening to the \verb+knockknock+ channel. The request is pending until an event occurs. + +Let's create a second Web resource as follows: +\lstset{language=C} +\begin{lstlisting} +/* +<generator> + <handlers doGet="triggerknock"/> +</generator> +*/ + +/* triggers the knockknock comet channel */ +static char triggerknock(struct args_t *args) { + server_push(&knockknock); + return 1; +} + +\end{lstlisting} + +When a request targets this second resource, the \verb+triggerknock+ function is called. It triggers the \verb+knockknock+ channel. At this time, the \verb+waitknock+ is called, thus generating a HTTP response containing the string "somebody knocked". This response will be sent to all registered clients. + +Three interaction mode are supported by Smews: +\begin{description} +\item[rest] This is the default mode, corresponding to the classical HTTP request/response scheme; +\item[alert] Incoming requests are pending, they will be answered when the associated channel is triggered; +\item[stream] Incoming requests are pending. Every time the associated channel is triggered, a chunk of HTTP response is generated and sent to all listening clients. The HTTP response is possibly never-ending. +\end{description} + +\subsection{Timers} + +Any Web application in Smews can use timers in order to execute a function at a given interval. As an example, this feature may be used in a sensor board to periodically check the current temperature. When the sampled value reaches a threshold, a HTTP chunck containing the data is sent to all registered clients {\it via} the stream interaction modes: +\lstset{language=C} +\begin{lstlisting} +/* +<generator> + <handlers init="init_adc_timer" + initGet="set_threshold" doGet="send_temperature"/> + <properties persistence="volatile" + interaction="stream" channel="tempAlert" /> + <args> <arg name="threshold" type="uint16" /> </args> +</generator> +*/ + +static uint16_t threshold = 512; +static uint16_t curr_sample; + +/* timer callback, checking the temperature */ +static void check_temp() { + uint16_t tmp_result = get_adc_val(ADC_TEMP); + if(tmp_result >= threshold) { + curr_sample = tmp_result; + trigger_channel(&tempAlert); + } +} + +/* initializes ADC and timer */ +static char init_adc_timer(void) { + return init_adc(ADC_TEMP) && set_timer(&check_temp, 200); +} + +/* called when a get request is received. initializes the threshold */ +static char set_thresholds(struct args_t *args) { + if(args != NULL) { + threshold = args->threshold; + return 1; + } else return 0; +} + +/* called to generate the HTTP response */ +static char send_temperature(struct args_t *args) { + out_uint(curr_sample); + return 1; +} +\end{lstlisting} + +The \verb+init_adc_timer+ function is called during Smews initialization. It associates the \verb+check_temp+ function to a timer, asking Smews to execute it every 200~ms. It also initializes the ADC (allowing to sample the temperature). When a client request is received, the \verb+set_thresholds+ function is called, thus setting the current threshold. The periodic timer executed every 200~ms compares the current temperature to this threshold. If needed, it triggers the channel, thus sending the current time to every registered clients. This produces an infinite HTTP response: the Web browser receives new data whenever the threshold is reached. + +\section{Web Application SConscript} + +Every Web application can provide a customized SConscript file, giving specific instruction for the pre-compilation phase. For a good example take a look in the \texttt{apps/welcome} folder, containing such a script. Here, we only detail the most interesting part of this file: +\lstset{language=python} +\begin{lstlisting} +[...] +appListName = 'appList.js' +appListPath = os.path.join(genDir,tmpBase,appListName) +appListAbsPath = os.path.join(sconsBasePath,appListPath) + +appList = open(appListAbsPath,'w') +if len(dirsMap.keys()) > 2: + appList.write('var appList = new Array();\n') + appsCount = 0 + for dir in dirsMap.keys(): + if dir != 'welcome' and dir != httpCodesDir: + [.. Code Missing ..] # Get Web Content Files + [.. Code Missing ..] # Write line in .js + # write title or empty string + if appsCount > 0: + appList.write('var appTitle = \"' + target.capitalize() + ' +app examples:\";\n') + else: + appList.write('var appTitle = \"\";\n') +else: + appList.write('var appTitle = \"\";\n') +appList.close() + +ret = {appListPath: os.path.join(dirsMap['smews'],appListName)} +Return('ret') +\end{lstlisting} + +The above lines iterate over the dirsMap hash map which has been built by the main Smews SCons files. It contains the set of applications being compiled with Smews (to be more precise, a set of associations between application names and paths). This code creates a \verb+appList.js+ file with code for adding links to the main page of the \verb+welcome+ application, links which point to other applications that were also compiled along with it. The generated \verb+applist.js+ file is embedded in \verb+index.html+ of the \verb+welcome+ application and then referenced when needed to display link to applications: +\lstset{language=html} +\begin{lstlisting} +[...] +<script type="text/javascript" src="appList.js"> </script> +[...] +\end{lstlisting} + + +\section{Synthesis of the features} + +We give here an synthetic and exhaustive list of the features available when writing a dynamic content generator for Smews: + +\begin{itemize} +\item \rtab{appsxml} details the XML markers available for sue in comment of C the files that need to be considered as a Web resource and associated to an URL; +\item \rtab{appscallbacks} gives the list of the callbacks a dynamic Web resource can implement; +\item \rtab{appssyscalls} lists the functions provided by Smews that can be called in any Web applicative code. +\end{itemize} + +\begin{table}[htb] + \fbox{ + \colorbox{black!10}{ + \begin{minipage}{1\textwidth} +{\tt <generator />} +\begin{quote} root of the applicative meta-data \end{quote} + +{\tt <handlers init="<funcName>" initGet="<funcName>" doGet="<funcName>" />} +\begin{quote} callback functions definition \end{quote} + +{\tt <properties persistence="persistent|idempotent|volatile"\\ +interaction="rest|alert|stream" channel="<channelNem>" />} +\begin{quote} defines the properties of the Web resource \end{quote} + +{\tt <args />} +\begin{quote} defines the possible URL arguments (set of {\tt arg} markers) \end{quote} + +{\tt <arg name="<str>" type="uint8|uint16|uint32|str" size="<nBytes>" />} +\begin{quote} defines one argument \end{quote} + \end{minipage} + } + } +\caption{XML markers for dynamic contents} +\label{tab:appsxml} +\end{table} + +\begin{table}[htb] + \fbox{ + \colorbox{black!10}{ + \begin{minipage}{1\textwidth} +{\tt char (init\_app\_func\_t)(void)} +\begin{quote} initialization of the applications, returning 1 if ok, 0 if ko. \end{quote} + +{\tt char (initget\_app\_func\_t)(struct args\_t *)} +\begin{quote} called as soon as a get request is received, returning 1 if ok, 0 if ko. The parameter targets the parsed URL arguments. \end{quote} + +{\tt char (doget\_app\_func\_t)(struct args\_t *)} +\begin{quote} called when the HTTP response is ready to be sent, returning 1 if ok, 0 if ko. The parameter targets the parsed URL arguments. This function is in charge of generating the HTTP response {\it via} {\tt out\_*} calls. \end{quote} + \end{minipage} + } + } +\caption{Functions handlers provided by Web applications} +\label{tab:appscallbacks} +\end{table} + +\begin{table}[htb] + \fbox{ + \colorbox{black!10}{ + \begin{minipage}{1\textwidth} +{\tt out\_c(char c)} +\begin{quote} to be used in the {\tt doGet} callback, thus adding the {\tt c} byte to the HTTP response that is currently generated \end{quote} + +{\tt out\_uint(uint16\_t i)} +\begin{quote} to be used in the {\tt doGet} callback, thus adding the {\tt i} integer to the HTTP response that is currently generated \end{quote} + +{\tt out\_str(const char str[])} +\begin{quote} to be used in the {\tt doGet} callback, thus adding the {\tt str} string to the HTTP response that is currently generated \end{quote} + +{\tt trigger\_channel(const struct output\_handler\_t *handler)} +\begin{quote} usable in any function, it triggers a Comet channel, useful for alert or stream interaction modes \end{quote} + +{\tt set\_timer(timer\_func\_t callback, uint16\_t period\_millis)} +\begin{quote} usable in any function, it allows to automatically call the {\tt callback} function every {\tt period\_millis} milliseconds \end{quote} + \end{minipage} + } + } +\caption{Functions provided by Smews} +\label{tab:appssyscalls} +\end{table} + +\chapter{Credits} + +\section{Contributors} + +\begin{description} + \item[Simon Duquennoy] is the main author of the Smews Software + \item[Thomas So\"{e}te] is the main contributor of the WSN430 port + \item[Geoffroy Cogniaux] is the main contributor of the FunCard7 port + \item[Alex Negrea] is the main author of this user guide and of the TLS support (not yet released) + \item[Geoffrey Chavepeyer \textnormal{and} Fabien Duchêne] are the main authors of the IPv6 support + \item[Jean-Fran\c{c}ois Hren] designed the Smew (bird) in the Smews logo +\end{description} +Thanks to \textbf{Gilles Grimaud} for his kind supervision. + +\section{License} + +Smews is under CeCILL license (\url{http://www.cecill.info/}) compliant with the GPL licence of SOSSE and TUN-TAP. It also includes part of the softwares listed below: +\begin{itemize} + \item SOSSE: Matthias Br\"{u}stle -- http://www.mbsks.franken.de/sosse/ + \item TUN-TAP: Maxim Krasnyansky -- http://vtun.sourceforge.net/tun/ +\end{itemize} + +\end{document} diff --git a/hostCodes/Funcard7/a.out b/hostCodes/Funcard7/a.out new file mode 100755 index 0000000000000000000000000000000000000000..55d9d78c918211c115d366a27a9304fbd9abfaac Binary files /dev/null and b/hostCodes/Funcard7/a.out differ diff --git a/hostCodes/Funcard7/apdu.c b/hostCodes/Funcard7/apdu.c new file mode 100755 index 0000000000000000000000000000000000000000..59f6dec94bfbe49f2c8e075beaa8f78e802df941 --- /dev/null +++ b/hostCodes/Funcard7/apdu.c @@ -0,0 +1,95 @@ +#include <time.h> +#include "scard.h" +#define APDU_HEADER_SIZE 5 + +short send_apdu(SCARDCONTEXT hContext,SCARDHANDLE hCard,char *paquet,int len,LONG *rv,int P2) { + short sw; + BYTE pbRecvBuffer[MTU+1+2]; + BYTE *pbSendBuffer; + DWORD dwSendLength = len + APDU_HEADER_SIZE; + DWORD dwRecvLength = sizeof(pbRecvBuffer); + + pbSendBuffer = malloc(dwSendLength); + pbSendBuffer[0] = 0x80; + pbSendBuffer[1] = 0x01; + pbSendBuffer[2] = 0x00; + pbSendBuffer[3] = P2; + pbSendBuffer[4] = len; + memcpy(pbSendBuffer+APDU_HEADER_SIZE,paquet,len); + + *rv = SCardTransmit(hCard, + SCARD_PCI_T0, + pbSendBuffer, + dwSendLength, + NULL,//&pioRecvPci, + pbRecvBuffer, + &dwRecvLength); + + sw = *((short*)(pbRecvBuffer+dwRecvLength-2)); + printf(" %d bytes. %02x%02x. %s \n", len, SW1(sw),SW2(sw), pcsc_stringify_error(*rv)); + + if(*rv) { + if(check_terminal_status(hContext,hCard)==-1) + return -1; + else + return 0x90; + } + + return sw; +} + + +short recv_apdu(SCARDCONTEXT hContext,SCARDHANDLE hCard,utun *t,unsigned short sw,LONG *rv) { + SCARD_IO_REQUEST pioRecvPci; + BYTE pbRecvBuffer[MTU+1+2]; + BYTE pbSendBuffer[APDU_HEADER_SIZE]; + BYTE *recvBuffPtr = pbRecvBuffer; + int packet_length = -1; + + DWORD dwSendLength = APDU_HEADER_SIZE; + DWORD dwRecvLength = sizeof(pbRecvBuffer); + + pbSendBuffer[0]= 0x80; + pbSendBuffer[1]= 0x02; + pbSendBuffer[2]= 0x00; + pbSendBuffer[3]= 0x00; + pbSendBuffer[4]= SW2(sw); + + do { + pbSendBuffer[4]= SW2(sw); + *rv = SCardTransmit(hCard, SCARD_PCI_T0, + pbSendBuffer, + dwSendLength, + #ifdef WIN32 + NULL, + #else + &pioRecvPci, + #endif + recvBuffPtr, + &dwRecvLength); + + sw = *((short*)(recvBuffPtr+dwRecvLength-2)); + + if(packet_length == -1) { + packet_length = (recvBuffPtr[2] << 8) + recvBuffPtr[3]; + printf("recv %d bytes\n",packet_length); + } + + printf(" %d bytes. %02x%02x. %s\n",dwRecvLength-2,SW1(sw),SW2(sw),pcsc_stringify_error(*rv)); + + if(*rv) { + if(check_terminal_status(hContext,hCard)==-1) + return -1; + else + return 0x90; + } + + packet_length -= dwRecvLength -2; + + recvBuffPtr += dwRecvLength-2; + } while(packet_length > 0); + + utun_write(t, pbRecvBuffer,recvBuffPtr-pbRecvBuffer); + + return sw; +} diff --git a/hostCodes/Funcard7/linux/Makefile b/hostCodes/Funcard7/linux/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..a914de4097189ae63528ae219ddebfb168a8d426 --- /dev/null +++ b/hostCodes/Funcard7/linux/Makefile @@ -0,0 +1,41 @@ + +ROOTDIR=. + +CFLAGS = -g -Wall -D LINUX +SRCDIR = $(ROOTDIR)/.. +OUTDIR = $(ROOTDIR) +LIBS = -lpcsclite + +BINARIES= scard +OBJECTS = $(addsuffix .o,scard ) + +default: + -make allnocall ROOTDIR=`pwd` + +all: + -make allnocall ROOTDIR=`pwd` + +allnocall: $(OBJECTS) $(BINARIES) + +scard: scard.o apdu.o terminal.o tunnel.o signal.o utils.o utun.o + cd $(OUTDIR) && $(CC) $(CFLAGS) -o ../$@ $^ $(LIBS) + +scard.o: + $(CC) $(CFLAGS) -c $< $(INCDIR) $(SRCDIR)/scard.c -o $(OUTDIR)/scard.o +apdu.o: + $(CC) $(CFLAGS) -c $< $(INCDIR) $(SRCDIR)/apdu.c -o $(OUTDIR)/apdu.o +terminal.o: + $(CC) $(CFLAGS) -c $< $(INCDIR) $(SRCDIR)/terminal.c -o $(OUTDIR)/terminal.o +tunnel.o: + $(CC) $(CFLAGS) -c $< $(INCDIR) $(SRCDIR)/tunnel.c -o $(OUTDIR)/tunnel.o +signal.o: + $(CC) $(CFLAGS) -c $< $(INCDIR) $(SRCDIR)/signal.c -o $(OUTDIR)/signal.o +utils.o: + $(CC) $(CFLAGS) -c $< $(INCDIR) $(SRCDIR)/utils.c -o $(OUTDIR)/utils.o +utun.o: + $(CC) $(CFLAGS) -c $< $(INCDIR) $(SRCDIR)/utun/nixtun.c -o $(OUTDIR)/utun.o + +clean: + rm -f *.o scard + + diff --git a/hostCodes/Funcard7/linux/debuglog.h b/hostCodes/Funcard7/linux/debuglog.h new file mode 100755 index 0000000000000000000000000000000000000000..056bc48010849c1a8737815075f5254432f13fac --- /dev/null +++ b/hostCodes/Funcard7/linux/debuglog.h @@ -0,0 +1,97 @@ +/* + * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * + * Copyright (C) 1999-2004 + * David Corcoran <corcoran@linuxnet.com> + * Copyright (C) 1999-2005 + * Ludovic Rousseau <ludovic.rousseau@free.fr> + * + * $Id: debuglog.h,v 1.3 2005-09-06 20:37:26 rousseau Exp $ + */ + +/** + * @file + * @brief This handles debugging. + * + * @note log message is sent to syslog or stderr depending on --foreground + * command line argument + * + * @test + * @code + * Log1(priority, "text"); + * log "text" with priority level priority + * Log2(priority, "text: %d", 1234); + * log "text: 1234" + * the format string can be anything printf() can understand + * Log3(priority, "text: %d %d", 1234, 5678); + * log "text: 1234 5678" + * the format string can be anything printf() can understand + * LogXxd(priority, msg, buffer, size); + * log "msg" + a hex dump of size bytes of buffer[] + * @endcode + */ + +#ifndef __debuglog_h__ +#define __debuglog_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define DEBUGLOG_LOG_ENTRIES 1 +#define DEBUGLOG_IGNORE_ENTRIES 2 + +enum { + DEBUGLOG_NO_DEBUG = 0, + DEBUGLOG_SYSLOG_DEBUG, + DEBUGLOG_STDERR_DEBUG +}; + +#define DEBUG_CATEGORY_NOTHING 0 +#define DEBUG_CATEGORY_APDU 1 +#define DEBUG_CATEGORY_SW 2 + +enum { + PCSC_LOG_DEBUG = 0, + PCSC_LOG_INFO, + PCSC_LOG_ERROR, + PCSC_LOG_CRITICAL +}; + +/* You can't do #ifndef __FUNCTION__ */ +#if !defined(__GNUC__) && !defined(__IBMC__) +#define __FUNCTION__ "" +#endif + +#define Log0(priority) log_msg(priority, "%s:%d:%s()", __FILE__, __LINE__, __FUNCTION__) +#define Log1(priority, fmt) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__) +#define Log2(priority, fmt, data) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data) +#define Log3(priority, fmt, data1, data2) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2) +#define Log3(priority, fmt, data1, data2) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2) +#define Log4(priority, fmt, data1, data2, data3) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3) +#define Log9(priority, fmt, data1, data2, data3, data4, data5, data6, data7, data8) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3, data4, data5, data6, data7, data8) +#define LogXxd(priority, msg, buffer, size) log_xxd(priority, msg, buffer, size) + +#define DebugLogA(a) Log1(PCSC_LOG_INFO, a) +#define DebugLogB(a, b) Log2(PCSC_LOG_INFO, a, b) +#define DebugLogC(a, b,c) Log3(PCSC_LOG_INFO, a, b, c) + +void log_msg(const int priority, const char *fmt, ...); +void log_xxd(const int priority, const char *msg, const unsigned char *buffer, + const int size); + +void DebugLogSuppress(const int); +void DebugLogSetLogType(const int); +int DebugLogSetCategory(const int); +void DebugLogCategory(const int, const unsigned char *, const int); +void DebugLogSetLevel(const int level); + +char *pcsc_stringify_error(long); + +#ifdef __cplusplus +} +#endif + +#endif /* __debuglog_h__ */ + diff --git a/hostCodes/Funcard7/linux/errorLog b/hostCodes/Funcard7/linux/errorLog new file mode 100644 index 0000000000000000000000000000000000000000..1b1d0d27091cb69010d31e8d02247a45f321fc93 --- /dev/null +++ b/hostCodes/Funcard7/linux/errorLog @@ -0,0 +1,25 @@ +Reader=Gemplus GemPC Twin 00 00 +Reading ATR : 3B BA 21 00 40 20 53 4D 45 57 53 08 09 04 01 05 +SCARD host adapter is now ready to accept connections +SRC = 192.168.0.1 DST = 192.168.0.2 +Dumping 60bytes +0000: 4500003C4931400040067037C0A80001 E..<I1@.@.p7.... +0010: C0A80002C4FE00504074D10800000000 .......P@t...... +0020: A002040058400000020401000402080A ....X@.......... +0030: 001C98390000000001030306 ...9........ + +Transmit_send2SC=Transaction failed., len=65[Ip=60] err=80100016 +State= 1B0034, Possible diagnostic : +There is a card in the reader, but it has not been moved into position for use. +Power is being provided to the card, but the reader driver is unaware of the mode of the card. +The card has been reset and is awaiting PTS negotiation. +Trying to reconnect in 3s... +Trying to reconnect... 1/100 +Command successful. +Card answered 90-00 +State= 1B0034, Possible diagnostic : +There is a card in the reader, but it has not been moved into position for use. +Power is being provided to the card, but the reader driver is unaware of the mode of the card. +The card has been reset and is awaiting PTS negotiation. +Trying to reconnect in 3s... +...Exiting diff --git a/hostCodes/Funcard7/linux/ifdhandler.h b/hostCodes/Funcard7/linux/ifdhandler.h new file mode 100755 index 0000000000000000000000000000000000000000..a1c64673c5cb933cdeed9659e117c323762638c3 --- /dev/null +++ b/hostCodes/Funcard7/linux/ifdhandler.h @@ -0,0 +1,211 @@ +/* + * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * + * Copyright (C) 1999-2004 + * David Corcoran <corcoran@linuxnet.com> + * Damien Sauveron <damien.sauveron@labri.fr> + * + * $Id: ifdhandler.h,v 1.3 2005-09-06 20:37:26 rousseau Exp $ + */ + +/** + * @file + * @brief This provides reader specific low-level calls. + */ + +#ifndef _ifd_handler_h_ +#define _ifd_handler_h_ + +#include <pcsclite.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* + * List of data structures available to ifdhandler + */ + + typedef struct _DEVICE_CAPABILITIES + { + LPTSTR Vendor_Name; /* Tag 0x0100 */ + LPTSTR IFD_Type; /* Tag 0x0101 */ + DWORD IFD_Version; /* Tag 0x0102 */ + LPTSTR IFD_Serial; /* Tag 0x0103 */ + DWORD IFD_Channel_ID; /* Tag 0x0110 */ + + DWORD Asynch_Supported; /* Tag 0x0120 */ + DWORD Default_Clock; /* Tag 0x0121 */ + DWORD Max_Clock; /* Tag 0x0122 */ + DWORD Default_Data_Rate; /* Tag 0x0123 */ + DWORD Max_Data_Rate; /* Tag 0x0124 */ + DWORD Max_IFSD; /* Tag 0x0125 */ + DWORD Synch_Supported; /* Tag 0x0126 */ + DWORD Power_Mgmt; /* Tag 0x0131 */ + DWORD Card_Auth_Devices; /* Tag 0x0140 */ + DWORD User_Auth_Device; /* Tag 0x0142 */ + DWORD Mechanics_Supported; /* Tag 0x0150 */ + DWORD Vendor_Features; /* Tag 0x0180 - 0x01F0 User Defined. */ + } + DEVICE_CAPABILITIES, *PDEVICE_CAPABILITIES; + + typedef struct _ICC_STATE + { + UCHAR ICC_Presence; /* Tag 0x0300 */ + UCHAR ICC_Interface_Status; /* Tag 0x0301 */ + UCHAR ATR[MAX_ATR_SIZE]; /* Tag 0x0303 */ + UCHAR ICC_Type; /* Tag 0x0304 */ + } + ICC_STATE, *PICC_STATE; + + typedef struct _PROTOCOL_OPTIONS + { + DWORD Protocol_Type; /* Tag 0x0201 */ + DWORD Current_Clock; /* Tag 0x0202 */ + DWORD Current_F; /* Tag 0x0203 */ + DWORD Current_D; /* Tag 0x0204 */ + DWORD Current_N; /* Tag 0x0205 */ + DWORD Current_W; /* Tag 0x0206 */ + DWORD Current_IFSC; /* Tag 0x0207 */ + DWORD Current_IFSD; /* Tag 0x0208 */ + DWORD Current_BWT; /* Tag 0x0209 */ + DWORD Current_CWT; /* Tag 0x020A */ + DWORD Current_EBC; /* Tag 0x020B */ + } + PROTOCOL_OPTIONS, *PPROTOCOL_OPTIONS; + + typedef struct _SCARD_IO_HEADER + { + DWORD Protocol; + DWORD Length; + } + SCARD_IO_HEADER, *PSCARD_IO_HEADER; + + /* + * End of structure list + */ + + /* + * The list of tags should be alot more but this is all I use in the + * meantime + */ + +#define TAG_IFD_ATR 0x0303 +#define TAG_IFD_SLOTNUM 0x0180 +#define TAG_IFD_SLOT_THREAD_SAFE 0x0FAC +#define TAG_IFD_THREAD_SAFE 0x0FAD +#define TAG_IFD_SLOTS_NUMBER 0x0FAE +#define TAG_IFD_SIMULTANEOUS_ACCESS 0x0FAF + + /* + * End of tag list + */ + + /* + * IFD Handler version number enummerations + */ +#define IFD_HVERSION_1_0 0x00010000 +#define IFD_HVERSION_2_0 0x00020000 +#define IFD_HVERSION_3_0 0x00030000 + /* + * End of version number enummerations + */ + + /* + * List of defines available to ifdhandler + */ + +#define IFD_POWER_UP 500 +#define IFD_POWER_DOWN 501 +#define IFD_RESET 502 + +#define IFD_NEGOTIATE_PTS1 1 +#define IFD_NEGOTIATE_PTS2 2 +#define IFD_NEGOTIATE_PTS3 4 + +#define IFD_SUCCESS 0 +#define IFD_ERROR_TAG 600 +#define IFD_ERROR_SET_FAILURE 601 +#define IFD_ERROR_VALUE_READ_ONLY 602 +#define IFD_ERROR_PTS_FAILURE 605 +#define IFD_ERROR_NOT_SUPPORTED 606 +#define IFD_PROTOCOL_NOT_SUPPORTED 607 +#define IFD_ERROR_POWER_ACTION 608 +#define IFD_ERROR_SWALLOW 609 +#define IFD_ERROR_EJECT 610 +#define IFD_ERROR_CONFISCATE 611 +#define IFD_COMMUNICATION_ERROR 612 +#define IFD_RESPONSE_TIMEOUT 613 +#define IFD_NOT_SUPPORTED 614 +#define IFD_ICC_PRESENT 615 +#define IFD_ICC_NOT_PRESENT 616 + + /* + * If you want to compile a V2.0 IFDHandler, define IFDHANDLERv2 before you + * include this file. + * + * By default it is setup for for most recent version of the API (V3.0) + */ + +#ifndef IFDHANDLERv2 + + /* + * List of Defined Functions Available to IFD_Handler 3.0 + * + * All the functions of IFD_Handler 2.0 are available + * IFDHCreateChannelByName() is new + * IFDHControl() API changed + */ + + RESPONSECODE IFDHCreateChannelByName(DWORD, LPTSTR); + RESPONSECODE IFDHControl(DWORD, DWORD, PUCHAR, DWORD, PUCHAR, DWORD, + LPDWORD); +#else + + /* + * List of Defined Functions Available to IFD_Handler 2.0 + */ + + RESPONSECODE IFDHControl(DWORD, PUCHAR, DWORD, PUCHAR, PDWORD); + +#endif + + /* + * common functions in IFD_Handler 2.0 and 3.0 + */ + RESPONSECODE IFDHCreateChannel(DWORD, DWORD); + RESPONSECODE IFDHCloseChannel(DWORD); + RESPONSECODE IFDHGetCapabilities(DWORD, DWORD, PDWORD, PUCHAR); + RESPONSECODE IFDHSetCapabilities(DWORD, DWORD, DWORD, PUCHAR); + RESPONSECODE IFDHSetProtocolParameters(DWORD, DWORD, UCHAR, + UCHAR, UCHAR, UCHAR); + RESPONSECODE IFDHPowerICC(DWORD, DWORD, PUCHAR, PDWORD); + RESPONSECODE IFDHTransmitToICC(DWORD, SCARD_IO_HEADER, PUCHAR, + DWORD, PUCHAR, PDWORD, PSCARD_IO_HEADER); + RESPONSECODE IFDHICCPresence(DWORD); + + /* + * List of Defined Functions Available to IFD_Handler 1.0 + */ + + RESPONSECODE IO_Create_Channel(DWORD); + RESPONSECODE IO_Close_Channel(); + RESPONSECODE IFD_Get_Capabilities(DWORD, PUCHAR); + RESPONSECODE IFD_Set_Capabilities(DWORD, PUCHAR); + RESPONSECODE IFD_Set_Protocol_Parameters(DWORD, UCHAR, UCHAR, + UCHAR, UCHAR); + RESPONSECODE IFD_Power_ICC(DWORD); + RESPONSECODE IFD_Swallow_ICC(); + RESPONSECODE IFD_Eject_ICC(); + RESPONSECODE IFD_Confiscate_ICC(); + RESPONSECODE IFD_Transmit_to_ICC(SCARD_IO_HEADER, PUCHAR, DWORD, + PUCHAR, PDWORD, PSCARD_IO_HEADER); + RESPONSECODE IFD_Is_ICC_Present(); + RESPONSECODE IFD_Is_ICC_Absent(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hostCodes/Funcard7/linux/mscdefines.h b/hostCodes/Funcard7/linux/mscdefines.h new file mode 100755 index 0000000000000000000000000000000000000000..605912d2cffc2db7b6d2c2ceec498d8d2c310479 --- /dev/null +++ b/hostCodes/Funcard7/linux/mscdefines.h @@ -0,0 +1,149 @@ +/* + * This provides high level definitions for data types, structures. + * + * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * + * Copyright (C) 2001-2002 + * David Corcoran <corcoran@linuxnet.com> + * + * You may not remove this header from this file + * without prior permission from the author. + * + * $Id: mscdefines.h,v 1.1.1.1 2005-09-06 20:29:05 rousseau Exp $ + */ + +#ifndef __mscdefines_h__ +#define __mscdefines_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <winscard.h> + +#ifndef MAX_BUFFER_SIZE +#define MAX_BUFFER_SIZE 265 +#endif + + /* + * Some type defines used in MuscleCard + */ + + typedef unsigned long MSC_RV; + typedef char MSCChar8; + typedef unsigned char *MSCPUChar8; + typedef const unsigned char *MSCPCUChar8; + typedef unsigned char MSCUChar8; + typedef unsigned short *MSCPUShort16; + typedef unsigned short MSCUShort16; + typedef short *MSCPShort16; + typedef short MSCShort16; + typedef unsigned long *MSCPULong32; + typedef unsigned long MSCULong32; + typedef long *MSCPLong32; + typedef long MSCLong32; + typedef const void *MSCPCVoid32; + typedef void *MSCPVoid32; + typedef const char *MSCCString; + typedef char *MSCString; + + typedef struct + { + MSCPVoid32 pvfWriteFramework; + MSCPVoid32 pvfInitializePlugin; + MSCPVoid32 pvfIdentifyToken; + MSCPVoid32 pvfFinalizePlugin; + MSCPVoid32 pvfGetStatus; + MSCPVoid32 pvfGetCapabilities; + MSCPVoid32 pvfExtendedFeature; + MSCPVoid32 pvfGenerateKeys; + MSCPVoid32 pvfImportKey; + MSCPVoid32 pvfExportKey; + MSCPVoid32 pvfComputeCrypt; + MSCPVoid32 pvfExtAuthenticate; + MSCPVoid32 pvfListKeys; + MSCPVoid32 pvfCreatePIN; + MSCPVoid32 pvfVerifyPIN; + MSCPVoid32 pvfChangePIN; + MSCPVoid32 pvfUnblockPIN; + MSCPVoid32 pvfListPINs; + MSCPVoid32 pvfCreateObject; + MSCPVoid32 pvfDeleteObject; + MSCPVoid32 pvfWriteObject; + MSCPVoid32 pvfReadObject; + MSCPVoid32 pvfListObjects; + MSCPVoid32 pvfLogoutAll; + MSCPVoid32 pvfGetChallenge; + + } + CFDyLibPointers, *LPCFDyLibPointers; + +#define MSC_MAXSIZE_TOKENAME 150 +#define MSC_MAXSIZE_SVCPROV 200 +#define MSC_MAXSIZE_OBJID 16 +#define MSC_MAXSIZE_AID 64 +#define MSC_MAXSIZE_MAC 128 +#define MSC_MAXSIZE_LABEL 32 +#define MSC_MAXSIZE_CERT_ISSUER 512 +#define MSC_MAXSIZE_CERT_SUBJECT 512 +#define MSC_MAXSIZE_CERT_SERIAL 512 +#define MSC_MAXSIZE_BUFFER MAX_BUFFER_SIZE + + typedef struct + { + MSCChar8 tokenName[MSC_MAXSIZE_TOKENAME]; /* Token name */ + MSCChar8 slotName[MAX_READERNAME]; /* Slot/reader name */ + MSCChar8 svProvider[MSC_MAXSIZE_SVCPROV]; /* Library */ + MSCUChar8 tokenId[MAX_ATR_SIZE]; /* Token ID (ATR) */ + MSCUChar8 tokenApp[MSC_MAXSIZE_AID]; /* Default app ID */ + MSCULong32 tokenAppLen; /* Default AID Length */ + MSCULong32 tokenIdLength; /* ID Length (ATR Length) */ + MSCULong32 tokenState; /* State (dwEventState) */ + MSCULong32 tokenType; /* Type - RFU */ + MSCPVoid32 addParams; /* Additional Data */ + MSCULong32 addParamsSize; /* Size of additional data */ + } + MSCTokenInfo, *MSCLPTokenInfo; + + /* + * Callback function definitions + */ + + typedef MSCULong32(*MSCCallBack) (MSCLPTokenInfo, MSCULong32, + MSCPVoid32); + + typedef struct + { + MSCULong32 arraySize; + MSCLPTokenInfo tokenArray; + MSCPVoid32 appData; + MSCCallBack callBack; + } + MSCEventWaitInfo, *MSCLPEventWaitInfo; + + typedef MSC_RV(*LPRWEventCallback) (MSCPVoid32, int); + + typedef struct + { + SCARDCONTEXT hContext; /* Handle to resource manager */ + SCARDHANDLE hCard; /* Handle to the connection */ + LPSCARD_IO_REQUEST ioType; /* Type of protocol */ + MSCUChar8 pMac[MSC_MAXSIZE_MAC]; /* MAC code */ + MSCULong32 macSize; /* Size of the MAC code */ + MSCPVoid32 tokenLibHandle; /* Handle to token library */ + CFDyLibPointers libPointers; /* Function pointers */ + MSCTokenInfo tokenInfo; /* token information */ + MSCUChar8 loggedIDs; /* Verification bit mask */ + MSCULong32 shareMode; /* Sharing mode for this */ + LPRWEventCallback rwCallback; /* Registered callback */ + } + MSCTokenConnection, *MSCLPTokenConnection; + +#define MSC_OK MSC_SUCCESS + +#ifdef __cplusplus +} +#endif + +#endif /* __mscdefines_h__ */ diff --git a/hostCodes/Funcard7/linux/musclecard.h b/hostCodes/Funcard7/linux/musclecard.h new file mode 100755 index 0000000000000000000000000000000000000000..277c7a1eef12b0b4e7ace3da9483897407855add --- /dev/null +++ b/hostCodes/Funcard7/linux/musclecard.h @@ -0,0 +1,957 @@ +/* + * This abstracts the MUSCLE Card Edge Inteface. + * + * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * + * Copyright (C) 2001-2002 + * David Corcoran <corcoran@linuxnet.com> + * + * You may not remove this header from this file + * without prior permission from the author. + * + * $Id: musclecard.h,v 1.1.1.1 2005-09-06 20:29:05 rousseau Exp $ + */ + +#ifndef __musclecard_h__ +#define __musclecard_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef WIN32 +#include "PCSC.h" +#endif + +#include <mscdefines.h> + +/* + * PCSC_API is defined for Windows but is a no-op on other + * platforms. + */ + +#ifndef PCSC_API +#define PCSC_API +#endif + + + /**************** + * Return codes * + ****************/ + + /** success */ +#define MSC_SUCCESS 0x9000 + + /** There have been memory problems on the card */ +#define MSC_NO_MEMORY_LEFT 0x9C01 + /** Entered PIN is not correct */ +#define MSC_AUTH_FAILED 0x9C02 + /** Required operation is not allowed in actual circumstances */ +#define MSC_OPERATION_NOT_ALLOWED 0x9C03 + /** Required operation is inconsistent with memory contents */ +#define MSC_INCONSISTENT_STATUS 0x9C04 + /** Required feature is not (yet) supported */ +#define MSC_UNSUPPORTED_FEATURE 0x9C05 + /** Required operation was not authorized because of a lack of privileges */ +#define MSC_UNAUTHORIZED 0x9C06 + /** Required object is missing */ +#define MSC_OBJECT_NOT_FOUND 0x9C07 + /** New object ID already in use */ +#define MSC_OBJECT_EXISTS 0x9C08 + /** Algorithm specified is not correct */ +#define MSC_INCORRECT_ALG 0x9C09 + + /** Verify operation detected an invalid signature */ +#define MSC_SIGNATURE_INVALID 0x9C0B + /** Operation has been blocked for security reason */ +#define MSC_IDENTITY_BLOCKED 0x9C0C + /** Unspecified error */ +#define MSC_UNSPECIFIED_ERROR 0x9C0D + /** PCSC and driver transport errors */ +#define MSC_TRANSPORT_ERROR 0x9C0E + /** Invalid parameter given */ +#define MSC_INVALID_PARAMETER 0x9C0F + /** Incorrect P1 parameter */ +#define MSC_INCORRECT_P1 0x9C10 + /** Incorrect P2 parameter */ +#define MSC_INCORRECT_P2 0x9C11 + /** End of sequence */ +#define MSC_SEQUENCE_END 0x9C12 + /** For debugging purposes */ +#define MSC_INTERNAL_ERROR 0x9CFF + + /*******************************************************/ + /* + * These returns are beyond the protocol specification + * and only exist here to provide return codes for the + * additional functions provided by the MuscleCard API + * beyond the protocol specification. + */ + /*******************************************************/ + + /** A blocking event has been cancelled */ +#define MSC_CANCELLED 0x9C50 + /* + * The buffer provided is too short + */ +#define MSC_INSUFFICIENT_BUFFER 0x9C51 + /* + * The selected token is not recognized + */ +#define MSC_UNRECOGNIZED_TOKEN 0x9C52 + /* + * The PC/SC services is not available + */ +#define MSC_SERVICE_UNRESPONSIVE 0x9C53 + /* + * The action has timed out + */ +#define MSC_TIMEOUT_OCCURRED 0x9C54 + /* + * The token has been removed + */ +#define MSC_TOKEN_REMOVED 0x9C55 + /* + * The token has been reset + */ +#define MSC_TOKEN_RESET 0x9C56 + /* + * The token has been inserted + */ +#define MSC_TOKEN_INSERTED 0x9C57 + /* + * The token is unresponsive + */ +#define MSC_TOKEN_UNRESPONSIVE 0x9C58 + /* + * The handle is invalid + */ +#define MSC_INVALID_HANDLE 0x9C59 + /* + * Invalid sharing + */ +#define MSC_SHARING_VIOLATION 0x9C60 + /* + * New PINs are not identical (happens if PIN is changed with keypad) + */ +#define MSC_PINS_NOT_IDENTICAL 0x9C61 + + +#define MSC_BLOCKSTATUS_RESUME 0x0000 +#define MSC_BLOCKSTATUS_BLOCKING 0x0001 +#define MSC_BLOCKSTATUS_CANCELLING 0x0002 + + /* + * Some boundary defines + */ +#define MSC_MAX_KEYS 16 +#define MSC_MAX_PINS 8 +#define MSC_SIZEOF_KEYPACKET 200 +#define MSC_MAXSIZEOF_APDU_DATALEN 255 +#define MSC_PERCENT_STEPSIZE 1000 +#define MSC_SINGLE_READ_PACKET 255 +#define MSC_MAXSIZE_TOKENARRAY 255 + + /* + * KeyPair Generation algorithms + */ +#define MSC_GEN_ALG_RSA 0x00 +#define MSC_GEN_ALG_RSA_CRT 0x01 +#define MSC_GEN_ALG_DSA 0x02 +#define MSC_GEN_ALG_DES 0x03 +#define MSC_GEN_ALG_3DES 0x04 +#define MSC_GEN_ALG_3DES3 0x05 + + /* + * Blob encodings in KeyBlob structure + */ +#define MSC_BLOB_ENC_PLAIN 0x00 +#define MSC_BLOB_ENC_CRYPT 0x01 + + /* + * Key Type in Key Blobs + */ +#define MSC_KEY_RSA_PUBLIC 0x01 +#define MSC_KEY_RSA_PRIVATE 0x02 +#define MSC_KEY_RSA_PRIVATE_CRT 0x03 +#define MSC_KEY_DSA_PUBLIC 0x04 +#define MSC_KEY_DSA_PRIVATE 0x05 +#define MSC_KEY_DES 0x06 +#define MSC_KEY_3DES 0x07 +#define MSC_KEY_3DES3 0x08 + + /* + * Key generation options TODO: add other + */ +#define MSC_OPT_DEFAULT 0x00 +#define MSC_OPT_RSA_PUB_EXP 0x01 +#define MSC_OPT_DSA_GPQ 0x02 + + /* + * Cipher operations in ComputeCrypt() + */ +#define MSC_CIPHER_INIT 0x01 +#define MSC_CIPHER_PROCESS 0x02 +#define MSC_CIPHER_FINAL 0x03 + + /* + * Cipher modes in ComputeCrypt() + */ +#define MSC_MODE_RSA_NOPAD 0x00 +#define MSC_MODE_RSA_PAD_PKCS1 0x01 +#define MSC_MODE_DSA_SHA 0x10 +#define MSC_MODE_DES_CBC_NOPAD 0x20 +#define MSC_MODE_DES_ECB_NOPAD 0x21 + + /* + * Cipher directions + */ +#define MSC_DIR_SIGN 0x01 +#define MSC_DIR_VERIFY 0x02 +#define MSC_DIR_ENCRYPT 0x03 +#define MSC_DIR_DECRYPT 0x04 + + /* + * Sequence options in ListXXX() + */ +#define MSC_SEQUENCE_RESET 0x00 +#define MSC_SEQUENCE_NEXT 0x01 + + /* + * Zero flag in DeleteObject() + */ +#define MSC_ZF_DEFAULT 0x00 +#define MSC_ZF_WRITE_ZERO 0x01 + + /* + * Some defines for ID's Bitmask + */ +#define MSC_AUT_ALL 0x0000 +#define MSC_AUT_NONE 0xFFFF + +#define MSC_AUT_PIN_0 0x0001 +#define MSC_AUT_PIN_1 0x0002 +#define MSC_AUT_PIN_2 0x0004 +#define MSC_AUT_PIN_3 0x0008 +#define MSC_AUT_PIN_4 0x0010 + +#define MSC_AUT_KEY_0 0x0100 +#define MSC_AUT_KEY_1 0x0200 +#define MSC_AUT_KEY_2 0x0400 +#define MSC_AUT_KEY_3 0x0800 +#define MSC_AUT_KEY_4 0x1000 +#define MSC_AUT_KEY_5 0x2000 + +#define MSC_AUT_USR_0 0x4000 +#define MSC_AUT_USR_1 0x8000 + + /* + * This structure allows you to customize your MuscleCard. It is used + * in MSCWriteFramework to specify attributes you may want to set in + * this 'personalization' routine and will be getting new values in + * future revisions of the API + */ + +#define MSC_INIT_DEFAULT_KEY 0x00 /* Use card's default transport + * key */ +#define MSC_INIT_IGNORE_KEY 0x01 /* Don't verify any key at all */ +#define MSC_INIT_USE_KEY 0x02 /* Use the key in this struct */ + + typedef struct + { + MSCUChar8 transportKey[MAX_BUFFER_SIZE]; + MSCULong32 transportKeyLen; + MSCUChar8 transportBehavior; + MSCULong32 objectMemory; + + MSCUChar8 newTransportKey[MAX_BUFFER_SIZE]; + MSCULong32 newTransportKeyLen; + + MSCUChar8 defaultCHV[MAX_BUFFER_SIZE]; + MSCULong32 defaultCHVLen; + MSCUChar8 defaultCHVTries; + + MSCUChar8 defaultCHVUnblock[MAX_BUFFER_SIZE]; + MSCULong32 defaultCHVUnblockSize; + MSCUChar8 defaultCHVUnblockTries; + + MSCUShort16 createObjectACL; + MSCUShort16 createKeysACL; + MSCUShort16 createPINsACL; + + MSCUChar8 maxNumberKeys; + MSCUChar8 maxNumberPINs; + MSCUShort16 maxNumberObjects; + + } + MSCInitTokenParams, *MSCLPInitTokenParams; + + /* + * Direction policy bitmasks for MSCKeyPolicy + */ +#define MSC_KEYPOLICY_MODE_RSA_NOPAD 0x0001 +#define MSC_KEYPOLICY_MODE_RSA_PAD_PKCS1 0x0002 +#define MSC_KEYPOLICY_MODE_DSA_SHA 0x0004 +#define MSC_KEYPOLICY_MODE_DES_CBC_NOPAD 0x0008 +#define MSC_KEYPOLICY_MODE_DES_ECB_NOPAD 0x0010 + +#define MSC_KEYPOLICY_DIR_SIGN 0x0100 +#define MSC_KEYPOLICY_DIR_VERIFY 0x0200 +#define MSC_KEYPOLICY_DIR_ENCRYPT 0x0400 +#define MSC_KEYPOLICY_DIR_DECRYPT 0x0800 + + typedef struct + { + MSCUShort16 cipherMode; + MSCUShort16 cipherDirection; + } + MSCKeyPolicy, *MSCLPKeyPolicy; + + typedef struct + { + MSCUShort16 readPermission; + MSCUShort16 writePermission; + MSCUShort16 usePermission; + } + MSCKeyACL, *MSCLPKeyACL; + + typedef struct + { + MSCUShort16 readPermission; + MSCUShort16 writePermission; + MSCUShort16 deletePermission; + } + MSCObjectACL, *MSCLPObjectACL, MSCCertACL, *MSCLPCertACL; + + typedef struct + { + MSCUChar8 algoType; + MSCUShort16 keySize; + MSCKeyACL privateKeyACL; + MSCKeyACL publicKeyACL; + MSCKeyPolicy privateKeyPolicy; + MSCKeyPolicy publicKeyPolicy; + MSCUChar8 keyGenOptions; + MSCPUChar8 pOptParams; + MSCULong32 optParamsSize; + } + MSCGenKeyParams, *MSCLPGenKeyParams; + + typedef MSCPUChar8 MSCLPKeyBlob; + + typedef struct + { + MSCUChar8 keyNum; + MSCUChar8 keyType; + MSCUChar8 keyPartner; /* Do not use (deprecated) */ + MSCUChar8 keyMapping; /* Do not use (deprecated) */ + MSCUShort16 keySize; + MSCKeyPolicy keyPolicy; + MSCKeyACL keyACL; + } + MSCKeyInfo, *MSCLPKeyInfo; + + typedef struct + { + MSCUChar8 keyNum; + MSCUChar8 cipherMode; + MSCUChar8 cipherDirection; + MSCPUChar8 optParams; + MSCUShort16 optParamsSize; + } + MSCCryptInit, *MSCLPCryptInit; + + /* + * Scope definitions for MSCListTokens + */ +#define MSC_LIST_KNOWN 1 /* Lists known tokens only */ +#define MSC_LIST_SLOTS 2 /* Lists all slots, with or without tokens + */ +#define MSC_LIST_ALL 3 /* Lists all tokens, known or not */ + +#define MSC_TOKEN_EMPTY_STR "Token Removed" +#define MSC_TOKEN_UNKNOWN_STR "Token Unknown" + +#define MSC_TOKEN_TYPE_REMOVED 1 /* Token was removed at one point */ +#define MSC_TOKEN_TYPE_UNKNOWN 2 /* Token is unknown, state is fine */ +#define MSC_TOKEN_TYPE_KNOWN 4 /* Token is known, state is fine */ +#define MSC_TOKEN_TYPE_RESET 8 /* Token is known, was reset */ + + /* + * endAction definitions for MSCReleaseConnection + */ +#define MSC_LEAVE_TOKEN SCARD_LEAVE_CARD +#define MSC_RESET_TOKEN SCARD_RESET_CARD +#define MSC_EJECT_TOKEN SCARD_EJECT_CARD + + /* + * sharingMode for MSCEstablishConnection + */ +#define MSC_SHARE_SHARED SCARD_SHARE_SHARED +#define MSC_SHARE_EXCLUSIVE SCARD_SHARE_EXCLUSIVE +#define MSC_SHARE_DIRECT SCARD_SHARE_DIRECT + + /* + * tokenState for MSCWaitForTokenEvent + */ +#define MSC_STATE_UNAWARE 0x4000 +#define MSC_STATE_CHANGED SCARD_STATE_CHANGED +#define MSC_STATE_UNKNOWN SCARD_STATE_UNKNOWN +#define MSC_STATE_UNAVAILABLE SCARD_STATE_UNAVAILABLE +#define MSC_STATE_EMPTY SCARD_STATE_EMPTY +#define MSC_STATE_PRESENT SCARD_STATE_PRESENT +#define MSC_STATE_EXCLUSIVE SCARD_STATE_EXCLUSIVE +#define MSC_STATE_INUSE SCARD_STATE_INUSE +#define MSC_STATE_MUTE SCARD_STATE_MUTE + +#define MSC_NO_TIMEOUT INFINITE + +/********************** TAGS for GetStatus ********************************/ + +#define MSC_TAG_FUNCTIONAL_UNITS 107 /* Card terminal functional units + (PIN pad, display, fingerprint, ...) */ + +#define MSC_SUPPORT_PINPAD 0x00000001 +#define MSC_SUPPORT_DISPLAY 0x00000002 +#define MSC_SUPPORT_FINGERPRINT 0x00000004 + + /* + * high level tags + */ +#define MSC_TAG_SUPPORT_FUNCTIONS 101 /* Supported functions */ +#define MSC_TAG_SUPPORT_CRYPTOALG 102 /* Supported crypto algorithms + */ + + /* + * crypto related tags + */ +#define MSC_TAG_CAPABLE_RSA 103 /* RSA capabilities */ +#define MSC_TAG_CAPABLE_DSA 104 /* DSA capabilities */ +#define MSC_TAG_CAPABLE_ECURVE 105 /* Eliptic Curve capabilities */ +#define MSC_TAG_CAPABLE_ELGAMAL 106 /* El Gamal capabilities */ + +#define MSC_TAG_CAPABLE_KEY_AUTH 180 /* Key import/gen AUT needed */ + +#define MSC_TAG_CAPABLE_DES 201 /* DES capabilities */ +#define MSC_TAG_CAPABLE_3DES 202 /* Triple DES capabilities */ +#define MSC_TAG_CAPABLE_IDEA 203 /* IDEA capabilities */ +#define MSC_TAG_CAPABLE_AES 204 /* AES capabilities */ +#define MSC_TAG_CAPABLE_BLOWFISH 205 /* Blowfish capabilities */ +#define MSC_TAG_CAPABLE_TWOFISH 206 /* Twofish capabilities */ + +#define MSC_TAG_CAPABLE_MD5 207 /* MD5 capabilities */ +#define MSC_TAG_CAPABLE_SHA1 208 /* SHA1 capabilities */ + + /* + * object related tags + */ +#define MSC_TAG_CAPABLE_OBJ_ATTR 301 /* returns general attributes */ +#define MSC_TAG_CAPABLE_OBJ_IDSIZE 302 /* returns size of object id */ +#define MSC_TAG_CAPABLE_OBJ_AUTH 303 /* return AUT needed for + * create */ +#define MSC_TAG_CAPABLE_OBJ_MAXNUM 304 /* maximum number of objects */ + + /* + * pin related tags + */ +#define MSC_TAG_CAPABLE_PIN_ATTR 401 /* returns general attributes */ +#define MSC_TAG_CAPABLE_PIN_MAXNUM 402 /* returns max number of pins */ +#define MSC_TAG_CAPABLE_PIN_MINSIZE 403 /* returns minimum pin size */ +#define MSC_TAG_CAPABLE_PIN_MAXSIZE 404 /* returns maximum pin size */ +#define MSC_TAG_CAPABLE_PIN_CHARSET 405 /* char set supported + * (bitmask) */ +#define MSC_TAG_CAPABLE_PIN_POLICY 406 /* returns pin policy + * (bitmask) */ +#define MSC_TAG_CAPABLE_PIN_AUTH 407 /* return AUT needed for + * create */ + +#define MSC_TAG_CAPABLE_ID_STATE 501 /* returns state capability */ + +#define MSC_TAG_CAPABLE_RANDOM 600 /* Random number capabilities */ +#define MSC_TAG_CAPABLE_RANDOM_MAX 601 /* Maximum random number */ +#define MSC_TAG_CAPABLE_RANDOM_MIN 602 /* Minimum random number */ + +/********************************** END OF TAGS ***************************/ + + /* + * Bitmask for TAG MSC_TAG_SUPPORT_FUNCTIONS + */ +#define MSC_SUPPORT_GENKEYS 0x00000001 +#define MSC_SUPPORT_IMPORTKEY 0x00000002 +#define MSC_SUPPORT_EXPORTKEY 0x00000004 +#define MSC_SUPPORT_COMPUTECRYPT 0x00000008 +#define MSC_SUPPORT_EXTAUTH 0x00000010 +#define MSC_SUPPORT_LISTKEYS 0x00000020 +#define MSC_SUPPORT_CREATEPIN 0x00000040 +#define MSC_SUPPORT_VERIFYPIN 0x00000080 +#define MSC_SUPPORT_CHANGEPIN 0x00000100 +#define MSC_SUPPORT_UNBLOCKPIN 0x00000200 +#define MSC_SUPPORT_LISTPINS 0x00000400 +#define MSC_SUPPORT_CREATEOBJECT 0x00000800 +#define MSC_SUPPORT_DELETEOBJECT 0x00001000 +#define MSC_SUPPORT_WRITEOBJECT 0x00002000 +#define MSC_SUPPORT_READOBJECT 0x00004000 +#define MSC_SUPPORT_LISTOBJECTS 0x00008000 +#define MSC_SUPPORT_LOGOUTALL 0x00010000 +#define MSC_SUPPORT_GETCHALLENGE 0x00020000 +#define MSC_SUPPORT_GETSTATUS 0x00040000 +#define MSC_SUPPORT_ISOVERIFYPIN 0x00080000 +#define MSC_SUPPORT_GSM_CHANGE_CVH 0x00100000 +#define MSC_SUPPORT_GSM_UNBLOCK_CVH 0x00200000 +#define MSC_SUPPORT_GETCAPABILITIES 0x00400000 + + /* + * Bitmask for MSC_TAG_SUPPORT_CRYPTOALG + */ +#define MSC_SUPPORT_RSA 0x00000001 /* Supports RSA */ +#define MSC_SUPPORT_DSA 0x00000002 /* Supports DSA */ +#define MSC_SUPPORT_ECURVE 0x00000004 /* Supports Eliptic Curve */ +#define MSC_SUPPORT_ELGAMAL 0x00000008 /* Supports El Gamal */ + +#define MSC_SUPPORT_DES 0x00000010 /* Supports DES */ +#define MSC_SUPPORT_3DES 0x00000020 /* Supports Triple DES */ +#define MSC_SUPPORT_IDEA 0x00000040 /* Supports IDEA */ +#define MSC_SUPPORT_AES 0x00000080 /* Supports AES */ +#define MSC_SUPPORT_BLOWFISH 0x00000100 /* Supports Blowfish */ +#define MSC_SUPPORT_TWOFISH 0x00000200 /* Supports Twofish */ +#define MSC_SUPPORT_SHA1 0x00000400 /* Supports SHA1 */ +#define MSC_SUPPORT_MD5 0x00000800 /* Supports MD5 */ + + /* + * Bitmask for TAG MSC_TAG_CAPABLE_RSA + */ +#define MSC_CAPABLE_RSA_512 0x00000001 /* Supports 512 bit RSA */ +#define MSC_CAPABLE_RSA_768 0x00000002 /* Supports 768 bit RSA */ +#define MSC_CAPABLE_RSA_1024 0x00000004 /* Supports 1024 bit RSA */ +#define MSC_CAPABLE_RSA_2048 0x00000008 /* Supports 2048 bit RSA */ +#define MSC_CAPABLE_RSA_4096 0x00000010 /* Supports 4096 bit RSA */ + +#define MSC_CAPABLE_RSA_KEYGEN 0x00001000 /* Support RSA key-gen */ +#define MSC_CAPABLE_RSA_NOPAD 0x00002000 /* Supports RSA NO PAD */ +#define MSC_CAPABLE_RSA_PKCS1 0x00004000 /* Supports PKCS padding */ + + /* + * Bitmask for TAG MSC_TAG_CAPABLE_DSA + */ +#define MSC_CAPABLE_DSA_512 0x00000001 /* Supports 512 bit DSA */ +#define MSC_CAPABLE_DSA_768 0x00000002 /* Supports 768 bit DSA */ +#define MSC_CAPABLE_DSA_1024 0x00000004 /* Supports 1024 bit DSA */ +#define MSC_CAPABLE_DSA_2048 0x00000008 /* Supports 2048 bit DSA */ +#define MSC_CAPABLE_DSA_4096 0x00000010 /* Supports 4096 bit DSA */ +#define MSC_CAPABLE_DSA_KEYGEN 0x00001000 /* Supports DSA key-gen */ + + /* + * Bitmask for TAG MSC_TAG_CAPABLE_DES + */ +#define MSC_CAPABLE_DES_KEYGEN 0x00001000 /* Supports DES key-gen */ +#define MSC_CAPABLE_DES_CBC 0x00002000 /* Supports DES CBC mode */ +#define MSC_CAPABLE_DES_EBC 0x00004000 /* Supports DES EBC mode */ +#define MSC_CAPABLE_DES_ECB 0x00008000 /* Supports DES ECB mode */ + + /* + * Bitmask for TAG MSC_TAG_CAPABLE_3DES + */ +#define MSC_CAPABLE_3DES_KEYGEN 0x00001000 /* Supports 3DES key-gen */ +#define MSC_CAPABLE_3DES_3KEY 0x00002000 /* Support 3 key 3DES */ +#define MSC_CAPABLE_3DES_CBC 0x00004000 /* Supports 3DES CBC mode */ +#define MSC_CAPABLE_3DES_EBC 0x00008000 /* Supports 3DES EBC mode */ +#define MSC_CAPABLE_3DES_ECB 0x00010000 /* Supports 3DES ECB mode */ + + /* + * Bitmask for TAG MSC_TAG_CAPABLE_IDEA + */ +#define MSC_CAPABLE_IDEA_KEYGEN 0x00001000 /* Supports IDEA key-gen */ +#define MSC_CAPABLE_IDEA_CBC 0x00002000 /* Supports IDEA CBC mode */ +#define MSC_CAPABLE_IDEA_ECB 0x00008000 /* Supports IDEA ECB mode */ + + /* + * Bitmask for TAG MSC_TAG_CAPABLE_AES + */ +#define MSC_CAPABLE_AES_KEYGEN 0x00001000 /* Supports AES key-gen */ +#define MSC_CAPABLE_AES_CBC 0x00002000 /* Supports AES CBC mode */ +#define MSC_CAPABLE_AES_ECB 0x00008000 /* Supports AES ECB mode */ + + /*********************************** + Bitmasks for other crypto algorithms + will come in future releases + ************************************/ + + /* + * Bitmask for TAG MSC_TAG_CAPABLE_OBJ_ATTR + */ +#define MSC_CAPABLE_OBJ_ZERO 0x00010000 /* Supports zero on DEL */ + + /* + * Bitmask for TAG MSC_TAG_CAPABLE_PIN_ATTR + */ +#define MSC_CAPABLE_PIN_RESET 0x00000100 /* Unblock reset's pin */ +#define MSC_CAPABLE_PIN_LEAVE 0x00000200 /* Unblock leaves pin */ + + /* + * Bitmask for TAG MSC_TAG_CAPABLE_PIN_CHARSET + */ +#define MSC_CAPABLE_PIN_A_Z 0x00000001 /* Supports uppercase A-Z */ +#define MSC_CAPABLE_PIN_a_z 0x00000002 /* Supports lowercase a-z */ +#define MSC_CAPABLE_PIN_0_9 0x00000004 /* Supports numbers 0-9 */ +#define MSC_CAPABLE_PIN_SPACE 0x00000008 /* Supports spaces */ +#define MSC_CAPABLE_PIN_CALC 0x00000010 /* Supports + - / * % .= */ +#define MSC_CAPABLE_PIN_NONALPHA 0x00000020 /* Supports all other + * chars */ + + /* + * Bitmask for TAG MSC_TAG_CAPABLE_PIN_POLICY + */ +#define MSC_CAPABLE_PIN_A_Z 0x00000001 /* Requires uppercase A-Z */ +#define MSC_CAPABLE_PIN_a_z 0x00000002 /* Requires lowercase a-z */ +#define MSC_CAPABLE_PIN_0_9 0x00000004 /* Requires numbers 0-9 */ +#define MSC_CAPABLE_PIN_NONALPHA 0x00000020 /* Requires + * non-alphanumeric */ +#define MSC_CAPABLE_PIN_HISTORY 0x00001000 /* Checks pin history */ + + /* + * Bitmask for TAG MSC_TAG_CAPABLE_ID_STATE + */ +#define MSC_CAPABLE_ID_STATE 0x00000001 /* maintains logged id + * state */ + + /* + * Bitmask for TAG MSC_TAG_CAPABLE_RANDOM + */ +#define MSC_CAPABLE_RANDOM_SEED 0x00000001 /* Uses supplied seed */ + + /* + * Structure used in MSCGetStatus to return status and capability + * information about the inserted token + */ + + typedef struct + { + MSCUShort16 appVersion; /* Applet version number */ + MSCUShort16 swVersion; /* Software version number */ + MSCULong32 freeMemory; /* Free memory for objects */ + MSCULong32 totalMemory; /* Total amount of memory */ + MSCUChar8 usedPINs; /* Number of pins used */ + MSCUChar8 usedKeys; /* Number of keys used */ + MSCUShort16 loggedID; /* Bitmask of ID's verified */ + } + MSCStatusInfo, *MSCLPStatusInfo; + + typedef struct + { + MSCChar8 objectID[MSC_MAXSIZE_OBJID]; + MSCULong32 objectSize; + MSCObjectACL objectACL; + } + MSCObjectInfo, *MSCLPObjectInfo; + + /*******************************************************************/ + /* + * Connection oriented functions + * + * These functions do not coorespond to internal library funcions + * but serve to connect to tokens. You can still use the internal + * PC/SC calls to do this. These provide an abstract means. + */ + /*******************************************************************/ + + /* + * Lists all known tokens on the system + */ + PCSC_API + MSC_RV MSCListTokens(MSCULong32 listScope, /* defines the scope to + * return */ + MSCLPTokenInfo tokenArray, /* token struct array */ + MSCPULong32 arrayLength /* Length of array */ + ); + + /* + * Establishes a connection to the specified token + */ + PCSC_API + MSC_RV MSCEstablishConnection(MSCLPTokenInfo tokenStruct, /* The + * struct + * of + * token */ + MSCULong32 sharingMode, /* Mode of sharing */ + MSCPUChar8 applicationName, /* The applet ID/Name */ + MSCULong32 nameSize, /* The ID/Name Size */ + MSCLPTokenConnection pConnection /* Returned connection */ + ); + + /* + * Releases a connection to the specified token + */ + PCSC_API + MSC_RV MSCReleaseConnection(MSCLPTokenConnection pConnection, /* Connection + * handle + */ + MSCULong32 endAction /* Action to perform */ + ); + + /* + * Blocks for an event to occur on a token + */ + PCSC_API + MSC_RV MSCWaitForTokenEvent(MSCLPTokenInfo tokenArray, /* Array of + * token + * structs */ + MSCULong32 arraySize, /* Size of the array */ + MSCULong32 timeoutValue /* Timeout */ + ); + + /* + * Cancels a pending MSCWaitForTokenEvent + */ + PCSC_API + MSC_RV MSCCancelEventWait(void /* No parameters */ + ); + + /* + * Registers a callback function for event change + */ + PCSC_API + MSC_RV MSCCallbackForTokenEvent(MSCLPTokenInfo tokenArray, /* Array + * of + * token + * structs + */ + MSCULong32 arraySize, /* Size of the array */ + MSCCallBack callBack, /* Callback function */ + MSCPVoid32 appData /* Application data */ + ); + + /* + * Cancels all callback registrations + */ + PCSC_API + MSC_RV MSCCallbackCancelEvent(void); + + /* + * Locks a transaction to the token + */ + PCSC_API + MSC_RV MSCBeginTransaction(MSCLPTokenConnection pConnection /* Connection + * handle */ + ); + + /* + * Releases a locked transaction to the token + */ + PCSC_API + MSC_RV MSCEndTransaction(MSCLPTokenConnection pConnection, /* Connection + * handle */ + MSCULong32 endAction /* Action to perform on token */ + ); + + /* + * Selects applet - Not to be used by applications + */ + MSC_RV MSCSelectAID(MSCLPTokenConnection pConnection, + MSCPUChar8 aidValue, MSCULong32 aidSize); + + /* + * Pre-personalization function + */ + PCSC_API + MSC_RV MSCWriteFramework(MSCLPTokenConnection pConnection, + MSCLPInitTokenParams pInitParams); + + /*****************************************************************/ + /* + * Core MuscleCard functions + */ + /* + * These functions coorespond directly to internal library + */ + /* + * functions. + */ + /*****************************************************************/ + + PCSC_API + MSC_RV MSCGetStatus(MSCLPTokenConnection pConnection, + MSCLPStatusInfo pStatusInfo); + + PCSC_API + MSC_RV MSCGetCapabilities(MSCLPTokenConnection pConnection, + MSCULong32 Tag, MSCPUChar8 Value, MSCPULong32 Length); + + PCSC_API + MSC_RV MSCExtendedFeature(MSCLPTokenConnection pConnection, + MSCULong32 extFeature, + MSCPUChar8 outData, + MSCULong32 outLength, MSCPUChar8 inData, MSCPULong32 inLength); + + PCSC_API + MSC_RV MSCGenerateKeys(MSCLPTokenConnection pConnection, + MSCUChar8 prvKeyNum, + MSCUChar8 pubKeyNum, MSCLPGenKeyParams pParams); + + PCSC_API + MSC_RV MSCImportKey(MSCLPTokenConnection pConnection, + MSCUChar8 keyNum, + MSCLPKeyACL pKeyACL, + MSCPUChar8 pKeyBlob, + MSCULong32 keyBlobSize, + MSCLPKeyPolicy keyPolicy, + MSCPVoid32 pAddParams, MSCUChar8 addParamsSize); + + PCSC_API + MSC_RV MSCExportKey(MSCLPTokenConnection pConnection, + MSCUChar8 keyNum, + MSCPUChar8 pKeyBlob, + MSCPULong32 keyBlobSize, + MSCPVoid32 pAddParams, MSCUChar8 addParamsSize); + + PCSC_API + MSC_RV MSCComputeCrypt(MSCLPTokenConnection pConnection, + MSCLPCryptInit cryptInit, + MSCPUChar8 pInputData, + MSCULong32 inputDataSize, + MSCPUChar8 pOutputData, MSCPULong32 outputDataSize); + + PCSC_API + MSC_RV MSCExtAuthenticate(MSCLPTokenConnection pConnection, + MSCUChar8 keyNum, + MSCUChar8 cipherMode, + MSCUChar8 cipherDirection, + MSCPUChar8 pData, + MSCULong32 dataSize); + + PCSC_API + MSC_RV MSCListKeys(MSCLPTokenConnection pConnection, + MSCUChar8 seqOption, + MSCLPKeyInfo pKeyInfo); + + PCSC_API + MSC_RV MSCCreatePIN(MSCLPTokenConnection pConnection, + MSCUChar8 pinNum, + MSCUChar8 pinAttempts, + MSCPUChar8 pPinCode, + MSCULong32 pinCodeSize, + MSCPUChar8 pUnblockCode, + MSCUChar8 unblockCodeSize); + + PCSC_API + MSC_RV MSCVerifyPIN(MSCLPTokenConnection pConnection, + MSCUChar8 pinNum, + MSCPUChar8 pPinCode, + MSCULong32 pinCodeSize); + + PCSC_API + MSC_RV MSCChangePIN(MSCLPTokenConnection pConnection, + MSCUChar8 pinNum, + MSCPUChar8 pOldPinCode, + MSCUChar8 oldPinCodeSize, + MSCPUChar8 pNewPinCode, MSCUChar8 newPinCodeSize); + + PCSC_API + MSC_RV MSCUnblockPIN(MSCLPTokenConnection pConnection, + MSCUChar8 pinNum, + MSCPUChar8 pUnblockCode, MSCULong32 unblockCodeSize); + + PCSC_API + MSC_RV MSCListPINs(MSCLPTokenConnection pConnection, + MSCPUShort16 pPinBitMask); + + PCSC_API + MSC_RV MSCCreateObject(MSCLPTokenConnection pConnection, + MSCString objectID, + MSCULong32 objectSize, MSCLPObjectACL pObjectACL); + + PCSC_API + MSC_RV MSCDeleteObject(MSCLPTokenConnection pConnection, + MSCString objectID, MSCUChar8 zeroFlag); + + PCSC_API + MSC_RV MSCWriteObject(MSCLPTokenConnection pConnection, + MSCString objectID, MSCULong32 offset, + MSCPUChar8 pInputData, MSCULong32 dataSize, + LPRWEventCallback rwCallback, MSCPVoid32 addParams); + + PCSC_API + MSC_RV MSCReadObject(MSCLPTokenConnection pConnection, + MSCString objectID, MSCULong32 offset, + MSCPUChar8 pOutputData, MSCULong32 dataSize, + LPRWEventCallback rwCallback, MSCPVoid32 addParams); + + PCSC_API + MSC_RV MSCReadAllocateObject(MSCLPTokenConnection pConnection, + MSCString objectID, MSCPUChar8 *pOutputData, + MSCPULong32 dataSize, + LPRWEventCallback rwCallback, MSCPVoid32 addParams); + + PCSC_API + MSC_RV MSCListObjects(MSCLPTokenConnection pConnection, + MSCUChar8 seqOption, MSCLPObjectInfo pObjectInfo); + + PCSC_API + MSC_RV MSCLogoutAll(MSCLPTokenConnection pConnection); + + PCSC_API + MSC_RV MSCGetChallenge(MSCLPTokenConnection pConnection, + MSCPUChar8 pSeed, + MSCUShort16 seedSize, + MSCPUChar8 pRandomData, MSCUShort16 randomDataSize); + + /*****************************************************************/ + /* + * Extended MuscleCard functions + */ + /* + * These functions do not coorespond to internal library funcions + */ + /* + * but rather use them to provide some extended functionality. + */ + /*****************************************************************/ + + PCSC_API + MSC_RV MSCGetKeyAttributes(MSCLPTokenConnection pConnection, + MSCUChar8 keyNumber, + MSCLPKeyInfo pKeyInfo); + + PCSC_API + MSC_RV MSCGetObjectAttributes(MSCLPTokenConnection pConnection, + MSCString objectID, + MSCLPObjectInfo pObjectInfo); + + PCSC_API + char *msc_error(MSC_RV errorCode); + + /* + * Was the token reset ? + */ + PCSC_API + MSCUChar8 MSCIsTokenReset(MSCLPTokenConnection pConnection); + + /* + * Clear the Reset state + */ + PCSC_API + MSCUChar8 MSCClearReset(MSCLPTokenConnection pConnection); + + /* + * Was the token moved (removed, removed/inserted) ? + */ + PCSC_API + MSCUChar8 MSCIsTokenMoved(MSCLPTokenConnection pConnection); + + /* + * Did any state change with the token ? + */ + PCSC_API + MSCUChar8 MSCIsTokenChanged(MSCLPTokenConnection pConnection); + + /* + * Is the token recognized ? + */ + PCSC_API + MSCUChar8 MSCIsTokenKnown(MSCLPTokenConnection pConnection); + +#ifdef __cplusplus +} +#endif + +#endif /* __musclecard_h__ */ diff --git a/hostCodes/Funcard7/linux/pcsclite.h b/hostCodes/Funcard7/linux/pcsclite.h new file mode 100755 index 0000000000000000000000000000000000000000..2056d28e2007608f63dd8f34adde849a42d54985 --- /dev/null +++ b/hostCodes/Funcard7/linux/pcsclite.h @@ -0,0 +1,250 @@ +/* + * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * + * Copyright (C) 1999-2004 + * David Corcoran <corcoran@linuxnet.com> + * Ludovic Rousseau <ludovic.rousseau@free.fr> + * + * $Id: pcsclite.h.in,v 1.3 2005-09-06 20:37:26 rousseau Exp $ + */ + +/** + * @file + * @brief This keeps a list of defines for pcsc-lite. + */ + +#ifndef __pcsclite_h__ +#define __pcsclite_h__ + +#include "wintypes.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef WIN32 +#include "winscard.h" +#else +typedef long SCARDCONTEXT; +typedef SCARDCONTEXT *PSCARDCONTEXT; +typedef SCARDCONTEXT *LPSCARDCONTEXT; +typedef long SCARDHANDLE; +typedef SCARDHANDLE *PSCARDHANDLE; +typedef SCARDHANDLE *LPSCARDHANDLE; + +#define MAX_ATR_SIZE 33 /* Maximum ATR size */ + +typedef struct +{ + const char *szReader; + void *pvUserData; + unsigned long dwCurrentState; + unsigned long dwEventState; + unsigned long cbAtr; + unsigned char rgbAtr[MAX_ATR_SIZE]; +} +SCARD_READERSTATE_A; + +typedef SCARD_READERSTATE_A SCARD_READERSTATE, *PSCARD_READERSTATE_A, + *LPSCARD_READERSTATE_A; + +typedef struct _SCARD_IO_REQUEST +{ + unsigned long dwProtocol; /* Protocol identifier */ + unsigned long cbPciLength; /* Protocol Control Inf Length */ +} +SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST; + +typedef const SCARD_IO_REQUEST *LPCSCARD_IO_REQUEST; + +extern SCARD_IO_REQUEST g_rgSCardT0Pci, g_rgSCardT1Pci, + g_rgSCardRawPci; + +#define SCARD_PCI_T0 (&g_rgSCardT0Pci) +#define SCARD_PCI_T1 (&g_rgSCardT1Pci) +#define SCARD_PCI_RAW (&g_rgSCardRawPci) + +#define SCARD_S_SUCCESS 0x00000000 +#define SCARD_E_CANCELLED 0x80100002 +#define SCARD_E_CANT_DISPOSE 0x8010000E +#define SCARD_E_INSUFFICIENT_BUFFER 0x80100008 +#define SCARD_E_INVALID_ATR 0x80100015 +#define SCARD_E_INVALID_HANDLE 0x80100003 +#define SCARD_E_INVALID_PARAMETER 0x80100004 +#define SCARD_E_INVALID_TARGET 0x80100005 +#define SCARD_E_INVALID_VALUE 0x80100011 +#define SCARD_E_NO_MEMORY 0x80100006 +#define SCARD_F_COMM_ERROR 0x80100013 +#define SCARD_F_INTERNAL_ERROR 0x80100001 +#define SCARD_F_UNKNOWN_ERROR 0x80100014 +#define SCARD_F_WAITED_TOO_LONG 0x80100007 +#define SCARD_E_UNKNOWN_READER 0x80100009 +#define SCARD_E_TIMEOUT 0x8010000A +#define SCARD_E_SHARING_VIOLATION 0x8010000B +#define SCARD_E_NO_SMARTCARD 0x8010000C +#define SCARD_E_UNKNOWN_CARD 0x8010000D +#define SCARD_E_PROTO_MISMATCH 0x8010000F +#define SCARD_E_NOT_READY 0x80100010 +#define SCARD_E_SYSTEM_CANCELLED 0x80100012 +#define SCARD_E_NOT_TRANSACTED 0x80100016 +#define SCARD_E_READER_UNAVAILABLE 0x80100017 + +#define SCARD_W_UNSUPPORTED_CARD 0x80100065 +#define SCARD_W_UNRESPONSIVE_CARD 0x80100066 +#define SCARD_W_UNPOWERED_CARD 0x80100067 +#define SCARD_W_RESET_CARD 0x80100068 +#define SCARD_W_REMOVED_CARD 0x80100069 + +#define SCARD_E_PCI_TOO_SMALL 0x80100019 +#define SCARD_E_READER_UNSUPPORTED 0x8010001A +#define SCARD_E_DUPLICATE_READER 0x8010001B +#define SCARD_E_CARD_UNSUPPORTED 0x8010001C +#define SCARD_E_NO_SERVICE 0x8010001D +#define SCARD_E_SERVICE_STOPPED 0x8010001E + +#define SCARD_SCOPE_USER 0x0000 /* Scope in user space */ +#define SCARD_SCOPE_TERMINAL 0x0001 /* Scope in terminal */ +#define SCARD_SCOPE_SYSTEM 0x0002 /* Scope in system */ + +#define SCARD_PROTOCOL_UNSET 0x0000 /* protocol not set */ +#define SCARD_PROTOCOL_T0 0x0001 /* T=0 active protocol. */ +#define SCARD_PROTOCOL_T1 0x0002 /* T=1 active protocol. */ +#define SCARD_PROTOCOL_RAW 0x0004 /* Raw active protocol. */ +#define SCARD_PROTOCOL_T15 0x0008 /* T=15 protocol. */ + +#define SCARD_PROTOCOL_ANY (SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1) /* IFD determines prot. */ + +#define SCARD_SHARE_EXCLUSIVE 0x0001 /* Exclusive mode only */ +#define SCARD_SHARE_SHARED 0x0002 /* Shared mode only */ +#define SCARD_SHARE_DIRECT 0x0003 /* Raw mode only */ + +#define SCARD_LEAVE_CARD 0x0000 /* Do nothing on close */ +#define SCARD_RESET_CARD 0x0001 /* Reset on close */ +#define SCARD_UNPOWER_CARD 0x0002 /* Power down on close */ +#define SCARD_EJECT_CARD 0x0003 /* Eject on close */ + +#define SCARD_UNKNOWN 0x0001 /* Unknown state */ +#define SCARD_ABSENT 0x0002 /* Card is absent */ +#define SCARD_PRESENT 0x0004 /* Card is present */ +#define SCARD_SWALLOWED 0x0008 /* Card not powered */ +#define SCARD_POWERED 0x0010 /* Card is powered */ +#define SCARD_NEGOTIABLE 0x0020 /* Ready for PTS */ +#define SCARD_SPECIFIC 0x0040 /* PTS has been set */ + +#define SCARD_STATE_UNAWARE 0x0000 /* App wants status */ +#define SCARD_STATE_IGNORE 0x0001 /* Ignore this reader */ +#define SCARD_STATE_CHANGED 0x0002 /* State has changed */ +#define SCARD_STATE_UNKNOWN 0x0004 /* Reader unknown */ +#define SCARD_STATE_UNAVAILABLE 0x0008 /* Status unavailable */ +#define SCARD_STATE_EMPTY 0x0010 /* Card removed */ +#define SCARD_STATE_PRESENT 0x0020 /* Card inserted */ +#define SCARD_STATE_ATRMATCH 0x0040 /* ATR matches card */ +#define SCARD_STATE_EXCLUSIVE 0x0080 /* Exclusive Mode */ +#define SCARD_STATE_INUSE 0x0100 /* Shared Mode */ +#define SCARD_STATE_MUTE 0x0200 /* Unresponsive card */ +#define SCARD_STATE_UNPOWERED 0x0400 /* Unpowered card */ + +#endif + +/* PC/SC Lite specific extensions */ +#define SCARD_W_INSERTED_CARD 0x8010006A +#define SCARD_E_UNSUPPORTED_FEATURE 0x8010001F + +#define SCARD_SCOPE_GLOBAL 0x0003 /* Scope is global */ + +#define SCARD_RESET 0x0001 /* Card was reset */ +#define SCARD_INSERTED 0x0002 /* Card was inserted */ +#define SCARD_REMOVED 0x0004 /* Card was removed */ + +#define BLOCK_STATUS_RESUME 0x00FF /* Normal resume */ +#define BLOCK_STATUS_BLOCKING 0x00FA /* Function is blocking */ + +#define PCSCLITE_CONFIG_DIR "/etc" + +#ifndef USE_IPCDIR +#define PCSCLITE_IPC_DIR "/var/run" +#else +#define PCSCLITE_IPC_DIR USE_IPCDIR +#endif + +#define PCSCLITE_READER_CONFIG PCSCLITE_CONFIG_DIR "/reader.conf" +#define PCSCLITE_PUBSHM_FILE PCSCLITE_IPC_DIR "/pcscd.pub" +#define PCSCLITE_CSOCK_NAME PCSCLITE_IPC_DIR "/pcscd.comm" + +#define PCSCLITE_SVC_IDENTITY 0x01030000 /* Service ID */ + +#ifndef INFINITE +#define INFINITE 0xFFFFFFFF /* Infinite timeout */ +#endif +#define PCSCLITE_INFINITE_TIMEOUT 4320000 /* 50 day infinite t/o */ + +#define PCSCLITE_VERSION_NUMBER "1.2.9-beta9" /* Current version */ +#define PCSCLITE_CLIENT_ATTEMPTS 120 /* Attempts to reach sv */ +#define PCSCLITE_MCLIENT_ATTEMPTS 20 /* Attempts to reach sv */ +#define PCSCLITE_STATUS_POLL_RATE 400000 /* Status polling rate */ +#define PCSCLITE_MSG_KEY_LEN 16 /* App ID key length */ +#define PCSCLITE_RW_ATTEMPTS 100 /* Attempts to rd/wrt */ + +/* Maximum applications */ +#define PCSCLITE_MAX_APPLICATIONS 16 +/* Maximum contexts by application */ +#define PCSCLITE_MAX_APPLICATION_CONTEXTS 16 +/* Maximum of applications contexts that pcscd can accept */ +#define PCSCLITE_MAX_APPLICATIONS_CONTEXTS \ + PCSCLITE_MAX_APPLICATIONS * PCSCLITE_MAX_APPLICATION_CONTEXTS +/* Maximum channels on a reader context */ +#define PCSCLITE_MAX_READER_CONTEXT_CHANNELS 16 +/* Maximum channels on an application context */ +#define PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS 16 +/* Maximum readers context (a slot is count as a reader) */ +#define PCSCLITE_MAX_READERS_CONTEXTS 16 + +/* PCSCLITE_MAX_READERS is deprecated + * use PCSCLITE_MAX_READERS_CONTEXTS instead */ +/* extern int PCSCLITE_MAX_READERS __attribute__ ((deprecated)); */ + +#define PCSCLITE_MAX_THREADS 16 /* Stat change threads */ +#define PCSCLITE_STATUS_WAIT 200000 /* Status Change Sleep */ +#define PCSCLITE_TRANSACTION_TIMEOUT 40 /* Transaction timeout */ +#define MAX_READERNAME 52 +#define MAX_LIBNAME 100 +#define MAX_DEVICENAME 255 + +#ifndef SCARD_ATR_LENGTH +#define SCARD_ATR_LENGTH MAX_ATR_SIZE /* Maximum ATR size */ +#endif + +/* + * Enhanced messaging has been added to accomodate newer devices which have + * more advanced capabilites, such as dedicated secure co-processors which + * can stream and encrypt data over USB. In order to used enhanced messaging + * you must define PCSCLITE_ENHANCED_MESSAGING in the framework(library), + * the daemon, and your application + */ +#undef PCSCLITE_ENHANCED_MESSAGING +#ifndef PCSCLITE_ENHANCED_MESSAGING +#define PCSCLITE_MAX_MESSAGE_SIZE 2048 /* Transport msg len */ +#define MAX_BUFFER_SIZE 264 /* Maximum Tx/Rx Buffer */ +#define PCSCLITE_SERVER_ATTEMPTS 5 /* Attempts to reach cl */ +#else +/* + * The message and buffer sizes must be multiples of 16. + * The max message size must be at least large enough + * to accomodate the transmit_struct + */ +#define PCSCLITE_MAX_MESSAGE_SIZE (1<<17) /* enhanced (128K) msg len */ +#define MAX_BUFFER_SIZE (1<<15) /* enhanced (32K) Tx/Rx Buffer */ +#define PCSCLITE_SERVER_ATTEMPTS 200 /* To allow larger data reads/writes */ +#endif + +/* + * Gets a stringified error response + */ +char *pcsc_stringify_error(long); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hostCodes/Funcard7/linux/reader.h b/hostCodes/Funcard7/linux/reader.h new file mode 100755 index 0000000000000000000000000000000000000000..ebe9c4d458b8a7b054ed552ebd8bae89b418e7af --- /dev/null +++ b/hostCodes/Funcard7/linux/reader.h @@ -0,0 +1,205 @@ +/* + * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * + * Copyright (C) 1999-2005 + * David Corcoran <corcoran@linuxnet.com> + * Ludovic Rousseau <ludovic.rousseau@free.fr> + * + * $Id: reader.h.in,v 1.2 2005-11-27 17:08:32 rousseau Exp $ + */ + +/** + * @file + * @brief This keeps a list of defines shared between the driver and the application + */ + +#ifndef __reader_h__ +#define __reader_h__ + +/* + * Tags for requesting card and reader attributes + */ + +#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) + +#define SCARD_CLASS_VENDOR_INFO 1 /* Vendor information definitions */ +#define SCARD_CLASS_COMMUNICATIONS 2 /* Communication definitions */ +#define SCARD_CLASS_PROTOCOL 3 /* Protocol definitions */ +#define SCARD_CLASS_POWER_MGMT 4 /* Power Management definitions */ +#define SCARD_CLASS_SECURITY 5 /* Security Assurance definitions */ +#define SCARD_CLASS_MECHANICAL 6 /* Mechanical characteristic definitions */ +#define SCARD_CLASS_VENDOR_DEFINED 7 /* Vendor specific definitions */ +#define SCARD_CLASS_IFD_PROTOCOL 8 /* Interface Device Protocol options */ +#define SCARD_CLASS_ICC_STATE 9 /* ICC State specific definitions */ +#define SCARD_CLASS_SYSTEM 0x7fff /* System-specific definitions */ + +#define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100) +#define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101) +#define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102) +#define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103) +#define SCARD_ATTR_CHANNEL_ID SCARD_ATTR_VALUE(SCARD_CLASS_COMMUNICATIONS, 0x0110) +#define SCARD_ATTR_ASYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0120) +#define SCARD_ATTR_DEFAULT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0121) +#define SCARD_ATTR_MAX_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0122) +#define SCARD_ATTR_DEFAULT_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0123) +#define SCARD_ATTR_MAX_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0124) +#define SCARD_ATTR_MAX_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0125) +#define SCARD_ATTR_SYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0126) +#define SCARD_ATTR_POWER_MGMT_SUPPORT SCARD_ATTR_VALUE(SCARD_CLASS_POWER_MGMT, 0x0131) +#define SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0140) +#define SCARD_ATTR_USER_AUTH_INPUT_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0142) +#define SCARD_ATTR_CHARACTERISTICS SCARD_ATTR_VALUE(SCARD_CLASS_MECHANICAL, 0x0150) + +#define SCARD_ATTR_CURRENT_PROTOCOL_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0201) +#define SCARD_ATTR_CURRENT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0202) +#define SCARD_ATTR_CURRENT_F SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0203) +#define SCARD_ATTR_CURRENT_D SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0204) +#define SCARD_ATTR_CURRENT_N SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0205) +#define SCARD_ATTR_CURRENT_W SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0206) +#define SCARD_ATTR_CURRENT_IFSC SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0207) +#define SCARD_ATTR_CURRENT_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0208) +#define SCARD_ATTR_CURRENT_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0209) +#define SCARD_ATTR_CURRENT_CWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020a) +#define SCARD_ATTR_CURRENT_EBC_ENCODING SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020b) +#define SCARD_ATTR_EXTENDED_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020c) + +#define SCARD_ATTR_ICC_PRESENCE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0300) +#define SCARD_ATTR_ICC_INTERFACE_STATUS SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0301) +#define SCARD_ATTR_CURRENT_IO_STATE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0302) +#define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303) +#define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304) + +#define SCARD_ATTR_ESC_RESET SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA000) +#define SCARD_ATTR_ESC_CANCEL SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA003) +#define SCARD_ATTR_ESC_AUTHREQUEST SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA005) +#define SCARD_ATTR_MAXINPUT SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA007) + +#define SCARD_ATTR_DEVICE_UNIT SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0001) +#define SCARD_ATTR_DEVICE_IN_USE SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0002) +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0003) +#define SCARD_ATTR_DEVICE_SYSTEM_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0004) +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0005) +#define SCARD_ATTR_DEVICE_SYSTEM_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0006) +#define SCARD_ATTR_SUPRESS_T1_IFS_REQUEST SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0007) + +#ifdef UNICODE +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_W +#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_W +#else +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_A +#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_A +#endif + +/* + * Provide source compatibility on different platforms + */ +#define SCARD_CTL_CODE(code) (0x42000000 + (code)) + +/* + * TeleTrust Class 2 reader tags + */ +#define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400) + +#define FEATURE_VERIFY_PIN_START 0x01 /* OMNIKEY Proposal */ +#define FEATURE_VERIFY_PIN_FINISH 0x02 /* OMNIKEY Proposal */ +#define FEATURE_MODIFY_PIN_START 0x03 /* OMNIKEY Proposal */ +#define FEATURE_MODIFY_PIN_FINISH 0x04 /* OMNIKEY Proposal */ +#define FEATURE_GET_KEY_PRESSED 0x05 /* OMNIKEY Proposal */ +#define FEATURE_VERIFY_PIN_DIRECT 0x06 /* USB CCID PIN Verify */ +#define FEATURE_MODIFY_PIN_DIRECT 0x07 /* USB CCID PIN Modify */ +#define FEATURE_MCT_READERDIRECT 0x08 /* KOBIL Proposal */ +#define FEATURE_MCT_UNIVERSAL 0x09 /* KOBIL Proposal */ +#define FEATURE_IFD_PIN_PROP 0x0A /* Gemplus Proposal */ +#define FEATURE_ABORT 0x0B /* SCM Proposal */ + +/* structures used (but not defined) in PCSC Part 10 revision 2.01.02: + * "IFDs with Secure Pin Entry Capabilities" */ + +#include <inttypes.h> + +/* Set structure elements aligment on bytes + * http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html */ +#ifdef __APPLE__ +#pragma pack(1) +#else +#pragma pack(push, 1) +#endif + +/* the structure must be 6-bytes long */ +typedef struct +{ + uint8_t tag; + uint8_t length; + uint32_t value; +} PCSC_TLV_STRUCTURE; + +/* the wLangId and wPINMaxExtraDigit are 16-bits long so are subject to byte + * ordering */ +#define HOST_TO_CCID_16(x) (x) +#define HOST_TO_CCID_32(x) (x) + +typedef struct +{ + uint8_t bTimerOut; /* timeout is seconds (00 means use default timeout) */ + uint8_t bTimerOut2; /* timeout in seconds after first key stroke */ + uint8_t bmFormatString; /* formatting options */ + uint8_t bmPINBlockString; /* bits 7-4 bit size of PIN length in APDU, + * bits 3-0 PIN block size in bytes after + * justification and formatting */ + uint8_t bmPINLengthFormat; /* bits 7-5 RFU, + * bit 4 set if system units are bytes, clear if + * system units are bits, + * bits 3-0 PIN length position in system units */ + uint16_t wPINMaxExtraDigit; /* 0xXXYY where XX is minimum PIN size in digits, + and YY is maximum PIN size in digits */ + uint8_t bEntryValidationCondition; /* Conditions under which PIN entry should + * be considered complete */ + uint8_t bNumberMessage; /* Number of messages to display for PIN verification */ + uint16_t wLangId; /* Language for messages */ + uint8_t bMsgIndex; /* Message index (should be 00) */ + uint8_t bTeoPrologue[3]; /* T=1 block prologue field to use (fill with 00) */ + uint32_t ulDataLength; /* length of Data to be sent to the ICC */ + uint8_t abData[1]; /* Data to send to the ICC */ +} PIN_VERIFY_STRUCTURE; + +typedef struct +{ + uint8_t bTimerOut; /* timeout is seconds (00 means use default timeout) */ + uint8_t bTimerOut2; /* timeout in seconds after first key stroke */ + uint8_t bmFormatString; /* formatting options */ + uint8_t bmPINBlockString; /* bits 7-4 bit size of PIN length in APDU, + * bits 3-0 PIN block size in bytes after + * justification and formatting */ + uint8_t bmPINLengthFormat; /* bits 7-5 RFU, + * bit 4 set if system units are bytes, clear if + * system units are bits, + * bits 3-0 PIN length position in system units */ + uint8_t bInsertionOffsetOld; /* Insertion position offset in bytes for + the current PIN */ + uint8_t bInsertionOffsetNew; /* Insertion position offset in bytes for + the new PIN */ + uint16_t wPINMaxExtraDigit; + /* 0xXXYY where XX is minimum PIN size in digits, + and YY is maximum PIN size in digits */ + uint8_t bConfirmPIN; /* Flags governing need for confirmation of new PIN */ + uint8_t bEntryValidationCondition; /* Conditions under which PIN entry should + * be considered complete */ + uint8_t bNumberMessage; /* Number of messages to display for PIN verification*/ + uint16_t wLangId; /* Language for messages */ + uint8_t bMsgIndex1; /* index of 1st prompting message */ + uint8_t bMsgIndex2; /* index of 2d prompting message */ + uint8_t bMsgIndex3; /* index of 3d prompting message */ + uint8_t bTeoPrologue[3]; /* T=1 block prologue field to use (fill with 00) */ + uint32_t ulDataLength; /* length of Data to be sent to the ICC */ + uint8_t abData[1]; /* Data to send to the ICC */ +} PIN_MODIFY_STRUCTURE; + +/* restore default structure elements alignment */ +#ifdef __APPLE__ +#pragma pack() +#else +#pragma pack(pop) +#endif + +#endif + diff --git a/hostCodes/Funcard7/linux/winscard.h b/hostCodes/Funcard7/linux/winscard.h new file mode 100755 index 0000000000000000000000000000000000000000..ddd81e3a0de3022146087fc3285790c3a2ffd890 --- /dev/null +++ b/hostCodes/Funcard7/linux/winscard.h @@ -0,0 +1,94 @@ +/* + * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * + * Copyright (C) 1999-2003 + * David Corcoran <corcoran@linuxnet.com> + * Ludovic Rousseau <ludovic.rousseau@free.fr> + * + * $Id: winscard.h,v 1.3 2005-09-06 20:37:26 rousseau Exp $ + */ + +/** + * @file + * @brief This handles smartcard reader communications. + */ + +#ifndef __winscard_h__ +#define __winscard_h__ + +#include "pcsclite.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + LONG SCardEstablishContext(DWORD dwScope, + LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext); + + LONG SCardReleaseContext(SCARDCONTEXT hContext); + + LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout); + + LONG SCardConnect(SCARDCONTEXT hContext, + LPCTSTR szReader, + DWORD dwShareMode, + DWORD dwPreferredProtocols, + LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol); + + LONG SCardReconnect(SCARDHANDLE hCard, + DWORD dwShareMode, + DWORD dwPreferredProtocols, + DWORD dwInitialization, LPDWORD pdwActiveProtocol); + + LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition); + + LONG SCardBeginTransaction(SCARDHANDLE hCard); + + LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition); + + LONG SCardCancelTransaction(SCARDHANDLE hCard); + + LONG SCardStatus(SCARDHANDLE hCard, + LPTSTR mszReaderNames, LPDWORD pcchReaderLen, + LPDWORD pdwState, + LPDWORD pdwProtocol, + LPBYTE pbAtr, LPDWORD pcbAtrLen); + + LONG SCardGetStatusChange(SCARDCONTEXT hContext, + DWORD dwTimeout, + LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders); + + LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, + LPCVOID pbSendBuffer, DWORD cbSendLength, + LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned); + + LONG SCardTransmit(SCARDHANDLE hCard, + LPCSCARD_IO_REQUEST pioSendPci, + LPCBYTE pbSendBuffer, DWORD cbSendLength, + LPSCARD_IO_REQUEST pioRecvPci, + LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength); + + LONG SCardListReaderGroups(SCARDCONTEXT hContext, + LPTSTR mszGroups, LPDWORD pcchGroups); + + LONG SCardListReaders(SCARDCONTEXT hContext, + LPCTSTR mszGroups, + LPTSTR mszReaders, LPDWORD pcchReaders); + + LONG SCardCancel(SCARDCONTEXT hContext); + + LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, + LPDWORD pcbAttrLen); + + LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, + DWORD cbAttrLen); + + void SCardUnload(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/hostCodes/Funcard7/linux/wintypes.h b/hostCodes/Funcard7/linux/wintypes.h new file mode 100755 index 0000000000000000000000000000000000000000..812633602fb8d51b9507dbf81eb0a3c5d01d9afe --- /dev/null +++ b/hostCodes/Funcard7/linux/wintypes.h @@ -0,0 +1,68 @@ +/* + * MUSCLE SmartCard Development ( http://www.linuxnet.com ) + * + * Copyright (C) 1999 + * David Corcoran <corcoran@linuxnet.com> + * + * $Id: wintypes.h,v 1.3 2005-09-06 20:37:26 rousseau Exp $ + */ + +/** + * @file + * @brief This keeps a list of Windows(R) types. + */ + +#ifndef __wintypes_h__ +#define __wintypes_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if !defined(WIN32) + +#ifndef BYTE + typedef unsigned char BYTE; +#endif + typedef unsigned char UCHAR; + typedef unsigned char *PUCHAR; + typedef unsigned short USHORT; + +#ifndef __COREFOUNDATION_CFPLUGINCOM__ + typedef unsigned long ULONG; + typedef void *LPVOID; + typedef short BOOL; +#endif + + typedef unsigned long *PULONG; + typedef const void *LPCVOID; + typedef unsigned long DWORD; + typedef unsigned long *PDWORD; + typedef unsigned short WORD; + typedef long LONG; + typedef long RESPONSECODE; + typedef const char *LPCTSTR; + typedef const BYTE *LPCBYTE; + typedef BYTE *LPBYTE; + typedef DWORD *LPDWORD; + typedef char *LPTSTR; + + /* this type is deprecated but still used by old drivers and applications + * You should use LPTSTR instead */ + typedef char *LPSTR +#ifdef __GNUC__ + /* __attribute__ is a GCC only extension */ + __attribute__ ((deprecated)) +#endif + ; + +#else +#include <windows.h> +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hostCodes/Funcard7/scard b/hostCodes/Funcard7/scard new file mode 100755 index 0000000000000000000000000000000000000000..4b6d03e330a5108983955017511f8902e5caf3c8 Binary files /dev/null and b/hostCodes/Funcard7/scard differ diff --git a/hostCodes/Funcard7/scard.c b/hostCodes/Funcard7/scard.c new file mode 100755 index 0000000000000000000000000000000000000000..bbe6e2dd91a4dd1144ac284f63e4e80439740e36 --- /dev/null +++ b/hostCodes/Funcard7/scard.c @@ -0,0 +1,76 @@ +#include <stdio.h> +#include <stdlib.h> +#include "scard.h" + +utun tunnel; +SCARDCONTEXT hContext; +SCARDHANDLE hCard; + +int main(int argc, char *argv[]) { + init_signals(); + + if(init_terminal(&hContext,&hCard)) + return -1; + else { + if(open_tunnel(&tunnel) !=-1) { + int output_len; + raw_packet packet; + short sw = 0x9000 ; + + printf("SCARD host adapter is now ready to accept connections\n"); + + /* main loop */ + while((output_len = utun_read(&tunnel, packet.raw, MTU)) >= 0) { + LONG card_status = 0; + int select_ret; + BYTE *packet_ptr; + + if(output_len == 0) + continue; + + select_ret = utun_select(&tunnel); + + /* send the last tun input to the card */ + printf("send %d bytes\n",output_len); + packet_ptr = packet.raw; + do { + unsigned char curr_len = output_len > 255 ? 255 : output_len; + sw = send_apdu(hContext,hCard,packet_ptr,curr_len,&card_status,select_ret); + + if(SW1(sw) < 0x90) { + printf("Error: %02x%02x\n",SW1(sw),SW2(sw)); + break; + } + + packet_ptr += curr_len; + output_len -= curr_len; + } while(output_len > 0); + + /* if there is something else to send, do it now */ + if(select_ret>0) { + memset(&packet,0,sizeof(raw_packet)); + continue; + } + + /* receive data from the card (and forward it to the tun) if needed */ + while(SW2(sw)) { + sw = recv_apdu(hContext,hCard,&tunnel,sw,&card_status); + if(SW1(sw) < 0x90 ) { + printf("Error: %02x%02x\n",SW1(sw),SW2(sw)); + break; + } + } + + if(card_status) { + check_terminal_status(hContext,hCard); + } + memset(&packet,0,sizeof(raw_packet)); + } + } + } + + close_tunnel(&tunnel); + release_terminal(&hContext,&hCard); + + return 0; +} diff --git a/hostCodes/Funcard7/scard.h b/hostCodes/Funcard7/scard.h new file mode 100755 index 0000000000000000000000000000000000000000..a6207321b4e1113306b924d52405ffc5734015e3 --- /dev/null +++ b/hostCodes/Funcard7/scard.h @@ -0,0 +1,78 @@ + +#ifndef SCARD_H +#define SCARD_H 1 + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "utun/utun.h" + +#ifdef WIN32 + #undef UNICODE + #include <windows.h> + #include <winscard.h> + #include "win32/winip.h" + + extern char* pcsc_stringify_error(LONG pcscError); + #define usleep Sleep + #define sleep(_tt) Sleep((_tt)*1000) + #define strlcpy strncpy + #define snprintf _snprintf + #define MAX_ATR_SIZE 36 + #define MAX_READERNAME 128 + #define MAX_BUFFER_SIZE 255 +#else + #include <ctype.h> + #include <netinet/ip.h> + #include "linux/wintypes.h" + #include "linux/pcsclite.h" + #include "linux/winscard.h" +#endif + +//APDU Status Word wrappers +#define SW2(_sw) (((_sw)>>8) & 0xFF) +#define SW1(_sw) ((_sw) & 0xFF) + + + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + + +#define MTU 1500 +#define RECONNECTION_DELAY 3 +#define RECONNECTION_COUNT 100 + +typedef union raw_packet +{ + struct { + struct iphdr ip; + } fmt; + unsigned char raw[MTU+1]; +} raw_packet; + +//-------------------- terminal.c --------------------------------- +//init a card terminal and wait for a smartcard to be inserted ( T0 protocol, shared mode ) +//check if the card is a smews Card with ATR +extern int init_terminal(SCARDCONTEXT *hContext,SCARDHANDLE *hCard); +//disconnect from terminal and currently UNPOWER smartcard too +extern void release_terminal(SCARDCONTEXT *hContext,SCARDHANDLE *hCard); +extern int check_terminal_status(SCARDCONTEXT hContext,SCARDHANDLE hCard); + +//-------------------- apdu.c ---------------------- +extern short send_apdu(SCARDCONTEXT hContext,SCARDHANDLE hCard,char *paquet,int len,LONG *rv,int P2); +extern short recv_apdu(SCARDCONTEXT hContext,SCARDHANDLE hCard,utun *t,unsigned short sw,LONG *rv); + +//------------------- tunnel.c ----------------------- +extern int open_tunnel(utun *tunnel); +extern void close_tunnel(utun *tunnel); + +//------------------- utils.c ------------------------ +extern void print_packet(const unsigned char *ptr,int len); + +//------------------- signal.c ----------------------- +extern void init_signals(void); + +#endif//SCARD_H diff --git a/hostCodes/Funcard7/signal.c b/hostCodes/Funcard7/signal.c new file mode 100755 index 0000000000000000000000000000000000000000..f804f4305743d4b4e0d3e4e58332b0ca86239b58 --- /dev/null +++ b/hostCodes/Funcard7/signal.c @@ -0,0 +1,35 @@ + +#include "scard.h" +#include <signal.h> + +extern utun tunnel; +extern SCARDCONTEXT hContext; +extern SCARDHANDLE hCard; + +int signals[6] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT } ; + +static void test_and_close(int sig_ptr) +{ + switch(sig_ptr) + { + case SIGINT: + case SIGTERM: + fprintf(stderr, "Recv signal %d\n", sig_ptr); + fflush(stderr); + close_tunnel(&tunnel); + release_terminal(&hContext,&hCard); + break; + default: + break; + } + exit(0); +} + +void init_signals(void) +{ + int i; + for (i=0 ; i < 6 ; i++) + signal( signals[i], test_and_close) ; +} + + diff --git a/hostCodes/Funcard7/terminal.c b/hostCodes/Funcard7/terminal.c new file mode 100755 index 0000000000000000000000000000000000000000..cb2b0a531ed4cf58055e2c5aa7335ad61700990d --- /dev/null +++ b/hostCodes/Funcard7/terminal.c @@ -0,0 +1,151 @@ + +#include "scard.h" + +int init_terminal( + SCARDCONTEXT *hContext, + SCARDHANDLE *hCard) +{ + LONG rv; + LPSTR mszReaders; + DWORD dwReaders; + DWORD dwAtrLen,dwProtocol,dwState,dwReaderLen; + BYTE pbAtr[MAX_ATR_SIZE]; + + rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, hContext); + rv = SCardListReaders(*hContext, NULL, NULL, &dwReaders); + mszReaders = malloc(sizeof(char)*dwReaders); + rv = SCardListReaders(*hContext, NULL, mszReaders, &dwReaders); + if(rv) + { + printf("ListReader error: %s\n",pcsc_stringify_error(rv)); + free(mszReaders); + return rv; + } + printf("Reader=%s\n",mszReaders); + + rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, hContext); + if(rv) + { + printf("Connect to reader error: %s\n",pcsc_stringify_error(rv)); + free(mszReaders); + return rv; + } + + rv = SCardConnect(*hContext, mszReaders, SCARD_SHARE_SHARED, + SCARD_PROTOCOL_T0, hCard, &dwProtocol); + if(rv == SCARD_E_NO_SMARTCARD //pcsc preference != + || rv == SCARD_W_REMOVED_CARD //winscard preference + ) + { + printf("Please insert a card in terminal \"%s\"\n",mszReaders); + } + + while(rv == SCARD_E_NO_SMARTCARD + || rv == SCARD_W_REMOVED_CARD) + { + //wait for a card to be inserted + usleep(100); + rv = SCardConnect(*hContext, mszReaders, SCARD_SHARE_SHARED, + SCARD_PROTOCOL_T0, hCard, &dwProtocol); + } + + + if(rv) + { + printf("Connect to card error: %s : err=%X\n",pcsc_stringify_error(rv),rv); + free(mszReaders); + return rv; + } + + dwAtrLen = sizeof(pbAtr); + rv=SCardStatus(*hCard, NULL, &dwReaderLen, &dwState, &dwProtocol, + pbAtr, &dwAtrLen); + + if(rv) + { + printf("Reading ATR error: %s\n",pcsc_stringify_error(rv)); + free(mszReaders); + return rv; + } + else + { + int i; + printf("Reading ATR: "); + for(i=0;i<dwAtrLen;i++) + printf("%.2X ",pbAtr[i]); + printf("\n"); + } + + //TODO : have a better control +// if(!(pbAtr[5]=='S' && pbAtr[6]=='M')) +// { +// printf("This card isn't a smews Card\n"); +// rv = 1; +// } + + + free(mszReaders); + return rv; +} + + +void release_terminal( + SCARDCONTEXT *hContext, + SCARDHANDLE *hCard) +{ + LONG rv; + rv = SCardDisconnect(*hCard, SCARD_UNPOWER_CARD); + if(rv)printf("Disconnect=%s\n",pcsc_stringify_error(rv)); + rv = SCardReleaseContext(*hContext); + if(rv)printf("Release=%s\n",pcsc_stringify_error(rv)); + printf("...Exiting \n"); +} + +int check_terminal_status(SCARDCONTEXT hContext,SCARDHANDLE hCard) +{ + + LONG rv; + DWORD dwAtrLen,dwProtocol,dwState,dwReaderLen; + BYTE pbAtr[MAX_ATR_SIZE]; + int c= 0; + + dwAtrLen = sizeof(pbAtr); + + rv=SCardStatus(hCard, NULL, &dwReaderLen, &dwState, &dwProtocol, + pbAtr, &dwAtrLen); + + if(dwState) + printf("State= %X, Possible diagnostic :\n",dwState); + + + if((dwState & SCARD_ABSENT) == SCARD_ABSENT ) + printf("There is no card in the reader.\n"); + if((dwState & SCARD_PRESENT) == SCARD_PRESENT) + printf("There is a card in the reader, but it has not been moved into position for use.\n"); + if((dwState & SCARD_SWALLOWED) == SCARD_SWALLOWED) + printf("There is a card in the reader in position for use. The card is not powered.\n"); + if((dwState & SCARD_POWERED) == SCARD_POWERED) + printf("Power is being provided to the card, but the reader driver is unaware of the mode of the card.\n"); + if((dwState & SCARD_NEGOTIABLE) == SCARD_NEGOTIABLE ) + printf("The card has been reset and is awaiting PTS negotiation.\n"); + if((dwState & SCARD_SPECIFIC) == SCARD_SPECIFIC) + printf("The card has been reset and specific communication protocols have been established.\n"); + + + rv= 1; + while(rv != SCARD_S_SUCCESS) + { + if(c==RECONNECTION_COUNT) + return -1; + c++; + printf("Trying to reconnect in %ds...\n",RECONNECTION_DELAY); + sleep(RECONNECTION_DELAY); + printf("Trying to reconnect... %d/%d\n",c,RECONNECTION_COUNT); + rv= SCardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, + SCARD_RESET_CARD, &dwProtocol); + printf("%s\n",pcsc_stringify_error(rv)); + } + + return 0; +} + diff --git a/hostCodes/Funcard7/tunnel.c b/hostCodes/Funcard7/tunnel.c new file mode 100755 index 0000000000000000000000000000000000000000..b14c9a949ea3d4253ab583860178befbffce6b6a --- /dev/null +++ b/hostCodes/Funcard7/tunnel.c @@ -0,0 +1,12 @@ + +#include "scard.h" + +int open_tunnel(utun *tunnel) +{ + return utun_open(tunnel,"192.168.1.5", "192.168.1.6",MTU); +} + +void close_tunnel(utun *tunnel) +{ + utun_close(tunnel); +} diff --git a/hostCodes/Funcard7/utils.c b/hostCodes/Funcard7/utils.c new file mode 100755 index 0000000000000000000000000000000000000000..7a1d666dffb7a4f96eee5bef6db215a053263e26 --- /dev/null +++ b/hostCodes/Funcard7/utils.c @@ -0,0 +1,173 @@ + +#include "scard.h" + +#ifdef WIN32 +char* pcsc_stringify_error(LONG pcscError) +{ + static char strError[75]; + + switch (pcscError) + { + case SCARD_S_SUCCESS: + strlcpy(strError, "Command successful.", sizeof(strError)); + break; + case SCARD_E_CANCELLED: + strlcpy(strError, "Command cancelled.", sizeof(strError)); + break; + case SCARD_E_CANT_DISPOSE: + strlcpy(strError, "Cannot dispose handle.", sizeof(strError)); + break; + case SCARD_E_INSUFFICIENT_BUFFER: + strlcpy(strError, "Insufficient buffer.", sizeof(strError)); + break; + case SCARD_E_INVALID_ATR: + strlcpy(strError, "Invalid ATR.", sizeof(strError)); + break; + case SCARD_E_INVALID_HANDLE: + strlcpy(strError, "Invalid handle.", sizeof(strError)); + break; + case SCARD_E_INVALID_PARAMETER: + strlcpy(strError, "Invalid parameter given.", sizeof(strError)); + break; + case SCARD_E_INVALID_TARGET: + strlcpy(strError, "Invalid target given.", sizeof(strError)); + break; + case SCARD_E_INVALID_VALUE: + strlcpy(strError, "Invalid value given.", sizeof(strError)); + break; + case SCARD_E_NO_MEMORY: + strlcpy(strError, "Not enough memory.", sizeof(strError)); + break; + case SCARD_F_COMM_ERROR: + strlcpy(strError, "RPC transport error.", sizeof(strError)); + break; + case SCARD_F_INTERNAL_ERROR: + strlcpy(strError, "Internal error.", sizeof(strError)); + break; + case SCARD_F_UNKNOWN_ERROR: + strlcpy(strError, "Unknown error.", sizeof(strError)); + break; + case SCARD_F_WAITED_TOO_LONG: + strlcpy(strError, "Waited too long.", sizeof(strError)); + break; + case SCARD_E_UNKNOWN_READER: + strlcpy(strError, "Unknown reader specified.", sizeof(strError)); + break; + case SCARD_E_TIMEOUT: + strlcpy(strError, "Command timeout.", sizeof(strError)); + break; + case SCARD_E_SHARING_VIOLATION: + strlcpy(strError, "Sharing violation.", sizeof(strError)); + break; + case SCARD_E_NO_SMARTCARD: + strlcpy(strError, "No smart card inserted.", sizeof(strError)); + break; + case SCARD_E_UNKNOWN_CARD: + strlcpy(strError, "Unknown card.", sizeof(strError)); + break; + case SCARD_E_PROTO_MISMATCH: + strlcpy(strError, "Card protocol mismatch.", sizeof(strError)); + break; + case SCARD_E_NOT_READY: + strlcpy(strError, "Subsystem not ready.", sizeof(strError)); + break; + case SCARD_E_SYSTEM_CANCELLED: + strlcpy(strError, "System cancelled.", sizeof(strError)); + break; + case SCARD_E_NOT_TRANSACTED: + strlcpy(strError, "Transaction failed.", sizeof(strError)); + break; + case SCARD_E_READER_UNAVAILABLE: + strlcpy(strError, "Reader is unavailable.", sizeof(strError)); + break; + case SCARD_W_UNSUPPORTED_CARD: + strlcpy(strError, "Card is not supported.", sizeof(strError)); + break; + case SCARD_W_UNRESPONSIVE_CARD: + strlcpy(strError, "Card is unresponsive.", sizeof(strError)); + break; + case SCARD_W_UNPOWERED_CARD: + strlcpy(strError, "Card is unpowered.", sizeof(strError)); + break; + case SCARD_W_RESET_CARD: + strlcpy(strError, "Card was reset.", sizeof(strError)); + break; + case SCARD_W_REMOVED_CARD: + strlcpy(strError, "Card was removed.", sizeof(strError)); + break; + /*case SCARD_W_INSERTED_CARD: + strlcpy(strError, "Card was inserted.", sizeof(strError)); + break;*/ + case SCARD_E_UNSUPPORTED_FEATURE: + strlcpy(strError, "Feature not supported.", sizeof(strError)); + break; + case SCARD_E_PCI_TOO_SMALL: + strlcpy(strError, "PCI struct too small.", sizeof(strError)); + break; + case SCARD_E_READER_UNSUPPORTED: + strlcpy(strError, "Reader is unsupported.", sizeof(strError)); + break; + case SCARD_E_DUPLICATE_READER: + strlcpy(strError, "Reader already exists.", sizeof(strError)); + break; + case SCARD_E_CARD_UNSUPPORTED: + strlcpy(strError, "Card is unsupported.", sizeof(strError)); + break; + case SCARD_E_NO_SERVICE: + strlcpy(strError, "Service not available.", sizeof(strError)); + break; + case SCARD_E_SERVICE_STOPPED: + strlcpy(strError, "Service was stopped.", sizeof(strError)); + break; + case SCARD_E_NO_READERS_AVAILABLE: + strlcpy(strError, "Cannot find a smart card reader.", sizeof(strError)); + break; + default: + snprintf(strError, sizeof(strError)-1, "Unkown error: 0x%08lX", + pcscError); + }; + + /* add a null byte */ + strError[sizeof(strError)-1] = '\0'; + + return strError; +} + +#endif + +void print_packet(const unsigned char *ptr,int len) +{ + int i,j; + + printf("Dumping %dbytes\n",len); + for(i=0;i<len;i++) + { + printf("%.4X: ",i); + for(j=0;i+j<len && j<16;j++) + { + printf("%.2X",ptr[i+j]); + } + if(j<16) + { + for(;j<16;j++) + printf(" "); + } + printf(" "); + for(j=0;i+j<len && j<16;j++) + { + printf("%c",isgraph(ptr[i+j])?ptr[i+j]:'.'); + } + if(j<16) + { + for(;j<16;j++) + printf(" "); + } + printf("\n"); + + i+=15; + } + printf("\n"); + fflush(stdout); + +} + diff --git a/hostCodes/Funcard7/utun/nixtun.c b/hostCodes/Funcard7/utun/nixtun.c new file mode 100755 index 0000000000000000000000000000000000000000..5454e4a63d3c2d521a35d3d452ceb08525f154fd --- /dev/null +++ b/hostCodes/Funcard7/utun/nixtun.c @@ -0,0 +1,103 @@ +/* +*Lib Universal TUN (libutun) Copyright(C) Geoffroy Cogniaux < geoffroy@cogniaux.com > +* +*Lib Universal TUN 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.1 of the License, or(at your option)any later version. +* +*Lib Universal TUN 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 Lib Universal TUN; if not, write to the Free Software +*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA +* +*/ + +#if defined LINUX || defined FREEBSD +#include "utun.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <linux/if.h> +#include <linux/if_tun.h> + +#define TUN_MTU 1500 +#define TUN_DEV "/dev/net/tun" +#define IFCONFIG "ifconfig %s %s pointopoint %s mtu %d" + +int utun_open (utun *t, char *ip_src, char *ip_dest, unsigned long mtu) +{ + struct ifreq ifr; + int fd, err; + char buf[256] ; + + if( (fd = open(TUN_DEV, O_RDWR)) < 0 ) + { + printf("Unable to open %s\n",TUN_DEV); + return -1; + } + + memset(&ifr, 0, sizeof(ifr)); + + ifr.ifr_flags = IFF_TUN|IFF_NO_PI ; + + if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) + { + close(fd); + return -1; + } + //printf("Device used for tunnel : %s \n",ifr.ifr_name); + + snprintf(buf,256, IFCONFIG, ifr.ifr_name, ip_src, ip_dest, mtu>100?mtu:TUN_MTU); + system(buf); +#ifdef FREEBSD + if( fd > -1 ) + { + int i=0; + /* Disable extended modes */ + ioctl(fd, TUNSLMODE, &i); + i = 1; + ioctl(fd, TUNSIFHEAD, &i); + } +#endif + t->fd= fd; + return fd; +} + +int utun_write (utun *t, unsigned char *buf, int len) +{ + return write(t->fd,buf,len); +} + +int utun_read (utun *t, unsigned char *buf, int len) +{ + return read(t->fd,buf,len); +} + +void utun_close (utun *t) +{ + close(t->fd); + t->fd= -1; +} + +int utun_select(utun *t) +{ + struct timeval tv; + fd_set fd_readset; + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_ZERO(&fd_readset); + FD_SET(t->fd, &fd_readset); + return select(t->fd + 1, &fd_readset, NULL, NULL, &tv); +} + + +#endif diff --git a/hostCodes/Funcard7/utun/nixtun.h b/hostCodes/Funcard7/utun/nixtun.h new file mode 100755 index 0000000000000000000000000000000000000000..9d89091dd7cf2343d672d3a37b17243769452160 --- /dev/null +++ b/hostCodes/Funcard7/utun/nixtun.h @@ -0,0 +1,35 @@ +/* +*Lib Universal TUN (libutun) Copyright(C) Geoffroy Cogniaux < geoffroy@cogniaux.com > +* +*Lib Universal TUN 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.1 of the License, or(at your option)any later version. +* +*Lib Universal TUN 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 DoKoD Parser; if not, write to the Free Software +*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA +* +*/ + +#ifndef LIN_TUN_H +#define LIN_TUN_H 1 + +#define utun_htons htons +#define utun_ntohs ntohs +#define utun_htonl htonl +#define utun_ntohl ntohl +#define utun_inet_addr inet_addr + +typedef struct tun_t { + int fd; +} utun; + + +#endif + diff --git a/hostCodes/Funcard7/utun/utun.c b/hostCodes/Funcard7/utun/utun.c new file mode 100755 index 0000000000000000000000000000000000000000..4c56476e4c45abcbf829f2f4c47b51c168e447dc --- /dev/null +++ b/hostCodes/Funcard7/utun/utun.c @@ -0,0 +1,20 @@ +/* +*Lib Universal TUN (libutun) Copyright(C) Geoffroy Cogniaux < geoffroy@cogniaux.com > +* +*Lib Universal TUN 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.1 of the License, or(at your option)any later version. +* +*Lib Universal TUN 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 Lib Universal TUN; if not, write to the Free Software +*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA +* +*/ + + diff --git a/hostCodes/Funcard7/utun/utun.h b/hostCodes/Funcard7/utun/utun.h new file mode 100755 index 0000000000000000000000000000000000000000..09880763201b4a24a3e6e7d31205fe1fc2c3d865 --- /dev/null +++ b/hostCodes/Funcard7/utun/utun.h @@ -0,0 +1,63 @@ +/* +*Lib Universal TUN (libutun) Copyright(C) Geoffroy Cogniaux < geoffroy@cogniaux.com > +* +*Lib Universal TUN 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.1 of the License, or(at your option)any later version. +* +*Lib Universal TUN 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 Lib Universal TUN; if not, write to the Free Software +*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA +* +*/ + +#ifndef UTUN_H +#define UTUN_H 1 + +#ifdef WIN32 +#include "wintun.h" +#elif defined LINUX || defined FREEBSD +#include "nixtun.h" +#else +#error Your system isn't supported by libutun, but you can help us to do it. Thanks. +#endif + +//Portable functions definitions +/** +Open a new TUN device.<br> +The <b>utun</b> structure is platform specific and should not be used directly in a <b>portable</b> program.<br> +<code> +utun t; +utun_open(&t,"192.168.1.5","192.168.1.6"); +</code> +*/ +extern int utun_open (utun *t, char *ip_src, char *ip_dest, unsigned long mtu); + +/** +Write a paquet on an opened device. +*/ +extern int utun_write (utun *t, unsigned char *buf, int len); + +/** +Read a paquet from an opened device. +*/ +extern int utun_read (utun *t, unsigned char *buf, int len); + +/** +Close an opened device. +*/ +extern void utun_close (utun *t); + +/** +Test an opened device for bytes availablity. +*/ +extern int utun_select(utun *t);// do not work on all platform + +#endif + diff --git a/hostCodes/Funcard7/utun/utuntest.c b/hostCodes/Funcard7/utun/utuntest.c new file mode 100755 index 0000000000000000000000000000000000000000..421c8a7bd8723d727d0aba80edf83046208fe984 --- /dev/null +++ b/hostCodes/Funcard7/utun/utuntest.c @@ -0,0 +1,100 @@ +/* +*Lib Universal TUN (libutun) Copyright(C) Geoffroy Cogniaux < geoffroy@cogniaux.com > +* +*Lib Universal TUN 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.1 of the License, or(at your option)any later version. +* +*Lib Universal TUN 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 Lib Universal TUN; if not, write to the Free Software +*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA +* +*/ +#include "utun.h" + +/** + +usage : +launch utuntest in a shell +open a new shell, try to ping 192.168.1.6, let see what happen +NB : this sample is pre-configurated with Win32 limitations, see wintun.c +*/ + +#define LOCAL_MTU 255 + +static void print_packet(const unsigned char *ptr,int len); + +int main(int argc, char *argv[]) +{ + utun t; + + if(utun_open(&t,"192.168.1.5","192.168.1.6",LOCAL_MTU)==0) + { + unsigned char paquet[LOCAL_MTU]; + int len; + + memset(paquet,0,LOCAL_MTU); + + while((len= utun_read(&t,paquet,LOCAL_MTU))>-1) + { + if(len==0) + { + fprintf(stderr,"Why should I receive 0 bytes ?\n"); + continue; + } + print_packet(paquet,len); + if(len) + { + //echo-reply + utun_write(&t,paquet,len); + } + } + + utun_close(&t); + } + + return 0; +} + +void print_packet(const unsigned char *ptr,int len) +{ + int i,j; + + printf("Dumping %dbytes\n",len); + for(i=0;i<len;i++) + { + printf("%.4X: ",i); + for(j=0;i+j<len && j<16;j++) + { + printf("%.2X",ptr[i+j]); + } + if(j<16) + { + for(;j<16;j++) + printf(" "); + } + printf(" "); + for(j=0;i+j<len && j<16;j++) + { + printf("%c",isgraph(ptr[i+j])?ptr[i+j]:'.'); + } + if(j<16) + { + for(;j<16;j++) + printf(" "); + } + printf("\n"); + + i+=15; + } + printf("\n"); + fflush(stdout); + +} + diff --git a/hostCodes/Funcard7/utun/wintun.c b/hostCodes/Funcard7/utun/wintun.c new file mode 100755 index 0000000000000000000000000000000000000000..f71cd6be1b24db32b168ba123ce8d8a0e78b8db4 --- /dev/null +++ b/hostCodes/Funcard7/utun/wintun.c @@ -0,0 +1,492 @@ +/* +*Lib Universal TUN (libutun) Copyright(C) Geoffroy Cogniaux < geoffroy@cogniaux.com > +* +*Lib Universal TUN 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.1 of the License, or(at your option)any later version. +* +*Lib Universal TUN 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 Lib Universal TUN; if not, write to the Free Software +*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA +* +** +*Lib Universal TUN uses TAP-Win32 on Windows(r) +* -- A kernel driver to provide virtual tap device +* functionality on Windows. Originally derived +* from the CIPE-Win32 project by Damion K. Wilson, +* with extensive modifications by James Yonan. +* +*All original source code using TAP-Win32 which derives from the CIPE-Win32 project is +*Copyright (C) Damion K. Wilson, 2003, and is released under the +*GPL version 2. +* +*All other original source code using TAP-Win32 is +*Copyright (C) 2002-2006 OpenVPN Solutions LLC, +*and is released under the GPL version 2 . + + + +On Windows, point-to-point IP support (i.e. --dev tun) +is emulated by the TAP-Win32 driver. The major limitation +imposed by this approach is that the --ifconfig local and +remote endpoints must be part of the same 255.255.255.252 +subnet. The following list shows examples of endpoint +pairs which satisfy this requirement. Only the final +component of the IP address pairs is at issue. + +As an example, the following option would be correct: + --ifconfig 10.7.0.5 10.7.0.6 (on host A) + --ifconfig 10.7.0.6 10.7.0.5 (on host B) +because [5,6] is part of the below list. + +[ 1, 2] [ 5, 6] [ 9, 10] [ 13, 14] [ 17, 18] +[ 21, 22] [ 25, 26] [ 29, 30] [ 33, 34] [ 37, 38] +[ 41, 42] [ 45, 46] [ 49, 50] [ 53, 54] [ 57, 58] +[ 61, 62] [ 65, 66] [ 69, 70] [ 73, 74] [ 77, 78] +[ 81, 82] [ 85, 86] [ 89, 90] [ 93, 94] [ 97, 98] +[101,102] [105,106] [109,110] [113,114] [117,118] +[121,122] [125,126] [129,130] [133,134] [137,138] +[141,142] [145,146] [149,150] [153,154] [157,158] +[161,162] [165,166] [169,170] [173,174] [177,178] +[181,182] [185,186] [189,190] [193,194] [197,198] +[201,202] [205,206] [209,210] [213,214] [217,218] +[221,222] [225,226] [229,230] [233,234] [237,238] +[241,242] [245,246] [249,250] [253,254] + +*/ + + +#ifdef WIN32 +#include "utun.h" + +int utun_write (utun *t, unsigned char *buf, int len) +{ + DWORD write_size, last_err; + + ResetEvent(t->overlap_write.hEvent); + if(WriteFile(t->device_handle,buf,len,&write_size,&t->overlap_write)) + { + return write_size; + } + switch (last_err = GetLastError()) + { + case ERROR_IO_PENDING: + { + WaitForSingleObject(t->overlap_write.hEvent, INFINITE); + GetOverlappedResult(t->device_handle, &t->overlap_write, + &write_size, FALSE); + return write_size; + } + break; + default: + { + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + last_err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + printf( "utun_write failed with error %d: %s\n", last_err, lpMsgBuf ); + } + break; + } + + return -1; +} + +int utun_read (utun *t, unsigned char *buf, int len) +{ + DWORD read_size, last_err; + + ResetEvent(t->overlap_read.hEvent); + if (ReadFile(t->device_handle, buf, len, &read_size, &t->overlap_read)) + { + return read_size; + } + switch (last_err = GetLastError()) + { + case ERROR_IO_PENDING: + { + WaitForSingleObject(t->overlap_read.hEvent, INFINITE); + GetOverlappedResult(t->device_handle, &t->overlap_read, &read_size, FALSE); + return read_size; + } + break; + default: + { + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + last_err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + printf( "utun_read failed with error %d: %s\n", last_err, lpMsgBuf ); + } + break; + } + + return -1; +} + +int utun_open (utun *t, char *ip_src, char *ip_dest,unsigned long mtu) +{ + HKEY key, key2; + long rc; + char regpath[1024], cmd[256]; + char adapterid[1024]; + char adaptername[1024]; + char tapname[1024]; + long len; + int found = 0; + int err, i; + unsigned long status = TRUE; +#ifdef _DEBUG + ULONG info[3]; +#endif + + memset(t, 0, sizeof(utun)); + t->device_handle = INVALID_HANDLE_VALUE; + t->ip_src = utun_inet_addr(ip_src); + + /* Open registry and look for a working TAP-WIN32 network adapters */ + if((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key))) + { + printf("Unable to read registry: [rc=%d]\n", rc); + return -1; + } + + for (i = 0; ; i++) + { + len = sizeof(adapterid); + if(RegEnumKeyEx(key, i, (LPCWSTR)adapterid, &len, 0, 0, 0, NULL)) + break; + + /* Find out more about this adapter */ + + _snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid); + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)regpath, 0, KEY_READ, &key2)) + continue; + + len = sizeof(adaptername); + err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len); + + RegCloseKey(key2); + + if(err) + continue; + + _snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid); + t->device_handle = CreateFile(tapname, + GENERIC_WRITE | GENERIC_READ, + 0,0, + OPEN_EXISTING, + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, + 0); + if(t->device_handle != INVALID_HANDLE_VALUE) + { + found = 1; + break; + } + else + { + LPVOID lpMsgBuf; + DWORD dw = GetLastError(); + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + + if(dw!=2)//File not found . + { + //could inform that a TAP is found but isn't working well. + printf("Adapter %s, file %s\n",adaptername,tapname); + printf( "utun_open failed with error %d: %s\n", dw, lpMsgBuf ); + } + } + }//end for + + RegCloseKey(key); + + if(!found) + { + printf("No Windows tap device found!\n"); + return -1; + } + + /* Try to open the useful TAP-Win32 driver !! */ + + if(t->device_handle == INVALID_HANDLE_VALUE) + { + _snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid); + t->device_handle = + CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); + } + + if(t->device_handle == INVALID_HANDLE_VALUE) + { + printf("%s (%s) is not a usable TAP-Win32\n", adaptername, adapterid); + return -1; + } + +#ifdef _DEBUG + if (DeviceIoControl (t->device_handle, TAP_IOCTL_GET_VERSION, + &info, sizeof (info), + &info, sizeof (info), &len, NULL)) + { + printf( "Loading TAP-Win32 Driver Version %d.%d %s\n", + (int) info[0], + (int) info[1], + (info[2] ? "(DEBUG)" : "")); + + } +#endif + + //Configure as PtoP, require to emulate TUN + if(t->device_handle) + { + ULONG ep[2]; + ep[0] = utun_inet_addr(ip_src); + ep[1] = utun_inet_addr(ip_dest); + + if (!DeviceIoControl (t->device_handle, TAP_IOCTL_CONFIG_POINT_TO_POINT, + ep, sizeof (ep), + ep, sizeof (ep), &len, NULL)) + { + printf( "ERROR: The TAP-Win32 driver rejected a DeviceIoControl call to set Point-to-Point mode"); + return -1; + } + } + + _snprintf(cmd, sizeof(cmd), + "netsh interface ip set address \"%s\" static %s 255.255.255.252",adaptername,ip_src); +#ifdef _DEBUG + printf("Setting to \"%s\" device a correct address, please wait...\n", adaptername); + printf("Excuting: %s\n", cmd); +#endif + if(system(cmd) == 0) + { + t->ip_src= utun_inet_addr(ip_src); + t->ip_dest= utun_inet_addr(ip_dest); +#ifdef _DEBUG + printf("Device \"%s\" set from %s to %s\n", adaptername, ip_src, ip_dest); +#endif + } + else + { + _snprintf(cmd, sizeof(cmd),"netsh interface ip show config \"%s\"",adaptername); + printf("WNG: Unable to set correctly IP addresses, please check it manually.\n", adaptername); + system(cmd); + } + + /* try to change MTU */ + if(mtu >= 100 && mtu <= 1500)// TAP-WIN32 V8 constraint + { + char cfgid[1024]; + char keyid[32]; + char str_mtu[32]; + + itoa(mtu,str_mtu,10); + + if((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ADAPTER_KEY, 0, KEY_READ, &key))) + { + printf("Unable to read registry: [rc=%d]\n", rc); + return -1; + } + for (i = 0; ; i++) + { + int len = sizeof(keyid); + if(RegEnumKeyEx(key, i, (LPCWSTR)keyid, &len, 0, 0, 0, NULL)) + break; + + _snprintf(regpath, sizeof(regpath), "%s\\%s\\", ADAPTER_KEY, keyid); + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)regpath, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, &key2)) + continue; + + len = sizeof(cfgid); + err = RegQueryValueEx(key2, "NetCfgInstanceId", 0, 0, cfgid, &len); + + if(strcmp(adapterid,cfgid)==0) + { + RegSetValueEx(key2,"MTU",0,REG_SZ,(LPCTSTR)&str_mtu,sizeof(DWORD)); + + RegCloseKey(key2); + break; + } + else + continue; + } + RegCloseKey(key); + + } + + + /* set driver media status to 'connected' (i.e. set the interface up) */ + if (!DeviceIoControl (t->device_handle, TAP_IOCTL_SET_MEDIA_STATUS, + &status, sizeof (status), + &status, sizeof (status), &len, NULL)) + { + printf("WARNING: Unable to enable TAP adapter\n"); + return -1; + } + + + t->overlap_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + t->overlap_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (!t->overlap_read.hEvent || !t->overlap_write.hEvent) + { + printf("WARNING: Unable to create Overlapped Events\n"); + return -1; + } + + return 0; +} + +void utun_close (utun *t) +{ + CancelIo(t->device_handle); + CloseHandle(t->overlap_read.hEvent); + CloseHandle(t->overlap_write.hEvent); + CloseHandle(t->device_handle); +} + +int utun_select(utun *t) +{ + + return 0; +} + + +__inline unsigned short utun_htons(unsigned short n) +{ + return ((n & 0xFF) << 8) | ((n & 0xFF00) >> 8); +} + +__inline unsigned short utun_ntohs(unsigned short n) +{ + return ((n & 0xFF) << 8) | ((n & 0xFF00) >> 8); +} + +__inline unsigned long utun_htonl(unsigned long n) +{ + return ((n & 0xFF) << 24) | ((n & 0xFF00) << 8) | ((n & 0xFF0000) >> 8) | ((n & 0xFF000000) >> 24); +} + +__inline unsigned long utun_ntohl(unsigned long n) +{ + return ((n & 0xFF) << 24) | ((n & 0xFF00) << 8) | ((n & 0xFF0000) >> 8) | ((n & 0xFF000000) >> 24); +} + +unsigned long utun_inet_addr(const char *src) +{ + unsigned int val; + int base, n; + unsigned char c; + unsigned int parts[4]; + unsigned int *pp = parts; + + c = *src; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; base = 10; + if (c == '0') { + c = *++src; + if (toupper(c) == 'X') + base = 16, c = *++src; + else + base = 8; + } + for (;;) { + if (isdigit(c)) { + val = (val * base) + (c - '0'); + c = *++src; + } else if (base == 16 && isxdigit(toupper(c))) { + val = (val << 4) | + (toupper(c) + 10 - 'A'); + c = *++src; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++src; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && !isspace(c)) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + + val = utun_htonl(val); + return (val); +} + + + + +#endif + diff --git a/hostCodes/Funcard7/utun/wintun.h b/hostCodes/Funcard7/utun/wintun.h new file mode 100755 index 0000000000000000000000000000000000000000..0edda2a8ab57654b371931af6829f0f18be477f3 --- /dev/null +++ b/hostCodes/Funcard7/utun/wintun.h @@ -0,0 +1,99 @@ +/* +*Lib Universal TUN (libutun) Copyright(C) Geoffroy Cogniaux < geoffroy@cogniaux.com > +* +*Lib Universal TUN 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.1 of the License, or(at your option)any later version. +* +*Lib Universal TUN 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 Lib Universal TUN; if not, write to the Free Software +*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA +* +** +*Lib Universal TUN uses TAP-Win32 on Windows(r) +* -- A kernel driver to provide virtual tap device +* functionality on Windows. Originally derived +* from the CIPE-Win32 project by Damion K. Wilson, +* with extensive modifications by James Yonan. +* +*All source code using TAP-Win32 which derives from the CIPE-Win32 project is +*Copyright (C) Damion K. Wilson, 2003, and is released under the +*GPL version 2. +* +*All other source code using TAP-Win32 is +*Copyright (C) 2002-2006 OpenVPN Solutions LLC, +*and is released under the GPL version 2 . +*/ + +#ifndef WINTUN_H +#define WINTUN_H 1 + +#ifdef WIN32 +#undef UNICODE +#include <windows.h> +#include <winioctl.h> +#include <stdio.h> +#include <string.h> + +#define itoa _itoa +#define snprint _snprintf + +//some decl avoiding winsock import, differents names are requiered because accessibles via windows.h in VC++ +extern unsigned short utun_htons(unsigned short n); +extern unsigned short utun_ntohs(unsigned short n); +extern unsigned long utun_htonl(unsigned long n); +extern unsigned long utun_ntohl(unsigned long n); +extern unsigned long utun_inet_addr(const char *src); + +#if defined (__CYGWIN__) +struct in_addr +{ + union + { + struct { unsigned char s_b1, s_b2, s_b3, s_b4; } s_un_b; + struct { unsigned short s_w1, s_w2; } s_un_w; + unsigned long s_addr; + }; +}; +#endif + +typedef struct tun_t { + HANDLE device_handle; + unsigned int ip_src,ip_dest; + OVERLAPPED overlap_read, overlap_write; +} utun; + + +//Following come from OpenVpn +#define TAP_CONTROL_CODE(request,method) \ + CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) + +#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED) +#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED) +#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED) +#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED) +#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED) +#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED) + +#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" +#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" + +#define USERMODEDEVICEDIR "\\\\.\\Global\\" +#define SYSDEVICEDIR "\\Device\\" +#define USERDEVICEDIR "\\DosDevices\\Global\\" +#define TAPSUFFIX ".tap" + +#define TAP_COMPONENT_ID "tap0801" + +#endif + +#endif diff --git a/hostCodes/Funcard7/win32/UpgradeLog.XML b/hostCodes/Funcard7/win32/UpgradeLog.XML new file mode 100755 index 0000000000000000000000000000000000000000..85fa6b181601864b1f3cbd5ccd76fefa7054ada8 --- /dev/null +++ b/hostCodes/Funcard7/win32/UpgradeLog.XML @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type='text/xsl' href='_UpgradeReport_Files/UpgradeReport.xslt'?><UpgradeLog> +<Properties><Property Name="Solution" Value="scard"> +</Property><Property Name="Fichier solution" Value="C:\Documents and Settings\pegomas\smews\hostAdapters\Funcard7\win32\scard.sln"> +</Property><Property Name="Date" Value="lundi 15 septembre 2008"> +</Property><Property Name="Time" Value="14:01"> +</Property></Properties><Event ErrorLevel="0" Project="scard" Source="scard.vcproj" Description="Le déploiement Web sur le serveur IIS local IIS n'est plus pris en charge. L'outil de génération Déploiement Web a été supprimé des paramètres de votre projet."> +</Event><Event ErrorLevel="1" Project="scard" Source="scard.vcproj" Description="Cette application a été mise à jour pour inclure les paramètres liés à la fonctionnalité Contrôle de compte d'utilisateur de Windows Vista. Par défaut, lorsqu'elle est exécutée sur Windows Vista avec le Contrôle de compte d'utilisateur activé, cette application est marquée pour s'exécuter avec les mêmes privilèges que le processus qui l'a lancée. Ce marquage empêche l'application de s'exécuter avec la virtualisation. Vous pouvez changer les paramètres du Contrôle de compte d'utilisateur dans les pages de propriétés du projet."> +</Event><Event ErrorLevel="0" Project="scard" Source="scard.vcproj" Description="Mise à niveau du projet terminée."> +</Event><Event ErrorLevel="3" Project="scard" Source="scard.vcproj" Description="Converted"> +</Event><Event ErrorLevel="0" Project="" Source="scard.sln" Description="Solution correctement convertie"> +</Event><Event ErrorLevel="3" Project="" Source="scard.sln" Description="Converted"> +</Event></UpgradeLog> \ No newline at end of file diff --git a/hostCodes/Funcard7/win32/driver/OemWin2k.inf b/hostCodes/Funcard7/win32/driver/OemWin2k.inf new file mode 100755 index 0000000000000000000000000000000000000000..219b4ca9fb6942f228279cecd288f675c9966b71 --- /dev/null +++ b/hostCodes/Funcard7/win32/driver/OemWin2k.inf @@ -0,0 +1,183 @@ +; **************************************************************************** +; * Copyright (C) 2002-2006 OpenVPN Solutions LLC * +; * This program is free software; you can redistribute it and/or modify * +; * it under the terms of the GNU General Public License version 2 * +; * as published by the Free Software Foundation. * +; **************************************************************************** + +; SYNTAX CHECKER +; cd \WINDDK\3790\tools\chkinf +; chkinf c:\src\openvpn\tap-win32\i386\oemwin2k.inf +; OUTPUT -> file:///c:/WINDDK/3790/tools/chkinf/htm/c%23+src+openvpn+tap-win32+i386+__OemWin2k.htm + +; INSTALL/REMOVE DRIVER +; tapinstall install OemWin2k.inf TAP0801 +; tapinstall update OemWin2k.inf TAP0801 +; tapinstall remove TAP0801 + +;********************************************************* +; Note to Developers: +; +; If you are bundling the TAP-Win32 driver with your app, +; you should try to rename it in such a way that it will +; not collide with other instances of TAP-Win32 defined +; by other apps. Multiple versions of the TAP-Win32 +; driver, each installed by different apps, can coexist +; on the same machine if you follow these guidelines: +; +; (1) Rename all tapXXXX instances in this file to +; something different (use at least 5 characters +; for this name!) +; (2) Change the "!define TAP" definition in openvpn.nsi +; to match what you changed tapXXXX to. +; (3) Change TARGETNAME in SOURCES to match what you +; changed tapXXXX to. +; (4) Change TAP_COMPONENT_ID in common.h to match what +; you changed tapXXXX to. +; (5) Change SZDEPENDENCIES in service.h to match what +; you changed tapXXXX to. +; (6) Change DeviceDescription and Provider strings. +; (7) Change PRODUCT_STRING in constants.h to what you +; set DeviceDescription to. +; +;********************************************************* + +[Version] + Signature = "$Windows NT$" + CatalogFile = tap.cat + ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} + Provider = %Provider% + Class = Net + +; This version number should match the version +; number given in SOURCES. + DriverVer=09/13/2006,8.00.00.0004 + +[Strings] + DeviceDescription = "TAP-Win32 Adapter V8" + Provider = "TAP-Win32 Provider" + +;---------------------------------------------------------------- +; Manufacturer + Product Section (Done) +;---------------------------------------------------------------- +[Manufacturer] + %Provider% = tap0801 + +[tap0801] + %DeviceDescription% = tap0801.ndi, tap0801 + +;--------------------------------------------------------------- +; Driver Section (Done) +;--------------------------------------------------------------- + +;----------------- Characteristics ------------ +; NCF_PHYSICAL = 0x04 +; NCF_VIRTUAL = 0x01 +; NCF_SOFTWARE_ENUMERATED = 0x02 +; NCF_HIDDEN = 0x08 +; NCF_NO_SERVICE = 0x10 +; NCF_HAS_UI = 0x80 +;----------------- Characteristics ------------ + +[tap0801.ndi] + CopyFiles = tap0801.driver, tap0801.files + AddReg = tap0801.reg + AddReg = tap0801.params.reg + Characteristics = 0x81 + +[tap0801.ndi.Services] + AddService = tap0801, 2, tap0801.service + +[tap0801.reg] + HKR, Ndi, Service, 0, "tap0801" + HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" + HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" + HKR, , Manufacturer, 0, "%Provider%" + HKR, , ProductName, 0, "%DeviceDescription%" + +[tap0801.params.reg] + HKR, Ndi\params\MTU, ParamDesc, 0, "MTU" + HKR, Ndi\params\MTU, Type, 0, "int" + HKR, Ndi\params\MTU, Default, 0, "1500" + HKR, Ndi\params\MTU, Optional, 0, "0" + HKR, Ndi\params\MTU, Min, 0, "100" + HKR, Ndi\params\MTU, Max, 0, "1500" + HKR, Ndi\params\MTU, Step, 0, "1" + HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status" + HKR, Ndi\params\MediaStatus, Type, 0, "enum" + HKR, Ndi\params\MediaStatus, Default, 0, "0" + HKR, Ndi\params\MediaStatus, Optional, 0, "0" + HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled" + HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected" + HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address" + HKR, Ndi\params\MAC, Type, 0, "edit" + HKR, Ndi\params\MAC, Optional, 0, "1" + HKR, Ndi\params\AllowNonAdmin, ParamDesc, 0, "Non-Admin Access" + HKR, Ndi\params\AllowNonAdmin, Type, 0, "enum" + HKR, Ndi\params\AllowNonAdmin, Default, 0, "1" + HKR, Ndi\params\AllowNonAdmin, Optional, 0, "0" + HKR, Ndi\params\AllowNonAdmin\enum, "0", 0, "Not Allowed" + HKR, Ndi\params\AllowNonAdmin\enum, "1", 0, "Allowed" + +;---------------------------------------------------------------- +; Service Section +;---------------------------------------------------------------- + +;---------- Service Type ------------- +; SERVICE_KERNEL_DRIVER = 0x01 +; SERVICE_WIN32_OWN_PROCESS = 0x10 +;---------- Service Type ------------- + +;---------- Start Mode --------------- +; SERVICE_BOOT_START = 0x0 +; SERVICE_SYSTEM_START = 0x1 +; SERVICE_AUTO_START = 0x2 +; SERVICE_DEMAND_START = 0x3 +; SERVICE_DISABLED = 0x4 +;---------- Start Mode --------------- + +[tap0801.service] + DisplayName = %DeviceDescription% + ServiceType = 1 + StartType = 3 + ErrorControl = 1 + LoadOrderGroup = NDIS + ServiceBinary = %12%\tap0801.sys + +;----------------------------------------------------------------- +; File Installation +;----------------------------------------------------------------- + +;----------------- Copy Flags ------------ +; COPYFLG_NOSKIP = 0x02 +; COPYFLG_NOVERSIONCHECK = 0x04 +;----------------- Copy Flags ------------ + +; SourceDisksNames +; diskid = description[, [tagfile] [, <unused>, subdir]] +; 1 = "Intel Driver Disk 1",e100bex.sys,, + +[SourceDisksNames] + 1 = %DeviceDescription%, tap0801.sys + +; SourceDisksFiles +; filename_on_source = diskID[, [subdir][, size]] +; e100bex.sys = 1,, ; on distribution disk 1 + +[SourceDisksFiles] +tap0801.sys = 1 + +[DestinationDirs] + tap0801.files = 11 + tap0801.driver = 12 + +[tap0801.files] +; TapPanel.cpl,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK +; cipsrvr.exe,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK + +[tap0801.driver] + tap0801.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK + +;--------------------------------------------------------------- +; End +;--------------------------------------------------------------- diff --git a/hostCodes/Funcard7/win32/driver/addtap.bat b/hostCodes/Funcard7/win32/driver/addtap.bat new file mode 100755 index 0000000000000000000000000000000000000000..5a00a6b122547017201deb78c42f4409c6d63679 --- /dev/null +++ b/hostCodes/Funcard7/win32/driver/addtap.bat @@ -0,0 +1,3 @@ +rem Add a new TAP-Win32 virtual ethernet adapter +".\tapinstall.exe" install ".\OemWin2k.inf" tap0801 +pause diff --git a/hostCodes/Funcard7/win32/driver/deltapall.bat b/hostCodes/Funcard7/win32/driver/deltapall.bat new file mode 100755 index 0000000000000000000000000000000000000000..be07c13a4acaf3a050cde87bf5b9487c59e313c5 --- /dev/null +++ b/hostCodes/Funcard7/win32/driver/deltapall.bat @@ -0,0 +1,4 @@ +echo WARNING: this script will delete ALL TAP-Win32 virtual adapters (use the device manager to delete adapters one at a time) +pause +".\tapinstall.exe" remove tap0801 +pause diff --git a/hostCodes/Funcard7/win32/driver/tap0801.sys b/hostCodes/Funcard7/win32/driver/tap0801.sys new file mode 100755 index 0000000000000000000000000000000000000000..170cb4ec360741de98932f8f14dc8681a495dac3 Binary files /dev/null and b/hostCodes/Funcard7/win32/driver/tap0801.sys differ diff --git a/hostCodes/Funcard7/win32/driver/tapinstall.exe b/hostCodes/Funcard7/win32/driver/tapinstall.exe new file mode 100755 index 0000000000000000000000000000000000000000..60aecce5d12ee10edc74b58f556b3ca28a1b6b64 Binary files /dev/null and b/hostCodes/Funcard7/win32/driver/tapinstall.exe differ diff --git a/hostCodes/Funcard7/win32/scard.sln b/hostCodes/Funcard7/win32/scard.sln new file mode 100755 index 0000000000000000000000000000000000000000..ca275c334e36c5cba27b8e400bd4ace39b6899c6 --- /dev/null +++ b/hostCodes/Funcard7/win32/scard.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scard", "scard.vcproj", "{D93F2AED-1AF9-4BAC-AB44-2E94F21C059B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D93F2AED-1AF9-4BAC-AB44-2E94F21C059B}.Debug|Win32.ActiveCfg = Debug|Win32 + {D93F2AED-1AF9-4BAC-AB44-2E94F21C059B}.Debug|Win32.Build.0 = Debug|Win32 + {D93F2AED-1AF9-4BAC-AB44-2E94F21C059B}.Release|Win32.ActiveCfg = Release|Win32 + {D93F2AED-1AF9-4BAC-AB44-2E94F21C059B}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/hostCodes/Funcard7/win32/scard.suo b/hostCodes/Funcard7/win32/scard.suo new file mode 100755 index 0000000000000000000000000000000000000000..c22f7364dd5fbccb1e5106f921fe438c8be99649 Binary files /dev/null and b/hostCodes/Funcard7/win32/scard.suo differ diff --git a/hostCodes/Funcard7/win32/scard.vcproj b/hostCodes/Funcard7/win32/scard.vcproj new file mode 100755 index 0000000000000000000000000000000000000000..2d84a41d0f4a0bf4c72dabae3cf81442b9584b18 --- /dev/null +++ b/hostCodes/Funcard7/win32/scard.vcproj @@ -0,0 +1,250 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="9,00" + Name="scard" + ProjectGUID="{D93F2AED-1AF9-4BAC-AB44-2E94F21C059B}" + RootNamespace="scard" + Keyword="Win32Proj" + TargetFrameworkVersion="131072" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(SolutionDir)$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="1" + CharacterSet="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="winscard.lib" + LinkIncremental="2" + AdditionalLibraryDirectories="C:\_devel\AVR\winscard\scard" + GenerateDebugInformation="true" + SubSystem="1" + RandomizedBaseAddress="1" + DataExecutionPrevention="0" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="$(SolutionDir)$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="1" + CharacterSet="1" + WholeProgramOptimization="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" + RuntimeLibrary="2" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + LinkIncremental="1" + GenerateDebugInformation="true" + SubSystem="1" + OptimizeReferences="2" + EnableCOMDATFolding="2" + RandomizedBaseAddress="1" + DataExecutionPrevention="0" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath="..\apdu.c" + > + </File> + <File + RelativePath="..\scard.c" + > + </File> + <File + RelativePath="..\signal.c" + > + </File> + <File + RelativePath="..\terminal.c" + > + </File> + <File + RelativePath="..\tunnel.c" + > + </File> + <File + RelativePath="..\utils.c" + > + </File> + <Filter + Name="utun" + > + <File + RelativePath="..\utun\utun.c" + > + </File> + <File + RelativePath="..\utun\wintun.c" + > + </File> + </Filter> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath="..\scard.h" + > + </File> + <File + RelativePath=".\winip.h" + > + </File> + <Filter + Name="utun" + > + <File + RelativePath="..\utun\utun.h" + > + </File> + <File + RelativePath="..\utun\wintun.h" + > + </File> + </Filter> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/hostCodes/Funcard7/win32/scard.vcproj.ROCHELLE.pegomas.user b/hostCodes/Funcard7/win32/scard.vcproj.ROCHELLE.pegomas.user new file mode 100755 index 0000000000000000000000000000000000000000..49e59d5e83598f6394b9a1cc68d0773380cd0d5d --- /dev/null +++ b/hostCodes/Funcard7/win32/scard.vcproj.ROCHELLE.pegomas.user @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioUserFile + ProjectType="Visual C++" + Version="9,00" + ShowAllFiles="false" + > + <Configurations> + <Configuration + Name="Debug|Win32" + > + <DebugSettings + Command="$(TargetPath)" + WorkingDirectory="" + CommandArguments="" + Attach="false" + DebuggerType="3" + Remote="1" + RemoteMachine="ROCHELLE" + RemoteCommand="" + HttpUrl="" + PDBPath="" + SQLDebugging="" + Environment="" + EnvironmentMerge="true" + DebuggerFlavor="" + MPIRunCommand="" + MPIRunArguments="" + MPIRunWorkingDirectory="" + ApplicationCommand="" + ApplicationArguments="" + ShimCommand="" + MPIAcceptMode="" + MPIAcceptFilter="" + /> + </Configuration> + <Configuration + Name="Release|Win32" + > + <DebugSettings + Command="$(TargetPath)" + WorkingDirectory="" + CommandArguments="" + Attach="false" + DebuggerType="3" + Remote="1" + RemoteMachine="ROCHELLE" + RemoteCommand="" + HttpUrl="" + PDBPath="" + SQLDebugging="" + Environment="" + EnvironmentMerge="true" + DebuggerFlavor="" + MPIRunCommand="" + MPIRunArguments="" + MPIRunWorkingDirectory="" + ApplicationCommand="" + ApplicationArguments="" + ShimCommand="" + MPIAcceptMode="" + MPIAcceptFilter="" + /> + </Configuration> + </Configurations> +</VisualStudioUserFile> diff --git a/hostCodes/Funcard7/win32/winip.h b/hostCodes/Funcard7/win32/winip.h new file mode 100755 index 0000000000000000000000000000000000000000..f984710b97ab819a16e5a4bae0bff162fb8d5f83 --- /dev/null +++ b/hostCodes/Funcard7/win32/winip.h @@ -0,0 +1,42 @@ + +#ifdef WIN32 + +#ifndef WIN32_NET_STRUCT +#define WIN32_NET_STRUCT + +typedef unsigned int u_int32_t; +typedef unsigned short u_int16_t; +typedef unsigned char u_int8_t; +typedef int int32_t; +typedef short int16_t; +typedef char int8_t; + +#define socklen_t int + +/* ************************************* */ + +struct iphdr { +#if BYTE_ORDER == LITTLE_ENDIAN + u_char ihl:4, /* header length */ + version:4; /* version */ +#else + u_char version:4, /* version */ + ihl:4; /* header length */ +#endif + u_char tos; /* type of service */ + short tot_len; /* total length */ + u_short id; /* identification */ + short frag_off; /* fragment offset field */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u_char ttl; /* time to live */ + u_char protocol; /* protocol */ + u_short check; /* checksum */ + u_int32_t saddr,daddr; /* source and dest address */ +}; + +#endif + +#endif + diff --git a/hostCodes/Funcard7/win32/winscard.lib b/hostCodes/Funcard7/win32/winscard.lib new file mode 100755 index 0000000000000000000000000000000000000000..b5d946a5653caab2094e61f01a526854d2dd7327 Binary files /dev/null and b/hostCodes/Funcard7/win32/winscard.lib differ diff --git a/hostCodes/benchmarker/autobench.py b/hostCodes/benchmarker/autobench.py new file mode 100644 index 0000000000000000000000000000000000000000..aaf574c4f2a7d07ebfee642fa18a96120197cf83 --- /dev/null +++ b/hostCodes/benchmarker/autobench.py @@ -0,0 +1,114 @@ +import sys +import os +import socket +import time +import signal +from subprocess import * +from datetime import datetime +from datetime import timedelta +import thread +import random +import benchTools + +def ratio(a,b): + return round(a / float(b),2) if b > 0 else 0 + +def printResults(trafficBytes,trafficPackets): + toWait = benchTools.toWait + statsMap = benchTools.statsMap + nClients = benchTools.nClients + firstReceiveTime = benchTools.firstReceiveTime + lattestUnconsistentTime = benchTools.lattestUnconsistentTime + nPublish = benchTools.nPublish + cptClients = 0 + keys = statsMap.keys() + keys.sort() + ptSum = 0 + ctSum = 0 + rpmSum = 0 + rpmuSum = 0 + rpmPercentSum = 0 + rpmuPercentSum = 0 + for key in keys: + ctSum += statsMap[key]['tct'] + ptSum += statsMap[key]['tpt'] + rpmSum += statsMap[key]['rpm'] + rpmuSum += statsMap[key]['rpmu'] + if int(100*ratio(rpmuSum,nPublish * nClients)) == 0: + print 'error: rupm == 0' + else: + print 'Results: %d %d %d %d %.1f %.1f %.1f' %(ratio(ctSum,nPublish * nClients), ratio(ptSum,rpmuSum),100*ratio(rpmSum,nPublish * nClients),100*ratio(rpmuSum,nPublish * nClients),trafficBytes,trafficPackets,100*ratio(ctSum,nClients*benchTools.timeDeltaToMillis(lattestUnconsistentTime-firstReceiveTime))) + +def main(): + if len(sys.argv) != 4: + print 'Usage: ' + sys.argv[0] + ' nClients pollInterval pubInterval' + exit(1) + + dstIP = 'www.wsn430.pan' + nClients = int(sys.argv[1]) + pollInterval = float(sys.argv[2]) + pubInterval = float(sys.argv[3]) + + print "Configuration %d %d %d" %(nClients, pollInterval, pubInterval) + print "Timestamp %s" %datetime.now() + + if pollInterval == 0: + if pubInterval == 0: + dstURL = '/time/cometRand' + else: + dstURL = '/time/comet%ds' %pubInterval + elif pollInterval == -1: + if pubInterval == 0: + dstURL = '/time/lpRand' + else: + dstURL = '/time/lp%ds' %pubInterval + else: + if pubInterval == 0: + dstURL = '/time/timeRand' + else: + dstURL = '/time/time' + + benchTools.start(dstIP,dstURL,nClients,pollInterval,pubInterval) + + if pubInterval == 0: + timeout = int(200) + else: + timeout = int(50 + max(3*max(pubInterval,pollInterval),nClients/2)) + print 'Timeout: %d' %timeout + maxInitTimer = datetime.now() + timedelta(seconds = timeout) + while benchTools.toWait > 0 or benchTools.firstReceiveTime == None: + if datetime.now() > maxInitTimer: + print 'init error' + sys.exit(1) + else: + time.sleep(1) + + if pubInterval == 0: + timeToSleep = 500 + else: + elapsed = benchTools.timeDeltaToMillis(datetime.now() - benchTools.firstReceiveTime) / 1000. + basicWait = max(150,5 * pubInterval) + timeToSleep = basicWait + (pubInterval - elapsed % pubInterval - 2) + + os.system('cat /proc/net/dev | grep sl0 > .net_stats') + devStats = filter(lambda c: c != '',open('.net_stats', 'r').readline().split(' ')) + trafficBytes1 = int(devStats[1]) + int(devStats[9]) + trafficPackets1 = int(devStats[2]) + int(devStats[10]) + + startTime = datetime.now() + + print 'Sleep %d' %timeToSleep + time.sleep(timeToSleep) + + endTime = datetime.now() + deltaTimeSec = benchTools.timeDeltaToMillis(endTime - startTime) / 1000. + + os.system('cat /proc/net/dev | grep sl0 > .net_stats') + devStats = filter(lambda c: c != '',open('.net_stats', 'r').readline().split(' ')) + os.remove('.net_stats') + trafficBytes2 = int(devStats[1]) + int(devStats[9]) + trafficPackets2 = int(devStats[2]) + int(devStats[10]) + + printResults((trafficBytes2 - trafficBytes1) / float(deltaTimeSec),(trafficPackets2 - trafficPackets1) / float(deltaTimeSec)) + +main() diff --git a/hostCodes/benchmarker/bench.py b/hostCodes/benchmarker/bench.py new file mode 100644 index 0000000000000000000000000000000000000000..2c0e84daf52d78032a3bb820a659330fe9b6f336 --- /dev/null +++ b/hostCodes/benchmarker/bench.py @@ -0,0 +1,121 @@ +import sys +import os +import socket +import time +import signal +from datetime import datetime +from datetime import timedelta +import thread +import random +import benchTools + +def ratio(a,b): + return round(a / float(b),2) if b > 0 else 0 + +def alarm_handler(signo,frame): + global trafficBytes1,trafficPackets1,startTime + toWait = benchTools.toWait + statsMap = benchTools.statsMap + nClients = benchTools.nClients + firstReceiveTime = benchTools.firstReceiveTime + lattestUnconsistentTime = benchTools.lattestUnconsistentTime + nPublish = benchTools.nPublish + if toWait > 0: + print 'Waiting %d...' %toWait + elif firstReceiveTime == None: + print 'Waiting for a first synchronized publication' + else: + endTime = datetime.now() + deltaTimeSec = benchTools.timeDeltaToMillis(endTime - startTime) / 1000. + os.system('cat /proc/net/dev | grep sl0 > .net_stats') + devStats = filter(lambda c: c != '',open('.net_stats', 'r').readline().split(' ')) + os.remove('.net_stats') + trafficBytes2 = int(devStats[1]) + int(devStats[9]) + trafficPackets2 = int(devStats[2]) + int(devStats[10]) + trafficBytes = (trafficBytes2 - trafficBytes1) / float(deltaTimeSec) + trafficPackets = (trafficPackets2 - trafficPackets1) / float(deltaTimeSec) + + cptClients = 0 + print '----------------------------------' + print 'id, port, mct, mpt, rpm, rpmu' + keys = statsMap.keys() + keys.sort() + ptSum = 0 + ctSum = 0 + rpmSum = 0 + rpmuSum = 0 + rpmPercentSum = 0 + rpmuPercentSum = 0 + for key in keys: + ctSum += statsMap[key]['tct'] + ptSum += statsMap[key]['tpt'] + rpmSum += statsMap[key]['rpm'] + rpmuSum += statsMap[key]['rpmu'] + mct = ratio(statsMap[key]['tct'], nPublish) + mpt = ratio(statsMap[key]['tpt'], statsMap[key]['rpmu']) + rpmPercent = 100*ratio(statsMap[key]['rpm'], nPublish) + rpmuPercent = 100*ratio(statsMap[key]['rpmu'], nPublish) + try: + port = statsMap[key]['sock'].getsockname()[1] + except: + port = 0 + print '[%d, %d], %d, %d, %d, %d, %d%%, %d%%' %(key,port,mct,mpt,statsMap[key]['rpm'],statsMap[key]['rpmu'],rpmPercent,rpmuPercent) + print 'id, mct, mpt, rpm, rpmu, nPublish (%d)' %(benchTools.timeDeltaToMillis(datetime.now() - firstReceiveTime) / 1000.) + print '--- mct, mpt, rpm, rpmu, nPublish, rpm%, rpmu%, ntb, ntp, ct%' + print '[AVG] %d, %d, %d, %d, %d, %d%%, %d%%, %.1f, %.1f, %d%%' %(ratio(ctSum,nPublish * nClients), ratio(ptSum,rpmuSum),ratio(rpmSum,nClients),ratio(rpmuSum,nClients),nPublish,100*ratio(rpmSum,nPublish * nClients),100*ratio(rpmuSum,nPublish * nClients),trafficBytes,trafficPackets,100*ratio(ctSum,nClients*benchTools.timeDeltaToMillis(lattestUnconsistentTime-firstReceiveTime))) + + signal.alarm(2) + +def main(): + global trafficBytes1,trafficPackets1,startTime + if len(sys.argv) != 4: + print 'Usage: ' + sys.argv[0] + ' nClients pollInterval pubInterval' + exit(1) + + dstIP = 'www.wsn430.pan' + nClients = int(sys.argv[1]) + pollInterval = float(sys.argv[2]) + pubInterval = float(sys.argv[3]) + + if pollInterval == 0: + if pubInterval == 0: + dstURL = '/time/cometRand' + else: + dstURL = '/time/comet%ds' %pubInterval + elif pollInterval == -1: + if pubInterval == 0: + dstURL = '/time/lpRand' + else: + dstURL = '/time/lp%ds' %pubInterval + else: + if pubInterval == 0: + dstURL = '/time/timeRand' + else: + dstURL = '/time/time' + + print 'Number of clients: %d' % nClients + if pollInterval == 0: + print 'Comet mode' + elif pollInterval == -1: + print 'Long polling mode' + else: + print 'Polling interval: %.3f seconds' % pollInterval + if pubInterval == 0: + print 'Publish interval: random' + else: + print 'Publish interval: %.3f seconds' % pubInterval + + os.system('cat /proc/net/dev | grep sl0 > .net_stats') + devStats = filter(lambda c: c != '',open('.net_stats', 'r').readline().split(' ')) + trafficBytes1 = int(devStats[1]) + int(devStats[9]) + trafficPackets1 = int(devStats[2]) + int(devStats[10]) + startTime = datetime.now() + + benchTools.start(dstIP,dstURL,nClients,pollInterval,pubInterval) + + signal.signal(signal.SIGALRM, alarm_handler) + signal.alarm(2) + while 1: + time.sleep(1) + +main() diff --git a/hostCodes/benchmarker/benchTools.py b/hostCodes/benchmarker/benchTools.py new file mode 100644 index 0000000000000000000000000000000000000000..5da391ef8acbc7a6e9958b793e81185a0591766f --- /dev/null +++ b/hostCodes/benchmarker/benchTools.py @@ -0,0 +1,190 @@ +import sys +import socket +import time +import signal +from datetime import datetime +from datetime import timedelta +import thread +import random + +dstIP = None +pubInterval = None +pollInterval = None +httpRequest = None +timeSync = None +firstPublishId = None +nPublish = 0 +toWait = None +firstReceiveTime = None +lattestUnconsistentTime = datetime.now() + +statsMap = {} + +def timeDeltaToMillis(time): + return time.days * 24 * 3600 * 1000 + time.seconds * 1000 + time.microseconds / 1000. + +initTime = datetime.now() +def millisToTime(time): + return initTime + timedelta(seconds = time / 1000,microseconds = (1000 * time) % 1000000) + +def doConnect(stat,dstIP,port): + global pubInterval + connected = False + while connected == False: + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(30) + sock.connect((dstIP, port)) + if pubInterval == 0: + sock.settimeout(100) + else: + sock.settimeout(max(2 * pubInterval,30)) + connected = True + stat['sock'] = sock + except: + time.sleep(4) + +def doSyncRequest(stat,httpRequest): + while True: + try: + stat['sock'].send(httpRequest) + ret = stat['sock'].recv(1024).split('\n') + return int(ret[4]) + except: + stat['sock'].close() + time.sleep(4) + doConnect(stat,dstIP,80) + +def doPullRequest(stat,httpRequest): + while True: + try: + stat['sock'].send(httpRequest) + ret = stat['sock'].recv(1024).split('\n') + if pubInterval > 0: + publishId = int(int(ret[4]) / pubInterval) + return (int(publishId * pubInterval),publishId,pubInterval) + else: + return (int(ret[4]),int(ret[5]),int(ret[6])*1000) + except: + stat['sock'].close() + time.sleep(4) + doConnect(stat,dstIP,80) + +def doPushRequest1(stat,httpRequest): + while True: + try: + stat['sock'].send(httpRequest) + return + except: + stat['sock'].close() + time.sleep(4) + doConnect(stat,dstIP,80) + +def doPushRequest2(stat,httpRequest): + while True: + try: + ret = stat['sock'].recv(1024).split('\n') + if pubInterval > 0: + if len(ret) == 3: + return (int(ret[1]),int(int(ret[1]) / pubInterval),pubInterval) + else: + return (int(ret[5]),int(int(ret[5]) / pubInterval),pubInterval) + else: + if len(ret) == 5: + return (int(ret[1]),int(ret[2]),int(ret[3])*1000) + else: + return (int(ret[5]),int(ret[6]),int(ret[7])*1000) + except: + doPushRequest1(stat,httpRequest) + +def clientFunc(id): + global statsMap, timeSync, firstPublishId, nPublish, toWait, firstReceiveTime, lattestUnconsistentTime + + if id != 0: + while timeSync == None: + pass + time.sleep(random.random() * nClients * 0.01) + + statsMap[id] = {'sock': None, 'rpm': 0, 'rpmu': 0, 'tpt': 0, 'tct': 0} + doConnect(statsMap[id],dstIP,80) + + if id == 0: + tmpTimeSync = None + for i in range(16): + rep = doSyncRequest(statsMap[id],'GET /time/time HTTP/1.1\r\nUser-Agent: custom\r\nHost: localhost\r\n\r\n ') + timeAfter = datetime.now() + repTime = millisToTime(rep) + if tmpTimeSync == None or tmpTimeSync > timeAfter - repTime: + tmpTimeSync = timeAfter - repTime + timeSync = tmpTimeSync + + time.sleep(random.random() * nClients * 0.01 + random.random() * pollInterval) + + publishId = -1 + totalPubTripTime = 0 + totalConsistentTime = 0 + isActive = False + + if isComet: + doPushRequest1(statsMap[id],httpRequest) + + while True: + timeBefore = datetime.now() + if isComet: + rep = doPushRequest2(statsMap[id],httpRequest) + else: + rep = doPullRequest(statsMap[id],httpRequest) + timeAfter = datetime.now() + if not isActive: + isActive = True + toWait -= 1 + lastPublishId = publishId + (published,publishId,nextPubDelay) = rep + if toWait == 0 and firstPublishId != None and publishId >= firstPublishId: + if publishId > lastPublishId: + if firstReceiveTime == None: + firstReceiveTime = timeAfter + lattestUnconsistentTime = max(lattestUnconsistentTime,millisToTime(published)+timeSync+timedelta(microseconds = 1000 * nextPubDelay)) + pubTripTime = timeDeltaToMillis((timeAfter - timeSync) - millisToTime(published)) + totalPubTripTime += pubTripTime + consistentTime = max(0,nextPubDelay - pubTripTime) + totalConsistentTime += consistentTime + statsMap[id]['rpmu'] += 1 + statsMap[id]['tpt'] = totalPubTripTime + statsMap[id]['tct'] = totalConsistentTime + nPublish = max(nPublish,publishId - firstPublishId + 1) + statsMap[id]['rpm'] += 1 + elif firstReceiveTime == None: + firstPublishId = max(firstPublishId,publishId + 1) + if isComet: + pass + elif isLp: + if pubInterval == 1000: + time.sleep(0.1 + random.random() * nClients * 0.01) + else: + time.sleep(0.1 + random.random() * nClients * 0.03) + else: + randPart = 0.1 * (0.5 - random.random()) * pollInterval + delta = datetime.now() - timeBefore + deltaSec = timeDeltaToMillis(delta) / 1000. + timeToSleep = pollInterval - (deltaSec % pollInterval) + randPart + time.sleep(max(0,timeToSleep)) + +def start(argDstIP,argDstURL,argNClients,argPollInterval,argPubInterval): + global dstIP,dstURL,nClients,pollInterval,pubInterval,isComet,isLp,toWait,httpRequest + dstIP = argDstIP + dstURL = argDstURL + nClients = argNClients + pollInterval = argPollInterval + pubInterval = int(argPubInterval * 1000) + isComet = pollInterval == 0 + isLp = pollInterval == -1 + pollInterval = max(0,pollInterval) + + httpRequest = 'GET ' + dstURL + ' HTTP/1.1\r\nUser-Agent: custom\r\nHost: localhost ' + for i in range(450): + httpRequest += '.' + httpRequest += '\r\n\r\n' + toWait = nClients + for i in range(nClients): + thread.start_new_thread(clientFunc,(i,)) diff --git a/hostCodes/benchmarker/makePlots.py b/hostCodes/benchmarker/makePlots.py new file mode 100644 index 0000000000000000000000000000000000000000..2defa0b0ce9b26c01765bff38e3051f9ca7851a4 --- /dev/null +++ b/hostCodes/benchmarker/makePlots.py @@ -0,0 +1,209 @@ +import os +import sys +import os.path +import time +import shutil +import random +from datetime import datetime + +def ratio(a,b): + return round(a / float(b),2) if b > 0 else 0 + +nWarnings = 0 + +class StatsSet: + def __init__(self): + self.statshash = {} + for id in ['mct','mpt','rpm','rupm','ntb','ntp']: + self.statshash[id] = Stat() + + def addResults(self,resFile,results): + global nWarnings + for id in ['mct','mpt','rpm','rupm','ntb','ntp']: + if results[id] <= 0: + if id == 'mpt': + print 'Warning: %s is %d in %s [corrected]' %(id,results[id],resFile) + results[id] = 0 + nWarnings+=1 + else: + print 'Warning: %s is %d in %s' %(id,results[id],resFile) + nWarnings+=1 + elif id in ['mct','rupm'] and results[id] > 100: + print 'Warning: %s is %d in %s [corrected]' %(id,results[id],resFile) + results[id] = 100 + nWarnings+=1 + for id in ['mct','mpt','rpm','rupm','ntb','ntp']: + self.statshash[id].addVal(results[id]) + + def getCount(self): + return self.statshash['mct'].getCount() + + def getMin(self,id): + return self.statshash[id].getMin() + + def getMax(self,id): + return self.statshash[id].getMax() + + def getAvg(self,id): + avg = self.statshash[id].getAvg() + if avg == None: + return None + if id in ['mpt']: + return avg / 1000. + elif id == 'ntb': + return avg / 1024. + else: + return avg + + def removeMin(self): + minRupmIdx = self.statshash['rupm'].getMinIdx() + for id in ['mct','mpt','rpm','rupm','ntb','ntp']: + self.statshash[id].removeIndex(minRupmIdx) + + def removeMax(self): + maxRupmIdx = self.statshash['rupm'].getMaxIdx() + for id in ['mct','mpt','rpm','rupm','ntb','ntp']: + self.statshash[id].removeIndex(maxRupmIdx) + +class Stat: + def __init__(self): + self.vals = [] + + def removeIndex(self,idx): + try: + self.vals.pop(idx) + except: + pass + + def addVal(self,val): + self.vals.append(val) + + def getCount(self): + return len(self.vals) + + def getAvg(self): + if len(self.vals) == 0: + return None + else: + sum = 0 + for val in self.vals: + sum += val + return float(sum) / len(self.vals) + + def getMinIdx(self): + if len(self.vals) == 0: + return None + minIdx = 0 + for i in range(len(self.vals)): + if self.vals[i] < self.vals[minIdx]: + minIdx = i + return minIdx + + def getMaxIdx(self): + if len(self.vals) == 0: + return None + maxIdx = 0 + for i in range(len(self.vals)): + if self.vals[i] > self.vals[maxIdx]: + maxIdx = i + return maxIdx + + def getMin(self): + try: + return self.vals[self.getMinIdx()] + except: + return 0 + + def getMax(self): + try: + return self.vals[self.getMaxIdx()] + except: + return 0 + +maxBenchs = 10 +nClientsSet = [1,16,32,64,128,255] +pubIntervalSet = [1,5,15,30,50,0] +pollIntervalSet = [-1,0,1,5,15,30,50] + +minCptBenhs = 999 +benchsProcessed = 0 +startTime = datetime.now() +resDir = sys.argv[1] +if not os.path.exists('plots'): + os.mkdir('plots') +globalStats = {} +for nClients in nClientsSet: + globalStats[nClients] = {} + nClientsDirName = './%s/%d' %(resDir,nClients) + + for pubInterval in pubIntervalSet: + globalStats[nClients][pubInterval] = {} + pubDirName = './%s/%d/%d' %(resDir,nClients,pubInterval) + + for pollInterval in pollIntervalSet: + stats = StatsSet() + cptBenchs = 0 + #while True: + for cptBenchs in range(maxBenchs+1): + if pollInterval == 0: + resFile = './%s/%d/%d/comet_#%d' %(resDir,nClients, pubInterval, cptBenchs) + elif pollInterval == -1: + resFile = './%s/%d/%d/lp_#%d' %(resDir,nClients, pubInterval, cptBenchs) + else: + resFile = './%s/%d/%d/pull%d_#%d' %(resDir,nClients, pubInterval, pollInterval, cptBenchs) + if os.path.exists(resFile): + res_file = open(resFile, 'r') + results = res_file.readlines() + results = results[len(results)-1].strip().split(' ') + if pubInterval == 0: + mct = float(results[7]) + else: + mct = 100 * ratio(int(results[1]),1000*pubInterval) + stats.addResults(resFile,{'mct': int(mct), 'mpt': int(results[2]), 'rpm': int(results[3]), 'rupm': int(results[4]), 'ntb': int(float(results[5])), 'ntp': float(results[6])}) + #cptBenchs += 1 + benchsProcessed += 1 + else: + minCptBenhs = min(minCptBenhs,cptBenchs) + #break + globalStats[nClients][pubInterval][pollInterval] = stats + +for pubInterval in pubIntervalSet: + for nClients in nClientsSet: + for pollInterval in pollIntervalSet: + count = globalStats[nClients][pubInterval][pollInterval].getCount() + if count >= 5: + globalStats[nClients][pubInterval][pollInterval].removeMin() + globalStats[nClients][pubInterval][pollInterval].removeMax() + if count >= 7: + globalStats[nClients][pubInterval][pollInterval].removeMin() + globalStats[nClients][pubInterval][pollInterval].removeMax() + sMin = globalStats[nClients][pubInterval][pollInterval].getMin('rupm') + sMax = globalStats[nClients][pubInterval][pollInterval].getMax('rupm') + if sMin != None: + if sMin < 0: + print 'Warning for %s of %d %d %d: %d' %('rupm',nClients,pubInterval,pollInterval,sMin) + nWarnings+=1 + elif (sMin == 0 or sMax/float(sMin) > 1.05) and sMax - sMin >= 5: + print 'Warning for %s of %d %d %d: from %d to %d' %('rupm',nClients,pubInterval,pollInterval,sMin,sMax) + nWarnings+=1 + +for statName in ['mct','mpt','rpm','rupm','ntb','ntp']: + for pubInterval in pubIntervalSet: + file = open('plots/%s_%d'%(statName,pubInterval),'w') + file.write('nclients\tlp\tcomet\tpull1\tpull5\tpull15\tpull30\tpull50\n') + file.write('# nClients: ') + for i in range(len(nClientsSet)): + file.write('%d -> %d, ' %(i,nClientsSet[i])) + file.write('\n') + for i in range(len(nClientsSet)): + tmpstr = '%d' %(i) + nClients = nClientsSet[i] + for pollInterval in pollIntervalSet: + statVal = globalStats[nClients][pubInterval][pollInterval].getAvg(statName) + tmpstr += '\t%f' %(statVal if statVal != None else 0) + file.write(tmpstr + '\n') + +if nWarnings > 0: + print '#warnings: %d' %nWarnings +print '#full iterations: %d' %minCptBenhs +print '#benchs processed: %d' %benchsProcessed diff --git a/hostCodes/benchmarker/multiBench.py b/hostCodes/benchmarker/multiBench.py new file mode 100644 index 0000000000000000000000000000000000000000..e8d55be6333b5eaebbd44397d53272bb5e803cec --- /dev/null +++ b/hostCodes/benchmarker/multiBench.py @@ -0,0 +1,95 @@ +import os +import sys +import os.path +import time +import shutil +import random +from datetime import datetime + +startTime = datetime.now() + +if len(sys.argv) == 2: + resDir = sys.argv[1] +else: + resDir = './results/' + resDir += str(startTime).split('.')[0].replace(' ','_') + os.system('svn log --revision HEAD | grep "line" | head -n 1 | cut -d "r" -f2 | cut -d " " -f 1 > .svn_rev') + rev_file = open('.svn_rev', 'r') + resDir += '_rev' + rev_file.readline().strip() + os.remove('.svn_rev') + os.mkdir(resDir) + +cptBenchs = 0 + +nClientsSet = [1,16,32,64,128,255] +pubIntervalSet = [1,5,15,30,50,0] +pollIntervalSet = [-1,0,1,5,15,30,50] + +while True: + print '--> Iteration: %d' %cptBenchs + for nClients in nClientsSet: + #isFlashed = False + print '--> nClients: %d' %nClients + + nClientsDirName = './%s/%d' %(resDir,nClients) + if not os.path.exists(nClientsDirName): + os.mkdir(nClientsDirName) + + for pubInterval in pubIntervalSet: + if pubInterval == 0: + print '--> pubInterval: random' + else: + print '--> pubInterval: %d' %pubInterval + pubDirName = './%s/%d/%d' %(resDir,nClients,pubInterval) + if not os.path.exists(pubDirName): + os.mkdir(pubDirName) + + for pollInterval in pollIntervalSet: + if pollInterval == 0: + print '--> Comet' + elif pollInterval == -1: + print '--> Long polling' + else: + print '--> Pull %d' %pollInterval + + if pollInterval == 0: + dstFile = './%s/%d/%d/comet_#%d' %(resDir,nClients, pubInterval, cptBenchs) + elif pollInterval == -1: + dstFile = './%s/%d/%d/lp_#%d' %(resDir,nClients, pubInterval, cptBenchs) + else: + dstFile = './%s/%d/%d/pull%d_#%d' %(resDir,nClients, pubInterval, pollInterval, cptBenchs) + + if os.path.exists(dstFile): + print 'The file %s already exists' %dstFile + else: + #if not isFlashed: + #print('Flashing Smews...') + #os.system('sudo msp430-jtag -e ./smewsBins/smews%d.elf 2> /dev/null > /dev/null' %nClients) + #isFlashed = True + print 'The file %s does not exist' %dstFile + cmdArgs = '%d %d %d' %(nClients, pollInterval, pubInterval) + cptErrors = 0 + while cptErrors < 9: + os.system('sudo /home/pegomas/myScripts/unConfigSlip 2> /dev/null > /dev/null') + time.sleep(1) + os.system('sudo /home/pegomas/myScripts/configSlip 2> /dev/null > /dev/null') + os.system('sudo msp430-jtag 2> /dev/null > /dev/null') + + print "Starting bench %d %d %d #%d (%s)" %(nClients, pollInterval, pubInterval, cptBenchs,str(datetime.now())) + time.sleep(25) + os.system('python ./autobench.py %s > .bench_result' %cmdArgs); + time.sleep(2) + result_file = open('.bench_result', 'r') + result = result_file.readlines() + if result[len(result)-1].startswith('Results:'): + print "Bench OK" + break + else: + print "An error occured" + cptErrors += 1 + result_file = open(dstFile, 'w') + result.insert(0,'Iteration: %d\n'%cptErrors) + result_file.writelines(result) + result_file.close() + os.remove('.bench_result') + cptBenchs += 1 diff --git a/hostCodes/gmScripts/calendar.user.js b/hostCodes/gmScripts/calendar.user.js new file mode 100644 index 0000000000000000000000000000000000000000..9f06c6ca5b4f1b15f949011a00e5cb3423ea9e5d --- /dev/null +++ b/hostCodes/gmScripts/calendar.user.js @@ -0,0 +1,116 @@ +// ==UserScript== +// @name Hello World +// @namespace http://diveintogreasemonkey.org/download/ +// @description example script to alert "Hello world!" on every page +// @include http://www.google.com/calendar/* +// ==/UserScript== + +unsafeWindow.createCallBack = createCallBack; +unsafeWindow.delCallBack = delCallBack; +unsafeWindow.parseBoxes = parseBoxes; + +var events = []; +var freeIds = []; +var form = null; +var del = null; + +function updateCallBack() { +} + +function plop(newId) { + ajaxGet("http://www.funcard7.pan/calendar/cal_add?id=" + newId + "&field=" + escape(events[newId]),updateCallBack); +} + +function delCallBack() { + var str = document.getElementById("mtb").innerHTML; + var newId = parseInt(str.slice(18 + str.indexOf("<i>"))); + if(!isNaN(newId)) { + events[newId] = ""; + freeIds.push(newId); + setTimeout(plop,0,newId); + } +} + +function createCallBack() { + dragEvent = document.getElementById("dragEventSubject"); + var newId; + if(freeIds.length > 0) { + newId = freeIds.pop(); + } else { + newId = events.length; + } + events[newId] = dragEvent.value; + dragEvent.value = "private event #" + newId; + setTimeout(plop,0,newId); +} + +function parseBoxes() { + if(!document.getElementById("create_event_btn_private")) { + var submitB = document.getElementById("create_event_btn"); + if(submitB) { + submitB.value = "Private event"; + submitB.id = "create_event_btn_private"; + var submitB2 = submitB.cloneNode(true); + submitB2.value = "Public event"; + submitB.parentNode.insertBefore(submitB2,submitB); + submitB.setAttribute("onclick","createCallBack();"); +// document.getElementById("event_details_btn").innerHTML = "modifier les détails"; + } + var sList = document.getElementsByTagName("span"); + if(sList.length>0) { + for (var i in sList) { + if(sList[i].innerHTML == "<button>Delete</button>") { + if(del != sList[i]) { + del = sList[i]; + sList[i].setAttribute("onclick","delCallBack();" + sList[i].getAttribute("onclick")); + } + } + } + } + } +} + +function parseBody() { + setTimeout(parseBody,400); + var keyWords = ["nobr","div","span","a"]; + var sep = ["<br/>"," - ","<br/>"," - "]; + for (keyWord in keyWords) { + var brList = document.getElementsByTagName(keyWords[keyWord]); + for (var i in brList) { + if(brList[i] && brList[i].innerHTML.slice(0,15) == "private event #") { + var id = brList[i].innerHTML.slice(15); + if(freeIds.indexOf(id) == -1 && id < events.length) + brList[i].innerHTML = events[id] + sep[keyWord] + "<i>private event #" + id + "</i>"; + } + } + } + parseBoxes(); +} + +function getEvents(responseDetails) { + if(responseDetails.status == 200) { + events = eval('(' + responseDetails.responseText + ')'); + freeIds = new Array(); + for(i in events) { + if(events[i] == "") + freeIds.push(i); + events[i] = unescape(events[i]); + } + } +} + +function ajaxGet(rqtUrl,ajaxCallBack) { + GM_xmlhttpRequest({ + method: "GET", + url: rqtUrl, + headers: { + "User-agent": "Firefox/3.0", + }, + onload: ajaxCallBack, + }); +} + +var form = null; +document.body.setAttribute("onclick","parseBoxes();"); +parseBody(); +ajaxGet("http://www.funcard7.pan/calendar/cal_get",getEvents); diff --git a/hostCodes/gmScripts/config.xml b/hostCodes/gmScripts/config.xml new file mode 100755 index 0000000000000000000000000000000000000000..01b4f6f4bf4a0b16f8e24223367dd78efc1a74b7 --- /dev/null +++ b/hostCodes/gmScripts/config.xml @@ -0,0 +1,12 @@ +<UserScriptConfig> + <Script filename="contactsBook.user.js" name="contactsBook" namespace="smews" description="" enabled="true" basedir="."> + <Include>*</Include> + <Exclude>http://www2.lifl.fr/~duquenno/gmap.php*</Exclude> + <Exclude>http://192.168.1.6/*</Exclude> + <Exclude>http://www.google.com/calendar/*</Exclude> + <Exclude>http://maps.google.fr</Exclude> + </Script> + <Script filename="calendar.user.js" name="calendar" namespace="smews" description="" enabled="true" basedir="."> + <Include>http://www.google.com/calendar/*</Include> + </Script> +</UserScriptConfig> diff --git a/hostCodes/gmScripts/contactsBook.user.js b/hostCodes/gmScripts/contactsBook.user.js new file mode 100644 index 0000000000000000000000000000000000000000..c0363dd5c1e5da5a54bf488a42c3618c0ffd0916 --- /dev/null +++ b/hostCodes/gmScripts/contactsBook.user.js @@ -0,0 +1,132 @@ +// ==UserScript== +// @name demo +// @namespace http://diveintogreasemonkey.org/download/ +// @include http://www2.lifl.fr/POPS/Eng/People/* +// ==/UserScript== + +var contactsHash = null; +var contactsBook = null; +var smewsContact; +var mouseX; +var mouseY; +var currentContact = null; +var timeout = null; + +unsafeWindow.timeout = timeout; +unsafeWindow.moveMouse = moveMouse; +unsafeWindow.showInfos = showInfos; +unsafeWindow.hideInfos = hideInfos; + +function moveMouse(e) { + mouseX = e.pageX; + mouseY = e.pageY; +} + +function parseBody() { + var bodyList = document.getElementsByTagName("body"); + if(bodyList.length > 0) { + var body = bodyList[0]; + var regStr = ""; + for (i in contactsBook) { + regStr += "|" + contactsBook[i].name + ""; + } + var reg=new RegExp("([^\"])(" + regStr.slice(1) + ")([^\"])", "gi"); + if(regStr != "") { + body.innerHTML = body.innerHTML.replace(reg,"$1$2<span style='font-size: 14pt;color:#F62' onmouseover='clearTimeout(timeout);timeout=null;showInfos(\"$2\")' onmouseout='if(!timeout) timeout = setTimeout(\"hideInfos()\",100);'> <img src=\"http://www.funcard7.pan/contactsBook/sc.png\" alt=\"*\"/></span>$3"); + } + smewsContact = document.createElement("div"); + smewsContact.id = "SmewsContact"; + smewsContact.style.position = "absolute"; + smewsContact.style.backgroundColor = "#dde"; + smewsContact.style.padding = "6px"; + smewsContact.style.visibility = "hidden"; + smewsContact.style.border = "2px solid black"; + smewsContact.setAttribute("onMouseOut","if(!timeout) timeout = setTimeout('hideInfos()',200);"); + smewsContact.setAttribute("onMouseOver","clearTimeout(timeout);timeout=null;"); + body.appendChild(smewsContact); + body.setAttribute("onMouseMove","moveMouse(event)"); + } +} + +// function cometAlert(responseDetails) { +// if(responseDetails.status == 200) { +// window.location.reload(); +// } +// } + +function getContactBook(responseDetails) { + if(responseDetails.status == 200) { + contactsBook = eval('(' + responseDetails.responseText + ')'); + for(i in contactsBook) { + contactsBook[i].name = unescape(contactsBook[i].name); + contactsBook[i].email = unescape(contactsBook[i].email); + contactsBook[i].phone = unescape(contactsBook[i].phone); + contactsBook[i].company = unescape(contactsBook[i].company); + contactsBook[i].address = unescape(contactsBook[i].address); + } + + contactsHash = new Array(); + for(i in contactsBook) { + contactsHash[contactsBook[i].name.toLowerCase()] = i; + } + parseBody(); +// ajaxGet("http://192.168.0.2/contactsBook/cb_comet",cometAlert); + } +} + +function ajaxGet(rqtUrl,ajaxCallBack) { + GM_xmlhttpRequest({ + method: "GET", + url: rqtUrl, + headers: { + "User-agent": "Firefox/3.0", + }, + onload: ajaxCallBack, + }); +} + +function showInfos(name) { + if(currentContact != name) { + currentContact = name; + var i = contactsHash[name.toLowerCase()]; + infos = "<table onmouseover=\"clearTimeout(timeout);timeout=null;\">"; + infos += "<tr><td style=\"padding-right: 6px\" align=\"right\"><b>E-mail:</b></td><td><a href=\"mailto:" + contactsBook[i].email + "\">" + contactsBook[i].email + "</a><br/></td></tr>"; + infos += "<tr><td style=\"padding-right: 6px\" align=\"right\"><b>Tel.:</b></td><td>" + contactsBook[i].phone + "<br/></td></tr>"; + infos += "<tr><td style=\"padding-right: 6px\" align=\"right\"><b>Company:</b></td><td>" + contactsBook[i].company + "<br/></td></tr>"; + infos += "<tr><td style=\"padding-right: 6px\" align=\"right\"><b>Address:</b></td><td>" + contactsBook[i].address + "<br/></td></tr>"; + infos += "</table>"; + + infos += '<iframe width="450" height="250" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://www2.lifl.fr/~duquenno/gmap.php?address=' + contactsBook[i].address + '"></iframe>'; + infos += '<br/><small><a href="http://maps.google.com/?q='+ contactsBook[i].address + '" style="color:#0000FF;text-align:left">Agrandir le plan</a></small>' + + smewsContact.innerHTML = infos; + + var boxY; + var relMouseY = mouseY - document.documentElement.scrollTop; + var boxX; + var relMouseX = mouseX - document.documentElement.scrollLeft; + if(relMouseY + 180 > window.innerHeight) + boxY = window.innerHeight - 380; + else if(relMouseY < 208) + boxY = 8; + else + boxY = relMouseY - 200; + boxY += document.documentElement.scrollTop; + + if(relMouseX + 490 > window.innerWidth) + boxX = mouseX - 475; + else + boxX = mouseX + 10; + + smewsContact.style.left = boxX + "px"; + smewsContact.style.top = boxY + "px"; + smewsContact.style.visibility = "visible"; + } +} + +function hideInfos() { + smewsContact.style.visibility = "hidden"; + currentContact = null; +} + +ajaxGet("http://www.funcard7.pan/contactsBook/cb_get",getContactBook); diff --git a/hostCodes/linuxUdp/SConstruct b/hostCodes/linuxUdp/SConstruct new file mode 100644 index 0000000000000000000000000000000000000000..0549b0bc47e4c46f923cb59665465187f06a51aa --- /dev/null +++ b/hostCodes/linuxUdp/SConstruct @@ -0,0 +1,6 @@ +BuildDir('bin', 'src',duplicate=0) +env = Environment() +env.Append(LIBS = 'm') +env.Append(CCFLAGS = '-g -O0') +env.Program('bin/main.c') + diff --git a/hostCodes/linuxUdp/src/main.c b/hostCodes/linuxUdp/src/main.c new file mode 100644 index 0000000000000000000000000000000000000000..6ded8ee9a34d6d45b41a32cbda24547d98b90be1 --- /dev/null +++ b/hostCodes/linuxUdp/src/main.c @@ -0,0 +1,105 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <fcntl.h> +#include <string.h> +#include <sys/ioctl.h> +#include <linux/if_tun.h> +#include <netinet/in.h> +#include <linux/if.h> +#include <math.h> + +/* configuration macros */ +#define DEVTUN "/dev/net/tun" + +/* common globals */ +#define BUFSIZE 2048 +unsigned char buffer_shadow[BUFSIZE+4]={0x0,0x0,0x08,0x0}; +#define buffer (buffer_shadow+4) + +/* misc. macros */ +#define MAX(a,b) ((a)>(b)?(a):(b)) + +void check(int test,const char *message) { + if(!test) { + perror(message); + exit(1); + } +} + +int main(int argc, char **argv) { + + /* misc. locals... */ + int i; + int j; + int ret; + int nRead; + int nfds; + int tun_fd; + int socket_fd; + fd_set fdset; + char tmpstr[64]; + char *cptr; + struct sockaddr_in sockaddr; + + /* host socket creation */ + socket_fd = socket(AF_INET,SOCK_DGRAM,0); + check(socket_fd != -1,"socket() error"); + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(1024); + sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + memset(&sockaddr.sin_zero,0,8); + ret=bind(socket_fd,(struct sockaddr*)&sockaddr,sizeof(sockaddr)); + check(ret != -1,"bind() error"); + + /* TUN interface creation */ + struct ifreq ifr; + tun_fd = open(DEVTUN, O_RDWR); + check(tun_fd != -1,"tun open() error"); + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TUN; + ret = ioctl(tun_fd, TUNSETIFF, (void *) &ifr); + check(ret >= 0,"tun ioctl error"); + /* TUN attachement to an IP address */ + snprintf((char*)tmpstr, BUFSIZE, "ifconfig %s 192.168.0.0 pointopoint 192.168.1.0 mtu 1500",ifr.ifr_name); + ret = system((char*)tmpstr); + check(ret != -1,"system() error when setting ifconfig"); + + /* main loop */ + nfds = MAX(tun_fd,socket_fd)+1; + FD_ZERO(&fdset); + while(1) { + FD_SET(tun_fd, &fdset); + FD_SET(socket_fd, &fdset); + + ret = select(nfds, &fdset, NULL, NULL, NULL); + check(ret != -1,"select() error"); + + /* wait for something to read on tun_fd or socket_fd */ + if(ret) { + if(FD_ISSET(tun_fd, &fdset)) { + /* something has been received on tun_fd, we forward it to socket_fd */ + nRead = read(tun_fd, (void *)buffer, BUFSIZE); + check(nRead != -1,"read() error"); + sockaddr.sin_port = htons(1025); + ret = sendto(socket_fd,buffer,nRead,0,(struct sockaddr*)&sockaddr,sizeof(sockaddr)); + check(ret != -1,"sendto() error"); + } + if(FD_ISSET(socket_fd, &fdset)) { + /* something has been received on socket_fd */ + int addrLen; + int emitterN; + nRead = recvfrom(socket_fd,buffer,BUFSIZE,0,(struct sockaddr*)&sockaddr,&addrLen); + check(nRead != -1,"recvfrom() error"); + emitterN = ntohs(sockaddr.sin_port) - (1025); + if(emitterN == 0) { + /* if the emitter is the Smews instance */ + ret = write(tun_fd, buffer_shadow, nRead+4); + check(ret != -1,"write() error"); + } + } + } + } + return 0; +} diff --git a/hostCodes/tunToSlip6/SConstruct b/hostCodes/tunToSlip6/SConstruct new file mode 100644 index 0000000000000000000000000000000000000000..b40a2114e13a7b7ba953300df49e16916576c0e0 --- /dev/null +++ b/hostCodes/tunToSlip6/SConstruct @@ -0,0 +1,5 @@ +BuildDir('bin', 'src',duplicate=0) +env = Environment() +env.Append(CCFLAGS = '-g -O0') +env.Program('bin/main.c') + diff --git a/hostCodes/tunToSlip6/src/main.c b/hostCodes/tunToSlip6/src/main.c new file mode 100644 index 0000000000000000000000000000000000000000..3f83c5d46b10f3d75a8a58ae23f06e028d909c49 --- /dev/null +++ b/hostCodes/tunToSlip6/src/main.c @@ -0,0 +1,196 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <fcntl.h> +#include <string.h> +#include <sys/ioctl.h> +#include <linux/if_tun.h> +#include <netinet/in.h> +#include <linux/if.h> +#include <math.h> +#include <termios.h> + +/* configuration macros */ +#define DEVTUN "/dev/net/tun" + +/* common globals */ +#define DEV_MTU 1500 +unsigned char tbuffer_shadow[DEV_MTU+4]={0x0,0x0,0x86,0xdd}; +#define tbuffer (tbuffer_shadow+4) +unsigned char sbuffer_shadow[DEV_MTU+4]={0x0,0x0,0x86,0xdd}; +#define sbuffer (sbuffer_shadow+4) +unsigned char *scurr = sbuffer; + +/* misc. macros */ +#define MAX(a,b) ((a)>(b)?(a):(b)) + +/* SLIP */ +#define SLIP_END 0xC0 /* indicates end of packet */ +#define SLIP_ESC 0xDB /* indicates byte stuffing */ +#define SLIP_ESC_END 0xDC /* ESC ESC_END means END data byte */ +#define SLIP_ESC_ESC 0xDD /* ESC ESC_ESC means ESC data byte */ + +static int ret; +static int tun_fd; +static int serial_fd; +static int forward_to_tun = 0; + +static void check(int test,const char *message) { + if(!test) { + perror(message); + exit(1); + } +} + +static int configure_port(int fd) { // configure the port + struct termios port_settings; // structure to store the port settings in + memset(&port_settings, 0, sizeof(struct termios)); + cfsetispeed(&port_settings, B115200); // set baud rates + cfsetospeed(&port_settings, B115200); + + port_settings.c_cflag |= CREAD; + port_settings.c_cflag |= CSTOPB; + port_settings.c_cflag |= CLOCAL; + port_settings.c_cflag |= CS8; + + return tcsetattr(fd, TCSANOW, &port_settings); // apply the settings to the port +} + +static void writeserial(unsigned char c) { + ret = write(serial_fd, &c, 1); + check(ret != -1,"write() to serial error"); +} + +static void read_from_tun() { + int i; + int nRead; + /* something has been received on tun_fd, we forward it to socket_fd */ + nRead = read(tun_fd, (void *)tbuffer_shadow, DEV_MTU); + check(nRead != -1,"read() from tun error"); + nRead -= 4; + printf("tunToSerial %d\n",nRead); + writeserial(SLIP_END); + for(i=0; i<nRead; i++) { + if(tbuffer[i]==SLIP_END){ + writeserial(SLIP_ESC); + writeserial(SLIP_ESC_END); + } else if(tbuffer[i]==SLIP_ESC){ + writeserial(SLIP_ESC); + writeserial(SLIP_ESC_ESC); + } else { + writeserial(tbuffer[i]); + } + } + writeserial(SLIP_END); +} + +static void read_from_serial() { + int nRead; + unsigned char tmp_buff[64]; + enum slip_state_e{slip_in,slip_escaped}; + static volatile enum slip_state_e slip_state = slip_in; + /* something has been received on socket_fd */ + while((nRead = read(serial_fd, tmp_buff, 64)) > 0) { + int i; + for(i=0; i<nRead; i++) { + unsigned char c = tmp_buff[i]; + unsigned char isChar = 1; + /* SLIP management */ + switch(c) { + case SLIP_END: + if(scurr != sbuffer) { + forward_to_tun = 1; + } + isChar = 0; + break; + case SLIP_ESC: + slip_state = slip_escaped; + isChar = 0; + break; + case SLIP_ESC_END: + if(slip_state == slip_escaped) { + slip_state = slip_in; + c = SLIP_END; + } + break; + case SLIP_ESC_ESC: + if(slip_state == slip_escaped) { + slip_state = slip_in; + c = SLIP_ESC; + } + break; + default: + break; + } + if(isChar && scurr < sbuffer + DEV_MTU) { + *scurr++ = c; + } + if(forward_to_tun == 1) { + printf("serialToTun %d\n",scurr-sbuffer); + ret = write(tun_fd, (void *)sbuffer_shadow, scurr-sbuffer + 4); + check(ret != -1,"write() to tun error"); + forward_to_tun = 0; + scurr = sbuffer; + } + } + } + check(nRead != -1,"read() from serial error"); +} + +int main(int argc, char **argv) { + /* misc. locals... */ + int nfds; + fd_set fdset; + char tmpstr[64]; + + if(argc != 2) { + fprintf(stderr,"Usage: %s <IPv6/mask>\n",argv[0]); + return; + } + + /* open the serial port */ + serial_fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY); + check(serial_fd != -1,"serial open() error"); + ret = configure_port(serial_fd); + check(ret != -1,"serial configure_port() error"); + + /* TUN interface creation */ + struct ifreq ifr; + tun_fd = open(DEVTUN, O_RDWR); + check(tun_fd != -1,"tun open() error"); + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TUN; + ret = ioctl(tun_fd, TUNSETIFF, (void *) &ifr); + check(ret >= 0,"tun ioctl error"); + /* TUN attachement to an IP address */ + snprintf((char*)tmpstr, 64, "ifconfig %s inet6 add %s",ifr.ifr_name,argv[1]); + ret = system((char*)tmpstr); + check(ret != -1,"system() ifocnfig add error"); + snprintf((char*)tmpstr, 64, "ifconfig %s up",ifr.ifr_name); + ret = system((char*)tmpstr); + check(ret != -1,"system() ifconfig up error"); + + /* main loop */ + nfds = MAX(tun_fd, serial_fd) + 1; + FD_ZERO(&fdset); + printf("Started\n"); + while(1) { + FD_SET(tun_fd, &fdset); + FD_SET(serial_fd, &fdset); + + ret = select(nfds, &fdset, NULL, NULL, NULL); + check(ret != -1,"select() error"); + + /* wait for something to read on tun_fd or socket_fd */ + if(ret) { + if(FD_ISSET(tun_fd, &fdset)) { + read_from_tun(); + } + if(FD_ISSET(serial_fd, &fdset)) { + read_from_serial(); + } + } + } + return 0; +} diff --git a/hostCodes/wsnSimulator/SConstruct b/hostCodes/wsnSimulator/SConstruct new file mode 100644 index 0000000000000000000000000000000000000000..c1747e4e44572079484ef4153700c1546035a8c5 --- /dev/null +++ b/hostCodes/wsnSimulator/SConstruct @@ -0,0 +1,6 @@ +BuildDir('bin', 'src',duplicate=0) +env = Environment() +env.Append(LIBS = 'm') +env.Append(CCFLAGS = '-g -O0') +env.Program('bin/simu.c') +Clean('.',['bin','.sconsign.dblite']) diff --git a/hostCodes/wsnSimulator/src/simu.c b/hostCodes/wsnSimulator/src/simu.c new file mode 100644 index 0000000000000000000000000000000000000000..294c372f82837b442c551826da260d1743105a41 --- /dev/null +++ b/hostCodes/wsnSimulator/src/simu.c @@ -0,0 +1,261 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <fcntl.h> +#include <string.h> +#include <sys/ioctl.h> +#include <linux/if_tun.h> +#include <netinet/in.h> +#include <linux/if.h> +#include <math.h> + +/* misc. macros */ +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define SQUARE(a) ((a)*(a)) +#define ABS_DIST(a,b) (sqrt(SQUARE((a).x - (b).x) + SQUARE((a).y - (b).y))) + +/* configuration macros */ +#define DEVTUN "/dev/net/tun" +#define DEFAULT_NNODES 64 +#define DEFAULT_NODE_RANGE 0.1 +#define DEFAULT_LOSS_RATE 0.05 + +/* data structures */ +struct node_s; +struct neighbour_s { + struct node_s *node; + struct neighbour_s *next; +}; +struct node_s { + float x; + float y; + int nodeN; + struct neighbour_s *first_neighbour; +}; + +/* common globals */ +#define BUFSIZE 2048 +unsigned char buffer_shadow[BUFSIZE+4]={0x0,0x0,0x08,0x0}; +#define buffer (buffer_shadow+4) +struct node_s *nodes; +const char sigNames[15][8] = {"HUP","INT","QUIT","ILL","","ABRT","","FPE","KILL","","SEGV","","PIPE","ALRM","TERM"}; + +void cleanup(int signo) { + /* Kill all Smews processes AND the simulator. No need to free any malloc... */ + if(signo > 0 && signo <= 16) + fprintf(stderr,"Signal received: %d (SIG%s)\n",signo,sigNames[signo-1]); + killpg(0, SIGKILL); +} + +void usage() { + printf("Options:\n"); + printf("-h: display this helps\n"); + printf("-b <path>: set the smews binary path\n"); + printf("-n <nNodes>: set the amount of nodes in the simulation\n"); + printf("-r <range>: set the range for wireless emissions (in ]0-1])\n"); + printf("-l <loss>: set the loss rate (in [0-1])\n"); +} + +void check(int test,const char *message) { + if(!test) { + perror(message); + cleanup(-1); + } +} + +void ensure(int test,const char *message) { + if(!test) { + fputs(message,stderr); + cleanup(-1); + } +} + +void add_neighbour(struct node_s *n1, struct node_s *n2) { + struct neighbour_s *old_neighbour = n1->first_neighbour; + n1->first_neighbour = (struct neighbour_s*)malloc(sizeof(struct neighbour_s)); + n1->first_neighbour->node = n2; + n1->first_neighbour->next = old_neighbour; +} + +int loss_occurs(int emitter, int receiver, double lossRate) { + return rand()/(float)RAND_MAX <= lossRate; +} + +int main(int argc, char **argv) { + + /* command line arguments variables */ + char *smewsBinaryPath = NULL; + int nNodes = DEFAULT_NNODES; + double nodeRange = DEFAULT_NODE_RANGE; + double lossRate = DEFAULT_LOSS_RATE; + + /* misc. locals... */ + int i; + int j; + int ret; + int nRead; + int nfds; + int tun_fd; + int socket_fd; + fd_set fdset; + char tmpstr[64]; + char *cptr; + struct sockaddr_in sockaddr; + + /* arguments parsing */ + if(argc == 1) + usage(); + opterr = 0; + while ((j = getopt (argc, argv, "hb:n:r:l:")) != -1) { + switch (j) { + case 'h': + usage(); + break; + case 'b': + smewsBinaryPath = optarg; + break; + case 'n': + nNodes = strtol(optarg, &cptr, 10); + ensure(!*cptr && nNodes > 0,"Option -n requires a positive integer as argument.\n"); + break; + case 'r': + nodeRange = strtod(optarg, &cptr); + ensure(!*cptr && nodeRange > 0 && nodeRange <=1,"Option -r requires a float in ]0-1] as argument.\n"); + break; + case 'l': + lossRate = strtod(optarg, &cptr); + ensure(!*cptr && lossRate >= 0 && lossRate <=1,"Option -r requires a float in [0-1] as argument.\n"); + break; + case '?': + if(isprint (optopt)) + sprintf(tmpstr,"Unknown option `-%c'.\n", optopt); + else + sprintf(tmpstr,"Unknown option character `0x%x'.\n",optopt); + ensure(0,tmpstr); + default: + ensure(0,"An error occured when parsing the arguments.\n"); + } + } + if(optind != argc) { + sprintf(tmpstr,"Invalid argument `%s'\n", argv[optind]); + ensure(0,tmpstr); + } + ensure(smewsBinaryPath != NULL,"Option -b is required.\n"); + + /* print the current configuration */ + printf("Configuring the simulator...\n"); + printf("Smews binary path: %s\n",smewsBinaryPath); + printf("Amount of nodes: %d\n",nNodes); + printf("Nodes range: %f\n",nodeRange); + printf("Loss rate: %f\n",lossRate); + + /* catch the 16 first signals signals */ + for(i=1; i<16; i++) + signal(i, &cleanup); + + /* host socket creation */ + socket_fd = socket(AF_INET,SOCK_DGRAM,0); + check(socket_fd != -1,"socket() error"); + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(1024); + sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + memset(&sockaddr.sin_zero,0,8); + ret=bind(socket_fd,(struct sockaddr*)&sockaddr,sizeof(sockaddr)); + check(ret != -1,"bind() error"); + + /* Smews processes and nodes creation */ + nodes = (struct node_s *)malloc(nNodes*sizeof(struct node_s)); + check(nodes != NULL,"malloc() error"); + srand(time(NULL)); + for(i=0; i<nNodes; i++) { + nodes[i].first_neighbour = NULL; + nodes[i].nodeN = i; + /* set coordinates for the node i */ + do { + nodes[i].x = rand()/(float)RAND_MAX; + nodes[i].y = rand()/(float)RAND_MAX; + for(j=0; j<i; j++) { + /* set neighbourhoud */ + if(ABS_DIST(nodes[i],nodes[j]) <= nodeRange) { + add_neighbour(&nodes[i],&nodes[j]); + add_neighbour(&nodes[j],&nodes[i]); + } + } + /* ensures that the graph is connected */ + } while (i!=0 && !nodes[i].first_neighbour); + /* new Smews process creation */ + sprintf(tmpstr,"%d",i); + setenv("SMEWS_ID",tmpstr,1); + if(!vfork()) { + execl(smewsBinaryPath,"",NULL); + perror("execl() error"); + cleanup(2); + } + } + + /* TUN interface creation */ + struct ifreq ifr; + tun_fd = open(DEVTUN, O_RDWR); + check(tun_fd != -1,"tun open() error"); + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TUN; + ret = ioctl(tun_fd, TUNSETIFF, (void *) &ifr); + check(ret >= 0,"tun ioctl error"); + /* TUN attachement to an IP address */ + snprintf((char*)tmpstr, BUFSIZE, "ifconfig %s 192.168.0.0 pointopoint 192.168.1.0 mtu 1500",ifr.ifr_name); + ret = system((char*)tmpstr); + check(ret != -1,"system() error when setting ifconfig"); + + /* main loop */ + printf("Simulation is launched...\n"); + nfds = MAX(tun_fd,socket_fd)+1; + FD_ZERO(&fdset); + while(1) { + FD_SET(tun_fd, &fdset); + FD_SET(socket_fd, &fdset); + ret = select(nfds, &fdset, NULL, NULL, NULL); + check(ret != -1,"select() error"); + /* wait for something to read on tun_fd or socket_fd */ + if(ret) { + if(FD_ISSET(tun_fd, &fdset)) { + /* something has been received on tun_fd, we forward it to the reachable node */ + nRead = read(tun_fd, (void *)buffer, BUFSIZE); + check(nRead != -1,"read() error"); + if(!loss_occurs(0,1,lossRate)) { + sockaddr.sin_port = htons(1025); + ret = sendto(socket_fd,buffer,nRead,0,(struct sockaddr*)&sockaddr,sizeof(sockaddr)); + check(ret != -1,"sendto() error"); + } + } + if(FD_ISSET(socket_fd, &fdset)) { + /* something has been received on socket_fd */ + int addrLen; + int emitterN; + nRead = recvfrom(socket_fd,buffer,BUFSIZE,0,(struct sockaddr*)&sockaddr,&addrLen); + check(nRead != -1,"recvfrom() error"); + emitterN = ntohs(sockaddr.sin_port) - (1025); + if(emitterN >= 0 && emitterN < nNodes) { + /* send the datagram to all the neighbours of the emitter */ + struct neighbour_s *curr_neighbour = nodes[emitterN].first_neighbour; + while(curr_neighbour) { + if(!loss_occurs(emitterN,curr_neighbour->node->nodeN,lossRate)) { + sockaddr.sin_port = htons(1025 + curr_neighbour->node->nodeN); + ret = sendto(socket_fd,buffer,nRead,0,(struct sockaddr*)&sockaddr,sizeof(sockaddr)); + check(ret != -1,"sendto() error"); + } + curr_neighbour = curr_neighbour->next; + } + /* if the emitter is the reachable node, send the datagram on the TUN interface */ + if(emitterN == 0) { + if(!loss_occurs(emitterN,0,lossRate)) { + ret = write(tun_fd, buffer_shadow, nRead+4); + check(ret != -1,"write() error"); + } + } + } + } + } + } + return 0; +} diff --git a/license b/license new file mode 100644 index 0000000000000000000000000000000000000000..bb05432c87c0bf56ad6964d05126e9486043ef82 --- /dev/null +++ b/license @@ -0,0 +1,34 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ diff --git a/panManager/SConstruct b/panManager/SConstruct new file mode 100644 index 0000000000000000000000000000000000000000..a7b93d301c6ac8c950b4c2196a1eb8951c996074 --- /dev/null +++ b/panManager/SConstruct @@ -0,0 +1,12 @@ +import os + +BuildDir('bin', 'src',duplicate=0) +env = Environment() +env.Append(CCFLAGS = '-g -O0 -Wall') +env.Append(LINKFLAGS = '-rdynamic') +env.Append(LIBS = 'dl') +env.Program('bin/panManager', Glob('bin/*.c')) + +for plugin in os.listdir('plugins'): + if not plugin.startswith('.'): + SConscript('plugins/%s/SConscript' %plugin) diff --git a/panManager/plugins/apduip/SConstruct b/panManager/plugins/apduip/SConstruct new file mode 100644 index 0000000000000000000000000000000000000000..9ac3c74de47e8af45f61ac14a71c2ef64b89d3b2 --- /dev/null +++ b/panManager/plugins/apduip/SConstruct @@ -0,0 +1 @@ +SConscript('SConscript') \ No newline at end of file diff --git a/panManager/plugins/apduip/apduip.c b/panManager/plugins/apduip/apduip.c new file mode 100644 index 0000000000000000000000000000000000000000..06fd908b056d18797522413ea0ea73576d7c9004 --- /dev/null +++ b/panManager/plugins/apduip/apduip.c @@ -0,0 +1,201 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <pcsclite.h> +#include <winscard.h> +#include <string.h> +#include "panManager.h" + +/* status bytes wrappers */ +#define SW1(_sw) ((_sw) & 0xFF) +#define SW2(_sw) (((_sw)>>8) & 0xFF) +/* size of APDU headers */ +#define APDU_HEADER_SIZE 5 + +static int ret; +static SCARDCONTEXT sc_context; +static SCARDHANDLE sc_handle; +static unsigned char *tbuffer; +static unsigned char *dbuffer; +static unsigned dev_mtu; + +/* process a check including the pcsc specific error */ +static void pcsccheck(int val, const char *str) { + check(val == 0, "%s: %s", str, pcsc_stringify_error(val)); +} + +/* send one IP packet using APDUs */ +static short apduip_send_packet(unsigned char *buffer, int size) { + short sw; + unsigned long in_size = 255 + 3; + unsigned long out_size = 255 + 3; + unsigned char in_buffer[in_size]; + unsigned char out_buffer[out_size]; + unsigned char *curr_output_ptr = buffer; + + /* set the APDU header */ + out_buffer[0] = 0x80; + out_buffer[1] = 0x01; + out_buffer[2] = 0x00; + out_buffer[3] = 0; + + /* loop to send the packet via multiple APDUs */ + do { + /* size of the current message */ + unsigned char curr_len = size > 255 ? 255 : size; + out_size = curr_len + APDU_HEADER_SIZE; + + /* set the buffer to be sent */ + out_buffer[4] = curr_len; + memcpy(out_buffer + APDU_HEADER_SIZE, curr_output_ptr, curr_len); + + /* process APDU */ + ret = SCardTransmit(sc_handle, SCARD_PCI_T0, out_buffer, out_size, NULL, in_buffer, &in_size); + pcsccheck(ret, "SCardTransmit() error (descending IP)"); + + /* check status word */ + sw = *((short*)(in_buffer + in_size - 2)); + check(SW1(sw) >= 0x90, "APDU error code (descending IP): 0x%02x%02x\n", SW1(sw), SW2(sw)); + + /* update pointers and remainig size */ + curr_output_ptr += curr_len; + size -= curr_len; + + } while(size > 0); + + return sw; +} + +/* receive one IP packet using APDUs */ +short apduip_recv_packet(unsigned short sw, unsigned char *buffer) { + unsigned long out_size = APDU_HEADER_SIZE; + unsigned long in_size = 255 + 3; + unsigned char out_buffer[APDU_HEADER_SIZE]; + unsigned char *curr_input_ptr = buffer; + int packet_length = -1; + + /* set the APDU header */ + out_buffer[0]= 0x80; + out_buffer[1]= 0x02; + out_buffer[2]= 0x00; + out_buffer[3]= 0x00; + out_buffer[4]= SW2(sw); + + /* loop to receive the packet from multiple APDUs */ + do { + /* process APDU */ + out_buffer[4]= SW2(sw); + ret = SCardTransmit(sc_handle, SCARD_PCI_T0, out_buffer, out_size, NULL, curr_input_ptr, &in_size); + pcsccheck(ret, "SCardTransmit() error (ascending IP)"); + + /* check status word */ + sw = *((short*)(curr_input_ptr + in_size - 2)); + check(SW1(sw) >= 0x90, "APDU error code (ascending IP): 0x%02x%02x\n", SW1(sw), SW2(sw)); + + /* set the initial IP packet length (contained in the first APDU response) */ + if(packet_length == -1) { + packet_length = (curr_input_ptr[2] << 8) + curr_input_ptr[3]; + check(packet_length <= dev_mtu, "IP packet bigger than MTU (%d > %d)\n", packet_length, dev_mtu); + } + + /* update pointers and remainig size */ + packet_length -= in_size - 2; + curr_input_ptr += in_size - 2; + } while(packet_length > 0); + + /* forward the packet to the tu ninterface */ + forward_to_tun(curr_input_ptr - buffer); + + return sw; +} + +/* callback: called when a packet has been received from the tun interface */ +static void forward_to_apduip(int size) { + unsigned char *curr_data = tbuffer; + short sw; + + /* send the current tun input to the card */ + sw = apduip_send_packet(curr_data, size); + + /* receive all ascending data from the card and forward it to the tun if needed */ + while(SW2(sw)) { + /* the status word allows to know if the card has other packets to send */ + sw = apduip_recv_packet(sw, dbuffer); + } +} + +/* callback: initializes the card reader */ +static int init_apduip(unsigned char *tbuff, unsigned char *dbuff, unsigned dmtu, char *argument) { + char *cr_names; + unsigned long cr_names_len, protocol; + + /* initialization and reader detection*/ + ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &sc_context); + pcsccheck(ret, "SCardEstablishContext() error"); + + ret = SCardListReaders(sc_context, NULL, NULL, &cr_names_len); + pcsccheck(ret, "ListReaders() error"); + + cr_names = malloc(cr_names_len); + ret = SCardListReaders(sc_context, NULL, cr_names, &cr_names_len); + pcsccheck(ret, "ListReaders() error"); + + message("Please insert a card in the reader: %s\n",cr_names); + + /* loop until a card has been inserted */ + do { + usleep(100); + ret = SCardConnect(sc_context, cr_names, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &sc_handle, &protocol); + } while (ret == SCARD_E_NO_SMARTCARD || ret == SCARD_W_REMOVED_CARD); + pcsccheck(ret, "SCardConnect() error"); + + /* set global variables */ + tbuffer = tbuff; + dbuffer = dbuff; + dev_mtu = dmtu; + + return 0; +} + +/* plugin callbacks declaration */ +struct dev_handlers_s plugin_handlers = { + "", + init_apduip, + NULL, /* this callback is unused here: with APDUs, no data can come from the card without having been requested by the reader */ + forward_to_apduip +}; diff --git a/panManager/plugins/slip/SConstruct b/panManager/plugins/slip/SConstruct new file mode 100644 index 0000000000000000000000000000000000000000..9ac3c74de47e8af45f61ac14a71c2ef64b89d3b2 --- /dev/null +++ b/panManager/plugins/slip/SConstruct @@ -0,0 +1 @@ +SConscript('SConscript') \ No newline at end of file diff --git a/panManager/plugins/slip/slip.c b/panManager/plugins/slip/slip.c new file mode 100644 index 0000000000000000000000000000000000000000..73a69fad54b2fe73b72ebe27d7518c47c923fdcc --- /dev/null +++ b/panManager/plugins/slip/slip.c @@ -0,0 +1,186 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <termios.h> + +#include "panManager.h" + +/* SLIP special bytes */ +#define SLIP_END 0xC0 /* indicates end of packet */ +#define SLIP_ESC 0xDB /* indicates byte stuffing */ +#define SLIP_ESC_END 0xDC /* ESC ESC_END means END data byte */ +#define SLIP_ESC_ESC 0xDD /* ESC ESC_ESC means ESC data byte */ + +static int ret; +static int slip_fd; +static unsigned char *tbuffer; +static unsigned char *dbuffer; +static unsigned dev_mtu; + +#define DEFAULT_SERIAL_DEV "/dev/ttyS0" + +/* writes one byte to the serial line */ +static void writeserial(unsigned char c) { + ret = write(slip_fd, &c, 1); + check(ret != -1,"write() to serial error"); +} + +/* callback: forward from tun to serial line using slip */ +static void forward_to_slip(int size) { + int i; + writeserial(SLIP_END); + for(i=0; i<size; i++) { + if(tbuffer[i]==SLIP_END){ + writeserial(SLIP_ESC); + writeserial(SLIP_ESC_END); + } else if(tbuffer[i]==SLIP_ESC){ + writeserial(SLIP_ESC); + writeserial(SLIP_ESC_ESC); + } else { + writeserial(tbuffer[i]); + } + } + writeserial(SLIP_END); +} + +/* callback: forward from serial line (slip) to tun */ +static void read_from_slip() { + int nRead; + unsigned char tmp_buff[64]; + enum slip_state_e{slip_in,slip_escaped}; + /* current slip state */ + static volatile enum slip_state_e slip_state = slip_in; + /* current position in the output buffer (inside dbuffer) */ + static unsigned char *scurr = NULL; + + if(scurr == NULL) { + scurr = dbuffer; + } + + /* something has been received on socket_fd */ + while((nRead = read(slip_fd, tmp_buff, 64)) > 0) { + int i; + int ended = 0; + /* process the current input */ + for(i=0; i<nRead; i++) { + unsigned char c = tmp_buff[i]; + unsigned char isChar = 1; + /* SLIP management */ + switch(c) { + case SLIP_END: + if(scurr != dbuffer) { + ended = 1; + } + isChar = 0; + break; + case SLIP_ESC: + slip_state = slip_escaped; + isChar = 0; + break; + case SLIP_ESC_END: + if(slip_state == slip_escaped) { + slip_state = slip_in; + c = SLIP_END; + } + break; + case SLIP_ESC_ESC: + if(slip_state == slip_escaped) { + slip_state = slip_in; + c = SLIP_ESC; + } + break; + default: + break; + } + /* write the new byte in the buffer is needed (and if possible) */ + if(isChar && scurr < dbuffer + dev_mtu) { + *scurr++ = c; + } + /* if the packet is ended, forward it to the tun interface */ + if(ended == 1) { + forward_to_tun(scurr-dbuffer); + /* reinitializations for a new packet */ + ended = 0; + scurr = dbuffer; + } + } + } + check(nRead != -1,"read() from serial error"); +} + +/* callback: initializes the serial line */ +static int init_slip(unsigned char *tbuff, unsigned char *dbuff, unsigned dmtu, char *argument) { + char *serial_dev = argument ? argument : DEFAULT_SERIAL_DEV; + struct termios port_settings; + + message("Initialization of the %s serial device\n", serial_dev); + + /* open the serial port */ + slip_fd = open(serial_dev, O_RDWR | O_NOCTTY); + check(slip_fd != -1,"serial open() error"); + + /* configure the port */ + memset(&port_settings, 0, sizeof(struct termios)); + ret = cfsetispeed(&port_settings, B115200); + check(slip_fd != -1,"serial cfsetispeed() error"); + + ret = cfsetospeed(&port_settings, B115200); + check(slip_fd != -1,"serial cfsetospeed() error"); + + port_settings.c_cflag |= CREAD; + port_settings.c_cflag |= CSTOPB; + port_settings.c_cflag |= CLOCAL; + port_settings.c_cflag |= CS8; + ret = tcsetattr(slip_fd, TCSANOW, &port_settings); + check(ret != -1,"serial configure_port() error"); + + /* set global variables */ + tbuffer = tbuff; + dbuffer = dbuff; + dev_mtu = dmtu; + + return slip_fd; +} + +/* plugin callbacks declaration */ +struct dev_handlers_s plugin_handlers = { + "set serial device", + init_slip, + read_from_slip, + forward_to_slip +}; diff --git a/panManager/src/panManager.c b/panManager/src/panManager.c new file mode 100644 index 0000000000000000000000000000000000000000..2d869bab14ac092f817380d65054931ec23c287c --- /dev/null +++ b/panManager/src/panManager.c @@ -0,0 +1,267 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <sys/ioctl.h> +#include <linux/if_tun.h> +#include <netinet/in.h> +#include <linux/if.h> +#include <ctype.h> +#include <stdarg.h> +#include <dlfcn.h> + +#include "panManager.h" + +/* configuration macros */ +#define DEVTUN "/dev/net/tun" +#define DEV_MTU 1500 + +/* globals */ +unsigned char tbuffer_shadow[DEV_MTU+4]={0}; +#define tbuffer (tbuffer_shadow+4) +unsigned char dbuffer_shadow[DEV_MTU+4]={0}; +#define dbuffer (dbuffer_shadow+4) + +/* misc. macros */ +#define MAX(a,b) ((a)>(b)?(a):(b)) + +static int ret; +static int tun_fd; +static int dev_fd; +static struct dev_handlers_s *dev_handlers = NULL; +static int verbose = 0; + +/* printf if verbose mode is on */ +void message(char *str, ...) { + va_list argp; + va_start(argp, str); + if(verbose) { + vprintf(str, argp); + } + va_end(argp); +} + +/* check if test is ok, print error message if needed then exit */ +void check(int test, const char *str, ...) { + va_list argp; + va_start(argp, str); + if(!test) { + if(errno == 0) { + vfprintf(stderr, str, argp); + printf("\n"); + } else { + char tmp[2048]; + snprintf(tmp, 2048, str, argp); + perror(tmp); + } + exit(1); + } + va_end(argp); +} + +/* usage for this program */ +static void usage(const char *path, const char *plugin_help_string) { + fprintf(stderr, "Usage: %s <plugin> <ip/masksize> [options]\n", path); + fprintf(stderr, "Options available:\n"); + fprintf(stderr, "\t-h: display this help\n"); + fprintf(stderr, "\t-v: verbose\n"); + fprintf(stderr, "\t-p <arg>: plugin argument"); + if(plugin_help_string == NULL) { + fprintf(stderr, " (set a plugin to get detailed informations)"); + } else if(plugin_help_string[0] == '\0'){ + fprintf(stderr, " (no option available for this plugin)"); + } else { + fprintf(stderr, " (%s)", plugin_help_string); + } + fprintf(stderr, "\n"); +} + +/* called by a plugin to forward data from dbuffer in to tun interface */ +void forward_to_tun(int size) { + message("Packet from device: %d bytes\n",size); + ret = write(tun_fd, (void *)dbuffer_shadow, size + 4); + check(ret != -1,"write() to tun error"); +} + +/* manages an incomming packet on the tun interface */ +static void tun_input() { + int nRead; + nRead = read(tun_fd, (void *)tbuffer_shadow, DEV_MTU); + check(nRead != -1,"read() from tun error"); + nRead -= 4; + message("Packet from tun: %d bytes\n",nRead); + /* call the plugin dependent function, dealing with the data in tbuffer */ + dev_handlers->forward_to_dev(nRead); +} + +/* manages an incomming packet on the device interface */ +static void dev_input() { + /* call the plugin dependent function, which could possible call forward_to_tun */ + dev_handlers->read_from_dev(); +} + +/* this program loads a plugin and links it to a tun interface */ +int main(int argc, char **argv) { + int nfds; + fd_set fdset; + char tmpstr[2048]; + char c; + char *cptr; + void *dlhandle; + int isv6 = 0; + char *plugin = NULL; + char *ifconfigopt = NULL; + char *ipaddr = NULL; + char display_help = 0; + char wrong_arguments = 0; + char *pluginopt = NULL; + + /* first try to get the plugin argument */ + if (argc < 2 || argv[1][0] == '-') { + usage(argv[0], NULL); + exit(2); + } else { + plugin = argv[1]; + } + + /* Open the plugin */ + snprintf(tmpstr, 2048, "./plugins/%s/lib%s.so", plugin, plugin); + dlhandle = dlopen(tmpstr, RTLD_NOW); + check(dlhandle != NULL, "dlopen() error: %s", dlerror()); + /* Get plugin_handlers, containing the plugin funciton handlers (struct dev_handlers_s) */ + dev_handlers = dlsym(dlhandle, "plugin_handlers"); + check(dev_handlers != NULL, "dlsym() error: %s", dlerror()); + + /* optional arguments parsing */ + while ((c = getopt (argc, argv, "hp:v")) != -1) { + switch (c) { + case 'h': + display_help = 1; + break; + case 'p': + pluginopt = optarg; + break; + case 'v': + verbose = 1; + break; + case '?': + wrong_arguments = 1; + break; + } + } + + /* call usage if needed */ +#define N_STATIC_ARGS 2 + if (wrong_arguments || optind + N_STATIC_ARGS != argc) { + usage(argv[0], dev_handlers->help_string); + exit(2); + } + + /* display help (-h option) */ + if(display_help) { + usage(argv[0], dev_handlers->help_string); + } + + /* get ip configuration arguments */ + ipaddr = argv[optind + 1]; + cptr = ipaddr; + + /* detect if the IP is v4 or v6 */ + while(*cptr++) { + if(*cptr == ':') { + isv6 = 1; + break; + } + } + + /* set ifconfig options and tun headers depending on the ip version */ + if(isv6) { + ifconfigopt = "inet6 add"; + dbuffer_shadow[2] = 0x86; + dbuffer_shadow[3] = 0xDD; + } else { + ifconfigopt = ""; + dbuffer_shadow[2] = 0x08; + dbuffer_shadow[3] = 0x00; + } + + /* Device initialization (done by the plugin) */ + dev_fd = dev_handlers->init_dev(tbuffer, dbuffer, DEV_MTU, pluginopt); + check(dev_fd != -1,"init_dev() error"); + + /* TUN interface creation */ + struct ifreq ifr; + tun_fd = open(DEVTUN, O_RDWR); + check(tun_fd != -1,"tun open() error"); + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TUN; + ret = ioctl(tun_fd, TUNSETIFF, (void *) &ifr); + check(ret >= 0,"tun ioctl error"); + + /* TUN attachement to an IP address */ + snprintf((char*)tmpstr, 64, "ifconfig %s %s %s up > /dev/null 2> /dev/null ",ifr.ifr_name,ifconfigopt,ipaddr); + ret = system((char*)tmpstr); + check(ret == 0, "system() ifconfig error"); + + /* main loop */ + nfds = MAX(tun_fd, dev_fd) + 1; + FD_ZERO(&fdset); + message("PAN manager ready\n"); + while(1) { + FD_SET(tun_fd, &fdset); + FD_SET(dev_fd, &fdset); + + /* wait until there is some data on either the tun or the device */ + ret = select(nfds, &fdset, NULL, NULL, NULL); + check(ret != -1,"select() error"); + + /* process the input on tun or the device */ + if(ret) { + if(FD_ISSET(tun_fd, &fdset)) { + tun_input(); + } + if(FD_ISSET(dev_fd, &fdset)) { + dev_input(); + } + } + } + return 0; +} diff --git a/panManager/src/panManager.h b/panManager/src/panManager.h new file mode 100644 index 0000000000000000000000000000000000000000..50ffd55b3cf8afefe028c593df95b925d7da9b1c --- /dev/null +++ b/panManager/src/panManager.h @@ -0,0 +1,59 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef _PANMANAGER_H_ +#define _PANMANAGER_H_ + +/* functions prototypes for plugins */ +typedef int (init_dev_t)(unsigned char *tbuff, unsigned char *dbuff, unsigned dmtu, char *argument); +typedef void (read_from_dev_t)(); +typedef void (forward_to_dev_t)(int size); + +/* this structure contains the functions pointers of a plugin */ +struct dev_handlers_s { + const char *help_string; + init_dev_t *init_dev; + read_from_dev_t *read_from_dev; + forward_to_dev_t *forward_to_dev; +}; + +/* check if test is ok, prints an error message if needed and exit */ +extern void check(int test, const char *str, ...); +/* prints a message if the verbose mode is on */ +extern void message(char *str, ...); +/* forwards a packet to the tun interface */ +extern void forward_to_tun(int size); + +#endif diff --git a/targets/Funcard7/SConscript b/targets/Funcard7/SConscript new file mode 100755 index 0000000000000000000000000000000000000000..ecb4930c1fb7ddef8677865cadc48a6d7cff3892 --- /dev/null +++ b/targets/Funcard7/SConscript @@ -0,0 +1,49 @@ +# Copyright or c or Copr. 2008, Geoffroy Cogniaux +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + +import os +import sys + +Import('env binDir projectName elfName') + +env.Replace(CC = 'avr-gcc') +env.Replace(AS = 'avr-as') +env.Replace(AR = 'avr-ar') +env.Replace(RANLIB = 'avr-ranlib') +env.Append(CCFLAGS = '-mmcu=at90s8515 -D __AVR_AT90S8515__ -DDAY=0x`date +%d` -DMONTH=0x`date +%m` -DYEAR=0x`date +%y`') +env.Append(ASFLAGS = '-mmcu=at90s8515') +env.Append(LINKFLAGS = '-mmcu=at90s8515 -D__AVR_AT90S8515__') +env.Append(CCFLAGS = '-mcall-prologues') + +binaryName = projectName + '.bin' +env.Command(binaryName, elfName, 'avr-objcopy -R .eeprom -O binary $SOURCE $TARGET') + +eepromName = projectName + '.eep.bin' +env.Command(eepromName, elfName, 'avr-objcopy -j .eeprom -O binary $SOURCE $TARGET') diff --git a/targets/Funcard7/drivers/at_config.h b/targets/Funcard7/drivers/at_config.h new file mode 100755 index 0000000000000000000000000000000000000000..bda77fc90cfbc0d1ee0f93f93d3256da11fe1650 --- /dev/null +++ b/targets/Funcard7/drivers/at_config.h @@ -0,0 +1,116 @@ +/* +* Copyright or © or Copr. 2008, Geoffroy Cogniaux +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +/* Parts of code from SOSSE: */ + +/* +* Simple Operating system for Smart cards +* Copyright (C) 2002 Matthias Bruestle <m@mbsks.franken.de> +* +* 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 +*/ + +#ifndef PPSCS_CONFIG_H +#define PPSCS_CONFIG_H + + +#if defined(__AVR_AT90S8515__) +//! This is a little endian architecture. +#define ENDIAN_LITTLE +//! Size of the internal EEPROM. +#define EEPROM_SIZE 0x200 +//! Size of the RAM. +#define RAM_SIZE 0x200 +//! Chip ID. +#define CHIP 0x01 +//! External EEPROM ID. +#define ESIZ 0x05 +//! AVR architecture. Needed for assembler. +#define ARCH avr2 +#elif defined(__AVR_AT90S8535__) +//! This is a little endian architecture. +#define ENDIAN_LITTLE +//! Size of the internal EEPROM +#define EEPROM_SIZE 0x200 +//! Size of the RAM. +#define RAM_SIZE 0x200 +//! Chip ID. +#define CHIP 0x01 +//! External EEPROM ID. +#define ESIZ 0x03 +//! AVR architecture. Needed for assembler. +#define ARCH avr2 +#elif defined(__AVR_AT90S2323__) +//! This is a little endian architecture. +#define ENDIAN_LITTLE +//! Size of the internal EEPROM +#define EEPROM_SIZE 0x80 +//! Size of the RAM. +#define RAM_SIZE 0x80 +//! Chip ID. +#define CHIP 0x00 +//! External EEPROM ID. +#define ESIZ 0x03 +//! AVR architecture. Needed for assembler. +#define ARCH avr2 +#elif defined(__AVR_ATmega161__) +//! This is a little endian architecture. +#define ENDIAN_LITTLE +//! Size of the internal EEPROM +#define EEPROM_SIZE 0x200 +//! Size of the RAM. +#define RAM_SIZE 0x400 +//! Chip ID. +#define CHIP 0x02 +//! External EEPROM ID. +#define ESIZ 0x03 +//! AVR architecture. Needed for assembler. +#define ARCH avr5 +#else +#error Unknown destination platform. +#endif + +#endif /* PPSCS_CONFIG_H */ + diff --git a/targets/Funcard7/drivers/eepromi2c.s b/targets/Funcard7/drivers/eepromi2c.s new file mode 100755 index 0000000000000000000000000000000000000000..e12db7a74c25b5a09130d93f1c05456d17b8dca3 --- /dev/null +++ b/targets/Funcard7/drivers/eepromi2c.s @@ -0,0 +1,299 @@ +; Copyright or © or Copr. 2008, Geoffroy Cogniaux, Simon Duquennoy, +; Thomas Soete +; +; This software is a computer program whose purpose is to design an +; efficient Web server for very-constrained embedded system. +; +; This software is governed by the CeCILL license under French law and +; abiding by the rules of distribution of free software. You can use, +; modify and/ or redistribute the software under the terms of the CeCILL +; license as circulated by CEA, CNRS and INRIA at the following URL +; "http://www.cecill.info". +; +; As a counterpart to the access to the source code and rights to copy, +; modify and redistribute granted by the license, users are provided only +; with a limited warranty and the software's author, the holder of the +; economic rights, and the successive licensors have only limited +; liability. +; +; In this respect, the user's attention is drawn to the risks associated +; with loading, using, modifying and/or developing or reproducing the +; software by the user in light of its specific status of free software, +; that may mean that it is complicated to manipulate, and that also +; therefore means that it is reserved for developers and experienced +; professionals having in-depth computer knowledge. Users are therefore +; encouraged to load and test the software's suitability as regards their +; requirements in conditions enabling the security of their systems and/or +; data to be ensured and, more generally, to use and operate it in the +; same conditions as regards security. +; +; The fact that you are presently reading this means that you have had +; knowledge of the CeCILL license and that you accept its terms. +; + +; Parts of code from SOSSE: + +; Simple Operating system for Smart cards +; Copyright (C) 2002 Matthias Bruestle <m@mbsks.franken.de> +; +; 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 + +#include "at_config.h" + +.arch avr2; should be replace by ARCH + +DDRB=0x17 +EE_SCL=1 +EE_SDA=0 +PINB=0x16 +PORTB=0x18 + .text + .global xewrt, fxeread, fxeread_next +XEAddr: + rcall XEStrt + clc + ldi r19,0xA0 + rcall XEEOut + rcall XE0Bit + mov r19,r31 + rcall XEEOut + rcall XE0Bit + mov r19,r30 + rcall XEEOut + rcall XE0Bit + ret + +; address r25:r24 +; byte r23(=0):r22 +xewrt: + push r29 + push r28 + push r16 + push r1 + push r0 + mov r31,r25 + mov r30,r24 +; Start +; address r31:r30 +; result XE(Z+) = r22 +; rcall xereadlocal +; cp r0,r22 +; breq dontwrite + rcall XE1Bit + rcall XEStop + ldi r28,lo8(-1) + ldi r29,hi8(-1) + sts last_addr,r28 + sts (last_addr)+1,r29 + rcall XEAddr + mov r19,r22 + rcall XEEOut + rcall XE0Bit + rcall XEStop + rcall XEDly +dontwrite: +; Done + pop r0 + pop r1 + pop r16 + pop r28 + pop r29 + ret + +XEDly: + ldi r25,0x20 + mov r1,r25 +avr3B9: + ldi r25,0xFF +avr3BA: + dec r25 + brne avr3BA + dec r1 + brne avr3B9 + ret + +XEStrt: + rcall ClrPB0 + rcall SetPB2 + rcall SetPB0 + rcall ClrPB2 + rcall ClrPB0 + ret + +XEStop: + rcall ClrPB0 + rcall ClrPB2 + rcall SetPB0 + rcall SetPB2 + rcall ClrPB0 + ret + +XEEIn: + clr r0 + ldi r16,0x08 + rcall SetPB2 + rcall PB2In +avr3CF: + rcall SetPB0 + sbic PINB,EE_SDA + rjmp avr3D5 + clc + rol r0 + rjmp avr3D7 +avr3D5: sec + rol r0 +avr3D7: rcall ClrPB0 + dec r16 + brne avr3CF + rcall PB2Out + ret + +XEEOut: + ldi r16,0x08 + mov r0,r19 +avr3DE: + clc + rol r0 + brlo avr3E4 + rcall ClrPB2 + rcall ClkPls + rjmp avr3E6 +avr3E4: + rcall SetPB2 + rcall ClkPls +avr3E6: + dec r16 + brne avr3DE + ret + +XE1Bit: rcall SetPB2 + rcall ClkPls + ret + +XE0Bit: + rcall ClrPB2 + rcall ClkPls + ret + +ClkPls: + rcall SetPB0 + rcall ClrPB0 + ret + +SetPB2: + sbi PORTB,EE_SDA + rjmp PBExit + +ClrPB2: + cbi PORTB,EE_SDA + rjmp PBExit + +SetPB0: + sbi PORTB,EE_SCL + rjmp PBExit + +ClrPB0: + cbi PORTB,EE_SCL + rjmp PBExit + +PB2Out: + sbi DDRB,EE_SDA + rjmp PBExit + +PB2In: + cbi DDRB,EE_SDA + rjmp PBExit + +PBExit: + nop + nop + nop + ret + +; address r25:r24 +; result r25(=0):r24 +fxeread: + push r29 + push r28 + push r16 + push r1 + push r0 + mov r31,r25 + mov r30,r24 +; Start + lds r28,last_addr + lds r29,(last_addr)+1 + adiw r28,1 + cp r28,r24 + cpc r29,r25 + brne new_addr + sts last_addr,r28 + sts (last_addr)+1,r29 + rcall fxeread_local_next + rjmp fxeread_end +new_addr: + sts last_addr,r24 + sts (last_addr)+1,r25 + rcall fxeread_local +fxeread_end: +; Done + clr r25 + mov r24,r0 + pop r0 + pop r1 + pop r16 + pop r28 + pop r29 + ret + +fxeread_next: + push r29 + push r28 + push r16 + push r1 + push r0 +; Start + lds r28,last_addr + lds r29,(last_addr)+1 + adiw r28,1 + sts last_addr,r28 + sts (last_addr)+1,r29 + rcall fxeread_local_next +; Done + clr r25 + mov r24,r0 + pop r0 + pop r1 + pop r16 + pop r28 + pop r29 + ret + +fxeread_local: + rcall XE1Bit + rcall XEStop + rcall XEAddr + rcall XEStrt + clc + ldi r19,0xA1 + rcall XEEOut + rcall XE0Bit + rcall XEEIn + ret + +fxeread_local_next: + rcall XE0Bit + rcall XEEIn + ret diff --git a/targets/Funcard7/drivers/hardware.c b/targets/Funcard7/drivers/hardware.c new file mode 100755 index 0000000000000000000000000000000000000000..d281861df34288aa88756dcd676305c263c339d5 --- /dev/null +++ b/targets/Funcard7/drivers/hardware.c @@ -0,0 +1,241 @@ +/* +* Copyright or © or Copr. 2008, Geoffroy Cogniaux, Simon Duquennoy, +* Thomas Soete +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "at_config.h" +#include "types.h" +#include "target.h" + +/* Structures used for efficient casts */ +union word_dword_u { + uint16_t word[2]; + uint32_t dword; +}; +union byte_dword_u { + uint8_t byte[4]; + uint32_t dword; +}; +union byte_word_u { + unsigned char byte[2]; + uint16_t word; +}; + +/* T0 protocol C wrappers */ +//io.s +extern void sendbyteT0(unsigned char b); +extern unsigned char dropByteT0(void); +extern void sendFbyteT0(unsigned char b); +extern unsigned char recFbyteT0(void); +//eepromi2c.s +extern void xewrt(uint16_t *addr, unsigned char value); +extern uint8_t fxeread(uint8_t* addr); +extern uint8_t fxeread_next(); + +#define T0_sendFAck(header) sendFbyteT0((header)[1]) +#define T0_sendFCAck(header) sendFbyteT0(~(header)[1]) + +/* APDU definitions used by smews */ +#define CLA_PROP 0x80 +#define INS_SEND_PACKET 0x01 +#define INS_RECV_PACKET 0x02 + +/* Wrappers on APDU header struct */ +unsigned char header[5]; +#define H_CLA(header) ((header)[0]) +#define H_INS(header) ((header)[1]) +#define H_P1(header) ((header)[2]) +#define H_P2(header) ((header)[3]) +#define H_LE(header) ((header)[4]) + +uint16_t last_addr = -1; + +static uint8_t max_read; +static uint8_t curr_read; + +static uint8_t nwrite; +static uint16_t segment_left; +#define APDU_SIZE 255 + +#define PTS_0 0xff +#define PTS_1 0x10 +#define PTS_2 0x08 +#define PTS_3 0xE7 + +/* unallows CONST_VAR to target the zero address */ +unsigned char null_eeprom_ptr EEMEM = 0xFF; + +#define ATR_LEN_ADDR 16 +static unsigned char atr[] EEMEM = { + 0x3B, //TS - direct convention + 0xBA, //T0 -TA1/ TB1/TD1 follows, historical bytes, + 0x08, //Fi=372 - Di = 12 (31clocks/bit) 115200 Baud + 0x00, //TB1 - no Vpp, deprecated + 0x40, //TD1 - TC2 follows + 0x20, //TC2 - WI 32 : T0 specific=>Waiting time + 0x53, // - SMEWS : (On Smart Card) + 0x4D, + 0x45, + 0x57, + 0x53, + YEAR, //add at compilation time + MONTH, //add at compilation time + DAY, //add at compilation time + CHIP, //- Chip type, @see at_config.h + ESIZ, //- External EEPROM size, @see at_config.h +}; + +void T0_sendFWord(uint16_t word) { + sendFbyteT0(word >> 8); + sendFbyteT0(word); +} + +static char check_apdu() { + if((H_CLA(header) & 0xFC) != CLA_PROP ) { + T0_sendFWord(SW_WRONG_CLA); + return 0; + } + if(H_INS(header) > 0x02 ) { + T0_sendFWord(SW_WRONG_INS); + return 0; + } + return 1; +} + +static void get_apdu() { + do { + H_CLA(header) = recFbyteT0(); + H_INS(header) = recFbyteT0(); + H_P1(header) = recFbyteT0(); + H_P2(header) = recFbyteT0(); + H_LE(header) = recFbyteT0(); + } while(!check_apdu()); +} + +void hardware_init(void) { + uint8_t i; + + /* ports init */ + ACSR = 0x80; + DDRA = 0xFF; + DDRB = 0xFF; + DDRC = 0xFF; + DDRD = 0xFF; + PORTA = 0xFF; + PORTB = 0xFF; + PORTC = 0xFF; + PORTD = 0xFF; + + /* Send ATR */ + for( i=0; i < ATR_LEN_ADDR ; i++ ) { + sendbyteT0(CONST_READ_UI8(atr+i)); + } + + dropByteT0(); + dropByteT0(); + dropByteT0(); + dropByteT0(); + sendbyteT0(PTS_0); + sendbyteT0(PTS_1); + sendbyteT0(PTS_2); + sendbyteT0(PTS_3); + + /* initialize state, terminal is the first who talks, so we wait for it */ + get_apdu(); + curr_read = 0; + max_read = H_LE(header); +} + +void init_read() { + T0_sendFWord(SW_OK); + get_apdu(); + curr_read = 0; + max_read = H_LE(header); +} + +unsigned char dev_get(void) { + if(curr_read == max_read) { + init_read(); + } + /* change com direction : ~ACK */ + T0_sendFCAck(header); + curr_read++; + /* explicit recv of data : */ + return recFbyteT0(); +} + +char dev_prepare_output(uint16_t len) { + unsigned char out_size = len > 255 ? 255 : len; + nwrite = 0; + T0_sendFWord(SW_OK | out_size); + segment_left = len - out_size; + + /* initialize write state, terminal is the first who talks, so we wait for it */ + get_apdu(); + /* change com direction */ + T0_sendFAck(header); + + return 1; +} + +unsigned char dev_data_to_read(void) { + return max_read - curr_read > 0 || H_P2(header) > 0; +} + +void dev_put(unsigned char byte) { + sendFbyteT0(byte); + if(++nwrite == APDU_SIZE) + dev_prepare_output(segment_left); +} + +/* extended EEPROM routines */ +uint32_t eeprom_read_dword(const void *addr) { + union byte_dword_u tmp_cast; + tmp_cast.byte[0] = fxeread((uint8_t*)addr); + tmp_cast.byte[1] = fxeread_next(); + tmp_cast.byte[2] = fxeread_next(); + tmp_cast.byte[3] = fxeread_next(); + return tmp_cast.dword; +} + +uint16_t eeprom_read_word(const void *addr) { + union byte_word_u tmp_cast; + tmp_cast.byte[0]= fxeread((uint8_t*)addr); + tmp_cast.byte[1]= fxeread_next(); + return tmp_cast.word; +} + +void eeprom_write_nbytes(void *dst, const unsigned char *src, uint16_t len) { + while( len-- ) { + xewrt(dst++, *src++); + } +} diff --git a/targets/Funcard7/drivers/io.s b/targets/Funcard7/drivers/io.s new file mode 100755 index 0000000000000000000000000000000000000000..52b7087623e9c51f92f6890058adc25a1b7a4348 --- /dev/null +++ b/targets/Funcard7/drivers/io.s @@ -0,0 +1,395 @@ +; Copyright or © or Copr. 2008, Geoffroy Cogniaux, Gilles Grimaud, +; Simon Duquennoy +; +; This software is a computer program whose purpose is to design an +; efficient Web server for very-constrained embedded system. +; +; This software is governed by the CeCILL license under French law and +; abiding by the rules of distribution of free software. You can use, +; modify and/ or redistribute the software under the terms of the CeCILL +; license as circulated by CEA, CNRS and INRIA at the following URL +; "http://www.cecill.info". +; +; As a counterpart to the access to the source code and rights to copy, +; modify and redistribute granted by the license, users are provided only +; with a limited warranty and the software's author, the holder of the +; economic rights, and the successive licensors have only limited +; liability. +; +; In this respect, the user's attention is drawn to the risks associated +; with loading, using, modifying and/or developing or reproducing the +; software by the user in light of its specific status of free software, +; that may mean that it is complicated to manipulate, and that also +; therefore means that it is reserved for developers and experienced +; professionals having in-depth computer knowledge. Users are therefore +; encouraged to load and test the software's suitability as regards their +; requirements in conditions enabling the security of their systems and/or +; data to be ensured and, more generally, to use and operate it in the +; same conditions as regards security. +; +; The fact that you are presently reading this means that you have had +; knowledge of the CeCILL license and that you accept its terms. +; + +; Parts of code from SOSSE: + +; Simple Operating system for Smart cards +; Copyright (C) 2002 Matthias Bruestle <m@mbsks.franken.de> +; +; 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 + +;======================================================================== +; T=0 character I/O routines for 9600bps at 3.58 MHz +;======================================================================== + +#include "at_config.h" + +.arch avr2; should be replace by ARCH +IO_PIN=6 +PINB=0x16 +DDRB=0x17 +PORTB=0x18 + .text + .global dropByteT0, sendbyteT0, sendFbyteT0, recFbyteT0 + .comm direction,1,1 +;======================================================================== +; Wait loops. +; Wait t17*3+7 cycles +delay: + dec r22 ; 1 + brne delay ; 1/2 + ret ; 4 + +delay1etu: + ldi r22, 121 ; 1 + rjmp delay ; 2 + +;======================================================================== +; Receive a byte with T=0 error correction. +; result r25(=0):r24 +dropByteT0: +; push r23 ; 2 - getbit +; push r22 ; 2 - delay +; push r21 ; 2 - loop counter +; push r20 ; 2 - parity counter + + ; Set direction bit, to indicate, that we received a byte + ldi r22, 1 + sts direction,r22 + + ; Setup IN direction + cbi DDRB, 6 ; 2 + cbi PORTB, 6 ; 2 + +; Wait for start bit. +waitforstart: + ; Bit begins here. + sbic PINB, IO_PIN ; 1/2! + rjmp waitforstart ; 2/0 + sbic PINB, IO_PIN ; 1/2! - Recheck for spike + rjmp waitforstart ; 2/0 + + ldi r23, 5 ; 1 +delay_loop: + ldi r22, 245 ; 1 + rcall delay ; 742 + dec r23 ; 1 + brne delay_loop ; 1/2 + +; pop r20 ; 2 - parity counter +; pop r21 ; 2 - loop counter +; pop r22 ; 2 - delay +; pop r23 ; 2 - getbit + ret + +;======================================================================== +; Receive a fast byte with T=0 error correction. +; result r25(=0):r24 +recFbyteT0: +; push r23 ; 2 - getbit +; push r22 ; 2 - delay +; push r21 ; 2 - loop counter +; push r20 ; 2 - parity counter + + ; Set direction bit, to indicate, that we received a byte + ldi r22, 1 + sts direction,r22 + +restartrecFbyte: + ; Setup IN direction + cbi DDRB, 6 ; 2 + cbi PORTB, 6 ; 2 + +; Wait for start bit. +waitforstartF: + ; Bit begins here. + sbic PINB, IO_PIN ; 1/2! + rjmp waitforstartF ; 2/0 + sbic PINB, IO_PIN ; 1/2! - Recheck for spike + rjmp waitforstartF ; 2/0 + ; Sample start bit + clr r24 ; 1 + clr r25 ; 1 - Clear zero byte for ADC + nop + nop + nop ; 3 + rcall getFbit ; 3 (16bit PC) + ;brcs waitforstart ; 1/2 - Go on, even if not valid a start bit? + nop ; 1 - For brcs +; Receive now 9 bits + ldi r21, 0x09 ; 1 + clr r20 ; 1 + ldi r22, 66 ; 1 + nop ; 1 + nop ; 1 +rnextbitF: + rcall wait10clock ; 3 + rcall getFbit ; 3 + add r20, r23 ; 1 + clc ; 1 + sbrc r23, 0 ; 1/2 + sec ; 1/0 + ror r24 ; 1 + ldi r22, 65 ; 1 + dec r21 ; 1 + brne rnextbitF ; 1/2 +; Check parity + rol r24 ; 1 - We've rotated one to much + sbrc r20, 0 ; 1/2 + rjmp regetbyteF ; 2/0 + + ; Wait half etu + ldi r22, 3 ; 1 + rcall delay ; 16 + nop ; 1 + + clr r25 +; pop r20 ; 2 - parity counter +; pop r21 ; 2 - loop counter +; pop r22 ; 2 - delay +; pop r23 ; 2 - getbit + ret + +wait11clock: + nop ; 1 +wait10clock: + nop ; 1 + nop ; 1 + nop ; 1 + ret ; 4 + +regetbyteF: + ; Wait half etu + ldi r22, 3 ; 1 + rcall delay ; 16 + nop ; 1 + ; Set OUT direction + sbi DDRB, 6 ; 2 + ; Signal low + cbi PORTB, 6 ; 2 + ldi r22, 15 ; 1 + rcall delay ; 52 + nop ; 1 -about 1.5 etu + rjmp restartrecFbyte ; 2 +;======================================================================== +; Read a bit. +; Uses r23, r25 +; Returns bit in r23.0. +; 3 cycles before first bit +; 6 cycles after last bit. +getFbit: + clr r23 ; 1 + clc ; 1 + ; At start + 112 cycles + sbic PINB, IO_PIN ; 1/2 + sec ; 1/0 + adc r23, r25 ; 1 + ret ; 4 (with 16bit PC) +;======================================================================== +; Send a byte with T=0 error correction. +; byte r25(=0):r24 +sendbyteT0: +; push r22 ; 2 - delay +; push r23 ; 2 - parity counter + + lds r22,direction + tst r22 + breq resendbyteT0 + rcall delay1etu ; + rcall delay1etu ; + ; Clear direction bit, to indicate, that we sent a byte + ldi r22, 0 + sts direction,r22 + +resendbyteT0: + ; Set OUT direction + sbi PORTB, 6 ; 2 + sbi DDRB, 6 ; 2 + ; Send start bit + cbi PORTB, IO_PIN ; 2 + ldi r22, 119 ; 1 + rcall delay ; 364 + ; Send now 8 bits + ldi r25, 0x08 ; 1 + clr r23 ; 1 +snextbit: + ror r24 ; 1 + brcs sendbit1 ; 1/2 + cbi PORTB, IO_PIN ; 2 + rjmp bitset ; 2 +sendbit1: + sbi PORTB, IO_PIN ; 2 + inc r23 ; 1 +bitset: + ldi r22, 118 ; 1 + rcall delay ; 361 + nop ; 1 + dec r25 ; 1 + brne snextbit ; 1/2 + ; Send parity + sbrc r23, 0 ; 1/2 + rjmp sendparity1 ; 2 + nop ; 1 + nop ; 1 + cbi PORTB, IO_PIN ; 2 + rjmp delayparity ; 2 +sendparity1: + nop ; 1 + sbi PORTB, IO_PIN ; 2 + nop ; 1 + nop ; 1 +delayparity: + ldi r22, 112 ; 1 + rcall delay ; 343 + ; Stop bit + sbi PORTB, IO_PIN ; 2 + ldi r22, 119 ; 1 + rcall delay ; 364 + ; Set IN direction + cbi DDRB, 6 ; 2 + cbi PORTB, 6 ; 2 + ; Look for error signal + clc ; 1 + sbic PINB, IO_PIN ; 1/2 + sec ; 1/0 + brcs retsendbyteT0 ; 1/2 + ; Resend byte + ; Bring byte to starting position + ror r24 ; 1 + ; Wait for end of error signal +waitforendoferror: + sbic PINB, IO_PIN ; 1/2! + rjmp waitforendoferror ; 2/0 + ; Wait then a half etu + ldi r22, 58 ; 1 + rcall delay ; 181 + rjmp resendbyteT0 ; 2 + ; return +retsendbyteT0: + ldi r22, 116 ; 1 + rcall delay ; 355 +; pop r23 ; 2 - parity counter +; pop r22 ; 2 - delay + ret ; 4 +;======================================================================== + +;======================================================================== +; Send a byte with T=0 error correction. +; byte r25(=0):r24 +sendFbyteT0: +; push r22 ; 2 - delay +; push r23 ; 2 - parity counter + + lds r22,direction + tst r22 + breq resendFbyteT0 + ldi r22, 18 ; 1 + rcall delay ; 61 + ; Clear direction bit, to indicate, that we sent a byte + ldi r22, 0 + sts direction,r22 + +resendFbyteT0: + ; Set OUT direction + sbi PORTB, 6 ; 2 + sbi DDRB, 6 ; 2 + ; Send start bit + cbi PORTB, IO_PIN ; 2 + ldi r22, 5 ; 1 + rcall delay ; 22 + nop ; 1 + ; Send now 8 bits + ldi r25, 0x08 ; 1 + clr r23 ; 1 +sFnextbit: + ror r24 ; 1 + brcs sendFbit1 ; 1/2 + cbi PORTB, IO_PIN ; 2 + rjmp bitFset ; 2 +sendFbit1: + sbi PORTB, IO_PIN ; 2 + inc r23 ; 1 +bitFset: + ldi r22, 5 ; 1 + rcall delay ; 22 + dec r25 ; 1 + brne sFnextbit ; 1/2 + ; Send parity + sbrc r23, 0 ; 1/2 + rjmp sendFparity1 ; 2 + nop ; 1 + nop ; 1 + cbi PORTB, IO_PIN ; 2 + rjmp delayFparity ; 2 +sendFparity1: + nop ; 1 + sbi PORTB, IO_PIN ; 2 + nop ; 1 + nop ; 1 +delayFparity: + ldi r22, 5 ; 1 + rcall delay ; 22 + ; Stop bit + sbi PORTB, IO_PIN ; 2 + ldi r22, 5 ; 1 + rcall delay ; 22 + nop ; 1 + ; Set IN direction + cbi DDRB, 6 ; 2 + cbi PORTB, 6 ; 2 + ; Look for error signal + clc ; 1 + sbic PINB, IO_PIN ; 1/2 + sec ; 1/0 + brcs retsendFbyteT0 ; 1/2 + ; Resend byte + ; Bring byte to starting position + ror r24 ; 1 + ; Wait for end of error signal +waitforendofFerror: + sbic PINB, IO_PIN ; 1/2! + rjmp waitforendofFerror ; 2/0 + ; Wait then a half etu + ldi r22, 3 ; 1 + rcall delay ; 16 + nop ; 1 + rjmp resendFbyteT0 ; 2 + ; return +retsendFbyteT0: + rcall wait11clock ; 3 +; pop r23 ; 2 - parity counter +; pop r22 ; 2 - delay + ret ; 4 +;======================================================================== diff --git a/targets/Funcard7/drivers/sw.h b/targets/Funcard7/drivers/sw.h new file mode 100755 index 0000000000000000000000000000000000000000..add300a84520fab6da0a605fbc3f9632e681b739 --- /dev/null +++ b/targets/Funcard7/drivers/sw.h @@ -0,0 +1,59 @@ +/* +* Copyright or © or Copr. 2008, Geoffroy Cogniaux +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef PROTO_ERRNO_H +#define PROTO_ERRNO_H + +#define _DEBUG + +typedef enum { + SW_OK =0x9000, + SW_WRONG_CLA =0x6E00, + SW_WRONG_CONDITION =0x6985, + SW_WRONG_DATA =0x6A80, + SW_WRONG_INS =0x6D00, + SW_WRONG_LE =0x6C00, + SW_WRONG_LEN =0x6700, + SW_WRONG_P1P2 =0x6A86, + SW_WRONG_REFERENCE =0x6B00, + //HOT SPECIAL CONTROL SPICES AND OTHER CHILI DEBUG + SW_CONTROL_OUTPUT =0x9100, + SW_CONTROL_DONE =0x9200, + SW_CONTROL_ERROR =0x9300, + SW_CONTROL_INPUT =0x9400, + SW_CONTROL_READ =0x9500, + SW_CONTROL_DEBUG =0x9600 +} SW; + +#endif /* PROTO_ERRNO_H */ + diff --git a/targets/Funcard7/drivers/target.h b/targets/Funcard7/drivers/target.h new file mode 100755 index 0000000000000000000000000000000000000000..b272491569297ceef514b1cafcb7da9217a07286 --- /dev/null +++ b/targets/Funcard7/drivers/target.h @@ -0,0 +1,112 @@ +/* +* Copyright or © or Copr. 2008, Geoffroy Cogniaux +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __TARGET_H__ +#define __TARGET_H__ + +#include <avr/io.h> +#include "at_config.h" +#include "sw.h" +#define NULL ((void*)0) +#define EEMEM __attribute__((section(".eeprom"))) + +extern void hardware_init(void); +extern unsigned char dev_get(void); +extern void dev_put(unsigned char byte); +extern char dev_prepare_output(uint16_t len); +extern unsigned char dev_data_to_read(void); +extern void init_read(); + +/* Drivers interface */ + +#define HARDWARE_INIT hardware_init() +#define HARDWARE_STOP +#define TIME_MILLIS 0 +#define DEV_GET(c) {(c) = dev_get();} +#define DEV_PUT(c) dev_put(c) +#define DEV_PREPARE_OUTPUT(length) if(!dev_prepare_output(length)) return; +#define DEV_OUTPUT_DONE +#define DEV_DATA_TO_READ dev_data_to_read() +#define DEV_WAIT init_read() + +/* Smews states */ + +#define SMEWS_WAITING +#define SMEWS_SENDING +#define SMEWS_RECEIVING +#define SMEWS_ENDING + +/* Const and persistent access macros */ + +#define CONST_VOID_P_VAR const void* +#define CONST_VAR(type,name) type const name EEMEM +#define PERSISTENT_VAR(type,name) CONST_VAR(type,name) + +extern uint8_t fxeread(uint8_t* addr); +extern uint32_t eeprom_read_dword (const void *addr); +extern uint16_t eeprom_read_word (const void *addr); + +#define CONST_READ_UI8(x) ((uint8_t)fxeread((uint8_t*)(x))) +#define CONST_READ_UI16(x) eeprom_read_word ((x)) +#define CONST_READ_UI32(x) eeprom_read_dword((x)) +#define CONST_READ_ADDR(x) ((void*)(eeprom_read_word((x)))) + +#define CONST_UI8(x) CONST_READ_UI8(&(x)) +#define CONST_UI16(x) CONST_READ_UI16(&(x)) +#define CONST_UI32(x) CONST_READ_UI32(&(x)) +#define CONST_ADDR(x) CONST_READ_ADDR(&(x)) + +extern void eeprom_write_nbytes(void *dst, const unsigned char *src, uint16_t len); +#define CONST_WRITE_NBYTES(dst,src,len) eeprom_write_nbytes(dst,src,len) + +/* Endianness */ +#define ENDIANNESS LITTLE_ENDIAN + +/* Context switching */ +/* To be done */ + +#define BACKUP_CTX(sp) + +#define RESTORE_CTX(sp) + +#define PUSHREGS + +#define POPREGS + +/* Smews configuration */ + +#define OUTPUT_BUFFER_SIZE 32 +#define STACK_SIZE 32 +#define ALLOC_SIZE 128 + +#endif /* __TARGET_H__ */ diff --git a/targets/GBA/SConscript b/targets/GBA/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..dd49da4a466852dd19c5be132118c777abfa4474 --- /dev/null +++ b/targets/GBA/SConscript @@ -0,0 +1,47 @@ +# Copyright or c or Copr. 2008, Simon Duquennoy +# +# Author e-mail: simon.duquennoy@lifl.fr +# +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + + +import os +import sys + +Import('env binDir projectName elfName targetDir') + +env.Replace(CC = 'arm-agb-elf-gcc') +env.Replace(AS = 'arm-agb-elf-as') +env.Replace(AR = 'arm-agb-elf-ar') +env.Replace(RANLIB = 'arm-agb-elf-ranlib') +env.Append(LINKFLAGS = '-nostartfiles -static -Wl -T ' + os.path.join(targetDir,'lnkscript')) + +binaryName = projectName + '.bin' +env.Command(binaryName, elfName, ['arm-agb-elf-objcopy -O binary $SOURCE $TARGET','gbafix $TARGET']) diff --git a/targets/GBA/drivers/crt0.s b/targets/GBA/drivers/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..1c13862ac70d30a855bbbe479e3e62a366348717 --- /dev/null +++ b/targets/GBA/drivers/crt0.s @@ -0,0 +1,689 @@ +@******************************************************************************* +@* _ _____ _____ * +@* | | | _ |/ ___| * +@* ___ _ __| |_| |/' |\ `--. * +@* / __| '__| __| /| | `--. \ * +@* | (__| | | |_\ |_/ //\__/ / * +@* \___|_| \__|\___(_)____/ * +@* * +@* * +@******************************************************************************* +@* crt0.S v1.28 by Jeff Frohwein * +@******************************************************************************* + +@ v1.0 - Original release +@ v1.1 - Added proper .data section support +@ v1.2 - Added support for c++, overlays, interrupts, and +@ far calls (__FarFunction & __FarProcedure). +@ - Some ideas from Jason Wilkins & Mike Heckenbach. +@ v1.21- Killed the dumb test bug left in the code. +@ v1.22- Killed dumb bug "numero dos" in multiple interrupts routine. Thanks Mike H. :) +@ v1.23- Now correctly handles zero length .bss section. +@ v1.24- Loop back to start_vector now works if main {} exits. +@ v1.25- __FarProcedure now works. It was missing a .thumb_func directive. +@ v1.26- Added missing Serial Interrupt processing to __MultipleInterrupts section. +@ Added __FastInterrupt option for minimal interrupt processing. +@ Optimized __MultipleInterrupts section to save 4 bytes of stack space. +@ Added __ISRinIWRAM option that puts interrupt processing in IWRAM by default. +@ Options passed to main() or AgbMain() are now set to 0. (Thanks to DarkFader) +@ v1.27- Even though it might not cause any problems for anyone "as is", +@ changed .SECTION .iwram to .SECTION .iwram,"ax",%progbits +@ just to be safe. That is the more correct description/definition. +@ Added warning below about small default interrupt stack. +@ v1.28- Added force alignment (align 4) to CopyMem & ClearMem to +@ prevent infinite loops in cases where LD (buggy?) fails +@ to align(4). (Thanks to Mark Price & others.) +@ +@ This file is released into the public domain for commercial +@ or non-commercial usage with no restrictions placed upon it. + + .TEXT + +@ Comment out the next line ONLY if you plan to never support +@ multiboot mode and want to save a few bytes by removing +@ multiboot support code. Otherwise, leave it alone. It wont +@ disturb code designed to run only on flash carts. +@ +@ The normal way to enable generating code that works with +@ both multiboot and flash carts is to add the following to +@ your C code in your main project file AS A GLOBAL VARIABLE: +@ +@ #define MULTIBOOT int __gba_multiboot; +@ Then use it like this : MULTIBOOT +@ +@ IT MUST BE A GLOBAL VARIABLE OR IT WILL NOT WORK! +@ If this variable is not defined somewhere in your project +@ then code will be generated to run out of ROM instead of +@ EXRAM. The value of this variable is not important. + + .equ __MultiBootInclude, 1 + +@ If you are compiling for multiboot dedicated (will not +@ run in a cart) code then uncomment the following. Normally +@ you should leave this commented out so that a multiboot +@ image will run in a cart as well (by copying from ROM to RAM). +@ +@ This sets the maker code to "MB " which is a key that +@ some emulators look for to know to load the rom image +@ at 0x2000000 instead of the standard 0x8000000. + + .equ __MultibootDedicated, 1 + +@ There are two methods for clearing memory and +@ copying appropriate setup data. The fast & bulky +@ method is GBA DMA copy/clear but some emulators +@ do not accurately do DMA. If you have an inaccurate +@ emulator or want to conserve ROM space then comment +@ out the following line. There is not much advantage +@ gained by doing DMA copy/clear. + +@ .equ __DMACopyClear, 1 + +@ Uncomment the following line to support C++ development. +@ You also need to name your main C function the following: +@ int main (void) ...instead of... int AgbMain (void) +@ Doing so will cause ~5500 bytes of c++ support code to be +@ linked in with your project so do not enable c++ support +@ unless you plan to use it. + +@ .equ __CPPSupport, 1 + +@ Comment out the following line to disable interrupt support +@ in your code and to save some space in this file. + +.equ __InterruptSupport, 1 + + +@ Comment out the following line to put interrupt support in +@ ROM instead of IWRAM. Interrupt support in ROM will slow +@ down interrupt execution and has no advantage other than +@ saving a little bit of IWRAM. + +@ .equ __ISRinIWRAM, 1 + +@ NOTE: Only ONE of the following 3 interrupt options may be +@ uncommented. Also, __InterruptSupport above must be uncommented +@ for any of the following to have an effect. +@ +@ __FastInterrupts +@ Uncomment this line for minimal interrupt processing. +@ This allows 160 bytes of interrupt stack space with the +@ default lnkscript. +@ +@ __SingleInterrupts +@ Uncomment this line if you wish to use a table of function +@ pointers to process specific interrupts. This allows 160 +@ bytes of interrupt stack space with the default lnkscript. +@ +@ __MultipleInterrupts +@ Uncomment this line to allow multiple-interrupts-at-once +@ support. If you have several interrupts where one can +@ occur while another is being serviced then you need to +@ enable this option. This option uses the main stack instead +@ of the interrupt stack so you have access to a larger stack. + +@ .equ __FastInterrupts, 1 + .equ __SingleInterrupts, 1 +@ .equ __MultipleInterrupts, 1 + + +@ Uncomment the following line to disable sound and enter an +@ infinite loop if cart is removed during game play. You +@ must have the cart interrupt enabled for this to work and +@ __ISRinIWRAM, above, must be enabled (not commented out.) + +@ .equ __HandleCartInterrupt, 1 + +@ The following prevents IRQ stack overflow by switching to +@ System mode (User stack) when handling multiple interrupts. +@ To force use of IRQ stack only, comment out the following line. + + .equ __SwitchToUserStack, 1 + +@ !!!! NOTE: THE COPY ROUTINES IN THIS FILE WORK ON 4 BYTE +@ BOUNDARIES. YOUR LINKER SCRIPT MUST ALIGN SECTION STARTS +@ AND SECTION ENDS FOR SECTIONS THAT GET COPIED TO RAM WITH +@ ALIGN(4) !!!! + + .GLOBAL _start +_start: + .ALIGN + .CODE 32 + @ Start Vector + + b rom_header_end + + @ Nintendo Logo Character Data (8000004h) + .fill 156,1,0 + + @ Game Title (80000A0h) + .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + .byte 0x00,0x00,0x00,0x00 + + .ifdef __MultibootDedicated + @ Game Code (80000ACh) + .ascii "MB " + .else + @ Game Code (80000ACh) + .byte 0x00,0x00,0x00,0x00 + .endif + + @ Maker Code (80000B0h) + .byte 0x30,0x31 + + @ Fixed Value (80000B2h) + .byte 0x96 + + @ Main Unit Code (80000B3h) + .byte 0x00 + + @ Device Type (80000B4h) + .byte 0x00 + + @ Unused Data (7Byte) (80000B5h) + .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00 + + @ Software Version No (80000BCh) + .byte 0x00 + + @ Complement Check (80000BDh) + .byte 0xf0 + + @ Checksum (80000BEh) + .byte 0x00,0x00 + + .ALIGN + .ARM @ ..or you can use CODE 32 here + +rom_header_end: + b start_vector @ This branch must be here for proper + @ positioning of the following header. + @ DO NOT REMOVE IT. + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ The following reserved bytes are used if the code is compiled for @ +@ multiboot mode. It does not hurt anything to leave this header in +@ even if the code is not compiled for multiboot. The GBA BIOS will +@ auto-patch the first two bytes with 0x03 and 0x01, respectively, +@ before running any code if it is executed as multiboot. +@ + +@ The following two bytes are included even for non-multiboot supporting +@ builds to guarantee that any generic library code that depends on them +@ will still be functional. + + .GLOBAL __boot_method, __slave_number + +__boot_method: + .byte 0 @ boot method (0=ROM boot, 3=Multiplay boot) +__slave_number: + .byte 0 @ slave # (1=slave#1, 2=slave#2, 3=slave#3) + + .ifdef __MultiBootInclude + + .byte 0 @ reserved + .byte 0 @ reserved + .word 0 @ reserved + .word 0 @ reserved + .word 0 @ reserved + .word 0 @ reserved + .word 0 @ reserved + .word 0 @ reserved + .endif +@ @ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +@@@@@@@@@@@@@@@@@@@@@@ +@ Reset @ +@@@@@@@@@@@@@@@@@@@@@@ + + .GLOBAL start_vector + .ALIGN + .ARM @ ..or you can use CODE 32 here +start_vector: + mov r0, #0x12 @ Switch to IRQ Mode + msr cpsr, r0 + ldr sp,=__sp_irq @ Set SP_irq + mov r0, #0x1f @ Switch to System Mode + msr cpsr, r0 + ldr sp,=__sp_usr @ Set SP_usr + +@ Enter Thumb mode + adr r0,1f + 1 @ add r0,pc,#1 also works here + @ for those that want to conserve labels. + bx r0 + + .THUMB @ ..or you can use .CODE 16 here +1: + + .ifdef __InterruptSupport + ldr r1, =__intr_vector_buf @ Set Interrupt Address + ldr r0, =intr_main + str r0, [r1] + .endif + + .ifdef __MultiBootInclude + +@ *** Multiboot Copy Routine *** +@ Check the Program Counter to see if code is running +@ at 0x2000000 or 0x8000000. If it is running at 0x8000000 +@ then copy 256K bytes of it to 0x2000000 and then branch +@ to 0x2000000. +@ The reason for all this is to allow a program to be used +@ "as is" with an flash cart/emulator or with an MBV2-style +@ multiboot cable. +@ NOTE: You can also detect if this ROM is running from +@ 0x2000000 by checking the multiboot header above. + + ldr r0,=__text_start + lsl r0,#5 @ Was code compiled at 0x08000000 or higher? + bcs DoEWRAMClear @ yes, you can not run it in external WRAM + +@ Make sure we are in ExWRAM + + mov r0,pc + lsl r0,#5 @ Are we running from ROM (0x8000000 or higher) ? + bcc SkipEWRAMClear @ No, so no need to do a copy. + +@ We were started in ROM, silly emulators. :P +@ So we need to copy to ExWRAM. + + mov r3,#0x40 + lsl r3,#12 @ r3 = 0x40000 + lsl r2,r3,#7 @ r2 = 0x2000000 + mov r6,r2 @ r6 = 0x2000000 + lsl r1,r2,#2 @ r1 = 0x8000000 + + bl CopyMem + +@ Jump to the code to execute + + bx r6 + .endif + +DoEWRAMClear: +@ Clear External WRAM to 0x00 + + mov r1,#0x40 + lsl r1,#12 @ r1 = 0x40000 + lsl r0,r1,#7 @ r0 = 0x2000000 + bl ClearMem + +SkipEWRAMClear: +@ ldr r0,=AgbMain +@ bx r0 + +@ Clear Internal WRAM to 0x00 + mov r0,#3 + lsl r0,#24 @ r0 = 0x3000000 + ldr r1,=__sp_usr_offset - 16 + bl ClearMem + + .ifdef __MultiBootInclude +@ Clear BSS section to 0x00 +@ (Sometimes BSS may be in External WRAM) + ldr r0,=__bss_start + ldr r1,=__bss_end + sub r1,r0 + bl ClearMem + .endif + +@ Copy initialized data (data section) from LMA to VMA (ROM to RAM) + ldr r1,=__data_lma + ldr r2,=__data_start + ldr r4,=__data_end + bl CopyMemChk + +@ Copy internal work ram (iwram section) from LMA to VMA (ROM to RAM) + ldr r1,=__iwram_lma + ldr r2,=__iwram_start + ldr r4,=__iwram_end + bl CopyMemChk + +@ Copy internal work ram overlay 0 (iwram0 section) from LMA to VMA (ROM to RAM) + ldr r2,=__load_stop_iwram0 + ldr r1,=__load_start_iwram0 + sub r3,r2,r1 @ Is there any data to copy? + beq CIW0Skip @ no + + ldr r2,=__iwram_overlay_start + bl CopyMem +CIW0Skip: + +@ Copy external work ram (ewram section) from LMA to VMA (ROM to RAM) + ldr r1,=__ewram_lma + ldr r2,=__ewram_start + ldr r4,=__ewram_end + bl CopyMemChk + +@ Copy external work ram overlay 0 (ewram0 section) from LMA to VMA (ROM to RAM) + ldr r2,=__load_stop_ewram0 + ldr r1,=__load_start_ewram0 + sub r3,r2,r1 @ Is there any data to copy? + beq CEW0Skip @ no + + ldr r2,=__ewram_overlay_start + bl CopyMem +CEW0Skip: + +@ Jump to user code + + mov r0,#0 @ int argc + mov r1,#0 @ char *argv[] + + ldr r3,=start_vector + mov lr,r3 @ Set start_vector as return address + +.ifdef __CPPSupport + ldr r3,=main +.else + ldr r3,=main +.endif + bx r3 + + + .GLOBAL __FarFunction,__FarProcedure + .THUMB_FUNC +__FarFunction: + .THUMB_FUNC +__FarProcedure: + bx r0 + nop + nop @ This nop is here to allow unmapped memory to be used as + @ as a delay of almost 1 sec with a 1 cycle resolution. + @ Read this for technical info: + @ http://www.devrs.com/gba/files/gbadevfaqs.php#RepeatUses + +@ Clear memory to 0x00 if length != 0 +@ r0 = Start Address +@ r1 = Length + +ClearMem: +@ cmp r1,#0 @ Is length zero? +@ beq ClearMX @ yes, exit + + mov r2,#3 @ These commands are used in cases where + add r1,r2 @ the length is not a multiple of 4, + bic r1,r2 @ even though it should be. + + beq ClearMX @ Length is zero so exit + +.ifdef __DMACopyClear + ldr r2,reg_base + lsr r1,#2 @ r1 = (length/4) & 0xffff + + adr r3,fill_val + str r3,[r2,#0x4] @ Set source address (fill value) + str r0,[r2,#0x8] @ Set destination address (fill dest address) + strh r1,[r2,#0xc] @ Set DMA length + ldr r1,=0x8500 @ dma_clrb + strh r1,[r2,#0xe] @ Start DMA +.else + mov r2,#0 +ClrLoop: + stmia r0!,{r2} + sub r1,#4 + bne ClrLoop +.endif +ClearMX: + bx lr + +@ Copy memory if length != 0 +@ r1 = Source Address +@ r2 = Dest Address +@ r4 = Dest Address + Length + +CopyMemChk: + sub r3,r4,r2 @ Is there any data to copy? +@ beq CIDExit @ no + +@ Copy memory +@ r1 = Source Address +@ r2 = Dest Address +@ r3 = Length + +CopyMem: + mov r0,#3 @ These commands are used in cases where + add r3,r0 @ the length is not a multiple of 4, + bic r3,r0 @ even though it should be. + + beq CIDExit @ Length is zero so exit + +.ifdef __DMACopyClear + ldr r0,reg_base + lsr r3,#2 @ r3 = (length/4) & 0xffff + + str r1,[r0,#0x4] @ Set source address + str r2,[r0,#0x8] @ Set destination address + strh r3,[r0,#0xc] @ Set DMA length + ldr r3,=0x8400 @ dma_copy + strh r3,[r0,#0xe] @ Start DMA +.else +CIDLoop: + ldmia r1!,{r0} + stmia r2!,{r0} + sub r3,#4 + bne CIDLoop +.endif +CIDExit: +If_Undefined_Reference__rename_main_or_AgbMain_to_each_other_in_your_C_file: + bx lr + + .ALIGN + +.ifdef __DMACopyClear +fill_val: .word 0 +reg_base: .word 0x040000d0 +.endif + + .ALIGN + .POOL + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ Interrupt Processing @ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + .ifdef __ISRinIWRAM + .SECTION .iwram,"ax",%progbits + .endif + + .EXTERN IntrTable + .EXTERN InterruptProcess + .GLOBAL intr_main + .ALIGN + .ARM + +@ NOTE: Ifyou copy the following code (start: intr_main - +@ end: intr_main_end) to internal WRAM then do not forget +@ to copy everything between these two labels. The .POOL +@ data must be copied since it is used by intr_main. + +@ NOTE2: If __ISRinIWRAM is defined then the copy to +@ IWRAM is done automatically for you. + + .ifdef __InterruptSupport + + .ifdef __FastInterrupts +intr_main: + ldr r0,=InterruptProcess + bx r0 + .endif + + .ifdef __SingleInterrupts +intr_main: + @ Single interrupts support + mov r3, #0x4000000 @ REG_BASE + ldr r2, [r3,#0x200]! @ Read REG_IE + and r1, r2, r2, lsr #16 @ r1 = IE & IF + ldr r2, =IntrTable + + ands r0, r1, #1 @ V-Blank Interrupt + bne jump_intr + add r2, r2, #4 + ands r0, r1, #2 @ H-Blank Interrupt + bne jump_intr + add r2, r2, #4 + ands r0, r1, #4 @ V Counter Interrupt + bne jump_intr + add r2, r2, #4 + ands r0, r1, #8 @ Timer 0 Interrupt + bne jump_intr + add r2, r2, #4 + ands r0, r1, #0x10 @ Timer 1 Interrupt + bne jump_intr + add r2, r2, #4 + ands r0, r1, #0x20 @ Timer 2 Interrupt + bne jump_intr + add r2, r2, #4 + ands r0, r1, #0x40 @ Timer 3 Interrupt + bne jump_intr + add r2, r2, #4 + ands r0, r1, #0x80 @ Serial Communication Interrupt + bne jump_intr + add r2, r2, #4 + ands r0, r1, #0x100 @ DMA0 Interrupt + bne jump_intr + add r2, r2, #4 + ands r0, r1, #0x200 @ DMA1 Interrupt + bne jump_intr + add r2, r2, #4 + ands r0, r1, #0x400 @ DMA2 Interrupt + bne jump_intr + add r2, r2, #4 + ands r0, r1, #0x800 @ DMA3 Interrupt + bne jump_intr + add r2, r2, #4 + ands r0, r1, #0x1000 @ Key Interrupt + bne jump_intr + add r2, r2, #4 + ands r0, r1, #0x2000 @ Cart Interrupt + + .ifdef __HandleCartInterrupt + strneb r0, [r3, #0x84 - 0x200] @ Stop sound if cart removed (REG_SOUNDCNT_X) +loop: bne loop @ Infinite loop if cart removed + .endif + +jump_intr: + strh r0, [r3, #2] @ IF Clear + ldr r0, [r2] @ Jump to user IRQ process + bx r0 + .endif + + .ifdef __MultipleInterrupts +intr_main: + @ Multiple interrupts support + mov r2, #0x4000000 @ REG_BASE + ldr r3, [r2,#0x200]! @ r2 = IE : r3 = IF|IE + ldrh r1, [r2, #0x8] @ r1 = IME + mrs r0, spsr + stmfd sp!, {r0-r2,lr} @ {spsr, IME, REG_IE, lr} // IF|IE + + mov r0, #1 @ IME = 1 (To permit multiple interrupts if + @ an interrupt occurs) + strh r0, [r2, #0x8] + and r1, r3, r3, lsr #16 @ r1 = IE & IF + ldr r12, =IntrTable + + ands r0, r1, #1 @ V-blank interrupt + bne jump_intr + add r12,r12, #4 + ands r0, r1, #2 @ H-blank interrupt + bne jump_intr + add r12,r12, #4 + ands r0, r1, #4 @ V-counter interrupt + bne jump_intr + add r12,r12, #4 + ands r0, r1, #8 @ Timer 0 interrupt + bne jump_intr + add r12,r12, #4 + ands r0, r1, #0x10 @ Timer 1 interrupt + bne jump_intr + add r12,r12, #4 + ands r0, r1, #0x20 @ Timer 2 interrupt + bne jump_intr + add r12,r12, #4 + ands r0, r1, #0x40 @ Timer 3 interrupt + bne jump_intr + add r12,r12, #4 + ands r0, r1, #0x80 @ Serial Communication Interrupt + bne jump_intr + add r12,r12, #4 + ands r0, r1, #0x100 @ DMA 0 interrupt + bne jump_intr + add r12,r12, #4 + ands r0, r1, #0x200 @ DMA 1 interrupt + bne jump_intr + add r12,r12, #4 + ands r0, r1, #0x400 @ DMA 2 interrupt + bne jump_intr + add r12,r12, #4 + ands r0, r1, #0x800 @ DMA 3 interrupt + bne jump_intr + add r12,r12, #4 + ands r0, r1, #0x1000 @ Key interrupt + bne jump_intr + add r12,r12, #4 + ands r0, r1, #0x2000 @ Cart interrupt + + .ifdef __HandleCartInterrupt + strneb r0, [r2, #0x84 - 0x200] @ Stop sound if cart removed (REG_SOUNDCNT_X) +loop: bne loop @ Infinite loop if cart removed + .endif + +jump_intr: + strh r0, [r2, #2] @ Clear IF + +@ Enable multiple interrupts & switch to system +@ mode if __SwitchToUserStack is defined. + + mrs r3, cpsr + .ifdef __SwitchToUserStack + bic r3, r3, #0xdf @ \__ + orr r3, r3, #0x1f @ / --> Enable IRQ & FIQ. Set CPU mode to System. + .else + bic r3, r3, #0xc0 @ Enable IRQ & FIQ + .endif + msr cpsr, r3 + + ldr r0, [r12] + + stmfd sp!, {lr} + adr lr, IntrRet + bx r0 +IntrRet: + ldmfd sp!, {lr} + +@ Disable multiple interrupts & switch to IRQ Mode +@ if __SwitchToUserStack is defined. + + mrs r3, cpsr + .ifdef __SwitchToUserStack + bic r3, r3, #0xdf @ \__ + orr r3, r3, #0x92 @ / --> Disable IRQ. Enable FIQ. Set CPU mode to IRQ. + .else + orr r3, r3, #0x80 @ Disable IRQ. + .endif + msr cpsr, r3 + + ldmfd sp!, {r0-r2,lr} @ {spsr, IME, REG_IE, lr} //IF|IE +@ strh r3, [r2] @ set IE + strh r1, [r2, #0x8] @ restore REG_IME + msr spsr, r0 @ restore spsr + bx lr + + .endif + + .ALIGN + .POOL @ Ifyou copy the intr_main routine, above, to internal + @ RAM then copy the pool data as well because IntrTable + @ address is stored here. Use intr_main_end as last address+1. +intr_main_end: + .endif + + .ALIGN + .POOL + + + .END + diff --git a/targets/GBA/drivers/hardware.c b/targets/GBA/drivers/hardware.c new file mode 100644 index 0000000000000000000000000000000000000000..fca61dbaba97de47e91bcfda973892dcd63ab21a --- /dev/null +++ b/targets/GBA/drivers/hardware.c @@ -0,0 +1,122 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + + +#include "target.h" +#include "slip_dev.h" + + +struct TIMERCHN { + unsigned short counter; + unsigned short control; +}; + +#define REG_IE (*(volatile unsigned short *) 0x04000200) +#define IT_ENABLE 0x0001 +#define IT_SERIAL 0x0080 +#define IT_TIMER0 0x0008 +#define IT_KEY 0x1000 +#define TIMER ((volatile struct TIMERCHN *) 0x04000100) +#define TIMER_START 0x80 +#define TIMER_IRQ 0x40 +#define TIMER_COUNTUP 0x04 +#define TIMER_SYSCLOCK 0x00 +#define TIMER_SYSCLOCK64 0x01 +#define TIMER_SYSCLOCK256 0x02 +#define TIMER_SYSCLOCK1024 0x03 +#define REG_IME (*(volatile unsigned short *) 0x04000208) +#define REG_IE (*(volatile unsigned short *) 0x04000200) +#define REG_IF (*(volatile unsigned short *) 0x04000202) + + +/* KEYPAD INPUT AND CONTROL REGISTERS */ +#define REG_KEY (*(volatile unsigned short *) 0x4000130) +#define REG_P1CNT (*(volatile unsigned short *) 0x4000132) + +/* KEY PAD DEFINES */ +#define KEY_A 0x0001 +#define KEY_B 0x0002 +#define KEY_SELECT 0x0004 +#define KEY_START 0x0008 +#define KEY_RIGHT 0x0010 +#define KEY_LEFT 0x0020 +#define KEY_UP 0x0040 +#define KEY_DOWN 0x0080 +#define KEY_R 0x0100 +#define KEY_L 0x0200 + +volatile uint32_t global_timer; + +static void ret(void){} +static void _int_timer0(); + +const void * const IntrTable[14] = { + ret, + ret, + ret, + _int_timer0, + ret, + ret, + ret, + _int_serial_com, + ret, + ret, + ret, + ret, + ret, + ret +}; + +static void _int_timer0() { + // Disable this interrupt + REG_IE &= ~IT_TIMER0; + global_timer++; + TIMER[0].counter = 65535 - 16780; + TIMER[0].control = TIMER_START | TIMER_IRQ | TIMER_SYSCLOCK; + REG_IE |= IT_TIMER0; +} + +void hardware_timer_init(void) { + REG_IME = IT_ENABLE; + REG_IE = IT_TIMER0 | IT_SERIAL; + TIMER[0].counter = 65535 - 16780; + TIMER[0].control = TIMER_START | TIMER_IRQ | TIMER_SYSCLOCK; + global_timer = 0; +} + +void hardware_init() { + hardware_timer_init(); + dev_init(); +} diff --git a/targets/GBA/drivers/serial_line.c b/targets/GBA/drivers/serial_line.c new file mode 100644 index 0000000000000000000000000000000000000000..d22fc3adc2f1ead8c4154e20a41c026a8a2ce315 --- /dev/null +++ b/targets/GBA/drivers/serial_line.c @@ -0,0 +1,207 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "types.h" +#include "serial_line.h" + +#define TIMEOUT 50 + +#define REG_IME (*(volatile unsigned short *) 0x04000208) +#define REG_IE (*(volatile unsigned short *) 0x04000200) +#define REG_IF (*(volatile unsigned short *) 0x04000202) + +#define IT_ENABLE 0x0001 +#define IT_SERIAL 0x0080 +#define IT_TIMER0 0x0008 +#define IT_KEY 0x1000 + +// Serial IO Registers +#define REG_SIOCNT *(volatile unsigned short int *)(0x4000128) // Serial control +#define REG_SIODATA8 *(volatile unsigned short int *)(0x400012a) // Serial data +#define REG_RCNT *(volatile unsigned short int *)(0x4000134) // General IO + +// UART settings +#define SIO_USE_UART 0x3000 + +// Baud Rate +#define SIO_BAUD_9600 0x0000 +#define SIO_BAUD_38400 0x0001 +#define SIO_BAUD_57600 0x0002 +#define SIO_BAUD_115200 0x0003 + +#define SIO_CTS 0x0004 +#define SIO_PARITY_ODD 0x0008 +#define SIO_SEND_DATA 0x0010 +#define SIO_RECV_DATA 0x0020 +#define SIO_ERROR 0x0040 +#define SIO_LENGTH_8 0x0080 +#define SIO_USE_FIFO 0x0100 +#define SIO_USE_PARITY 0x0200 +#define SIO_SEND_ENABLE 0x0400 +#define SIO_RECV_ENABLE 0x0800 +#define SIO_REQUEST_IRQ 0x4000 + +#define RCNT_MODE_UART 0x0000 + +#define BAUD_PRESCALE SIO_BAUD_115200 + +volatile serial_line_t serial_line; +enum slip_state_e{slip_in,slip_escaped}; +static enum slip_state_e slip_state; + +/*-----------------------------------------------------------------------------------*/ +void dev_init(void) { + unsigned short GBA_Rate, GBA_Opts; + + GBA_Rate = BAUD_PRESCALE; + + REG_SIODATA8 = 'B'; + REG_RCNT = 0; + REG_SIOCNT = 0; + + GBA_Opts = GBA_Rate | SIO_USE_UART; + + GBA_Opts |= SIO_CTS; + GBA_Opts |= SIO_LENGTH_8; + + REG_SIOCNT = GBA_Opts; + REG_SIOCNT |= SIO_SEND_ENABLE | SIO_RECV_ENABLE; + REG_SIOCNT |= SIO_RECV_DATA | SIO_SEND_DATA; + + REG_SIOCNT |= SIO_REQUEST_IRQ; + + serial_line.writePtr = serial_line.buffer; + serial_line.readPtr = NULL; + slip_state = slip_in; + + return; +} + +/*-----------------------------------------------------------------------------------*/ +void _int_serial_com(){ + REG_IE &= ~IT_SERIAL; + + if(REG_SIOCNT & SIO_RECV_DATA) + return; + + int16_t c = (int16_t) REG_SIODATA8; + + + /* SLIP management */ + switch(c) { + case SLIP_END: + return; + case SLIP_ESC: + slip_state = slip_escaped; + return; + case SLIP_ESC_END: + if(slip_state == slip_escaped) { + slip_state = slip_in; + c = SLIP_END; + } + break; + case SLIP_ESC_ESC: + if(slip_state == slip_escaped) { + slip_state = slip_in; + c = SLIP_ESC; + } + break; + default: + break; + } + + if(serial_line.writePtr != NULL) { + if(serial_line.readPtr == NULL) + serial_line.readPtr = serial_line.writePtr; + *serial_line.writePtr++ = c; + if(serial_line.writePtr == serial_line.buffer + INBUF_SIZE) + serial_line.writePtr = serial_line.buffer; + if(serial_line.writePtr == serial_line.readPtr) + serial_line.writePtr = NULL; + } + + /* Reenable this interrupt */ + REG_IE |= IT_SERIAL; +} + +/*-----------------------------------------------------------------------------------*/ +static inline unsigned char read_byte_from_buffer(void) { + int16_t c; + REG_IE &= ~IT_SERIAL; + + if(serial_line.writePtr == NULL) + serial_line.writePtr = serial_line.readPtr; + c = *serial_line.readPtr++; + if(serial_line.readPtr == serial_line.buffer + INBUF_SIZE) + serial_line.readPtr = serial_line.buffer; + if (serial_line.readPtr == serial_line.writePtr) + serial_line.readPtr = NULL; + + REG_IE |= IT_SERIAL; + return c; +} + +/*-----------------------------------------------------------------------------------*/ +int16_t dev_get(void) { + uint32_t last_time = global_timer; + while(serial_line.readPtr == NULL && global_timer-last_time<TIMEOUT); + if(serial_line.readPtr == NULL) { + return -1; + } else { + return read_byte_from_buffer(); + } +} + + +/*-----------------------------------------------------------------------------------*/ +int32_t serial_line_write(unsigned char value) { + while(REG_SIOCNT & SIO_SEND_DATA); + REG_SIODATA8 = value; + REG_SIOCNT |= SIO_RECV_DATA | SIO_SEND_DATA; + return 1; +} + +/*-----------------------------------------------------------------------------------*/ +void dev_put(unsigned char byte) { + if(byte==SLIP_END){ + serial_line_write(SLIP_ESC); + serial_line_write(SLIP_ESC_END); + } else if(byte==SLIP_ESC){ + serial_line_write(SLIP_ESC); + serial_line_write(SLIP_ESC_ESC); + } else { + serial_line_write(byte); + } +} diff --git a/targets/GBA/drivers/serial_line.h b/targets/GBA/drivers/serial_line.h new file mode 100644 index 0000000000000000000000000000000000000000..c916eecf698442e9f1fd9035dfd13cc265b2312a --- /dev/null +++ b/targets/GBA/drivers/serial_line.h @@ -0,0 +1,63 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __SLIP_DEV_H__ +#define __SLIP_DEV_H__ + +/* Extern functions */ +extern void hardware_init(void); +extern int16_t dev_get(void); +extern void dev_put(unsigned char byte); +extern void dev_init(void); +extern int32_t serial_line_write(unsigned char value); +extern void _int_serial_com(); + +/* SLIP */ +#define SLIP_END 0xC0 /* indicates end of packet */ +#define SLIP_ESC 0xDB /* indicates byte stuffing */ +#define SLIP_ESC_END 0xDC /* ESC ESC_END means END data byte */ +#define SLIP_ESC_ESC 0xDD /* ESC ESC_ESC means ESC data byte */ + +#define INBUF_SIZE 512 +/* Serial line */ +typedef struct { + volatile unsigned char buffer[INBUF_SIZE]; + volatile unsigned char *volatile writePtr; + volatile unsigned char *volatile readPtr; +} serial_line_t; + +extern volatile serial_line_t serial_line; + +#endif diff --git a/targets/GBA/drivers/target.h b/targets/GBA/drivers/target.h new file mode 100644 index 0000000000000000000000000000000000000000..af9c42b86f911341f8122446327510d3c530a5b6 --- /dev/null +++ b/targets/GBA/drivers/target.h @@ -0,0 +1,107 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + + +#ifndef __TARGET_H__ +#define __TARGET_H__ + +/* Types definition */ +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef char int8_t; + +#include "serial_line.h" + +extern volatile uint32_t global_timer; + +/* Drivers interface */ + +#define HARDWARE_INIT hardware_init() +#define HARDWARE_STOP +#define TIME_MILLIS global_timer +#define DEV_GET(c) {(c) = dev_get();} +#define DEV_PUT(c) dev_put(c) +#define DEV_PREPARE_OUTPUT(length) serial_line_write(SLIP_END); +#define DEV_OUTPUT_DONE serial_line_write(SLIP_END); +#define DEV_DATA_TO_READ (serial_line.readPtr != NULL) + +/* Smews states */ + +#define SMEWS_WAITING +#define SMEWS_RECEIVING +#define SMEWS_SENDING +#define SMEWS_ENDING + +/* Const and persistent access macros */ + +#define CONST_VOID_P_VAR const void * +#define CONST_VAR(type,name) type const name +#define PERSISTENT_VAR(type,name) type name + +#define CONST_READ_UI8(x) ((uint8_t)*((uint8_t*)(x))) +#define CONST_READ_UI16(x) ((uint16_t)*((uint16_t*)(x))) +#define CONST_READ_UI32(x) ((uint32_t)*((uint32_t*)(x))) +#define CONST_READ_ADDR(x) ((void*)*((void**)(x))) + +#define CONST_UI8(x) CONST_READ_UI8(&(x)) +#define CONST_UI16(x) CONST_READ_UI8(&(x)) +#define CONST_UI32(x) CONST_READ_UI32(&(x)) +#define CONST_ADDR(x) CONST_READ_ADDR(&(x)) + +/* Endianness */ + +#define ENDIANNESS LITTLE_ENDIAN + +/* Context switching */ +/* To be done */ + +#define BACKUP_CTX(sp) + +#define RESTORE_CTX(sp) + +#define PUSHREGS + +#define POPREGS + +/* Smews configuration */ + +#define OUTPUT_BUFFER_SIZE 256 +#define ALLOC_SIZE 2048 +#define STACK_SIZE 64 + +#endif /* __TARGET_H__ */ diff --git a/targets/GBA/install b/targets/GBA/install new file mode 100755 index 0000000000000000000000000000000000000000..0375d0afd5e4e52e58b33ffb492b396f9f16fb99 --- /dev/null +++ b/targets/GBA/install @@ -0,0 +1 @@ +if2a -f -n -W -v ./bin/GNA/smews.bin diff --git a/targets/GBA/lnkscript b/targets/GBA/lnkscript new file mode 100644 index 0000000000000000000000000000000000000000..0e2bdcdb60d3570d9c420eacb4fc8dc9d75dc341 --- /dev/null +++ b/targets/GBA/lnkscript @@ -0,0 +1,298 @@ +/* Linker Script v1.3 by Jeff Frohwein */ +/* v1.0 - Original release */ +/* v1.1 - Added proper .data section support */ +/* v1.2 - Added support for c++ & iwram overlays */ +/* - Major contributions by Jason Wilkins. */ +/* v1.3 - .ewram section now can be used when */ +/* compiling for MULTIBOOT mode. This fixes */ +/* malloc() in DevKitAdvance which depends */ +/* on __eheap_start instead of end to define*/ +/* the starting location of heap space. */ +/* External global variable __gba_iwram_heap*/ +/* support added to allow labels end, _end, */ +/* & __end__ to point to end of iwram or */ +/* the end of ewram. */ + +/* This file is released into the public domain */ +/* for commercial or non-commercial use with no */ +/* restrictions placed upon it. */ + +/* NOTE!!!: This linker script defines the RAM & */ +/* ROM start addresses. In order for it to work */ +/* properly, remove -Ttext and -Tbss linker */ +/* options from your makefile if they are */ +/* present. */ + +/* You can use the following to view section */ +/* addresses in your .elf file: */ +/* objdump -h file.elf */ +/* Please note that empty sections may incorrectly*/ +/* list the lma address as the vma address for */ +/* some versions of objdump. */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +/* STARTUP(crt0.o) */ +/* SEARCH_DIR(/bin/arm); */ + +/* By default this linker script will generate code */ +/* for flash carts located at 0x8000000. In order to */ +/* generate code that is compiled at 0x2000000 that */ +/* will run on flash carts or in multiboot mode then */ +/* you need to add the following variable to your main */ +/* project file. It's value is NOT important but */ +/* IT MUST BE A GLOBAL VARIABLE OR IT WILL NOT WORK: */ + +/* #define MULTIBOOT int __gba_multiboot; */ +/* Then use it like this: MULTIBOOT */ + +/* By default this linker script will set the labels */ +/* end, _end, & __end__ at the end of ewram. To force */ +/* them to be set to the end of iwram then you need to */ +/* add the following variable to your main */ +/* project file. It's value is NOT important but */ +/* IT MUST BE A GLOBAL VARIABLE OR IT WILL NOT WORK: */ + +/* #define IWRAMHEAP int __gba_iwram_heap; */ +/* Then use it like this: IWRAMHEAP */ + +/* The linker script function "var1 += var2;" sometimes */ +/* reports incorrect values in the *.map file but the */ +/* actual value it calculates is usually, if not always, */ +/* correct. If you leave out the ". = ALIGN(4);" at the */ +/* end of each section then the return value of SIZEOF() */ +/* is sometimes incorrect and "var1 += var2;" appears to */ +/* not work as well. "var1 += var2" style functions are */ +/* avoided below as a result. */ + +/* The linker script MEMORY directive is not used here due */ +/* to the fact that __text_start is not always a fixed value. */ + +__text_start = DEFINED (__gba_multiboot) ? 0x2000000 : 0x8000000; +/* __ewram_start = 0x2000000; */ /* Removed in v1.3 */ +__eheap_end = 0x2040000; +__iwram_start = 0x3000000; +__iheap_end = 0x3008000 - 0x400; +__sp_usr = 0x3008000 - 0x100; +__sp_irq = 0x3008000 - 0x60; +__intr_vector_buf = 0x3008000 - 4; +__sp_usr_offset = __sp_usr - __iwram_start; +__intr_vect_offset = __intr_vector_buf - __sp_usr; + +SECTIONS +{ + .text __text_start : /* ALIGN (4): */ + { + *(EXCLUDE_FILE (*text.iwram*) .text) + *(.text.*) + *(.stub) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + *(.glue_7) + *(.glue_7t) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } = 0xff +/* laddr = ADDR(.text) + SIZEOF(.text); */ + __text_end = .; + + .rodata : + { + *(.rodata) + *all.rodata*(*) + *(.roda) + *(.rodata.*) + *(.gnu.linkonce.r*) + SORT(CONSTRUCTORS) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } = 0xff +/* laddr += SIZEOF(.rodata); */ + + .ctors : + { + /* gcc uses crtbegin.o to find the start of the constructors, so + we make sure it is first. Because this is a wildcard, it + doesn't matter if the user does not actually link against + crtbegin.o; the linker won't look for a file to match a + wildcard. The wildcard also means that it doesn't matter which + directory crtbegin.o is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } = 0 +/* laddr += SIZEOF(.ctors); */ + laddr = ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors); + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } = 0 +/* laddr += SIZEOF(.dtors); */ + laddr = ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors) + SIZEOF(.dtors); + + .eh_frame : + { + KEEP (*(.eh_frame)) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } = 0 +/* laddr += SIZEOF(.eh_frame); */ + + .gcc_except_table : + { + *(.gcc_except_table) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } = 0 +/* laddr += (SIZEOF(.gcc_except_table) + 3) & ~ 3; */ +/* __iwram_lma = laddr; */ + __iwram_lma = (ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors) + SIZEOF(.dtors) + SIZEOF(.eh_frame) + SIZEOF(.gcc_except_table) + 3) & ~ 3; + + .iwram __iwram_start : AT (__iwram_lma) + { + __iwram_start = ABSOLUTE(.) ; + *(.iwram) + *iwram.*(.text) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } = 0xff +/* laddr += SIZEOF(.iwram); */ +/* __data_lma = laddr; */ + __data_lma = ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors) + SIZEOF(.dtors) + SIZEOF(.eh_frame) + SIZEOF(.gcc_except_table) + SIZEOF(.iwram); + + __iwram_end = . ; + + .bss ALIGN(4) : + { + __bss_start = ABSOLUTE(.); + __bss_start__ = ABSOLUTE(.); + *(.dynbss) + *(.gnu.linkonce.b*) + *(COMMON) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } + + __bss_end = . ; + __bss_end__ = . ; + + .data ALIGN(4) : AT (__data_lma) + { + __data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + CONSTRUCTORS + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } = 0xff +/* laddr += SIZEOF(.data); */ +/* __iwram_overlay_lma = laddr; */ + __iwram_overlay_lma = ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors) + SIZEOF(.dtors) + SIZEOF(.eh_frame) + SIZEOF(.gcc_except_table) + SIZEOF(.iwram) + SIZEOF(.data); + + __data_end = .; + PROVIDE (edata = .); +/* __data_lma = LOADADDR(.data); */ + __iwram_overlay_start = . ; + + OVERLAY : NOCROSSREFS AT (__iwram_overlay_lma) + { + .iwram0 { *(.iwram0) . = ALIGN(4);} + .iwram1 { *(.iwram1) . = ALIGN(4);} + .iwram2 { *(.iwram2) . = ALIGN(4);} + .iwram3 { *(.iwram3) . = ALIGN(4);} + .iwram4 { *(.iwram4) . = ALIGN(4);} + .iwram5 { *(.iwram5) . = ALIGN(4);} + .iwram6 { *(.iwram6) . = ALIGN(4);} + .iwram7 { *(.iwram7) . = ALIGN(4);} + .iwram8 { *(.iwram8) . = ALIGN(4);} + .iwram9 { *(.iwram9) . = ALIGN(4);} + } = 0xff +/* laddr += (SIZEOF(.iwram0)+SIZEOF(.iwram1)+SIZEOF(.iwram2)+SIZEOF(.iwram3)+SIZEOF(.iwram4)+SIZEOF(.iwram5)+SIZEOF(.iwram6)+SIZEOF(.iwram7)+SIZEOF(.iwram8)+SIZEOF(.iwram9)); */ +/* __ewram_lma = laddr; */ + __ewram_lma = ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors) + SIZEOF(.dtors) + SIZEOF(.eh_frame) + SIZEOF(.gcc_except_table) + SIZEOF(.iwram) + SIZEOF(.data) + SIZEOF(.iwram0)+SIZEOF(.iwram1)+SIZEOF(.iwram2)+SIZEOF(.iwram3)+SIZEOF(.iwram4)+SIZEOF(.iwram5)+SIZEOF(.iwram6)+SIZEOF(.iwram7)+SIZEOF(.iwram8)+SIZEOF(.iwram9); + +/* __iwram_overlay_lma = LOADADDR (.iwram0); */ + __iwram_overlay_end = . ; +/* _end = . ; */ +/* __end__ = . ; */ +/* PROVIDE (end = .); */ + __iheap_start = . ; + + /* v1.3 */ + __ewram_start = DEFINED (__gba_multiboot) ? __ewram_lma : 0x2000000; + + .ewram __ewram_start : AT (__ewram_lma) + { +/* __ewram_start = ABSOLUTE(.); */ + *(.ewram) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } = 0xff +/* laddr += SIZEOF(.ewram); */ +/* __ewram_overlay_lma = laddr; */ + __ewram_overlay_lma = ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors) + SIZEOF(.dtors) + SIZEOF(.eh_frame) + SIZEOF(.gcc_except_table) + SIZEOF(.iwram) + SIZEOF(.data) + SIZEOF(.iwram0)+SIZEOF(.iwram1)+SIZEOF(.iwram2)+SIZEOF(.iwram3)+SIZEOF(.iwram4)+SIZEOF(.iwram5)+SIZEOF(.iwram6)+SIZEOF(.iwram7)+SIZEOF(.iwram8)+SIZEOF(.iwram9) + SIZEOF(.ewram); + +/* __ewram_lma = LOADADDR(.ewram); */ + __ewram_end = . ; + __ewram_overlay_start = . ; + + OVERLAY ALIGN(4): NOCROSSREFS AT (__ewram_overlay_lma) + { + .ewram0 { *(.ewram0) . = ALIGN(4);} + .ewram1 { *(.ewram1) . = ALIGN(4);} + .ewram2 { *(.ewram2) . = ALIGN(4);} + .ewram3 { *(.ewram3) . = ALIGN(4);} + .ewram4 { *(.ewram4) . = ALIGN(4);} + .ewram5 { *(.ewram5) . = ALIGN(4);} + .ewram6 { *(.ewram6) . = ALIGN(4);} + .ewram7 { *(.ewram7) . = ALIGN(4);} + .ewram8 { *(.ewram8) . = ALIGN(4);} + .ewram9 { *(.ewram9) . = ALIGN(4);} + } = 0xff + + __ewram_overlay_end = . ; + + __eheap_start = . ; + + _end = DEFINED (__gba_iwram_heap) ? __iheap_start : .; /* v1.3 */ + __end__ = _end ; /* v1.3 */ + PROVIDE (end = _end); /* v1.3 */ + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + .stack 0x80000 : { _stack = .; *(.stack) } + /* These must appear regardless of . */ +} diff --git a/targets/MicaZ/SConscript b/targets/MicaZ/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..a4d6a1f5b0782aafdabb9a026485dd1b3cf726bf --- /dev/null +++ b/targets/MicaZ/SConscript @@ -0,0 +1,48 @@ +# Copyright or c or Copr. 2008, Simon Duquennoy +# +# Author e-mail: simon.duquennoy@lifl.fr +# +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + + +import os +import sys + +Import('env binDir projectName elfName') + +env.Replace(CC = 'avr-gcc') +env.Replace(AS = 'avr-as') +env.Replace(AR = 'avr-ar') +env.Replace(RANLIB = 'avr-ranlib') +env.Append(CCFLAGS = '-mmcu=atmega128 -mcall-prologues') +env.Append(LINKFLAGS = '-mmcu=atmega128') + +binaryName = projectName + '.bin' +env.Command(binaryName, elfName, 'avr-objcopy -j .text -j .data -O srec $SOURCE $TARGET') diff --git a/targets/MicaZ/drivers/hardware.c b/targets/MicaZ/drivers/hardware.c new file mode 100644 index 0000000000000000000000000000000000000000..e5e2e92350880634d6fdce9c361a8a469ebd5e34 --- /dev/null +++ b/targets/MicaZ/drivers/hardware.c @@ -0,0 +1,114 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + + +#include "target.h" +#include <avr/interrupt.h> +#include <avr/io.h> + +#define AVR_TIMER_CTC (_BV(WGM01)) +#define AVR_TIMER_CLK_0 0x00 +#define AVR_TIMER_CLK_1 (_BV(CS00)) +#define AVR_TIMER_CLK_8 (_BV(CS01)) +#define AVR_TIMER_CLK_32 (_BV(CS01) | _BV(CS00)) +#define AVR_TIMER_CLK_64 (_BV(CS02)) +#define AVR_TIMER_CLK_128 (_BV(CS02) | _BV(CS00)) +#define AVR_TIMER_CLK_256 (_BV(CS02) | _BV(CS01)) +#define AVR_TIMER_CLK_1024 (_BV(CS02) | _BV(CS01) | _BV(CS00)) + +#define ADC_PROC_REF_AREF (0x00) +#define ADC_PROC_REF_AVCC _BV(REFS0) +#define ADC_PROC_REF_RSRVD _BV(REFS1) +#define ADC_PROC_REF_INTERNAL (_BV(REFS1)|_BV(REFS0)) + +#define ADC_PROC_CH1 0x01 +#define ADC_PROC_GND 0x1F + +#define ADC_PROC_CLK_2 (_BV(ADPS0)) +#define ADC_PROC_CLK_4 (_BV(ADPS1)) +#define ADC_PROC_CLK_8 (_BV(ADPS1)|_BV(ADPS0)) +#define ADC_PROC_CLK_16 (_BV(ADPS2)) +#define ADC_PROC_CLK_32 (_BV(ADPS2)|_BV(ADPS0)) +#define ADC_PROC_CLK_64 (_BV(ADPS2)|_BV(ADPS1)) +#define ADC_PROC_CLK_128 (_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0)) + +volatile uint32_t global_timer; + +ISR(TIMER0_COMP_vect) { + cli(); + global_timer++; + sei(); +} + +void hardware_timer_init(void) { + global_timer = 0; + /* Use external clock */ + ASSR = _BV(AS0); + /* TOIE1 <- 1 : Allow Timer compare match interrupt */ + TIMSK = _BV(OCIE0); + /* at every 16 Binary milliseconds (1024 BMS = 1 Second) */ + TCNT0 = 0; + OCR0 = 32; + /* Timer CTC mode with external clock */ + TCCR0 = AVR_TIMER_CTC | AVR_TIMER_CLK_1; +} + +void hardware_init() { + sei(); + DDRA |= (0x07); + PORTA |= (0x07); + hardware_timer_init(); + dev_init(); +} + +uint16_t initADC(unsigned char channel) { + ADMUX = (ADC_PROC_REF_AREF | ADC_PROC_CH1); + ADCSR = 0; + ADCSR |= _BV(ADEN); + ADCSR |= ADC_PROC_CLK_64; + DDRE |= _BV(channel); + return 1; +} + +uint16_t GetADCVal(unsigned char channel) { + PORTE |= _BV(channel); + + ADCSR |= _BV(ADSC); + while(ADCSR & _BV(ADSC)); + + PORTE &= ~_BV(channel); + + return ADCL + ((ADCH & 0x03) << 8); +} diff --git a/targets/MicaZ/drivers/serial_line.c b/targets/MicaZ/drivers/serial_line.c new file mode 100644 index 0000000000000000000000000000000000000000..1cb86af05d6afb0a6e79019c83496119ad49a8fd --- /dev/null +++ b/targets/MicaZ/drivers/serial_line.c @@ -0,0 +1,153 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "types.h" +#include <avr/interrupt.h> + +#define F_CPU 7372800 +#define BAUD 115200 +#define BAUD_PRESCALE (((F_CPU/16)/BAUD)-1) + +#define TIMEOUT 50 + +volatile serial_line_t serial_line; +enum slip_state_e{slip_in,slip_escaped}; +static enum slip_state_e slip_state; + +/*-----------------------------------------------------------------------------------*/ +void dev_init(void) { + UBRR0H = (unsigned char)(BAUD_PRESCALE>>8); + UBRR0L = (unsigned char)BAUD_PRESCALE; + UCSR0B |= (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); // Turn on the transmission and reception circuitry + UCSR0C |= (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes - URSEL bit set to select the UCRSC register + + serial_line.writePtr = serial_line.buffer; + serial_line.readPtr = NULL; + slip_state = slip_in; + + return; +} + +/*-----------------------------------------------------------------------------------*/ +ISR(USART0_RX_vect) { + cli(); + int16_t c = (int16_t) UDR0; + + /* SLIP management */ + switch(c) { + case SLIP_END: + goto uart_irq_end; + case SLIP_ESC: + slip_state = slip_escaped; + goto uart_irq_end; + case SLIP_ESC_END: + if(slip_state == slip_escaped) { + slip_state = slip_in; + c = SLIP_END; + } + break; + case SLIP_ESC_ESC: + if(slip_state == slip_escaped) { + slip_state = slip_in; + c = SLIP_ESC; + } + break; + default: + break; + } + + if(serial_line.writePtr != NULL) { + if(serial_line.readPtr == NULL) + serial_line.readPtr = serial_line.writePtr; + *serial_line.writePtr++ = c; + if(serial_line.writePtr == serial_line.buffer + INBUF_SIZE) + serial_line.writePtr = serial_line.buffer; + if(serial_line.writePtr == serial_line.readPtr) + serial_line.writePtr = NULL; + } +uart_irq_end: + /* Reenable this interrupt */ + sei(); +} + +/*-----------------------------------------------------------------------------------*/ +static unsigned char read_byte_from_buffer(void) { + int16_t c; + cli(); + + if(serial_line.writePtr == NULL) + serial_line.writePtr = serial_line.readPtr; + c = *serial_line.readPtr++; + if(serial_line.readPtr == serial_line.buffer + INBUF_SIZE) + serial_line.readPtr = serial_line.buffer; + if (serial_line.readPtr == serial_line.writePtr) + serial_line.readPtr = NULL; + + sei(); + return c; +} + +/*-----------------------------------------------------------------------------------*/ +int16_t dev_get(void) { + uint32_t last_time = global_timer; + while(serial_line.readPtr == NULL && global_timer-last_time<TIMEOUT); + if(serial_line.readPtr == NULL) { + return -1; + } else { + return read_byte_from_buffer(); + } +} + +/*-----------------------------------------------------------------------------------*/ +int32_t serial_line_write(unsigned char value) { + /* Wait for empty transmit buffer */ + while(!(UCSR0A & (1<<UDRE0))); + /* Put data into buffer, sends the data */ + UDR0 = value; + return 1; +} + +/*-----------------------------------------------------------------------------------*/ +void dev_put(unsigned char byte) { + if(byte==SLIP_END){ + serial_line_write(SLIP_ESC); + serial_line_write(SLIP_ESC_END); + } else if(byte==SLIP_ESC){ + serial_line_write(SLIP_ESC); + serial_line_write(SLIP_ESC_ESC); + } else { + serial_line_write(byte); + } +} diff --git a/targets/MicaZ/drivers/serial_line.h b/targets/MicaZ/drivers/serial_line.h new file mode 100644 index 0000000000000000000000000000000000000000..5cb4258dd26ca050bbfb8ef945c0e6e4656dd0d9 --- /dev/null +++ b/targets/MicaZ/drivers/serial_line.h @@ -0,0 +1,63 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __SLIP_DEV_H__ +#define __SLIP_DEV_H__ + +/* Extern variables */ + +extern void hardware_init(void); +extern int16_t dev_get(void); +extern void dev_put(unsigned char byte); +extern void dev_init(void); +extern int32_t serial_line_write(unsigned char value); + +/* SLIP */ +#define SLIP_END 0xC0 /* indicates end of packet */ +#define SLIP_ESC 0xDB /* indicates byte stuffing */ +#define SLIP_ESC_END 0xDC /* ESC ESC_END means END data byte */ +#define SLIP_ESC_ESC 0xDD /* ESC ESC_ESC means ESC data byte */ + +#define INBUF_SIZE 512 +/* Serial line */ +typedef struct { + volatile unsigned char buffer[INBUF_SIZE]; + volatile unsigned char *volatile writePtr; + volatile unsigned char *volatile readPtr; +} serial_line_t; + +extern volatile serial_line_t serial_line; + +#endif diff --git a/targets/MicaZ/drivers/target.h b/targets/MicaZ/drivers/target.h new file mode 100644 index 0000000000000000000000000000000000000000..9670b5b4232cde921dc5487825d6ffcec918c5e5 --- /dev/null +++ b/targets/MicaZ/drivers/target.h @@ -0,0 +1,113 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __TARGET_H__ +#define __TARGET_H__ + +#include <stdint.h> +#include <avr/pgmspace.h> + +#define NULL ((void*)0) + +#include "serial_line.h" + +extern volatile uint32_t global_timer; + +/* Drivers interface */ + +#define HARDWARE_INIT hardware_init() +#define HARDWARE_STOP +#define TIME_MILLIS global_timer +#define DEV_GET(c) {(c) = dev_get();} +#define DEV_PUT(c) dev_put(c) +#define DEV_PREPARE_OUTPUT(length) serial_line_write(SLIP_END); +#define DEV_OUTPUT_DONE serial_line_write(SLIP_END); +#define DEV_DATA_TO_READ (serial_line.readPtr != NULL) + +/* Smews states */ + +typedef enum { LED_YELLOW, LED_GREEN, LED_RED } led_t ; +#define LED_OFF(LED) (PORTA |= _BV(LED)) +#define LED_ON(LED) (PORTA &= ~_BV(LED)) +#define LED_TOGGLE(LED) (PORTA ^= _BV(LED)) + +#define SMEWS_WAITING {LED_OFF(LED_GREEN);/*LED_ON(LED_YELLOW);*/} +#define SMEWS_RECEIVING {/*LED_OFF(LED_YELLOW);*/LED_ON(LED_GREEN);} +#define SMEWS_SENDING {LED_OFF(LED_GREEN);LED_ON(LED_RED);} +#define SMEWS_ENDING {LED_OFF(LED_RED);} + +/* Const and persistent access macros */ + +#define CONST_VOID_P_VAR PGM_VOID_P +#define CONST_VAR(type,name) type const name PROGMEM +#define PERSISTENT_VAR(type,name) type name +#define CONST_WRITE_NBYTES(dst,src,len) strncpy(dst,src,len) + +#define CONST_READ_UI8(x) pgm_read_byte_near(x) +#define CONST_READ_UI16(x) pgm_read_word_near(x) +#define CONST_READ_UI32(x) pgm_read_dword_near(x) +#define CONST_READ_ADDR(x) ((void*)pgm_read_word_near(x)) + +#define CONST_UI8(x) CONST_READ_UI8(&(x)) +#define CONST_UI16(x) CONST_READ_UI16(&(x)) +#define CONST_UI32(x) CONST_READ_UI32(&(x)) +#define CONST_ADDR(x) CONST_READ_ADDR(&(x)) + +/* Endianness */ + +#define ENDIANNESS LITTLE_ENDIAN + +/* Context switching */ +/* To be done */ + +#define BACKUP_CTX(sp) + +#define RESTORE_CTX(sp) + +#define PUSHREGS + +#define POPREGS + +/* Smews configuration */ +#define OUTPUT_BUFFER_SIZE 256 +#define ALLOC_SIZE 2048 +#define STACK_SIZE 64 + +/* ADC */ +#define ADC_LIGHT 5 +extern uint16_t initADC(unsigned char channel); +extern uint16_t GetADCVal(unsigned char channel); + +#endif /* __TARGET_H__ */ diff --git a/targets/MicaZ/install b/targets/MicaZ/install new file mode 100755 index 0000000000000000000000000000000000000000..ccb51ff4da797da025913aba0869d0f571cfaa24 --- /dev/null +++ b/targets/MicaZ/install @@ -0,0 +1,7 @@ +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS0 --wr_fuse_e=0xff +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS0 --wr_fuse_e=0xff +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS0 --wr_fuse_h=0x9f +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS0 --wr_fuse_l=0xbf +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS0 --erase +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS0 --upload if=./bin/MicaZ/smews.bin +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS0 --verify if=./bin/MicaZ/smews.bin diff --git a/targets/MicaZwireless/Makefile b/targets/MicaZwireless/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d2f6423adba4a6353d7a230951a07a151726f3d5 --- /dev/null +++ b/targets/MicaZwireless/Makefile @@ -0,0 +1,173 @@ +# Hey Emacs, this is a -*- makefile -*- +#---------------------------------------------------------------------------- +# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al. +# +# Released to the Public Domain +# +# Additional material for this makefile was written by: +# Peter Fleury +# Tim Henigan +# Colin O'Flynn +# Reiner Patommel +# Markus Pfaff +# Sander Pool +# Frederik Rouleau +# Carlos Lamas +# +# Modified by Amdouni Mohamed +#---------------------------------------------------------------------------- +# On command line: +# +# make all = Make software. +# +# make clean = Clean out built project files. +# +# make program = Download the hex file to the device, using uisp. +# Please customize the serial port settings below first! +# +# To rebuild project do "make clean" then "make all". +#---------------------------------------------------------------------------- + +# MCU name +MCU = atmega128 + +# Processor frequency. +F_CPU = 7372800 + +# Output format. +FORMAT = ihex + +# Target file name (without extension). +TARGET = driver + +# Object files directory +OBJDIR = . + +# List C source files here. (C dependencies are automatically generated.) +SRC = $(TARGET).c mcu.c phy.c mac.c + +# Optimization level, can be [0, 1, 2, 3, s]. +OPT = s + +# Place -D or -U options here for C sources +CDEFS = -DF_CPU=$(F_CPU)UL + +#---------------- Compiler Options C ---------------- +# -O*: optimization level +# -Wall...: warning level +#CFLAGS = -g$(DEBUG) +CFLAGS = $(CDEFS) +CFLAGS += -O$(OPT) +CFLAGS += -Wall + +#---------------- Programming Options (uisp) ---------------- +# should be changed in adequation with you serial port +# Programming hardware +SERIAL_OUT = /dev/ttyUSB0 +USPI_FLAGS = -dpart=atmega128 -dprog=mib510 -dserial=$(SERIAL_OUT) + +# Define programs and commands. +SHELL = sh +CC = avr-gcc +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +REMOVE = rm -f +REMOVEDIR = rm -rf +COPY = cp + +# Define all object files. +OBJ = $(SRC:%.c=$(OBJDIR)/%.o) + +# Compiler flags to generate dependency files. +GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS) + +#generated messages : +MSG_BEGIN = -------- begin -------- +MSG_END = -------- end -------- +MSG_FLASH = Creating load file for Flash: +MSG_LINKING = Linking: +MSG_COMPILING = Compiling C: +MSG_CLEANING = Cleaning project: + +# Default target. +all: begin gccversion build end + +# Change the build target to build a HEX file or a library. +build: elf hex +#build: lib + + +elf: $(TARGET).elf +hex: $(TARGET).hex + +begin: + @echo + @echo $(MSG_BEGIN) + +end: + @echo $(MSG_END) + @echo + +# Display compiler version information. +gccversion : + @$(CC) --version + +# Program the device. +program: all + uisp -v=0 $(USPI_FLAGS) --wr_fuse_e=0xff + uisp -v=0 $(USPI_FLAGS) --wr_fuse_e=0xff + uisp -v=0 $(USPI_FLAGS) --wr_fuse_h=0x9f + uisp -v=0 $(USPI_FLAGS) --wr_fuse_l=0xbf + uisp -v=0 $(USPI_FLAGS) --erase + uisp -v=0 $(USPI_FLAGS) --upload if=./$(TARGET).hex + uisp -v=0 $(USPI_FLAGS) --verify if=./$(TARGET).hex + +# Create final output files (.hex, .eep) from ELF output file. +%.hex: %.elf + @echo + @echo $(MSG_FLASH) $@ + $(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock $< $@ + +# Link: create ELF output file from object files. +.SECONDARY : $(TARGET).elf +.PRECIOUS : $(OBJ) +%.elf: $(OBJ) + @echo + @echo $(MSG_LINKING) $@ + $(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS) + + +# Compile: create object files from C source files. +$(OBJDIR)/%.o : %.c + @echo + @echo $(MSG_COMPILING) $< + $(CC) -c $(ALL_CFLAGS) $< -o $@ + + +# Target: clean project. +clean: begin clean_list end + +clean_list : + @echo + @echo $(MSG_CLEANING) + $(REMOVE) $(TARGET).hex + $(REMOVE) $(TARGET).elf + $(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o) + $(REMOVE) $(SRC:.c=.s) + $(REMOVE) $(SRC:.c=.d) + $(REMOVE) $(SRC:.c=.i) + $(REMOVEDIR) .dep + + +# Create object files directory +$(shell mkdir $(OBJDIR) 2>/dev/null) + + +# Include the dependency files. +-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) + + diff --git a/targets/MicaZwireless/cc2420.h b/targets/MicaZwireless/cc2420.h new file mode 100644 index 0000000000000000000000000000000000000000..5601e98ec22b1399bfe27ed153f7dc01e79babb1 --- /dev/null +++ b/targets/MicaZwireless/cc2420.h @@ -0,0 +1,141 @@ +#ifndef CC2420_H_ +#define CC2420_H_ + + + +/******************************************************************************************************* + ******************************************************************************************************* + ************************** from CC2420 datasheet ************************** + ******************************************************************************************************* + *******************************************************************************************************/ + +//------------------------------------------------------------------------------------------------------ +//address commands +#define CC2420_SNOP 0x00 //No Operation (has no other effect than reading out status-bits) +#define CC2420_SXOSCON 0x01 //Turn on the crystal oscillator (set XOSC16M_PD = 0 and BIAS_PD = 0) +#define CC2420_STXCAL 0x02 //Enable and calibrate frequency synthesizer for TX; Go from RX +#define CC2420_SRXON 0x03 //Enable RX +#define CC2420_STXON 0x04 //Enable TX after calibration (if not already performed) +#define CC2420_STXONCCA 0x05 //If CCA indicates a clear channel:Enable calibration, then TX. +#define CC2420_SRFOFF 0x06 //Disable RX/TX and frequency synthesizer +#define CC2420_SXOSCOFF 0x07 //Turn off the crystal oscillator and RF +#define CC2420_SFLUSHRX 0x08 //Flush the RX FIFO buffer and reset the demodulator. +#define CC2420_SFLUSHTX 0x09 //Flush the TX FIFO buffer +#define CC2420_SACK 0x0A //Send acknowledge frame, with pending field cleared. +#define CC2420_SACKPEND 0x0B //Send acknowledge frame, with pending field set. +#define CC2420_SRXDEC 0x0C //Start RXFIFO in-line decryption / authentication (as set by SPI_SEC_MODE) +#define CC2420_STXENC 0x0D //Start TXFIFO in-line encryption / authentication (as set by SPI_SEC_MODE), without starting TX. +#define CC2420_SAES 0x0E //AES Stand alone encryption strobe + +//CC2420 registers address� +#define CC2420_MAIN 0x10 // Main Control Register +#define CC2420_MDMCTRL0 0x11 // Modem Control Register 0 +#define CC2420_MDMCTRL1 0x12 // Modem Control Register 1 +#define CC2420_RSSI 0x13 // RSSI and CCA Status and Control register +#define CC2420_SYNCWORD 0x14 // Synchronisation word control register +#define CC2420_TXCTRL 0x15 // Transmit Control Register +#define CC2420_RXCTRL0 0x16 // Receive Control Register 0 +#define CC2420_RXCTRL1 0x17 // Receive Control Register 1 +#define CC2420_FSCTRL 0x18 // Frequency Synthesizer Control and Status Register//FSCTRL.FREQ=357+5*(K-11) +#define CC2420_SECCTRL0 0x19 // Security Control Register 0 +#define CC2420_SECCTRL1 0x1A // Security Control Register 1 +#define CC2420_BATTMON 0x1B // Battery Monitor Control and Status Register +#define CC2420_IOCFG0 0x1C // Input / Output Control Register 0 +#define CC2420_IOCFG1 0x1D // Input / Output Control Register 1 +#define CC2420_MANFIDL 0x1E // Manufacturer ID, Low 16 bits +#define CC2420_MANFIDH 0x1F // Manufacturer ID, High 16 bits +#define CC2420_FSMTC 0x20 // Finite State Machine Time Constants +#define CC2420_MANAND 0x21 // Manual signal AND override register +#define CC2420_MANOR 0x22 // Manual signal OR override register +#define CC2420_AGCCTRL 0x23 // AGC Control Register +#define CC2420_AGCTST0 0x24 // AGC Test Register 0 +#define CC2420_AGCTST1 0x25 // AGC Test Register 1 +#define CC2420_AGCTST2 0x26 // AGC Test Register 2 +#define CC2420_FSTST0 0x27 // Frequency Synthesizer Test Register 0 +#define CC2420_FSTST1 0x28 // Frequency Synthesizer Test Register 1 +#define CC2420_FSTST2 0x29 // Frequency Synthesizer Test Register 2 +#define CC2420_FSTST3 0x2A // Frequency Synthesizer Test Register 3 +#define CC2420_RXBPFTST 0x2B // Receiver Bandpass Filter Test Register +#define CC2420_FSMSTATE 0x2C // Finite State Machine State Status Register +#define CC2420_ADCTST 0x2D // ADC Test Register +#define CC2420_DACTST 0x2E // DAC Test Register +#define CC2420_TOPTST 0x2F // Top Level Test Register +#define CC2420_RESERVED 0x30 // Reserved for future use control / status register + +#define CC2420_TXFIFO 0x3E // Transmit FIFO Byte Register +#define CC2420_RXFIFO 0x3F // Receiver FIFO Byte Register +//------------------------------------------------------------------------------------------------------- + + + +/******************************************************************************************************* + ******************************************************************************************************* + ************************** cc2420 Memory ************************** + ******************************************************************************************************* + *******************************************************************************************************/ + +//------------------------------------------------------------------------------------------------------ +// Sizes +#define CC2420_RAM_SIZE 368 +#define CC2420_FIFO_SIZE 128 + +//RAM Memory Space� +#define CC2420_RAM_TXFIFO 0x000 +#define CC2420_RAM_RXFIFO 0x080 +#define CC2420_RAM_KEY0 0x100 +#define CC2420_RAM_RXNONCE 0x110 +#define CC2420_RAM_SABUF 0x120 +#define CC2420_RAM_KEY1 0x130 +#define CC2420_RAM_TXNONCE 0x140 +#define CC2420_RAM_CBCSTATE 0x150 +#define CC2420_RAM_IEEEADDR 0x160 +#define CC2420_RAM_PANID 0x168 +#define CC2420_RAM_SHORTADDR 0x16A +//------------------------------------------------------------------------------------------------------------ + + + + +/******************************************************************************************************* + ******************************************************************************************************* + ************************ cc2420 Status byte ************************** + ******************************************************************************************************* + *******************************************************************************************************/ + +//------------------------------------------------------------------------------------------------------- +// Status byte +#define CC2420_XOSC16M_STABLE 6 +#define CC2420_TX_UNDERFLOW 5 +#define CC2420_ENC_BUSY 4 +#define CC2420_TX_ACTIVE 3 +#define CC2420_LOCK 2 +#define CC2420_RSSI_VALID 1 +//------------------------------------------------------------------------------------------------------- +// SECCTRL0 +#define CC2420_SECCTRL0_NO_SECURITY 0x0000 +#define CC2420_SECCTRL0_CBC_MAC 0x0001 +#define CC2420_SECCTRL0_CTR 0x0002 +#define CC2420_SECCTRL0_CCM 0x0003 + +#define CC2420_SECCTRL0_SEC_M_IDX 2 + +#define CC2420_SECCTRL0_RXKEYSEL0 0x0000 +#define CC2420_SECCTRL0_RXKEYSEL1 0x0020 + +#define CC2420_SECCTRL0_TXKEYSEL0 0x0000 +#define CC2420_SECCTRL0_TXKEYSEL1 0x0040 + +#define CC2420_SECCTRL0_SEC_CBC_HEAD 0x0100 +#define CC2420_SECCTRL0_RXFIFO_PROTECTION 0x0200 +//------------------------------------------------------------------------------------------------------- +// RSSI to Energy Detection conversion +#define RSSI_OFFSET -38 +#define RSSI_2_ED(rssi) ((rssi) < RSSI_OFFSET ? 0 : ((rssi) - (RSSI_OFFSET))) +#define ED_2_LQI(ed) (((ed) > 63 ? 255 : ((ed) << 2))) +//------------------------------------------------------------------------------------------------------- + + + +#endif + + diff --git a/targets/MicaZwireless/compiler.h b/targets/MicaZwireless/compiler.h new file mode 100644 index 0000000000000000000000000000000000000000..f93284ec285aadd0abda98965eb1f448cae07197 --- /dev/null +++ b/targets/MicaZwireless/compiler.h @@ -0,0 +1,50 @@ +#ifndef COMPILER_H +#define COMPILER_H + + + +/****************************************************************************** +******************* Commonly used types ******************* +******************************************************************************/ +typedef unsigned char BOOL; + +// Data +typedef unsigned char BYTE; +typedef unsigned int WORD; +typedef unsigned long int DWORD; + +// Unsigned numbers +typedef unsigned char UINT8; +typedef unsigned int UINT16; +typedef unsigned long int UINT32; + +// Signed numbers +typedef signed char INT8; +typedef signed int INT16; +typedef signed long int INT32; + +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef TRUE + #define TRUE 1 +#endif + +#ifndef NULL + #define NULL 0 +#endif + + +#define BM(n) (1 << (n)) +#define BF(x,b,s) (((x) & (b)) >> (s)) +#define MIN(n,m) (((n) < (m)) ? (n) : (m)) +#define MAX(n,m) (((n) < (m)) ? (m) : (n)) +#define ABS(n) ((n < 0) ? -(n) : (n)) + + + + +#endif + + diff --git a/targets/MicaZwireless/config.h b/targets/MicaZwireless/config.h new file mode 100644 index 0000000000000000000000000000000000000000..b9eba65034282fe0118185dabb61e0f67a97cc70 --- /dev/null +++ b/targets/MicaZwireless/config.h @@ -0,0 +1,47 @@ +#ifndef CONFIG_H_ +#define CONFIG_H_ + + +/*********************************************************************************************** +* This file is used to set up node. +the application is like the radio counter of TinyOS. +the sender count from 0 to 7, each number is displayed on the Leds and sent to thereceiver. +the receiver shows this number using Leds. + +* To rpepare the Hex file of the sender, you should change MY_ADDR in config.h to 0x1234 and NODE_TYPE to SENDER_NODE +* To rpepare the Hex file of the receiver, you should change MY_ADDR in config.h to 0x1235 and NODE_TYPE to RECEIVER_NODE + +the for each file use this script to flash MicaZ mote : + +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS4 --wr_fuse_e=0xff +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS4 --wr_fuse_e=0xff +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS4 --wr_fuse_h=0x9f +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS4 --wr_fuse_l=0xbf +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS4 --erase +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS4 --upload if=./driver_micaz.hex +uisp -v=0 -dpart=atmega128 -dprog=mib510 -dserial=/dev/ttyS4 --verify if=./driver_micaz.hex + +************************************************************************************************/ + + +#define CHANNEL 11 +#define PANID 0x2420 +#define RECEIVER_NODE 1 +#define SENDER_NODE 2 + +/*********************************************************************************************** +* //address for receiver : 0x1235 +* //address for sender : 0x1234 +************************************************************************************************/ +// to be set up for each mote +#define MY_ADDR 0x1235 + +#define NODE_TYPE RECEIVER_NODE + + + + +#endif + + + diff --git a/targets/MicaZwireless/driver.c b/targets/MicaZwireless/driver.c new file mode 100755 index 0000000000000000000000000000000000000000..164fefcecbe903ddd7d7095b45c4b56ce12e5b12 --- /dev/null +++ b/targets/MicaZwireless/driver.c @@ -0,0 +1,390 @@ +#include "compiler.h" +#include "config.h" +#include "cc2420.h" +#include "mcu.h" +#include "phy.h" +#include "mac.h" +#include <stdlib.h> +#include <stdio.h> +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/wdt.h> +#include <util/delay.h> +#include <avr/sleep.h> + + + +/******************************************************************************************************* + ************************** from mac.h ************************** + *******************************************************************************************************/ +//------------------------------------------------------------------------------------------------------- +// The RF settings structure is declared here, since we'll always need halRfInit() +extern volatile CC2420_SETTINGS rfSettings; + +// Basic RF transmission and reception structures +extern CC2420_RX_INFO rfRxInfo; +extern CC2420_TX_INFO rfTxInfo; +extern unsigned char pTxBuffer[CC2420_MAX_PAYLOAD_SIZE]; +extern unsigned char pRxBuffer[CC2420_MAX_PAYLOAD_SIZE]; + +extern unsigned char flag_ReceiveComplete; +//------------------------------------------------------------------------------------------------------- + +/******************************************************************************************************* + ************************** Handel interrupts ************************** + *******************************************************************************************************/ + +// FIFOP Pin of MicaZ sensor interfaces with Timer2 of ATmega128L +// So we initialise timer2 counter to maximum (OxFF) in init interrupt +// We set up Timer2 to have an external clock source on the rising edge +// and set up an over flow interrupt +// we should reinitialise timer counter to 0xFF in the ISR + +ISR(TIMER2_OVF_vect) +{ + unsigned char tempL,tempH; + unsigned char length; + unsigned int frameControlField; + unsigned char pFooter[2]; + unsigned char i,j=0; + unsigned int result=0; + + //TCNT to 0xFF to enable over flow on the next rising edge + TCNT2=0xFF; + CLEAR_FIFOP_INT(); + + // Clean up and exit in case of FIFO overflow, which is indicated by FIFOP = 1 and FIFO = 0 + if((FIFOP_IS_1) && (!(FIFO_IS_1))) + { + WriteStrobeReg_spi(CC2420_SFLUSHRX); + WriteStrobeReg_spi(CC2420_SFLUSHRX); + return; + } + + //check again if there is data in the RXFIFO buffer + if (FIFO_IS_1) + { + + //wait until transmission complete + while(SFD_IS_1); + SPI_ENABLE(); + + //read frame length + i = spi(0x40|CC2420_RXFIFO); + length = WriteStrobeReg(CC2420_SNOP); + + length &= CC2420_LENGTH_MASK; // Ignore MSB : MSB always set to 0 + + // Ignore the packet if the length is too short less than an ack packet + + if (length < CC2420_ACK_PACKET_SIZE) // CC2420_ACK_PACKET_SIZE == 5 + { + //if wrong packet erase data + for(j=0; j<length; j++) + { + WriteStrobeReg(CC2420_SNOP); + } + } + else //if the length is valid, then treat the packet + { + // Read the frame control field and the data sequence number + tempL = WriteStrobeReg(CC2420_SNOP); + tempH = WriteStrobeReg(CC2420_SNOP); + frameControlField = tempH; + frameControlField = (frameControlField<<8)|tempL; + rfSettings.pRxInfo->ackRequest = !!(frameControlField & CC2420_FCF_ACK_BM); + rfSettings.pRxInfo->seqNumber = WriteStrobeReg(CC2420_SNOP); + + // test if it is an acknowledgment packet + if ((length == CC2420_ACK_PACKET_SIZE) && (frameControlField == CC2420_FCF_FRAMETYPE_ACK) && (rfSettings.pRxInfo->seqNumber == rfSettings.txSeqNumber)) + { + // Read the footer and check for CRC OK + pFooter[0] = WriteStrobeReg(CC2420_SNOP); + pFooter[1] = WriteStrobeReg(CC2420_SNOP); + + // Indicate the successful ack reception (this flag is polled by the transmission routine) + if (pFooter[1] & CC2420_CRC_OK_BM) + rfSettings.ackReceived = TRUE; + } + + else if (length < CC2420_PACKET_OVERHEAD_SIZE_DsSs) // Too small to be a valid packet? + { + for(j=0; j<length-3; j++) + { + WriteStrobeReg(CC2420_SNOP); + } + return; + } + + else // Receive the rest of the packet + { + // Register the payload length + rfSettings.pRxInfo->length = length - CC2420_PACKET_OVERHEAD_SIZE_DsSs; + + // Skip the destination PAN (that's taken care of by harware address recognition!) + i = WriteStrobeReg(CC2420_SNOP); + i = WriteStrobeReg(CC2420_SNOP); + + // Skip the dest address (that's taken care of by harware address recognition!) + if( ( frameControlField & CC2420_FCF_DESTADDR_BM ) == CC2420_FCF_DESTADDR_16BIT ) + { + i = WriteStrobeReg(CC2420_SNOP); + i = WriteStrobeReg(CC2420_SNOP); + } + + // Read source address + if( ( frameControlField & CC2420_FCF_SOURCEADDR_BM ) == CC2420_FCF_SOURCEADDR_16BIT ) + { + tempL = WriteStrobeReg(CC2420_SNOP); + tempH = WriteStrobeReg(CC2420_SNOP); + rfSettings.pRxInfo->srcAddr = tempH; + rfSettings.pRxInfo->srcAddr = (rfSettings.pRxInfo->srcAddr<<8)|tempL; + } + + // Read the packet payload + for(j=0; j < rfSettings.pRxInfo->length; j++) + { + rfSettings.pRxInfo->pPayload[j] = WriteStrobeReg(CC2420_SNOP); + if(j > CC2420_MAX) + break; + } + + // Read the footer to get the RSSI value + pFooter[0] = WriteStrobeReg(CC2420_SNOP); + pFooter[1] = WriteStrobeReg(CC2420_SNOP); + rfSettings.pRxInfo->rssi = pFooter[0]; + + flag_ReceiveComplete = 1; + } + } + SPI_DISABLE(); + i=WriteStrobeReg_spi(CC2420_SFLUSHRX); + i=WriteStrobeReg_spi(CC2420_SFLUSHRX); + } + if(flag_ReceiveComplete) + { + //transmission ok : display number sent using Leds + result = rfSettings.pRxInfo->pPayload[0]; + switch (result) + { + + case 0: + { + //000 + RLED_DISABLE(); + YLED_DISABLE(); + GLED_DISABLE(); + _delay_ms(500); + + break; + } + + case 1: + { + + YLED_EN(); + RLED_DISABLE(); + GLED_DISABLE(); + + break; + } + + case 2: + { + YLED_DISABLE(); + GLED_EN(); + RLED_DISABLE(); + + break; + } + case 3: + { + YLED_EN(); + GLED_EN(); + RLED_DISABLE(); + + + break; + } + + case 4: + { + YLED_DISABLE(); + GLED_DISABLE(); + RLED_EN(); + + break; + } + + case 5: + { + YLED_EN(); + GLED_DISABLE(); + RLED_EN(); + + break; + } + + case 6: + { + YLED_DISABLE(); + GLED_EN(); + RLED_EN(); + + break; + } + + case 7: + { + YLED_EN(); + GLED_EN(); + RLED_EN(); + + + break; + } + + + default: + break; + } + + + flag_ReceiveComplete = 0; + //sleep_disable(); + } + //sleep_disable(); + +} + +int main(void) +{ + + int i; + MAC_Init(); + + if(NODE_TYPE == RECEIVER_NODE) + { + while (1) + { + //set_sleep_mode(SLEEP_MODE_IDLE); + //sleep_mode(); + }; + } + + else + { + if(NODE_TYPE == SENDER_NODE) + { + rfTxInfo.destAddr = 0x1235; + rfTxInfo.length = 1; + rfTxInfo.ackRequest = FALSE; + i=0; + + while (1) + { + // Led display : 000 <--> RGY + if(i==8) + { + i= 0; + } + + + switch (i) + { + case 0: + { + pTxBuffer[0] = 0x00; + //000 + RLED_DISABLE(); + YLED_DISABLE(); + GLED_DISABLE(); + _delay_ms(500); + break; + } + + case 1: + { + pTxBuffer[0] = 0x01; + YLED_EN(); + RLED_DISABLE(); + GLED_DISABLE(); + break; + } + + case 2: + { + pTxBuffer[0] = 0x02; + YLED_DISABLE(); + GLED_EN(); + RLED_DISABLE(); + break; + } + + case 3: + { + pTxBuffer[0] = 0x03; + YLED_EN(); + GLED_EN(); + RLED_DISABLE(); + break; + } + + case 4: + { + pTxBuffer[0] = 0x04; + YLED_DISABLE(); + GLED_DISABLE(); + RLED_EN(); + break; + } + + case 5: + { + pTxBuffer[0] = 0x05; + YLED_EN(); + GLED_DISABLE(); + RLED_EN(); + break; + } + + case 6: + { + pTxBuffer[0] = 0x06; + YLED_DISABLE(); + GLED_EN(); + RLED_EN(); + break; + } + + case 7: + { + pTxBuffer[0] = 0x07; + YLED_EN(); + GLED_EN(); + RLED_EN(); + break; + } + + default: + break; + } + + i++; + + CC2420_SendPacket(&rfTxInfo); + _delay_ms(5000); + + }; + + + } + + } + + +} + + + + diff --git a/targets/MicaZwireless/mac.c b/targets/MicaZwireless/mac.c new file mode 100644 index 0000000000000000000000000000000000000000..33c10394739480c898489cde7e987ba567b27816 --- /dev/null +++ b/targets/MicaZwireless/mac.c @@ -0,0 +1,281 @@ +#include <stdlib.h> +#include <stdio.h> +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/wdt.h> +#include <util/delay.h> +#include <avr/sleep.h> +#include <string.h> +#include "cc2420.h" +#include "mac.h" +#include "phy.h" +#include "compiler.h" +#include "mcu.h" +#include "config.h" + + + + +// The RF settings structure is declared here // could be referenced in other .c files by "extern" +volatile CC2420_SETTINGS rfSettings; + +// Basic RF transmission and reception structures +CC2420_RX_INFO rfRxInfo; + +CC2420_TX_INFO rfTxInfo; + +unsigned char pTxBuffer[CC2420_MAX_PAYLOAD_SIZE]; + +unsigned char pRxBuffer[CC2420_MAX_PAYLOAD_SIZE]; + +unsigned char flag_ReceiveComplete; + + + + +/*********************************************************************************************** +* set channel by controlling freq register : datasheet formula +************************************************************************************************/ +void CC2420_SetChannel(unsigned char channel_temp) +{ + WriteConfigReg_spi(CC2420_FSCTRL,(0x4165 | (357+5*(unsigned int)(channel_temp-11)))); +} + + +/*********************************************************************************************** +* Pan id in RAM +************************************************************************************************/ +void CC2420_SetPanId(unsigned int PanId_temp) +{ + unsigned char PanIdtemp[2]; + + PanIdtemp[1] = (PanId_temp >> 8); + PanIdtemp[0] = (PanId_temp & 0x00FF); + + WriteRAM_spi(CC2420_RAM_PANID,PanIdtemp,2); +} + + +/*********************************************************************************************** +* Set ShortAddress in Ram +************************************************************************************************/ +void CC2420_SetShortAddress(unsigned int ShortAddress) +{ + unsigned char ShortAddresstemp[2]; + + ShortAddresstemp[1] = (ShortAddress >> 8); + ShortAddresstemp[0] = (ShortAddress & 0x00FF); + + WriteRAM_spi(CC2420_RAM_SHORTADDR,ShortAddresstemp,2); +} + +/*********************************************************************************************** +* enable receive mode (command address) // Rxfifo should be flushed to avoid conflit +************************************************************************************************/ +void CC2420_ReceiveOn(void) +{ + unsigned char i; + + rfSettings.receiveOn = TRUE; + + i=WriteStrobeReg_spi(CC2420_SRXON); + i=WriteStrobeReg_spi(CC2420_SFLUSHRX); + i=WriteStrobeReg_spi(CC2420_SFLUSHRX); + FIFOP_INT_INIT(); + ENABLE_FIFOP_INT(); +} + +/*********************************************************************************************** +* disable receive mode +************************************************************************************************/ +void CC2420_ReceiveOff(void) +{ + unsigned char i; + + rfSettings.receiveOn = FALSE; + i=WriteStrobeReg_spi(CC2420_SRFOFF); + DISABLE_FIFOP_INT(); +} + + + +/*********************************************************************************************** +* CC2420 init +************************************************************************************************/ +void CC2420_Init() +{ + unsigned char i; + + //voltage regulator is on & reset pin is inactive + SET_VREG_ACTIVE(); + _delay_ms(10); + SET_RESET_ACTIVE(); + _delay_ms(50); + SET_RESET_INACTIVE(); + _delay_ms(10); + + //Turn off all interrupts during CC2420 registers accessing + DISABLE_GLOBAL_INT(); + + // Register modifications + i = WriteStrobeReg_spi(CC2420_SXOSCON); + i = WriteConfigReg_spi(CC2420_MDMCTRL0, 0x0AE2); // Turn off automatic packet acknowledgment + i = WriteConfigReg_spi(CC2420_MDMCTRL1, 0x0500); // Set the correlation threshold = 20 + i = WriteConfigReg_spi(CC2420_IOCFG0, 0x007F); // Set the FIFOP threshold to maximum + i = WriteConfigReg_spi(CC2420_SECCTRL0, 0x01C4); // Turn off "Security enable" + + //Wait for the crystal oscillator to become stable + do + { + i = WriteStrobeReg_spi(CC2420_SXOSCON); //sixth bit to one + _delay_ms(100); + } + while((i&0x40)==0); +} + + + + +/*********************************************************************************************** +* CC2420 send data : address format : src : 16 bits, dest : 16 bits, intra panid +* We use only short addresses for sending&receiving data, other @ format combinations +* can be added as a case switch and new parameter +************************************************************************************************/ +unsigned char CC2420_SendPacket(CC2420_TX_INFO *pRTI) +{ + unsigned int frameControlField; + unsigned char packetLength; + unsigned char success; + unsigned char SendDataTemp[CC2420_MAX]={' '}; + unsigned char i; + + // Wait until the transceiver is idle + while (FIFOP_IS_1 || SFD_IS_1); + + // Turn off global interrupts to avoid interference on the SPI interface + DISABLE_GLOBAL_INT(); + + // Flush the TX FIFO + WriteStrobeReg_spi(CC2420_SFLUSHTX); + + // Write the packet to the TX FIFO (the FCS is appended automatically when AUTOCRC is enabled) + + packetLength = pRTI->length + CC2420_PACKET_OVERHEAD_SIZE_DsSs; + frameControlField = CC2420_FCF_FRAMETYPE_DATA; + frameControlField |= pRTI->ackRequest ? CC2420_FCF_ACK_REQUEST : CC2420_FCF_NO_ACK_REQUEST; + frameControlField |= CC2420_FCF_INTRAPAN; + frameControlField |= CC2420_FCF_DESTADDR_16BIT; + frameControlField |= CC2420_FCF_SOURCEADDR_16BIT; + + SendDataTemp[0] = packetLength; // Packet length + SendDataTemp[1] = frameControlField & 0x00FF; // Frame control field + SendDataTemp[2] = frameControlField >> 8; + SendDataTemp[3] = rfSettings.txSeqNumber; // Sequence number + SendDataTemp[4] = rfSettings.panId & 0x00FF; + SendDataTemp[5] = rfSettings.panId >> 8; // Dest. PAN ID + SendDataTemp[6] = pRTI->destAddr & 0x00FF; // Dest. address + SendDataTemp[7] = pRTI->destAddr >> 8; + SendDataTemp[8] = rfSettings.myAddr & 0x00FF; // Source address + SendDataTemp[9] = rfSettings.myAddr >> 8; + + for(i=0;i<pRTI->length;i++) // Payload + { + SendDataTemp[i+10] = *pRTI->pPayload++; + } + + Write_TXFIFO( SendDataTemp, packetLength+1 ); + + + SPI_ENABLE(); + + WriteStrobeReg(CC2420_STXON); + + while (!SFD_IS_1);// wait SFD to be fired + while (SFD_IS_1); // wait transmission to be accopmlished + + SPI_DISABLE(); + + // Turn interrupts back on + ENABLE_GLOBAL_INT(); + success = TRUE; + + // if an acknowledgment has been asked : treatment should be done here + + // Increment the sequence number, and return the result + rfSettings.txSeqNumber++; + + // Turn on RX mode + CC2420_ReceiveOn(); + + pRTI->pPayload = pTxBuffer; + + memset(pRTI->pPayload,' ',CC2420_MAX_PAYLOAD_SIZE); + + return success; +} + + + +void MAC_Init(void) +{ + + PHY_Init(); //init ports & init spi + + _delay_ms(200); + + CC2420_Init(); // CC2420 : configure registers : security ack etc + + rfTxInfo.pPayload = pTxBuffer; + rfRxInfo.pPayload = pRxBuffer; + + + // Set the RF channel + CC2420_SetChannel(CHANNEL); + + // Set the protocol configuration + // from config.h file + rfSettings.pRxInfo = &rfRxInfo; + rfSettings.panId = PANID; + rfSettings.myAddr = MY_ADDR; + + + rfSettings.txSeqNumber = 0; + rfSettings.receiveOn = FALSE; + + // Write the short address and the PAN ID to the CC2420 RAM (requires that the XOSC is on and stable) + CC2420_SetPanId(PANID); + CC2420_SetShortAddress(MY_ADDR); + + + // Initialize the FIFOP external interrupt + FIFOP_INT_INIT(); + ENABLE_FIFOP_INT(); + + + ENABLE_GLOBAL_INT(); + + // Turn on RX mode + CC2420_ReceiveOn(); + + //RLED_EN(); +} + + + +/*********************************************************************** +* +************************************************************************/ +void mac_pTxBuffer_Clear(void) +{ + memset(pTxBuffer,' ',CC2420_MAX_PAYLOAD_SIZE); +} + +/*********************************************************************** +* +************************************************************************/ +void mac_pRxBuffer_Clear(void) +{ + memset(pRxBuffer,' ',CC2420_MAX_PAYLOAD_SIZE); +} + + diff --git a/targets/MicaZwireless/mac.h b/targets/MicaZwireless/mac.h new file mode 100644 index 0000000000000000000000000000000000000000..3a0766492f495b465465649aea9473b82697959c --- /dev/null +++ b/targets/MicaZwireless/mac.h @@ -0,0 +1,126 @@ +#ifndef MAC_H_ +#define MAC_H_ + + + +/******************************************************************************************************* + ******************************************************************************************************* + ****************** Constants concerned with the Basic RF packet format ************************* + ******************************************************************************************************* + *******************************************************************************************************/ + +//------------------------------------------------------------------------------------------------------- +// Packet overhead ((frame control field, sequence number, PAN ID, destination and source) + (footer)) +// Note that the length byte itself is not included included in the packet length +#define CC2420_PACKET_OVERHEAD_SIZE_DsSs ((2 + 1 + 2 + 2 + 2) + (2)) +#define CC2420_PACKET_OVERHEAD_SIZE_DsSl ((2 + 1 + 2 + 2 + 8) + (2)) +#define CC2420_PACKET_OVERHEAD_SIZE_DlSs ((2 + 1 + 2 + 8 + 2) + (2)) +#define CC2420_MAX_PAYLOAD_SIZE (CC2420_MAX - CC2420_PACKET_OVERHEAD_SIZE_DsSs) +#define CC2420_ACK_PACKET_SIZE 5 +#define CC2420_MAX 127 + + +// The time it takes for the acknowledgment packet to be received after the data packet has been transmitted +#define CC2420_ACK_DURATION (0.5 * 32 * 2 * ((4 + 1) + (1) + (2 + 1) + (2))) +#define CC2420_SYMBOL_DURATION (32 * 0.5) + +// The length byte +#define CC2420_LENGTH_MASK 0x7F + +// Frame control field +#define CC2420_FCF_FRAMETYPE_DATA 0x0001 +#define CC2420_FCF_FRAMETYPE_ACK 0x0002 + +#define CC2420_FCF_INTRAPAN 0x0040 + +#define CC2420_FCF_ACK_REQUEST 0x0020 +#define CC2420_FCF_NO_ACK_REQUEST 0x0000 +#define CC2420_FCF_DESTADDR_16BIT 0x0800 +#define CC2420_FCF_DESTADDR_64BIT 0x0C00 +#define CC2420_FCF_DESTADDR_BM 0x0C00 +#define CC2420_FCF_SOURCEADDR_16BIT 0x8000 +#define CC2420_FCF_SOURCEADDR_64BIT 0xC000 +#define CC2420_FCF_SOURCEADDR_BM 0xC000 + +#define CC2420_FCF_ACK_BM 0x0020 + + + +// Footer +#define CC2420_CRC_OK_BM 0x80 +//------------------------------------------------------------------------------------------------------- + + +//------------------------------------------------------------------------------------------------------- +// The data structure which is used to transmit packets +typedef struct { + //unsigned int destPanId; + unsigned int destAddr; + //unsigned char destIEEE[8]; + unsigned char length; + unsigned char *pPayload; + unsigned char ackRequest; +} CC2420_TX_INFO; +//------------------------------------------------------------------------------------------------------- + +//------------------------------------------------------------------------------------------------------- +// The receive struct: +typedef struct { + unsigned char seqNumber; + unsigned int srcAddr; + //unsigned char srcIEEE[8]; + unsigned int srcPanId; + unsigned char length; + unsigned char *pPayload; + unsigned char ackRequest; + unsigned char rssi; +} CC2420_RX_INFO; +//------------------------------------------------------------------------------------------------------- + +//------------------------------------------------------------------------------------------------------- +// The RF settings structure: +typedef struct { + CC2420_RX_INFO *pRxInfo; + unsigned char txSeqNumber; + volatile unsigned char ackReceived; + unsigned int panId; + unsigned int myAddr; + //unsigned char myIEEE[8]; + unsigned char receiveOn; + //unsigned char JoinNetworkSuccess; +} CC2420_SETTINGS; +//------------------------------------------------------------------------------------------------------- + + + + + /****************************************************************************************************** + ************************** Definition ************************** + *******************************************************************************************************/ + +//------------------------------------------------------------------------------------------------------- +void CC2420_Init(); +unsigned char CC2420_SendPacket(CC2420_TX_INFO *pRTI); + +void CC2420_SetChannel(unsigned char channel_temp); +void CC2420_SetPanId(unsigned int PanId); +void CC2420_SetShortAddress(unsigned int ShortAddress); +//unsigned char* CC2420_ReadIEEEAddr(void); +//void CC2420_SetIEEEAddr(void); + +void CC2420_ReceiveOn(void); +void CC2420_ReceiveOff(void); + + +void MAC_Init(void); + +void mac_pRxBuffer_Clear(void); +void mac_pTxBuffer_Clear(void); +//------------------------------------------------------------------------------------------------------- + + + + +#endif + + diff --git a/targets/MicaZwireless/mcu.c b/targets/MicaZwireless/mcu.c new file mode 100644 index 0000000000000000000000000000000000000000..cfe3312bd9d40e6a254ffe3dfde82e8009079a73 --- /dev/null +++ b/targets/MicaZwireless/mcu.c @@ -0,0 +1,65 @@ +#include <stdlib.h> +#include <stdio.h> +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/wdt.h> +#include <util/delay.h> +#include <avr/sleep.h> +#include <string.h> +#include "mcu.h" +#include "compiler.h" + +/*********************************************************************************************** +* ATMega128L port init (Led directions as output) +************************************************************************************************/ +void PORT_Init(void) +{ + //init led direction + DDRA |= (1<<RLED)|(1<<GLED)|(1<<YLED); + RLED_DISABLE(); + GLED_DISABLE(); + YLED_DISABLE(); + //init fifo as input + DDRB &= ~BM(FIFO); + + //init SFD CCA and FIFOP as inputs + DDRD &= ~(BM(SFD)|BM(CCA)|BM(FIFOP)); + + //init rest and vreg as output + DDRA |= (BM(RESET_N)|BM(VREG_EN)); + + //init value of reset and vreg + PORTA &= ~(BM(RESET_N)|BM(VREG_EN)); +} + + +/*********************************************************************************************** +* SPI port init +************************************************************************************************/ +void SPI_Init(void) +{ + unsigned char temp; + /* Set MOSI (DDB2) and SCK (DDB1)(output, all others input) */ + DDRB |= (1<<CSN)|(1<<SCK)|(1<<MOSI); + PORTB |= (1<<CSN); + /* Enable SPI, Master, set clock rate fck/16 : 1Mhz */ + SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0); + + SPSR = 0x00; + temp = SPSR; + temp = SPDR; //free interrupts +} + +/*********************************************************************************************** +* SPI read/write +************************************************************************************************/ + +unsigned char spi(unsigned char data) +{ + SPDR=data; + while ((SPSR & (1<<SPIF))==0); + return SPDR; +} + + + diff --git a/targets/MicaZwireless/mcu.h b/targets/MicaZwireless/mcu.h new file mode 100644 index 0000000000000000000000000000000000000000..309e10f102e0bf9cd667a4f51e876dc418efd56f --- /dev/null +++ b/targets/MicaZwireless/mcu.h @@ -0,0 +1,178 @@ +#ifndef MCU_H_ +#define MCU_H_ + +/******************************************************************************************************* + ******************************************************************************************************* + ************************** Global macros ************************** + ******************************************************************************************************* + *******************************************************************************************************/ + +#define ENABLE_GLOBAL_INT() sei() +#define DISABLE_GLOBAL_INT() cli() + + + +/******************************************************************************************************* + ******************************************************************************************************* + ************************** ATMega128L SPI ************************ + ******************************************************************************************************* + *******************************************************************************************************/ + +//------------------------------------------------------------------------------------------------------ +/* SPI--->SPCR : SPI Control Register */ +#define SPR0 0 //SPI Clock Rate Select : fosc/4 :00, fosc/16: SPR0:1 SPR1:0 +#define MSTR 4 //Master/Slave Select : This bit selects Master SPI mode when written to one +#define SPE 6 //SPI Enable : This bit must be set to enable any SPI operations. + +/* SPI--->SPSR : SPI Status Register */ +#define SPIF 7 //SPI Interrupt Flag + +//------------------------------------------------------------------------------------------------------ + +/******************************************************************************************************* + ******************************************************************************************************* + ************************** ATmega128L I/O PORTS ************************** + ******************************************************************************************************* + *******************************************************************************************************/ + +//------------------------------------------------------------------------------------------------------ +// Port A +#define YLED 0 // PA.0 - Output: Yellow LED +#define GLED 1 // PA.1 - Output: Green LED +#define RLED 2 // PA.2 - Output: Red LED +#define VREG_EN 5 // PA.5 - Output: VREG_EN to CC2420 +#define RESET_N 6 // PA.6 - Output: RESET_N to CC2420 + + +// Port B +#define CSN 0 // PB.0 - Output: SPI Chip Select (CS_N) +#define SCK 1 // PB.1 - Output: SPI Serial Clock (SCLK) +#define MOSI 2 // PB.2 - Output: SPI Master out - slave in (MOSI) +#define MISO 3 // PB.3 - Input: SPI Master in - slave out (MISO) +#define FIFO 7 // PB.7 - Input: FIFO from CC2420 + +// Port D +#define SFD 4 // PD.4 - Input: SFD from CC2420 (on input captur 1) +#define CCA 6 // PD.6 - Input: CCA from CC2420 (Timer1) +#define FIFOP 7 // PD.7 - Input: FIFOP from CC2420 (Timer2) + + +// Enables/disables the SPI interface +#define SPI_DISABLE() ( PORTB |= BM(CSN) ) // chip select CSn +#define SPI_ENABLE() ( PORTB &= ~BM(CSN) ) // chip select CSn (active low) + +//------------------------------------------------------------------------------------------------------ + + /****************************************************************************************************** + ******************************************************************************************************* + ************************** CC2420 PIN ACCESS ************************** + ******************************************************************************************************* + *******************************************************************************************************/ + +//------------------------------------------------------------------------------------------------------- +// Pin status +#define FIFO_IS_1 (!!(PINB & BM(FIFO))) +#define CCA_IS_1 (!!(PIND & BM(CCA))) +#define RESET_IS_1 (!!(PINA & BM(RESET_N))) +#define VREG_IS_1 (!!(PINA & BM(VREG_EN))) +#define FIFOP_IS_1 (!!(PIND & BM(FIFOP))) +#define SFD_IS_1 (!!(PIND & BM(SFD))) + +// CC2420 voltage regulator enable pin +#define SET_VREG_ACTIVE() ( PORTA |= BM(VREG_EN) ) //Votltage regulator (active high) +#define SET_VREG_INACTIVE() ( PORTA &= ~BM(VREG_EN) ) //Votltage regulator + +// The CC2420 reset pin +#define SET_RESET_ACTIVE() ( PORTA &= ~BM(RESET_N) ) //reset pin (active low) +#define SET_RESET_INACTIVE() ( PORTA |= BM(RESET_N) ) //reset pin +//------------------------------------------------------------------------------------------------------- + + +/******************************************************************************************************* + ******************************************************************************************************* + ************************** INTERRUPTS ************************** + ******************************************************************************************************* + *******************************************************************************************************/ + +//------------------------------------------------------------------------------------------------------- +/* FIFOP on Timer2 over flow : external clock */ +/* Interrupts --->TIFR : Timer/Counter Interrupt Flag Register */ +#define TOV2 6 //Bit 6 : TOV2: Timer/Counter2 Overflow Flag +#define ICF1 5 //Bit 5 : ICF1: Timer/Counter1, Input Capture Flag + +/* Interrupts --->TIMSK: Timer/Counter Interrupt Mask Register */ +#define TICIE1 5 //Timer/Counter1, Input Capture Interrupt Enable +#define TOIE2 6 //Timer/Counter2 Overflow Interrupt Enable + +/* Interrupts --->TCCR2: Timer/Counter Control Register */ +#define WGM20 6 //Waveform Generation Mode : to set Timer/Counter Mode of Operation +#define WGM21 3 //Waveform Generation Mode : to set Timer/Counter Mode of Operation +#define CS20 0 //Clock Select 0 : to set External clock source on T2 pin +#define CS21 1 //Clock Select 1 : to set External clock source on T2 pin +#define CS22 2 //Clock Select 2 : to set External clock source on T2 pin + +/* Interrupts --->TCCR1B: Timer/Counter1 Control Register B */ +#define ICES1 6 //Input Capture Edge Select Timer1 + +//Normal mode on Timer2 : TOP 0xFF, immediate update, TOV2 MAX +//Need to initialize TCNT2 to 0xFF : it will generate an overflows interrupt +//TCNT2 should be initialized again to 0xFF in the ISR +#define FIFOP_INT_INIT() do { TCNT2=0xFF; \ + TCCR2 &= ~(BM(WGM20)|BM(WGM21)); \ + TCCR2 |= (BM(CS22) | BM(CS21)| BM(CS20)); \ + CLEAR_FIFOP_INT(); \ + } while (0) + +#define ENABLE_FIFOP_INT() do {TIMSK |= BM(TOIE2); } while(0) + +#define DISABLE_FIFOP_INT() do {TIMSK &= ~BM(TOIE2); } while (0) + +#define CLEAR_FIFOP_INT() do {TIFR &= ~BM(TOV2); } while(0) + + +// SFD interrupt on timer 1 capture pin +#define ENABLE_SFD_CAPTURE_INT() do { TIMSK |= BM(TICIE1); } while (0) +#define DISABLE_SFD_CAPTURE_INT() do { TIMSK &= ~BM(TICIE1); } while (0) +#define CLEAR_SFD_CAPTURE_INT() do { TIFR = BM(ICF1); } while (0) + + +//------------------------------------------------------------------------------------------------------- + + /****************************************************************************************************** + ******************************************************************************************************* + ************************** LED ************************** + ******************************************************************************************************* + *******************************************************************************************************/ + +//------------------------------------------------------------------------------------------------------ +// LED +#define RLED_EN() PORTA &= ~(1<<RLED) +#define RLED_DISABLE() PORTA |= (1<<RLED) +#define RLED_TOGGLE() PORTA ^= (1<<RLED) +#define GLED_EN() PORTA &= ~(1<<GLED) +#define GLED_DISABLE() PORTA |= (1<<GLED) +#define GLED_TOGGLE() PORTA ^= (1<<GLED) +#define YLED_EN() PORTA &= ~(1<<YLED) +#define YLED_DISABLE() PORTA |= (1<<YLED) +#define YLED_TOGGLE() PORTA ^= (1<<YLED) + +//------------------------------------------------------------------------------------------------------ + + + /****************************************************************************************************** + ************************** Definitions ************************** + *******************************************************************************************************/ + +//------------------------------------------------------------------------------------------------------ +void PORT_Init(void); +void SPI_Init(void); +unsigned char spi(unsigned char data); +void Sleep(void); +//------------------------------------------------------------------------------------------------------ + + + +#endif + + + diff --git a/targets/MicaZwireless/phy.c b/targets/MicaZwireless/phy.c new file mode 100644 index 0000000000000000000000000000000000000000..a45c99fd93d35aa9d714fd6bd51489590ba96a6c --- /dev/null +++ b/targets/MicaZwireless/phy.c @@ -0,0 +1,152 @@ +#include <stdlib.h> +#include <stdio.h> +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/wdt.h> +#include <util/delay.h> +#include <avr/sleep.h> +#include "phy.h" +#include "cc2420.h" +#include "mcu.h" +#include "compiler.h" +#include "config.h" + + +/*********************************************************************************************** +* +************************************************************************************************/ +unsigned char WriteStrobeReg_spi(unsigned char cmd) +{ + unsigned char Value; + SPI_ENABLE(); //CSn low + Value = spi(0x00|cmd); + SPI_DISABLE(); //CSn high + //_delay_ms(1); + return Value; +} + +unsigned char WriteStrobeReg(unsigned char cmd) +{ + unsigned char Value; + Value = spi(0x00|cmd); + //_delay_ms(1); + return Value; +} + + +/*********************************************************************************************** +* +************************************************************************************************/ +unsigned char WriteConfigReg_spi(unsigned char cmd, unsigned int data) +{ + unsigned char TempH,TempL,Value; + TempH = (data >> 8); + TempL = (data & 0x00FF); + + SPI_ENABLE(); //CSn low + Value = spi(0x00|cmd); + spi(TempH); + spi(TempL); + SPI_DISABLE(); //CSn high + + //_delay_ms(1); + return Value; +} + + + +/*********************************************************************************************** +* +************************************************************************************************/ +unsigned int ReadConfigReg_spi(unsigned char cmd) +{ + unsigned char Status,ValueH,ValueL; + unsigned int Value; + + SPI_ENABLE(); //CSn low + Status = spi(0x40|cmd); + ValueH = spi(0x00); + ValueL = spi(0x00); + SPI_DISABLE(); //CSn high + + Value = ValueH ; + Value = Value<<8 ; + Value |= ValueL ; + + return Value; +} + + + + +/*********************************************************************************************** +* +************************************************************************************************/ +void Write_TXFIFO(unsigned char *data,unsigned char n) +{ + unsigned char i; + + SPI_ENABLE(); + WriteStrobeReg(CC2420_TXFIFO); + for (i = 0; i < (n); i++) + { + spi(*data++); + } + SPI_DISABLE(); +} + + + +/*********************************************************************************************** +* +************************************************************************************************/ +void WriteRAM_spi(unsigned int cmd,unsigned char data[],unsigned char n) +{ + unsigned char cmdTempH,cmdTempL,i; + cmdTempH = (0x007F & cmd); + cmdTempL = ((cmd>>1) & 0x00C0); + + SPI_ENABLE(); //CSn low + spi(0x80|cmdTempH); + spi(0x00|cmdTempL); + for(i=0; i<n; i++) + { + spi(data[i]); + } + SPI_DISABLE(); //CSn high + + _delay_ms(1); +} + + + +/*********************************************************************************************** +* +************************************************************************************************/ +unsigned char ReadRAM(unsigned int cmd) +{ + unsigned char cmdTempH,cmdTempL; + unsigned char Value; + cmdTempH = (0x007F & cmd); + cmdTempL = ((cmd>>1) & 0x00C0); + + spi(0x80|cmdTempH); + Value = spi(0x20|cmdTempL); + + _delay_ms(1); + return Value; +} + + +/*********************************************************************************************** +* +************************************************************************************************/ +void PHY_Init(void) +{ + PORT_Init(); + SPI_Init(); +} + + + + diff --git a/targets/MicaZwireless/phy.h b/targets/MicaZwireless/phy.h new file mode 100644 index 0000000000000000000000000000000000000000..fa3d58b8572077d8c927444e0fadb80ca1dffb9c --- /dev/null +++ b/targets/MicaZwireless/phy.h @@ -0,0 +1,32 @@ +#ifndef PHY_H_ +#define PHY_H_ + + + + + /****************************************************************************************************** + ************************** Definitions ************************** + *******************************************************************************************************/ + +//------------------------------------------------------------------------------------------------------- +unsigned char WriteStrobeReg_spi(unsigned char cmd); +unsigned char WriteStrobeReg(unsigned char cmd); +unsigned char WriteConfigReg_spi(unsigned char cmd, unsigned int data); +unsigned int ReadConfigReg_spi(unsigned char cmd); + +void Write_TXFIFO(unsigned char *data,unsigned char n); + +void WriteRAM_spi(unsigned int cmd,unsigned char data[],unsigned char n); + +unsigned char ReadRAM(unsigned int cmd); + +void PHY_Init(void); +//------------------------------------------------------------------------------------------------------- + + + + +#endif + + + diff --git a/targets/MicaZwireless/readme.txt b/targets/MicaZwireless/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..ef51600e95f741645193d90403a12a04c910f741 --- /dev/null +++ b/targets/MicaZwireless/readme.txt @@ -0,0 +1,9 @@ +* This config.h file is used to set up the node. +the application is like the radio counter of TinyOS. +the sender count from 0 to 7, each number is displayed on the Leds and sent to the receiver. +the receiver shows this number using Leds. + +* To rpepare the Hex file of the sender, you should change MY_ADDR in config.h to 0x1234 and NODE_TYPE to SENDER_NODE +* To rpepare the Hex file of the receiver, you should change MY_ADDR in config.h to 0x1235 and NODE_TYPE to RECEIVER_NODE + +Please read Makefile to know how to compile and flash mote. diff --git a/targets/WSN430/SConscript b/targets/WSN430/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..a45ec254dfbff35851f852c2e7b5e92219247bed --- /dev/null +++ b/targets/WSN430/SConscript @@ -0,0 +1,45 @@ +# Copyright or c or Copr. 2008, Simon Duquennoy +# +# Author e-mail: simon.duquennoy@lifl.fr +# +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + + +import os +import sys + +Import('env binDir projectName elfName') + +env.Replace(CC = 'msp430-gcc') +env.Replace(AS = 'msp430-as') +env.Replace(AR = 'msp430-ar') +env.Replace(RANLIB = 'msp430-ranlib') +env.Append(CCFLAGS = '-mmcu=msp430x1611 -ffunction-sections') +env.Append(LINKFLAGS = '-mmcu=msp430x1611 -Wl,--gc-sections,--undefined=_reset_vector__,--undefined=InterruptVectors,--undefined=_copy_data_init__,--undefined=_clear_bss_init__,--undefined=_end_of_init__') diff --git a/targets/WSN430/drivers/hardware.c b/targets/WSN430/drivers/hardware.c new file mode 100644 index 0000000000000000000000000000000000000000..dc67fdfad675358511106adec5b55b5fe3a398a1 --- /dev/null +++ b/targets/WSN430/drivers/hardware.c @@ -0,0 +1,119 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + + +#include "target.h" + +#define LFXT1CLK_HZ 32768 + +volatile uint32_t global_timer; + +#ifndef DISABLE_RTX +interrupt (TIMERA0_VECTOR) timerA0( void ) { + global_timer++; +} + +void timer_init() { + /* Ensure the timer is stopped. */ + TACTL = 0; + /* Clear everything to start with. */ + TACTL |= TACLR; + /* Run the timer of the SMCLK (1MHz). */ + TACTL = TASSEL_2; + /* Set the compare match value according to the tick rate we want. */ + TACCR0 = 999; + /* Enable the interrupts. */ + TACCTL0 = CCIE; + + /* ID_0 (0<<6) Timer A input divider: 0 - /1 */ + /* ID_1 (1<<6) Timer A input divider: 1 - /2 */ + /* ID_2 (2<<6) Timer A input divider: 2 - /4 */ + /* ID_3 (3<<6) Timer A input divider: 3 - /8 */ + TACTL |= ID_0; + + /* Up mode. */ + TACTL |= MC_1; +} +#endif + +void xtal_init() { + int i; + // Init Xtal + DCOCTL = 0; + BCSCTL1 = 0; + BCSCTL2 = SELM_2 | (SELS | DIVS_3) ; + + // Wait + do { + IFG1 &= ~OFIFG; /* Clear OSCFault flag */ + for (i = 0xff; i > 0; i--) /* Time for flag to set */ + nop(); /* */ + } while ((IFG1 & OFIFG) != 0); /* OSCFault flag still set? */ +} + +void hardware_init() { + // WDog OFF + WDTCTL = WDTPW + WDTHOLD; + + LEDS_INIT(); + xtal_init(); + dev_init(); +#ifndef DISABLE_RTX + timer_init(); +#endif + LEDS_OFF(); + eint(); +} + +uint16_t initADC(unsigned char channel) { + return 1; +} + +uint16_t GetADCVal(unsigned char channel) { + ADC12CTL0 = ADC12ON | SHT0_15 | REFON; // ADC on, int. ref. on (1,5 V), multiple sample & conversion + + ADC12CTL1 = ADC12SSEL_2 | ADC12DIV_7 | CSTARTADD_0 | CONSEQ_1 | SHP; // MCLK / 8 = 1 MHz + + ADC12MCTL0 = EOS | SREF_1 | (channel & 0x0F); // int. ref., channel 10, last seg. + + ADC12CTL0 |= ENC; // enable conversion + ADC12CTL0 |= ADC12SC; // sample & convert + + while (ADC12CTL0 & ADC12SC); // wait until conversion is complete + + ADC12CTL0 &= ~ENC; // disable conversion + + return ADC12MEM0; +} diff --git a/targets/WSN430/drivers/serial_line.c b/targets/WSN430/drivers/serial_line.c new file mode 100644 index 0000000000000000000000000000000000000000..66746f286785cb3c044b0e3fa5a7ef49d7290414 --- /dev/null +++ b/targets/WSN430/drivers/serial_line.c @@ -0,0 +1,188 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "types.h" +#include "serial_line.h" + +#define UART1_PIN_RX 7 +#define UART1_PIN_TX 6 + +#define UART1_BIT_RX (1 << UART1_PIN_RX) +#define UART1_BIT_TX (1 << UART1_PIN_TX) + +#define TIMEOUT 50 + +volatile serial_line_t serial_line; +enum slip_state_e{slip_in,slip_escaped}; +static enum slip_state_e slip_state; + +/*-----------------------------------------------------------------------------------*/ +void dev_init(void) { + //Init of MSP430 Usart1 pins + P3SEL |= (UART1_BIT_RX | UART1_BIT_TX); + + //Init of USART1 Module + U1ME |= UTXE1|URXE1; //Enable USART1 transmiter and receiver (UART mode) + + U1CTL = SWRST; //reset + U1CTL = CHAR; //init & release reset + + U1TCTL = SSEL_SMCLK|TXEPT; //use SMCLK + U1RCTL = 0; + + // 115200 @ SMCLK 1MHz + #define U1BR1_INIT 0 + #define U1BR0_INIT 0x08 + #define U1MCTL_INIT 0x6d + + U1BR1 = U1BR1_INIT; + U1BR0 = U1BR0_INIT; + U1MCTL = U1MCTL_INIT; + + U1IE |= URXIE1; + + serial_line.writePtr = serial_line.buffer; + serial_line.readPtr = NULL; + slip_state = slip_in; + + return; +} + +/*-----------------------------------------------------------------------------------*/ +interrupt (USART1RX_VECTOR) usart1irq( void ) { + volatile int16_t c; + /* Check status register for receive errors. */ + if(URCTL1 & RXERR) { + /* Clear error flags by forcing a dummy read. */ + c = (int16_t) RXBUF1; + return; + } else { + c = (int16_t) U1RXBUF; + } + + /* SLIP management */ + switch(c) { + case SLIP_END: + return; + case SLIP_ESC: + slip_state = slip_escaped; + return; + case SLIP_ESC_END: + if(slip_state == slip_escaped) { + slip_state = slip_in; + c = SLIP_END; + } + break; + case SLIP_ESC_ESC: + if(slip_state == slip_escaped) { + slip_state = slip_in; + c = SLIP_ESC; + } + break; + default: + break; + } + + if(serial_line.writePtr != NULL) { + if(serial_line.readPtr == NULL) + serial_line.readPtr = serial_line.writePtr; + *serial_line.writePtr++ = c; + if(serial_line.writePtr == serial_line.buffer + INBUF_SIZE) + serial_line.writePtr = serial_line.buffer; + if(serial_line.writePtr == serial_line.readPtr) + serial_line.writePtr = NULL; + } +} + +/*-----------------------------------------------------------------------------------*/ +static unsigned char read_byte_from_buffer() { + unsigned char c; + if(serial_line.writePtr == NULL) + serial_line.writePtr = serial_line.readPtr; + c = *serial_line.readPtr++; + if(serial_line.readPtr == serial_line.buffer + INBUF_SIZE) + serial_line.readPtr = serial_line.buffer; + if (serial_line.readPtr == serial_line.writePtr) + serial_line.readPtr = NULL; + return c; +} + +/*-----------------------------------------------------------------------------------*/ +int16_t dev_get(void) { + uint32_t last_time = global_timer; + while(serial_line.readPtr == NULL && global_timer-last_time<TIMEOUT); + if(serial_line.readPtr == NULL) { + return -1; + } else { + return read_byte_from_buffer(); + } +} + +/*-----------------------------------------------------------------------------------*/ +int32_t serial_line_write(unsigned char value) { + U1TXBUF = value; + while ((U1TCTL & TXEPT) != TXEPT); + return 1; +} + +/*-----------------------------------------------------------------------------------*/ +void dev_put(unsigned char byte) { + if(byte==SLIP_END){ + serial_line_write(SLIP_ESC); + serial_line_write(SLIP_ESC_END); + } else if(byte==SLIP_ESC){ + serial_line_write(SLIP_ESC); + serial_line_write(SLIP_ESC_ESC); + } else { + serial_line_write(byte); + } +} + +/* for debug purposes. allows to use printf. */ +// /*-----------------------------------------------------------------------------------*/ +// void putchar(unsigned char byte) { +// static char in_frame = 0; +// if(!in_frame) { +// serial_line_write(SLIP_END); +// in_frame = 1; +// } +// if(byte == '\n') { +// serial_line_write(SLIP_END); +// in_frame = 0; +// } else { +// dev_put(byte); +// } +// +// } diff --git a/targets/WSN430/drivers/serial_line.h b/targets/WSN430/drivers/serial_line.h new file mode 100644 index 0000000000000000000000000000000000000000..eca6fc9965566aec0045ecb3d8172bfb3aa68966 --- /dev/null +++ b/targets/WSN430/drivers/serial_line.h @@ -0,0 +1,64 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __SLIP_DEV_H__ +#define __SLIP_DEV_H__ + +#include "target.h" + +/* Extern functions */ +extern void hardware_init(void); +extern int16_t dev_get(void); +extern void dev_put(unsigned char byte); +extern void dev_init(void); +extern int32_t serial_line_write(unsigned char value); + +/* SLIP */ +#define SLIP_END 0xC0 /* indicates end of packet */ +#define SLIP_ESC 0xDB /* indicates byte stuffing */ +#define SLIP_ESC_END 0xDC /* ESC ESC_END means END data byte */ +#define SLIP_ESC_ESC 0xDD /* ESC ESC_ESC means ESC data byte */ + +#define INBUF_SIZE 512 +/* Serial line */ +typedef struct { + volatile unsigned char buffer[INBUF_SIZE]; + volatile unsigned char *volatile writePtr; + volatile unsigned char *volatile readPtr; +} serial_line_t; + +extern volatile serial_line_t serial_line; + +#endif diff --git a/targets/WSN430/drivers/target.h b/targets/WSN430/drivers/target.h new file mode 100644 index 0000000000000000000000000000000000000000..db452e4866f05edff1cf0d1a311f6186f67ec39c --- /dev/null +++ b/targets/WSN430/drivers/target.h @@ -0,0 +1,148 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __TARGET_H__ +#define __TARGET_H__ + +#include <stdint.h> +#include <io.h> +#include <string.h> +#include <signal.h> +#include <iomacros.h> + +#include "serial_line.h" + +extern volatile uint32_t global_timer; + +/* Drivers interface */ + +#define HARDWARE_INIT hardware_init() +#define HARDWARE_STOP +#define TIME_MILLIS global_timer +#define DEV_GET(c) {(c) = dev_get();} +#define DEV_PUT(c) dev_put(c) +#define DEV_PREPARE_OUTPUT(length) serial_line_write(SLIP_END); +#define DEV_OUTPUT_DONE serial_line_write(SLIP_END); +#define DEV_DATA_TO_READ (serial_line.readPtr != NULL) + +/* Smews states */ + +typedef enum { LED_RED = 4, LED_GREEN, LED_BLUE } led_t ; +#define LED_OUT P5OUT +#define BIT_BLUE (1 << 6) +#define BIT_GREEN (1 << 5) +#define BIT_RED (1 << 4) + +#define LEDS_OFF() LED_OUT |= (BIT_BLUE | BIT_GREEN | BIT_RED) +#define LEDS_ON() LED_OUT &= ~(BIT_BLUE | BIT_GREEN | BIT_RED) + +#define LEDS_INIT() \ +do { \ + P5OUT &= ~(BIT_BLUE | BIT_GREEN | BIT_RED); \ + P5DIR |= (BIT_BLUE | BIT_GREEN | BIT_RED); \ + P5SEL &= ~(BIT_BLUE | BIT_GREEN | BIT_RED); \ +} while(0) + +#define LED_OFF(LED) (LED_OUT |= (1 << LED)) +#define LED_ON(LED) (LED_OUT &= ~(1 << LED)) +#define LED_TOGGLE(LED) (LED_OUT ^= (1 << LED)) + +#define SMEWS_WAITING {LEDS_OFF();/*LED_ON(LED_BLUE);*/} +#define SMEWS_RECEIVING {LEDS_OFF();LED_ON(LED_GREEN);} +#define SMEWS_SENDING {LEDS_OFF();LED_ON(LED_RED);} +#define SMEWS_ENDING {LEDS_OFF();} + +/* Const and persistent access macros */ + +#define CONST_VOID_P_VAR const void * +#define CONST_VAR(type,name) type const name +#define PERSISTENT_VAR(type,name) type name +#define CONST_WRITE_NBYTES(dst,src,len) strncpy(dst,src,len) + +#define CONST_READ_UI8(x) ((uint8_t)*((uint8_t*)(x))) +#define CONST_READ_UI16(x) ((uint16_t)*((uint16_t*)(x))) +#define CONST_READ_UI32(x) ((uint32_t)*((uint32_t*)(x))) +#define CONST_READ_ADDR(x) ((void*)*((void**)(x))) + +#define CONST_UI8(x) CONST_READ_UI8(&(x)) +#define CONST_UI16(x) CONST_READ_UI16(&(x)) +#define CONST_UI32(x) CONST_READ_UI32(&(x)) +#define CONST_ADDR(x) CONST_READ_ADDR(&(x)) + +/* Endianness */ +#define ENDIANNESS LITTLE_ENDIAN + +/* Context switching */ + +#define BACKUP_CTX(sp) \ + asm ("mov r1, %0" : "=r"((sp)[0])); \ + +#define RESTORE_CTX(sp) \ + asm ("mov %0, r1" :: "r"((sp)[0])); \ + +/* in adequacy with msp430 registers usage, + * we only have to push and pop only from r6 to r11 */ +#define PUSHREGS asm( \ + "push r11\n" \ + "push r10\n" \ + "push r9\n" \ + "push r8\n" \ + "push r7\n" \ + "push r6\n" \ + ); \ + +#define POPREGS asm( \ + "pop r6\n" \ + "pop r7\n" \ + "pop r8\n" \ + "pop r9\n" \ + "pop r10\n" \ + "pop r11\n" \ + ); \ + +/* Smews configuration */ + +#define OUTPUT_BUFFER_SIZE 256 +#define ALLOC_SIZE 2048 +#define STACK_SIZE 64 + +/* Custom Functions */ +#define ADC_LIGHT INCH_4 +#define ADC_IR INCH_5 +#define ADC_TEMP INCH_10 +extern uint16_t initADC(unsigned char channel); +extern uint16_t GetADCVal(unsigned char channel); + +#endif /* __TARGET_H__ */ diff --git a/targets/WSN430/install b/targets/WSN430/install new file mode 100755 index 0000000000000000000000000000000000000000..58a6248b9347b0d8b87b7aa4fdf72d3d869c645a --- /dev/null +++ b/targets/WSN430/install @@ -0,0 +1 @@ +msp430-jtag -e ./bin/WSN430/smews.elf diff --git a/targets/WSN430wireless/SConscript b/targets/WSN430wireless/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..a45ec254dfbff35851f852c2e7b5e92219247bed --- /dev/null +++ b/targets/WSN430wireless/SConscript @@ -0,0 +1,45 @@ +# Copyright or c or Copr. 2008, Simon Duquennoy +# +# Author e-mail: simon.duquennoy@lifl.fr +# +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + + +import os +import sys + +Import('env binDir projectName elfName') + +env.Replace(CC = 'msp430-gcc') +env.Replace(AS = 'msp430-as') +env.Replace(AR = 'msp430-ar') +env.Replace(RANLIB = 'msp430-ranlib') +env.Append(CCFLAGS = '-mmcu=msp430x1611 -ffunction-sections') +env.Append(LINKFLAGS = '-mmcu=msp430x1611 -Wl,--gc-sections,--undefined=_reset_vector__,--undefined=InterruptVectors,--undefined=_copy_data_init__,--undefined=_clear_bss_init__,--undefined=_end_of_init__') diff --git a/targets/WSN430wireless/relay_transmitter/Makefile b/targets/WSN430wireless/relay_transmitter/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..51e1f39877172dd9c4d2866484bc449f6f289f2c --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/Makefile @@ -0,0 +1,24 @@ +CC = msp430-gcc +CFLAGS = -mmcu=msp430x1611 -ffunction-sections + +BINARIES = serie_to_radio +OBJ = serie_to_radio.o cc1100.o serial_line.o hardware.o spi1.o +all: $(BINARIES) + +serie_to_radio: $(OBJ) + $(CC) $(CFLAGS) -o serie_to_radio $(OBJ) + +serie_to_radio.o: serie_to_radio.c + $(CC) -c $(CFLAGS) serie_to_radio.c +cc1100.o: cc1100.c + $(CC) -c $(CFLAGS) cc1100.c +serial_line.o: serial_line.c + $(CC) -c $(CFLAGS) serial_line.c +hardware.o: hardware.c + $(CC) -c $(CFLAGS) hardware.c +spi1.o: spi1.c + $(CC) -c $(CFLAGS) spi1.c + +.PHONY: clean +clean: + $(RM) $(BINARIES) *.o *~ diff --git a/targets/WSN430wireless/relay_transmitter/cc1100.c b/targets/WSN430wireless/relay_transmitter/cc1100.c new file mode 100755 index 0000000000000000000000000000000000000000..6b1cebfcc2194417496c7adcfc931723a06329f6 --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/cc1100.c @@ -0,0 +1,237 @@ +/* + * Copyright 2008-2009 INRIA/SensTools + * + * <dev-team@sentools.info> + * + * This software is a set of libraries designed to develop applications + * for the WSN430 embedded hardware platform. + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. + */ + +/** + * \addtogroup cc1100 + * @{ + */ + +/** + * \file + * \brief CC1100 driver implementation + * \author Guillaume Chelius <guillaume.chelius@inria.fr> + * \author Antoine Fraboulet <antoine.fraboulet@insa-lyon.fr> + * \author Colin Chaballier + * \author Clément Burin des Roziers <clement.burin-des-roziers@inria.fr> + * \date October 08 + */ + +/** + * @} + */ + +#include <io.h> +#include <signal.h> + +#include "spi1.h" + +#include "cc1100.h" +#include "cc1100_gdo.h" +#include "cc1100_globals.h" + +static uint16_t (*gdo0_cb)(void); +static uint16_t (*gdo2_cb)(void); + +void inline micro_delay(register unsigned int n) +{ + __asm__ __volatile__ ( + "1: \n" + " dec %[n] \n" + " jne 1b \n" + : [n] "+r"(n)); +} + +void cc1100_reinit(void) +{ + spi1_init(); +} + +critical void cc1100_init(void) +{ + gdo0_cb = 0x0; + gdo2_cb = 0x0; + + spi1_init(); + GDO_INIT(); + + spi1_select(SPI1_CC1100); + spi1_deselect(SPI1_CC1100); + spi1_select(SPI1_CC1100); + spi1_deselect(SPI1_CC1100); + micro_delay(80); + spi1_select(SPI1_CC1100); + while (spi1_read_somi()) ; + spi1_write_single(CC1100_STROBE_SRES | CC1100_ACCESS_STROBE); + while (spi1_read_somi()) ; + spi1_deselect(SPI1_CC1100); + + + // write default frequency : 868MHz + cc1100_write_reg(CC1100_REG_FREQ2, 0x20); + cc1100_write_reg(CC1100_REG_FREQ1, 0x25); + cc1100_write_reg(CC1100_REG_FREQ0, 0xED); + + // value from SmartRF + cc1100_write_reg(CC1100_REG_DEVIATN, 0x0); +} + +critical uint8_t cc1100_read_reg(uint8_t addr) +{ + uint8_t reg; + spi1_select(SPI1_CC1100); + spi1_write_single(addr | CC1100_ACCESS_READ); + reg = spi1_read_single(); + spi1_deselect(SPI1_CC1100); + return reg; +} + +critical void cc1100_write_reg(uint8_t addr, uint8_t value) +{ + spi1_select(SPI1_CC1100); + spi1_write_single(addr | CC1100_ACCESS_WRITE); + spi1_write_single(value); + spi1_deselect(SPI1_CC1100); +} + +critical uint8_t cc1100_strobe_cmd(uint8_t cmd) +{ + uint8_t ret; + spi1_select(SPI1_CC1100); + ret = spi1_write_single(cmd | CC1100_ACCESS_STROBE); + spi1_deselect(SPI1_CC1100); + return ret; +} + +critical void cc1100_fifo_put(uint8_t* buffer, uint16_t length) +{ + spi1_select(SPI1_CC1100); + spi1_write_single(CC1100_DATA_FIFO_ADDR | CC1100_ACCESS_WRITE_BURST); + spi1_write(buffer, length); + spi1_deselect(SPI1_CC1100); +} + +critical void cc1100_fifo_get(uint8_t* buffer, uint16_t length) +{ + spi1_select(SPI1_CC1100); + spi1_write_single(CC1100_DATA_FIFO_ADDR | CC1100_ACCESS_READ_BURST); + spi1_read(buffer, length); + spi1_deselect(SPI1_CC1100); +} + +critical uint8_t cc1100_read_status(uint8_t addr) +{ + return cc1100_read_reg(addr | CC1100_ACCESS_STATUS); +} + + +void cc1100_gdo0_register_callback(uint16_t (*cb)(void)) +{ + gdo0_cb = cb; +} + +void cc1100_gdo2_register_callback(uint16_t (*cb)(void)) +{ + gdo2_cb = cb; +} + +#define STATE_IDLE 0 +#define STATE_RX 1 +#define STATE_TX 2 +#define STATE_FSTXON 3 +#define STATE_CALIB 4 +#define STATE_SETTL 5 +#define STATE_RXOVER 6 +#define STATE_TXUNDER 7 + +#define WAIT_STATUS(status) \ + while ( ((cc1100_cmd_nop()>>4) & 0x7) != status) ; + +void cc1100_cmd_calibrate(void) +{ + cc1100_cmd_idle(); + cc1100_strobe_cmd(CC1100_STROBE_SCAL); + WAIT_STATUS(STATE_IDLE); +} + +void cc1100_cmd_idle(void) +{ + switch ((cc1100_cmd_nop() >> 4) & 0x7) + { + case STATE_RXOVER: + cc1100_cmd_flush_rx(); + break; + case STATE_TXUNDER: + cc1100_cmd_flush_tx(); + break; + default: + cc1100_strobe_cmd(CC1100_STROBE_SIDLE); + } + WAIT_STATUS(STATE_IDLE); +} + + +void port1irq(void); +/** + * Interrupt service routine for PORT1. + * Used for handling CC1100 interrupts triggered on + * the GDOx pins. + */ +interrupt(PORT1_VECTOR) port1irq(void) +{ + if (P1IFG & GDO0_PIN) + { + GDO0_INT_CLEAR(); + if (gdo0_cb != 0x0) + { + if (gdo0_cb()) + { + LPM4_EXIT; + } + } + } + + if (P1IFG & GDO2_PIN) + { + GDO2_INT_CLEAR(); + if (gdo2_cb != 0x0) + { + if (gdo2_cb()) + { + LPM4_EXIT; + } + } + } +} + diff --git a/targets/WSN430wireless/relay_transmitter/cc1100.h b/targets/WSN430wireless/relay_transmitter/cc1100.h new file mode 100755 index 0000000000000000000000000000000000000000..b6813ceb3b3066608a05b1b715c372213996709e --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/cc1100.h @@ -0,0 +1,960 @@ +/* + * Copyright 2008-2009 INRIA/SensTools + * + * <dev-team@sentools.info> + * + * This software is a set of libraries designed to develop applications + * for the WSN430 embedded hardware platform. + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. + */ + +/** + * \defgroup cc1100 CC1100 radio driver + * \ingroup wsn430 + * @{ + * This module allows the user to control the CC1100 radio chip. + * + * The CC1100 is a sub 1GHz radio chip offering a wide + * range of configuration options, such as frequency, bandwidth, + * datarate, modulation, power, etc... + * It may be fine-tuned to do many wireless network protocols. + */ + +/** + * \file + * \brief CC1100 driver header + * \author Guillaume Chelius <guillaume.chelius@inria.fr> + * \author Antoine Fraboulet <antoine.fraboulet@insa-lyon.fr> + * \author Colin Chaballier + * \author Clément Burin des Roziers <clement.burin-des-roziers@inria.fr> + * \date October 08 + */ +#ifndef _CC1100_H +#define _CC1100_H + +#include "cc1100_globals.h" +#include "cc1100_gdo.h" + +// other +void micro_delay(register unsigned int n); + +// real functions +/** + * \brief radio initialization procedure + */ +void cc1100_init(void); + +/** + * \brief Re-initialize the SPI driver only + */ +void cc1100_reinit(void); + +/** + * \brief read the content of any cc1100 register + * \param addr the address of the register + * \return the value of the register + */ +uint8_t cc1100_read_reg(uint8_t addr); + +/** + * \brief write a value to any cc1100 register + * \param addr the address of the register + * \param value the value of to be written + */ +void cc1100_write_reg(uint8_t addr, uint8_t value); + +/** + * \brief copy a buffer to the radio TX FIFO + * \param buffer a pointer to the buffer + * \param length the number of bytes to copy + */ +void cc1100_fifo_put(uint8_t* buffer, uint16_t length); + +/** + * \brief copy the content of the radio RX FIFO to a buffer + * \param buffer a pointer to the buffer + * \param length the number of bytes to copy + **/ +void cc1100_fifo_get(uint8_t* buffer, uint16_t length); + +/** + * \brief read a cc1100 status register + * \param addr the address of the register + * \return the value of the register + */ +uint8_t cc1100_read_status(uint8_t addr); + +/** + * \brief strobe a command to the CC1100 + * \param cmd the command to strobe + * \return the status byte read while strobing + */ +uint8_t cc1100_strobe_cmd(uint8_t cmd); + + +// status byte +#define cc1100_status() \ + cc1100_strobe_cmd(CC1100_STROBE_SNOP) + +// commands macros + +/** + * \brief force chip to reset all registers to default state + */ +#define cc1100_cmd_reset() \ + cc1100_strobe_cmd(CC1100_STROBE_SRES) + +/** + * \brief stop cristal oscillator + */ +#define cc1100_cmd_xoff() \ + cc1100_strobe_cmd(CC1100_STROBE_SXOFF) + +/** + * \brief calibrate frequency synthetizer + */ +void cc1100_cmd_calibrate(void); + +/** + * \brief enable rx. + */ +#define cc1100_cmd_rx() \ + cc1100_strobe_cmd(CC1100_STROBE_SRX) + +/** + * \brief enable tx. if in rx with cca enabled, go to tx if channel clear + */ +#define cc1100_cmd_tx() \ + cc1100_strobe_cmd(CC1100_STROBE_STX) + +/** + * \brief stop tx/rx/calibration/wor + */ +void cc1100_cmd_idle(void); + +/** + * \brief start wake-on-radio : periodic channel sampling with RX polling + */ +#define cc1100_cmd_wor() \ + cc1100_strobe_cmd(CC1100_STROBE_SWOR) + +/** + * \brief enter power down + */ +#define cc1100_cmd_pwd() \ + cc1100_strobe_cmd(CC1100_STROBE_SPWD) + +/** + * \brief flush RX FIFO + */ +#define cc1100_cmd_flush_rx() \ + cc1100_strobe_cmd(CC1100_STROBE_SFRX) + +/** + * \brief flush TX FIFO + */ +#define cc1100_cmd_flush_tx() \ + cc1100_strobe_cmd(CC1100_STROBE_SFTX) + +/** + * \brief reset real time clock to Event1 value for WOR + */ +#define cc1100_cmd_reset_wor() \ + cc1100_strobe_cmd(CC1100_STROBE_SWORRST) + +/** + * \brief does nothing, update status byte + */ +#define cc1100_cmd_nop() \ + cc1100_strobe_cmd(CC1100_STROBE_SNOP) + + +// Power Table Config +/** + * \brief configure the radio chip with the given power + * \param power the first table value to use (no shaping supported) + */ +#define cc1100_cfg_patable(table, length) \ + cc1100_write_reg(CC1100_PATABLE_ADDR | CC1100_ACCESS_WRITE_BURST, (table)[0]) + +/** + * \name GDOx configuration constants + * @{ + */ +#define CC1100_GDOx_RX_FIFO 0x00 /* assert above threshold, deassert when below */ +#define CC1100_GDOx_RX_FIFO_EOP 0x01 /* assert above threshold or EOP, deassert when empty */ +#define CC1100_GDOx_TX_FIFO 0x02 /* assert above threshold, deassert when below */ +#define CC1100_GDOx_TX_THR_FULL 0x03 /* asserts TX FIFO full. De-asserts when below thr */ +#define CC1100_GDOx_RX_OVER 0x04 /* asserts when RX overflow, deassert when flushed */ +#define CC1100_GDOx_TX_UNDER 0x05 /* asserts when RX underflow, deassert when flushed */ +#define CC1100_GDOx_SYNC_WORD 0x06 /* assert SYNC sent/recv, deasserts on EOP */ + /* In RX, de-assert on overflow or bad address */ + /* In TX, de-assert on underflow */ +#define CC1100_GDOx_RX_OK 0x07 /* assert when RX PKT with CRC ok, de-assert on 1byte */ + /* read from RX Fifo */ +#define CC1100_GDOx_PREAMB_OK 0x08 /* assert when preamble quality reached : PQI/PQT ok */ +#define CC1100_GDOx_CCA 0x09 /* Clear channel assessment. High when RSSI level is */ + /* below threshold (dependent on the current CCA_MODE) */ +/** + * @} + */ + +/** + * \brief Configure the gdo0 output pin. + * + * Example : use 0x06 for sync/eop or 0x0 for rx fifo threshold + * \param cfg the configuration value + */ +#define cc1100_cfg_gdo0(cfg) \ + cc1100_write_reg(CC1100_REG_IOCFG0, cfg) + +/** + * \brief Configure the gdo2 output pin. + * + * Example : use 0x06 for sync/eop or 0x0 for rx fifo threshold + * \param cfg the configuration value + */ +#define cc1100_cfg_gdo2(cfg) \ + cc1100_write_reg(CC1100_REG_IOCFG2, cfg) + +/** + * \brief Set the threshold for both RX and TX FIFOs. + * corresponding values are : + * + * value 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 \n + * TX 61 | 57 | 53 | 49 | 45 | 41 | 37 | 33 | 29 | 25 | 21 | 17 | 13 | 9 | 5 | 1 \n + * RX 4 | 8 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 + * + * \param cfg the configuration value + */ +#define cc1100_cfg_fifo_thr(cfg) \ + cc1100_write_reg(CC1100_REG_FIFOTHR, ((cfg)&0x0F)) + +/** + * \brief Set the packet length in fixed packet length mode + * or the maximum packet length in variable length mode + * \param cfg the configuration value + */ +#define cc1100_cfg_packet_length(cfg) \ + cc1100_write_reg(CC1100_REG_PKTLEN, (cfg)) + +/** + * \brief Set the preamble quality estimator threshold + * (values are 0-7) + * \param cfg the configuration value + */ +#define cc1100_cfg_pqt(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_PKTCTRL1); \ + reg = (reg & 0x1F) | (((cfg) << 5) & 0xE0); \ + cc1100_write_reg(CC1100_REG_PKTCTRL1, reg); \ +} while (0) + +/** + * \name CRC Autoflush configuration constants + * @{ + */ +#define CC1100_CRC_AUTOFLUSH_ENABLE 0x1 +#define CC1100_CRC_AUTOFLUSH_DISABLE 0x0 +/** + * @} + */ + +/** + * \brief enable/disable the automatic flush of RX FIFO when CRC is not OK + * \param cfg the configuration value + */ +#define cc1100_cfg_crc_autoflush(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_PKTCTRL1); \ + reg = (reg & 0xF7) | (((cfg) << 3) & 0x08); \ + cc1100_write_reg(CC1100_REG_PKTCTRL1, reg); \ +} while (0) + +/** + * \name Append status configuration constants + * @{ + */ +#define CC1100_APPEND_STATUS_ENABLE 0x1 +#define CC1100_APPEND_STATUS_DISABLE 0x0 +/** + * @} + */ + +/** + * \brief enable/disable the appending of 2 information bytes at the end of + * a received packet. + * + * Two extra bytes need to be read from the RXFIFO if the appending is set. + * The first contains the RSSI of the received signal, the second contains + * the CRC result on the most significant bit, and the LQI on the 7 others. + * \param cfg the configuration value + */ +#define cc1100_cfg_append_status(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_PKTCTRL1); \ + reg = (reg & 0xFB) | (((cfg) << 2) & 0x04); \ + cc1100_write_reg(CC1100_REG_PKTCTRL1, reg); \ +} while (0) + +/** + * \name Address check configuration constants + * @{ + */ +#define CC1100_ADDR_NO_CHECK 0x0 +#define CC1100_ADDR_CHECK_NO_BROADCAST 0x1 +#define CC1100_ADDR_CHECK_BROADCAST_0 0x2 +#define CC1100_ADDR_CHECK_NO_BROADCAST_0_255 0x3 +/** + * @} + */ + +/** + * \brief control the address check mode + * \param cfg the configuration value + */ +#define cc1100_cfg_adr_check(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_PKTCTRL1); \ + reg = (reg & 0xFC) | (((cfg) << 0) & 0x03); \ + cc1100_write_reg(CC1100_REG_PKTCTRL1, reg); \ +} while (0) + +/** + * \name Data whitening configuration constants + * @{ + */ +#define CC1100_DATA_WHITENING_ENABLE 0x1 +#define CC1100_DATA_WHITENING_DISABLE 0x0 +/** + * @} + */ + +/** + * \brief turn data whitening on/off + * \param cfg the configuration value + */ +#define cc1100_cfg_white_data(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_PKTCTRL0); \ + reg = (reg & 0xBF) | (((cfg) << 6) & 0x40); \ + cc1100_write_reg(CC1100_REG_PKTCTRL0, reg); \ +} while (0) + + +/** + * \name CRC calculation configuration constants + * @{ + */ +#define CC1100_CRC_CALCULATION_ENABLE 0x1 +#define CC1100_CRC_CALCULATION_DISABLE 0x0 +/** + * @} + */ + +/** + * \brief turn CRC calculation on/off + * \param cfg the configuration value + */ +#define cc1100_cfg_crc_en(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_PKTCTRL0); \ + reg = (reg & 0xFB) | (((cfg) << 2) & 0x04); \ + cc1100_write_reg(CC1100_REG_PKTCTRL0, reg); \ +} while (0) + +/** + * \name Packet length configuration constants + * @{ + */ +#define CC1100_PACKET_LENGTH_FIXED 0x0 +#define CC1100_PACKET_LENGTH_VARIABLE 0x1 +#define CC1100_PACKET_LENGTH_INFINITE 0x2 +/** + * @} + */ + +/** + * \brief configure the packet length mode + * \param cfg the configuration value + */ +#define cc1100_cfg_length_config(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_PKTCTRL0); \ + reg = (reg & 0xFC) | (((cfg) << 0) & 0x03); \ + cc1100_write_reg(CC1100_REG_PKTCTRL0, reg); \ +} while (0) + +/** + * \brief Set the device address for packet filtration + * \param cfg the configuration value + */ +#define cc1100_cfg_device_addr(cfg) \ + cc1100_write_reg(CC1100_REG_ADDR, (cfg)) + +/** + * \brief Set the channel number. + * \param cfg the configuration value + */ +#define cc1100_cfg_chan(cfg) \ + cc1100_write_reg(CC1100_REG_CHANNR, (cfg)) + +/** + * \brief Set the desired IF frequency. + * (values are 0-31) + * \param cfg the configuration value + */ +#define cc1100_cfg_freq_if(cfg) \ + cc1100_write_reg(CC1100_REG_FSCTRL1, ((cfg) & 0x1F)) + +/** + * \brief Set the desired base frequency. + * \param cfg the configuration value (22bits) + */ +#define cc1100_cfg_freq(cfg) do { \ + uint8_t reg; \ + reg = (uint8_t) ( ((cfg)>>16)&0xFF ); \ + cc1100_write_reg(CC1100_REG_FREQ2, reg); \ + reg = (uint8_t) ( ((cfg)>>8)&0xFF ); \ + cc1100_write_reg(CC1100_REG_FREQ1, reg); \ + reg = (uint8_t) ( (cfg)&0xFF ); \ + cc1100_write_reg(CC1100_REG_FREQ0, reg); \ +} while (0) + +/** + * \brief Set the exponent of the channel bandwidth + * (values are 0-3) + * \param cfg the configuration value + */ +#define cc1100_cfg_chanbw_e(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MDMCFG4); \ + reg = (reg & 0x3F) | (((cfg) << 6) & 0xC0); \ + cc1100_write_reg(CC1100_REG_MDMCFG4, reg); \ +} while (0) + +/** + * \brief Set mantissa of the channel bandwidth + * (values are 0-3) + * \param cfg the configuration value + */ +#define cc1100_cfg_chanbw_m(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MDMCFG4); \ + reg = (reg & 0xCF) | (((cfg)<<4) & 0x30); \ + cc1100_write_reg(CC1100_REG_MDMCFG4, reg); \ +} while (0) + +/** + * \brief Set the exponent of the data symbol rate + * (values are 0-16) + * \param cfg the configuration value + */ +#define cc1100_cfg_drate_e(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MDMCFG4); \ + reg = (reg & 0xF0) | (((cfg)) & 0x0F); \ + cc1100_write_reg(CC1100_REG_MDMCFG4, reg); \ +} while (0) + +/** + * \brief Set the mantissa of the data symbol rate + * (values are 0-255) + * \param cfg the configuration value + */ +#define cc1100_cfg_drate_m(cfg) \ + cc1100_write_reg(CC1100_REG_MDMCFG3, (cfg)) + +/** + * \name Modulation configuration constants + * @{ + */ +#define CC1100_MODULATION_2FSK 0x00 +#define CC1100_MODULATION_GFSK 0x01 +#define CC1100_MODULATION_ASK 0x03 +#define CC1100_MODULATION_MSK 0x07 +/** + * @} + */ +/** + * \brief Set the signal modulation + * \param cfg the configuration value + */ +#define cc1100_cfg_mod_format(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MDMCFG2); \ + reg = (reg & 0x8F) | (((cfg) << 4) & 0x70); \ + cc1100_write_reg(CC1100_REG_MDMCFG2, reg); \ +} while (0) + +/** + * \name Manchester encoding configuration constants + * @{ + */ +#define CC1100_MANCHESTER_ENABLE 0x1 +#define CC1100_MANCHESTER_DISABLE 0x0 +/** + * @} + */ +/** + * \brief Set manchester encoding on/off + * \param cfg the configuration value + */ +#define cc1100_cfg_manchester_en(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MDMCFG2); \ + reg = (reg & 0xF7) | (((cfg) << 3) & 0x08); \ + cc1100_write_reg(CC1100_REG_MDMCFG2, reg); \ +} while (0) + + +/** + * \name Sync mode configuration constants + * @{ + */ +#define CC1100_SYNCMODE_NO_PREAMB 0x0 +#define CC1100_SYNCMODE_15_16 0x1 +#define CC1100_SYNCMODE_16_16 0x2 +#define CC1100_SYNCMODE_30_32 0x3 +#define CC1100_SYNCMODE_NO_PREAMB_CS 0x4 +#define CC1100_SYNCMODE_15_16_CS 0x5 +#define CC1100_SYNCMODE_16_16_CS 0x6 +#define CC1100_SYNCMODE_30_32_CS 0x7 +/** + * @} + */ +/** + * \brief select the sync-word qualifier mode + * \param cfg the configuration value + */ +#define cc1100_cfg_sync_mode(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MDMCFG2); \ + reg = (reg & 0xF8) | (((cfg) << 0) & 0x07); \ + cc1100_write_reg(CC1100_REG_MDMCFG2, reg); \ +} while (0) + +/** + * \name FEC configuration constants + * @{ + */ +#define CC1100_FEC_ENABLE 0x1 +#define CC1100_FEC_DISABLE 0x0 +/** + * @} + */ +/** + * \brief Set forward error correction on/off + * supported in fixed packet length mode only + * \param cfg the configuration value + */ +#define cc1100_cfg_fec_en(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MDMCFG1); \ + reg = (reg & 0x7F) | (((cfg) << 7) & 0x80); \ + cc1100_write_reg(CC1100_REG_MDMCFG1, reg); \ +} while (0) + +/** + * \brief Set the minimum number of preamble bytes to be tramsitted \n + * Setting : 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 \n + * nb. of bytes : 2 | 3 | 4 | 6 | 8 | 12 | 16 | 24 + * \param cfg the configuration value + */ +#define cc1100_cfg_num_preamble(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MDMCFG1); \ + reg = (reg & 0x8F) | (((cfg) << 4) & 0x70); \ + cc1100_write_reg(CC1100_REG_MDMCFG1, reg); \ +} while (0) + +/** + * \brief Set the channel spacing exponent + * (values are 0-3) + * \param cfg the configuration value + */ +#define cc1100_cfg_chanspc_e(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MDMCFG1); \ + reg = (reg & 0xFE) | (((cfg) << 0) & 0x01); \ + cc1100_write_reg(CC1100_REG_MDMCFG1, reg); \ +} while (0) + +/** + * \brief Set the channel spacing mantissa + * (values are 0-255) + * \param cfg the configuration value + */ +#define cc1100_cfg_chanspc_m(cfg) \ + cc1100_write_reg(CC1100_REG_MDMCFG0, (cfg)) + +/** + * \name RC oscillator configuration constants + * @{ + */ +#define CC1100_RX_TIME_RSSI_ENABLE 0x1 +#define CC1100_RX_TIME_RSSI_DISABLE 0x0 +/** + * @} + */ +/** + * \brief Set direct RX termination based on rssi measurement + * \param cfg the configuration value + */ +#define cc1100_cfg_rx_time_rssi(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MCSM2); \ + reg = (reg & 0xEF) | (((cfg) << 4) & 0x10); \ + cc1100_write_reg(CC1100_REG_MCSM2, reg); \ +} while (0) + +/** + * \brief Set timeout for syncword search in RX for WOR and normal op + * (values are 0-7) + * \param cfg the configuration value + */ +#define cc1100_cfg_rx_time(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MCSM2); \ + reg = (reg & 0xF8) | (((cfg) << 0) & 0x07); \ + cc1100_write_reg(CC1100_REG_MCSM2, reg); \ +} while (0) + +/** + * \name CCA mode configuration constants + * @{ + */ +#define CC1100_CCA_MODE_ALWAYS 0x0 +#define CC1100_CCA_MODE_RSSI 0x1 +#define CC1100_CCA_MODE_PKT_RX 0x2 +#define CC1100_CCA_MODE_RSSI_PKT_RX 0x3 +/** + * @} + */ +/** + * \brief Set the CCA mode reflected in CCA signal + * \param cfg the configuration value + */ +#define cc1100_cfg_cca_mode(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MCSM1); \ + reg = (reg & 0xCF) | (((cfg) << 4) & 0x30); \ + cc1100_write_reg(CC1100_REG_MCSM1, reg); \ +} while (0) + +/** + * \name RXOFF mode configuration constants + * @{ + */ +#define CC1100_RXOFF_MODE_IDLE 0x00 +#define CC1100_RXOFF_MODE_FSTXON 0x01 /* freq synth on, ready to Tx */ +#define CC1100_RXOFF_MODE_TX 0x02 +#define CC1100_RXOFF_MODE_STAY_RX 0x03 +/** + * @} + */ +/** + * \brief Set the behavior after a packet RX + * \param cfg the configuration value + */ +#define cc1100_cfg_rxoff_mode(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MCSM1); \ + reg = (reg & 0xF3) | (((cfg) << 2) & 0x0C); \ + cc1100_write_reg(CC1100_REG_MCSM1, reg); \ +} while (0) + +/** + * \name TXOFF mode configuration constants + * @{ + */ +#define CC1100_TXOFF_MODE_IDLE 0x00 +#define CC1100_TXOFF_MODE_FSTXON 0x01 /* freq synth on, ready to Tx */ +#define CC1100_TXOFF_MODE_STAY_TX 0x02 +#define CC1100_TXOFF_MODE_RX 0x03 +/** + * @} + */ +/** + * \brief Set the behavior after packet TX + * \param cfg the configuration value + */ +#define cc1100_cfg_txoff_mode(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MCSM1); \ + reg = (reg & 0xFC) | (((cfg) << 0) & 0x03); \ + cc1100_write_reg(CC1100_REG_MCSM1, reg); \ +} while (0) + + +/** + * \name Automatic calibration configuration constants + * @{ + */ +#define CC1100_AUTOCAL_NEVER 0x00 +#define CC1100_AUTOCAL_IDLE_TO_TX_RX 0x01 +#define CC1100_AUTOCAL_TX_RX_TO_IDLE 0x02 +#define CC1100_AUTOCAL_4TH_TX_RX_TO_IDLE 0x03 +/** + * @} + */ +/** + * \brief Set auto calibration policy + * \param cfg the configuration value + */ +#define cc1100_cfg_fs_autocal(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_MCSM0); \ + reg = (reg & 0xCF) | (((cfg) << 4) & 0x30); \ + cc1100_write_reg(CC1100_REG_MCSM0, reg); \ +} while (0) + +/** + * \brief Set the relative threshold for asserting Carrier Sense \n + * Setting : 0 | 1 | 2 | 3 \n + * thr : disabled | 6dB | 10dB | 14dB \n + * \param cfg the configuration value + */ +#define cc1100_cfg_carrier_sense_rel_thr(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_AGCCTRL1); \ + reg = (reg & 0xCF) | (((cfg) << 4) & 0x30); \ + cc1100_write_reg(CC1100_REG_AGCCTRL1, reg); \ +} while (0) + +/** + * \brief Set the absolute threshold for asserting Carrier Sense + * referenced to MAGN_TARGET \n + * Setting : -8 | -7 | -1 | 0 | 1 | 7 \n + * thr : disabled | -7dB | -1dB | at MAGN_TARGET | 1dB | 7dB \n + * \param cfg the configuration value + */ +#define cc1100_cfg_carrier_sense_abs_thr(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_AGCCTRL1); \ + reg = (reg & 0xF0) | (((cfg) << 0) & 0x0F); \ + cc1100_write_reg(CC1100_REG_AGCCTRL1, reg); \ +} while (0) + +/** + * \brief Set event0 timeout register for WOR operation + * \param cfg the configuration value + */ +#define cc1100_cfg_event0(cfg) do { \ + uint8_t reg; \ + reg = (uint8_t)((cfg >> 8) & 0xFF); \ + cc1100_write_reg(CC1100_REG_WOREVT1, reg); \ + reg = (uint8_t)((cfg) & 0xFF); \ + cc1100_write_reg(CC1100_REG_WOREVT0, reg); \ +} while (0) + +/** + * \name RC oscillator configuration constants + * @{ + */ +#define CC1100_RC_OSC_ENABLE 0x0 +#define CC1100_RC_OSC_DISABLE 0x1 +/** + * @} + */ + +/** + * \brief Set the RC oscillator on/off, needed by WOR + * \param cfg the configuration value + */ +#define cc1100_cfg_rc_pd(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_WORCTRL); \ + reg = (reg & 0x7F) | (((cfg) << 7) & 0x80); \ + cc1100_write_reg(CC1100_REG_WORCTRL, reg); \ +} while (0) + +/** + * \brief Set the event1 timeout register + * \param cfg the configuration value + */ +#define cc1100_cfg_event1(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_WORCTRL); \ + reg = (reg & 0x8F) | (((cfg) << 4) & 0x70); \ + cc1100_write_reg(CC1100_REG_WORCTRL, reg); \ +} while (0) + +/** + * \brief Set the WOR resolution + * \param cfg the configuration value + */ +#define cc1100_cfg_wor_res(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_WORCTRL); \ + reg = (reg & 0xFC) | (((cfg) << 0) & 0x03); \ + cc1100_write_reg(CC1100_REG_WORCTRL, reg); \ +} while (0) + +/** + * \brief select the PA power setting, index of the patable + * \param cfg the configuration value + */ +#define cc1100_cfg_pa_power(cfg) do { \ + uint8_t reg; \ + reg = cc1100_read_reg(CC1100_REG_FREND0); \ + reg = (reg & 0xF8) | (((cfg) << 0) & 0x07); \ + cc1100_write_reg(CC1100_REG_FREND0, reg); \ +} while (0) + +// Status Registers access +/** + * \brief read the register containing the last CRC calculation match + * and LQI estimate + */ +#define cc1100_status_crc_lqi() \ + cc1100_read_status(CC1100_REG_LQI) + +/** + * \brief read the RSSI + */ +#define cc1100_status_rssi() \ + cc1100_read_status(CC1100_REG_RSSI) + +/** + * \brief read the main radio state machine state + */ +#define cc1100_status_marcstate() \ + cc1100_read_status(CC1100_REG_MARCSTATE) + +/** + * \brief read the high byte of the WOR timer + */ +#define cc1100_status_wortime1() \ + cc1100_read_status(CC1100_REG_WORTIME1) + +/** + * \brief read the low byte of the WOR timer + */ +#define cc1100_status_wortime0() \ + cc1100_read_status(CC1100_REG_WORTIME0) + +/** + * \brief read the packet status register + */ +#define cc1100_status_pktstatus() \ + cc1100_read_status(CC1100_REG_PKTSTATUS) + +/** + * \brief read the number of bytes in TX FIFO + */ +#define cc1100_status_txbytes() \ + cc1100_read_status(CC1100_REG_TXBYTES) + +/** + * \brief read the number of bytes in RX FIFO + */ +#define cc1100_status_rxbytes() \ + cc1100_read_status(CC1100_REG_RXBYTES) + + +// GDOx int config & access + +/** + * \brief enable interrupt for GDO0 + */ +#define cc1100_gdo0_int_enable() \ + GDO0_INT_ENABLE() +/** + * \brief disable interrupt for GDO0 + */ +#define cc1100_gdo0_int_disable() \ + GDO0_INT_DISABLE() +/** + * \brief clear interrupt for GDO0 + */ +#define cc1100_gdo0_int_clear() \ + GDO0_INT_CLEAR() +/** + * \brief configure interrupt for GDO0 on high to low transition + */ +#define cc1100_gdo0_int_set_falling_edge() \ + GDO0_INT_SET_FALLING() +/** + * \brief configure interrupt for GDO0 on low to high transition + */ +#define cc1100_gdo0_int_set_rising_edge() \ + GDO0_INT_SET_RISING() +/** + * \brief read the state of GDO0 + */ +#define cc1100_gdo0_read() \ + GDO0_READ() + +/** + * \brief register a callback function for GDO0 interrupt + * \param cb a function pointer + */ +void cc1100_gdo0_register_callback(uint16_t (*cb)(void)); + +/** + * \brief enable interrupt for GDO2 + */ +#define cc1100_gdo2_int_enable() \ + GDO2_INT_ENABLE() +/** + * \brief disable interrupt for GDO2 + */ +#define cc1100_gdo2_int_disable() \ + GDO2_INT_DISABLE() +/** + * \brief clear interrupt for GDO2 + */ +#define cc1100_gdo2_int_clear() \ + GDO2_INT_CLEAR() +/** + * \brief configure interrupt for GDO2 on high to low transition + */ +#define cc1100_gdo2_int_set_falling_edge() \ + GDO2_INT_SET_FALLING() +/** + * \brief configure interrupt for GDO2 on low to high transition + */ +#define cc1100_gdo2_int_set_rising_edge() \ + GDO2_INT_SET_RISING() +/** + * \brief read the state of GDO2 + */ +#define cc1100_gdo2_read() \ + GDO2_READ() +/** + * \brief register a callback function for GDO2 interrupt + * \param cb a function pointer + */ +void cc1100_gdo2_register_callback(uint16_t (*cb)(void)); + +#endif + +/** + * @} + */ diff --git a/targets/WSN430wireless/relay_transmitter/cc1100_gdo.h b/targets/WSN430wireless/relay_transmitter/cc1100_gdo.h new file mode 100755 index 0000000000000000000000000000000000000000..ee64ae7371e8f8dc633bde3f2ae7921f00390c21 --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/cc1100_gdo.h @@ -0,0 +1,127 @@ +/* + * Copyright 2008-2009 INRIA/SensTools + * + * <dev-team@sentools.info> + * + * This software is a set of libraries designed to develop applications + * for the WSN430 embedded hardware platform. + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. + */ + +/** + * \addtogroup cc1100 + * @{ + */ + + +/** + * \file + * \brief CC1100 GDO PIN hardware abstraction + * \author Guillaume Chelius <guillaume.chelius@inria.fr> + * \author Antoine Fraboulet <antoine.fraboulet@insa-lyon.fr> + * \author Colin Chaballier + * \author Clément Burin des Roziers <clement.burin-des-roziers@inria.fr> + * \date October 08 + */ + +/** + * @} + */ + +#ifndef _CC1100_GDO_H +#define _CC1100_GDO_H + +#define GDO0_PIN (1<<3) +#define GDO2_PIN (1<<4) + +/** + * \brief Initialize IO PORT for GDO connectivity + **/ +#define GDO_INIT() do \ +{ \ + P1SEL &= ~(GDO0_PIN | GDO2_PIN); \ + P1DIR &= ~(GDO0_PIN | GDO2_PIN); \ + P1IE &= ~(GDO0_PIN | GDO2_PIN); \ +} while (0) + +/** + * \brief Enable Interrupt for GDO0 pin + **/ +#define GDO0_INT_ENABLE() P1IE |= GDO0_PIN + +/** + * \brief Enable Interrupt for GDO2 pin + **/ +#define GDO2_INT_ENABLE() P1IE |= GDO2_PIN + +/** + * \brief Disable Interrupt for GDO0 pin + **/ +#define GDO0_INT_DISABLE() P1IE &= ~GDO0_PIN + +/** + * \brief Disable Interrupt for GDO2 pin + **/ +#define GDO2_INT_DISABLE() P1IE &= ~GDO2_PIN + +/** + * \brief Clear interrupt flag for GDO0 pin + **/ +#define GDO0_INT_CLEAR() P1IFG &= ~GDO0_PIN +/** + * \brief Clear interrupt flag for GDO2 pin + **/ +#define GDO2_INT_CLEAR() P1IFG &= ~GDO2_PIN + +/** + * \brief Set interrupt on rising edge for GDO0 pin + **/ +#define GDO0_INT_SET_RISING() P1IES &= ~GDO0_PIN +/** + * \brief Set interrupt on falling edge for GDO0 pin + **/ +#define GDO0_INT_SET_FALLING() P1IES |= GDO0_PIN +/** + * \brief Set interrupt on rising edge for GDO2 pin + **/ +#define GDO2_INT_SET_RISING() P1IES &= ~GDO2_PIN +/** + * \brief Set interrupt on falling edge for GDO2 pin + **/ +#define GDO2_INT_SET_FALLING() P1IES |= GDO2_PIN + +/** + * \brief Read GDO0 pin value + **/ +#define GDO0_READ() (P1IN & GDO0_PIN) +/** + * \brief Read GDO2 pin value + **/ +#define GDO2_READ() (P1IN & GDO2_PIN) + +#endif diff --git a/targets/WSN430wireless/relay_transmitter/cc1100_globals.h b/targets/WSN430wireless/relay_transmitter/cc1100_globals.h new file mode 100755 index 0000000000000000000000000000000000000000..437e06975183ded1afb1d729a97d6d0c0c05de4b --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/cc1100_globals.h @@ -0,0 +1,355 @@ +/* + * Copyright 2008-2009 INRIA/SensTools + * + * <dev-team@sentools.info> + * + * This software is a set of libraries designed to develop applications + * for the WSN430 embedded hardware platform. + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. + */ + +/** + * \addtogroup cc1100 + * @{ + */ + + +/** + * \file + * \brief Configuration registers addresses and default values + * \author Guillaume Chelius <guillaume.chelius@inria.fr> + * \date 20/11/05. + */ + + +/** + * @} + */ + +#ifndef _CC1100_GLOBALS_H +#define _CC1100_GLOBALS_H + + +/** + * \name CC1100 time constants + * @{ + */ +#define CC1100_POWER_UP_DELAY_NS 40000 +#define CC1100_POWER_UP_DELAY_US 40 +#define CC1100_MANCAL_DELAY_NS 721000 +#define CC1100_MANCAL_DELAY_US 721 +#define CC1100_FS_WAKEUP_DELAY_NS 44200 +#define CC1100_FS_WAKEUP_DELAY_US 45 +#define CC1100_SETTLING_DELAY_NS 44200 +#define CC1100_SETTLING_DELAY_US 44 +#define CC1100_CALIBRATE_DELAY_NS 720600 +#define CC1100_CALIBRATE_DELAY_US 720 +#define CC1100_IDLE_NOCAL_DELAY_NS 100 +#define CC1100_IDLE_NOCAL_DELAY_US 1 +#define CC1100_TX_RX_DELAY_NS 21500 +#define CC1100_TX_RX_DELAY_US 22 +#define CC1100_RX_TX_DELAY_NS 9600 +#define CC1100_RX_TX_DELAY_US 10 +/** + * @} + */ + +/** + * \name CC1100 State Machine in status byte + * @{ + */ +#define CC1100_STATUS_IDLE 0x00 +#define CC1100_STATUS_RX 0x01 +#define CC1100_STATUS_TX 0x02 +#define CC1100_STATUS_FSTXON 0x03 +#define CC1100_STATUS_CALIBRATE 0x04 +#define CC1100_STATUS_SETTLING 0x05 +#define CC1100_STATUS_RXFIFO_OVERFLOW 0x06 +#define CC1100_STATUS_TXFIFO_UNDERFLOW 0x07 +/** + * @} + */ + + +/** + * \name CC1100 internal states + * @{ + */ +#define CC1100_STATE_SLEEP 0x00 +#define CC1100_STATE_IDLE 0x01 +#define CC1100_STATE_XOFF 0x02 +#define CC1100_STATE_MANCAL 0x03 +#define CC1100_STATE_FS_WAKEUP 0x06 +#define CC1100_STATE_FS_CALIBRATE 0x08 +#define CC1100_STATE_SETTLING 0x09 +#define CC1100_STATE_CALIBRATE 0x12 +#define CC1100_STATE_RX 0x13 +#define CC1100_STATE_TXRX_SETTLING 0x16 +#define CC1100_STATE_RX_OVERFLOW 0x17 +#define CC1100_STATE_FSTXON 0x18 +#define CC1100_STATE_TX 0x19 +#define CC1100_STATE_RXTX_SETTLING 0x21 +#define CC1100_STATE_TX_UNDERFLOW 0x22 +#define CC1100_STATE_IDLING 0x23 +/** + * @} + */ + + +/** + * \name CC1100 RAM & register Access + * @{ + */ +#define CC1100_ACCESS_READ 0x80 +#define CC1100_ACCESS_READ_BURST 0xC0 +#define CC1100_ACCESS_WRITE 0x00 +#define CC1100_ACCESS_WRITE_BURST 0x40 +#define CC1100_ACCESS_STATUS 0xC0 +#define CC1100_ACCESS_STROBE 0x00 + +/** + * @} + */ + +/** + * \name C1100 Strobe commands + * @{ + */ +#define CC1100_STROBE_SRES 0x30 /* reset */ +#define CC1100_STROBE_SFSTXON 0x31 /* enable and calibrate */ +#define CC1100_STROBE_SXOFF 0x32 /* crystall off */ +#define CC1100_STROBE_SCAL 0x33 /* calibrate */ +#define CC1100_STROBE_SRX 0x34 /* enable rx */ +#define CC1100_STROBE_STX 0x35 /* enable tx */ +#define CC1100_STROBE_SIDLE 0x36 /* go idle */ +#define CC1100_STROBE_SAFC 0x37 /* AFC adjustment */ +#define CC1100_STROBE_SWOR 0x38 /* wake on radio */ +#define CC1100_STROBE_SPWD 0x39 /* power down */ +#define CC1100_STROBE_SFRX 0x3A /* flush Rx fifo */ +#define CC1100_STROBE_SFTX 0x3B /* flush Tx fifo */ +#define CC1100_STROBE_SWORRST 0x3C /* reset WOR timer */ +#define CC1100_STROBE_SNOP 0x3D /* no operation */ +/** + * @} + */ + + +/** + * \name C1100 Registers + * @{ + */ +#define CC1100_REG_IOCFG2 0x00 +#define CC1100_REG_IOCFG2_DEFAULT 0x29 +#define CC1100_REG_IOCFG1 0x01 +#define CC1100_REG_IOCFG1_DEFAULT 0x2E +#define CC1100_REG_IOCFG0 0x02 +#define CC1100_REG_IOCFG0_DEFAULT 0x3F +#define CC1100_REG_FIFOTHR 0x03 +#define CC1100_REG_FIFOTHR_DEFAULT 0x07 +#define CC1100_REG_SYNC1 0x04 +#define CC1100_REG_SYNC1_DEFAULT 0xD3 +#define CC1100_REG_SYNC0 0x05 +#define CC1100_REG_SYNC0_DEFAULT 0x91 +#define CC1100_REG_PKTLEN 0x06 +#define CC1100_REG_PKTLEN_DEFAULT 0xFF +#define CC1100_REG_PKTCTRL1 0x07 +#define CC1100_REG_PKTCTRL1_DEFAULT 0x04 +#define CC1100_REG_PKTCTRL0 0x08 +#define CC1100_REG_PKTCTRL0_DEFAULT 0x45 +#define CC1100_REG_ADDR 0x09 +#define CC1100_REG_ADDR_DEFAULT 0x00 +#define CC1100_REG_CHANNR 0x0A +#define CC1100_REG_CHANNR_DEFAULT 0x00 +#define CC1100_REG_FSCTRL1 0x0B +#define CC1100_REG_FSCTRL1_DEFAULT 0x0F +#define CC1100_REG_FSCTRL0 0x0C +#define CC1100_REG_FSCTRL0_DEFAULT 0x00 +#define CC1100_REG_FREQ2 0x0D +#define CC1100_REG_FREQ2_DEFAULT 0x1E +#define CC1100_REG_FREQ1 0x0E +#define CC1100_REG_FREQ1_DEFAULT 0xC4 +#define CC1100_REG_FREQ0 0x0F +#define CC1100_REG_FREQ0_DEFAULT 0xEC +#define CC1100_REG_MDMCFG4 0x10 +#define CC1100_REG_MDMCFG4_DEFAULT 0x8C +#define CC1100_REG_MDMCFG3 0x11 +#define CC1100_REG_MDMCFG3_DEFAULT 0x22 +#define CC1100_REG_MDMCFG2 0x12 +#define CC1100_REG_MDMCFG2_DEFAULT 0x02 +#define CC1100_REG_MDMCFG1 0x13 +#define CC1100_REG_MDMCFG1_DEFAULT 0x22 +#define CC1100_REG_MDMCFG0 0x14 +#define CC1100_REG_MDMCFG0_DEFAULT 0xF8 +#define CC1100_REG_DEVIATN 0x15 +#define CC1100_REG_DEVIATN_DEFAULT 0x47 +#define CC1100_REG_MCSM2 0x16 +#define CC1100_REG_MCSM2_DEFAULT 0x07 +#define CC1100_REG_MCSM1 0x17 +#define CC1100_REG_MCSM1_DEFAULT 0x30 +#define CC1100_REG_MCSM0 0x18 +#define CC1100_REG_MCSM0_DEFAULT 0x04 +#define CC1100_REG_FOCCFG 0x19 +#define CC1100_REG_FOCCFG_DEFAULT 0x36 +#define CC1100_REG_BSCFG 0x1A +#define CC1100_REG_BSCFG_DEFAULT 0x6C +#define CC1100_REG_AGCCTRL2 0x1B +#define CC1100_REG_AGCCTRL2_DEFAULT 0x03 +#define CC1100_REG_AGCCTRL1 0x1C +#define CC1100_REG_AGCCTRL1_DEFAULT 0x40 +#define CC1100_REG_AGCCTRL0 0x1D +#define CC1100_REG_AGCCTRL0_DEFAULT 0x91 +#define CC1100_REG_WOREVT1 0x1E +#define CC1100_REG_WOREVT1_DEFAULT 0x87 +#define CC1100_REG_WOREVT0 0x1F +#define CC1100_REG_WOREVT0_DEFAULT 0x6B +#define CC1100_REG_WORCTRL 0x20 +#define CC1100_REG_WORCTRL_DEFAULT 0xF8 +#define CC1100_REG_FREND1 0x21 +#define CC1100_REG_FREND1_DEFAULT 0xA6 +#define CC1100_REG_FREND0 0x22 +#define CC1100_REG_FREND0_DEFAULT 0x10 +#define CC1100_REG_FSCAL3 0x23 +#define CC1100_REG_FSCAL3_DEFAULT 0xA9 +#define CC1100_REG_FSCAL2 0x24 +#define CC1100_REG_FSCAL2_DEFAULT 0x0A +#define CC1100_REG_FSCAL1 0x25 +#define CC1100_REG_FSCAL1_DEFAULT 0x20 +#define CC1100_REG_FSCAL0 0x26 +#define CC1100_REG_FSCAL0_DEFAULT 0x0D +#define CC1100_REG_RCCTRL1 0x27 +#define CC1100_REG_RCCTRL1_DEFAULT 0x41 +#define CC1100_REG_RCCTRL0 0x28 +#define CC1100_REG_RCCTRL0_DEFAULT 0x00 +/** + * @} + */ + + +/** + * \name Configuration registers + * @{ + */ +#define CC1100_REG_FSTEST 0x29 +#define CC1100_REG_FSTEST_DEFAULT 0x57 +#define CC1100_REG_PTEST 0x2A +#define CC1100_REG_PTEST_DEFAULT 0x7F +#define CC1100_REG_AGCTEST 0x2B +#define CC1100_REG_AGCTEST_DEFAULT 0x3F +#define CC1100_REG_TEST2 0x2B +#define CC1100_REG_TEST2_DEFAULT 0x88 +#define CC1100_REG_TEST1 0x2C +#define CC1100_REG_TEST1_DEFAULT 0x31 +#define CC1100_REG_TEST0 0x2D +#define CC1100_REG_TEST0_DEFAULT 0x0B +/** + * @} + */ + + +/** + * \name Read only registers + * @{ + */ +#define CC1100_REG_PARTNUM 0x30 +#define CC1100_REG_PARTNUM_DEFAULT 0x00 +#define CC1100_REG_VERSION 0x31 +#define CC1100_REG_VERSION_DEFAULT 0x01 +#define CC1100_REG_FREQEST 0x32 +#define CC1100_REG_FREQEST_DEFAULT 0x00 +#define CC1100_REG_LQI 0x33 +#define CC1100_REG_LQI_DEFAULT 0x7F +#define CC1100_REG_RSSI 0x34 +#define CC1100_REG_RSSI_DEFAULT 0x80 +#define CC1100_REG_MARCSTATE 0x35 +#define CC1100_REG_MARCSTATE_DEFAULT 0x01 +#define CC1100_REG_WORTIME1 0x36 +#define CC1100_REG_WORTIME1_DEFAULT 0x00 +#define CC1100_REG_WORTIME0 0x37 +#define CC1100_REG_WORTIME0_DEFAULT 0x00 +#define CC1100_REG_PKTSTATUS 0x38 +#define CC1100_REG_PKTSTATUS_DEFAULT 0x00 +#define CC1100_REG_VCO_VC_DAC 0x39 +#define CC1100_REG_VCO_VC_DAC_DEFAULT 0x94 +#define CC1100_REG_TXBYTES 0x3A +#define CC1100_REG_TXBYTES_DEFAULT 0x00 +#define CC1100_REG_RXBYTES 0x3B +#define CC1100_REG_RXBYTES_DEFAULT 0x00 + + +#define CC1100_PATABLE_ADDR 0x3E +#define CC1100_DATA_FIFO_ADDR 0x3F +/** + * @} + */ + + +/** + * \name GDOx configuration + * @{ + */ +#define CC1100_GDOx_RX_FIFO 0x00 /* assert above threshold, deassert when below */ +#define CC1100_GDOx_RX_FIFO_EOP 0x01 /* assert above threshold or EOP */ +#define CC1100_GDOx_TX_FIFO 0x02 /* assert above threshold, deassert below thr */ +#define CC1100_GDOx_TX_THR_FULL 0x03 /* asserts when TX FIFO is full. De-asserts when */ + /* the TX FIFO is drained below TXFIFO_THR. */ +#define CC1100_GDOx_RX_OVER 0x04 /* asserts when RX overflow, deassert when flushed */ +#define CC1100_GDOx_TX_UNDER 0x05 /* asserts when RX underflow, deassert when flushed */ +#define CC1100_GDOx_SYNC_WORD 0x06 /* assert SYNC sent/recv, deasserts on EOP */ + /* In RX, de-assert on overflow or bad address */ + /* In TX, de-assert on underflow */ +#define CC1100_GDOx_RX_OK 0x07 /* assert when RX PKT with CRC ok, de-assert on 1byte */ + /* read from RX Fifo */ +#define CC1100_GDOx_PREAMB_OK 0x08 /* assert when preamble quality reached : PQI/PQT ok */ +#define CC1100_GDOx_CCA 0x09 /* Clear channel assessment. High when RSSI level is */ + /* below threshold (dependent on the current CCA_MODE) */ + +#define CC1100_GDOx_CHIP_RDY 0x29 /* CHIP_RDY */ + +#define CC1100_GDOx_XOSC_STABLE 0x2B /* XOSC_STABLE */ + +#define CC1100_GDOx_CLK_XOSC_1 0x30 /* CLK_XOSC/1 */ +#define CC1100_GDOx_CLK_XOSC_1p5 0x31 /* CLK_XOSC/1.5 */ +#define CC1100_GDOx_CLK_XOSC_2 0x32 /* CLK_XOSC/2 */ +#define CC1100_GDOx_CLK_XOSC_3 0x33 /* CLK_XOSC/3 */ +#define CC1100_GDOx_CLK_XOSC_4 0x34 /* CLK_XOSC/4 */ +#define CC1100_GDOx_CLK_XOSC_6 0x35 /* CLK_XOSC/6 */ +#define CC1100_GDOx_CLK_XOSC_8 0x36 /* CLK_XOSC/8 */ +#define CC1100_GDOx_CLK_XOSC_12 0x37 /* CLK_XOSC/12 */ +#define CC1100_GDOx_CLK_XOSC_16 0x38 /* CLK_XOSC/16 */ +#define CC1100_GDOx_CLK_XOSC_24 0x39 /* CLK_XOSC/24 */ +#define CC1100_GDOx_CLK_XOSC_32 0x3A /* CLK_XOSC/32 */ +#define CC1100_GDOx_CLK_XOSC_48 0x3B /* CLK_XOSC/48 */ +#define CC1100_GDOx_CLK_XOSC_64 0x3C /* CLK_XOSC/64 */ +#define CC1100_GDOx_CLK_XOSC_96 0x3D /* CLK_XOSC/96 */ +#define CC1100_GDOx_CLK_XOSC_128 0x3E /* CLK_XOSC/128 */ +#define CC1100_GDOx_CLK_XOSC_192 0x3F /* CLK_XOSC/192 */ +/** + * @} + */ + +#endif diff --git a/targets/WSN430wireless/relay_transmitter/hardware.c b/targets/WSN430wireless/relay_transmitter/hardware.c new file mode 100755 index 0000000000000000000000000000000000000000..dc67fdfad675358511106adec5b55b5fe3a398a1 --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/hardware.c @@ -0,0 +1,119 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + + +#include "target.h" + +#define LFXT1CLK_HZ 32768 + +volatile uint32_t global_timer; + +#ifndef DISABLE_RTX +interrupt (TIMERA0_VECTOR) timerA0( void ) { + global_timer++; +} + +void timer_init() { + /* Ensure the timer is stopped. */ + TACTL = 0; + /* Clear everything to start with. */ + TACTL |= TACLR; + /* Run the timer of the SMCLK (1MHz). */ + TACTL = TASSEL_2; + /* Set the compare match value according to the tick rate we want. */ + TACCR0 = 999; + /* Enable the interrupts. */ + TACCTL0 = CCIE; + + /* ID_0 (0<<6) Timer A input divider: 0 - /1 */ + /* ID_1 (1<<6) Timer A input divider: 1 - /2 */ + /* ID_2 (2<<6) Timer A input divider: 2 - /4 */ + /* ID_3 (3<<6) Timer A input divider: 3 - /8 */ + TACTL |= ID_0; + + /* Up mode. */ + TACTL |= MC_1; +} +#endif + +void xtal_init() { + int i; + // Init Xtal + DCOCTL = 0; + BCSCTL1 = 0; + BCSCTL2 = SELM_2 | (SELS | DIVS_3) ; + + // Wait + do { + IFG1 &= ~OFIFG; /* Clear OSCFault flag */ + for (i = 0xff; i > 0; i--) /* Time for flag to set */ + nop(); /* */ + } while ((IFG1 & OFIFG) != 0); /* OSCFault flag still set? */ +} + +void hardware_init() { + // WDog OFF + WDTCTL = WDTPW + WDTHOLD; + + LEDS_INIT(); + xtal_init(); + dev_init(); +#ifndef DISABLE_RTX + timer_init(); +#endif + LEDS_OFF(); + eint(); +} + +uint16_t initADC(unsigned char channel) { + return 1; +} + +uint16_t GetADCVal(unsigned char channel) { + ADC12CTL0 = ADC12ON | SHT0_15 | REFON; // ADC on, int. ref. on (1,5 V), multiple sample & conversion + + ADC12CTL1 = ADC12SSEL_2 | ADC12DIV_7 | CSTARTADD_0 | CONSEQ_1 | SHP; // MCLK / 8 = 1 MHz + + ADC12MCTL0 = EOS | SREF_1 | (channel & 0x0F); // int. ref., channel 10, last seg. + + ADC12CTL0 |= ENC; // enable conversion + ADC12CTL0 |= ADC12SC; // sample & convert + + while (ADC12CTL0 & ADC12SC); // wait until conversion is complete + + ADC12CTL0 &= ~ENC; // disable conversion + + return ADC12MEM0; +} diff --git a/targets/WSN430wireless/relay_transmitter/relay_transmitter.c b/targets/WSN430wireless/relay_transmitter/relay_transmitter.c new file mode 100755 index 0000000000000000000000000000000000000000..6c970436b0795d1493dc027c42c309b065062794 --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/relay_transmitter.c @@ -0,0 +1,59 @@ +/* +* Copyright or © or Copr. 2010, Guillaume Marchand and Damien Riquet +* +* Authors e-mail: guillaume.marchand@etudiant.univ-lille1.fr +* damien.riquet@etudiant.univ-lille1.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "target.h" +#include "serial_line.h" +#include "cc1100.h" + +/* LEDs meanings : +* RED : Hardware is working +* BLUE : Radio Rx/Tx +* GREEN : Serial Rx/Tx +*/ + +int main(void) { + uint16_t i; + + /* Hardware initialisation : serie, radio */ + hardware_init(); + cc1100_init(); + LED_ON(LED_RED); /* Hardware is working */ + + /* Relay loop */ + while(1) {} + + return 0; +} diff --git a/targets/WSN430wireless/relay_transmitter/serial_line.c b/targets/WSN430wireless/relay_transmitter/serial_line.c new file mode 100755 index 0000000000000000000000000000000000000000..bdb443ebb54d293c9b94d5bde01a9d783940ac46 --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/serial_line.c @@ -0,0 +1,149 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "types.h" +#include "serial_line.h" +#include "target.h" + +#define UART1_PIN_RX 7 +#define UART1_PIN_TX 6 + +#define UART1_BIT_RX (1 << UART1_PIN_RX) +#define UART1_BIT_TX (1 << UART1_PIN_TX) + +#define TIMEOUT 5000 +#define TIMETOWAIT 500 + +volatile serial_line_t serial_line; + +/*-----------------------------------------------------------------------------------*/ +void dev_init(void) { + //Init of MSP430 Usart1 pins + P3SEL |= (UART1_BIT_RX | UART1_BIT_TX); + + //Init of USART1 Module + U1ME |= UTXE1|URXE1; //Enable USART1 transmiter and receiver (UART mode) + + U1CTL = SWRST; //reset + U1CTL = CHAR; //init & release reset + + U1TCTL = SSEL_SMCLK|TXEPT; //use SMCLK + U1RCTL = 0; + + // 115200 @ SMCLK 1MHz + #define U1BR1_INIT 0 + #define U1BR0_INIT 0x08 + #define U1MCTL_INIT 0x6d + + U1BR1 = U1BR1_INIT; + U1BR0 = U1BR0_INIT; + U1MCTL = U1MCTL_INIT; + + U1IE |= URXIE1; + + serial_line.writePtr = serial_line.buffer; + serial_line.readPtr = NULL; + + return; +} + +/*-----------------------------------------------------------------------------------*/ +/* Serial line handler */ +interrupt (USART1RX_VECTOR) usart1irq( void ) { + volatile int16_t c; + uint32_t last_time = global_timer; /* To be deleted */ + LED_ON(LED_GREEN); /* Rx */ + while(global_timer-last_time<TIMETOWAIT); /* To be deleted */ + /* Check status register for receive errors. */ + if(URCTL1 & RXERR) { + /* Clear error flags by forcing a dummy read. */ + c = RXBUF1; + return; + } else { + c = (int16_t) U1RXBUF; + } + + if(serial_line.writePtr != NULL) { + if(serial_line.readPtr == NULL) + serial_line.readPtr = serial_line.writePtr; + *serial_line.writePtr++ = c; + if(serial_line.writePtr == serial_line.buffer + INBUF_SIZE) + serial_line.writePtr = serial_line.buffer; + if(serial_line.writePtr == serial_line.readPtr) + serial_line.writePtr = NULL; + } + /* TODO Envoie en radio */ + LED_OFF(LED_GREEN); /* End of Rx */ +} + +/*-----------------------------------------------------------------------------------*/ +static unsigned char read_byte_from_buffer() { + unsigned char c; + if(serial_line.writePtr == NULL) + serial_line.writePtr = serial_line.readPtr; + c = *serial_line.readPtr++; + if(serial_line.readPtr == serial_line.buffer + INBUF_SIZE) + serial_line.readPtr = serial_line.buffer; + if (serial_line.readPtr == serial_line.writePtr) + serial_line.readPtr = NULL; + return c; +} + +/*-----------------------------------------------------------------------------------*/ +int16_t dev_get(void) { + uint32_t last_time = global_timer; + while(serial_line.readPtr == NULL && global_timer-last_time<TIMEOUT); + if(serial_line.readPtr == NULL) { + return -1; + } else { + return read_byte_from_buffer(); + } +} + +/*-----------------------------------------------------------------------------------*/ +int32_t serial_line_write(unsigned char value) { + U1TXBUF = value; + while ((U1TCTL & TXEPT) != TXEPT); + return 1; +} + +/*-----------------------------------------------------------------------------------*/ +void dev_put(unsigned char byte) { + uint32_t last_time = global_timer; + LED_ON(LED_GREEN); /* Tx */ + while(global_timer-last_time<TIMETOWAIT); + serial_line_write(byte); + LED_OFF(LED_GREEN); /* End of Tx */ +} diff --git a/targets/WSN430wireless/relay_transmitter/serial_line.h b/targets/WSN430wireless/relay_transmitter/serial_line.h new file mode 100755 index 0000000000000000000000000000000000000000..eca6fc9965566aec0045ecb3d8172bfb3aa68966 --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/serial_line.h @@ -0,0 +1,64 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __SLIP_DEV_H__ +#define __SLIP_DEV_H__ + +#include "target.h" + +/* Extern functions */ +extern void hardware_init(void); +extern int16_t dev_get(void); +extern void dev_put(unsigned char byte); +extern void dev_init(void); +extern int32_t serial_line_write(unsigned char value); + +/* SLIP */ +#define SLIP_END 0xC0 /* indicates end of packet */ +#define SLIP_ESC 0xDB /* indicates byte stuffing */ +#define SLIP_ESC_END 0xDC /* ESC ESC_END means END data byte */ +#define SLIP_ESC_ESC 0xDD /* ESC ESC_ESC means ESC data byte */ + +#define INBUF_SIZE 512 +/* Serial line */ +typedef struct { + volatile unsigned char buffer[INBUF_SIZE]; + volatile unsigned char *volatile writePtr; + volatile unsigned char *volatile readPtr; +} serial_line_t; + +extern volatile serial_line_t serial_line; + +#endif diff --git a/targets/WSN430wireless/relay_transmitter/serie_to_radio.c b/targets/WSN430wireless/relay_transmitter/serie_to_radio.c new file mode 100755 index 0000000000000000000000000000000000000000..5dfde660460da25f517d29c9ff63aea975c737b8 --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/serie_to_radio.c @@ -0,0 +1,29 @@ +#include "target.h" +#include "serial_line.h" +#include "cc1100.h" + +int main(void) { + uint16_t i; + + /* Initialisation materiel serie, radio */ + hardware_init(); + cc1100_init(); + LED_ON(LED_RED); + + /* On envoie sur le lien serie */ + while(1) { + int16_t from_serie; + LED_OFF(LED_GREEN); /* Rx */ + LED_OFF(LED_BLUE); /* Tx */ + from_serie = dev_get(); + if (from_serie != -1) { + LED_ON(LED_GREEN); + } else { + LED_ON(LED_RED); + } + + for(i=0;i<20000;i++); + } + + return 0; +} diff --git a/targets/WSN430wireless/relay_transmitter/spi1.c b/targets/WSN430wireless/relay_transmitter/spi1.c new file mode 100755 index 0000000000000000000000000000000000000000..9ff2fd1f18c24bf8ef7e4f80bb94075568fab61c --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/spi1.c @@ -0,0 +1,201 @@ +/* + * Copyright 2008-2009 INRIA/SensTools + * + * <dev-team@sentools.info> + * + * This software is a set of libraries designed to develop applications + * for the WSN430 embedded hardware platform. + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. + */ +/** + *addtogroup wsn430 + * @{ + */ + +/** + *addtogroup spi1 + * @{ + */ + +/** + *file + *brief SPI1 driver + *author Clément Burin des Roziers <clement.burin-des-roziers@inria.fr> + *date October 09 + */ + +/** + * @} + */ + +/** + * @} + */ + +#include <io.h> +#include "spi1.h" + +/* Local Macros */ +/* + * wait until a byte has been received on spi port + */ +#define WAIT_EORX() while ( (IFG2 & URXIFG1) == 0){} + +/* + * wait until a byte has been sent on spi port + */ +#define WAIT_EOTX() while ( (IFG2 & UTXIFG1) == 0){} + +#define CC1100_CS_PIN (1<<2) +#define CC2420_CS_PIN (1<<2) +#define DS1722_CS_PIN (1<<3) +#define M25P80_CS_PIN (1<<4) + +#define CC1100_ENABLE() P4OUT &= ~CC1100_CS_PIN +#define CC1100_DISABLE() P4OUT |= CC1100_CS_PIN + +#define CC2420_ENABLE() P4OUT &= ~CC2420_CS_PIN +#define CC2420_DISABLE() P4OUT |= CC2420_CS_PIN + +#define DS1722_ENABLE() P4OUT |= DS1722_CS_PIN +#define DS1722_DISABLE() P4OUT &= ~DS1722_CS_PIN + +#define M25P80_ENABLE() P4OUT &= ~M25P80_CS_PIN +#define M25P80_DISABLE() P4OUT |= M25P80_CS_PIN + +void spi1_init(void) { + /* Configure IO pins */ + P5DIR |= (1<<1) | (1<<3); /* output for CLK and SIMO */ + P5DIR &= ~(1<<2); /* input for SOMI */ + P5SEL |= (1<<1) | (1<<2) | (1<<3); /* SPI for all three */ + + /* Configure USART1 */ + U1CTL = SWRST; /* SPI 1 software reset */ + U1CTL = CHAR | SYNC | MM | SWRST; /* 8bit SPI master */ + U1TCTL = CKPH | SSEL_2 | STC; /* clock delay, SMCLK */ + + U1RCTL = 0; /* clear errors */ + U1BR0 = 0x2; /* baudrate = SMCLK/2 */ + U1BR1 = 0x0; + + ME2 |= USPIE1; /* enable SPI module */ + IE2 &= ~(UTXIE1 | URXIE1); /* disable SPI interrupt */ + U1CTL &= ~(SWRST); /* clear reset */ + + /* CS IO pins configuration */ + P4SEL &= ~(CC1100_CS_PIN | DS1722_CS_PIN | M25P80_CS_PIN); + P4DIR |= (CC1100_CS_PIN | DS1722_CS_PIN | M25P80_CS_PIN); + + /* disable peripherals */ + M25P80_DISABLE(); + CC1100_DISABLE(); + DS1722_DISABLE(); +} + +uint8_t spi1_write_single(uint8_t byte) { + uint8_t dummy; + U1TXBUF = byte; + WAIT_EORX(); + dummy = U1RXBUF; + + return dummy; +} + +uint8_t spi1_read_single(void) { + return spi1_write_single(0x0); +} + +uint8_t spi1_write(uint8_t* data, int16_t len) { + uint8_t dummy=0; + int16_t i; + + for (i=0; i<len; i++) { + U1TXBUF = data[i]; + WAIT_EORX(); + dummy = U1RXBUF; + } + return dummy; +} +void spi1_read(uint8_t* data, int16_t len) { + int16_t i; + + for (i=0; i<len; i++) { + U1TXBUF = 0x0; + WAIT_EORX(); + data[i] = U1RXBUF; + } +} + +void spi1_select(int16_t chip) { + switch (chip) { + case SPI1_CC1100: + M25P80_DISABLE(); + DS1722_DISABLE(); + CC1100_ENABLE(); + break; + case SPI1_DS1722: + M25P80_DISABLE(); + CC1100_DISABLE(); + DS1722_DISABLE(); + U1CTL |= SWRST; + U1TCTL &= ~(CKPH); + U1CTL &= ~(SWRST); + DS1722_ENABLE(); + break; + case SPI1_M25P80: + CC1100_DISABLE(); + DS1722_DISABLE(); + M25P80_ENABLE(); + break; + default: + break; + } +} + +void spi1_deselect(int16_t chip) { + switch (chip) { + case SPI1_CC1100: + CC1100_DISABLE(); + break; + case SPI1_DS1722: + DS1722_DISABLE(); + U1CTL |= SWRST; + U1TCTL |= CKPH; + U1CTL &= ~(SWRST); + break; + case SPI1_M25P80: + M25P80_DISABLE(); + break; + default: + break; + } +} + +int16_t spi1_read_somi(void) { + return P5IN & (1<<2); +} diff --git a/targets/WSN430wireless/relay_transmitter/spi1.h b/targets/WSN430wireless/relay_transmitter/spi1.h new file mode 100755 index 0000000000000000000000000000000000000000..fcf57317191a99777aa5ff50c47e2e1f3d756dd0 --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/spi1.h @@ -0,0 +1,96 @@ +/* + * Copyright 2008-2009 INRIA/SensTools + * + * <dev-team@sentools.info> + * + * This software is a set of libraries designed to develop applications + * for the WSN430 embedded hardware platform. + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. + */ +/** + * \defgroup spi1 SPI1 driver + * \ingroup wsn430 + * @{ + * + * The SPI1 driver allows SPI communication + * using the USART1 block of the MSP430. This driver is mainly + * used by other peripheral devices' drivers. + * + * It defines macros to initialize the SPI module, + * to chip select/deselect the three default hardware + * peripherals connected by SPI to the MSP430, + * to write/read bytes to/from these peripherals. + * + * Note that when chip selecting a device, + * the driver automatically deselects + * the two other ones to avoid bus collision. + * + */ + +/** + * \file + * \brief SPI1 driver. + * \author Antoine Fraboulet <antoine.fraboulet@insa-lyon.fr> + * \author Colin Chaballier + * \author Clément Burin des Roziers <clement.burin-des-roziers@inria.fr> + * \date November 08 + */ + +#ifndef SPI1_H +#define SPI1_H + +extern uint8_t spi1_tx_return_value; + +enum { + SPI1_CC1100 = 1, + SPI1_CC2420 = 1, + SPI1_DS1722 = 2, + SPI1_M25P80 = 3 +}; + +/** + * Initialize the UART1 for SPI use. + */ +void spi1_init(void); + +uint8_t spi1_write_single(uint8_t byte); +uint8_t spi1_read_single(void); + +uint8_t spi1_write(uint8_t* data, int16_t len); +void spi1_read(uint8_t* data, int16_t len); + +void spi1_select(int16_t chip); +void spi1_deselect(int16_t chip); + +int16_t spi1_read_somi(void); + +/** + * @} + */ + +#endif diff --git a/targets/WSN430wireless/relay_transmitter/target.h b/targets/WSN430wireless/relay_transmitter/target.h new file mode 100755 index 0000000000000000000000000000000000000000..db452e4866f05edff1cf0d1a311f6186f67ec39c --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/target.h @@ -0,0 +1,148 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __TARGET_H__ +#define __TARGET_H__ + +#include <stdint.h> +#include <io.h> +#include <string.h> +#include <signal.h> +#include <iomacros.h> + +#include "serial_line.h" + +extern volatile uint32_t global_timer; + +/* Drivers interface */ + +#define HARDWARE_INIT hardware_init() +#define HARDWARE_STOP +#define TIME_MILLIS global_timer +#define DEV_GET(c) {(c) = dev_get();} +#define DEV_PUT(c) dev_put(c) +#define DEV_PREPARE_OUTPUT(length) serial_line_write(SLIP_END); +#define DEV_OUTPUT_DONE serial_line_write(SLIP_END); +#define DEV_DATA_TO_READ (serial_line.readPtr != NULL) + +/* Smews states */ + +typedef enum { LED_RED = 4, LED_GREEN, LED_BLUE } led_t ; +#define LED_OUT P5OUT +#define BIT_BLUE (1 << 6) +#define BIT_GREEN (1 << 5) +#define BIT_RED (1 << 4) + +#define LEDS_OFF() LED_OUT |= (BIT_BLUE | BIT_GREEN | BIT_RED) +#define LEDS_ON() LED_OUT &= ~(BIT_BLUE | BIT_GREEN | BIT_RED) + +#define LEDS_INIT() \ +do { \ + P5OUT &= ~(BIT_BLUE | BIT_GREEN | BIT_RED); \ + P5DIR |= (BIT_BLUE | BIT_GREEN | BIT_RED); \ + P5SEL &= ~(BIT_BLUE | BIT_GREEN | BIT_RED); \ +} while(0) + +#define LED_OFF(LED) (LED_OUT |= (1 << LED)) +#define LED_ON(LED) (LED_OUT &= ~(1 << LED)) +#define LED_TOGGLE(LED) (LED_OUT ^= (1 << LED)) + +#define SMEWS_WAITING {LEDS_OFF();/*LED_ON(LED_BLUE);*/} +#define SMEWS_RECEIVING {LEDS_OFF();LED_ON(LED_GREEN);} +#define SMEWS_SENDING {LEDS_OFF();LED_ON(LED_RED);} +#define SMEWS_ENDING {LEDS_OFF();} + +/* Const and persistent access macros */ + +#define CONST_VOID_P_VAR const void * +#define CONST_VAR(type,name) type const name +#define PERSISTENT_VAR(type,name) type name +#define CONST_WRITE_NBYTES(dst,src,len) strncpy(dst,src,len) + +#define CONST_READ_UI8(x) ((uint8_t)*((uint8_t*)(x))) +#define CONST_READ_UI16(x) ((uint16_t)*((uint16_t*)(x))) +#define CONST_READ_UI32(x) ((uint32_t)*((uint32_t*)(x))) +#define CONST_READ_ADDR(x) ((void*)*((void**)(x))) + +#define CONST_UI8(x) CONST_READ_UI8(&(x)) +#define CONST_UI16(x) CONST_READ_UI16(&(x)) +#define CONST_UI32(x) CONST_READ_UI32(&(x)) +#define CONST_ADDR(x) CONST_READ_ADDR(&(x)) + +/* Endianness */ +#define ENDIANNESS LITTLE_ENDIAN + +/* Context switching */ + +#define BACKUP_CTX(sp) \ + asm ("mov r1, %0" : "=r"((sp)[0])); \ + +#define RESTORE_CTX(sp) \ + asm ("mov %0, r1" :: "r"((sp)[0])); \ + +/* in adequacy with msp430 registers usage, + * we only have to push and pop only from r6 to r11 */ +#define PUSHREGS asm( \ + "push r11\n" \ + "push r10\n" \ + "push r9\n" \ + "push r8\n" \ + "push r7\n" \ + "push r6\n" \ + ); \ + +#define POPREGS asm( \ + "pop r6\n" \ + "pop r7\n" \ + "pop r8\n" \ + "pop r9\n" \ + "pop r10\n" \ + "pop r11\n" \ + ); \ + +/* Smews configuration */ + +#define OUTPUT_BUFFER_SIZE 256 +#define ALLOC_SIZE 2048 +#define STACK_SIZE 64 + +/* Custom Functions */ +#define ADC_LIGHT INCH_4 +#define ADC_IR INCH_5 +#define ADC_TEMP INCH_10 +extern uint16_t initADC(unsigned char channel); +extern uint16_t GetADCVal(unsigned char channel); + +#endif /* __TARGET_H__ */ diff --git a/targets/WSN430wireless/relay_transmitter/types.h b/targets/WSN430wireless/relay_transmitter/types.h new file mode 100755 index 0000000000000000000000000000000000000000..867441e332ca18aa02cfee54026da4559a8fb0db --- /dev/null +++ b/targets/WSN430wireless/relay_transmitter/types.h @@ -0,0 +1,107 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __TYPES_H__ +#define __TYPES_H__ + +/* Allows to define ENDIANNESS as LITTLE_ENDIAN or BIG_ENDIAN */ +#ifndef BIG_ENDIAN + #define BIG_ENDIAN 0 +#endif +#ifndef LITTLE_ENDIAN + #define LITTLE_ENDIAN 1 +#endif + +/* Include the target dependent target.h file */ +#include "target.h" + +/* Define NULL is needed */ +#ifndef NULL + #define NULL ((void*)0) +#endif + +/* Constant declaration */ +#ifndef CONST_VOID_P_VAR + #define CONST_VOID_P_VAR const void * +#endif +#ifndef CONST_VAR + #define CONST_VAR(type,name) type const name +#endif + +/* Read constant "variables" */ +#ifndef CONST_READ_UI8 + #define CONST_READ_UI8(x) (*((uint8_t*)(x))) +#endif +#ifndef CONST_READ_UI16 + #define CONST_READ_UI16(x) (*((uint16_t*)(x))) +#endif +#ifndef CONST_READ_UI32 + #define CONST_READ_UI32(x) (*((uint32_t*)(x))) +#endif +#ifndef CONST_READ_ADDR + #define CONST_READ_ADDR(x) (*((void**)(x))) +#endif + +/* Endianness has to be defined */ +#if ENDIANNESS != LITTLE_ENDIAN && ENDIANNESS != BIG_ENDIAN + #error ENDIANNESS has to be defined in "target.h" as LITTLE_ENDIAN or BIG_ENDIAN +#endif + +/* Wn: weight of the n_th byte of a 32 bits integer */ +#if ENDIANNESS == LITTLE_ENDIAN + #define W0 3 + #define W1 2 + #define W2 1 + #define W3 0 +#else + #define W0 0 + #define W1 1 + #define W2 2 + #define W3 3 +#endif +/* Sn: weight of the n_th byte of a 16 bits integer */ +#if ENDIANNESS == LITTLE_ENDIAN + #define S0 1 + #define S1 0 +#else + #define S0 0 + #define S1 1 +#endif + +/* Cast variable as uint16_t or uint32_t */ +#define UI16(x) (*((uint16_t*)(x))) +#define UI32(x) (*((uint32_t*)(x))) + +#endif /* __TYPES_H__ */ diff --git a/targets/cygwin/SConscript b/targets/cygwin/SConscript new file mode 100755 index 0000000000000000000000000000000000000000..e9aabb4a004c3ddd8490766b92345e4a923aca9a --- /dev/null +++ b/targets/cygwin/SConscript @@ -0,0 +1,41 @@ +# Copyright or c or Copr. 2008, Geoffroy Cogniaux +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + +import os +import sys + +Import('env binDir projectName elfName') + +env.Replace(CC = 'gcc') +env.Replace(AS = 'as') +env.Replace(AR = 'ar') +env.Replace(RANLIB = 'ranlib') +env.Append(CCFLAGS = ' -D_DEBUG -DWIN32 -D__CYGWIN__ -mno-cygwin ') +env.Append(LINKFLAGS = ' -D_DEBUG -DWIN32 -D__CYGWIN__ -mno-cygwin ') diff --git a/targets/cygwin/drivers/TAP-WIN32/addtap.bat b/targets/cygwin/drivers/TAP-WIN32/addtap.bat new file mode 100755 index 0000000000000000000000000000000000000000..0fd3b5b77e9ef85f13bed1902e4c4377cce76f33 --- /dev/null +++ b/targets/cygwin/drivers/TAP-WIN32/addtap.bat @@ -0,0 +1,3 @@ +rem Add a new TAP-Win32 virtual ethernet adapter +"tapinstall.exe" install "driver/OemWin2k.inf" tap0801 +pause diff --git a/targets/cygwin/drivers/TAP-WIN32/deltapall.bat b/targets/cygwin/drivers/TAP-WIN32/deltapall.bat new file mode 100755 index 0000000000000000000000000000000000000000..f42594cd20013e1827f429b26a82bda265b68915 --- /dev/null +++ b/targets/cygwin/drivers/TAP-WIN32/deltapall.bat @@ -0,0 +1,4 @@ +echo WARNING: this script will delete ALL TAP-Win32 virtual adapters (use the device manager to delete adapters one at a time) +pause +"tapinstall.exe" remove tap0801 +pause diff --git a/targets/cygwin/drivers/TAP-WIN32/driver/OemWin2k.inf b/targets/cygwin/drivers/TAP-WIN32/driver/OemWin2k.inf new file mode 100755 index 0000000000000000000000000000000000000000..219b4ca9fb6942f228279cecd288f675c9966b71 --- /dev/null +++ b/targets/cygwin/drivers/TAP-WIN32/driver/OemWin2k.inf @@ -0,0 +1,183 @@ +; **************************************************************************** +; * Copyright (C) 2002-2006 OpenVPN Solutions LLC * +; * This program is free software; you can redistribute it and/or modify * +; * it under the terms of the GNU General Public License version 2 * +; * as published by the Free Software Foundation. * +; **************************************************************************** + +; SYNTAX CHECKER +; cd \WINDDK\3790\tools\chkinf +; chkinf c:\src\openvpn\tap-win32\i386\oemwin2k.inf +; OUTPUT -> file:///c:/WINDDK/3790/tools/chkinf/htm/c%23+src+openvpn+tap-win32+i386+__OemWin2k.htm + +; INSTALL/REMOVE DRIVER +; tapinstall install OemWin2k.inf TAP0801 +; tapinstall update OemWin2k.inf TAP0801 +; tapinstall remove TAP0801 + +;********************************************************* +; Note to Developers: +; +; If you are bundling the TAP-Win32 driver with your app, +; you should try to rename it in such a way that it will +; not collide with other instances of TAP-Win32 defined +; by other apps. Multiple versions of the TAP-Win32 +; driver, each installed by different apps, can coexist +; on the same machine if you follow these guidelines: +; +; (1) Rename all tapXXXX instances in this file to +; something different (use at least 5 characters +; for this name!) +; (2) Change the "!define TAP" definition in openvpn.nsi +; to match what you changed tapXXXX to. +; (3) Change TARGETNAME in SOURCES to match what you +; changed tapXXXX to. +; (4) Change TAP_COMPONENT_ID in common.h to match what +; you changed tapXXXX to. +; (5) Change SZDEPENDENCIES in service.h to match what +; you changed tapXXXX to. +; (6) Change DeviceDescription and Provider strings. +; (7) Change PRODUCT_STRING in constants.h to what you +; set DeviceDescription to. +; +;********************************************************* + +[Version] + Signature = "$Windows NT$" + CatalogFile = tap.cat + ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} + Provider = %Provider% + Class = Net + +; This version number should match the version +; number given in SOURCES. + DriverVer=09/13/2006,8.00.00.0004 + +[Strings] + DeviceDescription = "TAP-Win32 Adapter V8" + Provider = "TAP-Win32 Provider" + +;---------------------------------------------------------------- +; Manufacturer + Product Section (Done) +;---------------------------------------------------------------- +[Manufacturer] + %Provider% = tap0801 + +[tap0801] + %DeviceDescription% = tap0801.ndi, tap0801 + +;--------------------------------------------------------------- +; Driver Section (Done) +;--------------------------------------------------------------- + +;----------------- Characteristics ------------ +; NCF_PHYSICAL = 0x04 +; NCF_VIRTUAL = 0x01 +; NCF_SOFTWARE_ENUMERATED = 0x02 +; NCF_HIDDEN = 0x08 +; NCF_NO_SERVICE = 0x10 +; NCF_HAS_UI = 0x80 +;----------------- Characteristics ------------ + +[tap0801.ndi] + CopyFiles = tap0801.driver, tap0801.files + AddReg = tap0801.reg + AddReg = tap0801.params.reg + Characteristics = 0x81 + +[tap0801.ndi.Services] + AddService = tap0801, 2, tap0801.service + +[tap0801.reg] + HKR, Ndi, Service, 0, "tap0801" + HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" + HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" + HKR, , Manufacturer, 0, "%Provider%" + HKR, , ProductName, 0, "%DeviceDescription%" + +[tap0801.params.reg] + HKR, Ndi\params\MTU, ParamDesc, 0, "MTU" + HKR, Ndi\params\MTU, Type, 0, "int" + HKR, Ndi\params\MTU, Default, 0, "1500" + HKR, Ndi\params\MTU, Optional, 0, "0" + HKR, Ndi\params\MTU, Min, 0, "100" + HKR, Ndi\params\MTU, Max, 0, "1500" + HKR, Ndi\params\MTU, Step, 0, "1" + HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status" + HKR, Ndi\params\MediaStatus, Type, 0, "enum" + HKR, Ndi\params\MediaStatus, Default, 0, "0" + HKR, Ndi\params\MediaStatus, Optional, 0, "0" + HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled" + HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected" + HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address" + HKR, Ndi\params\MAC, Type, 0, "edit" + HKR, Ndi\params\MAC, Optional, 0, "1" + HKR, Ndi\params\AllowNonAdmin, ParamDesc, 0, "Non-Admin Access" + HKR, Ndi\params\AllowNonAdmin, Type, 0, "enum" + HKR, Ndi\params\AllowNonAdmin, Default, 0, "1" + HKR, Ndi\params\AllowNonAdmin, Optional, 0, "0" + HKR, Ndi\params\AllowNonAdmin\enum, "0", 0, "Not Allowed" + HKR, Ndi\params\AllowNonAdmin\enum, "1", 0, "Allowed" + +;---------------------------------------------------------------- +; Service Section +;---------------------------------------------------------------- + +;---------- Service Type ------------- +; SERVICE_KERNEL_DRIVER = 0x01 +; SERVICE_WIN32_OWN_PROCESS = 0x10 +;---------- Service Type ------------- + +;---------- Start Mode --------------- +; SERVICE_BOOT_START = 0x0 +; SERVICE_SYSTEM_START = 0x1 +; SERVICE_AUTO_START = 0x2 +; SERVICE_DEMAND_START = 0x3 +; SERVICE_DISABLED = 0x4 +;---------- Start Mode --------------- + +[tap0801.service] + DisplayName = %DeviceDescription% + ServiceType = 1 + StartType = 3 + ErrorControl = 1 + LoadOrderGroup = NDIS + ServiceBinary = %12%\tap0801.sys + +;----------------------------------------------------------------- +; File Installation +;----------------------------------------------------------------- + +;----------------- Copy Flags ------------ +; COPYFLG_NOSKIP = 0x02 +; COPYFLG_NOVERSIONCHECK = 0x04 +;----------------- Copy Flags ------------ + +; SourceDisksNames +; diskid = description[, [tagfile] [, <unused>, subdir]] +; 1 = "Intel Driver Disk 1",e100bex.sys,, + +[SourceDisksNames] + 1 = %DeviceDescription%, tap0801.sys + +; SourceDisksFiles +; filename_on_source = diskID[, [subdir][, size]] +; e100bex.sys = 1,, ; on distribution disk 1 + +[SourceDisksFiles] +tap0801.sys = 1 + +[DestinationDirs] + tap0801.files = 11 + tap0801.driver = 12 + +[tap0801.files] +; TapPanel.cpl,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK +; cipsrvr.exe,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK + +[tap0801.driver] + tap0801.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK + +;--------------------------------------------------------------- +; End +;--------------------------------------------------------------- diff --git a/targets/cygwin/drivers/TAP-WIN32/driver/tap0801.sys b/targets/cygwin/drivers/TAP-WIN32/driver/tap0801.sys new file mode 100755 index 0000000000000000000000000000000000000000..170cb4ec360741de98932f8f14dc8681a495dac3 Binary files /dev/null and b/targets/cygwin/drivers/TAP-WIN32/driver/tap0801.sys differ diff --git a/targets/cygwin/drivers/TAP-WIN32/tapinstall.exe b/targets/cygwin/drivers/TAP-WIN32/tapinstall.exe new file mode 100755 index 0000000000000000000000000000000000000000..60aecce5d12ee10edc74b58f556b3ca28a1b6b64 Binary files /dev/null and b/targets/cygwin/drivers/TAP-WIN32/tapinstall.exe differ diff --git a/targets/cygwin/drivers/hardware.c b/targets/cygwin/drivers/hardware.c new file mode 100755 index 0000000000000000000000000000000000000000..f6807d4c6aa74d143775b459bfbad369f2c0f154 --- /dev/null +++ b/targets/cygwin/drivers/hardware.c @@ -0,0 +1,77 @@ +#include "types.h" +#undef UNICODE +#include <windows.h> +#include "wintun.h" +#include "target.h" + +utun t; +#define BUF_SIZE DEV_MTU +unsigned char read_buf[BUF_SIZE]; +unsigned char write_buf[BUF_SIZE]; +int STATE_READ,STATE_WRITE,MAX_READ,MAX_WRITE; +short r; + +void hardware_init(void) +{ +#if (DEFAULT_IP_ADDR_0 != 192 || DEFAULT_IP_ADDR_1 != 168 || DEFAULT_IP_ADDR_2 != 0 || DEFAULT_IP_ADDR_3 != 2) +#error smews IP Address has to be 192.168.0.2, @see wintun.c : changes can be done in config.h +#endif + utun_open(&t,"192.168.0.1", "192.168.0.2", DEV_MTU ); + STATE_READ= 0; + STATE_WRITE= 0; + MAX_READ= 0; + MAX_WRITE= -1; + memset(read_buf,0,BUF_SIZE); + memset(write_buf,0,BUF_SIZE); +} + +unsigned char dev_get(void) +{ + r++; + + if(STATE_READ == MAX_READ) + { + MAX_READ= utun_read(&t,read_buf,BUF_SIZE); + STATE_READ= 0; + } + return read_buf[STATE_READ++]; +} + +void dev_put(unsigned char byte) +{ + if(STATE_WRITE+1 == MAX_WRITE) + { + if(MAX_WRITE>0) + { + int written; + write_buf[STATE_WRITE++]= byte; + written= utun_write(&t,write_buf,MAX_WRITE); + if(written!=MAX_WRITE) + abort(); + } + else + abort(); + } + else + write_buf[STATE_WRITE++]= byte; +} + +char dev_prepare_output(uint16_t len) +{ + if(len>BUF_SIZE) + { + //MSS too large !?! + abort(); + return 0; + } + fflush(stdout); + memset(write_buf,0,BUF_SIZE); + STATE_WRITE= 0; + MAX_WRITE= len; + return 1; +} + +unsigned char dev_data_to_read(void) +{ + return MAX_READ - STATE_READ; +} diff --git a/targets/cygwin/drivers/target.h b/targets/cygwin/drivers/target.h new file mode 100755 index 0000000000000000000000000000000000000000..40ca287db7cc7fbdc8bf4e7c440831b4c326c1df --- /dev/null +++ b/targets/cygwin/drivers/target.h @@ -0,0 +1,63 @@ + + +#ifndef CYGWIN_TARGET_TYPES_H +#define CYGWIN_TARGET_TYPES_H + +#define DEV_MTU 1500 + +#include <stdint.h> + +extern void hardware_init(void); +extern unsigned char dev_get(void); +extern void dev_put(unsigned char byte); +extern char dev_prepare_output(uint16_t len); +extern unsigned char dev_data_to_read(void); + +#define HARDWARE_INIT hardware_init() +#define HARDWARE_STOP +#define TIME_MILLIS 0 +#define DEV_GET(c) {(c) = dev_get();} +#define DEV_PUT(c) dev_put(c) +#define DEV_PREPARE_OUTPUT(length) if(!dev_prepare_output(length)) return +#define DEV_OUTPUT_DONE +#define DEV_DATA_TO_READ dev_data_to_read() + + +#define SMEWS_WAITING +#define SMEWS_SENDING +#define SMEWS_RECEIVING +#define SMEWS_ENDING + +/* Progmem macros */ + +#define CONST_VOID_P_VAR const void * +#define CONST_VAR(type,name) type const name +#define PERSISTENT_VAR(type,name) type name + +#define CONST_READ_UI8(x) ((uint8_t)*((uint8_t*)(x))) +#define CONST_READ_UI16(x) ((uint16_t)*((uint16_t*)(x))) +#define CONST_READ_UI32(x) ((uint32_t)*((uint32_t*)(x))) +#define CONST_READ_ADDR(x) ((void*)*((void**)(x))) + +#define CONST_UI8(x) ((uint8_t)(x)) +#define CONST_UI16(x) ((uint16_t)(x)) +#define CONST_UI32(x) ((uint32_t)(x)) +#define CONST_ADDR(x) ((void*)(x)) + +#define CONST_WRITE_NBYTES(dst,src,len) memcpy(dst,src,len) + +extern int strcmp(const char *s1, const char *s2); +#define STRCMP_P(s,sconst) strcmp(s,sconst) + +/* Endianness */ + +#define ENDIANNESS LITTLE_ENDIAN + +/* Smews configuration */ + +#define MAX_TIMERS 8 +#define MAX_CONNECTIONS 32 +#define OUTPUT_BUFFER_SIZE 128 +#define ARGS_BUFFER_SIZE 128 + +#endif /* AVR_TARGET_TYPES_H */ diff --git a/targets/cygwin/drivers/wintun.c b/targets/cygwin/drivers/wintun.c new file mode 100755 index 0000000000000000000000000000000000000000..fa71a18af6d2ed598baed6c7c3c8f21107fb8492 --- /dev/null +++ b/targets/cygwin/drivers/wintun.c @@ -0,0 +1,491 @@ +/* +*Lib Universal TUN (libutun) Copyright(C) Geoffroy Cogniaux < geoffroy@cogniaux.com > +* +*Lib Universal TUN 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.1 of the License, or(at your option)any later version. +* +*Lib Universal TUN 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 Lib Universal TUN; if not, write to the Free Software +*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA +* +** +*Lib Universal TUN uses TAP-Win32 on Windows(r) +* -- A kernel driver to provide virtual tap device +* functionality on Windows. Originally derived +* from the CIPE-Win32 project by Damion K. Wilson, +* with extensive modifications by James Yonan. +* +*All original source code using TAP-Win32 which derives from the CIPE-Win32 project is +*Copyright (C) Damion K. Wilson, 2003, and is released under the +*GPL version 2. +* +*All other original source code using TAP-Win32 is +*Copyright (C) 2002-2006 OpenVPN Solutions LLC, +*and is released under the GPL version 2 . + + + +On Windows, point-to-point IP support (i.e. --dev tun) +is emulated by the TAP-Win32 driver. The major limitation +imposed by this approach is that the --ifconfig local and +remote endpoints must be part of the same 255.255.255.252 +subnet. The following list shows examples of endpoint +pairs which satisfy this requirement. Only the final +component of the IP address pairs is at issue. + +As an example, the following option would be correct: + --ifconfig 10.7.0.5 10.7.0.6 (on host A) + --ifconfig 10.7.0.6 10.7.0.5 (on host B) +because [5,6] is part of the below list. + +[ 1, 2] [ 5, 6] [ 9, 10] [ 13, 14] [ 17, 18] +[ 21, 22] [ 25, 26] [ 29, 30] [ 33, 34] [ 37, 38] +[ 41, 42] [ 45, 46] [ 49, 50] [ 53, 54] [ 57, 58] +[ 61, 62] [ 65, 66] [ 69, 70] [ 73, 74] [ 77, 78] +[ 81, 82] [ 85, 86] [ 89, 90] [ 93, 94] [ 97, 98] +[101,102] [105,106] [109,110] [113,114] [117,118] +[121,122] [125,126] [129,130] [133,134] [137,138] +[141,142] [145,146] [149,150] [153,154] [157,158] +[161,162] [165,166] [169,170] [173,174] [177,178] +[181,182] [185,186] [189,190] [193,194] [197,198] +[201,202] [205,206] [209,210] [213,214] [217,218] +[221,222] [225,226] [229,230] [233,234] [237,238] +[241,242] [245,246] [249,250] [253,254] + +*/ + + +#ifdef WIN32 +#include "wintun.h" + +int utun_write (utun *t, unsigned char *buf, int len) +{ + DWORD write_size, last_err; + + ResetEvent(t->overlap_write.hEvent); + if(WriteFile(t->device_handle,buf,len,&write_size,&t->overlap_write)) + { + return write_size; + } + switch (last_err = GetLastError()) + { + case ERROR_IO_PENDING: + { + WaitForSingleObject(t->overlap_write.hEvent, INFINITE); + GetOverlappedResult(t->device_handle, &t->overlap_write, + &write_size, FALSE); + return write_size; + } + break; + default: + { + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + last_err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + printf( "utun_write failed with error %d: %s\n", last_err, lpMsgBuf ); + } + break; + } + + return -1; +} + +int utun_read (utun *t, unsigned char *buf, int len) +{ + DWORD read_size, last_err; + + ResetEvent(t->overlap_read.hEvent); + if (ReadFile(t->device_handle, buf, len, &read_size, &t->overlap_read)) + { + return read_size; + } + switch (last_err = GetLastError()) + { + case ERROR_IO_PENDING: + { + WaitForSingleObject(t->overlap_read.hEvent, INFINITE); + GetOverlappedResult(t->device_handle, &t->overlap_read, &read_size, FALSE); + return read_size; + } + break; + default: + { + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + last_err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + printf( "utun_read failed with error %d: %s\n", last_err, lpMsgBuf ); + } + break; + } + + return -1; +} + +int utun_open (utun *t, char *ip_src, char *ip_dest,unsigned long mtu) +{ + HKEY key, key2; + long rc; + char regpath[1024], cmd[256]; + char adapterid[1024]; + char adaptername[1024]; + char tapname[1024]; + long len; + int found = 0; + int err, i; + unsigned long status = TRUE; +#ifdef _DEBUG + ULONG info[3]; +#endif + + memset(t, 0, sizeof(utun)); + t->device_handle = INVALID_HANDLE_VALUE; + t->ip_src = utun_inet_addr(ip_src); + + /* Open registry and look for a working TAP-WIN32 network adapters */ + if((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key))) + { + printf("Unable to read registry: [rc=%d]\n", rc); + return -1; + } + + for (i = 0; ; i++) + { + len = sizeof(adapterid); + if(RegEnumKeyEx(key, i, (LPCWSTR)adapterid, &len, 0, 0, 0, NULL)) + break; + + /* Find out more about this adapter */ + + _snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid); + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)regpath, 0, KEY_READ, &key2)) + continue; + + len = sizeof(adaptername); + err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len); + + RegCloseKey(key2); + + if(err) + continue; + + _snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid); + t->device_handle = CreateFile(tapname, + GENERIC_WRITE | GENERIC_READ, + 0,0, + OPEN_EXISTING, + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, + 0); + if(t->device_handle != INVALID_HANDLE_VALUE) + { + found = 1; + break; + } + else + { + LPVOID lpMsgBuf; + DWORD dw = GetLastError(); + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + + if(dw!=2)//File not found . + { + //could inform that a TAP is found but isn't working well. + printf("Adapter %s, file %s\n",adaptername,tapname); + printf( "utun_open failed with error %d: %s\n", dw, lpMsgBuf ); + } + } + }//end for + + RegCloseKey(key); + + if(!found) + { + printf("No Windows tap device found!\n"); + return -1; + } + + /* Try to open the useful TAP-Win32 driver !! */ + + if(t->device_handle == INVALID_HANDLE_VALUE) + { + _snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid); + t->device_handle = + CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); + } + + if(t->device_handle == INVALID_HANDLE_VALUE) + { + printf("%s (%s) is not a usable TAP-Win32\n", adaptername, adapterid); + return -1; + } + +#ifdef _DEBUG + if (DeviceIoControl (t->device_handle, TAP_IOCTL_GET_VERSION, + &info, sizeof (info), + &info, sizeof (info), &len, NULL)) + { + printf( "Loading TAP-Win32 Driver Version %d.%d %s\n", + (int) info[0], + (int) info[1], + (info[2] ? "(DEBUG)" : "")); + + } +#endif + + //Configure as PtoP, require to emulate TUN + if(t->device_handle) + { + ULONG ep[2]; + ep[0] = utun_inet_addr(ip_src); + ep[1] = utun_inet_addr(ip_dest); + + if (!DeviceIoControl (t->device_handle, TAP_IOCTL_CONFIG_POINT_TO_POINT, + ep, sizeof (ep), + ep, sizeof (ep), &len, NULL)) + { + printf( "ERROR: The TAP-Win32 driver rejected a DeviceIoControl call to set Point-to-Point mode"); + return -1; + } + } + + _snprintf(cmd, sizeof(cmd), + "netsh interface ip set address \"%s\" static %s 255.255.255.252",adaptername,ip_src); +#ifdef _DEBUG + printf("Setting to \"%s\" device a correct address, please wait...\n", adaptername); + printf("Excuting: %s\n", cmd); +#endif + if(system(cmd) == 0) + { + t->ip_src= utun_inet_addr(ip_src); + t->ip_dest= utun_inet_addr(ip_dest); +#ifdef _DEBUG + printf("Device \"%s\" set from %s to %s\n", adaptername, ip_src, ip_dest); +#endif + } + else + { + _snprintf(cmd, sizeof(cmd),"netsh interface ip show config \"%s\"",adaptername); + printf("WNG: Unable to set correctly IP addresses, please check it manually.\n"); + system(cmd); + } + + /* try to change MTU */ + if(mtu >= 100 && mtu <= 1500)// TAP-WIN32 V8 constraint + { + char cfgid[1024]; + char keyid[32]; + char str_mtu[32]; + + itoa(mtu,str_mtu,10); + + if((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ADAPTER_KEY, 0, KEY_READ, &key))) + { + printf("Unable to read registry: [rc=%d]\n", rc); + return -1; + } + for (i = 0; ; i++) + { + int len = sizeof(keyid); + if(RegEnumKeyEx(key, i, (LPCWSTR)keyid, &len, 0, 0, 0, NULL)) + break; + + _snprintf(regpath, sizeof(regpath), "%s\\%s\\", ADAPTER_KEY, keyid); + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)regpath, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, &key2)) + continue; + + len = sizeof(cfgid); + err = RegQueryValueEx(key2, "NetCfgInstanceId", 0, 0, cfgid, &len); + + if(strcmp(adapterid,cfgid)==0) + { + RegSetValueEx(key2,"MTU",0,REG_SZ,(LPCTSTR)&str_mtu,sizeof(DWORD)); + + RegCloseKey(key2); + break; + } + else + continue; + } + RegCloseKey(key); + + } + + + /* set driver media status to 'connected' (i.e. set the interface up) */ + if (!DeviceIoControl (t->device_handle, TAP_IOCTL_SET_MEDIA_STATUS, + &status, sizeof (status), + &status, sizeof (status), &len, NULL)) + { + printf("WARNING: Unable to enable TAP adapter\n"); + return -1; + } + + + t->overlap_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + t->overlap_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (!t->overlap_read.hEvent || !t->overlap_write.hEvent) + { + printf("WARNING: Unable to create Overlapped Events\n"); + return -1; + } + + return 0; +} + +void utun_close (utun *t) +{ + CancelIo(t->device_handle); + CloseHandle(t->overlap_read.hEvent); + CloseHandle(t->overlap_write.hEvent); + CloseHandle(t->device_handle); +} + +int utun_select(utun *t) +{ + return 0; +} + + +__inline unsigned short utun_htons(unsigned short n) +{ + return ((n & 0xFF) << 8) | ((n & 0xFF00) >> 8); +} + +__inline unsigned short utun_ntohs(unsigned short n) +{ + return ((n & 0xFF) << 8) | ((n & 0xFF00) >> 8); +} + +__inline unsigned long utun_htonl(unsigned long n) +{ + return ((n & 0xFF) << 24) | ((n & 0xFF00) << 8) | ((n & 0xFF0000) >> 8) | ((n & 0xFF000000) >> 24); +} + +__inline unsigned long utun_ntohl(unsigned long n) +{ + return ((n & 0xFF) << 24) | ((n & 0xFF00) << 8) | ((n & 0xFF0000) >> 8) | ((n & 0xFF000000) >> 24); +} + +unsigned long utun_inet_addr(const char *src) +{ + unsigned int val; + int base, n; + unsigned char c; + unsigned int parts[4]; + unsigned int *pp = parts; + + c = *src; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; base = 10; + if (c == '0') { + c = *++src; + if (toupper(c) == 'X') + base = 16, c = *++src; + else + base = 8; + } + for (;;) { + if (isdigit(c)) { + val = (val * base) + (c - '0'); + c = *++src; + } else if (base == 16 && isxdigit(toupper(c))) { + val = (val << 4) | + (toupper(c) + 10 - 'A'); + c = *++src; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++src; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && !isspace(c)) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + + val = utun_htonl(val); + return (val); +} + + + + +#endif + diff --git a/targets/cygwin/drivers/wintun.h b/targets/cygwin/drivers/wintun.h new file mode 100755 index 0000000000000000000000000000000000000000..4fd6f94bc9b8d9bf311f1da21b74c66188982c29 --- /dev/null +++ b/targets/cygwin/drivers/wintun.h @@ -0,0 +1,106 @@ +/* +*Lib Universal TUN (libutun) Copyright(C) Geoffroy Cogniaux < geoffroy@cogniaux.com > +* +*Lib Universal TUN 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.1 of the License, or(at your option)any later version. +* +*Lib Universal TUN 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 Lib Universal TUN; if not, write to the Free Software +*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA +* +** +*Lib Universal TUN uses TAP-Win32 on Windows(r) +* -- A kernel driver to provide virtual tap device +* functionality on Windows. Originally derived +* from the CIPE-Win32 project by Damion K. Wilson, +* with extensive modifications by James Yonan. +* +*All original source code using TAP-Win32 which derives from the CIPE-Win32 project is +*Copyright (C) Damion K. Wilson, 2003, and is released under the +*GPL version 2. +* +*All other original source code using TAP-Win32 is +*Copyright (C) 2002-2006 OpenVPN Solutions LLC, +*and is released under the GPL version 2 . +*/ + +#ifndef WINTUN_H +#define WINTUN_H 1 + +#ifdef WIN32 +#undef UNICODE +#include <windows.h> +#include <winioctl.h> +#include <stdio.h> +#include <string.h> + +#define itoa _itoa +#define snprint _snprintf + +//some decl avoiding winsock import, differents names are requiered because accessibles via windows.h in VC++ +extern unsigned short utun_htons(unsigned short n); +extern unsigned short utun_ntohs(unsigned short n); +extern unsigned long utun_htonl(unsigned long n); +extern unsigned long utun_ntohl(unsigned long n); +extern unsigned long utun_inet_addr(const char *src); + +#if defined (__CYGWIN__) +#include <ctype.h> +struct in_addr +{ + union + { + struct { unsigned char s_b1, s_b2, s_b3, s_b4; } s_un_b; + struct { unsigned short s_w1, s_w2; } s_un_w; + unsigned long s_addr; + }; +}; +#endif + +typedef struct tun_t { + HANDLE device_handle; + unsigned int ip_src,ip_dest; + OVERLAPPED overlap_read, overlap_write; +} utun; + + +//Following come from OpenVpn +#define TAP_CONTROL_CODE(request,method) \ + CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) + +#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED) +#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED) +#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED) +#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED) +#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED) +#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED) + +#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" +#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" + +#define USERMODEDEVICEDIR "\\\\.\\Global\\" +#define SYSDEVICEDIR "\\Device\\" +#define USERDEVICEDIR "\\DosDevices\\Global\\" +#define TAPSUFFIX ".tap" + +#define TAP_COMPONENT_ID "tap0801" + +#endif + +extern int utun_open (utun *t, char *ip_src, char *ip_dest, unsigned long mtu); +extern int utun_write (utun *t, unsigned char *buf, int len); +extern int utun_read (utun *t, unsigned char *buf, int len); +extern void utun_close (utun *t); +extern int utun_select(utun *t); + +#endif diff --git a/targets/klinux/Makefile b/targets/klinux/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..ca24c1413be6b721a5b9798c983deb72b7005ee4 --- /dev/null +++ b/targets/klinux/Makefile @@ -0,0 +1,17 @@ +default: ksmews +KERNELDIR := /lib/modules/`uname -r`/build +PWD := `pwd`/ +obj-m := ksmews.o + +include $(M)ksmews-objs-list + +EXTRA_CFLAGS += -DCHUNCKS_NBITS=5 -I$(M)/core -I$(M)/drivers -I$(M)/. + +.PHONY: clean + +clean: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean + $(RM) -rf Module.markers modules.order + +ksmews: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules diff --git a/targets/klinux/SConscript b/targets/klinux/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..beb7794f35cec7caa26ea995ffa5cf1f42d16855 --- /dev/null +++ b/targets/klinux/SConscript @@ -0,0 +1,110 @@ +# Copyright or c or Copr. 2008, Simon Duquennoy +# +# Author e-mail: simon.duquennoy@lifl.fr +# +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + +import os +import sys +import glob +import GenContents + +Import('env binDir genDir coreDir targetDir driversDir genDir wcBase projectName elfName sourcesMap chuncksNbits gzipped tmpBase') + +koName = 'ksmews.ko' +objsListName = 'ksmews-objs-list' + +env.Replace(CC = 'gcc') +env.Replace(AS = 'as') +env.Replace(AR = 'ar') +env.Replace(RANLIB = 'ranlib') + +# used by getCodeFiles +def getCodeFilesRec(wcPath,path): + files=[] + for file in glob.glob(path + '/*'): + if os.path.basename(file) != 'SConscript': + if os.path.isdir(file): + files = files + (getCodeFilesRec(wcPath,file)) + elif file.endswith('c') or file.endswith('h') or file.endswith('s'): + files.append(file[len(wcPath)+1:]) + return files + +# returns all files contained in path (with recurssion) +def getCodeFiles(path): + return getCodeFilesRec(path,path) + +# builder used to override the usual object file construction +def dontGenerateObject(target, source, env): + return None + +# builder used to override the usual library construction +def dontGenerateLibrary(target, source, env): + return None + +# builder used generate the object list needed by the kernel module makefile +def generatedObjectsList(target, source, env): + objsListFile = open(str(target[0]),'w') + sourceStr = map(lambda x: str(x),source) + allObjs = map(lambda x: x[len(genDir)+1:len(x)-1]+'o',filter(lambda x: x.endswith('.c') or x.endswith('.s'),sourceStr)) + for obj in allObjs: + objsListFile.write('ksmews-objs += %s\n' %(obj)) + objsListFile.close() + return None + +# builder used to override the usual executable binary construction +def dontGenerateProgram(target, source, env): + makefile = env.Command(os.path.join(genDir,"Makefile"), os.path.join(targetDir,"Makefile"), Copy("$TARGET", "$SOURCE")) + srcCore = getCodeFiles('core') + srcDrivers = getCodeFiles(driversDir) + tmpDir = os.path.join(genDir,tmpBase) + srcGen = getCodeFiles(tmpDir) + for src in srcCore: + env.Command(os.path.join(genDir,'core',src), os.path.join('core',src), Copy("$TARGET", "$SOURCE")) + for src in srcDrivers: + env.Command(os.path.join(genDir,'drivers',src), os.path.join(driversDir,src), Copy("$TARGET", "$SOURCE")) + for src in srcGen: + env.Command(os.path.join(genDir,tmpDir,src), os.path.join(tmpDir,src), Copy("$TARGET", "$SOURCE")) + allSrcs = map(lambda x: os.path.join('core',x),srcCore) + allSrcs += map(lambda x: os.path.join('drivers',x),srcDrivers) + allSrcs += map(lambda x: os.path.join(tmpDir,x),srcGen) + allSrcs += map(lambda x: GenContents.getFileName(x,chuncksNbits,gzipped) + '.c',sourcesMap.keys()) + allSrcs.append('resources_index.c') + allSrcs.append('channels.h') + allSrcs = map(lambda x: os.path.join(genDir,x),allSrcs) + objsList = env.ObjectsList(os.path.join(genDir,objsListName), allSrcs) + env.Command(os.path.join(genDir,koName), allSrcs + makefile + objsList, 'make -C %s' %(genDir)) + env.Command(os.path.join(binDir,koName), os.path.join(genDir,koName), Copy("$TARGET", "$SOURCE")) + return None + +env['BUILDERS']['Object'] = Builder(action = dontGenerateObject) +env['BUILDERS']['Library'] = Builder(action = dontGenerateLibrary) +env['BUILDERS']['Program'] = Builder(action = dontGenerateProgram) +env['BUILDERS']['ObjectsList'] = Builder(action = generatedObjectsList) diff --git a/targets/klinux/drivers/module.c b/targets/klinux/drivers/module.c new file mode 100644 index 0000000000000000000000000000000000000000..ce51a0d588522103ded7981bd78a119340be074c --- /dev/null +++ b/targets/klinux/drivers/module.c @@ -0,0 +1,247 @@ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/netdevice.h> +#include <linux/netfilter.h> +#include <linux/inetdevice.h> +#include <linux/timer.h> +#include "smews.h" +#include "input.h" +#include "output.h" +#include "connections.h" + +int ksmews_recv_eth(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); + +static struct packet_type ksmews_ip_packet_type = { + .type = __constant_htons(ETH_P_IP), + .func = ksmews_recv_eth, +}; +static struct list_head initial_pt_handlers; +static struct list_head *pt_handlers_head = NULL; +static struct net_device *smews_dev = NULL; +static char *curr_in_data = NULL; +static char *curr_out_data = NULL; +static struct sk_buff *out_skb = NULL; +static unsigned char hw_src[6]; +static unsigned char hw_dst[6]; +static char hw_dst_set = 0; + +void ksmews_callback(unsigned long arg); + +//~ static struct timer_list ksmews_timer; +DECLARE_TASKLET(ksmews_tasklet,ksmews_callback,0); + +//~ #define KSMEWS_DBG + +#define ksmews_print(...) printk(KERN_ALERT "[ksmews] " __VA_ARGS__ ) +#ifdef KSMEWS_DBG + #define ksmews_dbg(...) printk(KERN_ALERT "[ksmews] " __VA_ARGS__ ) +#else + #define ksmews_dbg(...) +#endif + + +/*-----------------------------------------------------------------------------------*/ +void smews_put(unsigned char c) { + if(out_skb) + *curr_out_data++ = c; + return; +} + +/*-----------------------------------------------------------------------------------*/ +void smews_putn_const(unsigned char *ptr,uint16_t n) { + memcpy(curr_out_data,ptr,n); + curr_out_data+=n; +} + +/*-----------------------------------------------------------------------------------*/ +void smews_prepare_output(uint16_t length) { + ksmews_dbg(">prepare output %d\n",length); + /* create skbuf with the requested size */ + out_skb = alloc_skb(length + LL_ALLOCATED_SPACE(smews_dev), GFP_ATOMIC); + if (out_skb == NULL) + return; + /* set the skbuf */ + out_skb->dev = smews_dev; + out_skb->protocol = ETH_P_IP; + out_skb->network_header = out_skb->data+20; + /* reserve space for both ethernet header and data (size: length) */ + skb_reserve(out_skb, LL_RESERVED_SPACE(smews_dev)); + curr_out_data = skb_put(out_skb,length); + /* fill ethernet header */ + if (dev_hard_header(out_skb, smews_dev, ETH_P_IP, hw_dst, hw_src, out_skb->len) < 0) { + out_skb = NULL; + return; + } + ksmews_dbg("<prepare output\n"); +} + +/*-----------------------------------------------------------------------------------*/ +void smews_output_done(void) { + ksmews_dbg(">send\n"); + /* transmit the skbuf */ + if(out_skb) { + NF_HOOK(NFPROTO_UNSPEC, 0, out_skb, NULL, out_skb->dev, dev_queue_xmit); + } + ksmews_dbg("<send\n"); +} + +/*-----------------------------------------------------------------------------------*/ +int16_t smews_get(void) { + if(curr_in_data) + return 0x00ff & (*curr_in_data++); + else + return -1; +} + +/*-----------------------------------------------------------------------------------*/ +unsigned char smews_data_to_read(void) { + return curr_in_data != NULL; +} + +/*-----------------------------------------------------------------------------------*/ +static inline int deliver_skb(struct sk_buff *skb, struct packet_type *pt_prev, struct net_device *orig_dev) { + atomic_inc(&skb->users); + return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); +} + +/*-----------------------------------------------------------------------------------*/ +void ksmews_callback(unsigned long arg) { + ksmews_dbg(">tasklet\n"); + if(smews_main_loop_step(1)) { + tasklet_hi_schedule(&ksmews_tasklet); + } + ksmews_dbg("<tasklet\n"); +} + +/*-----------------------------------------------------------------------------------*/ +int ksmews_recv_eth(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { + ksmews_dbg(">recv IP/Eth\n"); + /* target the beginning of the IP data */ + /* first check if this packet is for smews */ + if(ntohl(*(unsigned int*)(skb->network_header + 16)) != UI32(local_ip_addr) || // check IP dst address + ntohs(*(unsigned short*)(skb->network_header + 2)) < 40 || // check IP packet size + *(unsigned char*)(skb->network_header + 9) != 6 || // check IP proto == TCP + ntohs(*(unsigned short*)(skb->network_header + 22)) != 80 // check TCP dst port == 80 + ) { /* forward the packet to initial kernel handlers (this code is mainly copied from linux net/core/dev.c) */ + ksmews_dbg("*forward\n"); + struct packet_type *ptype, *pt_prev = NULL; + struct net_device *null_or_orig = NULL; + if(orig_dev->master) { + if(skb_bond_should_drop(skb)) + null_or_orig = orig_dev; /* deliver only exact match */ + } + + list_for_each_entry(ptype, &initial_pt_handlers, list) { + if(ptype->dev == null_or_orig || + ptype->dev == skb->dev || + ptype->dev == orig_dev) { + if(pt_prev) + deliver_skb(skb, pt_prev, orig_dev); + pt_prev = ptype; + } + } + if(pt_prev) { + pt_prev->func(skb, skb->dev, pt_prev, orig_dev); + } else { + kfree_skb(skb); + } + } else { /* process the packet in smews */ + ksmews_dbg("*process\n"); + if(!hw_dst_set) { /* store the source address as a future dst address */ + memcpy(hw_dst,skb->mac_header+6,6); + hw_dst_set = 1; + } + /* run smews */ + curr_in_data = skb->network_header; + //~ if(smews_receive()) { + //~ tasklet_hi_schedule(&ksmews_tasklet); + //~ } + //~ curr_in_data = NULL; + if(smews_receive()) { + curr_in_data = NULL; + while(smews_main_loop_step(1)); + //~ tasklet_hi_schedule(&ksmews_tasklet); + } + + /* free the skbuf and give back the hand */ + kfree_skb(skb); + } + ksmews_dbg("<recv IP/Eth\n"); + return 0; +} + +/*-----------------------------------------------------------------------------------*/ +void ksmews_override_eth_handler(struct packet_type *pt) { + struct packet_type *pt1; + /* insert the new handler */ + dev_add_pack(pt); + /* access the handlers list */ + pt_handlers_head = pt->list.prev; + /* create a list for the initial handlers */ + INIT_LIST_HEAD(&initial_pt_handlers); + /* fill the list with inirial handlers */ + list_for_each_entry(pt1, pt_handlers_head, list) { + if (pt1 && pt != pt1 && pt->type == pt1->type) { + struct packet_type *pt2 = list_entry(pt1->list.next, typeof(*pt1), list); + list_del(&pt1->list); + list_add(&pt1->list,&initial_pt_handlers); + pt1 = pt2; + } + } +} + +/*-----------------------------------------------------------------------------------*/ +void ksmews_restore_eth_handler(struct packet_type *pt) { + /* remove the current handler */ + dev_remove_pack(pt); + /* restore the inirial handlers */ + list_splice(&initial_pt_handlers,pt_handlers_head); +} + +/*-----------------------------------------------------------------------------------*/ +static int ksmews_init(void) { + ksmews_print("*initializing\n"); + /* init smews */ + smews_init(); + /* remove the kernel handlers for all IP/ethernet packets, replace with the smews handler */ + ksmews_override_eth_handler(&ksmews_ip_packet_type); + /* search the ethernet device structure */ + smews_dev = __dev_get_by_name(&init_net,"eth0"); + if(smews_dev == NULL) { + smews_dev = __dev_get_by_name(&init_net,"eth1"); + if(smews_dev == NULL) { + return 0; + } + } + /* get the mac and IP addresses from the device */ + memcpy(hw_src,smews_dev->perm_addr,6); + UI32(local_ip_addr) = ntohl(inet_select_addr(smews_dev, 0, 0)); + /* print status */ + ksmews_print("*network device: %s\n",smews_dev->name); + ksmews_print("*mac address: %02x:%02x:%02x:%02x:%02x:%02x\n",hw_src[0],hw_src[1],hw_src[2],hw_src[3],hw_src[4],hw_src[5]); + ksmews_print("*IP address: %d.%d.%d.%d\n",local_ip_addr[3],local_ip_addr[2],local_ip_addr[1],local_ip_addr[0]); + +//~ init_timer(&ksmews_timer); +//~ ksmews_timer.function=ksmews_callback; +//~ ksmews_timer.expires=jiffies; +//~ add_timer(&ksmews_timer); + + return 0; +} + +/*-----------------------------------------------------------------------------------*/ +static void __exit ksmews_exit(void) { + /* restore the initial handlers for IP/ethernet packets */ + ksmews_restore_eth_handler(&ksmews_ip_packet_type); + /* remove the timer */ + tasklet_kill(&ksmews_tasklet); + //~ del_timer_sync(&ksmews_timer); + ksmews_print("exiting\n"); +} + +/*-----------------------------------------------------------------------------------*/ +module_init(ksmews_init); +module_exit(ksmews_exit); + +MODULE_LICENSE("GPL"); diff --git a/targets/klinux/drivers/target.h b/targets/klinux/drivers/target.h new file mode 100644 index 0000000000000000000000000000000000000000..439bf65ded95bb54118b074512c18129df3cce9d --- /dev/null +++ b/targets/klinux/drivers/target.h @@ -0,0 +1,147 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __TARGET_H__ +#define __TARGET_H__ + +/* Other c and h target-specific files must be located in the drivers directory */ + +/* Types definition */ + +/* Target specific includes */ + +/* smews includes */ +#include <linux/init.h> +#include <linux/module.h> + +extern int16_t smews_get(void); +extern void smews_put(unsigned char c); +extern void smews_putn_const(unsigned char *ptr,uint16_t n); +extern unsigned char smews_data_to_read(void); +extern void smews_prepare_output(uint16_t length); +extern void smews_output_done(void); +extern void smews_wait_input(void); + +/* Drivers interface */ + +#define DEV_MTU 1500 +#define HARDWARE_INIT +#define HARDWARE_STOP +#define TIME_MILLIS 0 +#define DEV_GET(c) {(c) = smews_get();} +#define DEV_PUT(c) smews_put(c) +#define DEV_PUTN(ptr,n) +#define DEV_PUTN_CONST(ptr,n) smews_putn_const(ptr,n) +#define DEV_PREPARE_OUTPUT(length) smews_prepare_output(length) +#define DEV_OUTPUT_DONE smews_output_done() +#define DEV_DATA_TO_READ smews_data_to_read() +#define DEV_WAIT + +/* Smews states */ + +/* Called by the kernel when starting to wait for data */ +#define SMEWS_WAITING +/* Called by the kernel when starting to receive data */ +#define SMEWS_RECEIVING +/* Called by the kernel when starting to send data */ +#define SMEWS_SENDING +/* Called by the kernel when ending to send data */ +#define SMEWS_ENDING + +/* Cons variables macros */ + +/* Used to declare a reference to a const */ +#define CONST_VOID_P_VAR const void * +/* used to declare a variable as const */ +#define CONST_VAR(type,name) type const name +#define PERSISTENT_VAR(type,name) type name + +/* Gets a byte from address x */ +#define CONST_READ_UI8(x) ((uint8_t)*((uint8_t*)(x))) +/* Gets two bytes from address x */ +#define CONST_READ_UI16(x) ((uint16_t)*((uint16_t*)(x))) +/* Gets four bytes from address x */ +#define CONST_READ_UI32(x) ((uint32_t)*((uint32_t*)(x))) +/* Gets an address from address x */ +#define CONST_READ_ADDR(x) ((void*)*((void**)(x))) + +/* Get the value of x, where x is declared as a one byte const */ +#define CONST_UI8(x) ((uint8_t)(x)) +/* Get the value of x, where x is declared as a two bytes const */ +#define CONST_UI16(x) ((uint16_t)(x)) +/* Get the value of x, where x is declared as a four bytes const */ +#define CONST_UI32(x) ((uint32_t)(x)) +/* Get the value of x, where x is declared as a const reference */ +#define CONST_ADDR(x) ((void*)(x)) +/* Writes len bytes from src to dst, where dst targets a persistent variable */ +#define CONST_WRITE_NBYTES(dst,src,len) + +/* Endianness: define ENDIANNESS as LITTLE_ENDIAN or BIG_ENDIAN */ +#ifndef ENDIANNESS + #define ENDIANNESS LITTLE_ENDIAN +#endif + +/* Context switching */ + +#define USE_FRAME_POINTER + +#define BACKUP_CTX(sp) \ + asm ("movl %%esp, %0" : "=r"((sp)[0])); \ + asm ("movl %%ebp, %0" : "=r"((sp)[1])); \ + +#define RESTORE_CTX(sp) \ + asm ("movl %0, %%esp" :: "r"((sp)[0])); \ + asm ("movl %0, %%ebp" :: "r"((sp)[1])); \ + + +#define PUSHREGS asm( \ + "pushl %edi\n" \ + "pushl %esi\n" \ + "pushl %ebx\n" \ +); \ + +#define POPREGS asm( \ + "popl %ebx\n" \ + "popl %esi\n" \ + "popl %edi\n" \ +); \ + +/* Smews configuration */ + +#define OUTPUT_BUFFER_SIZE 256 +#define STACK_SIZE 4*1024 +#define ALLOC_SIZE 64*1024 + +#endif /* __TARGET_H__ */ diff --git a/targets/linux/SConscript b/targets/linux/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..05fb3bcb79783732bcba7d6dd4758d5fd76627b1 --- /dev/null +++ b/targets/linux/SConscript @@ -0,0 +1,44 @@ +# Copyright or c or Copr. 2008, Simon Duquennoy +# +# Author e-mail: simon.duquennoy@lifl.fr +# +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + + +import os +import sys + +Import('env binDir projectName elfName') + +env.Replace(CC = 'gcc') +env.Replace(AS = 'as') +env.Replace(AR = 'ar') +env.Replace(RANLIB = 'ranlib') +env.Append(CCFLAGS = '-fno-strict-aliasing') diff --git a/targets/linux/drivers/hardware.c b/targets/linux/drivers/hardware.c new file mode 100644 index 0000000000000000000000000000000000000000..d3d22fcb2bf6eedf310509d5acaecffbb1cf70cf --- /dev/null +++ b/targets/linux/drivers/hardware.c @@ -0,0 +1,175 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "target.h" +#include "connections.h" + +#include <stdio.h> +#include <string.h> +#include <sys/socket.h> + +#include <sys/ioctl.h> +#include <linux/if.h> +#include <linux/if_tun.h> +#include <sys/time.h> +#include <fcntl.h> + +#define DEVTUN "/dev/net/tun" + +unsigned char in_buffer[INBUF_SIZE]; +#ifdef IPV6 +unsigned char out_buffer[OUTBUF_SIZE]={0x0,0x0,0x86,0xdd}; +#else +unsigned char out_buffer[OUTBUF_SIZE]={0x0,0x0,0x08,0x0}; +#endif + +int tun_fd; +int in_curr; +int out_curr; +int in_nbytes; +struct timeval tv; +fd_set fdset; +static int ret; + +/*-----------------------------------------------------------------------------------*/ +void check(int test,const char *message) { + if(!test) { + perror(message); + exit(1); + } +} + +/*-----------------------------------------------------------------------------------*/ +uint32_t get_time(void) { + struct timeval stime; + ret = gettimeofday(&stime, (struct timezone*)0); + check(ret != -1,"gettimeofday() error"); + return stime.tv_sec * 1000 + stime.tv_usec / 1000; +} + +/*-----------------------------------------------------------------------------------*/ +void dev_init(void) { + struct ifreq ifr; + +#ifdef IPV6 + int lastBit; + + if ((local_ip_addr[0] % 2)) + lastBit = local_ip_addr[0]-1; + else + lastBit = local_ip_addr[0]+1; + +#endif + + tun_fd = open(DEVTUN, O_RDWR); + check(tun_fd != -1,"tun open() error"); + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TUN; + ret = ioctl(tun_fd, TUNSETIFF, (void *) &ifr); + check(ret != -1,"ioctl() error"); +#ifdef IPV6 + snprintf((char*)out_buffer+4, sizeof(out_buffer)-4, "ifconfig %s inet6 add %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/127",ifr.ifr_name,local_ip_addr[15],local_ip_addr[14],local_ip_addr[13],local_ip_addr[12],local_ip_addr[11],local_ip_addr[10],local_ip_addr[9],local_ip_addr[8],local_ip_addr[7],local_ip_addr[6],local_ip_addr[5],local_ip_addr[4],local_ip_addr[3],local_ip_addr[2],local_ip_addr[1],lastBit); + ret = system((char*)out_buffer+4); + check(ret != -1,"system() error"); + snprintf((char*)out_buffer+4, sizeof(out_buffer)-4, "ifconfig %s up", ifr.ifr_name); +#else + snprintf((char*)out_buffer+4, sizeof(out_buffer)-4, "ifconfig %s 192.168.0.1 pointopoint %d.%d.%d.%d mtu 1500",ifr.ifr_name,local_ip_addr[3],local_ip_addr[2],local_ip_addr[1],local_ip_addr[0]); +#endif + ret = system((char*)out_buffer+4); + check(ret != -1,"system() error"); + + in_curr = 0; + in_nbytes = 0; + out_curr = 4; + FD_ZERO(&fdset); +} + +/*-----------------------------------------------------------------------------------*/ +int16_t dev_get() { + unsigned char c; + if(in_curr >= in_nbytes - 1) { + int ret; + tv.tv_sec = 0; + tv.tv_usec = 50000; + FD_SET(tun_fd, &fdset); + ret = select(tun_fd + 1, &fdset, NULL, NULL, &tv); + check(ret != -1,"select() error"); + if(ret == 0) { + return -1; + } else { + ret = read(tun_fd, (void *)in_buffer, INBUF_SIZE); + if(ret == -1) { + return -1; + } else { + in_nbytes = ret; + in_curr = -1 + 4; + c = in_buffer[++in_curr]; + } + } + } else { + c = in_buffer[++in_curr]; + } + return c; +} + +/*-----------------------------------------------------------------------------------*/ +void wait_input() { + tv.tv_sec = 0; + tv.tv_usec = 50000; + FD_SET(tun_fd, &fdset); + ret = select(tun_fd + 1, &fdset, NULL, NULL, &tv); + check(ret != -1,"select() error"); +} + +/*-----------------------------------------------------------------------------------*/ +unsigned char dev_data_to_read() { + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_SET(tun_fd, &fdset); + ret = select(tun_fd + 1, &fdset, NULL, NULL, &tv); + check(ret != -1,"select() error"); + return ret; +} + +/*-----------------------------------------------------------------------------------*/ +void dev_prepare_output() { + out_curr=4; +} + +/*-----------------------------------------------------------------------------------*/ +void dev_output_done(void) { + ret = write(tun_fd, out_buffer, out_curr); + check(ret != -1,"write() error"); +} diff --git a/targets/linux/drivers/target.h b/targets/linux/drivers/target.h new file mode 100644 index 0000000000000000000000000000000000000000..772963ebc7795a7a52581b3c8f70867ea2e97ffa --- /dev/null +++ b/targets/linux/drivers/target.h @@ -0,0 +1,145 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __TARGET_H__ +#define __TARGET_H__ + +#include <stdint.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/select.h> + +/* Network drivers */ + +extern void dev_init(void); +extern uint32_t get_time(void); +extern int16_t dev_get(); +extern unsigned char dev_data_to_read(); +extern void dev_prepare_output(); +extern void dev_output_done(void); +extern void wait_input(void); + +#define INBUF_SIZE 2048 +#define OUTBUF_SIZE 1516 + +extern unsigned char in_buffer[INBUF_SIZE]; +extern unsigned char out_buffer[OUTBUF_SIZE]; + +extern int tun_fd; +extern int in_curr; +extern int out_curr; +extern int in_nbytes; +extern struct timeval tv; +extern fd_set fdset; + +/* Drivers interface */ + +#define DEV_MTU 1500 +#define HARDWARE_INIT dev_init() +#define HARDWARE_STOP + +#define TIME_MILLIS get_time() +#define DEV_GET(c) {(c) = dev_get();} +#define DEV_PUT(c) {out_buffer[out_curr++]=(c);} +#define DEV_PUTN(ptr,n) {memcpy(out_buffer + out_curr,ptr,n); out_curr+=n;} +#define DEV_PUTN_CONST(ptr,n) {memcpy(out_buffer + out_curr,ptr,n); out_curr+=n;} +#define DEV_PREPARE_OUTPUT(length) dev_prepare_output() +#define DEV_OUTPUT_DONE dev_output_done() +#define DEV_DATA_TO_READ dev_data_to_read() +#define DEV_WAIT {wait_input();} + +/* Smews states */ + +#define SMEWS_WAITING +#define SMEWS_RECEIVING +#define SMEWS_SENDING +#define SMEWS_ENDING + +/* Const and persistent access macros */ + +#define CONST_VOID_P_VAR const void * +#define CONST_VAR(type,name) type const name +#define PERSISTENT_VAR(type,name) type name + +#define CONST_READ_UI8(x) (*((uint8_t*)(x))) +#define CONST_READ_UI16(x) (*((uint16_t*)(x))) +#define CONST_READ_UI32(x) (*((uint32_t*)(x))) +#define CONST_READ_ADDR(x) (*((void**)(x))) + +#define CONST_UI8(x) ((uint8_t)(x)) +#define CONST_UI16(x) ((uint16_t)(x)) +#define CONST_UI32(x) ((uint32_t)(x)) +#define CONST_ADDR(x) ((void*)(x)) + +#define CONST_WRITE_NBYTES(dst,src,len) memcpy(dst,src,len) + +/* Endianness */ + +#define ENDIANNESS LITTLE_ENDIAN + +/* Context switching */ + +#define USE_FRAME_POINTER + +#define BACKUP_CTX(sp) \ + asm ("movl %%esp, %0" : "=r"((sp)[0])); \ + asm ("movl %%ebp, %0" : "=r"((sp)[1])); \ + +#define RESTORE_CTX(sp) \ + asm ("movl %0, %%esp" :: "r"((sp)[0])); \ + asm ("movl %0, %%ebp" :: "r"((sp)[1])); \ + + +#define PUSHREGS asm( \ + "pushl %edi\n" \ + "pushl %esi\n" \ + "pushl %ebx\n" \ +); \ + +#define POPREGS asm( \ + "popl %ebx\n" \ + "popl %esi\n" \ + "popl %edi\n" \ +); \ + +/* Smews configuration */ + +#define OUTPUT_BUFFER_SIZE 256 +#define STACK_SIZE 4*1024 +#define ALLOC_SIZE 32*1024 + +#endif /* __TARGET_H__ */ diff --git a/targets/linuxUdp/SConscript b/targets/linuxUdp/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..a097c079ff02b991a09d3148d4d2956e197e3c0b --- /dev/null +++ b/targets/linuxUdp/SConscript @@ -0,0 +1,44 @@ +# Copyright or c or Copr. 2008, Simon Duquennoy +# +# Author e-mail: simon.duquennoy@lifl.fr +# +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + + +import os +import sys + +Import('env binDir projectName elfName') + +env.Replace(CC = 'gcc') +env.Replace(AS = 'as') +env.Replace(AR = 'ar') +env.Replace(RANLIB = 'ranlib') +env.Append(CCFLAGS = '-ansi') diff --git a/targets/linuxUdp/drivers/hardware.c b/targets/linuxUdp/drivers/hardware.c new file mode 100644 index 0000000000000000000000000000000000000000..21647618b16a6351fd17be382443bba2b8a6b45e --- /dev/null +++ b/targets/linuxUdp/drivers/hardware.c @@ -0,0 +1,165 @@ + /* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#include "types.h" +#include "target.h" +#include "connections.h" + + +#include <stdio.h> +#include <arpa/inet.h> +#include <sys/time.h> + +unsigned char in_buffer[INBUF_SIZE]; +unsigned char out_buffer[OUTBUF_SIZE]; + +int in_curr; +int out_curr; +int in_nbytes; +struct timeval tv; +fd_set fdset; +int smewsId; +int socket_fd; +struct sockaddr_in sockaddr; +static int ret; + +/*-----------------------------------------------------------------------------------*/ +static void check(int test,const char *message) { + if(!test) { + perror(message); + exit(1); + } +} + +/*-----------------------------------------------------------------------------------*/ +uint32_t get_time(void) { + struct timeval stime; + ret = gettimeofday(&stime, (struct timezone*)0); + check(ret != -1,"gettimeofday() error"); + return stime.tv_sec * 1000 + stime.tv_usec / 1000; +} + +/*-----------------------------------------------------------------------------------*/ +void dev_init(void) { + /* get ID from environ */ + if(getenv("SMEWS_ID")) + smewsId = atoi(getenv("SMEWS_ID")); + else + smewsId = 0; + + /* set IP address */ + local_ip_addr[3] = 192; + local_ip_addr[2] = 168; + local_ip_addr[1] = 1 + (smewsId >> 8); + local_ip_addr[0] = smewsId % 0xff; + + /* create socket */ + socket_fd = socket(AF_INET,SOCK_DGRAM,0); + check(socket_fd != -1,"socket() error"); + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(1024 + 1 + smewsId); + sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + memset(&sockaddr.sin_zero,0,8); + ret = bind(socket_fd,(struct sockaddr*)&sockaddr,sizeof(sockaddr)); + check(ret != -1,"bind() error"); + + /* set sockaddr for output */ + sockaddr.sin_port = htons(1024); + + /* initialize fdset */ + FD_ZERO(&fdset); + + /* do a first void output */ + dev_output_done(); +} + +/*-----------------------------------------------------------------------------------*/ +void wait_input() { + tv.tv_sec = 0; + tv.tv_usec = 50000; + FD_SET(socket_fd, &fdset); + ret = select(socket_fd + 1, &fdset, NULL, NULL, &tv); + check(ret != -1,"select() error"); +} + + +/*-----------------------------------------------------------------------------------*/ +unsigned char dev_data_to_read() { + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_SET(socket_fd, &fdset); + ret = select(socket_fd + 1, &fdset, NULL, NULL, &tv); + check(ret != -1,"select() error"); + return ret; +} + +/*-----------------------------------------------------------------------------------*/ +int16_t dev_get(void) { + unsigned char c; + if(in_curr >= in_nbytes - 1) { + int ret; + tv.tv_sec = 0; + tv.tv_usec = 100000; + FD_SET(socket_fd, &fdset); + ret = select(socket_fd + 1, &fdset, NULL, NULL, &tv); + check(ret != -1,"select() error"); + if(ret == 0) { + return -1; + } else { + ret = recv(socket_fd,in_buffer,INBUF_SIZE,0); + if(ret == -1) { + return -1; + } else { + in_nbytes = ret; + in_curr = -1; + c = in_buffer[++in_curr]; + } + } + } else { + c = in_buffer[++in_curr]; + } + return c; +} + +/*-----------------------------------------------------------------------------------*/ +void dev_prepare_output() { + out_curr=0; +} + +/*-----------------------------------------------------------------------------------*/ +void dev_output_done(void) { + ret = sendto(socket_fd,out_buffer,out_curr,0,(struct sockaddr*)&sockaddr,sizeof(sockaddr)); + check(ret != -1,"sendto() error"); +} diff --git a/targets/linuxUdp/drivers/target.h b/targets/linuxUdp/drivers/target.h new file mode 100644 index 0000000000000000000000000000000000000000..51b623d6ba19fcc84b574b7486cd8547ee539b2a --- /dev/null +++ b/targets/linuxUdp/drivers/target.h @@ -0,0 +1,145 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __TARGET_H__ +#define __TARGET_H__ + +#include <stdint.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/select.h> + +/* Network drivers */ + +extern void dev_init(void); +extern uint32_t get_time(void); +extern void dev_init(void); +extern int16_t dev_get(void); +extern unsigned char dev_data_to_read(); +extern void dev_prepare_output(); +extern void dev_output_done(void); +extern void wait_input(void); + +#define INBUF_SIZE 2048 +#define OUTBUF_SIZE 2048 + +extern unsigned char in_buffer[INBUF_SIZE]; +extern unsigned char out_buffer[OUTBUF_SIZE]; + +extern int pipe_r; +extern int in_curr; +extern int out_curr; +extern int in_nbytes; +extern struct timeval tv; +extern fd_set fdset; + +/* Drivers interface */ + +#define DEV_MTU 1500 +#define HARDWARE_INIT dev_init() +#define HARDWARE_STOP + +#define TIME_MILLIS get_time() +#define DEV_GET(c) {(c)=dev_get();} +#define DEV_PUT(c) {out_buffer[out_curr++]=(c);} +#define DEV_PUTN(ptr,n) {memcpy(out_buffer + out_curr,ptr,n); out_curr+=n;} +#define DEV_PUTN_CONST(ptr,n) {memcpy(out_buffer + out_curr,ptr,n); out_curr+=n;} +#define DEV_PREPARE_OUTPUT(length) dev_prepare_output() +#define DEV_OUTPUT_DONE dev_output_done() +#define DEV_DATA_TO_READ dev_data_to_read() +#define DEV_WAIT {wait_input();} + +/* Smews states */ + +#define SMEWS_WAITING +#define SMEWS_RECEIVING +#define SMEWS_SENDING +#define SMEWS_ENDING + +/* Const and persistent access macros */ + +#define CONST_VOID_P_VAR const void * +#define CONST_VAR(type,name) type const name +#define PERSISTENT_VAR(type,name) type name + +#define CONST_READ_UI8(x) ((uint8_t)*((uint8_t*)(x))) +#define CONST_READ_UI16(x) ((uint16_t)*((uint16_t*)(x))) +#define CONST_READ_UI32(x) ((uint32_t)*((uint32_t*)(x))) +#define CONST_READ_ADDR(x) ((void*)*((void**)(x))) + +#define CONST_UI8(x) ((uint8_t)(x)) +#define CONST_UI16(x) ((uint16_t)(x)) +#define CONST_UI32(x) ((uint32_t)(x)) +#define CONST_ADDR(x) ((void*)(x)) + +#define CONST_WRITE_NBYTES(dst,src,len) memcpy(dst,src,len) + +/* Endianness */ +#define ENDIANNESS LITTLE_ENDIAN + +/* Context switching */ + +#define USE_FRAME_POINTER + +#define BACKUP_CTX(sp) \ + asm ("movl %%esp, %0" : "=r"((sp)[0])); \ + asm ("movl %%ebp, %0" : "=r"((sp)[1])); \ + +#define RESTORE_CTX(sp) \ + asm ("movl %0, %%esp" :: "r"((sp)[0])); \ + asm ("movl %0, %%ebp" :: "r"((sp)[1])); \ + + +#define PUSHREGS asm( \ + "pushl %edi\n" \ + "pushl %esi\n" \ + "pushl %ebx\n" \ +); \ + +#define POPREGS asm( \ + "popl %ebx\n" \ + "popl %esi\n" \ + "popl %edi\n" \ +); \ + +/* Smews configuration */ + +#define OUTPUT_BUFFER_SIZE 256 +#define STACK_SIZE 4*1024 +#define ALLOC_SIZE 64*1024 + +#endif /* __TARGET_H__ */ diff --git a/targets/skeleton/SConscript b/targets/skeleton/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..c1082e0e930955aaecfb6b6e6afeaa187b7f75f6 --- /dev/null +++ b/targets/skeleton/SConscript @@ -0,0 +1,43 @@ +# Copyright or c or Copr. 2008, Simon Duquennoy +# +# Author e-mail: simon.duquennoy@lifl.fr +# +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + + +import os +import sys + +Import('env binDir projectName elfName') + +env.Replace(CC = 'gcc') +env.Replace(AS = 'as') +env.Replace(AR = 'ar') +env.Replace(RANLIB = 'ranlib') diff --git a/targets/skeleton/drivers/target.h b/targets/skeleton/drivers/target.h new file mode 100644 index 0000000000000000000000000000000000000000..ccbdf3ea6acf7545163bdba17c8c5188a14663a4 --- /dev/null +++ b/targets/skeleton/drivers/target.h @@ -0,0 +1,150 @@ +/* +* Copyright or © or Copr. 2008, Simon Duquennoy +* +* Author e-mail: simon.duquennoy@lifl.fr +* +* This software is a computer program whose purpose is to design an +* efficient Web server for very-constrained embedded system. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +*/ + +#ifndef __TARGET_H__ +#define __TARGET_H__ + +/* Other c and h target-specific files must be located in the drivers directory */ + +/* Types definition */ + +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef char int8_t; + +/* Target specific includes */ + +/* Smews includes */ + + + +/* Drivers interface */ + +/* Set the maximal MTU for the network interface used */ +#define DEV_MTU 1500 +/* Initializes the hardware */ +#define HARDWARE_INIT +/* Stops the hardware */ +#define HARDWARE_STOP +/* Returns the time in milliseconds */ +#define TIME_MILLIS 0 +/* Return 1 if data can be read */ +#define DEV_DATA_TO_READ 0 +/* Reads one byte */ +#define DEV_GET(c) {(c) = 0;} +/* Writes one byte */ +#define DEV_PUT(c) +/* Preparation for sending n bytes */ +#define DEV_PREPARE_OUTPUT(n) +/* End of output */ +#define DEV_OUTPUT_DONE + +/* Optionnal Smews macros */ + +/* Writes n bytes starting from ptr */ +#define DEV_PUTN(ptr,n) +/* Writes n bytes starting from ptr (for const data) */ +#define DEV_PUTN_CONST(ptr,n) +/* Passive wait for a device input. Must return after a given time */ +#define DEV_WAIT + +/* Smews states */ + +/* Called by the kernel when starting to wait for data */ +#define SMEWS_WAITING +/* Called by the kernel when starting to receive data */ +#define SMEWS_RECEIVING +/* Called by the kernel when starting to send data */ +#define SMEWS_SENDING +/* Called by the kernel when ending to send data */ +#define SMEWS_ENDING + +/* Cons variables macros */ + +/* Used to declare a reference to a const */ +#define CONST_VOID_P_VAR const void * +/* used to declare a variable as const */ +#define CONST_VAR(type,name) type const name +#define PERSISTENT_VAR(type,name) type name + +/* Gets a byte from address x */ +#define CONST_READ_UI8(x) ((uint8_t)*((uint8_t*)(x))) +/* Gets two bytes from address x */ +#define CONST_READ_UI16(x) ((uint16_t)*((uint16_t*)(x))) +/* Gets four bytes from address x */ +#define CONST_READ_UI32(x) ((uint32_t)*((uint32_t*)(x))) +/* Gets an address from address x */ +#define CONST_READ_ADDR(x) ((void*)*((void**)(x))) + +/* Get the value of x, where x is declared as a one byte const */ +#define CONST_UI8(x) ((uint8_t)(x)) +/* Get the value of x, where x is declared as a two bytes const */ +#define CONST_UI16(x) ((uint16_t)(x)) +/* Get the value of x, where x is declared as a four bytes const */ +#define CONST_UI32(x) ((uint32_t)(x)) +/* Get the value of x, where x is declared as a const reference */ +#define CONST_ADDR(x) ((void*)(x)) +/* Writes len bytes from src to dst, where dst targets a persistent variable */ +#define CONST_WRITE_NBYTES(dst,src,len) + +/* Endianness: define ENDIANNESS as LITTLE_ENDIAN or BIG_ENDIAN */ +#ifndef ENDIANNESS + #define ENDIANNESS LITTLE_ENDIAN +#endif + +/* Context switching */ + +/* save the stack pointer in sp[0] (and possibly a frame pointer in sp[1]) */ +#define BACKUP_CTX(sp) +/* restore the stack pointer from sp[0] (and possibly a frame pointer from sp[1]) */ +#define RESTORE_CTX(sp) +/* push all registers that must not be modified by any function call */ +#define PUSHREGS +/* pop all registers that must not be modified by any function call */ +#define POPREGS + +/* Smews configuration */ + +/* size of the buffer used to generate dynamic content */ +#define OUTPUT_BUFFER_SIZE 256 +/* size of the shared stack used by all dynamic content generators */ +#define STACK_SIZE 64 +/* size of the dynamic memory allocator pool */ +#define ALLOC_SIZE 2048 + +#endif /* __TARGET_H__ */ diff --git a/tools/GenApps.py b/tools/GenApps.py new file mode 100755 index 0000000000000000000000000000000000000000..20b832046ed54a9b2dbce04523ef074686ecd036 --- /dev/null +++ b/tools/GenApps.py @@ -0,0 +1,544 @@ +# -*- coding: utf-8 -*- +# Copyright or c or Copr. 2008, Simon Duquennoy +# +# Author e-mail: simon.duquennoy@lifl.fr +# +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + +import xml.parsers.expat +import GenBlob +import os +import gzip +import StringIO +import glob +import shutil +import time +import datetime + +# initialization +propertiesInfos = None +handlerInfos = {} +argsList = [] +chuncksSize = 0 +cOutName = 'pages.c' +mimeListFileName = os.path.join('tools','mimeList') +mimeHash = {} +StaticResource, DynamicResource = range(2) +argsTypesMap = {'str': 'arg_str', +'uint8' : 'arg_ui8', +'uint16' : 'arg_ui16', +'uint32' : 'arg_ui32' +} + +# process the Mime file +for line in open(mimeListFileName,'r'): + split = line.split() + if len(split) == 2: + mimeHash[split[0]]=split[1] + +# get Mime type from a file extension +def getMime(hash,ext): + lowExt = ext.lower() + if hash.has_key(lowExt): + return hash[lowExt] + else: + return 'text/plain' + +# write files header +def writeHeader(file,enriched): + if enriched == 0: + tmp = 'generated' + else: + tmp = 'enriched' + file.write('/*\n') + file.write('* This file has been ' + tmp + ' by GenApps, a tool of the smews project\n') + file.write('* smews home page: http://www2.lifl.fr/~duquenno/Research/smews\n') + t = datetime.datetime.now() + t = time.mktime(t.timetuple()) + file.write('* Generation date: ' + str(datetime.datetime.utcfromtimestamp(t).ctime()) + '\n') + file.write('*/\n\n') + +# replaces dot and file separators by underscores +def getCName(fileName): + return fileName.replace('.','_').replace(os.sep,'_') + +# returns the name of the generated file for file fileName +def getFileName(fileName,chuncksNBits,gzipped): + if getResourceType(fileName) == DynamicResource: + fileName = fileName[0:fileName.rfind('.')] + else: + prefix = ('g' if gzipped else 'r') + '_' + prefix += 'c' + str(chuncksNBits) + '_' + fileName = os.path.join(os.path.dirname(fileName),prefix + os.path.basename(fileName)) + if fileName.endswith('.embed'): + fileName = fileName[:fileName.rfind('.')] + return fileName.replace('.','_') + +# used by getAppFiles +def getAppFilesRec(appPath,path): + files=[] + for file in glob.glob(path + '/*'): + if os.path.basename(file) != 'SConscript': + if os.path.isdir(file): + files = files + (getAppFilesRec(appPath,file)) + elif not file.endswith('~'): + files.append(file[len(appPath)+1:]) + return files + +# returns all files contained in path (with recurssion) +def getAppFiles(path): + return getAppFilesRec(path,path) + +# Web resource type from original applicative file +def getResourceType(path): + if path.endswith('.c') or path.endswith('.h'): + return DynamicResource + else: + return StaticResource + +# extracts c file properties from its xml data +# returns the file data +def extractPropsFromXml(srcFile,dstFileInfos): + # open the source file in order to parse the XML and return the file data + file = open(srcFile,'r') + lines = file.readlines() + if len(lines) > 1: + fileData = reduce(lambda x,y: x + y,lines) + else: + fileData = '' + # prcoess XML only if dstFilInfos do not already contains informations + if not dstFileInfos.has_key('hasXml'): + # 3 XML handler functions + def start_element(name, attrs): + global argsList + global handlerInfos + global propertiesInfos + if name == 'args': + argsList = [] + elif name == 'arg': + argsList.append(attrs) + elif name == 'handlers': + handlerInfos = attrs + elif name == 'properties': + propertiesInfos = attrs + + def end_element(name): + return + def char_data(data): + return + + # select the XML part of the c file + xmlRoot = 'generator' + xmlData = fileData[fileData.rfind('<' + xmlRoot + '>'):] + xmlData = xmlData[:xmlData.rfind('</' + xmlRoot + '>') + len(xmlRoot) + 3] + + # default value for the generator properties + dstFileInfos['persistence'] = 'persistent' + dstFileInfos['interaction'] = 'rest' + dstFileInfos['channel'] = '' + # XML data have been found + if len(xmlData) > 1: + global argsList + global handlerInfos + global propertiesInfos + + # init globals used for parsing + propertiesInfos = None + handlerInfos = {} + argsList = [] + + # parse the XML + p = xml.parsers.expat.ParserCreate() + p.StartElementHandler = start_element + p.EndElementHandler = end_element + p.CharacterDataHandler = char_data + p.Parse(xmlData, 0) + + # doGet handler + if handlerInfos == None or not handlerInfos.has_key('doGet'): + exit('Error: the file ' + srcFile + ' does not describe a doGet handler') + dstFileInfos['doGet'] = handlerInfos['doGet'] + # init handler + if handlerInfos.has_key('init'): + dstFileInfos['init'] = handlerInfos['init'] + # initGet handler + if handlerInfos.has_key('initGet'): + dstFileInfos['initGet'] = handlerInfos['initGet'] + # generator arguments + dstFileInfos['argsList'] = argsList + if propertiesInfos != None: + # generator persistence + if propertiesInfos.has_key('persistence'): + dstFileInfos['persistence'] = propertiesInfos['persistence'] + # generator interaction mode + # generator channel name + if propertiesInfos.has_key('channel'): + dstFileInfos['channel'] = propertiesInfos['channel'] + dstFileInfos['interaction'] = 'alert' # default mode when a channel is set + if propertiesInfos.has_key('interaction'): + dstFileInfos['interaction'] = propertiesInfos['interaction'] + if(dstFileInfos['channel'] == ''): + defaultChannel = os.path.basename(srcFile) + defaultChannel = defaultChannel[:defaultChannel.rfind('.c')] + defaultChannel = getCName(defaultChannel) + dstFileInfos['channel'] = defaultChannel + + # boolean used to know if the c file contains XML data + dstFileInfos['hasXml'] = len(xmlData) > 1 + return fileData + +# generates the .props file for a c file +# the .props file contains a subset of the information described in generators XMLs +# all information used to build the file-index.c file or the channel.h file MUST be included in the props file +def generateResourceProps(srcFile,dstFileInfos): + # extract the properties from the XML (if needed) + extractPropsFromXml(srcFile,dstFileInfos) + # store the hasXml flag and the comet channel + pOut = open(dstFileInfos['fileName'],'w') + pOut.write('1\n' if dstFileInfos['hasXml'] else '0\n') + pOut.write(dstFileInfos['channel'] + '\n') + pOut.close() + +# launches a Web applicative resource file generation +def generateResource(srcFile,dstFile,chuncksNbits,gzipped,dstFileInfos): + if getResourceType(srcFile) == DynamicResource: + generateDynamicResource(srcFile,dstFile,dstFileInfos) + else: + generateStaticResource(srcFile,dstFile,chuncksNbits,gzipped) + +# dynamic resources: the generator file is enriched +def generateDynamicResource(srcFile,dstFile,dstFileInfos): + # extract the properties from the XML (if needed) + fileData = extractPropsFromXml(srcFile,dstFileInfos) + # if the c/h file does not conatin any XML, we simply copy it: this is not a generator + if not dstFileInfos['hasXml']: + shutil.copyfile(srcFile,dstFile) + # here, the c file is a generator. It will be enriched + else: + cFuncName = getCName(srcFile[:srcFile.rfind('.c')]) + + generatedHeader = '#include "generators.h"\n' + generatedHeader += '#include "stddef.h"\n\n' + + generatedOutputHandler = '/********** Output handler **********/\n' + # handler functions declaration + if dstFileInfos.has_key('init'): + generatedOutputHandler += 'static generator_init_func_t ' + dstFileInfos['init'] + ';\n' + if dstFileInfos.has_key('initGet'): + generatedOutputHandler += 'static generator_initget_func_t ' + dstFileInfos['initGet'] + ';\n' + generatedOutputHandler += 'static generator_doget_func_t ' + dstFileInfos['doGet'] + ';\n' + # output_handler structure creation + generatedOutputHandler += 'CONST_VAR(struct output_handler_t, ' + cFuncName + ') = {\n' + # handler type + generatedOutputHandler += '\t.handler_type = type_generator,\n' + generatedOutputHandler += '\t.handler_comet = %d,\n' %(1 if dstFileInfos['channel'] != '' else 0) + generatedOutputHandler += '\t.handler_stream = %d,\n' %(1 if dstFileInfos['interaction'] == 'streaming' else 0) + if dstFileInfos['persistence'] == 'persistent': + etype = 'prop_persistent' + elif dstFileInfos['persistence'] == 'idempotent': + etype = 'prop_idempotent' + elif dstFileInfos['persistence'] == 'volatile': + etype = 'prop_volatile' + if etype == None: + etype = 'prop_persistent' + # the handler is a dynamic resource (generator), we fill the function handlers fields + generatedOutputHandler += '\t.handler_data = {\n' + generatedOutputHandler += '\t\t.generator = {\n' + generatedOutputHandler += '\t\t\t.prop = %s,\n' %etype + # init + if not dstFileInfos.has_key('init'): + generatedOutputHandler += '\t\t\t.init = NULL,\n' + else: + generatedOutputHandler += '\t\t\t.init = ' + dstFileInfos['init'] + ',\n' + # initGet + if dstFileInfos.has_key('initGet'): + generatedOutputHandler += '\t\t\t.initget = ' + dstFileInfos['initGet'] + ',\n' + # doGet + generatedOutputHandler += '\t\t\t.doget = ' + dstFileInfos['doGet'] + ',\n' + generatedOutputHandler += '\t\t}\n' + generatedOutputHandler += '\t},\n' + # generator arguments information are also written in the structure + generatedOutputHandler += '#ifndef DISABLE_ARGS\n' + generatedOutputHandler += '\t.handler_args = {\n' + if len(dstFileInfos['argsList']) > 0: + generatedOutputHandler += '\t\t.args_tree = args_tree,\n' + generatedOutputHandler += '\t\t.args_index = args_index,\n' + generatedOutputHandler += '\t\t.args_size = sizeof(struct args_t)\n' + else: + generatedOutputHandler += '\t\t.args_tree = NULL,\n' + generatedOutputHandler += '\t\t.args_index = NULL,\n' + generatedOutputHandler += '\t\t.args_size = 0\n' + generatedOutputHandler += '\t}\n' + generatedOutputHandler += '#endif\n' + generatedOutputHandler += '};\n' + + # arguments c structure creation (this structure is directly used by the generator functions) + generatedArgsStruc = '/********** Arguments structure **********/\n' + generatedArgsStruc += 'struct args_t {\n' + # for each argument, create a filed in the structure + for attrs in dstFileInfos['argsList']: + tmpString = '' + if attrs['type'] == 'str': + tmpString = 'char ' + attrs['name'] + '[' + attrs['size'] + ']' + else: + tmpString = attrs['type'] + '_t ' + attrs['name'] + generatedArgsStruc += '\t' + tmpString + ';\n' + generatedArgsStruc += '};\n' + + # arguments index creation + generatedIndex = '/********** Arguments index **********/\n' + generatedIndex += 'static CONST_VAR(struct arg_ref_t, args_index[]) = {\n' + # for each argument, type and size informations + # the offset (in bytes in the structure) is also provided + for attrs in dstFileInfos['argsList']: + tmpType = '' + if attrs['type'] == 'str': + tmpType = 'char[' + attrs['size'] + ']' + else: + tmpType = attrs['type'] + '_t' + generatedIndex += '\t{arg_type: ' + argsTypesMap[attrs['type']] + ', arg_size: sizeof(' + tmpType + '), arg_offset: offsetof(struct args_t,' + attrs['name'] + ')},\n' + generatedIndex += '};\n' + + # new c file creation + cOut = open(dstFile,'w') + writeHeader(cOut,1) + cOut.write(generatedHeader) + if len(dstFileInfos['argsList']) > 0: + cOut.write('#ifndef DISABLE_ARGS\n') + cOut.write(generatedArgsStruc) + cOut.write('\n') + cOut.write(generatedIndex) + GenBlob.genBlobTree(cOut,map(lambda x: x['name'],dstFileInfos['argsList']),'args_tree',True) + cOut.write('#endif\n') + cOut.write('\n') + cOut.write(generatedOutputHandler) + # the end of the file contains the original c file + cOut.write('\n/* End of the enriched part */\n\n') + cOut.write(fileData) + cOut.close() + +# static file: the file is completely pre-processed into a c file: +# HTTP header insertion +# chuncks checksums calculation +def generateStaticResource(srcFile,dstFile,chuncksNbits,gzipped): + # HTTP header generation and concatenation with file data + try: + # open the source file + file = open(srcFile,'rb') + lines = file.readlines() + if len(lines) != 0: + fileData = reduce(lambda x,y: x + y,lines) + else: + fileData = '' + if gzipped: + # the whole file is gzipped + sio = StringIO.StringIO() + gzipper = gzip.GzipFile(mode="wb", fileobj=sio, compresslevel=9) + gzipper.write(fileData) + gzipper.close() + fileData = sio.getvalue() + # HTTP header insertion before the file data + tmp = str(len(fileData)) + '\r\nServer: Smews\r\nContent-Type: ' + getMime(mimeHash,srcFile[srcFile.rfind('.')+1:]) + if gzipped: + tmp += '\r\nContent-Encoding: gzip' + #~ headerPadding = 205 + #~ if headerPadding > 4: + #~ tmp += '\r\na:' + #~ for i in range(headerPadding-4): + #~ tmp += '0' + tmp += '\r\nConnection: Keep-Alive\r\n\r\n' + fileData + fileData = tmp + if os.path.basename(srcFile) == '404.html': + fileData = 'HTTP/1.1 404 Not Found\r\nContent-Length: ' + fileData + else: + fileData = 'HTTP/1.1 200 OK\r\nContent-Length: ' + fileData + + except IOError: + fileData = ('HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n') + + # TCP chuncks checksums precalculationon the file data (HTTP header included) + chkSum = 0 + chkSumList = [] + chuncksSize = 2 ** chuncksNbits + for i in range(len(fileData)): + if i % 2 == 0: + chkSum += ord(fileData[i]) << 8 + else: + chkSum += ord(fileData[i]) + if (i % chuncksSize == chuncksSize - 1) | (i == len(fileData)-1): + while chkSum & 0xffff0000: + chkSum = (chkSum & 0xffff) + (chkSum >> 16); + chkSumList += [chkSum] + chkSum = 0 + + # destination c file creation + cOut = open(dstFile,'w') + writeHeader(cOut,0) + + # inclusions + cOut.write('#include "handlers.h"\n') + + # data structures declaration + cName = getCName(srcFile) + cOut.write('\n/********** File ' + srcFile + ' **********/\n') + cOut.write('const uint16_t chk_' + cName + '[] /*CONST_VAR*/;\n') + cOut.write('const unsigned char data_' + cName + '[] /*CONST_VAR*/;\n') + + # we fill the output handler structure + cOut.write('\n/********** File handler **********/\n') + cOut.write('CONST_VAR(struct output_handler_t, ' + cName + '_handler) = {\n') + cOut.write('\t.handler_type = type_file,\n' + + '\t.handler_data = {\n' + + '\t\t.file = {\n' + + '\t\t\t.length = ' + str(len(fileData)) + ',\n' + + '\t\t\t.chk = chk_' + cName + ',\n' + + '\t\t\t.data = data_' + cName + '\n' + + '\t\t}\n' + + '\t},\n') + cOut.write('};\n') + + # chuncks checksums data generation + cOut.write('\n/********** Chuncks checksums **********/\n') + cOut.write('CONST_VAR(uint16_t, chk_' + cName + '[]) = {\n') + cOut.write(reduce(lambda x,y: x + "," + y,map(lambda x: hex(x),chkSumList))) + cOut.write('};') + + # file data generation + cOut.write('\n') + cOut.write('\n/********** File data **********/\n') + cOut.write('CONST_VAR(unsigned char, data_' + cName + '[]) = {\n') + cOut.write(reduce(lambda x,y: x + "," + y,map(lambda x: hex(ord(x)),fileData))) + cOut.write('};\n') + + cOut.close() + +# channels h file generation. This file contains channel declarations +def generateChannelsH(dstFile,propsFilesMap): + # extract XML properties of each file (if needed) + for fileName in propsFilesMap.keys(): + extractPropsFromXml(fileName,propsFilesMap[fileName]) + # h file creation + hOut = open(dstFile,'w') + writeHeader(hOut,0) + hOut.write('#ifndef __CHANNELS_H__\n') + hOut.write('#define __CHANNELS_H__\n\n') + for fileName in propsFilesMap.keys(): + # for each channel: external structure declaration, macro for the channel name + if propsFilesMap[fileName]['channel'] != '': + cStructName = getCName(fileName[:fileName.rfind('.c')]) + hOut.write('extern CONST_VAR(struct output_handler_t, ' + cStructName + ');\n') + hOut.write('#define ' + propsFilesMap[fileName]['channel'] + ' ' + cStructName + '\n') + hOut.write('\n#endif\n') + hOut.close() + +# file index c file generatin +# the file index file links URLs to output_handler struct, thanks to an URL tree +# the URL tree is generated using genBlob.py scripts +def generateIndex(dstDir,sourcesMap,target,chuncksNbits,appBase,propsFilesMap): + # files selection, static files and geenrators separation + filesNames = sourcesMap.keys() + staticFilesNames = filter(lambda x: getResourceType(x) == StaticResource,filesNames) + generatorFilesNames = filter(lambda x: getResourceType(x) == DynamicResource,filesNames) + # extract XML information for each generetor file (if needed) + for fileName in generatorFilesNames: + if not propsFilesMap[fileName].has_key('hasXml'): + extractPropsFromXml(fileName,propsFilesMap[fileName]) + # remove c files that do not contain any XML: they are not generators + generatorFilesNames = filter(lambda x: propsFilesMap[x]['hasXml'],generatorFilesNames) + + # c file creation + cOut = open(target,'w') + writeHeader(cOut,0) + + cOut.write('#include "handlers.h"\n') + + # external handler references + cOut.write('\n/********** External references **********/\n') + for fileName in staticFilesNames: + cName = getCName(fileName) + cOut.write('extern CONST_VAR(struct output_handler_t, ' + cName + '_handler);\n') + for fileName in generatorFilesNames: + cFuncName = getCName(fileName[:fileName.rfind('.c')]) + cOut.write('extern const struct output_handler_t ' + cFuncName + ';\n') + + # filesRef is a map used to associate URLs to output_handlers + filesRefs = {} + # static files + for fileName in set(staticFilesNames): + # retrieve the output_handler for this file + handlerName = getCName(fileName) + '_handler' + # retrive the URL for this file + fileName = sourcesMap[fileName] + # .embed extensions are deleted + if fileName.endswith('.embed'): + fileName = fileName[:fileName.rfind('.')] + # URLs always use '/' as file separator + if os.sep == '\\': + fileName = fileName.replace('\\','/') + # update filesRef + filesRefs[fileName] = handlerName + # the case of index.hmtl files + if os.path.basename(fileName) == 'index.html': + fileName = os.path.dirname(fileName) + if fileName != os.sep: + fileName = fileName + '/' + filesRefs[fileName] = handlerName + # generator + for fileName in set(generatorFilesNames): + # retrieve the output_handler for this file + handlerName = fileName[:fileName.rfind('.')] + handlerName = getCName(handlerName) + # retrive the URL for this file + fileName = sourcesMap[fileName] + # .c extension is deleted + fileName = fileName[:fileName.rfind('.c')] + # URLs always use '/' as file separator + if os.sep == '\\': + fileName = fileName.replace('\\','/') + #update filesRef + filesRefs[fileName] = handlerName + + # the ordered list of URLs + filesList = filesRefs.keys() + filesList.sort() + + # files index creation (table of ordered output_handlers) + cOut.write('\n/********** Files index **********/\n') + cOut.write('CONST_VAR(const struct output_handler_t /*CONST_VAR*/ *, resources_index[]) = {\n') + # insert each handler + for file in filesList: + cOut.write('\t&' + filesRefs[file] + ',\n') + # the final handler is NULL + cOut.write('\tNULL,\n') + cOut.write('};\n') + + # generate the URLs tree + GenBlob.genBlobTree(cOut,filesList,'urls_tree',False) + cOut.close() diff --git a/tools/GenBlob.py b/tools/GenBlob.py new file mode 100755 index 0000000000000000000000000000000000000000..484a75cfb5735be90546826d8e6d685d64dc2801 --- /dev/null +++ b/tools/GenBlob.py @@ -0,0 +1,245 @@ +# -*- coding: utf-8 -*- +# Copyright or c or Copr. 2008, Simon Duquennoy +# +# Author e-mail: simon.duquennoy@lifl.fr +# +# This software is a computer program whose purpose is to design an +# efficient Web server for very-constrained embedded system. +# +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + +import time +import datetime + +# treeToString +def treeToStringRec(node,indent): + string = indent + node['string'] + if node['final']: + string += '|END' + for i in range(len(node['string'])): + indent += '-' + for child in node['childs']: + string += '\n' + treeToStringRec(child,indent) + return string + +def treeToString(tree): + return treeToStringRec(tree,'* ')[1:] + +# tertiaryTreeToString +def tertiaryTreeToStringRec(node,indent,key): + string = indent + string += key + node['string'] + if node['final']: + string += '|END' + for i in range(len(node['string'])): + indent += '-' + for key in node['childs'].keys(): + string += '\n' + tertiaryTreeToStringRec(node['childs'][key],indent,key) + return string + +def tertiaryTreeToString(tree): + return tertiaryTreeToStringRec(tree,'* ','-') + +# buildTree +def buildTree(symbols,indexMap): + tree = {'string': '', 'childs': [], 'final': False, 'root': True} + currentRef = 0 + + for symbol in symbols: + childSet = tree['childs'] + for char in symbol: + for node in childSet: + if node['string'] == char: + childSet = node['childs'] + break + else: + newNode = {'string': char, 'childs': [], 'final': False} + childSet.append(newNode) + childSet = newNode['childs'] + newNode['final'] = True + newNode['ref'] = indexMap[currentRef] + currentRef += 1 + return tree + +# compactTree +def compactTreeRec(node,nBrothers): + for child in node['childs']: + compactTreeRec(child,len(node['childs'])-1) + if nBrothers == 0 and not node['final'] and len(node['childs']) == 1: + node['string'] += node['childs'][0]['string'] + node['final'] = node['childs'][0]['final'] + if node['final']: + node['ref'] = node['childs'][0]['ref'] + node['childs'] = node['childs'][0]['childs'] + +def compactTree(tree): + compactTreeRec(tree,0) + +# compactTernaryTree +def compactTernaryTree(node): + for key in node['childs'].keys(): + compactTernaryTree(node['childs'][key]) + #if not node['final'] and node['childs'].keys()==['='] and (node['childs']['=']['childs'].keys()==['='] or node['childs']['=']['final']): + if not node['final'] and node['childs'].keys()==['=']: + node['string'] += node['childs']['=']['string'] + node['final'] = node['childs']['=']['final'] + if node['final']: + node['ref'] = node['childs']['=']['ref'] + node['childs'] = node['childs']['=']['childs'] + +# toTernaryTree +def toTernaryTree(node): + if type(node['childs']) == list: + node['childs'] = {'=': node['childs']} + for key in node['childs'].keys(): + childs = node['childs'][key] + if len(childs) > 0: + centralIndex = len(childs) / 2 + infNodes = childs[:centralIndex] + centralNode = childs[centralIndex] + supNodes = childs[centralIndex+1:] + node['childs'][key] = centralNode + centralNode['childs'] = {'=': centralNode['childs'], '<': infNodes,'>': supNodes} + toTernaryTree(centralNode) + else: + del node['childs'][key] + +# understoodableBLOB +def understoodableBLOBRec(node,key): + offset = 0 + string = '' + if node['string'] != '': + string += ',"' + node['string'] + '"' + offset += len(node['string']) + if node['final']: + string += ',ref:' + str(node['ref']) + offset += 1 + childsList = [] + if node['childs'].has_key('<'): + childsList.append('<') + if node['childs'].has_key('='): + childsList.append('=') + if node['childs'].has_key('>'): + childsList.append('>') + flags = node['childs'].has_key('<') & 1 | ((node['childs'].has_key('=') & 1) << 1)| ((node['childs'].has_key('>') & 1) << 2) + returned = {} + flagsStr = '' + for key in childsList: + flagsStr += key + returned[key] = understoodableBLOBRec(node['childs'][key],key) + offset += returned[key]['offset'] + if flags != 2: + if flagsStr != '': + string += ',' + flagsStr + else: + string += ',0' + offset += 1 + for i in range(len(childsList)-1): + string += ',' + childsList[i+1] + ':' + str(returned[childsList[i]]['offset']) + offset += 1 + for key in childsList: + string += returned[key]['blob'] + return {'blob': string, 'offset': offset} + +def understoodableBLOB(tree): + ret = understoodableBLOBRec(tree,'|') + return {'string': ret['blob'][1:], 'length': ret['offset']} + +# BLOB +def BLOBRec(node,key): + offset = 0 + string = '' + for char in node['string']: + string += ',' + str(ord(char)) + offset += len(node['string']) + if node['final']: + string += ',' + str(128 + node['ref']) + offset += 1 + childsList = [] + if node['childs'].has_key('<'): + childsList.append('<') + if node['childs'].has_key('='): + childsList.append('=') + if node['childs'].has_key('>'): + childsList.append('>') + flags = node['childs'].has_key('<') & 1 | ((node['childs'].has_key('=') & 1) << 1)| ((node['childs'].has_key('>') & 1) << 2) + returned = {} + for key in childsList: + returned[key] = BLOBRec(node['childs'][key],key) + offset += returned[key]['offset'] + if flags != 2: + string += ',' + str(flags) + offset += 1 + for i in range(len(childsList)-1): + string += ',' + str(returned[childsList[i]]['offset']) + offset += 1 + for key in childsList: + string += returned[key]['blob'] + return {'blob': string, 'offset': offset} + +def BLOB(tree): + ret = BLOBRec(tree,'|') + return {'string': ret['blob'][1:], 'length': ret['offset']} + +# generate the smbols tree +def genBlobTree(cOut,symbols,blobName,isStatic): + sortedSymbols = symbols[:] + sortedSymbols.sort() + indexMap = {} + for i in range(len(symbols)): + indexMap[sortedSymbols.index(symbols[i])] = i + + symbolsSize = 0 + for symbol in symbols: + symbolsSize += len(symbol) + + cOut.write('\n/********** Symbols list, total length: ' + str(symbolsSize) + ' bytes **********/\n/*\n') + for symbol in symbols: + cOut.write('* ' + symbol + '\n') + cOut.write('*/\n\n') + + tree = buildTree(sortedSymbols,indexMap) + compactTree(tree) + treeString = treeToString(tree) + + cOut.write('/********** Generated Ternary Tree **********/\n/*\n') + toTernaryTree(tree) + compactTernaryTree(tree) + treeString = tertiaryTreeToString(tree) + cOut.write(treeString) + cOut.write('\n*/\n\n') + + blob = understoodableBLOB(tree) + cOut.write('/********** \"Understoodable\" Generated BLOB, total length: ' + str(blob['length']) + ' bytes **********/\n/*\n') + cOut.write('* ' + blob['string']) + cOut.write('\n*/\n\n') + + blob = BLOB(tree) + cOut.write('/********** Finally Generated BLOB, total length: ' + str(blob['length']) + ' bytes **********/\n') + if isStatic: + cOut.write('static ') + cOut.write('CONST_VAR(unsigned char, ' + blobName + '[]) = {' + blob['string'] + '};\n') diff --git a/tools/IPy.py b/tools/IPy.py new file mode 100644 index 0000000000000000000000000000000000000000..9fd80ece442c92fe14711bd30abfe6015499a7e3 --- /dev/null +++ b/tools/IPy.py @@ -0,0 +1,1304 @@ +""" +IPy - class and tools for handling of IPv4 and IPv6 addresses and networks. +See README file for learn how to use IPy. + +Further Information might be available at: +http://software.inl.fr/trac/trac.cgi/wiki/IPy +""" + +# $HeadURL: https://svn.inl.fr/inl-svn/src/tools/ipy/tags/IPy-0.70/IPy.py $ +# $Id: IPy.py 19309 2009-10-29 10:21:13Z haypo $ + +__rcsid__ = '$Id: IPy.py 19309 2009-10-29 10:21:13Z haypo $' +__version__ = '0.70' + +import types + +# Definition of the Ranges for IPv4 IPs +# this should include www.iana.org/assignments/ipv4-address-space +# and www.iana.org/assignments/multicast-addresses +IPv4ranges = { + '0': 'PUBLIC', # fall back + '00000000': 'PRIVATE', # 0/8 + '00001010': 'PRIVATE', # 10/8 + '01111111': 'PRIVATE', # 127.0/8 + '1': 'PUBLIC', # fall back + '1010100111111110': 'PRIVATE', # 169.254/16 + '101011000001': 'PRIVATE', # 172.16/12 + '1100000010101000': 'PRIVATE', # 192.168/16 + '11011111': 'RESERVED', # 223/8 + '111': 'RESERVED' # 224/3 + } + +# Definition of the Ranges for IPv6 IPs +# see also www.iana.org/assignments/ipv6-address-space, +# www.iana.org/assignments/ipv6-tla-assignments, +# www.iana.org/assignments/ipv6-multicast-addresses, +# www.iana.org/assignments/ipv6-anycast-addresses +IPv6ranges = { + '00000000' : 'RESERVED', # ::/8 + '00000001' : 'UNASSIGNED', # 100::/8 + '0000001' : 'NSAP', # 200::/7 + '0000010' : 'IPX', # 400::/7 + '0000011' : 'UNASSIGNED', # 600::/7 + '00001' : 'UNASSIGNED', # 800::/5 + '0001' : 'UNASSIGNED', # 1000::/4 + '0010000000000000' : 'RESERVED', # 2000::/16 Reserved + '0010000000000001' : 'ASSIGNABLE', # 2001::/16 Sub-TLA Assignments [RFC2450] + '00100000000000010000000': 'ASSIGNABLE IANA', # 2001:0000::/29 - 2001:01F8::/29 IANA + '00100000000000010000001': 'ASSIGNABLE APNIC', # 2001:0200::/29 - 2001:03F8::/29 APNIC + '00100000000000010000010': 'ASSIGNABLE ARIN', # 2001:0400::/29 - 2001:05F8::/29 ARIN + '00100000000000010000011': 'ASSIGNABLE RIPE', # 2001:0600::/29 - 2001:07F8::/29 RIPE NCC + '0010000000000010' : '6TO4', # 2002::/16 "6to4" [RFC3056] + '0011111111111110' : '6BONE', # 3FFE::/16 6bone Testing [RFC2471] + '0011111111111111' : 'RESERVED', # 3FFF::/16 Reserved + '010' : 'GLOBAL-UNICAST', # 4000::/3 + '011' : 'UNASSIGNED', # 6000::/3 + '100' : 'GEO-UNICAST', # 8000::/3 + '101' : 'UNASSIGNED', # A000::/3 + '110' : 'UNASSIGNED', # C000::/3 + '1110' : 'UNASSIGNED', # E000::/4 + '11110' : 'UNASSIGNED', # F000::/5 + '111110' : 'UNASSIGNED', # F800::/6 + '1111110' : 'UNASSIGNED', # FC00::/7 + '111111100' : 'UNASSIGNED', # FE00::/9 + '1111111010' : 'LINKLOCAL', # FE80::/10 + '1111111011' : 'SITELOCAL', # FEC0::/10 + '11111111' : 'MULTICAST', # FF00::/8 + '0' * 96 : 'IPV4COMP', # ::/96 + '0' * 80 + '1' * 16 : 'IPV4MAP', # ::FFFF:0:0/96 + '0' * 128 : 'UNSPECIFIED', # ::/128 + '0' * 127 + '1' : 'LOOPBACK' # ::1/128 + } + + +class IPint: + """Handling of IP addresses returning integers. + + Use class IP instead because some features are not implemented for + IPint.""" + + def __init__(self, data, ipversion=0, make_net=0): + """Create an instance of an IP object. + + Data can be a network specification or a single IP. IP + addresses can be specified in all forms understood by + parseAddress(). The size of a network can be specified as + + /prefixlen a.b.c.0/24 2001:658:22a:cafe::/64 + -lastIP a.b.c.0-a.b.c.255 2001:658:22a:cafe::-2001:658:22a:cafe:ffff:ffff:ffff:ffff + /decimal netmask a.b.c.d/255.255.255.0 not supported for IPv6 + + If no size specification is given a size of 1 address (/32 for + IPv4 and /128 for IPv6) is assumed. + + If make_net is True, an IP address will be transformed into the network + address by applying the specified netmask. + + >>> print IP('127.0.0.0/8') + 127.0.0.0/8 + >>> print IP('127.0.0.0/255.0.0.0') + 127.0.0.0/8 + >>> print IP('127.0.0.0-127.255.255.255') + 127.0.0.0/8 + >>> print IP('127.0.0.1/255.0.0.0', make_net=True) + 127.0.0.0/8 + + See module documentation for more examples. + """ + + # Print no Prefixlen for /32 and /128 + self.NoPrefixForSingleIp = 1 + + # Do we want prefix printed by default? see _printPrefix() + self.WantPrefixLen = None + + netbits = 0 + prefixlen = -1 + + # handling of non string values in constructor + if type(data) == types.IntType or type(data) == types.LongType: + self.ip = long(data) + if ipversion == 0: + if self.ip < 0x100000000L: + ipversion = 4 + else: + ipversion = 6 + if ipversion == 4: + prefixlen = 32 + elif ipversion == 6: + prefixlen = 128 + else: + raise ValueError, "only IPv4 and IPv6 supported" + self._ipversion = ipversion + self._prefixlen = prefixlen + # handle IP instance as an parameter + elif isinstance(data, IPint): + self._ipversion = data._ipversion + self._prefixlen = data._prefixlen + self.ip = data.ip + else: + # TODO: refactor me! + # splitting of a string into IP and prefixlen et. al. + x = data.split('-') + if len(x) == 2: + # a.b.c.0-a.b.c.255 specification ? + (ip, last) = x + (self.ip, parsedVersion) = parseAddress(ip) + if parsedVersion != 4: + raise ValueError, "first-last notation only allowed for IPv4" + (last, lastversion) = parseAddress(last) + if lastversion != 4: + raise ValueError, "last address should be IPv4, too" + if last < self.ip: + raise ValueError, "last address should be larger than first" + size = last - self.ip + netbits = _count1Bits(size) + # make sure the broadcast is the same as the last ip + # otherwise it will return /16 for something like: + # 192.168.0.0-192.168.191.255 + if IP('%s/%s' % (ip, 32-netbits)).broadcast().int() != last: + raise ValueError, \ + "the range %s is not on a network boundary." % data + elif len(x) == 1: + x = data.split('/') + # if no prefix is given use defaults + if len(x) == 1: + ip = x[0] + prefixlen = -1 + elif len(x) > 2: + raise ValueError, "only one '/' allowed in IP Address" + else: + (ip, prefixlen) = x + if prefixlen.find('.') != -1: + # check if the user might have used a netmask like + # a.b.c.d/255.255.255.0 + (netmask, vers) = parseAddress(prefixlen) + if vers != 4: + raise ValueError, "netmask must be IPv4" + prefixlen = _netmaskToPrefixlen(netmask) + elif len(x) > 2: + raise ValueError, "only one '-' allowed in IP Address" + else: + raise ValueError, "can't parse" + + (self.ip, parsedVersion) = parseAddress(ip) + if ipversion == 0: + ipversion = parsedVersion + if prefixlen == -1: + if ipversion == 4: + prefixlen = 32 - netbits + elif ipversion == 6: + prefixlen = 128 - netbits + else: + raise ValueError, "only IPv4 and IPv6 supported" + self._ipversion = ipversion + self._prefixlen = int(prefixlen) + + if make_net: + self.ip = self.ip & _prefixlenToNetmask(self._prefixlen, self._ipversion) + + if not _checkNetaddrWorksWithPrefixlen(self.ip, + self._prefixlen, self._ipversion): + raise ValueError, "%s has invalid prefix length (%s)" % (repr(self), self._prefixlen) + + def int(self): + """Return the first / base / network addess as an (long) integer. + + The same as IP[0]. + + >>> "%X" % IP('10.0.0.0/8').int() + 'A000000' + """ + return self.ip + + def version(self): + """Return the IP version of this Object. + + >>> IP('10.0.0.0/8').version() + 4 + >>> IP('::1').version() + 6 + """ + return self._ipversion + + def prefixlen(self): + """Returns Network Prefixlen. + + >>> IP('10.0.0.0/8').prefixlen() + 8 + """ + return self._prefixlen + + def net(self): + """ + Return the base (first) address of a network as an (long) integer. + """ + return self.int() + + def broadcast(self): + """ + Return the broadcast (last) address of a network as an (long) integer. + + The same as IP[-1].""" + return self.int() + self.len() - 1 + + def _printPrefix(self, want): + """Prints Prefixlen/Netmask. + + Not really. In fact it is our universal Netmask/Prefixlen printer. + This is considered an internal function. + + want == 0 / None don't return anything 1.2.3.0 + want == 1 /prefix 1.2.3.0/24 + want == 2 /netmask 1.2.3.0/255.255.255.0 + want == 3 -lastip 1.2.3.0-1.2.3.255 + """ + + if (self._ipversion == 4 and self._prefixlen == 32) or \ + (self._ipversion == 6 and self._prefixlen == 128): + if self.NoPrefixForSingleIp: + want = 0 + if want == None: + want = self.WantPrefixLen + if want == None: + want = 1 + if want: + if want == 2: + # this should work with IP and IPint + netmask = self.netmask() + if type(netmask) != types.IntType \ + and type(netmask) != types.LongType: + netmask = netmask.int() + return "/%s" % (intToIp(netmask, self._ipversion)) + elif want == 3: + return "-%s" % (intToIp(self.ip + self.len() - 1, self._ipversion)) + else: + # default + return "/%d" % (self._prefixlen) + else: + return '' + + # We have different flavours to convert to: + # strFullsize 127.0.0.1 2001:0658:022a:cafe:0200:c0ff:fe8d:08fa + # strNormal 127.0.0.1 2001:658:22a:cafe:200:c0ff:fe8d:08fa + # strCompressed 127.0.0.1 2001:658:22a:cafe::1 + # strHex 0x7F000001L 0x20010658022ACAFE0200C0FFFE8D08FA + # strDec 2130706433 42540616829182469433547974687817795834 + + def strBin(self, wantprefixlen = None): + """Return a string representation as a binary value. + + >>> print IP('127.0.0.1').strBin() + 01111111000000000000000000000001 + """ + + + if self._ipversion == 4: + bits = 32 + elif self._ipversion == 6: + bits = 128 + else: + raise ValueError, "only IPv4 and IPv6 supported" + + if self.WantPrefixLen == None and wantprefixlen == None: + wantprefixlen = 0 + ret = _intToBin(self.ip) + return '0' * (bits - len(ret)) + ret + self._printPrefix(wantprefixlen) + + def strCompressed(self, wantprefixlen = None): + """Return a string representation in compressed format using '::' Notation. + + >>> IP('127.0.0.1').strCompressed() + '127.0.0.1' + >>> IP('2001:0658:022a:cafe:0200::1').strCompressed() + '2001:658:22a:cafe:200::1' + >>> IP('ffff:ffff:ffff:ffff:ffff:f:f:fffc/127').strCompressed() + 'ffff:ffff:ffff:ffff:ffff:f:f:fffc/127' + """ + + if self.WantPrefixLen == None and wantprefixlen == None: + wantprefixlen = 1 + + if self._ipversion == 4: + return self.strFullsize(wantprefixlen) + else: + if self.ip >> 32 == 0xffff: + ipv4 = intToIp(self.ip & 0xffffffff, 4) + text = "::ffff:" + ipv4 + self._printPrefix(wantprefixlen) + return text + # find the longest sequence of '0' + hextets = [int(x, 16) for x in self.strFullsize(0).split(':')] + # every element of followingzeros will contain the number of zeros + # following the corresponding element of hextets + followingzeros = [0] * 8 + for i in range(len(hextets)): + followingzeros[i] = _countFollowingZeros(hextets[i:]) + # compressionpos is the position where we can start removing zeros + compressionpos = followingzeros.index(max(followingzeros)) + if max(followingzeros) > 1: + # genererate string with the longest number of zeros cut out + # now we need hextets as strings + hextets = [x for x in self.strNormal(0).split(':')] + while compressionpos < len(hextets) and hextets[compressionpos] == '0': + del(hextets[compressionpos]) + hextets.insert(compressionpos, '') + if compressionpos + 1 >= len(hextets): + hextets.append('') + if compressionpos == 0: + hextets = [''] + hextets + return ':'.join(hextets) + self._printPrefix(wantprefixlen) + else: + return self.strNormal(0) + self._printPrefix(wantprefixlen) + + def strNormal(self, wantprefixlen = None): + """Return a string representation in the usual format. + + >>> print IP('127.0.0.1').strNormal() + 127.0.0.1 + >>> print IP('2001:0658:022a:cafe:0200::1').strNormal() + 2001:658:22a:cafe:200:0:0:1 + """ + + if self.WantPrefixLen == None and wantprefixlen == None: + wantprefixlen = 1 + + if self._ipversion == 4: + ret = self.strFullsize(0) + elif self._ipversion == 6: + ret = ':'.join([hex(x)[2:] for x in [int(x, 16) for x in self.strFullsize(0).split(':')]]) + else: + raise ValueError, "only IPv4 and IPv6 supported" + + + + return ret + self._printPrefix(wantprefixlen) + + def strFullsize(self, wantprefixlen = None): + """Return a string representation in the non-mangled format. + + >>> print IP('127.0.0.1').strFullsize() + 127.0.0.1 + >>> print IP('2001:0658:022a:cafe:0200::1').strFullsize() + 2001:0658:022a:cafe:0200:0000:0000:0001 + """ + + if self.WantPrefixLen == None and wantprefixlen == None: + wantprefixlen = 1 + + return intToIp(self.ip, self._ipversion).lower() + self._printPrefix(wantprefixlen) + + def strHex(self, wantprefixlen = None): + """Return a string representation in hex format in lower case. + + >>> IP('127.0.0.1').strHex() + '0x7f000001' + >>> IP('2001:0658:022a:cafe:0200::1').strHex() + '0x20010658022acafe0200000000000001' + """ + + if self.WantPrefixLen == None and wantprefixlen == None: + wantprefixlen = 0 + + x = hex(self.ip) + if x[-1] == 'L': + x = x[:-1] + return x.lower() + self._printPrefix(wantprefixlen) + + def strDec(self, wantprefixlen = None): + """Return a string representation in decimal format. + + >>> print IP('127.0.0.1').strDec() + 2130706433 + >>> print IP('2001:0658:022a:cafe:0200::1').strDec() + 42540616829182469433547762482097946625 + """ + + if self.WantPrefixLen == None and wantprefixlen == None: + wantprefixlen = 0 + + x = str(self.ip) + if x[-1] == 'L': + x = x[:-1] + return x + self._printPrefix(wantprefixlen) + + def iptype(self): + """Return a description of the IP type ('PRIVATE', 'RESERVERD', etc). + + >>> print IP('127.0.0.1').iptype() + PRIVATE + >>> print IP('192.168.1.1').iptype() + PRIVATE + >>> print IP('195.185.1.2').iptype() + PUBLIC + >>> print IP('::1').iptype() + LOOPBACK + >>> print IP('2001:0658:022a:cafe:0200::1').iptype() + ASSIGNABLE RIPE + + The type information for IPv6 is out of sync with reality. + """ + + # this could be greatly improved + + if self._ipversion == 4: + iprange = IPv4ranges + elif self._ipversion == 6: + iprange = IPv6ranges + else: + raise ValueError, "only IPv4 and IPv6 supported" + + bits = self.strBin() + for i in range(len(bits), 0, -1): + if iprange.has_key(bits[:i]): + return iprange[bits[:i]] + return "unknown" + + + def netmask(self): + """Return netmask as an integer. + + >>> "%X" % IP('195.185.0.0/16').netmask().int() + 'FFFF0000' + """ + + # TODO: unify with prefixlenToNetmask? + if self._ipversion == 4: + locallen = 32 - self._prefixlen + elif self._ipversion == 6: + locallen = 128 - self._prefixlen + else: + raise ValueError, "only IPv4 and IPv6 supported" + + return ((2L ** self._prefixlen) - 1) << locallen + + + def strNetmask(self): + """Return netmask as an string. Mostly useful for IPv6. + + >>> print IP('195.185.0.0/16').strNetmask() + 255.255.0.0 + >>> print IP('2001:0658:022a:cafe::0/64').strNetmask() + /64 + """ + + # TODO: unify with prefixlenToNetmask? + if self._ipversion == 4: + locallen = 32 - self._prefixlen + return intToIp(((2L ** self._prefixlen) - 1) << locallen, 4) + elif self._ipversion == 6: + locallen = 128 - self._prefixlen + return "/%d" % self._prefixlen + else: + raise ValueError, "only IPv4 and IPv6 supported" + + def len(self): + """Return the length of a subnet. + + >>> print IP('195.185.1.0/28').len() + 16 + >>> print IP('195.185.1.0/24').len() + 256 + """ + + if self._ipversion == 4: + locallen = 32 - self._prefixlen + elif self._ipversion == 6: + locallen = 128 - self._prefixlen + else: + raise ValueError, "only IPv4 and IPv6 supported" + + return 2L ** locallen + + + def __nonzero__(self): + """All IPy objects should evaluate to true in boolean context. + Ordinarily they do, but if handling a default route expressed as + 0.0.0.0/0, the __len__() of the object becomes 0, which is used + as the boolean value of the object. + """ + return 1 + + + def __len__(self): + """Return the length of a subnet. + + Called to implement the built-in function len(). + It breaks with IPv6 Networks. Anybody knows how to fix this.""" + + # Python < 2.2 has this silly restriction which breaks IPv6 + # how about Python >= 2.2 ... ouch - it persists! + + return int(self.len()) + + + def __getitem__(self, key): + """Called to implement evaluation of self[key]. + + >>> ip=IP('127.0.0.0/30') + >>> for x in ip: + ... print repr(x) + ... + IP('127.0.0.0') + IP('127.0.0.1') + IP('127.0.0.2') + IP('127.0.0.3') + >>> ip[2] + IP('127.0.0.2') + >>> ip[-1] + IP('127.0.0.3') + """ + + if type(key) != types.IntType and type(key) != types.LongType: + raise TypeError + if key < 0: + if abs(key) <= self.len(): + key = self.len() - abs(key) + else: + raise IndexError + else: + if key >= self.len(): + raise IndexError + + return self.ip + long(key) + + + + def __contains__(self, item): + """Called to implement membership test operators. + + Should return true if item is in self, false otherwise. Item + can be other IP-objects, strings or ints. + + >>> IP('195.185.1.1').strHex() + '0xc3b90101' + >>> 0xC3B90101L in IP('195.185.1.0/24') + 1 + >>> '127.0.0.1' in IP('127.0.0.0/24') + 1 + >>> IP('127.0.0.0/24') in IP('127.0.0.0/25') + 0 + """ + + item = IP(item) + if item.ip >= self.ip and item.ip < self.ip + self.len() - item.len() + 1: + return 1 + else: + return 0 + + + def overlaps(self, item): + """Check if two IP address ranges overlap. + + Returns 0 if the two ranges don't overlap, 1 if the given + range overlaps at the end and -1 if it does at the beginning. + + >>> IP('192.168.0.0/23').overlaps('192.168.1.0/24') + 1 + >>> IP('192.168.0.0/23').overlaps('192.168.1.255') + 1 + >>> IP('192.168.0.0/23').overlaps('192.168.2.0') + 0 + >>> IP('192.168.1.0/24').overlaps('192.168.0.0/23') + -1 + """ + + item = IP(item) + if item.ip >= self.ip and item.ip < self.ip + self.len(): + return 1 + elif self.ip >= item.ip and self.ip < item.ip + item.len(): + return -1 + else: + return 0 + + + def __str__(self): + """Dispatch to the prefered String Representation. + + Used to implement str(IP).""" + + return self.strCompressed() + + + def __repr__(self): + """Print a representation of the Object. + + Used to implement repr(IP). Returns a string which evaluates + to an identical Object (without the wantprefixlen stuff - see + module docstring. + + >>> print repr(IP('10.0.0.0/24')) + IP('10.0.0.0/24') + """ + + return("IPint('%s')" % (self.strCompressed(1))) + + + def __cmp__(self, other): + """Called by comparison operations. + + Should return a negative integer if self < other, zero if self + == other, a positive integer if self > other. + + Networks with different prefixlen are considered non-equal. + Networks with the same prefixlen and differing addresses are + considered non equal but are compared by their base address + integer value to aid sorting of IP objects. + + The version of Objects is not put into consideration. + + >>> IP('10.0.0.0/24') > IP('10.0.0.0') + 1 + >>> IP('10.0.0.0/24') < IP('10.0.0.0') + 0 + >>> IP('10.0.0.0/24') < IP('12.0.0.0/24') + 1 + >>> IP('10.0.0.0/24') > IP('12.0.0.0/24') + 0 + + """ + + # Im not really sure if this is "the right thing to do" + if self._prefixlen < other.prefixlen(): + return (other.prefixlen() - self._prefixlen) + elif self._prefixlen > other.prefixlen(): + + # Fixed bySamuel Krempp <krempp@crans.ens-cachan.fr>: + + # The bug is quite obvious really (as 99% bugs are once + # spotted, isn't it ? ;-) Because of precedence of + # multiplication by -1 over the substraction, prefixlen + # differences were causing the __cmp__ function to always + # return positive numbers, thus the function was failing + # the basic assumptions for a __cmp__ function. + + # Namely we could have (a > b AND b > a), when the + # prefixlen of a and b are different. (eg let + # a=IP("1.0.0.0/24"); b=IP("2.0.0.0/16");) thus, anything + # could happen when launching a sort algorithm.. + # everything's in order with the trivial, attached patch. + + return (self._prefixlen - other.prefixlen()) * -1 + else: + if self.ip < other.ip: + return -1 + elif self.ip > other.ip: + return 1 + elif self._ipversion != other._ipversion: + # IP('0.0.0.0'), IP('::/0') + return cmp(self._ipversion, other._ipversion) + else: + return 0 + + + def __hash__(self): + """Called for the key object for dictionary operations, and by + the built-in function hash(). Should return a 32-bit integer + usable as a hash value for dictionary operations. The only + required property is that objects which compare equal have the + same hash value + + >>> IP('10.0.0.0/24').__hash__() + -167772185 + """ + + thehash = int(-1) + ip = self.ip + while ip > 0: + thehash = thehash ^ (ip & 0x7fffffff) + ip = ip >> 32 + thehash = thehash ^ self._prefixlen + return int(thehash) + + +class IP(IPint): + """Class for handling IP addresses and networks.""" + + def net(self): + """Return the base (first) address of a network as an IP object. + + The same as IP[0]. + + >>> IP('10.0.0.0/8').net() + IP('10.0.0.0') + """ + return IP(IPint.net(self), ipversion=self._ipversion) + + def broadcast(self): + """Return the broadcast (last) address of a network as an IP object. + + The same as IP[-1]. + + >>> IP('10.0.0.0/8').broadcast() + IP('10.255.255.255') + """ + return IP(IPint.broadcast(self)) + + def netmask(self): + """Return netmask as an IP object. + + >>> IP('10.0.0.0/8').netmask() + IP('255.0.0.0') + """ + return IP(IPint.netmask(self)) + + + def reverseNames(self): + """Return a list with values forming the reverse lookup. + + >>> IP('213.221.113.87/32').reverseNames() + ['87.113.221.213.in-addr.arpa.'] + >>> IP('213.221.112.224/30').reverseNames() + ['224.112.221.213.in-addr.arpa.', '225.112.221.213.in-addr.arpa.', '226.112.221.213.in-addr.arpa.', '227.112.221.213.in-addr.arpa.'] + >>> IP('127.0.0.0/24').reverseNames() + ['0.0.127.in-addr.arpa.'] + >>> IP('127.0.0.0/23').reverseNames() + ['0.0.127.in-addr.arpa.', '1.0.127.in-addr.arpa.'] + >>> IP('127.0.0.0/16').reverseNames() + ['0.127.in-addr.arpa.'] + >>> IP('127.0.0.0/15').reverseNames() + ['0.127.in-addr.arpa.', '1.127.in-addr.arpa.'] + >>> IP('128.0.0.0/8').reverseNames() + ['128.in-addr.arpa.'] + >>> IP('128.0.0.0/7').reverseNames() + ['128.in-addr.arpa.', '129.in-addr.arpa.'] + >>> IP('::1:2').reverseNames() + ['2.0.0.0.1.ip6.arpa.'] + """ + + if self._ipversion == 4: + ret = [] + # TODO: Refactor. Add support for IPint objects + if self.len() < 2**8: + for x in self: + ret.append(x.reverseName()) + elif self.len() < 2**16L: + for i in range(0, self.len(), 2**8): + ret.append(self[i].reverseName()[2:]) + elif self.len() < 2**24L: + for i in range(0, self.len(), 2**16): + ret.append(self[i].reverseName()[4:]) + else: + for i in range(0, self.len(), 2**24): + ret.append(self[i].reverseName()[6:]) + return ret + elif self._ipversion == 6: + s = hex(self.ip)[2:].lower() + if s[-1] == 'l': + s = s[:-1] + if self._prefixlen % 4 != 0: + raise NotImplementedError, "can't create IPv6 reverse names at sub nibble level" + s = list(s) + s.reverse() + s = '.'.join(s) + first_nibble_index = int(32 - (self._prefixlen / 4)) * 2 + return ["%s.ip6.arpa." % s[first_nibble_index:]] + else: + raise ValueError, "only IPv4 and IPv6 supported" + + + + def reverseName(self): + """Return the value for reverse lookup/PTR records as RFC 2317 look alike. + + RFC 2317 is an ugly hack which only works for sub-/24 e.g. not + for /23. Do not use it. Better set up a zone for every + address. See reverseName for a way to achieve that. + + >>> print IP('195.185.1.1').reverseName() + 1.1.185.195.in-addr.arpa. + >>> print IP('195.185.1.0/28').reverseName() + 0-15.1.185.195.in-addr.arpa. + >>> IP('::1:2').reverseName() + '2.0.0.0.1.ip6.arpa.' + """ + + if self._ipversion == 4: + s = self.strFullsize(0) + s = s.split('.') + s.reverse() + first_byte_index = int(4 - (self._prefixlen / 8)) + if self._prefixlen % 8 != 0: + nibblepart = "%s-%s" % (s[3-(self._prefixlen / 8)], intToIp(self.ip + self.len() - 1, 4).split('.')[-1]) + if nibblepart[-1] == 'l': + nibblepart = nibblepart[:-1] + nibblepart += '.' + else: + nibblepart = "" + + s = '.'.join(s[first_byte_index:]) + return "%s%s.in-addr.arpa." % (nibblepart, s) + + elif self._ipversion == 6: + s = hex(self.ip)[2:].lower() + if s[-1] == 'l': + s = s[:-1] + if self._prefixlen % 4 != 0: + nibblepart = "%s-%s" % (s[self._prefixlen:], hex(self.ip + self.len() - 1)[2:].lower()) + if nibblepart[-1] == 'l': + nibblepart = nibblepart[:-1] + nibblepart += '.' + else: + nibblepart = "" + s = list(s) + s.reverse() + s = '.'.join(s) + first_nibble_index = int(32 - (self._prefixlen / 4)) * 2 + return "%s%s.ip6.arpa." % (nibblepart, s[first_nibble_index:]) + else: + raise ValueError, "only IPv4 and IPv6 supported" + + def make_net(self, netmask): + """Transform a single IP address into a network specification by + applying the given netmask. + + Returns a new IP instance. + + >>> print IP('127.0.0.1').make_net('255.0.0.0') + 127.0.0.0/8 + """ + if '/' in str(netmask): + raise ValueError, "invalid netmask (%s)" % netmask + return IP('%s/%s' % (self, netmask), make_net=True) + + def __getitem__(self, key): + """Called to implement evaluation of self[key]. + + >>> ip=IP('127.0.0.0/30') + >>> for x in ip: + ... print str(x) + ... + 127.0.0.0 + 127.0.0.1 + 127.0.0.2 + 127.0.0.3 + >>> print str(ip[2]) + 127.0.0.2 + >>> print str(ip[-1]) + 127.0.0.3 + """ + return IP(IPint.__getitem__(self, key)) + + def __repr__(self): + """Print a representation of the Object. + + >>> IP('10.0.0.0/8') + IP('10.0.0.0/8') + """ + + return("IP('%s')" % (self.strCompressed(1))) + + def __add__(self, other): + """Emulate numeric objects through network aggregation""" + if self.prefixlen() != other.prefixlen(): + raise ValueError, "Only networks with the same prefixlen can be added." + if self.prefixlen < 1: + raise ValueError, "Networks with a prefixlen longer than /1 can't be added." + if self.version() != other.version(): + raise ValueError, "Only networks with the same IP version can be added." + if self > other: + # fixed by Skinny Puppy <skin_pup-IPy@happypoo.com> + return other.__add__(self) + else: + ret = IP(self.int()) + ret._prefixlen = self.prefixlen() - 1 + return ret + + +def _parseAddressIPv6(ipstr): + """ + Internal function used by parseAddress() to parse IPv6 address with ':'. + + >>> _parseAddressIPv6('::') + 0L + >>> _parseAddressIPv6('::1') + 1L + >>> _parseAddressIPv6('0:0:0:0:0:0:0:1') + 1L + >>> _parseAddressIPv6('0:0:0::0:0:1') + 1L + >>> _parseAddressIPv6('0:0:0:0:0:0:0:0') + 0L + >>> _parseAddressIPv6('0:0:0::0:0:0') + 0L + + >>> _parseAddressIPv6('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210') + 338770000845734292534325025077361652240L + >>> _parseAddressIPv6('1080:0000:0000:0000:0008:0800:200C:417A') + 21932261930451111902915077091070067066L + >>> _parseAddressIPv6('1080:0:0:0:8:800:200C:417A') + 21932261930451111902915077091070067066L + >>> _parseAddressIPv6('1080:0::8:800:200C:417A') + 21932261930451111902915077091070067066L + >>> _parseAddressIPv6('1080::8:800:200C:417A') + 21932261930451111902915077091070067066L + >>> _parseAddressIPv6('FF01:0:0:0:0:0:0:43') + 338958331222012082418099330867817087043L + >>> _parseAddressIPv6('FF01:0:0::0:0:43') + 338958331222012082418099330867817087043L + >>> _parseAddressIPv6('FF01::43') + 338958331222012082418099330867817087043L + >>> _parseAddressIPv6('0:0:0:0:0:0:13.1.68.3') + 218186755L + >>> _parseAddressIPv6('::13.1.68.3') + 218186755L + >>> _parseAddressIPv6('0:0:0:0:0:FFFF:129.144.52.38') + 281472855454758L + >>> _parseAddressIPv6('::FFFF:129.144.52.38') + 281472855454758L + >>> _parseAddressIPv6('1080:0:0:0:8:800:200C:417A') + 21932261930451111902915077091070067066L + >>> _parseAddressIPv6('1080::8:800:200C:417A') + 21932261930451111902915077091070067066L + >>> _parseAddressIPv6('::1:2:3:4:5:6') + 1208962713947218704138246L + >>> _parseAddressIPv6('1:2:3:4:5:6::') + 5192455318486707404433266432802816L + """ + + # Split string into a list, example: + # '1080:200C::417A' => ['1080', '200C', '417A'] and fill_pos=2 + # and fill_pos is the position of '::' in the list + items = [] + index = 0 + fill_pos = None + while index < len(ipstr): + text = ipstr[index:] + if text.startswith("::"): + if fill_pos is not None: + # Invalid IPv6, eg. '1::2::' + raise ValueError("%r: Invalid IPv6 address: more than one '::'" % ipstr) + fill_pos = len(items) + index += 2 + continue + pos = text.find(':') + if pos == 0: + # Invalid IPv6, eg. '1::2:' + raise ValueError("%r: Invalid IPv6 address" % ipstr) + if pos != -1: + items.append(text[:pos]) + if text[pos:pos+2] == "::": + index += pos + else: + index += pos+1 + + if index == len(ipstr): + # Invalid IPv6, eg. '1::2:' + raise ValueError("%r: Invalid IPv6 address" % ipstr) + else: + items.append(text) + break + + if items and '.' in items[-1]: + # IPv6 ending with IPv4 like '::ffff:192.168.0.1' + if not (fill_pos <= len(items)-1): + # Invalid IPv6: 'ffff:192.168.0.1::' + raise ValueError("%r: Invalid IPv6 address: '::' after IPv4" % ipstr) + value = parseAddress(items[-1])[0] + items = items[:-1] + ["%04x" % (value >> 16), "%04x" % (value & 0xffff)] + + # Expand fill_pos to fill with '0' + # ['1','2'] with fill_pos=1 => ['1', '0', '0', '0', '0', '0', '0', '2'] + if fill_pos is not None: + diff = 8 - len(items) + if diff <= 0: + raise ValueError("%r: Invalid IPv6 address: '::' is not needed" % ipstr) + items = items[:fill_pos] + ['0']*diff + items[fill_pos:] + + # Here we have a list of 8 strings + if len(items) != 8: + # Invalid IPv6, eg. '1:2:3' + raise ValueError("%r: Invalid IPv6 address: should have 8 hextets" % ipstr) + + # Convert strings to long integer + value = 0L + index = 0 + for item in items: + try: + item = int(item, 16) + error = not(0 <= item <= 0xFFFF) + except ValueError: + error = True + if error: + raise ValueError("%r: Invalid IPv6 address: invalid hexlet %r" % (ipstr, item)) + value = (value << 16) + item + index += 1 + return value + +def parseAddress(ipstr): + """ + Parse a string and return the corresponding IP address (as integer) + and a guess of the IP version. + + Following address formats are recognized: + + >>> parseAddress('0x0123456789abcdef') # IPv4 if <= 0xffffffff else IPv6 + (81985529216486895L, 6) + >>> parseAddress('123.123.123.123') # IPv4 + (2071690107L, 4) + >>> parseAddress('123.123') # 0-padded IPv4 + (2071658496L, 4) + >>> parseAddress('1080:0000:0000:0000:0008:0800:200C:417A') + (21932261930451111902915077091070067066L, 6) + >>> parseAddress('1080:0:0:0:8:800:200C:417A') + (21932261930451111902915077091070067066L, 6) + >>> parseAddress('1080:0::8:800:200C:417A') + (21932261930451111902915077091070067066L, 6) + >>> parseAddress('::1') + (1L, 6) + >>> parseAddress('::') + (0L, 6) + >>> parseAddress('0:0:0:0:0:FFFF:129.144.52.38') + (281472855454758L, 6) + >>> parseAddress('::13.1.68.3') + (218186755L, 6) + >>> parseAddress('::FFFF:129.144.52.38') + (281472855454758L, 6) + """ + + if ipstr.startswith('0x'): + ret = long(ipstr[2:], 16) + if ret > 0xffffffffffffffffffffffffffffffffL: + raise ValueError, "%r: IP Address can't be bigger than 2^128" % (ipstr) + if ret < 0x100000000L: + return (ret, 4) + else: + return (ret, 6) + + if ipstr.find(':') != -1: + return (_parseAddressIPv6(ipstr), 6) + + elif len(ipstr) == 32: + # assume IPv6 in pure hexadecimal notation + return (long(ipstr, 16), 6) + + elif ipstr.find('.') != -1 or (len(ipstr) < 4 and int(ipstr) < 256): + # assume IPv4 ('127' gets interpreted as '127.0.0.0') + bytes = ipstr.split('.') + if len(bytes) > 4: + raise ValueError, "IPv4 Address with more than 4 bytes" + bytes += ['0'] * (4 - len(bytes)) + bytes = [long(x) for x in bytes] + for x in bytes: + if x > 255 or x < 0: + raise ValueError, "%r: single byte must be 0 <= byte < 256" % (ipstr) + return ((bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3], 4) + + else: + # we try to interprete it as a decimal digit - + # this ony works for numbers > 255 ... others + # will be interpreted as IPv4 first byte + ret = long(ipstr, 10) + if ret > 0xffffffffffffffffffffffffffffffffL: + raise ValueError, "IP Address can't be bigger than 2^128" + if ret <= 0xffffffffL: + return (ret, 4) + else: + return (ret, 6) + + +def intToIp(ip, version): + """Transform an integer string into an IP address.""" + + # just to be sure and hoping for Python 2.22 + ip = long(ip) + + if ip < 0: + raise ValueError, "IPs can't be negative: %d" % (ip) + + ret = '' + if version == 4: + if ip > 0xffffffffL: + raise ValueError, "IPv4 Addresses can't be larger than 0xffffffff: %s" % (hex(ip)) + for l in range(4): + ret = str(ip & 0xffL) + '.' + ret + ip = ip >> 8 + ret = ret[:-1] + elif version == 6: + if ip > 0xffffffffffffffffffffffffffffffffL: + raise ValueError, "IPv6 Addresses can't be larger than 0xffffffffffffffffffffffffffffffff: %s" % (hex(ip)) + l = '0' * 32 + hex(ip)[2:-1] + for x in range(1, 33): + ret = l[-x] + ret + if x % 4 == 0: + ret = ':' + ret + ret = ret[1:] + else: + raise ValueError, "only IPv4 and IPv6 supported" + + return ret + +def _ipVersionToLen(version): + """Return number of bits in address for a certain IP version. + + >>> _ipVersionToLen(4) + 32 + >>> _ipVersionToLen(6) + 128 + >>> _ipVersionToLen(5) + Traceback (most recent call last): + File "<stdin>", line 1, in ? + File "IPy.py", line 1076, in _ipVersionToLen + raise ValueError, "only IPv4 and IPv6 supported" + ValueError: only IPv4 and IPv6 supported + """ + + if version == 4: + return 32 + elif version == 6: + return 128 + else: + raise ValueError, "only IPv4 and IPv6 supported" + + +def _countFollowingZeros(l): + """Return number of elements containing 0 at the beginning of the list.""" + if len(l) == 0: + return 0 + elif l[0] != 0: + return 0 + else: + return 1 + _countFollowingZeros(l[1:]) + + +_BitTable = {'0': '0000', '1': '0001', '2': '0010', '3': '0011', + '4': '0100', '5': '0101', '6': '0110', '7': '0111', + '8': '1000', '9': '1001', 'a': '1010', 'b': '1011', + 'c': '1100', 'd': '1101', 'e': '1110', 'f': '1111'} + +def _intToBin(val): + """Return the binary representation of an integer as string.""" + + if val < 0: + raise ValueError, "Only positive values allowed" + s = hex(val).lower() + ret = '' + if s[-1] == 'l': + s = s[:-1] + for x in s[2:]: + if __debug__: + if not _BitTable.has_key(x): + raise AssertionError, "hex() returned strange result" + ret += _BitTable[x] + # remove leading zeros + while ret[0] == '0' and len(ret) > 1: + ret = ret[1:] + return ret + +def _count1Bits(num): + """Find the highest bit set to 1 in an integer.""" + ret = 0 + while num > 0: + num = num >> 1 + ret += 1 + return ret + +def _count0Bits(num): + """Find the highest bit set to 0 in an integer.""" + + # this could be so easy if _count1Bits(~long(num)) would work as excepted + num = long(num) + if num < 0: + raise ValueError, "Only positive Numbers please: %s" % (num) + ret = 0 + while num > 0: + if num & 1 == 1: + break + num = num >> 1 + ret += 1 + return ret + + +def _checkPrefix(ip, prefixlen, version): + """Check the validity of a prefix + + Checks if the variant part of a prefix only has 0s, and the length is + correct. + + >>> _checkPrefix(0x7f000000L, 24, 4) + 1 + >>> _checkPrefix(0x7f000001L, 24, 4) + 0 + >>> repr(_checkPrefix(0x7f000001L, -1, 4)) + 'None' + >>> repr(_checkPrefix(0x7f000001L, 33, 4)) + 'None' + """ + + # TODO: unify this v4/v6/invalid code in a function + bits = _ipVersionToLen(version) + + if prefixlen < 0 or prefixlen > bits: + return None + + if ip == 0: + zbits = bits + 1 + else: + zbits = _count0Bits(ip) + if zbits < bits - prefixlen: + return 0 + else: + return 1 + + +def _checkNetmask(netmask, masklen): + """Checks if a netmask is expressable as a prefixlen.""" + + num = long(netmask) + bits = masklen + + # remove zero bits at the end + while (num & 1) == 0 and bits != 0: + num = num >> 1 + bits -= 1 + if bits == 0: + break + # now check if the rest consists only of ones + while bits > 0: + if (num & 1) == 0: + raise ValueError, "Netmask %s can't be expressed as an prefix." % (hex(netmask)) + num = num >> 1 + bits -= 1 + + +def _checkNetaddrWorksWithPrefixlen(net, prefixlen, version): + """Check if a base addess of a network is compatible with a prefixlen""" + if net & _prefixlenToNetmask(prefixlen, version) == net: + return 1 + else: + return 0 + + +def _netmaskToPrefixlen(netmask): + """Convert an Integer representing a netmask to a prefixlen. + + E.g. 0xffffff00 (255.255.255.0) returns 24 + """ + + netlen = _count0Bits(netmask) + masklen = _count1Bits(netmask) + _checkNetmask(netmask, masklen) + return masklen - netlen + + +def _prefixlenToNetmask(prefixlen, version): + """Return a mask of n bits as a long integer. + + From 'IP address conversion functions with the builtin socket module' + by Alex Martelli + http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66517 + """ + if prefixlen == 0: + return 0 + elif prefixlen < 0: + raise ValueError, "Prefixlen must be > 0" + return ((2L<<prefixlen-1)-1) << (_ipVersionToLen(version) - prefixlen) + + +if __name__ == "__main__": + import doctest + failure, nbtest = doctest.testmod() + if failure: + import sys + sys.exit(1) + diff --git a/tools/mimeList b/tools/mimeList new file mode 100644 index 0000000000000000000000000000000000000000..63607c3eeb803f5d86e727df409de92be59c368c --- /dev/null +++ b/tools/mimeList @@ -0,0 +1,165 @@ +dwg application/acad +asd application/astound +asn application/astound +tsp application/dsptype +dxf application/dxf +spl application/futuresplash +gz application/gzip +ptlk application/listenup +hqx application/mac-binhex40 +mbd application/mbedlet +mif application/mif +xls application/msexcel +xla application/msexcel +hlp application/mshelp +chm application/mshelp +ppt application/mspowerpoint +ppz application/mspowerpoint +pps application/mspowerpoint +pot application/mspowerpoint +doc application/msword +dot application/msword +bin application/octet-stream +exe application/octet-stream +com application/octet-stream +dll application/octet-stream +class application/octet-stream +oda application/oda +pdf application/pdf +ai application/postscript +eps application/postscript +ps application/postscript +rtc application/rtc +rtf application/rtf +smp application/studiom +tbk application/toolbook +vmd application/vocaltec-media-desc +vmf application/vocaltec-media-file +bcpio application/x-bcpio +z application/x-compress +cpio application/x-cpio +csh application/x-csh +dcr application/x-director +dir application/x-director +dxr application/x-director +dvi application/x-dvi +evy application/x-envoy +gtar application/x-gtar +hdf application/x-hdf +php application/x-httpd-php +phtml application/x-httpd-php +js application/x-javascript +latex application/x-latex +bin application/x-macbinary +mif application/x-mif +nc application/x-netcdf +cdf application/x-netcdf +nsc application/x-nschat +sh application/x-sh +shar application/x-shar +swf application/x-shockwave-flash +cab application/x-shockwave-flash +spr application/x-sprite +sprite application/x-sprite +sit application/x-stuffit +sca application/x-supercard +sv4cpio application/x-sv4cpio +sv4crc application/x-sv4crc +tar application/x-tar +tcl application/x-tcl +tex application/x-tex +texinfo application/x-texinfo +texi application/x-texinfo +t application/x-troff +tr application/x-troff +roff application/x-troff +man application/x-troff-man +troff application/x-troff-man +me application/x-troff-me +troff application/x-troff-me +me application/x-troff-ms +troff application/x-troff-ms +ustar application/x-ustar +src application/x-wais-source + application/x-www-form-urlencoded +zip application/zip +au audio/basic +snd audio/basic +es audio/echospeech +tsi audio/tsplayer +vox audio/voxware +aif audio/x-aiff +aiff audio/x-aiff +aifc audio/x-aiff +dus audio/x-dspeeh +cht audio/x-dspeeh +mid audio/x-midi +midi audio/x-midi +mp2 audio/x-mpeg +ram audio/x-pn-realaudio +ra audio/x-pn-realaudio +rpm audio/x-pn-realaudio-plugin +stream audio/x-qt-stream +wav audio/x-wav +dwf drawing/x-dwf +cod image/cis-cod +ras image/cmu-raster +fif image/fif +gif image/gif +png image/png +ief image/ief +jpeg image/jpeg +jpg image/jpeg +jpe image/jpeg +svg image/svg+xml +tiff image/tiff +tif image/tiff +mcf image/vasa +wbmp image/vnd.wap.wbmp +fh4 image/x-freehand +fh5 image/x-freehand +fhc image/x-freehand +pnm image/x-portable-anymap +pbm image/x-portable-bitmap +pgm image/x-portable-graymap +ppm image/x-portable-pixmap +rgb image/x-rgb +xwd image/x-windowdump +xbm image/x-xbitmap +xpm image/x-xpixmap +wrl model/vrml +csv text/comma-separated-values +css text/css +htm text/html +html text/html +shtml text/html +js text/javascript +txt text/plain +rtx text/richtext +rtf text/rtf +tsv text/tab-separated-values +wml text/vnd.wap.wml +wmlc application/vnd.wap.wmlc +wmls text/vnd.wap.wmlscript +wmlsc application/vnd.wap.wmlscriptc +etx text/x-setext +sgm text/x-sgml +sgml text/x-sgml +talk text/x-speech +spc text/x-speech +mpeg video/mpeg +mpg video/mpeg +mpe video/mpeg +qt video/quicktime +mov video/quicktime +*viv video/vnd.vivo +vivo video/vnd.vivo +avi video/x-msvideo +movie video/x-sgi-movie +vts workbook/formulaone +vtts workbook/formulaone +3dmf x-world/x-3dmf +3dm x-world/x-3dmf +qd3d x-world/x-3dmf +qd3 x-world/x-3dmf +wrl x-world/x-vrml