int multirom_ui(struct multirom_status *s, struct multirom_rom **to_boot)
{
    if(multirom_init_fb(s->rotation) < 0)
        return UI_EXIT_BOOT_ROM;

    fb_freeze(1);

    mrom_status = s;

    exit_ui_code = -1;
    selected_rom = NULL;
    active_msgbox = NULL;

    multirom_ui_setup_colors(s->colors, &CLR_PRIMARY, &CLR_SECONDARY);
    themes_info = multirom_ui_init_themes();
    if((cur_theme = multirom_ui_select_theme(themes_info, fb_width, fb_height)) == NULL)
    {
        fb_freeze(0);

        ERROR("Couldn't find theme for resolution %dx%d!\n", fb_width, fb_height);
        fb_add_text(0, 0, WHITE, SIZE_SMALL, "Couldn't find theme for resolution %dx%d!\nPress POWER to reboot.", fb_width, fb_height);
        fb_draw();
        fb_clear();
        fb_close();

        start_input_thread();
        while(wait_for_key() != KEY_POWER);
        stop_input_thread();
        return UI_EXIT_REBOOT;
    }

    workers_start();

    multirom_ui_init_header();
    multirom_ui_switch(TAB_INTERNAL);

    add_touch_handler(&multirom_ui_touch_handler, NULL);
    start_input_thread();
    keyaction_enable(1);
    keyaction_set_destroy_msgbox_handle(multirom_ui_destroy_msgbox);

    multirom_set_brightness(s->brightness);

    fb_freeze(0);

    if(s->auto_boot_rom && s->auto_boot_seconds > 0)
        multirom_ui_auto_boot();
    else
        fb_draw();

    while(1)
    {
        pthread_mutex_lock(&exit_code_mutex);
        if(exit_ui_code != -1)
        {
            pthread_mutex_unlock(&exit_code_mutex);
            break;
        }

        if(loop_act & LOOP_UPDATE_USB)
        {
            multirom_find_usb_roms(mrom_status);
            if(themes_info->data->selected_tab == TAB_USB)
                multirom_ui_tab_rom_update_usb(themes_info->data->tab_data);
            loop_act &= ~(LOOP_UPDATE_USB);
        }

        if(loop_act & LOOP_START_PONG)
        {
            loop_act &= ~(LOOP_START_PONG);
            keyaction_enable(0);
            input_push_context();
            fb_push_context();

            pong();

            fb_pop_context();
            input_pop_context();
            keyaction_enable(1);
        }

        if(loop_act & LOOP_CHANGE_CLR)
        {
            fb_freeze(1);

            multirom_ui_setup_colors(s->colors, &CLR_PRIMARY, &CLR_SECONDARY);

            // force redraw tab
            int tab = themes_info->data->selected_tab;
            themes_info->data->selected_tab = -1;

            multirom_ui_destroy_tab(tab);
            multirom_ui_switch(tab);

            fb_freeze(0);
            fb_draw();

            loop_act &= ~(LOOP_CHANGE_CLR);
        }

        pthread_mutex_unlock(&exit_code_mutex);

        usleep(100000);
    }

    keyaction_enable(0);
    keyaction_clear();

    rm_touch_handler(&multirom_ui_touch_handler, NULL);

    fb_create_msgbox(500*DPI_MUL, 250*DPI_MUL, CLR_PRIMARY);

    switch(exit_ui_code)
    {
        case UI_EXIT_BOOT_ROM:
            *to_boot = selected_rom;
            fb_msgbox_add_text(-1, 40*DPI_MUL, SIZE_BIG, "Booting ROM...");
            fb_msgbox_add_text(-1, -1, SIZE_NORMAL, selected_rom->name);
            break;
        case UI_EXIT_REBOOT:
        case UI_EXIT_REBOOT_RECOVERY:
        case UI_EXIT_REBOOT_BOOTLOADER:
            fb_msgbox_add_text(-1, -1, SIZE_BIG, "Rebooting...");
            break;
        case UI_EXIT_SHUTDOWN:
            fb_msgbox_add_text(-1, -1, SIZE_BIG, "Shutting down...");
            break;
    }

    fb_draw();
    fb_freeze(1);

    cur_theme->destroy(themes_info->data);

    int i;
    for(i = 0; i < TAB_COUNT; ++i)
    {
        button_destroy(themes_info->data->tab_btns[i]);
        themes_info->data->tab_btns[i] = NULL;
    }

    stop_input_thread();

    multirom_ui_destroy_tab(themes_info->data->selected_tab);
    multirom_ui_free_themes(themes_info);
    themes_info = NULL;

    workers_stop();

    fb_clear();
#if MR_DEVICE_HOOKS >= 2
    mrom_hook_before_fb_close();
#endif
    fb_close();
    return exit_ui_code;
}
Beispiel #2
0
void accept_thread(void *asdf)
{
	sigset_t sigs_to_block;
	int e, n;
	struct pollfd *acceptpfd = NULL;
	struct listen_t **acceptpl = NULL;
	int listen_n = 0;
	int poll_n = 0;
	struct listen_t *l;

	pthreads_profiling_reset("accept");
	
	sigemptyset(&sigs_to_block);
	sigaddset(&sigs_to_block, SIGALRM);
	sigaddset(&sigs_to_block, SIGINT);
	sigaddset(&sigs_to_block, SIGTERM);
	sigaddset(&sigs_to_block, SIGQUIT);
	sigaddset(&sigs_to_block, SIGHUP);
	sigaddset(&sigs_to_block, SIGURG);
	sigaddset(&sigs_to_block, SIGPIPE);
	sigaddset(&sigs_to_block, SIGUSR1);
	sigaddset(&sigs_to_block, SIGUSR2);
	pthread_sigmask(SIG_BLOCK, &sigs_to_block, NULL);
	
	/* start the accept thread, which will start server threads */
	hlog(LOG_INFO, "Accept thread starting...");
	
	/* we allocate a worker structure to be used within the accept thread
	 * for parsing incoming UDP packets and passing them on to the dupecheck
	 * thread.
	 */
	udp_worker = worker_alloc();
	udp_worker->id = 81;
	
	/* we also need a client structure to be used with incoming
	 * HTTP position uploads
	 */
	udp_pseudoclient = pseudoclient_setup(81);
	udp_pseudoclient->flags |= CLFLAGS_UDPSUBMIT;
	
	accept_reconfiguring = 1;
	while (!accept_shutting_down) {
		if (accept_reconfiguring) {
			accept_reconfiguring = 0;
			listen_n -= close_removed_listeners();
			
			/* start listening on the sockets */
			listen_n += open_missing_listeners();
			
			if (listen_n < 1) {
				hlog(LOG_CRIT, "Failed to listen on any ports.");
				exit(2);
			}
			
			/* reconfiguration must scan old clients against ACL */
			rescan_client_acls();
			
			/* how many are we polling */
			poll_n = 0;
			for (l = listen_list; (l); l = l->next)
				if (!l->corepeer)
					poll_n++;
			
			hlog(LOG_DEBUG, "Generating polling list for %d/%d listeners...", poll_n, listen_n);
			
			/* array of FDs for poll() */
			if (acceptpfd)
				hfree(acceptpfd);
			acceptpfd = hmalloc(poll_n * sizeof(*acceptpfd));
			
			/* array of listeners */
			if (acceptpl)
				hfree(acceptpl);
			acceptpl = hmalloc(poll_n * sizeof(*acceptpl));
			
			n = 0;
			for (l = listen_list; (l); l = l->next) {
				/* The accept thread does not poll() UDP sockets for core peers.
				 * Worker 0 takes care of that, and processes the incoming packets.
				 */
				if (l->corepeer) {
					hlog(LOG_DEBUG, "... %d: fd %d (%s) - not polled, is corepeer", n, (l->udp) ? l->udp->fd : l->fd, l->addr_s);
					continue;
				}
				
				int fd;
				if (l->udp) {
					l->udp->polled = 1;
					fd = l->udp->fd;
				} else {
					fd = l->fd;
				}
				
				hlog(LOG_DEBUG, "... %d: fd %d (%s)", n, fd, l->addr_s);
				acceptpfd[n].fd = fd;
				acceptpfd[n].events = POLLIN|POLLPRI|POLLERR|POLLHUP;
				acceptpl[n] = l;
				n++;
			}
			hlog(LOG_INFO, "Accept thread ready.");
			
			/* stop the dupechecking and uplink threads while adjusting
			 * the amount of workers... they walk the worker list, and
			 * might get confused when workers are stopped or started.
			 */
			if (workers_running != workers_configured) {
				uplink_stop();
				dupecheck_stop();
				workers_start();
				dupecheck_start();
				uplink_start();
			}
			
			/*
			 * generate UDP peer clients
			 */
			peerip_clients_close();
			if (peerip_config)
				peerip_clients_config();
			
			/* accept liveupgrade clients */
			if (liveupgrade_status)
				accept_liveupgrade_accept();
		}
		
		/* check for new connections */
		e = poll(acceptpfd, poll_n, 200);
		if (e == 0)
			continue;
		if (e < 0) {
			if (errno == EINTR)
				continue;
			hlog(LOG_ERR, "poll() on accept failed: %s (continuing)", strerror(errno));
			continue;
		}
		
		/* now, which socket was that on? */
		for (n = 0; n < poll_n; n++) {
			l = acceptpl[n];
			if (!(l) || (l->udp ? l->udp->fd : l->fd) != acceptpfd[n].fd) {
				hlog(LOG_CRIT, "accept_thread: polling list and listener list do mot match!");
				exit(1);
			}
			if (acceptpfd[n].revents) {
				if (l->udp)
					accept_udp_recv(l); /* receive UDP packets */
				else
					do_accept(l); /* accept a single connection */
			}
		}
	}
	
	if (accept_shutting_down == 2)
		worker_shutdown_clients = cJSON_CreateArray();
	
	hlog(LOG_DEBUG, "Accept thread shutting down listening sockets and worker threads...");
	uplink_stop();
	close_listeners();
	dupecheck_stop();
	http_shutting_down = 1;
	workers_stop(accept_shutting_down);
	hfree(acceptpfd);
	hfree(acceptpl);
	acceptpfd = NULL;
	acceptpl = NULL;
	
	/* free up the pseudo-client */
	client_free(udp_pseudoclient);
	udp_pseudoclient = NULL;
	
	/* free up the pseudo-worker structure, after dupecheck is long dead */
	worker_free_buffers(udp_worker);
	hfree(udp_worker);
	udp_worker = NULL;
}