Exemple #1
0
void check_clients(fd_set *fds)
{
  struct client_list **c;

  for (c = &clients; *c; )
    {
      int next = 1;

      if (FD_ISSET((*c)->fd, fds))
	{
	  int len;
	  const void *packet = read_sf_packet((*c)->fd, &len);

	  if (packet)
	    {
	      forward_packet(packet, len);
	      free((void *)packet);
	    }
	  else
	    {
	      rem_client(c);
	      next = 0;
	    }
	}
      if (next)
	c = &(*c)->next;
    }
}
Exemple #2
0
void dispatch_packet(const void *packet, int len)
{
  struct client_list **c;

  for (c = &clients; *c; )
    if (write_sf_packet((*c)->fd, packet, len) >= 0)
      c = &(*c)->next;
    else
      rem_client(c);
}
Exemple #3
0
int main(int argc, char* argv[])
{
    int opt, ret;
    int daemon = 1, lock = 0;
    int screen_status, aux_pressed, power_pressed, y, x;
    char *config;
    FILE *file;
    struct sockaddr_un addr;
    
    struct chain_socket *aux_grabber = 0, *power_grabber = 0;
    
    struct input_event input;
    struct iod_cmd cmd;
    struct chain_socket *cs;
    
    size_t size;
    
    y = x = screen_status = aux_pressed = power_pressed = 0;
    pwd = IOD_PWD;
    
    while((opt = getopt(argc, argv, "fd:")) != -1)
    {
        switch(opt)
        {
        case 'f':
            daemon = 0;
            break;
        case 'd':
            pwd = optarg;
            break;
        default:
            usage(argv[0]);
            return 0;
        }
    }
    
    if(optind == argc)
    {
        usage(argv[0]);
        return 0;
    }
    
    config = argv[optind];
    
    if(mkdir(pwd, 0777) == -1 && errno != EEXIST)
    {
        perror("Failed to create working dir");
        return 7;
    }
    
    if(daemon)
    {
        int tmp = fork();
        if(tmp < 0)
        {
            perror("Failed to fork process");
            return 1;
        }
        if(tmp > 0)
        {
            return 0;
        }
        
        setsid();
        
        close(0); close(1); close(2);
        tmp = open("/dev/null", O_RDWR); dup(tmp); dup(tmp);
        
        chdir(pwd);
        
        if((tmp = open("pid", O_WRONLY|O_CREAT, 755)) < 0)
        {
            perror("Failed to open pidfile");
            return 2;
        }
        
        pid_t pid = getpid();
        char buf[10];
        int count = sprintf(buf, "%i", pid);
        write(tmp, &buf, count*sizeof(char));
        
        if(lockf(tmp, F_TLOCK, -count*sizeof(char)) < 0)
        {
            perror("Daemon already running");
            return 3;
        }
    }
    
    if(!(file = fopen(config, "r")))
    {
        perror("Failed to open config file");
        return 4;
    }
    
    if((size = getline(&screen_dev, &size, file)) == -1)
    {
        fprintf(stderr, "Failed to read screen config\n");
        return 5;
    }
    screen_dev[size-1] = 0;
    
    if((screen_fd = open(screen_dev, O_RDONLY)) == -1)
    {
        perror("Failed to open screen socket");
        return 6;
    }
    
    if((size = getline(&aux_dev, &size, file)) == -1)
    {
        fprintf(stderr, "Failed to read aux config\n");
        return 7;
    }
    aux_dev[size-1] = 0;
    
    if((aux_fd = open(aux_dev, O_RDONLY)) == -1)
    {
        perror("Failed to open aux socket");
        return 8;
    }
    
    if((size = getline(&power_dev, &size, file)) == -1)
    {
        fprintf(stderr, "Failed to read power config\n");
        return 9;
    }
    power_dev[size-1] = 0;
    fclose(file);
    
    if((power_fd = open(power_dev, O_RDONLY)) == -1)
    {
        perror("Failed to open power socket");
        return 10;
    }
    
    DEBUG(print_info(screen_fd));
    DEBUG(print_info(aux_fd));
    DEBUG(print_info(power_fd));
    
    if((ret = open_socket(&sock, &addr)))
        return ret;
    
    pfds_cap = 10;
    pfds = malloc(pfds_cap*sizeof(struct pollfd));
    pfds[0].fd = screen_fd;
    pfds[0].events = POLLIN;
    pfds[1].fd = aux_fd;
    pfds[1].events = POLLIN;
    pfds[2].fd = power_fd;
    pfds[2].events = POLLIN;
    pfds[3].fd = sock;
    pfds[3].events = POLLIN;
    
    client_count = 0;
    CIRCLEQ_INIT(&client_list);
    
    signal(SIGINT, signal_handler);
    
    DEBUG(printf("Ready\n"));
    
    while(1)
    {
        poll(pfds, client_count+4, -1);
        
        if(pfds[0].revents & POLLHUP || pfds[0].revents & POLLERR)
        {
            DEBUG(printf("pollhup/err on screen socket\n"));
            close(screen_fd);
            if((screen_fd = open(screen_dev, O_RDONLY)) < 0)
            {
                perror("Failed to open screen socket");
                screen_fd = 0;
                cleanup();
                return 6;
            }
        }
        else if(pfds[0].revents & POLLIN)
        {
            read(screen_fd, &input, sizeof(struct input_event));
            
            if(lock)
                continue;
            
            switch(input.type)
            {
            case EV_KEY:
                switch(input.code)
                {
                case BTN_TOUCH:
                    switch(input.value)
                    {
                        case 0:
                            screen_status = 0;
                            break;
                        case 1:
                            screen_status = 1;
                            break;
                    }
                    break;
                }
                break;
            case EV_ABS:
                switch(input.code)
                {
                case ABS_X:
                    y = input.value-MIN_PIXEL;
                    break;
                case ABS_Y:
                    x = input.value-MIN_PIXEL;
                    break;
                case ABS_PRESSURE:
                    break;
                }
                break;
            case EV_SYN:
                switch(input.code)
                {
                case SYN_REPORT:
                    switch(screen_status)
                    {
                    case 0:
                        DEBUG(printf("Touchscreen released (%i,%i)\n", y, x));
                        send_client_cord(IOD_EVENT_RELEASED, y, x, 0);
                        break;
                    case 1:
                        DEBUG(printf("Touchscreen pressed (%i,%i)\n", y, x));
                        send_client_cord(IOD_EVENT_PRESSED, y, x, 0);
                        screen_status = 2;
                        break;
                    case 2:
                        send_client_cord(IOD_EVENT_MOVED, y, x, 0);
                        break;
                    }
                    break;
                }
                break;
            }
        }
        else if(pfds[1].revents & POLLHUP || pfds[1].revents & POLLERR)
        {
            DEBUG(printf("pollhup/err on aux socket\n"));
            close(aux_fd);
            if((aux_fd = open(aux_dev, O_RDONLY)) == -1)
            {
                perror("Failed to open aux socket");
                aux_fd = 0;
                cleanup();
                return 8;
            }
        }
        else if(pfds[1].revents & POLLIN)
        {
            read(aux_fd, &input, sizeof(struct input_event));
            switch(input.type)
            {
            case EV_KEY:
                switch(input.code)
                {
                case KEY_PHONE:
                    aux_pressed = input.value;
                    break;
                }
                break;
            case EV_SYN:
                switch(input.code)
                {
                case SYN_REPORT:
                    DEBUG(printf("AUX %s\n",
                        aux_pressed ? "pressed" : "released"));
                    cs = aux_grabber ? aux_grabber : 0;
                    send_client_status(IOD_EVENT_AUX, aux_pressed, cs);
                    break;
                }
                break;
            }
        }
        else if(pfds[2].revents & POLLHUP || pfds[2].revents & POLLERR)
        {
            DEBUG(printf("pollhup/err on power socket\n"));
            close(power_fd);
            if((power_fd = open(power_dev, O_RDONLY)) == -1)
            {
                perror("Failed to open power socket");
                power_fd = 0;
                cleanup();
                return 10;
            }
        }
        else if(pfds[2].revents & POLLIN)
        {
            read(power_fd, &input, sizeof(struct input_event));
            switch(input.type)
            {
            case EV_KEY:
                switch(input.code)
                {
                case KEY_POWER:
                    power_pressed = input.value;
                    break;
                }
                break;
            case EV_PWR:
                break;
            case EV_SYN:
                switch(input.code)
                {
                case SYN_REPORT:
                    DEBUG(printf("Power %s\n",
                        power_pressed ? "pressed" : "released"));
                    cs = power_grabber ? power_grabber : 0;
                    send_client_status(IOD_EVENT_POWER, power_pressed, cs);
                    break;
                }
                break;
            }
        }
        else if(pfds[3].revents & POLLHUP || pfds[3].revents & POLLERR)
        {
            DEBUG(printf("pollhup/err on socket\n"));
            close(sock);
            if((ret = open_socket(&sock, &addr)))
            {
                sock = 0;
                cleanup();
                return ret;
            }
        }
        else if(pfds[3].revents & POLLIN)
        {
            int client;
            if((client = accept(sock, 0, 0)) == -1)
            {
                DEBUG(perror("Failed to accept client"));
                continue;
            }
            cs = client_list.cqh_first;
            add_client(client);
            if(cs != (void*)&client_list)
                send_client_status(IOD_EVENT_DEACTIVATED, 0, cs);
            else
                send_client_status(IOD_EVENT_ACTIVATED, 0, 0);
        }
        else
        {
            int x;
            for(x=4; x<client_count+4; x++)
                if(pfds[x].revents & POLLHUP || pfds[x].revents & POLLERR)
                {
                    DEBUG(printf("pollhup/pollerr on client socket [%i]\n", pfds[x].fd));
                    cs = find_client(&x, 0);
remove:             if(cs == aux_grabber)
                    {
                        DEBUG(printf("AUX ungrabbed [%i] %i\n",
                            cs->sock, cs->pid));
                        aux_grabber = 0;
                    }
                    if(cs == power_grabber)
                    {
                        DEBUG(printf("Power ungrabbed [%i] %i\n",
                            cs->sock, cs->pid));
                        power_grabber = 0;
                    }
                    if(cs->lock)
                    {
                        DEBUG(printf("Screen unlocked [%i] %i\n",
                            cs->sock, cs->pid));
                        lock = 0;
                    }
                    if(rem_client(x, cs))
                        send_client_status(IOD_EVENT_ACTIVATED, 0, 0);
                    break;
                }
                else if(pfds[x].revents & POLLIN)
                {
                    if(recv_client(pfds[x].fd, &cmd))
                        break;
                    switch(cmd.cmd)
                    {
                    case IOD_CMD_REGISTER:
                        register_client(x, cmd.pid);
                        break;
                    case IOD_CMD_REMOVE:
                        if((cs = find_client(&x, cmd.pid)))
                        {
                            if(cs->sock == pfds[x].fd)
                                goto remove;
                            else
                            {
                                DEBUG(printf("Client remove [%i] %i\n",
                                    cs->sock, cs->pid));
                                send_client_status(
                                    IOD_EVENT_REMOVED, 0, cs);
                            }
                        }
                        break;
                    case IOD_CMD_SWITCH:
                        cs = client_list.cqh_first;
                        if(switch_client(cmd.value, x, cmd.pid))
                            send_client_status(
                                IOD_EVENT_DEACTIVATED, 0, cs);
                        break;
                    case IOD_CMD_LOCK:
                        cs = find_client(&x, 0);
                        if(!lock || cs->lock)
                        {
                            lock = cs->lock = cmd.value;
                            DEBUG(printf("Screen %s [%i] %i\n",
                                lock ? "locked" : "unlocked",
                                x, cs->pid));
                            send_client_status(
                                IOD_EVENT_LOCK, IOD_SUCCESS_MASK, cs);
                        }
                        else
                            send_client_status(
                                IOD_EVENT_LOCK, 0, cs);
                        break;
                    case IOD_CMD_HIDE:
                        hide_client(x, cmd.pid,
                            cmd.value & ~IOD_HIDE_MASK,
                            cmd.value & IOD_HIDE_MASK);
                        break;
                    case IOD_CMD_ACK:
                        switch(cmd.value)
                        {
                        case IOD_EVENT_DEACTIVATED:
                            cs = client_list.cqh_first;
                            DEBUG(printf("Client switched [%i] %i -> [%i] %i\n",
                                pfds[x].fd, find_client(&x, 0)->pid,
                                cs->sock, cs->pid));
                            send_client_status(
                                IOD_EVENT_ACTIVATED, 0, 0);
                            break;
                        case IOD_EVENT_REMOVED:
                            cs = find_client(&x, 0);
                            goto remove;
                        default:
                            DEBUG(printf("Client done [%i] %i\n",
                                pfds[x].fd, find_client(&x, 0)->pid));
                            break;
                        }
                        break;
                    case IOD_CMD_GRAB:
                        cs = find_client(&x, 0);
                        switch(cmd.value & ~IOD_GRAB_MASK)
                        {
                        case IOD_GRAB_AUX:
                            if(!aux_grabber || cs == aux_grabber)
                            {
                                if(cmd.value & IOD_GRAB_MASK)
                                {
                                    DEBUG(printf("AUX grabbed [%i] %i\n",
                                        cs->sock, cs->pid));
                                    aux_grabber = cs;
                                }
                                else
                                {
                                    DEBUG(printf("AUX ungrabbed [%i] %i\n",
                                        cs->sock, cs->pid));
                                    aux_grabber = 0;
                                }
                                send_client_status(IOD_EVENT_GRAB,
                                    IOD_SUCCESS_MASK|IOD_GRAB_AUX, cs);
                            }
                            else
                                send_client_status(IOD_EVENT_GRAB,
                                    IOD_GRAB_AUX, cs);
                            break;
                        case IOD_GRAB_POWER:
                            if(!power_grabber || cs == power_grabber)
                            {
                                if(cmd.value & IOD_GRAB_MASK)
                                {
                                    DEBUG(printf("Power grabbed [%i] %i\n",
                                        cs->sock, cs->pid));
                                    power_grabber = cs;
                                }
                                else
                                {
                                    DEBUG(printf("Power ungrabbed [%i] %i\n",
                                        cs->sock, cs->pid));
                                    power_grabber = 0;
                                }
                                send_client_status(IOD_EVENT_GRAB,
                                    IOD_SUCCESS_MASK|IOD_GRAB_POWER, cs);
                            }
                            else
                                send_client_status(IOD_EVENT_GRAB,
                                    IOD_GRAB_POWER, cs);
                            break;
                        }
                        break;
                    case IOD_CMD_POWERSAVE:
                        DEBUG(printf("Powersave %s broadcast\n",
                            cmd.value ? "on" : "off"));
                        cs = client_list.cqh_first;
                        while(cs != (void*)&client_list)
                        {
                            if(cs->sock != pfds[x].fd)
                                send_client_status(
                                    IOD_EVENT_POWERSAVE, cmd.value, cs);
                            cs = cs->chain.cqe_next;
                        }
                        break;
                    default:
                        DEBUG(printf("Unrecognized command 0x%02hhx [%i] %i\n",
                            cmd.cmd, pfds[x].fd, find_client(&x, 0)->pid));
                    }
                    break;
                }
        }
    }
    
    cleanup();
    
    return 0;
}