Merge remote-tracking branch 'upstream/master'
authorCallum <callum@callum-ubuntu.(none)>
Sun, 1 Sep 2013 09:55:55 +0000 (17:55 +0800)
committerCallum <callum@callum-ubuntu.(none)>
Sun, 1 Sep 2013 09:55:55 +0000 (17:55 +0800)
30 files changed:
camera/.capture.c.swp [deleted file]
irc/log
nginx-configs/README [new file with mode: 0644]
nginx-configs/fastcgi_params [new file with mode: 0644]
nginx-configs/mime.types [new file with mode: 0644]
nginx-configs/sites-enabled/mctxconfig [new file with mode: 0644]
sensors/beagleboard sensors notes.docx [new file with mode: 0644]
sensors/sensors test drivers (c)/generic_buffer.c [new file with mode: 0644]
sensors/sensors test drivers (c)/iio_utils.h [new file with mode: 0644]
sensors/sensors test drivers (c)/readme.txt [new file with mode: 0644]
sensors/sensors test drivers (c)/script_adc.sh [new file with mode: 0644]
sensors/sensors test drivers (c)/script_trigger.sh [new file with mode: 0644]
sensors/simple code examples.c [new file with mode: 0644]
sensors/simpleGPIO (c++)/SimpleGPIO.cpp [new file with mode: 0644]
sensors/simpleGPIO (c++)/SimpleGPIO.h [new file with mode: 0644]
server/Makefile
server/common.h
server/fastcgi.c
server/fastcgi.h
server/log.c
server/main.c
server/options.h
server/run.sh
server/sensor.c
server/sensor.h
server/thread.c [new file with mode: 0644]
server/thread.h [new file with mode: 0644]
server/valgrind.sh [new file with mode: 0755]
testing/fastcgi-approach/-etc-nginx/fastcgi_params [deleted file]
testing/fastcgi-approach/-etc-nginx/sites-enabled/default [deleted file]

diff --git a/camera/.capture.c.swp b/camera/.capture.c.swp
deleted file mode 100644 (file)
index 9d8f11f..0000000
Binary files a/camera/.capture.c.swp and /dev/null differ
diff --git a/irc/log b/irc/log
index 73c9654..b954d89 100644 (file)
--- a/irc/log
+++ b/irc/log
 17:07 -!- Irssi: #mctxuwa_softdev: Total of 1 nicks [1 ops, 0 halfops, 0 voices, 0 normal]
 17:07 -!- Irssi: Join to #mctxuwa_softdev was synced in 1 secs
 17:08 -!- You're now known as sam_moore
