diff options
author | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
---|---|---|
committer | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
commit | 709c4d66e0b107ca606941b988bad717c0b45d9b (patch) | |
tree | 37ee08b1eb308f3b2b6426d5793545c38396b838 /recipes/sccd/files/scc.c | |
parent | fa6cd5a3b993f16c27de4ff82b42684516d433ba (diff) |
rename packages/ to recipes/ per earlier agreement
See links below for more details:
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21326
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21816
Signed-off-by: Denys Dmytriyenko <denis@denix.org>
Acked-by: Mike Westerhof <mwester@dls.net>
Acked-by: Philip Balister <philip@balister.org>
Acked-by: Khem Raj <raj.khem@gmail.com>
Acked-by: Marcin Juszkiewicz <hrw@openembedded.org>
Acked-by: Koen Kooi <koen@openembedded.org>
Acked-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com>
Diffstat (limited to 'recipes/sccd/files/scc.c')
-rw-r--r-- | recipes/sccd/files/scc.c | 412 |
1 files changed, 412 insertions, 0 deletions
diff --git a/recipes/sccd/files/scc.c b/recipes/sccd/files/scc.c new file mode 100644 index 0000000000..b917bf1ee8 --- /dev/null +++ b/recipes/sccd/files/scc.c @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2006 + * Protium Computing, Inc. 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 Protium Computing, Inc. + * 4. The name of Protium Computing, Inc. may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY PROTIUM COMPUTING ``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 PROTIUM COMPUTING 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 <stdio.h> +#include <fcntl.h> +#include <time.h> +#include <unistd.h> +#include <stdlib.h> +#include <strings.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <termios.h> + +#include "scc.h" + +char * prog; +int initialize = 0; +int verbose = 0; + +scc_cmd_t powercmds[] = { + { "a", 0x61000000}, + { "run", SCC_RUN}, + { "off", SCC_STOP}, + { "advoff", SCC_ADVISESTOP}, + { "restart", SCC_RESTART,}, + { "advrestart", SCC_ADVISERESTART}, + { "reset", SCC_RESET,}, + { "advreset", SCC_ADVISERESET}, + { "EOT", -1}}; + +scc_cmd_t ledcmds[] = { + { "off", SCC_LEDOFF}, + { "blue", SCC_LEDBLUE}, + { "red", SCC_LEDRED}, + { "blueflash", SCC_LEDBLUEFLASH}, + { "redflash", SCC_LEDREDFLASH}, + { "alternate", SCC_LEDALTERNATE1}, + { "alternate3", SCC_LEDALTERNATE3}, + { "EOT", -1}}; + +scc_cmd_t fancmds[]= { + { "auto", SCC_FANAUTO}, + { "on", SCC_FANON}, + { "EOT", -1}}; + +void +usage(void) +{ + int i; + scc_cmd_t *c; + + fprintf(stderr, "Usage: %s OPTIONS\n", prog); + fprintf(stderr,"%s controls the Iomega StorCenter's LED, fan and soft power.\n\n", prog); + fprintf(stderr," -?\t\tthis message\n"); + fprintf(stderr," -v\t\tverbose, show all packets\n"); + fprintf(stderr," -d\t\tsend send directly, stop/restart only\n"); + fprintf(stderr,"\n -p POWER\tcontrol soft power\n"); + fprintf(stderr,"\t\tPOWER=["); + for (c = powercmds,i=0; c->scc_cmdval != -1; c++,i++) { + if (i) fprintf(stderr,"|"); + fprintf(stderr,"%s", c->scc_cmd); + } + fprintf(stderr,"]\n\n"); + + fprintf(stderr," -l LED\tcontrol LED state\n"); + fprintf(stderr,"\t\tLED=["); + for (c = ledcmds,i=0; c->scc_cmdval != -1; c++,i++) { + if (i) fprintf(stderr,"|"); + fprintf(stderr,"%s", c->scc_cmd); + } + fprintf(stderr,"]\n -r RATE\tRate the LED flashes (0<=RATE<256)\n\n"); + + + fprintf(stderr," -f FAN\tcontrol fan operation\n"); + fprintf(stderr,"\t\tFAN=["); + for (c = fancmds,i=0; c->scc_cmdval != -1; c++,i++) { + if (i) fprintf(stderr,"|"); + fprintf(stderr,"%s", c->scc_cmd); + } + fprintf(stderr,"]\n -h TEMP\tHot temp when FAN=auto should go on (0<=TEMP<256)\n"); + fprintf(stderr," -c TEMP\tCold temp when FAN=auto should go off (0<=TEMP<256)\n"); + + (void)exit(2); +} + +int +sendrecv(int fd, int *i, int *j) +{ + char buf[8]; + int rc; + fd_set fds; + struct timeval sec = {1, 0}; + struct timespec tenth_sec = {0, 100000000}; + + + /* build the buffer */ + *(int *)(buf) = *i; + *(int *)(buf + 4) = *j; + + if (verbose) + printf("Send: [0x%08x 0x%08x]\n", *i, *j); + + if ((rc = write(fd, buf, 8)) != 8) { + perror("write failed failed"); + return(-1); + } + + /* Wait for data */ + FD_ZERO(&fds); + FD_SET(fd, &fds); + rc = select(1024, &fds, NULL, NULL, &sec); + + if (rc == -1) { + perror("select failed"); + return (-1); + } else if (!rc) { + perror("select timedout"); + return (-1); + } + + /* Consume it */ + if ((rc = read(fd, buf, 8)) != 8) { + perror("read failed failed"); + return(-1); + } + + *i = *(int *)(buf); + *j = *(int *)(buf + 4); + + if (verbose) + printf("Recv: [0x%08x 0x%08x]\n", *i, *j); + + /* Let it rest */ + nanosleep(&tenth_sec, NULL); + + return(0); +} + +int +setup_clnt() +{ + int s, len; + struct sockaddr_un remote; + + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + return(-1); + } + + remote.sun_family = AF_UNIX; + strcpy(remote.sun_path, SCC_SOCKET); + len = strlen(remote.sun_path) + sizeof(remote.sun_family); + if (connect(s, (struct sockaddr *)&remote, len) == -1) { + return(-1); + } + + return(s); +} + +int +setup_cntlr(int *i, int *j) +{ + int fd; + char *dev = SCC_DEVICE; + struct termios ti; + + /* setup the serial connection to 9600, 8n1 */ + if ((fd = open(dev, O_RDWR|O_NOCTTY)) < 0) { + perror("Open failed"); + return(-1); + } + + if (ioctl(fd, TCGETS, &ti) < 0) { + perror("TCGETS failed"); + return(-1); + } + + if (ioctl(fd, TCFLSH, 0) < 0) { + perror("TCFLSH failed"); + return(-1); + } + + ti.c_iflag = IGNPAR; + ti.c_oflag = 0; + ti.c_cflag = (B9600 | CS8 | CREAD | CLOCAL); + ti.c_lflag = 0; + ti.c_line = N_TTY; + bzero(ti.c_cc, NCCS); + ti.c_cc[VMIN] = 0x08; + + if (ioctl(fd, TCSETS, &ti) < 0) { + perror("TCSETS failed"); + return(-1); + } + + if (verbose) printf("Resetting microcontroller\n"); + *i = SCC_RESETW1; + *j = SCC_RESETW2; + scc_setval(i, SCC_IDMASK, SCC_HOST); + scc_setval(j, SCC_CKSUMMASK, (int)scc_cksum(i, j)); + if (sendrecv(fd, i, j) < 0) + return(-1); + + return(fd); +} + +int +main(int argc, char *argv[]) +{ + + int devfd, w1, w2, h1, h2; + int coldtemp, hottemp, fancmd; + int ledrate, ledcmd; + int powercmd; + int direct; + int c; + char buf[SCC_PACKETLEN]; + scc_cmd_t *ct; + + extern char *optarg; + extern int optind, opterr, optopt; + + prog = argv[0]; + fancmd = coldtemp = hottemp = -1; + ledcmd = ledrate = -1; + powercmd = -1; + direct = 0; + + while ((c = getopt(argc, argv, "c:df:h:l:p:r:wv?")) != EOF) { + switch (c) { + case 'c': + if (coldtemp != -1) /* more than one -c arg */ + usage(); + + coldtemp = atoi(optarg); + if ((coldtemp > 255) || (coldtemp < 0)) + usage(); + break; + case 'd': + direct = 1; + break; + case 'f': + if (fancmd != -1) /* more than one -f arg */ + usage(); + + for (ct = fancmds; ct->scc_cmdval != -1; ct++) { + if (!strcmp(ct->scc_cmd, optarg)) { + fancmd = ct->scc_cmdval; + } + } + + if (fancmd == -1) /* Failed to find the req */ + usage(); + + break; + case 'h': + if (hottemp != -1) /* more than one -h arg */ + usage(); + + hottemp = atoi(optarg); + if ((hottemp > 255) || (hottemp < 0)) + usage(); + break; + case 'l': + if (ledcmd != -1) /* more than one -l arg */ + usage(); + + for (ct = ledcmds; ct->scc_cmdval != -1; ct++) { + if (!strcmp(ct->scc_cmd, optarg)) { + ledcmd = ct->scc_cmdval; + } + } + + if (ledcmd == -1) /* Failed to find the req */ + usage(); + break; + case 'p': + if (powercmd != -1) /* more than one -p arg */ + usage(); + + for (ct = powercmds; ct->scc_cmdval != -1; ct++) { + if (!strcmp(ct->scc_cmd, optarg)) { + powercmd = ct->scc_cmdval; + } + } + + if (powercmd == -1) /* Failed to find the req */ + usage(); + break; + case 'r': + if (ledrate != -1) /* more than one -h arg */ + usage(); + + ledrate = atoi(optarg); + if ((ledrate > 255) || (ledrate < 0)) + usage(); + break; + case 'v': + verbose=1; + break; + case '?': + usage(); + break; + + } + } + + if (direct) { + /* + * Setup the cntlr connection + */ + if ((devfd = setup_cntlr(&w1, &w2)) < 0) + exit(1); + scc_defaults(&w1, &w2); + } else { + /* + * Setup the clnt connection, if we get an connection + * refused that means the daemon isn't listening. + * so go direct + */ + w1 = 0; + w2 = 0; + if ((devfd = setup_clnt()) < 0) { + /* log it */ + if ((devfd = setup_cntlr(&w1, &w2)) < 0) + exit(1); + direct = 1; + scc_defaults(&w1, &w2); + } + } + + /* + * Direct (direct to the cntlr): + * w1 and w2 are setup with the default cntlr packet. + * Now lets poke the command line args into the packet. + * + * Nondirect (via the daemon): + * w1 and w2 are setup with nulls. The packet sent to the daemon + * contains only the changes to the current state. + */ + if (powercmd != -1) + scc_setval(&w1, SCC_POWERMASK, powercmd); + if (ledcmd != -1) + scc_setval(&w1, SCC_LEDMASK, ledcmd); + if (ledrate != -1) + scc_setrate(&w1, SCC_LEDRATEMASK, SCC_LEDRATESHIFT, ledrate); + if (fancmd != -1) + scc_setval(&w1, SCC_FANMASK, fancmd); + + if (coldtemp != -1) + scc_setrate(&w2, + SCC_FANTEMPOFFMASK, SCC_FANTEMPOFFSHIFT, coldtemp); + if (hottemp != -1) + scc_setrate(&w2, + SCC_FANTEMPONMASK, SCC_FANTEMPONSHIFT, hottemp); + + scc_setval(&w2, SCC_IDMASK, SCC_HOST); + scc_setval(&w2, SCC_CKSUMMASK, (int)scc_cksum(&w1, &w2)); + + + if (direct) { + if (verbose) { + printf("New State: \n"); + scc_validate(&w1, &w2, verbose); + } + + if (sendrecv(devfd, &w1, &w2) < 0) + exit(1); + } else { + *(int *)(&buf[0]) = w1; + *(int *)(&buf[4]) = w2; + + if (send(devfd, buf, SCC_PACKETLEN, 0) == -1) { + perror("send"); + exit(1); + } + } + + close(devfd); + exit(0); +} |