void sim_thread(void)
{
    struct queue_event ev;
    long last_broadcast_tick = current_tick;
    int num_acks_to_expect;
    
    while (1)
    {
        queue_wait(&sim_queue, &ev);
        switch(ev.id)
        {
            case SIM_SCREENDUMP:
                screen_dump();
#ifdef HAVE_REMOTE_LCD
                remote_screen_dump();
#endif
                break;
            case SIM_USB_INSERTED:
            /* from firmware/usb.c: */
                /* Tell all threads that they have to back off the storage.
                   We subtract one for our own thread. Expect an ACK for every
                   listener for each broadcast they received. If it has been too
                   long, the user might have entered a screen that didn't ACK
                   when inserting the cable, such as a debugging screen. In that
                   case, reset the count or else USB would be locked out until
                   rebooting because it most likely won't ever come. Simply
                   resetting to the most recent broadcast count is racy. */
                if(TIME_AFTER(current_tick, last_broadcast_tick + HZ*5))
                {
                    num_acks_to_expect = 0;
                    last_broadcast_tick = current_tick;
                }

                num_acks_to_expect += queue_broadcast(SYS_USB_CONNECTED, 0) - 1;
                DEBUGF("USB inserted. Waiting for %d acks...\n",
                       num_acks_to_expect);
                break;
            case SYS_USB_CONNECTED_ACK:
                if(num_acks_to_expect > 0 && --num_acks_to_expect == 0)
                {
                    DEBUGF("All threads have acknowledged the connect.\n");
                }
                else
                {
                    DEBUGF("usb: got ack, %d to go...\n",
                           num_acks_to_expect);
                }
                break;
            case SIM_USB_EXTRACTED:
                /* in usb.c, this is only done for exclusive storage
                 * do it here anyway but don't depend on the acks */
                queue_broadcast(SYS_USB_DISCONNECTED, 0);
                break;
            default:
                DEBUGF("sim_tasks: unhandled event: %ld\n", ev.id);
                break;
        }
    }
}
Exemple #2
0
static void sd_detect_callback(int ssp)
{
    (void)ssp;

    /* This is called only if the state was stable for 300ms - check state
     * and post appropriate event. */
    if(imx233_ssp_sdmmc_detect(SD_SSP))
        queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
    else
        queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
    imx233_ssp_sdmmc_setup_detect(SD_SSP, true, sd_detect_callback);
}
/*
 * Detect charger inserted. Return true if the state is transistional.
 */
static inline bool detect_charger(unsigned int pwr)
{
    /*
     * Detect charger plugged/unplugged transitions.  On a plugged or
     * unplugged event, we return immediately, run once through the main
     * loop (including the subroutines), and end up back here where we
     * transition to the appropriate steady state charger on/off state.
     */
    if (pwr & POWER_INPUT_CHARGER) {
        switch (charger_input_state)
        {
        case NO_CHARGER:
        case CHARGER_UNPLUGGED:
            charger_input_state = CHARGER_PLUGGED;
            break;

        case CHARGER_PLUGGED:
            queue_broadcast(SYS_CHARGER_CONNECTED, 0);
            last_sent_battery_level = 0;
            charger_input_state = CHARGER;
            break;

        case CHARGER:
            /* Steady state */
            return false;
        }
    }
    else {    /* charger not inserted */
        switch (charger_input_state)
        {
        case NO_CHARGER:
            /* Steady state */
            return false;

        case CHARGER_UNPLUGGED:
            queue_broadcast(SYS_CHARGER_DISCONNECTED, 0);
            last_sent_battery_level = 100;
            charger_input_state = NO_CHARGER;
            break;

        case CHARGER_PLUGGED:
        case CHARGER:
            charger_input_state = CHARGER_UNPLUGGED;
            break;
        }
    }

    /* Transitional state */
    return true;
}
Exemple #4
0
/**
 * Gets called by the policy framework if an important
 * event arrives: Incoming calls etc.
 */