+--- Day changed Mon Aug 26 2013
+11:11 -!- matches [[email protected]] has joined #mctxuwa_softdev
+11:11 -!- matches [[email protected]] has left #mctxuwa_softdev []
+11:12 <@sam_moore> Thought I might have the wrong server
+17:18 <@sam_moore> I do have the wrong server!
+17:19 -!- sam_moore [[email protected]] has left #mctxuwa_softdev [I have the wrong server!]
+--- Log closed Mon Aug 26 17:19:05 2013
+--- Log opened Mon Aug 26 17:19:34 2013
+17:19 -!- sam_moore [[email protected]] has joined #mctxuwa_softdev
+17:19 -!- Irssi: #mctxuwa_softdev: Total of 2 nicks [0 ops, 0 halfops, 0 voices, 2 normal]
+17:19 -!- Irssi: Join to #mctxuwa_softdev was synced in 5 secs
+17:19 < sam_moore> !motd
+17:20 < sam_moore> '!motd'
+17:20 < sam_moore> MctxBot: You're broken
+17:20 < sam_moore> Oh wait, never mind
+18:07 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+18:08 < jtanx> :P
+18:09 < jtanx> you can change the message if you want
+21:03 -!- jtanx [[email protected]] has quit ["brb"]
+21:12 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+22:46 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.89 [Firefox 23.0.1/20130814063812]"]
+--- Day changed Tue Aug 27 2013
+07:40 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+07:54 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.89 [Firefox 23.0.1/20130814063812]"]
+17:53 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+19:11 < jtanx> lol
+19:11 < jtanx> the camera that we were using for the soldering lab inserted a bunch of wavy lines/static into the video
+19:12 < sam_moore> It's an effect
+19:14 < jtanx> nah
+19:14 < jtanx> the camera was actually broken
+19:15 < sam_moore> (I figured that)
+19:15 < sam_moore> You could pretend it's supposed to be an 80s style video?
+19:15 < jtanx> yeah that could work
+19:16 < jtanx> have you done it yet?
+19:18 < sam_moore> No :S
+19:20 < jtanx> well
+19:21 < jtanx> according to the manual, you need to connect a wire from R5 on the sensor board to the relay board
+19:21 < jtanx> problem was we already chopped off the lead on R5
+19:22 < jtanx> another group connected the wire to the LEd though
+19:22 < jtanx> seemed to work
+20:02 < jtanx> so are we using clock_gettime?
+20:08 < sam_moore> I think so, we can use CLOCK_MONOTONIC_RAW if we are paranoid about the system time getting changed
+20:08 < sam_moore> Or we can just use CLOCK_REALTIME if we aren't
+20:09 < jtanx> I thought CLOCK_MONOTONIC was supposed to be best, because the RAW version wasn't compensated for temp/other stuff
+20:10 < jtanx> http://stackoverflow.com/questions/3523442/difference-between-clock-realtime-and-clock-monotonic
+20:10 < jtanx> about the FCGI loop blocking
+20:10 < jtanx> you can switch to FCGX_ methods
+20:10 < jtanx> I think
+20:11 < jtanx> but is it really necessary
+20:20 < jtanx> about the valgrind comment in sensors.c
+20:20 < jtanx> this is probably it: http://stackoverflow.com/questions/5844242/valgrind-yells-about-an-uninitialised-bytes
+20:23 < sam_moore> It's probably not necessary to stop the FCGI loop blocking, don't worry about it
+20:25 < sam_moore> Yeah, I didn't initialise the buffers anywhere
+20:25 < jtanx> actually I can't reproduce that message
+20:25 < sam_moore> Hmm
+20:26 < jtanx> about the sensor times
+20:27 < jtanx> what about if you all reference it relative to some point
+20:27 < jtanx> eg
+20:27 < sam_moore> The epoch :P
+20:27 < jtanx> lol
+20:27 < jtanx> I mean
+20:28 < jtanx> when you get sensor data, you store the difference in time between the start of recording and now
+20:28 < sam_moore> Sure, that makes more sense
+20:29 < sam_moore> Just give the client the start of recording time and they can convert it to a time of day / day in the calendar themselves
+20:30 < jtanx> yeah
+20:30 < jtanx> you could have a specific request to return the starting time
+20:30 < jtanx> then it's implicit for all requests
+20:30 < jtanx> btw I submitted a pull request for the nginx configs
+20:32 < sam_moore> Ok
+20:32 < sam_moore> I've added you to collaborators so you can merge them yourself if you need to
+20:33 < jtanx> ok
+20:35 < jtanx> huh
+20:35 < jtanx> http://www.cnx-software.com/2011/09/26/beagleboard-emulator-in-ubuntu-with-qemu/
+20:41 < sam_moore> Nice
+20:42 < sam_moore> "Currently you can not access Ethernet" Not so nice
+20:42 < sam_moore> Although this is dated 2011
+21:18 -!- jtanx [[email protected]] has quit ["bye"]
+--- Day changed Wed Aug 28 2013
+08:52 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+10:08 -!- MctxBot [[email protected]] has quit [Connection reset by peer]
+10:11 -!- MctxBot [[email protected]] has joined #mctxuwa_softdev
+10:39 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.89 [Firefox 23.0.1/20130814063812]"]
+15:16 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+15:48 -!- Callum [[email protected]] has joined #mctxuwa_softdev
+16:31 < jtanx> huh
+16:31 < jtanx> firefox's javascript debugger is pretty cool
+16:31 < sam_moore> Firebug? Yeah
+16:35 < jtanx> nah the inbuilt one
+16:35 < jtanx> firebug's good for inspecting html though
+16:35 < jtanx> haven't used firebugs js debugger yet
+16:35 < sam_moore> Oh, I didn't know they had an inbuilt one
+16:36 < jtanx> Ctrl+Shift+K
+16:36 < sam_moore> Of course I normally use Iceweasel, which is currently built as firefox 10.0.2 with a different name
+16:36 < jtanx> well that's about 10 releases behind
+16:36 < sam_moore> That looks pretty similar to firebug anyway
+16:55 < jtanx> inline conditionals in javascript are whack
+16:55 -!- Callum_ [[email protected]] has joined #mctxuwa_softdev
+16:55 < sam_moore> I haven't done much javascript, but a lot of it does seem whack
+16:56 < sam_moore> jtanx: What are you working on in JavaScript?
+16:56 < jtanx> unit tests
+16:57 < sam_moore> Cool
+17:01 -!- Callum [[email protected]] has quit [Ping timeout]
+17:01 -!- Callum_ is now known as Callum
+17:18 < jtanx> javascript in general is annoying me though
+17:25 < Callum> when exactly is this soldering lab due? fucking thing.
+17:27 < jtanx> next friday
+17:27 < Callum> it says week 5 on lms
+17:27 < jtanx> sept 6
+17:27 < Callum> where's it say this?
+17:27 < jtanx> yeah he made an announcement
+17:27 < jtanx> that it's wrong
+17:27 < jtanx> somewhere
+17:28 < Callum> sigh. this unit..i swear
+17:28 < Callum> if it really is next week then i'd be so relieved
+17:28 < Callum> wow
+17:28 < Callum> he made an announcement today..
+17:28 < Callum> wait yesterday
+17:29 < jtanx> still got that central plant fbd to do
+17:29 < Callum> why hasnt LMS emailed me a notification? (/end spam)
+17:29 < Callum> yea i know
+17:29 < Callum> which i think i have it pretty much done
+17:29 < Callum> not 100% sure on it though
+17:29 < Callum> and whether to add pumps and shit into it
+17:29 < jtanx> what did you have on it?
+17:30 < Callum> HA as i say that i check my phone and i have the message about the announcement
+17:30 < jtanx> and what did you call the chiller things?
+17:30 < Callum> pretty much just the 4 chillers, a line showing it can go back (they're literally called chillers ahha(
+17:31 < Callum> then i had another part to show the chillers (evaporation/condensor/compressor and cooling tower is connected to condenser) 
+17:31 < jtanx> ook
+17:31 < Callum> however
+17:32 < Callum> im not sure about the input/output of the chiller
+17:32 < Callum> because stuff online shows it to be the evaporator 
+17:32 < Callum> but isnt it water being pumped?
+17:32 < jtanx> I think there were pumps on the output
+17:33 < jtanx> were there three outputs?
+17:33 < Callum> also not sure if i should/wherte to add the tank (yea ofc theres pumps but not sure to put them in to the diagram, pretty much everything is pumped)
+17:33 < Callum> outputs where?
+17:33 < jtanx> North/Sout/East distribution things
+17:33 < jtanx> iirc
+17:33 < jtanx> yeah not sure whether to add tank or not
+17:34 < Callum> oh that, i didnt bother with that
+17:34 < Callum> just how did the chiller connect with the rest of the plant?
+17:34 < Callum> was the evaporator the input/output?
+17:34 < Callum> because the chiller feeds out to the water tower and the tower feeds back into the chiller (i think)
+17:36 < Callum> also what was the thing called? that allowed water to flow back and forth bypassing the chillers. back something?
+17:36 < Callum> really they should have told us before we went in we had to do this. some lazy fucks like me dont read the outline so i didnt take notes..or try to commit stuff to memory :po
+17:39 < jtanx> the bypass?
+17:39 < jtanx> I haven't gone into detail
+17:39 < jtanx> so I just have chiller
+17:39 < jtanx> and cooling tower
+17:39 < jtanx> maybe I should
+17:40 < Callum> remember how tehre was 4 chillers, and they would only run what was needed.
+17:40 < jtanx> yeah
+17:40 < jtanx> how many cooling towers?
+17:40 < Callum> and if they had more than they needed there was a pipe to flow back, or if they had some chilled water from the tanks or w.e it bypassed chillers
+17:40 < Callum> i dont know, but im not sure how to show it all
+17:40 < Callum> im sure what iv got is somewhat decent
+17:41 < jtanx> I used visio and I ended up spending so much time trying to get the lines rihgt
+17:41 < jtanx> probably would have been faster to hand draw it
+17:41 < jtanx> still not finished too
+17:41 < Callum> haha im fiarly sure i read somewhere it was hand drawn :p
+17:41 < jtanx> meh I suck at drawing
+17:42 < Callum> maybe not. "This is to be drawn and annotated on single A4 page"
+17:42 < Callum> i dont think they'll be picky
+17:42 < jtanx> and there's lines everywhere
+17:42 < Callum> really? how do you have lines everywhere?
+17:42 < jtanx> ok so chiller
+17:42 < Callum> it's a fairly simple system. unless i'v done it wrong :s
+17:43 < jtanx> has warm chilled water (1), chilled coolant (2), hot coolant (3), chilled chilled water(4), control line (5), (maybe) sensor back to controller (6)
+17:43 < jtanx> that's ~5 lines in/out of one box?
+17:44 < Callum> hmm. havent included coolant or control/sensor
+17:44 < Callum> maybe i should :S
+17:44 < jtanx> and an operator
+17:44 < jtanx> to the controller
+17:45 < Callum> thing is it asked for a high level FBD though
+17:45 < Callum> which means not very detailed
+17:45 < Callum> or maybe it didnt?
+17:45 < jtanx> yeah, so do you need to show condensor/evaporator
+17:45 < jtanx> I just have a chiller box
+17:46 < jtanx> anyway... afk ~10 mins
+17:46 < Callum> the condensor/evaporater is part of the chiller isnt it?
+17:46 < Callum> ok
+18:10 < Callum> anyone finished reading chapter 4 of the notes?
+18:11 < jtanx> what's that
+18:11 < Callum> sensors
+18:12 < Callum> so dull :l
+18:12 < Callum> and pretty much no chance to remember enough of it. quiz tomorrow is going to be fun.. 
+18:12 < jtanx> oh 
+18:13 < jtanx> shit
+18:13 < jtanx> have to study for that
+18:13 < Callum> rofl
+18:14 < jtanx> :/
+18:15 < Callum> gonna just have to wing most of them again like last time most likely. 
+18:15 < jtanx> probably
+18:15 < jtanx> Well, the unit testing thing works http://mctx.us.to:8080/unit-tests/
+18:15 < jtanx> now what unit tests should there be
+18:18 < Callum> not sure.
+18:25 < Callum> brilliant! the notes show a false colour image built from a black and white image...while printed in black and white.
+18:34 < jtanx> :P
+19:50 < jtanx> um
+19:50 < jtanx> did we get around to doing the sparkplus thing
+19:54 < jtanx> we need to do it before the end of the week
+19:54 < Callum> umm.
+19:54 < Callum> actually justin already set up the group
+19:54 < Callum> so you need to hurry up and join before we have to recreate the group :P
+19:54 < jtanx> nah it expired
+19:54 < Callum> wait already?
+19:54 < Callum> zzz
+19:55 < jtanx> 5 hr deadline
+19:55 < Callum> and adrian said it was 24Hr, whats with this 5 hour shit
+19:55 < jtanx> so... we need to try again
+19:55 < jtanx> when everyone's available
+20:11 -!- Callum [[email protected]] has quit [Ping timeout]
+20:49 -!- jtanx [[email protected]] has quit ["ha"]
+--- Day changed Thu Aug 29 2013
+07:47 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+09:16 < jtanx> firefox blocks ajax calls if you try to run the file locally :/
+09:45 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.89 [Firefox 23.0.1/20130814063812]"]
+13:33 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+14:24 -!- james__ [[email protected]] has joined #mctxuwa_softdev
+14:25 < james__> Hey Jeremy. Is there a way to find my login hash key if i am already logged into the api?
+14:28 < jtanx> um
+14:28 < jtanx> right now you should store it
+14:29 < jtanx> just declare a global variable and set it to the hash
+14:30 < jtanx> or if you have made a class
+14:30 < jtanx> just make it an element
+14:31 < james__> I'm still logged in from ages ago and i can't logout so i can get a different key that works
+14:31 < jtanx> that
+14:31 < jtanx> ok
+14:31 < james__> Possibly a bug that needs fixing? 
+14:31 < jtanx> so the way it works right now is there's a 3 minute timeout on the key
+14:31 < jtanx> no
+14:31 < jtanx> there's actually two layers
+14:32 < jtanx> the password that you enter first (mctxadmin) is what's called HTTP basic authentication
+14:32 < jtanx> this lets you gain access to /api/login
+14:32 < james__> Well i tried loging in again and its saying i am already logged in
+14:32 < jtanx> when you reach /api/login you get the access key
+14:32 < jtanx> there's a three minute timeout on the key
+14:32 < jtanx> if you wish to invalidate the key
+14:33 < jtanx> you call 
+14:33 < jtanx>  /api/login?end
+14:34 < jtanx> you can force getting a key by also calling /api/login?force
+14:34 < james__> right. well it worked this time
+14:34 < james__> Thats weird
+14:34 < jtanx> so the only thing that the key prevents is stopping accidental concurrent use
+14:34 < james__> Fair enough
+14:35 < jtanx> Calling /api/login?force will force a new key to be generated and the old one to be invalidated
+14:35 < james__> Okay
+14:35 < jtanx> btw as I was working on unit testing
+14:35 < jtanx> I did a function to retrieve the json data
+14:36 < jtanx> http://mctx.us.to:8080/unit-tests/unit-tests.js
+14:37 < james__> I will have a look.  I have some buttons working and stuff. Working on putting them in a seperate script file for easier editing etc
+14:37 < james__> They don't seem to be playing nice at the moment
+14:37 < jtanx> ok
+14:38 < jtanx> how come it takes so much effort to get some buttons working
+14:39 < james__> Getting the css to mesh with the js
+14:40 < james__> I have buttons fine 
+14:40 < james__> And they work
+14:40 < jtanx> maybe you should get the functionality to work first
+14:40 < jtanx> with the ajax queries
+14:40 < jtanx> before worrying about styling them
+14:40 < james__> I have the functionality pretty much working
+14:41 < jtanx> so the querying works?
+14:41 < james__> But i want the styling to work before we scale it up
+14:41 < james__> That way its less hassle to fix it later
+14:41 < jtanx> could you post it to git?
+14:41 < jtanx> it'd be cool to have a look
+14:45 < james__> The way i am thinking about having it set out is having a central index.html which just imports all the js. The js will contain all the functionlity seperated in to similar functions. Ie. all the buttons in one script
+14:46 < jtanx> right
+14:46 < james__> That should allow for ease of scaling and editing
+14:46 < james__> Also changing id's and stuff
+15:46 -!- james__ [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 23.0.1/20130814063812]"]
+19:25 -!- Callum [[email protected]] has joined #mctxuwa_softdev
+21:09 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.89 [Firefox 23.0.1/20130814063812]"]
+23:18 -!- Callum [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 23.0.1/20130814063812]"]
+--- Day changed Fri Aug 30 2013
+09:03 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+09:16 -!- jtanx [[email protected]] has quit [EOF From client]
+14:15 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+17:06 < jtanx> say you want to perform a command
+17:06 < jtanx> eg move an actuator
+17:07 < jtanx> and suppose checks have to be made against other sensors to ensure that this command is good to go
+17:07 < jtanx> how are those checks going to be made?
+18:10 < sam_moore> The Actuator Handler will call some sanity check against the most recent sensor data
+18:11 < sam_moore> If they aren't, it will respond with some appropriate JSON or HTTP status code
+18:11 < sam_moore> eg: "Try again later when the pressure is in the right range", or "Don't do that you silly person"
+18:15 < jtanx> ._.
+18:21 < jtanx> I wonder if there's a way to pull from your git repository without creating the 'merge branch master from...' commits
+18:22 < sam_moore> I don't think so
+18:22 < jtanx> I tried playing with rebasing but it doesn't work out so well
+18:40 < jtanx> ok so I've committed some stuff to my repository that changes the handling of controls/actuators/login
+18:41 < jtanx> I'm not sure if it's the best way to do it
+18:41 < jtanx> though
+18:41 < jtanx> What I did was get rid of /api/login
+18:41 < jtanx> and instead have /api/control
+18:41 < jtanx> All of the control code (eg actuators but may be other controls? Start/stop the whole thing?) has been moved to controls.c
+18:42 < jtanx> You still need to supply username and password to access /api/control
+18:42 < jtanx> and what was previously called  the 'authorization key'  is now the control key (ie who has control)
+19:00 < sam_moore> Ok, I'll take a look at it later
+19:01 < sam_moore> Don't worry about the merge messages, it's not a big deal
+19:06 < jtanx> ok thanks
+20:27 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 23.0.1/20130814063812]"]
+22:21 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+23:03 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 23.0.1/20130814063812]"]
+--- Day changed Sat Aug 31 2013
+09:09 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+15:30 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 23.0.1/20130814063812]"]
+17:40 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+20:48 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 23.0.1/20130814063812]"]
diff --git a/nginx-configs/README b/nginx-configs/README
new file mode 100644 (file)
index 0000000..1c6ade5
--- /dev/null
@@ -0,0 +1,18 @@
+This folder represents the files that should be placed under:
+/etc/nginx
+
+To install:
+* Delete all files under /etc/nginx/sites-enabled
+* Either:
+  * Copy 'mctxconfig' (under sites-enabled) to /etc/nginx/sites-available/
+    and create a symlink to that file under /etc/nginx/sites-enabled/
+  * Create a symlink directly from 'mctxconfig' to 
+    /etc/etc/nginx/sites-enabled/
+* Replace /etc/nginx/fastcgi_params and /etc/nginx/mime.types with the
+  provided files (either by copying or symlinking)
+
+Note:
+To get the login functionality working, you need to place a .htpasswd file
+under /usr/share/nginx/access (create folder if it doesn't exist). To generate
+the htpasswd file, install the apache2-utils package and use the 'htpasswd'
+executable.
diff --git a/nginx-configs/fastcgi_params b/nginx-configs/fastcgi_params
new file mode 100644 (file)
index 0000000..51aa692
--- /dev/null
@@ -0,0 +1,27 @@
+fastcgi_param  QUERY_STRING            $query_string;
+fastcgi_param  REQUEST_METHOD          $request_method;
+fastcgi_param  CONTENT_TYPE            $content_type;
+fastcgi_param  CONTENT_LENGTH          $content_length;
+
+fastcgi_param  SCRIPT_FILENAME         $request_filename;
+fastcgi_param  SCRIPT_NAME             $fastcgi_script_name;
+fastcgi_param  REQUEST_URI             $request_uri;
+fastcgi_param  DOCUMENT_URI            $document_uri;
+fastcgi_param  DOCUMENT_ROOT           $document_root;
+fastcgi_param  SERVER_PROTOCOL         $server_protocol;
+
+fastcgi_param  GATEWAY_INTERFACE       CGI/1.1;
+fastcgi_param  SERVER_SOFTWARE         nginx/$nginx_version;
+fastcgi_param  SERVER_HOSTNAME         mctxsoft;
+
+fastcgi_param  REMOTE_ADDR             $remote_addr;
+fastcgi_param  REMOTE_PORT             $remote_port;
+fastcgi_param  REMOTE_USER             $remote_user;
+fastcgi_param  SERVER_ADDR             $server_addr;
+fastcgi_param  SERVER_PORT             $server_port;
+fastcgi_param  SERVER_NAME             $server_name;
+
+fastcgi_param  HTTPS                   $https;
+
+# PHP only, required if PHP was built with --enable-force-cgi-redirect
+fastcgi_param  REDIRECT_STATUS         200;
diff --git a/nginx-configs/mime.types b/nginx-configs/mime.types
new file mode 100644 (file)
index 0000000..9d05612
--- /dev/null
@@ -0,0 +1,80 @@
+types {
+       text/html                               html htm shtml;
+       text/css                                css;
+       text/xml                                xml rss;
+       image/gif                               gif;
+       image/jpeg                              jpeg jpg;
+       application/x-javascript                js;
+       application/atom+xml                    atom;
+
+       text/mathml                             mml;
+       text/plain                              log;
+       text/plain                              txt;
+       text/vnd.sun.j2me.app-descriptor        jad;
+       text/vnd.wap.wml                        wml;
+       text/x-component                        htc;
+
+       image/png                               png;
+       image/tiff                              tif tiff;
+       image/vnd.wap.wbmp                      wbmp;
+       image/x-icon                            ico;
+       image/x-jng                             jng;
+       image/x-ms-bmp                          bmp;
+       image/svg+xml                           svg svgz;
+
+       application/java-archive                jar war ear;
+       application/json                        json;
+       application/mac-binhex40                hqx;
+       application/msword                      doc;
+       application/pdf                         pdf;
+       application/postscript                  ps eps ai;
+       application/rtf                         rtf;
+       application/vnd.ms-excel                xls;
+       application/vnd.ms-powerpoint           ppt;
+       application/vnd.wap.wmlc                wmlc;
+       application/vnd.google-earth.kml+xml    kml;
+       application/vnd.google-earth.kmz        kmz;
+       application/x-7z-compressed             7z;
+       application/x-cocoa                     cco;
+       application/x-java-archive-diff         jardiff;
+       application/x-java-jnlp-file            jnlp;
+       application/x-makeself                  run;
+       application/x-perl                      pl pm;
+       application/x-pilot                     prc pdb;
+       application/x-rar-compressed            rar;
+       application/x-redhat-package-manager    rpm;
+       application/x-sea                       sea;
+       application/x-shockwave-flash           swf;
+       application/x-stuffit                   sit;
+       application/x-tcl                       tcl tk;
+       application/x-x509-ca-cert              der pem crt;
+       application/x-xpinstall                 xpi;
+       application/xhtml+xml                   xhtml;
+       application/zip                         zip;
+
+       application/octet-stream                bin exe dll;
+       application/octet-stream                deb;
+       application/octet-stream                dmg;
+       application/octet-stream                eot;
+       application/octet-stream                iso img;
+       application/octet-stream                msi msp msm;
+       application/ogg                         ogx;
+
+       audio/midi                              mid midi kar;
+       audio/mpeg                              mpga mpega mp2 mp3 m4a;
+       audio/ogg                               oga ogg spx;
+       audio/x-realaudio                       ra;
+       audio/webm                              weba;
+
+       video/3gpp                              3gpp 3gp;
+       video/mp4                               mp4;
+       video/mpeg                              mpeg mpg mpe;
+       video/ogg                               ogv;
+       video/quicktime                         mov;
+       video/webm                              webm;
+       video/x-flv                             flv;
+       video/x-mng                             mng;
+       video/x-ms-asf                          asx asf;
+       video/x-ms-wmv                          wmv;
+       video/x-msvideo                         avi;
+}
diff --git a/nginx-configs/sites-enabled/mctxconfig b/nginx-configs/sites-enabled/mctxconfig
new file mode 100644 (file)
index 0000000..541f6d1
--- /dev/null
@@ -0,0 +1,131 @@
+# You may add here your
+# server {
+#      ...
+# }
+# statements for each of your virtual hosts to this file
+
+##
+# You should look at the following URL's in order to grasp a solid understanding
+# of Nginx configuration files in order to fully unleash the power of Nginx.
+# http://wiki.nginx.org/Pitfalls
+# http://wiki.nginx.org/QuickStart
+# http://wiki.nginx.org/Configuration
+#
+# Generally, you will want to move this file somewhere, and start with a clean
+# file but keep this around for reference. Or just disable in sites-enabled.
+#
+# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
+##
+
+server {
+       listen 80;
+       listen [::]:80 default_server ipv6only=on;
+
+       root /usr/share/nginx/html;
+       index index.php index.html index.htm;
+
+       # Make site accessible from http://localhost/
+       server_name localhost;
+
+       location / {
+               # First attempt to serve request as file, then
+               # as directory, then fall back to displaying a 404.
+               try_files $uri $uri/ =404;
+               # Uncomment to enable naxsi on this location
+               # include /etc/nginx/naxsi.rules
+       }
+
+       # Only for nginx-naxsi used with nginx-naxsi-ui : process denied requests
+       #location /RequestDenied {
+       #       proxy_pass http://127.0.0.1:8080;    
+       #}
+
+       #error_page 404 /404.html;
+
+       # redirect server error pages to the static page /50x.html
+       #
+       #error_page 500 502 503 504 /50x.html;
+       #location = /50x.html {
+       #       root /usr/share/nginx/html;
+       #}
+
+       # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
+       #
+       location ~ \.php$ {
+               fastcgi_split_path_info ^(.+\.php)(/.+)$;
+       #       # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
+       #
+       #       # With php5-cgi alone:
+       #       fastcgi_pass 127.0.0.1:9000;
+       #       # With php5-fpm:
+               fastcgi_pass unix:/var/run/php5-fpm.sock;
+               fastcgi_index index.php;
+               include fastcgi_params;
+       }
+
+       # deny access to .htaccess files, if Apache's document root
+       # concurs with nginx's one
+       #
+       location ~ /\.ht {
+               deny all;
+       }
+       
+       #Login area
+       location ^~ /api/login {
+               auth_basic "Restricted Access";
+               auth_basic_user_file /usr/share/nginx/access/.htpasswd;
+       
+               fastcgi_pass 127.0.0.1:9005;
+               fastcgi_param DOCUMENT_URI_LOCAL login;
+               include fastcgi_params;
+       }
+       
+       #MCTX API
+       location /api {
+               location ~ ^/api/?([^?]*) {
+                       fastcgi_pass 127.0.0.1:9005;
+                       fastcgi_param DOCUMENT_URI_LOCAL $1;
+                       include fastcgi_params;
+               }
+       }
+}
+
+
+# another virtual host using mix of IP-, name-, and port-based configuration
+#
+#server {
+#      listen 8000;
+#      listen somename:8080;
+#      server_name somename alias another.alias;
+#      root html;
+#      index index.html index.htm;
+#
+#      location / {
+#              try_files $uri $uri/ =404;
+#      }
+#}
+
+
+# HTTPS server
+#
+#server {
+#      listen 443;
+#      server_name localhost;
+#
+#      root html;
+#      index index.html index.htm;
+#
+#      ssl on;
+#      ssl_certificate cert.pem;
+#      ssl_certificate_key cert.key;
+#
+#      ssl_session_timeout 5m;
+#
+#      ssl_protocols SSLv3 TLSv1;
+#      ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
+#      ssl_prefer_server_ciphers on;
+#
+#      location / {
+#              try_files $uri $uri/ =404;
+#      }
+#}
diff --git a/sensors/beagleboard sensors notes.docx b/sensors/beagleboard sensors notes.docx
new file mode 100644 (file)
index 0000000..746600c
Binary files /dev/null and b/sensors/beagleboard sensors notes.docx differ
diff --git a/sensors/sensors test drivers (c)/generic_buffer.c b/sensors/sensors test drivers (c)/generic_buffer.c
new file mode 100644 (file)
index 0000000..40d0eca
--- /dev/null
@@ -0,0 +1,340 @@
+/* Industrialio buffer test code.
+ *
+ * Copyright (c) 2008 Jonathan Cameron
+ *
+ * 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.
+ *
+ * This program is primarily intended as an example application.
+ * Reads the current buffer setup from sysfs and starts a short capture
+ * from the specified device, pretty printing the result after appropriate
+ * conversion.
+ *
+ * Command line parameters
+ * generic_buffer -n <device_name> -t <trigger_name>
+ * If trigger name is not specified the program assumes you want a dataready
+ * trigger associated with the device and goes looking for it.
+ *
+ */
+
+#define _GNU_SOURCE
+
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include <linux/types.h>
+#include <string.h>
+#include <poll.h>
+#include <endian.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include "iio_utils.h"
+
+/**
+ * size_from_channelarray() - calculate the storage size of a scan
+ * @channels:          the channel info array
+ * @num_channels:      number of channels
+ *
+ * Has the side effect of filling the channels[i].location values used
+ * in processing the buffer output.
+ **/
+int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
+{
+       int bytes = 0;
+       int i = 0;
+       while (i < num_channels) {
+               if (bytes % channels[i].bytes == 0)
+                       channels[i].location = bytes;
+               else
+                       channels[i].location = bytes - bytes%channels[i].bytes
+                               + channels[i].bytes;
+               bytes = channels[i].location + channels[i].bytes;
+               i++;
+       }
+       return bytes;
+}
+
+void print2byte(int input, struct iio_channel_info *info)
+{
+       /* First swap if incorrect endian */
+       if (info->be)
+               input = be16toh((uint16_t)input);
+       else
+               input = le16toh((uint16_t)input);
+
+       /*
+        * Shift before conversion to avoid sign extension
+        * of left aligned data
+        */
+       input = input >> info->shift;
+       if (info->is_signed) {
+               int16_t val = input;
+               val &= (1 << info->bits_used) - 1;
+               val = (int16_t)(val << (16 - info->bits_used)) >>
+                       (16 - info->bits_used);
+               printf("%05f ", ((float)val + info->offset)*info->scale);
+       } else {
+               uint16_t val = input;
+               val &= (1 << info->bits_used) - 1;
+               printf("%05f ", ((float)val + info->offset)*info->scale);
+       }
+}
+/**
+ * process_scan() - print out the values in SI units
+ * @data:              pointer to the start of the scan
+ * @channels:          information about the channels. Note
+ *  size_from_channelarray must have been called first to fill the
+ *  location offsets.
+ * @num_channels:      number of channels
+ **/
+void process_scan(char *data,
+                 struct iio_channel_info *channels,
+                 int num_channels)
+{
+       int k;
+       for (k = 0; k < num_channels; k++)
+               switch (channels[k].bytes) {
+                       /* only a few cases implemented so far */
+               case 2:
+                       print2byte(*(uint16_t *)(data + channels[k].location),
+                                  &channels[k]);
+                       break;
+               case 4:
+                       if (!channels[k].is_signed) {
+                               uint32_t val = *(uint32_t *)
+                                       (data + channels[k].location);
+                               printf("%05f ", ((float)val +
+                                                channels[k].offset)*
+                                      channels[k].scale);
+
+                       }
+                       break;
+               case 8:
+                       if (channels[k].is_signed) {
+                               int64_t val = *(int64_t *)
+                                       (data +
+                                        channels[k].location);
+                               if ((val >> channels[k].bits_used) & 1)
+                                       val = (val & channels[k].mask) |
+                                               ~channels[k].mask;
+                               /* special case for timestamp */
+                               if (channels[k].scale == 1.0f &&
+                                   channels[k].offset == 0.0f)
+                                       printf("%" PRId64 " ", val);
+                               else
+                                       printf("%05f ", ((float)val +
+                                                        channels[k].offset)*
+                                              channels[k].scale);
+                       }
+                       break;
+               default:
+                       break;
+               }
+       printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+       unsigned long num_loops = 2;
+       unsigned long timedelay = 1000000;
+       unsigned long buf_len = 128;
+
+       int ret, c, i, j, toread;
+       int fp;
+
+       int num_channels;
+       char *trigger_name = NULL, *device_name = NULL;
+       char *dev_dir_name, *buf_dir_name;
+
+       int datardytrigger = 1;
+       char *data;
+       ssize_t read_size;
+       int dev_num, trig_num;
+       char *buffer_access;
+       int scan_size;
+       int noevents = 0;
+       char *dummy;
+
+       struct iio_channel_info *channels;
+
+       while ((c = getopt(argc, argv, "l:w:c:et:n:")) != -1) {
+               switch (c) {
+               case 'n':
+                       device_name = optarg;
+                       break;
+               case 't':
+                       trigger_name = optarg;
+                       datardytrigger = 0;
+                       break;
+               case 'e':
+                       noevents = 1;
+                       break;
+               case 'c':
+                       num_loops = strtoul(optarg, &dummy, 10);
+                       break;
+               case 'w':
+                       timedelay = strtoul(optarg, &dummy, 10);
+                       break;
+               case 'l':
+                       buf_len = strtoul(optarg, &dummy, 10);
+                       break;
+               case '?':
+                       return -1;
+               }
+       }
+
+       if (device_name == NULL)
+               return -1;
+
+       /* Find the device requested */
+       dev_num = find_type_by_name(device_name, "iio:device");
+       if (dev_num < 0) {
+               printf("Failed to find the %s\n", device_name);
+               ret = -ENODEV;
+               goto error_ret;
+       }
+       printf("iio device number being used is %d\n", dev_num);
+
+       asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
+       if (trigger_name == NULL) {
+               /*
+                * Build the trigger name. If it is device associated its
+                * name is <device_name>_dev[n] where n matches the device
+                * number found above
+                */
+               ret = asprintf(&trigger_name,
+                              "%s-dev%d", device_name, dev_num);
+               if (ret < 0) {
+                       ret = -ENOMEM;
+                       goto error_ret;
+               }
+       }
+
+       /* Verify the trigger exists */
+       trig_num = find_type_by_name(trigger_name, "trigger");
+       if (trig_num < 0) {
+               printf("Failed to find the trigger %s\n", trigger_name);
+               ret = -ENODEV;
+               goto error_free_triggername;
+       }
+       printf("iio trigger number being used is %d\n", trig_num);
+
+       /*
+        * Parse the files in scan_elements to identify what channels are
+        * present
+        */
+       ret = build_channel_array(dev_dir_name, &channels, &num_channels);
+       if (ret) {
+               printf("Problem reading scan element information\n");
+               printf("diag %s\n", dev_dir_name);
+               goto error_free_triggername;
+       }
+
+       /*
+        * Construct the directory name for the associated buffer.
+        * As we know that the lis3l02dq has only one buffer this may
+        * be built rather than found.
+        */
+       ret = asprintf(&buf_dir_name,
+                      "%siio:device%d/buffer", iio_dir, dev_num);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_free_triggername;
+       }
+       printf("%s %s\n", dev_dir_name, trigger_name);
+       /* Set the device trigger to be the data ready trigger found above */
+       ret = write_sysfs_string_and_verify("trigger/current_trigger",
+                                       dev_dir_name,
+                                       trigger_name);
+       if (ret < 0) {
+               printf("Failed to write current_trigger file\n");
+               goto error_free_buf_dir_name;
+       }
+
+       /* Setup ring buffer parameters */
+       ret = write_sysfs_int("length", buf_dir_name, buf_len);
+       if (ret < 0)
+               goto error_free_buf_dir_name;
+
+       /* Enable the buffer */
+       ret = write_sysfs_int("enable", buf_dir_name, 1);
+       if (ret < 0)
+               goto error_free_buf_dir_name;
+       scan_size = size_from_channelarray(channels, num_channels);
+       data = malloc(scan_size*buf_len);
+       if (!data) {
+               ret = -ENOMEM;
+               goto error_free_buf_dir_name;
+       }
+
+       ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_free_data;
+       }
+
+       /* Attempt to open non blocking the access dev */
+       fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
+       if (fp == -1) { /* If it isn't there make the node */
+               printf("Failed to open %s\n", buffer_access);
+               ret = -errno;
+               goto error_free_buffer_access;
+       }
+
+       /* Wait for events 10 times */
+       for (j = 0; j < num_loops; j++) {
+               if (!noevents) {
+                       struct pollfd pfd = {
+                               .fd = fp,
+                               .events = POLLIN,
+                       };
+
+                       poll(&pfd, 1, -1);
+                       toread = buf_len;
+
+               } else {
+                       usleep(timedelay);
+                       toread = 64;
+               }
+
+               read_size = read(fp,
+                                data,
+                                toread*scan_size);
+               if (read_size == -EAGAIN) {
+                       printf("nothing available\n");
+                       continue;
+               }
+               for (i = 0; i < read_size/scan_size; i++)
+                       process_scan(data + scan_size*i,
+                                    channels,
+                                    num_channels);
+       }
+
+       /* Stop the buffer */
+       ret = write_sysfs_int("enable", buf_dir_name, 0);
+       if (ret < 0)
+               goto error_close_buffer_access;
+
+       /* Disconnect the trigger - just write a dummy name. */
+       write_sysfs_string("trigger/current_trigger",
+                       dev_dir_name, "NULL");
+
+error_close_buffer_access:
+       close(fp);
+error_free_data:
+       free(data);
+error_free_buffer_access:
+       free(buffer_access);
+error_free_buf_dir_name:
+       free(buf_dir_name);
+error_free_triggername:
+       if (datardytrigger)
+               free(trigger_name);
+error_ret:
+       return ret;
+}
diff --git a/sensors/sensors test drivers (c)/iio_utils.h b/sensors/sensors test drivers (c)/iio_utils.h
new file mode 100644 (file)
index 0000000..cf32ae0
--- /dev/null
@@ -0,0 +1,654 @@
+/* IIO - useful set of util functionality
+ *
+ * Copyright (c) 2008 Jonathan Cameron
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <dirent.h>
+#include <errno.h>
+
+/* Made up value to limit allocation sizes */
+#define IIO_MAX_NAME_LENGTH 30
+
+#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
+#define FORMAT_TYPE_FILE "%s_type"
+
+const char *iio_dir = "/sys/bus/iio/devices/";
+
+/**
+ * iioutils_break_up_name() - extract generic name from full channel name
+ * @full_name: the full channel name
+ * @generic_name: the output generic channel name
+ **/
+inline int iioutils_break_up_name(const char *full_name,
+                                 char **generic_name)
+{
+       char *current;
+       char *w, *r;
+       char *working;
+       current = strdup(full_name);
+       working = strtok(current, "_\0");
+       w = working;
+       r = working;
+
+       while (*r != '\0') {
+               if (!isdigit(*r)) {
+                       *w = *r;
+                       w++;
+               }
+               r++;
+       }
+       *w = '\0';
+       *generic_name = strdup(working);
+       free(current);
+
+       return 0;
+}
+
+/**
+ * struct iio_channel_info - information about a given channel
+ * @name: channel name
+ * @generic_name: general name for channel type
+ * @scale: scale factor to be applied for conversion to si units
+ * @offset: offset to be applied for conversion to si units
+ * @index: the channel index in the buffer output
+ * @bytes: number of bytes occupied in buffer output
+ * @mask: a bit mask for the raw output
+ * @is_signed: is the raw value stored signed
+ * @enabled: is this channel enabled
+ **/
+struct iio_channel_info {
+       char *name;
+       char *generic_name;
+       float scale;
+       float offset;
+       unsigned index;
+       unsigned bytes;
+       unsigned bits_used;
+       unsigned shift;
+       uint64_t mask;
+       unsigned be;
+       unsigned is_signed;
+       unsigned enabled;
+       unsigned location;
+};
+
+/**
+ * iioutils_get_type() - find and process _type attribute data
+ * @is_signed: output whether channel is signed
+ * @bytes: output how many bytes the channel storage occupies
+ * @mask: output a bit mask for the raw data
+ * @be: big endian
+ * @device_dir: the iio device directory
+ * @name: the channel name
+ * @generic_name: the channel type name
+ **/
+inline int iioutils_get_type(unsigned *is_signed,
+                            unsigned *bytes,
+                            unsigned *bits_used,
+                            unsigned *shift,
+                            uint64_t *mask,
+                            unsigned *be,
+                            const char *device_dir,
+                            const char *name,
+                            const char *generic_name)
+{
+       FILE *sysfsfp;
+       int ret;
+       DIR *dp;
+       char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
+       char signchar, endianchar;
+       unsigned padint;
+       const struct dirent *ent;
+
+       ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_ret;
+       }
+       ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_free_scan_el_dir;
+       }
+       ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_free_builtname;
+       }
+
+       dp = opendir(scan_el_dir);
+       if (dp == NULL) {
+               ret = -errno;
+               goto error_free_builtname_generic;
+       }
+       while (ent = readdir(dp), ent != NULL)
+               /*
+                * Do we allow devices to override a generic name with
+                * a specific one?
+                */
+               if ((strcmp(builtname, ent->d_name) == 0) ||
+                   (strcmp(builtname_generic, ent->d_name) == 0)) {
+                       ret = asprintf(&filename,
+                                      "%s/%s", scan_el_dir, ent->d_name);
+                       if (ret < 0) {
+                               ret = -ENOMEM;
+                               goto error_closedir;
+                       }
+                       sysfsfp = fopen(filename, "r");
+                       if (sysfsfp == NULL) {
+                               printf("failed to open %s\n", filename);
+                               ret = -errno;
+                               goto error_free_filename;
+                       }
+
+                       ret = fscanf(sysfsfp,
+                                    "%ce:%c%u/%u>>%u",
+                                    &endianchar,
+                                    &signchar,
+                                    bits_used,
+                                    &padint, shift);
+                       if (ret < 0) {
+                               printf("failed to pass scan type description\n");
+                               ret = -errno;
+                               goto error_close_sysfsfp;
+                       }
+                       *be = (endianchar == 'b');
+                       *bytes = padint / 8;
+                       if (*bits_used == 64)
+                               *mask = ~0;
+                       else
+                               *mask = (1 << *bits_used) - 1;
+                       if (signchar == 's')
+                               *is_signed = 1;
+                       else
+                               *is_signed = 0;
+                       fclose(sysfsfp);
+                       free(filename);
+
+                       filename = 0;
+                       sysfsfp = 0;
+               }
+error_close_sysfsfp:
+       if (sysfsfp)
+               fclose(sysfsfp);
+error_free_filename:
+       if (filename)
+               free(filename);
+error_closedir:
+       closedir(dp);
+error_free_builtname_generic:
+       free(builtname_generic);
+error_free_builtname:
+       free(builtname);
+error_free_scan_el_dir:
+       free(scan_el_dir);
+error_ret:
+       return ret;
+}
+
+inline int iioutils_get_param_float(float *output,
+                                   const char *param_name,
+                                   const char *device_dir,
+                                   const char *name,
+                                   const char *generic_name)
+{
+       FILE *sysfsfp;
+       int ret;
+       DIR *dp;
+       char *builtname, *builtname_generic;
+       char *filename = NULL;
+       const struct dirent *ent;
+
+       ret = asprintf(&builtname, "%s_%s", name, param_name);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_ret;
+       }
+       ret = asprintf(&builtname_generic,
+                      "%s_%s", generic_name, param_name);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_free_builtname;
+       }
+       dp = opendir(device_dir);
+       if (dp == NULL) {
+               ret = -errno;
+               goto error_free_builtname_generic;
+       }
+       while (ent = readdir(dp), ent != NULL)
+               if ((strcmp(builtname, ent->d_name) == 0) ||
+                   (strcmp(builtname_generic, ent->d_name) == 0)) {
+                       ret = asprintf(&filename,
+                                      "%s/%s", device_dir, ent->d_name);
+                       if (ret < 0) {
+                               ret = -ENOMEM;
+                               goto error_closedir;
+                       }
+                       sysfsfp = fopen(filename, "r");
+                       if (!sysfsfp) {
+                               ret = -errno;
+                               goto error_free_filename;
+                       }
+                       fscanf(sysfsfp, "%f", output);
+                       break;
+               }
+error_free_filename:
+       if (filename)
+               free(filename);
+error_closedir:
+       closedir(dp);
+error_free_builtname_generic:
+       free(builtname_generic);
+error_free_builtname:
+       free(builtname);
+error_ret:
+       return ret;
+}
+
+/**
+ * bsort_channel_array_by_index() - reorder so that the array is in index order
+ *
+ **/
+
+inline void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
+                                        int cnt)
+{
+
+       struct iio_channel_info temp;
+       int x, y;
+
+       for (x = 0; x < cnt; x++)
+               for (y = 0; y < (cnt - 1); y++)
+                       if ((*ci_array)[y].index > (*ci_array)[y+1].index) {
+                               temp = (*ci_array)[y + 1];
+                               (*ci_array)[y + 1] = (*ci_array)[y];
+                               (*ci_array)[y] = temp;
+                       }
+}
+
+/**
+ * build_channel_array() - function to figure out what channels are present
+ * @device_dir: the IIO device directory in sysfs
+ * @
+ **/
+inline int build_channel_array(const char *device_dir,
+                             struct iio_channel_info **ci_array,
+                             int *counter)
+{
+       DIR *dp;
+       FILE *sysfsfp;
+       int count, i;
+       struct iio_channel_info *current;
+       int ret;
+       const struct dirent *ent;
+       char *scan_el_dir;
+       char *filename;
+
+       *counter = 0;
+       ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_ret;
+       }
+       dp = opendir(scan_el_dir);
+       if (dp == NULL) {
+               ret = -errno;
+               goto error_free_name;
+       }
+       while (ent = readdir(dp), ent != NULL)
+               if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
+                          "_en") == 0) {
+                       ret = asprintf(&filename,
+                                      "%s/%s", scan_el_dir, ent->d_name);
+                       if (ret < 0) {
+                               ret = -ENOMEM;
+                               goto error_close_dir;
+                       }
+                       sysfsfp = fopen(filename, "r");
+                       if (sysfsfp == NULL) {
+                               ret = -errno;
+                               free(filename);
+                               goto error_close_dir;
+                       }
+                       fscanf(sysfsfp, "%u", &ret);
+                       if (ret == 1)
+                               (*counter)++;
+                       fclose(sysfsfp);
+                       free(filename);
+               }
+       *ci_array = malloc(sizeof(**ci_array) * (*counter));
+       if (*ci_array == NULL) {
+               ret = -ENOMEM;
+               goto error_close_dir;
+       }
+       seekdir(dp, 0);
+       count = 0;
+       while (ent = readdir(dp), ent != NULL) {
+               if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
+                          "_en") == 0) {
+                       current = &(*ci_array)[count++];
+                       ret = asprintf(&filename,
+                                      "%s/%s", scan_el_dir, ent->d_name);
+                       if (ret < 0) {
+                               ret = -ENOMEM;
+                               /* decrement count to avoid freeing name */
+                               count--;
+                               goto error_cleanup_array;
+                       }
+                       sysfsfp = fopen(filename, "r");
+                       if (sysfsfp == NULL) {
+                               free(filename);
+                               ret = -errno;
+                               goto error_cleanup_array;
+                       }
+                       fscanf(sysfsfp, "%u", &current->enabled);
+                       fclose(sysfsfp);
+
+                       if (!current->enabled) {
+                               free(filename);
+                               count--;
+                               continue;
+                       }
+
+                       current->scale = 1.0;
+                       current->offset = 0;
+                       current->name = strndup(ent->d_name,
+                                               strlen(ent->d_name) -
+                                               strlen("_en"));
+                       if (current->name == NULL) {
+                               free(filename);
+                               ret = -ENOMEM;
+                               goto error_cleanup_array;
+                       }
+                       /* Get the generic and specific name elements */
+                       ret = iioutils_break_up_name(current->name,
+                                                    &current->generic_name);
+                       if (ret) {
+                               free(filename);
+                               goto error_cleanup_array;
+                       }
+                       ret = asprintf(&filename,
+                                      "%s/%s_index",
+                                      scan_el_dir,
+                                      current->name);
+                       if (ret < 0) {
+                               free(filename);
+                               ret = -ENOMEM;
+                               goto error_cleanup_array;
+                       }
+                       sysfsfp = fopen(filename, "r");
+                       fscanf(sysfsfp, "%u", &current->index);
+                       fclose(sysfsfp);
+                       free(filename);
+                       /* Find the scale */
+                       ret = iioutils_get_param_float(&current->scale,
+                                                      "scale",
+                                                      device_dir,
+                                                      current->name,
+                                                      current->generic_name);
+                       if (ret < 0)
+                               goto error_cleanup_array;
+                       ret = iioutils_get_param_float(&current->offset,
+                                                      "offset",
+                                                      device_dir,
+                                                      current->name,
+                                                      current->generic_name);
+                       if (ret < 0)
+                               goto error_cleanup_array;
+                       ret = iioutils_get_type(&current->is_signed,
+                                               &current->bytes,
+                                               &current->bits_used,
+                                               &current->shift,
+                                               &current->mask,
+                                               &current->be,
+                                               device_dir,
+                                               current->name,
+                                               current->generic_name);
+               }
+       }
+
+       closedir(dp);
+       /* reorder so that the array is in index order */
+       bsort_channel_array_by_index(ci_array, *counter);
+
+       return 0;
+
+error_cleanup_array:
+       for (i = count - 1;  i >= 0; i--)
+               free((*ci_array)[i].name);
+       free(*ci_array);
+error_close_dir:
+       closedir(dp);
+error_free_name:
+       free(scan_el_dir);
+error_ret:
+       return ret;
+}
+
+/**
+ * find_type_by_name() - function to match top level types by name
+ * @name: top level type instance name
+ * @type: the type of top level instance being sort
+ *
+ * Typical types this is used for are device and trigger.
+ **/
+inline int find_type_by_name(const char *name, const char *type)
+{
+       const struct dirent *ent;
+       int number, numstrlen;
+
+       FILE *nameFile;
+       DIR *dp;
+       char thisname[IIO_MAX_NAME_LENGTH];
+       char *filename;
+
+       dp = opendir(iio_dir);
+       if (dp == NULL) {
+               printf("No industrialio devices available\n");
+               return -ENODEV;
+       }
+
+       while (ent = readdir(dp), ent != NULL) {
+               if (strcmp(ent->d_name, ".") != 0 &&
+                       strcmp(ent->d_name, "..") != 0 &&
+                       strlen(ent->d_name) > strlen(type) &&
+                       strncmp(ent->d_name, type, strlen(type)) == 0) {
+                       numstrlen = sscanf(ent->d_name + strlen(type),
+                                          "%d",
+                                          &number);
+                       /* verify the next character is not a colon */
+                       if (strncmp(ent->d_name + strlen(type) + numstrlen,
+                                       ":",
+                                       1) != 0) {
+                               filename = malloc(strlen(iio_dir)
+                                               + strlen(type)
+                                               + numstrlen
+                                               + 6);
+                               if (filename == NULL) {
+                                       closedir(dp);
+                                       return -ENOMEM;
+                               }
+                               sprintf(filename, "%s%s%d/name",
+                                       iio_dir,
+                                       type,
+                                       number);
+                               nameFile = fopen(filename, "r");
+                               if (!nameFile) {
+                                       free(filename);
+                                       continue;
+                               }
+                               free(filename);
+                               fscanf(nameFile, "%s", thisname);
+                               fclose(nameFile);
+                               if (strcmp(name, thisname) == 0) {
+                                       closedir(dp);
+                                       return number;
+                               }
+                       }
+               }
+       }
+       closedir(dp);
+       return -ENODEV;
+}
+
+inline int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
+{
+       int ret;
+       FILE *sysfsfp;
+       int test;
+       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+       if (temp == NULL)
+               return -ENOMEM;
+       sprintf(temp, "%s/%s", basedir, filename);
+       sysfsfp = fopen(temp, "w");
+       if (sysfsfp == NULL) {
+               printf("failed to open %s\n", temp);
+               ret = -errno;
+               goto error_free;
+       }
+       fprintf(sysfsfp, "%d", val);
+       fclose(sysfsfp);
+       if (verify) {
+               sysfsfp = fopen(temp, "r");
+               if (sysfsfp == NULL) {
+                       printf("failed to open %s\n", temp);
+                       ret = -errno;
+                       goto error_free;
+               }
+               fscanf(sysfsfp, "%d", &test);
+               fclose(sysfsfp);
+               if (test != val) {
+                       printf("Possible failure in int write %d to %s%s\n",
+                               val,
+                               basedir,
+                               filename);
+                       ret = -1;
+               }
+       }
+error_free:
+       free(temp);
+       return ret;
+}
+
+int write_sysfs_int(char *filename, char *basedir, int val)
+{
+       return _write_sysfs_int(filename, basedir, val, 0);
+}
+
+int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
+{
+       return _write_sysfs_int(filename, basedir, val, 1);
+}
+
+int _write_sysfs_string(char *filename, char *basedir, char *val, int verify)
+{
+       int ret = 0;
+       FILE  *sysfsfp;
+       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+       if (temp == NULL) {
+               printf("Memory allocation failed\n");
+               return -ENOMEM;
+       }
+       sprintf(temp, "%s/%s", basedir, filename);
+       sysfsfp = fopen(temp, "w");
+       if (sysfsfp == NULL) {
+               printf("Could not open %s\n", temp);
+               ret = -errno;
+               goto error_free;
+       }
+       fprintf(sysfsfp, "%s", val);
+       fclose(sysfsfp);
+       if (verify) {
+               sysfsfp = fopen(temp, "r");
+               if (sysfsfp == NULL) {
+                       printf("could not open file to verify\n");
+                       ret = -errno;
+                       goto error_free;
+               }
+               fscanf(sysfsfp, "%s", temp);
+               fclose(sysfsfp);
+               if (strcmp(temp, val) != 0) {
+                       printf("Possible failure in string write of %s "
+                               "Should be %s "
+                               "written to %s\%s\n",
+                               temp,
+                               val,
+                               basedir,
+                               filename);
+                       ret = -1;
+               }
+       }
+error_free:
+       free(temp);
+
+       return ret;
+}
+
+/**
+ * write_sysfs_string_and_verify() - string write, readback and verify
+ * @filename: name of file to write to
+ * @basedir: the sysfs directory in which the file is to be found
+ * @val: the string to write
+ **/
+int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
+{
+       return _write_sysfs_string(filename, basedir, val, 1);
+}
+
+int write_sysfs_string(char *filename, char *basedir, char *val)
+{
+       return _write_sysfs_string(filename, basedir, val, 0);
+}
+
+int read_sysfs_posint(char *filename, char *basedir)
+{
+       int ret;
+       FILE  *sysfsfp;
+       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+       if (temp == NULL) {
+               printf("Memory allocation failed");
+               return -ENOMEM;
+       }
+       sprintf(temp, "%s/%s", basedir, filename);
+       sysfsfp = fopen(temp, "r");
+       if (sysfsfp == NULL) {
+               ret = -errno;
+               goto error_free;
+       }
+       fscanf(sysfsfp, "%d\n", &ret);
+       fclose(sysfsfp);
+error_free:
+       free(temp);
+       return ret;
+}
+
+int read_sysfs_float(char *filename, char *basedir, float *val)
+{
+       float ret = 0;
+       FILE  *sysfsfp;
+       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+       if (temp == NULL) {
+               printf("Memory allocation failed");
+               return -ENOMEM;
+       }
+       sprintf(temp, "%s/%s", basedir, filename);
+       sysfsfp = fopen(temp, "r");
+       if (sysfsfp == NULL) {
+               ret = -errno;
+               goto error_free;
+       }
+       fscanf(sysfsfp, "%f\n", val);
+       fclose(sysfsfp);
+error_free:
+       free(temp);
+       return ret;
+}
diff --git a/sensors/sensors test drivers (c)/readme.txt b/sensors/sensors test drivers (c)/readme.txt
new file mode 100644 (file)
index 0000000..80ca9a3
--- /dev/null
@@ -0,0 +1,20 @@
+This is a userspace application which accesses the adc via /dev/iio in continuous sampling mode.
+
+The application scans the scan_elements folder in /dev/iio/devices/iio:deviceX/scan_elements for enabled channels.
+
+Creates a data structure.
+
+Sets the buffer size. Enables the buffer. And reads from the dev file for the driver.
+
+The source code is located under kernel sources "drivers/staging/iio/Documentation/generic_buffer.c".
+
+How to compile:
+
+arm-arago-linux-gnueabi-gcc --static generic_buffer.c -o generic_buffer
+
+or
+
+-gcc --static generic_buffer.c -o generic_buffer
+
+
+SOURCE: https://github.com/ZubairLK/adc-iio-continuous-sampling-userspace
\ No newline at end of file
diff --git a/sensors/sensors test drivers (c)/script_adc.sh b/sensors/sensors test drivers (c)/script_adc.sh
new file mode 100644 (file)
index 0000000..2afcb63
--- /dev/null
@@ -0,0 +1,5 @@
+echo 1 > /sys/bus/iio/devices/iio_sysfs_trigger/add_trigger
+echo 1 > /sys/bus/iio/devices/iio\:device0/scan_elements/in_voltage7_en
+echo 1 > /sys/bus/iio/devices/iio\:device0/scan_elements/in_voltage5_en
+generic_buffer -n TI-am335x-adc -t sysfstrig1 -l 128
+
diff --git a/sensors/sensors test drivers (c)/script_trigger.sh b/sensors/sensors test drivers (c)/script_trigger.sh
new file mode 100644 (file)
index 0000000..cdaf2d1
--- /dev/null
@@ -0,0 +1 @@
+echo 1  > /sys/bus/iio/devices/trigger0/trigger_now
diff --git a/sensors/simple code examples.c b/sensors/simple code examples.c
new file mode 100644 (file)
index 0000000..0a973ba
--- /dev/null
@@ -0,0 +1,54 @@
+//Code to blink an LED - just to illustrate that it's pretty easy
+//Only important thing is which name to address the LED by
+
+#include <stdio.h>
+#include <unistd.h>
+using namespace std;
+int main(int argc, char** argv) {
+  FILE *LEDHandle = NULL;
+  char *LEDBrightness = "/sys/class/leds/beaglebone:green:usr0/brightness";
+  printf("\nStarting LED blink program wooo!\n");
+  while(1){
+    if((LEDHandle = fopen(LEDBrightness, "r+")) != NULL){
+      fwrite("1", sizeof(char), 1, LEDHandle);
+      fclose(LEDHandle);
+    }
+    sleep(1);
+    if((LEDHandle = fopen(LEDBrightness, "r+")) != NULL){
+      fwrite("0", sizeof(char), 1, LEDHandle);
+      fclose(LEDHandle);
+    }
+    sleep(1);
+  }
+  return 0;
+}
+
+//Sample code that should read a pressure sensor pin (conversion factors
+//are just random numbers). Again pretty simple.
+
+#include STUFF
+double pressure(char *string) {
+        int value = atoi(string);
+        double millivolts = (value / 4096.0) * 1800; //convert input to volts
+        double pressure = (millivolts - 500.0) / 10.0; //convert volts to pressure
+        return pressure;
+}
+void main() {
+        int fd = open("/sys/devices/platform/tsc/ain2", O_RDONLY); //open pin signal
+        while (1) {
+                char buffer[1024];
+                int ret = read(fd, buffer, sizeof(buffer)); //get data
+                if (ret != -1) {
+                        buffer[ret] = NULL;
+                        double kpa = pressure(buffer);
+                        printf("digital value: %s  kilopascals: %f\n", buffer, kpa);
+                        lseek(fd, 0, 0);
+                }
+                sleep(1);
+        }
+        close(fd);
+}
\ No newline at end of file
diff --git a/sensors/simpleGPIO (c++)/SimpleGPIO.cpp b/sensors/simpleGPIO (c++)/SimpleGPIO.cpp
new file mode 100644 (file)
index 0000000..ab17a98
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * SimpleGPIO.cpp
+ *
+ * Modifications by Derek Molloy, School of Electronic Engineering, DCU
+ * www.eeng.dcu.ie/~molloyd/
+ * Almost entirely based on Software by RidgeRun:
+ *
+ * Copyright (c) 2011, RidgeRun
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by the RidgeRun.
+ * 4. Neither the name of the RidgeRun nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RIDGERUN ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL RIDGERUN BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "SimpleGPIO.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+
+/****************************************************************
+ * gpio_export
+ ****************************************************************/
+int gpio_export(unsigned int gpio)
+{
+       int fd, len;
+       char buf[MAX_BUF];
+
+       fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY);
+       if (fd < 0) {
+               perror("gpio/export");
+               return fd;
+       }
+
+       len = snprintf(buf, sizeof(buf), "%d", gpio);
+       write(fd, buf, len);
+       close(fd);
+
+       return 0;
+}
+
+/****************************************************************
+ * gpio_unexport
+ ****************************************************************/
+int gpio_unexport(unsigned int gpio)
+{
+       int fd, len;
+       char buf[MAX_BUF];
+
+       fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY);
+       if (fd < 0) {
+               perror("gpio/export");
+               return fd;
+       }
+
+       len = snprintf(buf, sizeof(buf), "%d", gpio);
+       write(fd, buf, len);
+       close(fd);
+       return 0;
+}
+
+/****************************************************************
+ * gpio_set_dir
+ ****************************************************************/
+int gpio_set_dir(unsigned int gpio, PIN_DIRECTION out_flag)
+{
+       int fd;
+       char buf[MAX_BUF];
+
+       snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR  "/gpio%d/direction", gpio);
+
+       fd = open(buf, O_WRONLY);
+       if (fd < 0) {
+               perror("gpio/direction");
+               return fd;
+       }
+
+       if (out_flag == OUTPUT_PIN)
+               write(fd, "out", 4);
+       else
+               write(fd, "in", 3);
+
+       close(fd);
+       return 0;
+}
+
+/****************************************************************
+ * gpio_set_value
+ ****************************************************************/
+int gpio_set_value(unsigned int gpio, PIN_VALUE value)
+{
+       int fd;
+       char buf[MAX_BUF];
+
+       snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
+
+       fd = open(buf, O_WRONLY);
+       if (fd < 0) {
+               perror("gpio/set-value");
+               return fd;
+       }
+
+       if (value==LOW)
+               write(fd, "0", 2);
+       else
+               write(fd, "1", 2);
+
+       close(fd);
+       return 0;
+}
+
+/****************************************************************
+ * gpio_get_value
+ ****************************************************************/
+int gpio_get_value(unsigned int gpio, unsigned int *value)
+{
+       int fd;
+       char buf[MAX_BUF];
+       char ch;
+
+       snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
+
+       fd = open(buf, O_RDONLY);
+       if (fd < 0) {
+               perror("gpio/get-value");
+               return fd;
+       }
+
+       read(fd, &ch, 1);
+
+       if (ch != '0') {
+               *value = 1;
+       } else {
+               *value = 0;
+       }
+
+       close(fd);
+       return 0;
+}
+
+
+/****************************************************************
+ * gpio_set_edge
+ ****************************************************************/
+
+int gpio_set_edge(unsigned int gpio, char *edge)
+{
+       int fd;
+       char buf[MAX_BUF];
+
+       snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio);
+
+       fd = open(buf, O_WRONLY);
+       if (fd < 0) {
+               perror("gpio/set-edge");
+               return fd;
+       }
+
+       write(fd, edge, strlen(edge) + 1);
+       close(fd);
+       return 0;
+}
+
+/****************************************************************
+ * gpio_fd_open
+ ****************************************************************/
+
+int gpio_fd_open(unsigned int gpio)
+{
+       int fd;
+       char buf[MAX_BUF];
+
+       snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
+
+       fd = open(buf, O_RDONLY | O_NONBLOCK );
+       if (fd < 0) {
+               perror("gpio/fd_open");
+       }
+       return fd;
+}
+
+/****************************************************************
+ * gpio_fd_close
+ ****************************************************************/
+
+int gpio_fd_close(int fd)
+{
+       return close(fd);
+}
+
+
+/****************************************************************
+ * gpio_omap_mux_setup - Allow us to setup the omap mux mode for a pin
+ ****************************************************************/
+int gpio_omap_mux_setup(const char *omap_pin0_name, const char *mode)
+{
+       int fd;
+       char buf[MAX_BUF];
+       snprintf(buf, sizeof(buf), SYSFS_OMAP_MUX_DIR "%s", omap_pin0_name);
+       fd = open(buf, O_WRONLY);
+       if (fd < 0) {
+               perror("failed to open OMAP_MUX");
+               return fd;
+       }
+       write(fd, mode, strlen(mode) + 1);
+       close(fd);
+       return 0;
+}
\ No newline at end of file
diff --git a/sensors/simpleGPIO (c++)/SimpleGPIO.h b/sensors/simpleGPIO (c++)/SimpleGPIO.h
new file mode 100644 (file)
index 0000000..edbd78a
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * SimpleGPIO.h
+ *
+ * Copyright Derek Molloy, School of Electronic Engineering, Dublin City University
+ * www.eeng.dcu.ie/~molloyd/
+ *
+ * Based on Software by RidgeRun
+ * Copyright (c) 2011, RidgeRun
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by the RidgeRun.
+ * 4. Neither the name of the RidgeRun nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RIDGERUN ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL RIDGERUN BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SIMPLEGPIO_H_
+#define SIMPLEGPIO_H_
+
+ /****************************************************************
+ * Constants
+ ****************************************************************/
+
+#define SYSFS_GPIO_DIR "/sys/class/gpio"
+#define POLL_TIMEOUT (3 * 1000) /* 3 seconds */
+#define MAX_BUF 64
+#define SYSFS_OMAP_MUX_DIR "/sys/kernel/debug/omap_mux/"
+
+enum PIN_DIRECTION{
+       INPUT_PIN=0,
+       OUTPUT_PIN=1
+};
+
+enum PIN_VALUE{
+       LOW=0,
+       HIGH=1
+};
+
+/****************************************************************
+ * gpio_export
+ ****************************************************************/
+int gpio_export(unsigned int gpio);
+int gpio_unexport(unsigned int gpio);
+int gpio_set_dir(unsigned int gpio, PIN_DIRECTION out_flag);
+int gpio_set_value(unsigned int gpio, PIN_VALUE value);
+int gpio_get_value(unsigned int gpio, unsigned int *value);
+int gpio_set_edge(unsigned int gpio, char *edge);
+int gpio_fd_open(unsigned int gpio);
+int gpio_fd_close(int fd);
+int gpio_omap_mux_setup(const char *omap_pin0_name, const char *mode);
+
+#endif /* SIMPLEGPIO_H_ */
\ No newline at end of file
index f1084af..ef834a1 100644 (file)
@@ -1,12 +1,13 @@
 # Makefile for server software
 CXX = gcc
 FLAGS = -std=c99 -Wall -Werror -pedantic -g
