static void NORETURN_ATTR pmu_thread(void)
{
    struct queue_event ev;
    unsigned char ints[6];

    while (true)
    {
        queue_wait_w_tmo(&pmu_queue, &ev, TIMEOUT_BLOCK);
        switch (ev.id)
        {
            case Q_EINT:
                /* read (clear) PMU interrupts, this will also
                   raise the PMU IRQ pin */
                pmu_read_multiple(PCF5063X_REG_INT1, 2, ints);
                ints[5] = pmu_read(PCF50635_REG_INT6);

#if CONFIG_CHARGING
                if (ints[0] & ~ints_msk[0]) pmu_read_inputs_mbcs();
#endif
                if (ints[1] & ~ints_msk[1]) pmu_read_inputs_ooc();
                if (ints[5] & ~ints_msk[5]) pmu_read_inputs_gpio();

                eint_register(&pmu_eint);
                break;

            case SYS_TIMEOUT:
                break;
        }
    }
}
예제 #2
0
static bool scroll_process_message(int delay)
{
    struct queue_event ev;

    do
    {
        long tick = current_tick;
        queue_wait_w_tmo(&scroll_queue, &ev, delay);

        switch (ev.id)
        {
        case SYS_TIMEOUT:
            return false;
        case SYS_USB_CONNECTED:
            usb_acknowledge(SYS_USB_CONNECTED_ACK);
            usb_wait_for_disconnect(&scroll_queue);
            sync_display_ticks();
            return true;
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
        case SYS_REMOTE_PLUGGED:
            if (!remote_initialized)
                sync_display_ticks();
#endif
        }

        delay -= current_tick - tick;
    }
    while (delay > 0);

    return false;
}
예제 #3
0
파일: main-pp.c 프로젝트: albb0920/rockbox
/* Return USB_HANDLED if session took place else return USB_EXTRACTED */
static int handle_usb(int connect_timeout)
{
    static struct event_queue q SHAREDBSS_ATTR;
    struct queue_event ev;
    int usb = USB_EXTRACTED;
    long end_tick = 0;
    
    if (!usb_plugged())
        return USB_EXTRACTED;

    queue_init(&q, true);
    usb_init();
    usb_start_monitoring();

    printf("USB: Connecting");

    if (connect_timeout != TIMEOUT_BLOCK)
        end_tick = current_tick + connect_timeout;

    while (1)
    {
        /* Sleep no longer than 1/2s */
        queue_wait_w_tmo(&q, &ev, HZ/2);

        if (ev.id == SYS_USB_CONNECTED)
        {
            /* Switch to verbose mode if not in it so that the status updates
             * are shown */
            verbose = true;
            /* Got the message - wait for disconnect */
            printf("Bootloader USB mode");

            usb = USB_HANDLED;
            usb_acknowledge(SYS_USB_CONNECTED_ACK);
            usb_wait_for_disconnect(&q);
            break;
        }

        if (connect_timeout != TIMEOUT_BLOCK &&
            TIME_AFTER(current_tick, end_tick))
        {
            /* Timed out waiting for the connect - will happen when connected
             * to a charger instead of a host port and the charging pin is
             * the same as the USB pin */
            printf("USB: Timed out");
            break;
        }

        if (!usb_plugged())
            break; /* Cable pulled */
    }

    usb_close();
    queue_delete(&q);

    return usb;
}
예제 #4
0
static void codec_pcmbuf_insert_callback(
    const void *ch1, const void *ch2, int count)
{
    const char *src[2] = { ch1, ch2 };

    while (count > 0)
    {
        int out_count = dsp_output_count(ci.dsp, count);
        int inp_count;
        char *dest;

        while (1)
        {
            if ((dest = pcmbuf_request_buffer(&out_count)) != NULL)
                break;

            cancel_cpu_boost();

            /* It will be awhile before space is available but we want
               "instant" response to any message */
            queue_wait_w_tmo(&codec_queue, NULL, HZ/20);

            if (!queue_empty(&codec_queue) &&
                    codec_check_queue__have_msg() < 0)
                return;
        }

        /* Get the real input_size for output_size bytes, guarding
         * against resampling buffer overflows. */
        inp_count = dsp_input_count(ci.dsp, out_count);

        if (inp_count <= 0)
            return;

        /* Input size has grown, no error, just don't write more than length */
        if (inp_count > count)
            inp_count = count;

        out_count = dsp_process(ci.dsp, dest, src, inp_count);

        if (out_count <= 0)
            return;

        pcmbuf_write_complete(out_count);

        count -= inp_count;
    }
}
예제 #5
0
파일: button.c 프로젝트: 4nykey/rockbox
long button_get_w_tmo(int ticks)
{
    struct queue_event ev;
    
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
    /* Be sure to keep boosted state. */
    if (!queue_empty(&button_queue))
        return button_get(true);
    
    button_boost(false);
#endif
    
    queue_wait_w_tmo(&button_queue, &ev, ticks);
    if (ev.id == SYS_TIMEOUT)
        ev.id = BUTTON_NONE;
    else
        button_data = ev.data;
    return ev.id;
}
예제 #6
0
파일: screens.c 프로젝트: Rockbox/rockbox
int mmc_remove_request(void)
{
    struct queue_event ev;
    FOR_NB_SCREENS(i)
        screens[i].clear_display();
    splash(0, ID2P(LANG_REMOVE_MMC));

    while (1)
    {
        queue_wait_w_tmo(&button_queue, &ev, HZ/2);
        switch (ev.id)
        {
            case SYS_HOTSWAP_EXTRACTED:
                return SYS_HOTSWAP_EXTRACTED;

            case SYS_USB_DISCONNECTED:
                return SYS_USB_DISCONNECTED;
        }
    }
}
static void button_queue_wait(struct queue_event *evp, int timeout)
{
    /* Loop once after wait time if boosted in order to unboost and wait the
       full remaining time */
    do
    {
        int ticks = timeout;

        if (ticks == 0) /* TIMEOUT_NOBLOCK */
            ;
        else if (ticks > 0)
        {
            if (button_boosted && ticks > BUTTON_UNBOOST_TMO)
                ticks = BUTTON_UNBOOST_TMO;

            timeout -= ticks;
        }
        else            /* TIMEOUT_BLOCK (ticks < 0) */
        {
            if (button_boosted)
                ticks = BUTTON_UNBOOST_TMO;
        }

        queue_wait_w_tmo(&button_queue, evp, ticks);
        if (evp->id != SYS_TIMEOUT)
        {
            /* GUI boost build gets immediate kick, otherwise at least 3
               messages had to be there */
        #ifndef HAVE_GUI_BOOST
            if (queue_count(&button_queue) >= 2)
        #endif
                button_boost(true);

            break; 
        }

        if (button_boosted && TIME_AFTER(current_tick, button_unboost_tick))
            button_boost(false);
    }
    while (timeout);
}
예제 #8
0
int usb_wait_for_disconnect_w_tmo(struct event_queue *q, int ticks)
{
#ifdef USB_FULL_INIT
    struct queue_event ev;

    /* Don't return until we get SYS_USB_DISCONNECTED or SYS_TIMEOUT */
    while(1)
    {
        queue_wait_w_tmo(q, &ev, ticks);
        switch(ev.id)
        {
            case SYS_USB_DISCONNECTED:
                usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
                return 0;
            case SYS_TIMEOUT:
                return 1;
        }
    }
#else
    (void)q; (void)ticks;
    return 0;
#endif /* USB_FULL_INIT */
}
/* Voice thread message processing */
static enum voice_state voice_message(struct voice_thread_data *td)
{
    if (quiet_counter > 0)
        queue_wait_w_tmo(&voice_queue, &td->ev, HZ/10);
    else
        queue_wait(&voice_queue, &td->ev);

