Merge pull request #46 from dputtick/dev

Udev rules, autosleep, bugfixes
pull/61/head
Raphaël Vinot 2017-01-25 09:15:33 +01:00 committed by GitHub
commit 216a9cf426
18 changed files with 188 additions and 500 deletions

View File

@ -14,18 +14,21 @@ And the linux way is in the command line, via dd (see in copy_to_final.sh)
If you'd like to contribute to the project or build the image yourself, see If you'd like to contribute to the project or build the image yourself, see
[contributing](CONTRIBUTING.md) and the [setup readme](README_setup.md). [contributing](CONTRIBUTING.md) and the [setup readme](README_setup.md).
This is a work in progress - contributions are welcome.
Why/What Why/What
======== ========
This project aims to be useful when you get/find a USB key that you can't trust, This project aims to be useful when you get/find a USB key that you can't trust,
and you want to have a look at its contents without taking the risk of plugging it into your and you want to look at its contents without taking the risk of plugging it into
main computer directly. your computer directly.
This is a work in progress - contributions are welcome: CIRCLean is currently tested to work with USB keys that have FAT32, NTFS, or
ext2/3/4 filesystems. Currently, exFAT is not supported due to lack of support for
this format in pmount. The vast majority of USB keys will be FAT32 or NTFS.
The content of the first key will be copied or/and converted to the second key The content of the untrusted key will be copied or/and converted to the second
following these rules (based on the mime type, as determined by libmagic): (blank) key following these rules (based on the mime type as determined bylibmagic):
- Direct copy of: - Direct copy of:
- Plain text files (mime type: text/*) - Plain text files (mime type: text/*)
- Audio files (mime type: audio/*) - Audio files (mime type: audio/*)

View File

@ -1,2 +0,0 @@
led: led.c
gcc -ggdb -o led led.c

View File

@ -1,81 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
/* GPIO registers address */
#define BCM2708_PERI_BASE 0x20000000
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
#define BLOCK_SIZE (256)
/* GPIO setup macros. Always use GPIO_IN(x) before using GPIO_OUT(x) or GPIO_ALT(x,y) */
#define GPIO_IN(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define GPIO_OUT(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
#define GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
#define GPIO_SET(g) *(gpio+7) = 1<<(g) /* sets bit which are 1, ignores bit which are 0 */
#define GPIO_CLR(g) *(gpio+10) = 1<<(g) /* clears bit which are 1, ignores bit which are 0 */
#define GPIO_LEV(g) (*(gpio+13) >> (g)) & 0x00000001
#define GPIO_4 4
int mem_fd;
void *gpio_map;
volatile uint32_t *gpio;
int main(int argc, char* argv[])
{
int ret;
int i;
/* open /dev/mem */
mem_fd = open("/dev/mem", O_RDWR|O_SYNC);
if (mem_fd == -1) {
perror("Cannot open /dev/mem");
exit(1);
}
/* mmap GPIO */
gpio_map = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, GPIO_BASE);
if (gpio_map == MAP_FAILED) {
perror("mmap() failed");
exit(1);
}
/* Always use volatile pointer! */
gpio = (volatile uint32_t *)gpio_map;
GPIO_IN(GPIO_4); /* must use GPIO_IN before we can use GPIO_OUT */
GPIO_OUT(GPIO_4);
//Turn on led
while (1) {
//printf("Enable LED\n");
GPIO_SET(GPIO_4);
usleep(1000000);
//printf("Disable GPIO\n"); // Does not seem to work?
//GPIO_CLR(GPIO_4);
//usleep(1000000);
}
/* Free up ressources */
/* munmap GPIO */
ret = munmap(gpio_map, BLOCK_SIZE);
if (ret == -1) {
perror("munmap() failed");
exit(1);
}
/* close /dev/mem */
ret = close(mem_fd);
if (ret == -1) {
perror("Cannot close /dev/mem");
exit(1);
}
return EXIT_SUCCESS;
}

View File

@ -1,5 +1,5 @@
# /etc/pmount.allow # /etc/pmount.allow
# pmount will allow users to additionally mount all devices that are # pmount will allow users to additionally mount all devices that are
# listed here. # listed here.
/dev/sdb1 /dev/sdb*
/dev/sda* /dev/sda*

