/* * libbb/libbb.c - Bitbang library * * Written 2010 by Werner Almesberger * Copyright 2010 Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include #include #include #include #include #include //#include #include #include "libbb.h" #define PAGE_SIZE 4096 volatile void *libbb_mem; static int bbd_fd = -1; static int recv_fd(int s) { struct msghdr msg; struct cmsg { struct cmsghdr hdr; int fd; } cmsg; memset(&msg, 0, sizeof(msg)); msg.msg_control = &cmsg; msg.msg_controllen = sizeof(cmsg); if (recvmsg(s, &msg, 0) < 0) { perror("recvmsg"); exit(1); } return cmsg.fd; } static void child(void) { execl(LIBBD_PATH, LIBBD_PATH, NULL); perror(LIBBD_PATH); _exit(1); } #if 0 static int recv_fd(int s) { pid_t res; res = waitpid(pid, &status, 0); if (res < 0) { perror("waitpid"); exit(1); } if (res != pid) { fprintf(stderr, "waitpid returned %d for %d\n", (int) res, (int) pid); exit(1); } } #endif static int bbd(void) { int s[2]; pid_t pid; if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, s) < 0) { perror("socketpair"); exit(1); } if (dup2(s[1], 1) < 0) { perror("dup2"); exit(1); } pid = fork(); if (pid < 0) { perror("fork"); exit(1); } if (pid) return recv_fd(s[0]); else child(); return -1; /* can't happen */ } void libbb_open(void) { bbd_fd = bbd(); libbb_mem = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, bbd_fd, LIBBB_GPIO_BASE); if (libbb_mem == MAP_FAILED) { perror("mmap"); exit(1); } } void libbb_close(void) { if (close(bbd_fd) < 0) { perror("close"); exit(1); } }