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;
        }
    }
}
Exemplo n.º 2
0
void sim_thread(void)
{
    struct queue_event ev;
    
    while (1)
    {
        queue_wait(&sim_queue, &ev);
        switch(ev.id)
        {
            case SIM_SCREENDUMP:
                screen_dump();
#ifdef HAVE_REMOTE_LCD
                remote_screen_dump();
#endif
                break;
        }
    }
}
Exemplo n.º 3
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
        }
    }
}