View File

@ -11,27 +11,28 @@
# #
# By default this script does nothing. # By default this script does nothing.
# #
# The above are the default comments for rc.local. For Circlean, rc.local has ## The above are the default comments for rc.local. For Circlean, rc.local has
# been modified to start the grooming process on boot. ## been modified to start the grooming process after booting.
clean(){ clean(){
echo 'Rc Local done, quit.' echo "GROOMER: rc.local done, shutting down."
/sbin/shutdown -P -h now /sbin/shutdown -P -h now
} }
# Print the IP address echo "GROOMER: end of boot, running rc.local."
_IP=$(hostname -I) || true
if [ "$_IP" ]; then # Print the IP address (this doesn't work currently?)
printf "My IP address is %s\n" "$_IP" # _IP=$(hostname -I) || true
fi # if [ "$_IP" ]; then
# printf "My IP address is %s\n" "$_IP"
# fi
if [ -e /dev/sda ]; then if [ -e /dev/sda ]; then
if [ -e /dev/sdb ]; then if [ -e /dev/sdb ]; then
# avoid possible misuse # Avoid possible misuse - turn off eth0 (ethernet port)
/sbin/ifconfig eth0 down /sbin/ifconfig eth0 down
trap clean EXIT TERM INT trap clean EXIT TERM INT
cd /opt/groomer cd /opt/groomer
/usr/sbin/led &
./init.sh ./init.sh
fi fi
fi fi

View File

@ -0,0 +1,3 @@
# The purpose of this rules file is to ensure that the top left usb port and its partitions have a symlink to /dev/source_key[num], and the other ports to /dev/dest_key[num]
KERNEL=="sd*", KERNELS=="1-1.2", SUBSYSTEMS=="usb", SYMLINK+="source_key%n"
KERNEL=="sd*", KERNELS=="1-1.[3-5]", SUBSYSTEMS=="usb", SYMLINK+="dest_key%n"

View File

@ -1,2 +1,5 @@
# This udev rule is designed to make the hardware appear more like the actual raspi hardware when emulating in Qemu. You might have to change sdc to sda or sdb depending on where the filesystem you are emulating is available from in /dev/.
# See http://pub.phyks.me/respawn/mypersonaldata/public/2014-05-20-11-08-01/ for more info.
KERNEL=="sdc", SYMLINK+="mmcblk0" KERNEL=="sdc", SYMLINK+="mmcblk0"
KERNEL=="sdc?", SYMLINK+="mmcblk0p%n", KERNEL=="sdc?", SYMLINK+="mmcblk0p%n",
#KERNEL=="sdc2", SYMLINK+="root"

View File

@ -0,0 +1,26 @@
USERNAME="kitten"
ID=`/usr/bin/id -u`
# Paths used in multiple scripts
SRC="src"
DEV_SRC="/dev/source_key"
SRC_MNT="/media/src"
DST="dst"
DEV_DST="/dev/dest_key"
DST_MNT="/media/dst"
TEMP="${DST_MNT}/temp"
ZIPTEMP="${DST_MNT}/ziptemp"
LOGS="${DST_MNT}/logs"
GROOM_LOG="/tmp/groom_log.txt"
MUSIC="/opt/midi/"
# Commands
SYNC="/bin/sync"
TIMIDITY="/usr/bin/timidity"
MOUNT="/bin/mount"
PMOUNT="/usr/bin/pmount -A -s"
PUMOUNT="/usr/bin/pumount"

View File

@ -1,23 +0,0 @@
DEV_SRC='/dev/sda'
DEV_DST='sdb1'
# User allowed to do the following commands without password
USERNAME='kitten'
MUSIC="/opt/midi/"
ID=`/usr/bin/id -u`
# Paths used in multiple scripts
SRC="src"
DST="dst"
TEMP="/media/${DST}/temp"
ZIPTEMP="/media/${DST}/ziptemp"
LOGS="/media/${DST}/logs"
# commands
SYNC='/bin/sync'
TIMIDITY='/usr/bin/timidity'
MOUNT='/bin/mount'
PMOUNT='/usr/bin/pmount -A -s'
PUMOUNT='/usr/bin/pumount'

View File