void maemo_tell_rockbox_to_stop_audio(void)
{
    sim_enter_irq_handler();
    queue_broadcast(SYS_CALL_INCOMING, 0);
    sim_exit_irq_handler();

    osso_system_note_infoprint(maemo_osso_ctx, "Stopping rockbox playback", NULL);
}
Exemple #5
0
int usb_release_exclusive_storage(void)
{
    int num_acks_to_expect;
#ifdef HAVE_USBSTACK
    exclusive_storage_access = false;
#endif /* HAVE_USBSTACK */
    /* Tell all threads that we are back in business */
    num_acks_to_expect =
        queue_broadcast(SYS_USB_DISCONNECTED, 0) - 1;
    DEBUGF("USB extracted. Waiting for ack from %d threads...\n",
           num_acks_to_expect);
    return num_acks_to_expect;
}
Exemple #6
0
int sd_init(void)
{
    mutex_init(&sd_mutex);
    queue_init(&sd_queue, true);
    create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
            sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));

    #ifdef SANSA_FUZEPLUS
    imx233_ssp_setup_ssp1_sd_mmc_pins(true, 4, PINCTRL_DRIVE_8mA, false);
    #endif
    imx233_ssp_sdmmc_setup_detect(SD_SSP, true, sd_detect_callback);

    if(imx233_ssp_sdmmc_detect(SD_SSP))
        queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
    
    return 0;
}
Exemple #7
0
void usb_storage_init_connection(void)
{
    logf("ums: set config");
    /* prime rx endpoint. We only need room for commands */
    state = WAITING_FOR_COMMAND;

#if (CONFIG_CPU == IMX31L || defined(CPU_TCC77X) || defined(CPU_TCC780X) || \
     defined(BOOTLOADER) || CONFIG_CPU == DM320) && !defined(CPU_PP502x)
    static unsigned char _cbw_buffer[MAX_CBW_SIZE]
        USB_DEVBSS_ATTR __attribute__((aligned(32)));
    cbw_buffer = (void *)_cbw_buffer;

    static unsigned char _transfer_buffer[ALLOCATE_BUFFER_SIZE]
        USB_DEVBSS_ATTR __attribute__((aligned(32)));
    tb.transfer_buffer = (void *)_transfer_buffer;
#ifdef USB_USE_RAMDISK
    static unsigned char _ramdisk_buffer[RAMDISK_SIZE*SECTOR_SIZE];
    ramdisk_buffer = _ramdisk_buffer;
#endif
#else
    /* TODO : check if bufsize is at least 32K ? */
    size_t bufsize;
    unsigned char * audio_buffer;

    audio_buffer = audio_get_buffer(false,&bufsize);
#if defined(UNCACHED_ADDR) && CONFIG_CPU != AS3525
    cbw_buffer = (void *)UNCACHED_ADDR((unsigned int)(audio_buffer+31) & 0xffffffe0);
#else
    cbw_buffer = (void *)((unsigned int)(audio_buffer+31) & 0xffffffe0);
#endif
    tb.transfer_buffer = cbw_buffer + MAX_CBW_SIZE;
    commit_discard_dcache();
#ifdef USB_USE_RAMDISK
    ramdisk_buffer = tb.transfer_buffer + ALLOCATE_BUFFER_SIZE;