-LIB = -lpthread -lfcgi -lssl
-OBJ = log.o sensor.o fastcgi.o main.o
+LIB = -lpthread -lfcgi -lssl -lcrypto
+OBJ = log.o sensor.o fastcgi.o thread.o main.o
 RM = rm -f
 
 BIN = server
 
+
 $(BIN) : $(OBJ)
        $(CXX) $(FLAGS) -o $(BIN) $(OBJ) $(LIB)
 
index 5f71f9f..9b73de9 100644 (file)
 #include <pthread.h>
 #include <unistd.h>
 #include <assert.h>
+#include <sys/time.h>
 
 #include "log.h"
 #include "fastcgi.h"
+#include "thread.h"
 
 #endif //_COMMON_H
index 4fc3742..49bf197 100644 (file)
@@ -11,9 +11,9 @@
 #include <time.h>
 
 #include "common.h"
-#include "fastcgi.h"
 #include "sensor.h"
 #include "log.h"
+#include "options.h"
 
 #define LOGIN_TIMEOUT 180
 
@@ -170,6 +170,16 @@ void FCGI_BeginJSON(FCGIContext *context, StatusCodes status_code)
        printf("{\r\n");
        printf("\t\"module\" : \"%s\"", context->current_module);
        FCGI_JSONLong("status", status_code);