@ -1,112 +1,75 @@
#!/bin/bash #!/bin/bash
# set -e (exit when a line returns non-0 status) and -x (xtrace) flags
set -e set -e
set -x set -x
source ./constraint.sh # Import constants from config file
source ./config.sh
if ! [ "${ID}" -ge "1000" ]; then if ! [ "${ID}" -ge "1000" ]; then
echo "This script cannot run as root." echo "GROOMER: groomer.sh cannot run as root."
exit exit
fi fi
clean(){ clean(){
echo Cleaning. # Write anything in memory to disk
${SYNC} ${SYNC}
# Cleanup source # Remove temporary files from destination key
pumount ${SRC}
# Cleanup destination
rm -rf ${TEMP} rm -rf ${TEMP}
rm -rf ${ZIPTEMP} rm -rf ${ZIPTEMP}
pumount ${DST}
exit
} }
trap clean EXIT TERM INT trap clean EXIT TERM INT
# De we have a source device # Find the partition names on the device available at /dev/source_key
if [ ! -b ${DEV_SRC} ]; then
echo "Source device (${DEV_SRC}) does not exists."
exit
fi
# Find the partition names on the source device
DEV_PARTITIONS=`ls "${DEV_SRC}"* | grep "${DEV_SRC}[1-9][0-6]*" || true` DEV_PARTITIONS=`ls "${DEV_SRC}"* | grep "${DEV_SRC}[1-9][0-6]*" || true`
if [ -z "${DEV_PARTITIONS}" ]; then if [ -z "${DEV_PARTITIONS}" ]; then
echo "${DEV_SRC} does not have any partitions." echo "GROOMER: ${DEV_SRC} does not have any partitions."
exit exit
fi fi
# Do we have a destination device
if [ ! -b "/dev/${DEV_DST}" ]; then
echo "Destination device (/dev/${DEV_DST}) does not exists."
exit
fi
# mount and prepare destination device
if ${MOUNT}|grep ${DST}; then
${PUMOUNT} ${DST} || true
fi
# uid= only works on a vfat FS. What should wedo if we get an ext* FS ?
${PMOUNT} -w ${DEV_DST} ${DST}
if [ ${?} -ne 0 ]; then
echo "Unable to mount /dev/${DEV_DST} on /media/${DST}"
exit
else
echo "Target USB device (/dev/${DEV_DST}) mounted at /media/${DST}"
rm -rf "/media/${DST}/FROM_PARTITION_"*
# prepare temp dirs and make sure it's empty
mkdir -p "${TEMP}"
mkdir -p "${ZIPTEMP}"
mkdir -p "${LOGS}"
rm -rf "${TEMP}/"*
rm -rf "${ZIPTEMP}/"*
rm -rf "${LOGS}/"*
fi
# Groom da kitteh!
# Find the FS types
# lsblk -n -o name,fstype,mountpoint,label,uuid -r
PARTCOUNT=1 PARTCOUNT=1
for partition in ${DEV_PARTITIONS} for partition in ${DEV_PARTITIONS}
do do
# Processing a partition echo "GROOMER: Processing partition ${partition}"
echo "Processing partition: ${partition}" # Unmount anything that is mounted on /media/src
if [ `${MOUNT} | grep -c ${SRC}` -ne 0 ]; then if [ `${MOUNT} | grep -c ${SRC}` -ne 0 ]; then
${PUMOUNT} ${SRC} ${PUMOUNT} ${SRC}
fi fi
# Mount the current partition in write mode
${PMOUNT} -w ${partition} ${SRC} ${PMOUNT} -w ${partition} ${SRC}
ls "/media/${SRC}" | grep -i autorun.inf | xargs -I {} mv "/media/${SRC}"/{} "/media/${SRC}"/DANGEROUS_{}_DANGEROUS || true # Mark any autorun.inf files as dangerous on the source device
ls ${SRC_MNT} | grep -i autorun.inf | xargs -I {} mv "${SRC_MNT}"/{} "{SRC_MNT}"/DANGEROUS_{}_DANGEROUS || true
# Unmount and remount the current partition in read-only mode
${PUMOUNT} ${SRC} ${PUMOUNT} ${SRC}
${PMOUNT} -r ${partition} ${SRC} ${PMOUNT} -r ${partition} ${SRC}
if [ ${?} -ne 0 ]; then if [ ${?} -ne 0 ]; then
echo "Unable to mount ${partition} on /media/${SRC}" # Previous command (mounting current partition) failed
echo "GROOMER: Unable to mount ${partition} on /media/${SRC}"
else else
echo "${partition} mounted at /media/${SRC}" echo "GROOMER: ${partition} mounted at /media/${SRC}"
# Print the filenames on the current partition in a logfile # Put the filenames from the current partition in a logfile
find "/media/${SRC}" -fls "${LOGS}/Content_partition_${PARTCOUNT}.txt" find "/media/${SRC}" -fls "${LOGS}/contents_partition_${PARTCOUNT}.txt"
# create a directory on ${DST} named PARTION_$PARTCOUNT # Create a directory on ${DST} named PARTION_$PARTCOUNT
target_dir="/media/${DST}/FROM_PARTITION_${PARTCOUNT}" target_dir="/media/${DST}/FROM_PARTITION_${PARTCOUNT}"
echo "copying to: ${target_dir}"
mkdir -p "${target_dir}" mkdir -p "${target_dir}"
LOGFILE="${LOGS}/processing.txt" LOGFILE="${LOGS}/processing.txt"
# Run the current partition through filecheck.py
echo "==== Starting processing of /media/${SRC} to ${target_dir}. ====" >> ${LOGFILE} echo "==== Starting processing of /media/${SRC} to ${target_dir}. ====" >> ${LOGFILE}
filecheck.py --source /media/${SRC} --destination ${target_dir} || true filecheck.py --source /media/${SRC} --destination ${target_dir} || true
echo "==== Done with /media/${SRC} to ${target_dir}. ====" >> ${LOGFILE} echo "==== Done with /media/${SRC} to ${target_dir}. ====" >> ${LOGFILE}
# List destination files (recursively) for debugging
ls -lR "${target_dir}" ls -lR "${target_dir}"
fi fi
let PARTCOUNT=`expr $PARTCOUNT + 1` let PARTCOUNT=`expr $PARTCOUNT + 1`
done done
# The cleanup is automatically done in the function clean called when # The cleanup is automatically done in the function clean called when
# the program quits # the program exits