#endif
#endif
    usb_drv_recv(ep_out, cbw_buffer, MAX_CBW_SIZE);

    int i;
    for(i=0;i<storage_num_drives();i++) {
        locked[i] = false;
        ejected[i] = !check_disk_present(IF_MD(i));
        queue_broadcast(SYS_USB_LUN_LOCKED, (i<<16)+0);
    }
}
/* Monitor remote hotswap */
static void remote_tick(void)
{
    static bool last_status = false;
    static int countdown = 0;
    static int init_delay = 0;
    bool current_status;
    int val;
    int level;

    current_status = remote_detect();
    /* Only report when the status has changed */
    if (current_status != last_status)
    {
        last_status = current_status;
        countdown = current_status ? 20*HZ : 1;
    }
    else
    {
        /* Count down until it gets negative */
        if (countdown >= 0)
            countdown--;

        if (current_status)
        {
            if (!(countdown % 8))
            {
                /* Determine which type of remote it is */
                level = disable_irq_save();
                val = adc_scan(ADC_REMOTEDETECT);
                restore_irq(level);

                if (val < ADCVAL_H100_LCD_REMOTE_HOLD)
                {
                    if (val < ADCVAL_H100_LCD_REMOTE)
                        if (val < ADCVAL_H300_LCD_REMOTE)
                            _remote_type = REMOTETYPE_H300_LCD;  /* hold off */
                        else
                            _remote_type = REMOTETYPE_H100_LCD;  /* hold off */
                    else
                        if (val < ADCVAL_H300_LCD_REMOTE_HOLD)
                            _remote_type = REMOTETYPE_H300_LCD;  /* hold on */
                        else
                            _remote_type = REMOTETYPE_H100_LCD;  /* hold on */

                    if (--init_delay <= 0)
                    {
                        queue_broadcast(SYS_REMOTE_PLUGGED, 0);
                        init_delay = 6;
                    }
                }
                else
                {
                    _remote_type = REMOTETYPE_H300_NONLCD; /* hold on or off */
                }
            }
        }
        else
        {
            if (countdown == 0)
            {
                _remote_type = REMOTETYPE_UNPLUGGED;

                queue_broadcast(SYS_REMOTE_UNPLUGGED, 0);
            }
        }
    }

    /* handle chip select timeout */
    if (remote_cs_countdown >= 0)
        remote_cs_countdown--;
    if (remote_cs_countdown == 0)
        CS_HI;
}
Exemple #9
0
static void usb_thread(void)
{
    int num_acks_to_expect = 0;
    struct queue_event ev;

    while(1)
    {
        queue_wait(&usb_queue, &ev);
        switch(ev.id)
        {
#ifdef USB_DRIVER_CLOSE
            case USB_QUIT:
                return;
#endif
#ifdef HAVE_USBSTACK
            case USB_TRANSFER_COMPLETION:
                usb_core_handle_transfer_completion(
                    (struct usb_transfer_completion_event_data*)ev.data);
                break;
#endif
#ifdef USB_DETECT_BY_DRV
            /* In this case, these events the handle cable insertion USB
             * driver determines INSERTED/EXTRACTED state. */
            case USB_POWERED:
                /* Set the state to USB_POWERED for now and enable the driver
                 * to detect a bus reset only. If a bus reset is detected,
                 * USB_INSERTED will be received. */
                usb_state = USB_POWERED;
                usb_enable(true);
                break;

            case USB_UNPOWERED:
                usb_enable(false);
                /* This part shouldn't be obligatory for anything that can
                 * reliably detect removal of the data lines. USB_EXTRACTED
                 * could be posted on that event while bus power remains
                 * available. */
                queue_post(&usb_queue, USB_EXTRACTED, 0);
                break;
#endif /* USB_DETECT_BY_DRV */
            case USB_INSERTED:
#ifdef HAVE_LCD_BITMAP
                if(do_screendump_instead_of_usb)
                {
                    usb_state = USB_SCREENDUMP;
                    screen_dump();
#ifdef HAVE_REMOTE_LCD
                    remote_screen_dump();
#endif
                    break;
                }
#endif
#ifdef HAVE_USB_POWER
                if(usb_power_button())
                {
                    /* Only charging is desired */
                    usb_state = USB_POWERED;
#ifdef HAVE_USBSTACK
#ifdef USB_ENABLE_STORAGE
                    usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, false);
#endif

#ifdef USB_ENABLE_HID
#ifdef USB_ENABLE_CHARGING_ONLY
                    usb_core_enable_driver(USB_DRIVER_HID, false);
#else
                    usb_core_enable_driver(USB_DRIVER_HID, true);
#endif /* USB_ENABLE_CHARGING_ONLY */
#endif /* USB_ENABLE_HID */

#ifdef USB_ENABLE_CHARGING_ONLY
                    usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, true);
#endif
                    usb_attach();
#endif
                    break;
                }
#endif /* HAVE_USB_POWER */
#ifdef HAVE_USBSTACK
#ifdef HAVE_USB_POWER
                /* Set the state to USB_POWERED for now. If permission to connect
                 * by threads and storage is granted it will be changed to
                 * USB_CONNECTED. */
                usb_state = USB_POWERED;
#endif
#ifdef USB_ENABLE_STORAGE
                usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, true);
#endif
#ifdef USB_ENABLE_HID
                usb_core_enable_driver(USB_DRIVER_HID, usb_hid);