+
+       // Jeremy: Should we include a timestamp in the JSON; something like this?
+       double start_time = g_options.start_time.tv_sec + 1e-6*(g_options.start_time.tv_usec);
+       struct timeval now;
+       gettimeofday(&now, NULL);
+       double current_time = now.tv_sec + 1e-6*(now.tv_usec);
+       FCGI_JSONDouble("start_time", start_time);
+       FCGI_JSONDouble("current_time", current_time);
+       FCGI_JSONDouble("running_time", current_time - start_time);
+       
 }
 
 /**
@@ -203,6 +213,16 @@ void FCGI_JSONDouble(const char *key, double value)
        printf(",\r\n\t\"%s\" : %f", key, value);
 }
 
+/**
+ * Similar to FCGI_JsonPair except for boolean values.
+ * @param key The key of the JSON entry
+ * @param value The value associated with the key
+ */
+void FCGI_JSONBool(const char *key, bool value)
+{
+       printf(",\r\n\t\"%s\" : %s", key, value ? "true" : "false");
+}
+
 /**
  * Begins a JSON entry by writing the key. To be used in conjunction
  * with FCGI_JsonValue.
@@ -248,7 +268,7 @@ void FCGI_RejectJSON(FCGIContext *context)
        FCGI_BeginJSON(context, STATUS_ERROR);
        FCGI_JSONPair("description", "Invalid request");
        FCGI_JSONLong("responsenumber", context->response_number);
-       FCGI_JSONPair("params", getenv("DOCUMENT_URI_LOCAL"));
+       FCGI_JSONPair("params", getenv("QUERY_STRING"));
        FCGI_JSONPair("host", getenv("SERVER_HOSTNAME"));
        FCGI_JSONPair("user", getenv("REMOTE_USER"));
        FCGI_JSONPair("ip", getenv("REMOTE_ADDR"));
@@ -258,12 +278,28 @@ void FCGI_RejectJSON(FCGIContext *context)
 /**
  * Main FCGI request loop that receives/responds to client requests.
  * @param data Reserved.
+ * @returns NULL (void* required for consistency with pthreads, although at the moment this runs in the main thread anyway)
+ * TODO: Get this to exit with the rest of the program!
  */ 