View File

@ -1,26 +1,36 @@
#!/bin/bash #!/bin/bash
# set -e (exit when a line returns non-0 status) and -x (xtrace) flags
set -e set -e
set -x set -x
source ./constraint.sh # Import constants from config file
source ./config.sh
if [ ${ID} -ne 0 ]; then if [ ${ID} -ne 0 ]; then
echo "This script has to be run as root." echo "GROOMER: This script has to be run as root."
exit exit
fi fi
clean(){ clean(){
echo Done, cleaning. echo "GROOMER: cleaning up after init.sh."
${SYNC} ${SYNC}
# Stop the music from playing
kill -9 $(cat /tmp/music.pid) kill -9 $(cat /tmp/music.pid)
rm -f /tmp/music.pid rm -f /tmp/music.pid
} }
trap clean EXIT TERM INT trap clean EXIT TERM INT
# Stop hdmi display from sleeping after a period of time
setterm -powersave off -blank 0
# Start music
./music.sh & ./music.sh &
echo $! > /tmp/music.pid echo $! > /tmp/music.pid
su ${USERNAME} -c ./groomer.sh # List block storage devices for debugging
# Make sure to set tee in append (-a) mode below if you uncomment
# lsblk |& tee ${GROOM_LOG}
su ${USERNAME} -c ./mount_dest.sh |& tee ${GROOM_LOG}

View File