#endif
#ifdef USB_ENABLE_CHARGING_ONLY
                usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, false);
#endif

                /* Check any drivers enabled at this point for exclusive storage
                 * access requirements. */
                exclusive_storage_access = usb_core_any_exclusive_storage();

                if(!exclusive_storage_access)
                {
                    usb_attach();
                    break;
                }
#endif /* HAVE_USBSTACK */
                /* Tell all threads that they have to back off the storage.
                   We subtract one for our own thread. */
                num_acks_to_expect = queue_broadcast(SYS_USB_CONNECTED, 0) - 1;
                DEBUGF("USB inserted. Waiting for ack from %d threads...\n",
                       num_acks_to_expect);
                break;

            case SYS_USB_CONNECTED_ACK:
                if(num_acks_to_expect > 0 && --num_acks_to_expect == 0)
                {
                    DEBUGF("All threads have acknowledged the connect.\n");
                    usb_slave_mode(true);
                    usb_state = USB_INSERTED;
                }
                else
                {
                    DEBUGF("usb: got ack, %d to go...\n",
                           num_acks_to_expect);
                }
                break;

            case USB_EXTRACTED:
#ifdef HAVE_LCD_BITMAP
                if(usb_state == USB_SCREENDUMP)
                {
                    usb_state = USB_EXTRACTED;
                    break; /* Connected for screendump only */
                }
#endif
#ifndef HAVE_USBSTACK /* Stack must undo this if POWERED state was transitional */
#ifdef HAVE_USB_POWER
                if(usb_state == USB_POWERED)
                {
                    usb_state = USB_EXTRACTED;
                    break;
                }
#endif
#endif /* HAVE_USBSTACK */
                if(usb_state == USB_INSERTED)
                {
                    /* Only disable the USB mode if we really have enabled it
                       some threads might not have acknowledged the
                       insertion */
                    usb_slave_mode(false);
                }

                usb_state = USB_EXTRACTED;
#ifdef HAVE_USBSTACK
                if(!exclusive_storage_access)
                {
#ifndef USB_DETECT_BY_DRV /* Disabled handling USB_UNPOWERED */
                    usb_enable(false);
#endif
                    break;
                }

#endif /* HAVE_USBSTACK */
                num_acks_to_expect = usb_release_exclusive_storage();

                break;

            case SYS_USB_DISCONNECTED_ACK:
                if(num_acks_to_expect > 0 && --num_acks_to_expect == 0)
                {
                    DEBUGF("All threads have acknowledged. "
                           "We're in business.\n");
                }
                else
                {
                    DEBUGF("usb: got ack, %d to go...\n",
                           num_acks_to_expect);
                }
                break;

#ifdef HAVE_HOTSWAP
            case SYS_HOTSWAP_INSERTED:
            case SYS_HOTSWAP_EXTRACTED:
#ifdef HAVE_USBSTACK
                usb_core_hotswap_event(1,ev.id == SYS_HOTSWAP_INSERTED);
#else  /* !HAVE_USBSTACK */
                if(usb_state == USB_INSERTED)
                {
#if (CONFIG_STORAGE & STORAGE_MMC)
                    usb_enable(false);
                    usb_mmc_countdown = HZ/2; /* re-enable after 0.5 sec */
#endif /* STORAGE_MMC */
                }
#endif /* HAVE_USBSTACK */
                break;

#if (CONFIG_STORAGE & STORAGE_MMC)
            case USB_REENABLE:
                if(usb_state == USB_INSERTED)
                    usb_enable(true);  /* reenable only if still inserted */
                break;
#endif /* STORAGE_MMC */
#endif /* HAVE_HOTSWAP */

#ifdef USB_FIREWIRE_HANDLING
            case USB_REQUEST_REBOOT:
#ifdef HAVE_USB_POWER
                if (usb_reboot_button())
#endif
                    try_reboot();
                break;
#endif /* USB_FIREWIRE_HANDLING */

#if defined(HAVE_USB_CHARGING_ENABLE) && defined(HAVE_USBSTACK)
            case USB_CHARGER_UPDATE:
                usb_charging_maxcurrent_change(usb_charging_maxcurrent());
                break;
#endif
        }
    }
}
Exemple #10
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;
        }
    }
}