-void FCGI_RequestLoop (void *data)
+void FCGI_RequestLoop (void *data)
 {
        FCGIContext context = {0};
        
+       Log(LOGDEBUG, "First request...");
+       //TODO: The FCGI_Accept here is blocking. 
+       //              That means that if another thread terminates the program, this thread
+       //               will not terminate until the next request is made.
        while (FCGI_Accept() >= 0) {
+
+               if (Thread_Runstate() != RUNNING)
+               {
+                       //TODO: Yeah... deal with this better :P
+                       Log(LOGERR, "FIXME; FCGI gets request after other threads have finished.");
+                       printf("Content-type: text/plain\r\n\r\n+++OUT OF CHEESE ERROR+++\n");
+                       break;
+               }
+               
+               Log(LOGDEBUG, "Got request #%d", context.response_number);
                ModuleHandler module_handler = NULL;
                char module[BUFSIZ], params[BUFSIZ];
                
@@ -292,7 +328,15 @@ void FCGI_RequestLoop (void *data)
                        strncat(module, " [unknown]", BUFSIZ);
                        FCGI_RejectJSON(&context);
                }
-               
                context.response_number++;
+
+               Log(LOGDEBUG, "Waiting for request #%d", context.response_number);
        }
+
+       Log(LOGDEBUG, "Thread exiting.");
+       Thread_QuitProgram(false);
+       // NOTE: Don't call pthread_exit, because this runs in the main thread. Just return.
+       return NULL;
+
+       
 }