    switch (td->ev.id)
    {
    case Q_VOICE_PLAY:
        LOGFQUEUE("voice < Q_VOICE_PLAY");
        if (quiet_counter == 0)
        {
            /* Boost CPU now */
            trigger_cpu_boost();
        }
        else
        {
            /* Stop any clip still playing */
            voice_stop_playback();
        }

        quiet_counter = QUIET_COUNT;

        /* Copy the clip info */
        td->vi = *(struct voice_info *)td->ev.data;

        /* Be sure audio buffer is initialized */
        audio_restore_playback(AUDIO_WANT_VOICE);

        /* We need nothing more from the sending thread - let it run */
        queue_reply(&voice_queue, 1);

        /* Make audio play more softly and set delay to return to normal
           playback level */
        pcmbuf_soft_mode(true);

        /* Clean-start the decoder */
        td->st = speex_decoder_init(&speex_wb_mode);

        /* Make bit buffer use our own buffer */
        speex_bits_set_bit_buffer(&td->bits, td->vi.start, td->vi.size);
        speex_decoder_ctl(td->st, SPEEX_GET_LOOKAHEAD, &td->lookahead);

        return VOICE_STATE_DECODE;

    case SYS_TIMEOUT:
        if (voice_unplayed_frames())
        {
            /* Waiting for PCM to finish */
            break;
        }

        /* Drop through and stop the first time after clip runs out */
        if (quiet_counter-- != QUIET_COUNT)
        {
            if (quiet_counter <= 0)
                pcmbuf_soft_mode(false);

            break;
        }

        /* Fall-through */
    case Q_VOICE_STOP:
        LOGFQUEUE("voice < Q_VOICE_STOP");
        cancel_cpu_boost();
        voice_stop_playback();
        break;

    /* No default: no other message ids are sent */
    }