@ -0,0 +1,77 @@
#!/bin/bash
# set -e (exit when a line returns non-0 status) and -x (xtrace) flags
set -e
set -x
# Import constants from config file
source ./config.sh
if ! [ "${ID}" -ge "1000" ]; then
echo "GROOMER: mount_keys.sh cannot run as root."
exit
fi
clean(){
echo "GROOMER: Cleaning up in mount_keys.sh."
# Copy the temporary logfile to the destination key
cp ${GROOM_LOG} "${DST_MNT}/groomer_log_dst.txt"
# Write anything in memory to disk
${SYNC}
# Unmount source and destination
pumount ${SRC}
# Clean up and unmount destination
pumount ${DST}
exit
}
trap clean EXIT TERM INT
# Check that a device is available on /dev/source_key (symlinked to /dev/sda or sdb)
if [ ! -b ${DEV_SRC} ]; then
echo "GROOMER: Source device (${DEV_SRC}) does not exist."
exit
fi
# Check that a device is available on /dev/dest_key (symlinked to /dev/sda or sdb)
if [ ! -b ${DEV_DST} ]; then
echo "GROOMER: Destination device (${DEV_DST}) does not exist."
exit
fi
# If there is already a device mounted on /media/dst, unmount it
if ${MOUNT}|grep ${DST}; then
${PUMOUNT} ${DST} || true
fi
# uid= only works on a vfat FS. What should wedo if we get an ext* FS ?
# What does this ^ comment mean?
# Mount the first partition of DST (/dev/dest_key1)
# pmount automatically mounts on /media/ (at /media/dst in this case).
${PMOUNT} -w "${DEV_DST}1" ${DST}
if [ ${?} -ne 0 ]; then
echo "GROOMER: Unable to mount ${DEV_DST}1 on ${DST_MNT}"
exit
else
echo "GROOMER: Destination USB device (${DEV_DST}1) mounted at ${DST_MNT}"
# Remove any existing "FROM_PARTITION_" directories
rm -rf "/media/${DST}/FROM_PARTITION_"*
# Prepare temp dirs and make sure they're empty if they already exist
mkdir -p "${TEMP}"
mkdir -p "${ZIPTEMP}"
mkdir -p "${LOGS}"
rm -rf "${TEMP}/"*
rm -rf "${ZIPTEMP}/"*
rm -rf "${LOGS}/"*
fi
# Now that destination is mounted and prepared, run the groomer
./groomer.sh

View File