index e9db8ba..1efdef7 100644 (file)
@@ -22,11 +22,12 @@ extern void FCGI_BeginJSON(FCGIContext *context, StatusCodes status_code);
 extern void FCGI_JSONPair(const char *key, const char *value);
 extern void FCGI_JSONLong(const char *key, long value);
 extern void FCGI_JSONDouble(const char *key, double value);
+extern void FCGI_JSONBool(const char *key, bool value);
 extern void FCGI_JSONKey(const char *key);
 extern void FCGI_JSONValue(const char *format, ...);
 extern void FCGI_EndJSON();
 extern void FCGI_RejectJSON(FCGIContext *context);
-extern void FCGI_RequestLoop (void *data);
+extern void FCGI_RequestLoop (void *data);
 
 #endif
 
index f7e39bc..7b67043 100644 (file)
@@ -17,6 +17,9 @@ static const char * unspecified_funct = "???";
 
 // --- Function implementations --- //
 
+//TODO: Migrate to syslog (shouldn't be too hard; these functions basically do what syslog does)
+//             Note that we will want to have a seperate log as well as syslog; give the user the option to view the log using the GUI
+
 /**
  * Print a message to stderr
  * @param level - Specify how severe the message is.
index bfd5300..ec21a25 100644 (file)
@@ -13,7 +13,6 @@
 
 // --- Variable definitions --- //
 Options g_options; // options passed to program through command line arguments
-Sensor g_sensors[NUMSENSORS]; // sensors array
 
 // --- Function definitions --- //
 
@@ -26,6 +25,7 @@ void ParseArguments(int argc, char ** argv)
 {
        g_options.program = argv[0]; // program name
        g_options.verbosity = LOGDEBUG; // default log level
+       gettimeofday(&(g_options.start_time), NULL); // Start time
        Log(LOGDEBUG, "Called as %s with %d arguments.", g_options.program, argc);
 }
 
@@ -35,12 +35,14 @@ void ParseArguments(int argc, char ** argv)
  */
 //TODO: Something that gets massively annoying with threads is that you can't predict which one gets the signal
 // There are ways to deal with this, but I can't remember them