    return VOICE_STATE_MESSAGE;
}
예제 #10
0
void buffering_thread(void)
{
    bool filling = false;
    struct queue_event ev;

    while (true)
    {
        if (!filling) {
            cancel_cpu_boost();
        }

        queue_wait_w_tmo(&buffering_queue, &ev, filling ? 5 : HZ/2);

        switch (ev.id)
        {
            case Q_START_FILL:
                LOGFQUEUE("buffering < Q_START_FILL %d", (int)ev.data);
                /* Call buffer callbacks here because this is one of two ways
                 * to begin a full buffer fill */
                send_event(BUFFER_EVENT_BUFFER_LOW, 0);
                shrink_buffer();
                queue_reply(&buffering_queue, 1);
                filling |= buffer_handle((int)ev.data);
                break;

            case Q_BUFFER_HANDLE:
                LOGFQUEUE("buffering < Q_BUFFER_HANDLE %d", (int)ev.data);
                queue_reply(&buffering_queue, 1);
                buffer_handle((int)ev.data);
                break;

            case Q_RESET_HANDLE:
                LOGFQUEUE("buffering < Q_RESET_HANDLE %d", (int)ev.data);
                queue_reply(&buffering_queue, 1);
                reset_handle((int)ev.data);
                break;

            case Q_CLOSE_HANDLE:
                LOGFQUEUE("buffering < Q_CLOSE_HANDLE %d", (int)ev.data);
                queue_reply(&buffering_queue, close_handle((int)ev.data));
                break;

            case Q_HANDLE_ADDED:
                LOGFQUEUE("buffering < Q_HANDLE_ADDED %d", (int)ev.data);
                /* A handle was added: the disk is spinning, so we can fill */
                filling = true;
                break;

            case Q_BASE_HANDLE:
                LOGFQUEUE("buffering < Q_BASE_HANDLE %d", (int)ev.data);
                base_handle_id = (int)ev.data;
                break;

#ifndef SIMULATOR
            case SYS_USB_CONNECTED:
                LOGFQUEUE("buffering < SYS_USB_CONNECTED");
                usb_acknowledge(SYS_USB_CONNECTED_ACK);
                usb_wait_for_disconnect(&buffering_queue);
                break;
#endif

            case SYS_TIMEOUT:
                LOGFQUEUE_SYS_TIMEOUT("buffering < SYS_TIMEOUT");
                break;
        }

        update_data_counters();

        /* If the buffer is low, call the callbacks to get new data */
        if (num_handles > 0 && data_counters.useful <= conf_watermark)
            send_event(BUFFER_EVENT_BUFFER_LOW, 0);

#if 0
        /* TODO: This needs to be fixed to use the idle callback, disable it
         * for simplicity until its done right */
#if MEM > 8
        /* If the disk is spinning, take advantage by filling the buffer */
        else if (storage_disk_is_active() && queue_empty(&buffering_queue))
        {
            if (num_handles > 0 && data_counters.useful <= high_watermark)
                send_event(BUFFER_EVENT_BUFFER_LOW, 0);

            if (data_counters.remaining > 0 && BUF_USED <= high_watermark)
            {
                /* This is a new fill, shrink the buffer up first */
                if (!filling)
                    shrink_buffer();
                filling = fill_buffer();
                update_data_counters();
            }
        }
#endif
#endif

        if (queue_empty(&buffering_queue)) {
            if (filling) {
                if (data_counters.remaining > 0 && BUF_USED < buffer_len)
                    filling = fill_buffer();
                else if (data_counters.remaining == 0)
                    filling = false;
            }
            else if (ev.id == SYS_TIMEOUT)
            {
                if (data_counters.remaining > 0 &&
                    data_counters.useful <= conf_watermark) {
                    shrink_buffer();
                    filling = fill_buffer();
                }
            }
        }
    }
}
예제 #11
0
            /* GUI boost build gets immediate kick, otherwise at least 3
               messages had to be there */
        #ifndef HAVE_GUI_BOOST
            if (queue_count(&button_queue) >= 2)
        #endif
                button_boost(true);

            break; 
        }

        if (button_boosted && TIME_AFTER(current_tick, button_unboost_tick))
            button_boost(false);
    }
    while (timeout);
}
#else /* ndef HAVE_ADJUSTABLE_CPU_FREQ */
static inline void button_queue_wait(struct queue_event *evp, int timeout)
{
    queue_wait_w_tmo(&button_queue, evp, timeout);
}
예제 #12
0
static void sd_thread(void)
{
    struct queue_event ev;

    while (1)
    {
        queue_wait_w_tmo(&sd_queue, &ev, HZ);

        switch(ev.id)
        {
        case SYS_HOTSWAP_INSERTED:
        case SYS_HOTSWAP_EXTRACTED:
        {
            fat_lock();          /* lock-out FAT activity first -
                                    prevent deadlocking via disk_mount that
                                    would cause a reverse-order attempt with
                                    another thread */
            mutex_lock(&sd_mutex); /* lock-out card activity - direct calls
                                    into driver that bypass the fat cache */

            /* We now have exclusive control of fat cache and sd */

            disk_unmount(sd_first_drive);     /* release "by force", ensure file
                                    descriptors aren't leaked and any busy
                                    ones are invalid if mounting */
            /* Force card init for new card, re-init for re-inserted one or
             * clear if the last attempt to init failed with an error. */
            card_info.initialized = 0;

            if(ev.id == SYS_HOTSWAP_INSERTED)
            {
                int ret = sd_init_card();
                if(ret == 0)
                {
                    ret = disk_mount(sd_first_drive); /* 0 if fail */
                    if(ret < 0)
                        DEBUGF("disk_mount failed: %d", ret);
                }
                else
                    DEBUGF("sd_init_card failed: %d", ret);
            }

            /*
             * Mount succeeded, or this was an EXTRACTED event,
             * in both cases notify the system about the changed filesystems
             */
            if(card_info.initialized)
                queue_broadcast(SYS_FS_CHANGED, 0);

            /* Access is now safe */
            mutex_unlock(&sd_mutex);
            fat_unlock();
            }
            break;
        case SYS_TIMEOUT:
            if(!TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
                sd_enable(false);
            break;
        case SYS_USB_CONNECTED:
            usb_acknowledge(SYS_USB_CONNECTED_ACK);
            /* Wait until the USB cable is extracted again */
            usb_wait_for_disconnect(&sd_queue);
            break;
        }
    }
}