@ -3,7 +3,7 @@
set -e set -e
#set -x #set -x
source ./constraint.sh source ./config.sh
killed(){ killed(){
echo 'Music stopped.' echo 'Music stopped.'

View File

@ -1,2 +0,0 @@
ledBtn: ledBtn.c
gcc -o ledBtn ledBtn.c

View File

@ -1,282 +0,0 @@
/***************************************************************************************/
/* */
/* file : ledBtn.c */
/* */
/* synopsis : */
/* the compiled code should be ran with root privileges to allow for access to */
/* the GPIO pins through direct GPIO register manipulation in C-code. */
/* After initialization, the code update the LEDs status according to the commands */
/* passed on std input (using a pipe). */
/* It also monitors the push-button and triggers a reboot sequence */
/* when it is depressed. */
/* */
/* */
/* This code is based on examples from */
/* http://elinux.org/RPi_Low-level_peripherals#C */
/* How to access GPIO registers from C-code on the Raspberry-Pi, Example program */
/* Dom and Gert, 15-January-2012, Revised: 15-Feb-2013 */
/* */
/* and from Raphael Vinot (CIRCL.lu) */
/* */
/* v 1.00 - 22/02/2015 - initial release (Marc Durvaux) */
/* v 1.10 - 27/02/2015 - added 'z' command for debugging, improved handling of */
/* concateneted command sequences */
/* */
/* */
/* */
/***************************************************************************************/
// Includes
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
// Constant for low-level access to GPIO
#define BCM2708_PERI_BASE 0x20000000
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
#define BLOCK_SIZE (4*1024)
// global variables related to GPIO
int mem_fd ;
void *gpio_map ;
volatile unsigned *gpio ; // I/O access
// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
#define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH
#define GPIO_PULL *(gpio+37) // Pull up/pull down
#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock
// LED and push-button GPIO pin mapping (from schematic)
#define GREEN_LED 17
#define YELLOW_LED 18
#define RED_LED 22
#define PUSHBUTTON 23
// Time tic (in nsec) for loops : 10 ms
#define TIME_TIC 10000000L
// Blink half-period in tics
#define MAX_COUNT 30
// Button long pression threshold
#define LONG_PUSH 300
// forward declaration of functions
void setup_io() ;
void do_reboot() ;
/***************************************************************************************/
//
// main
// input : path and name of the FIFO must be passed as 1st argument
//
int main(int argc, char **argv) {
int fd, nbytes ;
int state, count, repeat_count ;
int Btn_state, Btn_prev_state, Btn_press_count ;
char code ;
state = 0 ; // initialize state variable
count = 0 ; // initialize loop counter
repeat_count = 0 ;
code = 0 ;
setup_io() ; // initialize GPIO pointer and GPIO pins
Btn_state = GET_GPIO( PUSHBUTTON) ; // get push-button initial state
Btn_prev_state = Btn_state ;
Btn_press_count = 0 ;
fd = open(argv[1], O_RDONLY) ;
if (fd < 0) {
perror("open") ;
exit (2) ;
}
while(1) {
Btn_state = GET_GPIO( PUSHBUTTON) ;
if (Btn_state != 0) { // button released
Btn_press_count = 0 ; // reset counter
} else { // button pressed
Btn_press_count++ ;
if (Btn_state != Btn_prev_state) {
//printf("Button pressed!\n");
if (state >= 4) { // final state, immediate reboot
close(fd) ;
do_reboot() ;
}
}
if (Btn_press_count == LONG_PUSH) { // trigger forced reboot
state = 10 ; // LED animation before reboot
repeat_count = 0 ;
}
}
Btn_prev_state = Btn_state ;
nbytes = read(fd, &code, 1) ;
if (nbytes < 0) {
perror("read") ;
exit (2) ;
}
if (nbytes > 0) {
switch (code) { // codes evaluated at every tic
case 'z' : // clear without restart (for debugging)
GPIO_CLR = 1<<GREEN_LED ;
GPIO_CLR = 1<<YELLOW_LED ;
GPIO_CLR = 1<<RED_LED ;
state = 0 ;
break ;
case 'r' : // Ready
GPIO_SET = 1<<GREEN_LED ;
state = 1 ;
break ;
case 'p' : // Processing
GPIO_CLR = 1<<GREEN_LED ;
GPIO_SET = 1<<YELLOW_LED ;
state = 2 ;
break ;
case 'e' : // Error (process aborted)
GPIO_CLR = 1<<GREEN_LED ;
GPIO_CLR = 1<<YELLOW_LED ;
GPIO_SET = 1<<RED_LED ;
state = 6 ;
break ;
case 'c' : // task successfully completed
GPIO_CLR = 1<<YELLOW_LED ;
GPIO_SET = 1<<GREEN_LED ;
state = 4 ;
count = 0 ;
break ;
case 'f' : // file processing successfully completed
GPIO_SET = 1<<GREEN_LED ;
state = 3 ;
count = 0 ;
break ;
} // end switch
}
count++ ;
if (count >= MAX_COUNT) {
count = 0 ;
switch (state) { // states evaluated after MAX_COUNT tics
case 3 : // green LED flash OFF
GPIO_CLR = 1<<GREEN_LED ;
state = 2 ;
break ;
case 4 : // green LED blinks OFF
GPIO_CLR = 1<<GREEN_LED ;
state = 5 ;
break ;
case 5 : // green LED blinks ON
GPIO_SET = 1<<GREEN_LED ;
state = 4 ;
break ;
case 10 : // start LED animation before reboot
GPIO_SET = 1<<GREEN_LED ;
GPIO_SET = 1<<YELLOW_LED ;
GPIO_SET = 1<<RED_LED ;
state = 11 ;
break ;
case 11 : // LED animation before reboot
GPIO_CLR = 1<<GREEN_LED ;
GPIO_CLR = 1<<YELLOW_LED ;
GPIO_CLR = 1<<RED_LED ;
repeat_count++ ;
if (repeat_count > 5) {
state = 12 ;
} else {
state = 10 ;
}
break ;
case 12 : // proceed with reboot
close(fd) ;
do_reboot() ;
break ;
} // end switch
} // end if
// loop delay
nanosleep((struct timespec[]){{0, TIME_TIC}}, NULL) ;
}
return 0 ; // we should never come here!
} // main
/***************************************************************************************/
//
// Set up a memory region to access GPIO
//
void setup_io() {
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("can't open /dev/mem \n");
exit(-1);
}
/* mmap GPIO */
gpio_map = mmap(
NULL, //Any adddress in our space will do
BLOCK_SIZE, //Map length
PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
MAP_SHARED, //Shared with other processes
mem_fd, //File to map
GPIO_BASE //Offset to GPIO peripheral
);
close(mem_fd); //No need to keep mem_fd open after mmap
if (gpio_map == MAP_FAILED) {
printf("mmap error %d\n", (int)gpio_map);//errno also set!
exit(-1);
}
// Always use volatile pointer!
gpio = (volatile unsigned *)gpio_map ;
// initializes the LED and push-button pins
INP_GPIO( GREEN_LED) ; // must use INP_GPIO before we can use OUT_GPIO
OUT_GPIO( GREEN_LED) ;
INP_GPIO( YELLOW_LED) ;
OUT_GPIO( YELLOW_LED) ;
INP_GPIO( RED_LED) ;
OUT_GPIO( RED_LED) ;
INP_GPIO( PUSHBUTTON) ;
// initializes LEDs to OFF state
GPIO_CLR = 1<<GREEN_LED ;
GPIO_CLR = 1<<YELLOW_LED ;
GPIO_CLR = 1<<RED_LED ;
} // setup_io
/***************************************************************************************/
//
// Call system reboot
//
void do_reboot() {
static char *execArgv[5] ; /* define arguments for shutdown exec */
execArgv[0] = "shutdown" ;
execArgv[1] = "-r" ;
execArgv[2] = "now" ;
execArgv[3] = NULL ;
//printf("going to reboot!\n") ;
execv("/sbin/shutdown", execArgv) ;
} // do_reboot
/*** END OF FILE ***********************************************************************/

View File

@ -1,27 +0,0 @@
#!/bin/sh
FIFO="/tmp/ledBtnFIFO"
#mkfifo $FIFO
#sudo ./ledBtn $FIFO
# send command "READY"
echo "r" > $FIFO
#sleep 1
# send command "PROCESSING"
echo "p" > $FIFO
sleep 1
# send command "FILE processed"
echo "f" > $FIFO
sleep 3
# send command "FILE processed"
echo "f" > $FIFO
sleep 3
# send command "processing successfully COMPLETED"
echo "c" > $FIFO
sleep 2
# send command "ZERO (clear display and return state to 0)"
echo "z" > $FIFO
sleep 2
# send command "ERROR"
echo "e" > $FIFO

View File

@ -0,0 +1,12 @@
#!/bin/bash
set -x
# cp /media/sf_ubuntu-shared/Circlean-Ubuntu/fs_filecheck/opt/groomer/init.sh /mnt/rpi/opt/groomer/init.sh
# cp /media/sf_ubuntu-shared/Circlean-Ubuntu/fs_filecheck/opt/groomer/groomer.sh /mnt/rpi/opt/groomer/groomer.sh
# cp /media/sf_ubuntu-shared/Circlean-Ubuntu/fs_filecheck/opt/groomer/config.sh /mnt/rpi/opt/groomer/config.sh
# cp /media/sf_ubuntu-shared/Circlean-Ubuntu/fs_filecheck/opt/groomer/mount_dest.sh /mnt/rpi/opt/groomer/mount_dest.sh
# cp /media/sf_ubuntu-shared/Circlean-Ubuntu/fs_filecheck/opt/groomer/music.sh /mnt/rpi/opt/groomer/music.sh
# cp /media/sf_ubuntu-shared/Circlean-Ubuntu/fs_filecheck/etc/rc.local /mnt/rpi/etc/rc.local
# cp /media/sf_ubuntu-shared/Circlean-Ubuntu/fs_filecheck/etc/pmount.allow /mnt/rpi/etc/pmount.allow
# cp /media/sf_ubuntu-shared/Circlean-Ubuntu/fs_filecheck/etc/udev/rules.d/10-usb.rules /mnt/rpi/etc/udev/rules.d/10-usb.rules

View File

@ -0,0 +1,7 @@
#!/bin/bash
IMAGE='2016-05-12_CIRCLean.img'
OFFSET=$((512 * 131072))
mkdir /mnt/rpi
mount -v -o offset=${OFFSET} -t ext4 ${IMAGE} /mnt/rpi