+// Probably sufficient to just call Thread_QuitProgram here
 void SignalHandler(int signal)
 {
        // At the moment just always exit.
        // Call `exit` so that Cleanup will be called to... clean up.
        Log(LOGWARN, "Got signal %d (%s). Exiting.", signal, strsignal(signal));
-       exit(signal);
+       Thread_QuitProgram(false);
+       //exit(signal);
 }
 
 /**
@@ -58,20 +60,31 @@ void Cleanup()
  * @param argc - Num args
  * @param argv - Args
  * @returns 0 on success, error code on failure
+ * NOTE: NEVER USE exit(3)! Instead call Thread_QuitProgram
  */
 int main(int argc, char ** argv)
 {
        ParseArguments(argc, argv);
 
-       // start sensor threads
-       for (int i = 0; i < NUMSENSORS; ++i)
+       // signal handler
+       //TODO: Make this work
+       /*
+       int signals[] = {SIGINT, SIGSEGV, SIGTERM};
+       for (int i = 0; i < sizeof(signals)/sizeof(int); ++i)
        {
-               Sensor_Init(g_sensors+i, i);
-               pthread_create(&(g_sensors[i].thread), NULL, Sensor_Main, (void*)(g_sensors+i));
+               signal(signals[i], SignalHandler);
        }
+       */
+       Sensor_Spawn();
 
        // run request thread in the main thread
        FCGI_RequestLoop(NULL);
+
+       // Join the dark side, Luke
+       // *cough*
+       // Join the sensor threads
+       Sensor_Join();
+       Cleanup();
        return 0;
 }
 
index 297acf4..a15e14a 100644 (file)
@@ -14,6 +14,10 @@ typedef struct
        const char * program;
        /** Determines at what level log messages are shown **/
        int verbosity;
+       /** Time at which program begins to run **/
+       struct timeval start_time;
+       /** Time at which program exits **/
+       struct timeval end_time;
 
 } Options;
 
index 756f9cf..11f2e34 100755 (executable)
@@ -1,3 +1,5 @@
 #!/bin/bash
 # Use this to quickly test run the server in valgrind
-spawn-fcgi -p9005 -n /usr/bin/valgrind ./server
+#spawn-fcgi -p9005 -n ./valgrind.sh
+# Use this to run the server normally
+spawn-fcgi -p9005 -n ./server
index 6222510..34c9310 100644 (file)
@@ -9,34 +9,44 @@
 #include "sensor.h"
 #include <math.h>
 
+/** Array of sensors, initialised by Sensor_Init **/
+static Sensor g_sensors[NUMSENSORS]; //global to this file
+
 /**
  * Read a data value from a sensor; block until value is read
  * @param sensor_id - The ID of the sensor
- * @returns The current value of the sensor
+ * @param d - DataPoint to set
+ * @returns NULL on error, otherwise d
  */
-DataPoint GetData(int sensor_id)
+DataPoint * GetData(int sensor_id, DataPoint * d)
 {
        // switch based on the sensor_id at the moment for testing;
        // might be able to just directly access ADC from sensor_id?
        //TODO: Implement for real sensors
 
-       DataPoint d;
-       //TODO: Deal with time stamps properly
-       static int count = 0;
-       d.time = count++;
+       
+       //TODO: We should ensure the time is *never* allowed to change on the server if we use gettimeofday
+       //              Another way people might think of getting the time is to count CPU cycles with clock()
+       //              But this will not work because a) CPU clock speed may change on some devices (RPi?) and b) It counts cycles used by all threads
+       gettimeofday(&(d->time_stamp), NULL);
+       
        switch (sensor_id)
        {
                case SENSOR_TEST0:
-                       d.value = count;
+               {
+                       static int count = 0;
+                       d->value = count++;
                        break;
+               }
                case SENSOR_TEST1:
-                       d.value = (float)(rand() % 100) / 100;
+                       d->value = (float)(rand() % 100) / 100;
                        break;
                default:
                        Fatal("Unknown sensor id: %d", sensor_id);
                        break;
        }       
        usleep(100000); // simulate delay in sensor polling
+
        return d;
 }
 
@@ -57,16 +67,15 @@ void Destroy(Sensor * s)
  * Initialise a sensor
  * @param s - Sensor to initialise
  */
-void Sensor_Init(Sensor * s, int id)
+void Init(Sensor * s, int id)
 {
        s->write_index = 0;
        s->read_offset = 0;
        s->id = id;
 
-       #define FILENAMESIZE BUFSIZ
+       #define FILENAMESIZE 3
        char filename[FILENAMESIZE];
-       //if (s->id >= pow(10, FILENAMESIZE))
-       if (false)
+       if (s->id >= pow(10, FILENAMESIZE))
        {
                Fatal("Too many sensors! FILENAMESIZE is %d; increase it and recompile.", FILENAMESIZE);
        }
@@ -81,6 +90,9 @@ void Sensor_Init(Sensor * s, int id)
 }
 
 
+
+
+
 /**
  * Run the main sensor polling loop
  * @param arg - Cast to Sensor* - Sensor that the thread will handle
@@ -90,7 +102,7 @@ void * Sensor_Main(void * arg)
 {
        Sensor * s = (Sensor*)(arg);
 
-       while (true) //TODO: Exit condition
+       while (Thread_Runstate() == RUNNING) //TODO: Exit condition
        {
                // The sensor will write data to a buffer until it is full
                // Then it will open a file and dump the buffer to the end of it.
@@ -102,7 +114,11 @@ void * Sensor_Main(void * arg)
 
                while (s->write_index < SENSOR_DATABUFSIZ)
                {
-                       s->buffer[s->write_index] = GetData(s->id);
+                       DataPoint * d = &(s->buffer[s->write_index]);
+                       if (GetData(s->id, d) == NULL)
+                       {
+                               Fatal("Error collecting data");
+                       }
                        s->write_index += 1;
                }
 
@@ -110,6 +126,8 @@ void * Sensor_Main(void * arg)
 
                // CRITICAL SECTION (no threads should be able to read/write the file at the same time)
                pthread_mutex_lock(&(s->mutex));
+                       //TODO: Valgrind complains about this fseek: "Syscall param write(buf) points to uninitialised byte(s)"
+                       //              Not sure why, but we should find out and fix it.
                        fseek(s->file, 0, SEEK_END);
                        int amount_written = fwrite(s->buffer, sizeof(DataPoint), SENSOR_DATABUFSIZ, s->file);
                        if (amount_written != SENSOR_DATABUFSIZ)
@@ -123,7 +141,8 @@ void * Sensor_Main(void * arg)
                s->write_index = 0; // reset position in buffer
                
        }
-       return NULL;
+       Log(LOGDEBUG, "Thread for sensor %d exits", s->id);
+       return NULL; 
 }
 
 /**
@@ -146,6 +165,27 @@ int Sensor_Query(Sensor * s, DataPoint * buffer, int bufsiz)
        return amount_read;
 }
 
+/**
+ * Get a Sensor given an ID string
+ * @param id_str ID string
+ * @returns Sensor* identified by the string; NULL on error
+ */
+Sensor * Sensor_Identify(const char * id_str)
+{
+       char * end;
+       // Parse string as integer
+       int id = strtol(id_str, &end, 10);
+       if (*end != '\0')
+       {
+               return NULL;
+       }
+       // Bounds check
+       if (id < 0 || id > NUMSENSORS)
+               return NULL;
+
+       return g_sensors+id;
+}
+
 /**
  * Handle a request to the sensor module
  * @param context - The context to work in
@@ -157,15 +197,14 @@ void Sensor_Handler(FCGIContext *context, char * params)
        StatusCodes status = STATUS_OK;
        const char * key; const char * value;
 
-       int sensor_id = SENSOR_NONE;
+       Sensor * sensor = NULL;
 
        while ((params = FCGI_KeyPair(params, &key, &value)) != NULL)
        {
                Log(LOGDEBUG, "Got key=%s and value=%s", key, value);
                if (strcmp(key, "id") == 0)
                {
-                       char *end;
-                       if (sensor_id != SENSOR_NONE)
+                       if (sensor != NULL)
                        {
                                Log(LOGERR, "Only one sensor id should be specified");
                                status = STATUS_ERROR;
@@ -177,11 +216,11 @@ void Sensor_Handler(FCGIContext *context, char * params)
                                status = STATUS_ERROR;
                                break;
                        }
-                       //TODO: Use human readable sensor identifier string for API?
-                       sensor_id = strtol(value, &end, 10);
-                       if (*end != '\0')
+
+                       sensor = Sensor_Identify(value);
+                       if (sensor == NULL)
                        {
-                               Log(LOGERR, "Sensor id not an integer; %s", value);
+                               Log(LOGERR, "Invalid sensor id: %s", value);
                                status = STATUS_ERROR;
                                break;
                        }
@@ -194,14 +233,9 @@ void Sensor_Handler(FCGIContext *context, char * params)
                }               
        }
 
-       if (sensor_id == SENSOR_NONE)
-       {
-               Log(LOGERR, "No sensor id specified");
-               status = STATUS_ERROR;
-       }
-       else if (sensor_id >= NUMSENSORS || sensor_id < 0)
+       if (status != STATUS_ERROR && sensor == NULL)
        {
-               Log(LOGERR, "Invalid sensor id %d", sensor_id);
+               Log(LOGERR, "No valid sensor id given");
                status = STATUS_ERROR;
        }
 
@@ -211,17 +245,21 @@ void Sensor_Handler(FCGIContext *context, char * params)
        }
        else
        {
+
                FCGI_BeginJSON(context, status);        
                FCGI_JSONPair(key, value); // should spit back sensor ID
                //Log(LOGDEBUG, "Call Sensor_Query...");
-               int amount_read = Sensor_Query(&(g_sensors[sensor_id]), buffer, SENSOR_QUERYBUFSIZ);
+               int amount_read = Sensor_Query(sensor, buffer, SENSOR_QUERYBUFSIZ);
                //Log(LOGDEBUG, "Read %d DataPoints", amount_read);
                //Log(LOGDEBUG, "Produce JSON response");
                FCGI_JSONKey("data");
                FCGI_JSONValue("[");
                for (int i = 0; i < amount_read; ++i)
                {
-                       FCGI_JSONValue("[%f, %f]", buffer[i].time, buffer[i].value);
+                       //TODO: Consider; is it better to give both tv_sec and tv_usec to the client seperately, instead of combining here?
+                       //NOTE: Must always use doubles; floats get rounded!
+                       double time = buffer[i].time_stamp.tv_sec + 1e-6*(buffer[i].time_stamp.tv_usec);
+                       FCGI_JSONValue("[%f, %f]", time, buffer[i].value);
                        if (i+1 < amount_read)
                                FCGI_JSONValue(",");
                }
@@ -230,3 +268,32 @@ void Sensor_Handler(FCGIContext *context, char * params)
                FCGI_EndJSON(); 
        }
 }
+
+/**
+ * Setup Sensors, start Sensor polling thread(s)
+ */
+void Sensor_Spawn()
+{
+       // start sensor threads
+       for (int i = 0; i < NUMSENSORS; ++i)
+       {
+               Init(g_sensors+i, i);
+               pthread_create(&(g_sensors[i].thread), NULL, Sensor_Main, (void*)(g_sensors+i));
+       }
+}
+
+/**
+ * Quit Sensor loops
+ */
+void Sensor_Join()
+{
+       if (!Thread_Runstate())
+       {
+               Fatal("This function should not be called before Thread_QuitProgram");
+       }
+       for (int i = 0; i < NUMSENSORS; ++i)
+       {
+               pthread_join(g_sensors[i].thread, NULL);
+               Destroy(g_sensors+i);
+       }
+}
index 4009e5a..a259036 100644 (file)
@@ -20,7 +20,7 @@
 typedef struct
 {
        /** Time at which data was taken **/
-       float time;
+       struct timeval time_stamp; //TODO: Consider; use float instead?
        /** Value of data **/
        float value;
 } DataPoint;
@@ -29,7 +29,7 @@ typedef struct
 typedef struct
 {
        /** ID number of the sensor **/
-       enum {SENSOR_TEST0=0, SENSOR_TEST1=1, SENSOR_NONE} id;
+       enum {SENSOR_TEST0=0, SENSOR_TEST1=1} id;
        /** Buffer to store data from the sensor **/
        DataPoint buffer[SENSOR_DATABUFSIZ];
        /** Index of last point written in the data buffer **/
@@ -46,10 +46,10 @@ typedef struct
        
 } Sensor;
 
-/** Array of Sensors **/
-extern Sensor g_sensors[];
 
-extern void Sensor_Init(Sensor * s, int id); // Initialise sensor
+
+extern void Sensor_Spawn(); // Initialise sensor
+extern void Sensor_Join(); //Join sensor threads
 extern void * Sensor_Main(void * args); // main loop for sensor thread; pass a Sensor* cast to void*
 
 extern int Sensor_Query(Sensor * s, DataPoint * buffer, int bufsiz); // fill buffer with sensor data
diff --git a/server/thread.c b/server/thread.c
new file mode 100644 (file)
index 0000000..57473ea
--- /dev/null
@@ -0,0 +1,62 @@
+/**
+ * @file thread.c
+ * @purpose Implementation of thread control
+ */
+
+#include "thread.h"
+#include "options.h"
+
+pthread_mutex_t mutex_runstate = PTHREAD_MUTEX_INITIALIZER;
+Runstate runstate = RUNNING;
+
+/**
+ * Set the runstate, causing all threads to exit when they next check Thread_Runstate
+ * Repeated calls to this function have no effect on the runstate.
+ * @param error - Set to true to indicate an error occured
+ */
+void Thread_QuitProgram(bool error)
+{
+       if (runstate != RUNNING)
+       {
+               Log(LOGNOTE, "Called when program is not running; runstate = %d", runstate);
+               return;
+       }
+
+
+       Log(LOGNOTE, "Program will quit; error = %d", (int)error);
+
+       //CRITICAL SECTION - We do NOT want multiple threads editing the runstate at the same time!
+       pthread_mutex_lock(&mutex_runstate);
+       if (error)
+               runstate = QUIT_ERROR;
+       else
+               runstate = QUIT;
+       
+       gettimeofday(&g_options.end_time, NULL);
+       pthread_mutex_unlock(&mutex_runstate);
+       // End critical section
+}
+
+/**
+ * Check the runstate; to be called periodically by all threads.
+ * This function will call Thread_QuitProgram and change the Runstate there is an exit condition detected.
+ */
+Runstate Thread_Runstate()
+{
+       //TODO: Add real exit conditions; for testing purposes, set a timeout
+       /*
+       struct timeval time;
+       gettimeofday(&time, NULL);
+       Log(LOGDEBUG, "It has been %d seconds since program started.", time.tv_sec - g_options.start_time.tv_sec);
+       if (time.tv_sec - g_options.start_time.tv_sec > 3)
+       {
+               Thread_QuitProgram(false);
+       }
+       */
+       
+       // Just reading the runstate doesn't really require a mutex
+       // The worst case: Another thread alters the runstate before this thread gets the result; this thread thinks the program is still running
+       // In that case, the thread will run an extra cycle of its loop and *then* exit. Since the runstate can only be changed once.
+       // We could put a mutex here anyway, but it will have an impact on how fast the loops can run.
+       return runstate;
+}
diff --git a/server/thread.h b/server/thread.h
new file mode 100644 (file)
index 0000000..14ae785
--- /dev/null
@@ -0,0 +1,21 @@
+/**
+ * @file thread.h
+ * @purpose Declarations for thread control related functions and variables
+ */
+
+#ifndef _THREAD_H
+#define _THREAD_H
+
+#include "common.h"
+#include <pthread.h>
+
+typedef enum {QUIT, QUIT_ERROR, RUNNING} Runstate;
+
+/** Determine if the thread should exit; to be called periodically **/
+extern Runstate Thread_Runstate();
+/** Tell all other threads (when they call Thread_ExitCondition) to exit. Repeated calls have no effect. **/
+extern void Thread_QuitProgram(bool error);
+
+#endif //_THREAD_H
+
+//EOF
diff --git a/server/valgrind.sh b/server/valgrind.sh
new file mode 100755 (executable)
index 0000000..2a50865
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/bash
+valgrind --leak-check=full ./server
diff --git a/testing/fastcgi-approach/-etc-nginx/fastcgi_params b/testing/fastcgi-approach/-etc-nginx/fastcgi_params
deleted file mode 100644 (file)
index 51aa692..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-fastcgi_param  QUERY_STRING            $query_string;
-fastcgi_param  REQUEST_METHOD          $request_method;
-fastcgi_param  CONTENT_TYPE            $content_type;
-fastcgi_param  CONTENT_LENGTH          $content_length;
-
-fastcgi_param  SCRIPT_FILENAME         $request_filename;
-fastcgi_param  SCRIPT_NAME             $fastcgi_script_name;
-fastcgi_param  REQUEST_URI             $request_uri;
-fastcgi_param  DOCUMENT_URI            $document_uri;
-fastcgi_param  DOCUMENT_ROOT           $document_root;
-fastcgi_param  SERVER_PROTOCOL         $server_protocol;
-
-fastcgi_param  GATEWAY_INTERFACE       CGI/1.1;
-fastcgi_param  SERVER_SOFTWARE         nginx/$nginx_version;
-fastcgi_param  SERVER_HOSTNAME         mctxsoft;
-
-fastcgi_param  REMOTE_ADDR             $remote_addr;
-fastcgi_param  REMOTE_PORT             $remote_port;
-fastcgi_param  REMOTE_USER             $remote_user;
-fastcgi_param  SERVER_ADDR             $server_addr;
-fastcgi_param  SERVER_PORT             $server_port;
-fastcgi_param  SERVER_NAME             $server_name;
-
-fastcgi_param  HTTPS                   $https;
-
-# PHP only, required if PHP was built with --enable-force-cgi-redirect
-fastcgi_param  REDIRECT_STATUS         200;
diff --git a/testing/fastcgi-approach/-etc-nginx/sites-enabled/default b/testing/fastcgi-approach/-etc-nginx/sites-enabled/default
deleted file mode 100644 (file)
index 541f6d1..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-# You may add here your
-# server {
-#      ...
-# }
-# statements for each of your virtual hosts to this file
-
-##
-# You should look at the following URL's in order to grasp a solid understanding
-# of Nginx configuration files in order to fully unleash the power of Nginx.
-# http://wiki.nginx.org/Pitfalls
-# http://wiki.nginx.org/QuickStart
-# http://wiki.nginx.org/Configuration
-#
-# Generally, you will want to move this file somewhere, and start with a clean
-# file but keep this around for reference. Or just disable in sites-enabled.
-#
-# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
-##
-
-server {
-       listen 80;
-       listen [::]:80 default_server ipv6only=on;
-
-       root /usr/share/nginx/html;
-       index index.php index.html index.htm;
-
-       # Make site accessible from http://localhost/
-       server_name localhost;
-
-       location / {
-               # First attempt to serve request as file, then
-               # as directory, then fall back to displaying a 404.
-               try_files $uri $uri/ =404;
-               # Uncomment to enable naxsi on this location
-               # include /etc/nginx/naxsi.rules
-       }
-
-       # Only for nginx-naxsi used with nginx-naxsi-ui : process denied requests
-       #location /RequestDenied {
-       #       proxy_pass http://127.0.0.1:8080;    
-       #}
-
-       #error_page 404 /404.html;
-
-       # redirect server error pages to the static page /50x.html
-       #
-       #error_page 500 502 503 504 /50x.html;
-       #location = /50x.html {
-       #       root /usr/share/nginx/html;
-       #}
-
-       # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
-       #
-       location ~ \.php$ {
-               fastcgi_split_path_info ^(.+\.php)(/.+)$;
-       #       # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
-       #
-       #       # With php5-cgi alone:
-       #       fastcgi_pass 127.0.0.1:9000;
-       #       # With php5-fpm:
-               fastcgi_pass unix:/var/run/php5-fpm.sock;
-               fastcgi_index index.php;
-               include fastcgi_params;
-       }
-
-       # deny access to .htaccess files, if Apache's document root
-       # concurs with nginx's one
-       #
-       location ~ /\.ht {
-               deny all;
-       }
-       
-       #Login area
-       location ^~ /api/login {
-               auth_basic "Restricted Access";
-               auth_basic_user_file /usr/share/nginx/access/.htpasswd;
-       
-               fastcgi_pass 127.0.0.1:9005;
-               fastcgi_param DOCUMENT_URI_LOCAL login;
-               include fastcgi_params;
-       }
-       
-       #MCTX API
-       location /api {
-               location ~ ^/api/?([^?]*) {
-                       fastcgi_pass 127.0.0.1:9005;
-                       fastcgi_param DOCUMENT_URI_LOCAL $1;
-                       include fastcgi_params;
-               }
-       }
-}
-
-
-# another virtual host using mix of IP-, name-, and port-based configuration
-#
-#server {
-#      listen 8000;
-#      listen somename:8080;
-#      server_name somename alias another.alias;
-#      root html;
-#      index index.html index.htm;
-#
-#      location / {
-#              try_files $uri $uri/ =404;
-#      }
-#}
-
-
-# HTTPS server
-#
-#server {
-#      listen 443;
-#      server_name localhost;
-#
-#      root html;
-#      index index.html index.htm;
-#
-#      ssl on;
-#      ssl_certificate cert.pem;
-#      ssl_certificate_key cert.key;
-#
-#      ssl_session_timeout 5m;
-#
-#      ssl_protocols SSLv3 TLSv1;
-#      ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
-#      ssl_prefer_server_ciphers on;
-#
-#      location / {
-#              try_files $uri $uri/ =404;
-#      }
-#}

UCC git Repository :: git.ucc.asn.au