Exemple #1
0
/****************************************************************************
NAME 
    usbFileName
    
DESCRIPTION
    Get file name from USB root
    
RETURNS
    void
*/ 
static void usbFileName(usb_file_info* root, usb_file_name_info* result)
{
    Source source = StreamFileSource(root->index);
    usb_file_name* file = (usb_file_name*)SourceMap(source);

    result->size = 0;

    if(file)
    {
        memmove(result->name, file->name, USB_NAME_SIZE);
        for(result->size = 0; result->size < USB_NAME_SIZE; result->size++)
            if(file->name[result->size] == ' ')
                break;
        *(result->name + result->size) = '.';
        result->size++;
        memmove(result->name + result->size, file->ext, USB_EXT_SIZE);
        result->size += USB_EXT_SIZE;
        SourceClose(source);
    }
#ifdef DEBUG_USB
    {
    uint8 count;
    USB_DEBUG(("USB: File Name "));
    for(count = 0; count < result->size; count++)
        USB_DEBUG(("%c", result->name[count]));
    USB_DEBUG(("\n"));
    }
#endif
}
Exemple #2
0
/****************************************************************************
NAME 
    usbAudioRoute
    
DESCRIPTION
    Connect USB audio stream
    
RETURNS
    void
*/ 
void usbAudioRoute(void)
{
    AudioPluginFeatures features;
    Sink sink;
    Source source;
    uint16 sampleFreq;
    UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_AUDIO_SOURCE, (uint16*)(&source));
    /* Note: UsbDeviceClassGetValue uses uint16 which limits max value of sample frequency to 64k (uint 16 has range 0->65536) */
    UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_SAMPLE_FREQ, &sampleFreq);
    sink = StreamSinkFromSource(source);
    /* determine additional features applicable for this audio plugin */
    features.stereo = (AUDIO_PLUGIN_FORCE_STEREO || theSink.features.stereo);
    features.use_i2s_output = theSink.features.UseI2SOutputCapability;

    USB_DEBUG(("USB: Audio "));
    /* Check Audio configured (sink will be NULL if VM USB not enabled) */
    if(USB_CLASS_ENABLED(USB_DEVICE_CLASS_AUDIO) && sink)
    {
        USB_DEBUG(("Configured "));
        if(usbAudioIsAttached())
        {
            USB_DEBUG(("Attached\n"));
            if(theSink.routed_audio != sink)
            {
                Task plugin;
                AUDIO_MODE_T mode;
                uint16 volume = usbGetVolume(&mode);
                const usb_plugin_info* plugin_info = usbAudioGetPluginInfo(&plugin, theSink.usb.config.plugin_type, theSink.usb.config.plugin_index);

                theSink.routed_audio = sink;
                UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_AUDIO_SINK, (uint16*)(&theSink.cvc_params.usb_params.usb_sink));
                /* Make sure we're using correct parameters for USB */
                theSink.a2dp_link_data->a2dp_audio_connect_params.mode_params = &theSink.a2dp_link_data->a2dp_audio_mode_params;

                USB_DEBUG(("USB: Connect 0x%X 0x%X", (uint16)sink, (uint16)(theSink.cvc_params.usb_params.usb_sink)));

#ifdef ENABLE_SUBWOOFER
            /* set the sub woofer link type prior to passing to audio connect */
            theSink.a2dp_link_data->a2dp_audio_connect_params.sub_woofer_type  = AUDIO_SUB_WOOFER_NONE;  
            theSink.a2dp_link_data->a2dp_audio_connect_params.sub_sink  = NULL;  
            /* bits inverted in dsp plugin */                
            sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,TRUE);
#else
            /* no subwoofer support, set the sub woofer bypass bit in music config message sent o dsp */
            sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,FALSE);
#endif          

                /* use a2dp connect parameters */
                /* sample frequency is not fixed so read this from usb library */
                if(plugin_info->plugin_type == usb_plugin_stereo)
                    AudioConnect(plugin, sink, AUDIO_SINK_USB, theSink.codec_task, volume, sampleFreq, features, mode, 0, powerManagerGetLBIPM(), &theSink.a2dp_link_data->a2dp_audio_connect_params, &theSink.task);
                /* all other plugins use cvc connect parameters */                
                else
                    AudioConnect(plugin, sink, AUDIO_SINK_USB, theSink.codec_task, volume, sampleFreq, features, mode, 0, powerManagerGetLBIPM(), &theSink.cvc_params, &theSink.task);
                
            }
        }
    }
    USB_DEBUG(("\n"));
}
Exemple #3
0
STATIC
VOID
UsbDisconnectDriver (
  IN USB_INTERFACE        *UsbIf
  )
/*++

Routine Description:

  Disconnect the USB interface with its driver. 

Arguments:

  UsbIf   - The interface to disconnect driver from

Returns:

  None
  
--*/
{
  EFI_TPL                 OldTpl;
  
  //
  // Release the hub if it's a hub controller, otherwise 
  // disconnect the driver if it is managed by other drivers.
  //
  if (UsbIf->IsHub) {
    UsbIf->HubApi->Release (UsbIf);

  } else if (UsbIf->IsManaged) {
    //
    // This function is called in both UsbIoControlTransfer and
    // the timer callback in hub enumeration. So, at least it is
    // called at EFI_TPL_CALLBACK. Some driver sitting on USB has
    // twisted TPL used. It should be no problem for us to connect
    // or disconnect at CALLBACK.
    //
    OldTpl           = UsbGetCurrentTpl ();
    USB_DEBUG (("UsbDisconnectDriver: old TPL is %d\n", OldTpl));

    gBS->RestoreTPL (EFI_TPL_CALLBACK);
  
    gBS->DisconnectController (UsbIf->Handle, NULL, NULL);
    UsbIf->IsManaged = FALSE;

    USB_DEBUG (("UsbDisconnectDriver: TPL after disconnect is %d\n", UsbGetCurrentTpl()));
    ASSERT (UsbGetCurrentTpl () == EFI_TPL_CALLBACK);

    gBS->RaiseTPL (OldTpl);
  }
}
Exemple #4
0
EFI_STATUS
UsbSelectSetting (
  IN USB_INTERFACE_DESC   *IfDesc,
  IN UINT8                Alternate
  )
/*++

Routine Description:

  Select an alternate setting for the interface. 
  Each interface can have several mutually exclusive
  settings. Only one setting is active. It will
  also reset its endpoints' toggle to zero.

Arguments:

  IfDesc    - The interface descriptor to set
  Alternate - The alternate setting number to locate

Returns:

  EFI_NOT_FOUND - There is no setting with this alternate index
  EFI_SUCCESS   - The interface is set to Alternate setting.

--*/
{
  USB_INTERFACE_SETTING   *Setting;
  UINT8                   Index;

  //
  // Locate the active alternate setting
  //
  Setting = NULL;

  for (Index = 0; Index < IfDesc->NumOfSetting; Index++) {
    Setting = IfDesc->Settings[Index];

    if (Setting->Desc.AlternateSetting == Alternate) {
      break;
    }
  }

  if (Index == IfDesc->NumOfSetting) {
    return EFI_NOT_FOUND;
  }

  IfDesc->ActiveIndex = Index;

  USB_DEBUG (("UsbSelectSetting: setting %d selected for interface %d\n", 
              Alternate, Setting->Desc.InterfaceNumber));

  //
  // Reset the endpoint toggle to zero
  //
  for (Index = 0; Index < Setting->Desc.NumEndpoints; Index++) {
    Setting->Endpoints[Index]->Toggle = 0;
  }

  return EFI_SUCCESS;
}
Exemple #5
0
/**
 * \brief Sets the address of a new device
 */
usb_error_t usb_req_set_address(struct usb_device *dev, uint16_t addr)
{
    USB_DEBUG_TR_ENTER;
    struct usb_device_request req;
    usb_error_t err = USB_ERR_INVAL;

    req.bRequest = USB_REQUEST_SET_ADDRESS;
    req.wValue = addr;
    req.wIndex = 0;
    req.wLength = 0;
    req.bType.recipient = USB_REQUEST_RECIPIENT_DEVICE;
    req.bType.type = USB_REQUEST_TYPE_STANDARD;
    req.bType.direction = USB_REQUEST_WRITE;

    if (dev->controller->hcdi_bus_fn->set_address != NULL) {
        USB_DEBUG("set_address function set.\n");
        err = (dev->controller->hcdi_bus_fn->set_address)(dev, addr);
    }

    if (err != USB_ERR_INVAL) {
        return (err);
    }

    return (usb_exec_request(dev, 0, &req, NULL, NULL));
}
Exemple #6
0
/****************************************************************************
NAME 
    usbSetLowPowerMode
    
DESCRIPTION
    If delay is non zero queue a message to reset into low powered mode. If
    delay is zero do nothing.
    
RETURNS
    void
*/ 
static void usbSetLowPowerMode(uint8 delay)
{
    /* Only queue low power mode if not enumerated and attached to normal host/hub */
    if(!theSink.usb.enumerated && delay && (UsbAttachedStatus() == HOST_OR_HUB)) 
    {
        USB_DEBUG(("USB: Queue low power in %d sec\n", delay));
        MessageSendLater(&theSink.task, EventUsbLowPowerMode, 0, D_SEC(delay));
    }
}
Exemple #7
0
/****************************************************************************
NAME 
    usbAudioSinkMatch
    
DESCRIPTION
    Compare sink to the USB audio sink
    
RETURNS
    TRUE if sink matches USB audio sink, otherwise FALSE
*/ 
bool usbAudioSinkMatch(Sink sink)
{
    Source usb_source = NULL;
    UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_AUDIO_SOURCE, (uint16*)&usb_source);

    USB_DEBUG(("USB: usbAudioSinkMatch sink %x = %x, enabled = %x\n", (uint16)sink , (uint16)StreamSinkFromSource(usb_source), USB_CLASS_ENABLED(USB_DEVICE_CLASS_AUDIO) ));

    return (USB_CLASS_ENABLED(USB_DEVICE_CLASS_AUDIO) && sink && (sink == StreamSinkFromSource(usb_source)));
}
Exemple #8
0
/****************************************************************************
NAME 
    usbGetAudioSink
    
DESCRIPTION
    check USB state and return sink if available
    
RETURNS
   sink if available, otherwise 0
*/ 
Sink usbGetAudioSink(void)
{
    Source usb_source = NULL;
    Sink sink = NULL;
    UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_AUDIO_SOURCE, (uint16*)&usb_source);
    
    /* if the usb lead is attached and the speaker is active, try to obtain the audio sink */
    if((usbAudioIsAttached())&&(theSink.usb.spkr_active))
    {
        /* attempt to obtain USB audio sink */
        sink = StreamSinkFromSource(usb_source);
        USB_DEBUG(("USB: usbGetAudioSink sink %x, enabled = %x\n", (uint16)sink , USB_CLASS_ENABLED(USB_DEVICE_CLASS_AUDIO) ));
    }
    /* USB not attached */
    else
        USB_DEBUG(("USB: usbGetAudioSink sink %x, enabled = %x, speaker active = %x\n", (uint16)sink , USB_CLASS_ENABLED(USB_DEVICE_CLASS_AUDIO), theSink.usb.spkr_active ));
    
    return sink;
}
/**
 * \brief   this function allocates the resources for a number of usb transfers
 *
 * \param   device      the device we want to allocate the transfers
 * \param   ifaces      array of interfaces
 * \param   usb_xfers   pointer to an array of usb_xfer
 * \param   setups      setup parameter array
 * \para    setup_count the number of setups we have to do
 * \
 */
usb_error_t usb_transfer_setup(struct usb_device *device, const uint8_t iface,
                               struct usb_xfer **ret_xfer, const struct usb_xfer_config *setup)
{
    USB_DEBUG_TR_ENTER;

    struct usb_xfer_setup_params params;
    memset(&params, 0, sizeof(params));

    params.device = device;
    params.speed = device->speed;
    params.hc_max_packet_count = 1;
    params.err = USB_ERR_OK;
    params.type = setup->usb_type;
    params.size[0] = 0;
    params.buf = NULL;
    params.xfer_setup = setup;

    struct usb_endpoint *ep = usb_endpoint_lookup(device, iface, setup);

    if ((ep == NULL) || (ep->pipe_fn == NULL)) {
        USB_DEBUG_XFER("WARNING: No associated pipe!\n");
        USB_DEBUG_TR_RETURN;
        return (USB_ERR_NO_PIPE);
    }

    struct usb_xfer *xfer = malloc(sizeof(struct usb_xfer));
    memset(xfer, 0, sizeof(*xfer));
    xfer->xfer_id = device->xfer_id++;
    xfer->device_xfers_next = device->xfers;
    device->xfers = xfer;
    xfer->xfer_done_cb = setup->xfer_done_cb;
    xfer->type = setup->usb_type;
    xfer->device_address = device->device_address;
    xfer->host_controller = device->controller;
    xfer->device = device;
    xfer->endpoint = ep;
    params.curr_xfer = xfer;
    params.pipe_fn = xfer->endpoint->pipe_fn;

    (device->controller->hcdi_bus_fn->xfer_setup)(&params);

    if (params.err != USB_ERR_OK) {
        USB_DEBUG(
            "ERROR: hcdi_xfer_setup failed: %s\n", usb_get_error_string(params.err));
        return (params.err);
    }

    xfer->endpoint->ref_allocation++;
    assert(xfer->endpoint->ref_allocation);

    *ret_xfer = xfer;

    USB_DEBUG_TR_RETURN;
    return (USB_ERR_OK);
}
Exemple #10
0
EFI_STATUS
UsbRemoveDevice (
  IN USB_DEVICE           *Device
  )
/*++

Routine Description:

  Remove the device and all its children from the bus.

Arguments:

  Device  - The device to remove 

Returns:

  EFI_SUCCESS - The device is removed

--*/
{
  USB_BUS                 *Bus;
  USB_DEVICE              *Child;
  EFI_STATUS              Status;
  UINT8                   Index;

  Bus = Device->Bus;

  //
  // Remove all the devices on its downstream ports. Search from devices[1]. 
  // Devices[0] is the root hub.
  //
  for (Index = 1; Index < USB_MAX_DEVICES; Index++) {
    Child = Bus->Devices[Index];

    if ((Child == NULL) || (Child->ParentAddr != Device->Address)) {
      continue;
    }

    Status = UsbRemoveDevice (Child);

    if (EFI_ERROR (Status)) {
      USB_ERROR (("UsbRemoveDevice: failed to remove child, ignore error\n"));
      Bus->Devices[Index] = NULL;
    }
  }

  UsbRemoveConfig (Device);

  USB_DEBUG (("UsbRemoveDevice: device %d removed\n", Device->Address));

  Bus->Devices[Device->Address] = NULL;
  UsbFreeDevice (Device);

  return EFI_SUCCESS;
}
Exemple #11
0
/****************************************************************************
NAME 
    usbSetBootMode
    
DESCRIPTION
    Set the boot mode to default or low power
    
RETURNS
    void
*/ 
void usbSetBootMode(uint8 bootmode)
{
    /* Don't change anything if battery charging disabled */
    if(!USB_CLASS_ENABLED(USB_DEVICE_CLASS_TYPE_BATTERY_CHARGING))
        return;

    if(BootGetMode() != bootmode)
    {
        USB_DEBUG(("USB: Set Mode %d\n", bootmode));
        BootSetMode(bootmode);
    }
}
Exemple #12
0
/****************************************************************************
NAME 
    usbAudioDisconnect
    
DESCRIPTION
    Disconnect USB audio stream
    
RETURNS
    void
*/ 
void usbAudioDisconnect(void)
{
    if(usbAudioSinkMatch(theSink.routed_audio))
    {
        USB_DEBUG(("USB: Disconnect 0x%X\n", (uint16)theSink.routed_audio));
        AudioDisconnect();
        theSink.routed_audio = 0;
        /* If speaker is in use then pause */
        if(theSink.usb.spkr_active)
            UsbDeviceClassSendEvent(USB_DEVICE_CLASS_EVENT_HID_CONSUMER_TRANSPORT_PAUSE);
    }
}
Exemple #13
0
/**
 * \brief   initiates the execution of an existing USB transfer
 *
 * \param   tid the ID of the transfer to start
 *
 * \return  USB_ERR_OK on sucess
 *          USB_ERR_XX on failure
 */
usb_error_t usb_transfer_start(usb_xfer_id_t tid)
{
    struct usb_xfer_state *st = usb_xfer_get_state(tid);
    if (st == NULL) {
        USB_DEBUG("inavlid transfer id");
        return (USB_ERR_INVAL);
    }


    uint32_t ret_error = 0;

    usb_manager.vtbl.transfer_start(&usb_manager, tid, &ret_error);

    if (((usb_error_t) ret_error) != USB_ERR_OK) {
        return ((usb_error_t) ret_error);
    }

    return (USB_ERR_OK);
}
Exemple #14
0
/****************************************************************************
NAME 
    usbInit
    
DESCRIPTION
    Initialisation done once the main loop is up and running. Determines USB
    attach status etc.
    
RETURNS
    void
*/ 
void usbInit(void)
{
    USB_DEBUG(("USB: Init\n"));

    /* Abort if no device classes supported */
    if(!theSink.usb.config.device_class)
        return;
    /* If battery charging enabled set the charge current */
    usbUpdateChargeCurrent();
#ifdef ENABLE_USB_AUDIO
    /* Pass NULL USB mic Sink until the plugin handles USB mic */
    theSink.a2dp_link_data->a2dp_audio_connect_params.usb_params = NULL; 
#endif
    /* Schedule reset to low power mode if attached */
    usbSetLowPowerMode(theSink.usb.config.attach_timeout);
    /* Check for audio */
    theSink.usb.ready = TRUE;
    audioHandleRouting(audio_source_none);
    PioSetPio(theSink.conf1->PIOIO.pio_outputs.PowerOnPIO, pio_drive, TRUE);
}
void usb_rx_transfer_start_call(struct usb_manager_binding *bind, uint32_t tid)
{
    USB_DEBUG_IDC("usb_rx_transfer_start_call()\n");

    struct usb_tstart_state *st = malloc(sizeof(struct usb_tstart_state));

    if (st == NULL) {
        debug_printf("WARNING: Cannot reply, out of memory!\n");
    }
    st->bind = bind;

    struct usb_device *dev = (struct usb_device *) (bind->st);

    assert(dev != NULL);

    struct usb_xfer *xfer = dev->xfers;

    while (xfer) {
        if (xfer->xfer_id == tid) {
            break;
        }
        xfer = xfer->device_xfers_next;
    }

    if (xfer == NULL) {
        USB_DEBUG("no xfer!\n");
        st->error = USB_ERR_BAD_CONTEXT;
        usb_tx_transfer_start_response(st);
    }

    usb_transfer_start(xfer);

    st->error = xfer->error;

    usb_tx_transfer_start_response(st);
}
Exemple #16
0
/****************************************************************************
NAME 
    usbGetVolume
    
DESCRIPTION
    Extract USB volume setting from USB lib levels
    
RETURNS
    Volume to pass to csr_usb_audio_plugin
*/ 
static uint16 usbGetVolume(AUDIO_MODE_T* mode)
{
    uint16 result;
    bool mic_muted;
    bool spk_muted = FALSE;

    /* Get vol settings from USB lib */
    usb_device_class_audio_levels levels;
    UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_AUDIO_LEVELS, (uint16*)&levels);

    /* limit check volume levels returned */
    if((levels.out_l_vol < 0)||(levels.out_l_vol > VOLUME_A2DP_MAX_LEVEL))
        levels.out_l_vol = VOLUME_A2DP_MAX_LEVEL;
    if((levels.out_r_vol < 0)||(levels.out_r_vol > VOLUME_A2DP_MAX_LEVEL))
        levels.out_r_vol = VOLUME_A2DP_MAX_LEVEL;

    USB_DEBUG(("USB: Gain L %X R %X\n", levels.out_l_vol, levels.out_r_vol));
    USB_DEBUG(("USB: Mute M %X S %X\n", levels.in_mute, levels.out_mute));

    if(theSink.usb.config.plugin_type == usb_plugin_stereo)
    {
        /* Use A2DP gain mappings */
        uint8 l_vol = theSink.conf1->gVolMaps[ levels.out_l_vol ].A2dpGain;
        uint8 r_vol = theSink.conf1->gVolMaps[ levels.out_r_vol ].A2dpGain;
        /* Convert A2DP gain setting to mute/gain */
        spk_muted = (r_vol == 0 && l_vol == 0);
        if(r_vol > 0) r_vol --;
        if(l_vol > 0) l_vol --;
        /* Pack result */
        result = ((l_vol << 8) | r_vol);
        displayUpdateVolume((levels.out_l_vol + levels.out_r_vol + 1) / 2);
#ifdef ENABLE_SUBWOOFER
        updateSwatVolume((levels.out_l_vol + levels.out_r_vol + 1) / 2);
#endif
    }
    
    else
    {
        /* Use HFP gain mappings */
        result = theSink.conf1->gVolMaps[ levels.out_l_vol ].VolGain;
        displayUpdateVolume(levels.out_l_vol);
#ifdef ENABLE_SUBWOOFER
        updateSwatVolume(levels.out_l_vol);
#endif
    }

    /* Mute if muted by host or not supported */
    mic_muted = levels.in_mute  || !USB_CLASS_ENABLED(USB_DEVICE_CLASS_TYPE_AUDIO_MICROPHONE);
    spk_muted = spk_muted || levels.out_mute || !USB_CLASS_ENABLED(USB_DEVICE_CLASS_TYPE_AUDIO_SPEAKER);

    if(mode)
    {
        if(mic_muted && spk_muted)
            *mode = AUDIO_MODE_MUTE_BOTH;
        else if(mic_muted)
            *mode = AUDIO_MODE_MUTE_MIC;
        else if(spk_muted)
            *mode = AUDIO_MODE_MUTE_SPEAKER;
        else
            *mode = AUDIO_MODE_CONNECTED;
    }

    return result;
}
Exemple #17
0
/****************************************************************************
NAME 
    usbSendHidEvent
    
DESCRIPTION
    Send HID event over USB
    
RETURNS
    void
*/ 
void usbSendHidEvent(usb_device_class_event event)
{
    USB_DEBUG(("USB: HID Event 0x%X\n", event));
    if(USB_CLASS_ENABLED(USB_DEVICE_CLASS_TYPE_HID_CONSUMER_TRANSPORT_CONTROL))
        UsbDeviceClassSendEvent(event);
}
Exemple #18
0
/****************************************************************************
NAME 
    usbGetChargeCurrent
    
DESCRIPTION
    Get USB charger limits
    
RETURNS
    void
*/ 
sink_charge_current* usbGetChargeCurrent(void) 
{
    /* USB charging not enabled - no limits */
    if(!USB_CLASS_ENABLED(USB_DEVICE_CLASS_TYPE_BATTERY_CHARGING))
        return NULL;

    USB_DEBUG(("USB: Status "));

    /* Set charge current */
    switch(UsbAttachedStatus())
    {
        case HOST_OR_HUB:
            USB_DEBUG(("Host/Hub "));
            if(theSink.usb.suspended)
            {
                USB_DEBUG(("Suspended (Battery %s)\n", usbDeadBatteryProvision() ? "Dead" : "Okay"));
                if(usbDeadBatteryProvision())
                    return &theSink.usb.config.i_susp_db;
                else
                    return &theSink.usb.config.i_susp;
            }
            else if(powerManagerIsChargerFullCurrent())
            {
                USB_DEBUG(("%sEnumerated (Chg Full)\n", theSink.usb.enumerated ? "" : "Not "));
                if(!theSink.usb.enumerated)
                    return &theSink.usb.config.i_att;
                else
                    return &theSink.usb.config.i_conn;
            }
            else
            {
                USB_DEBUG(("%sEnumerated (Chg Partial)\n", theSink.usb.enumerated ? "" : "Not "));
                if(!theSink.usb.enumerated)
                    return &theSink.usb.config.i_att_trickle;
                else
                    return &theSink.usb.config.i_conn_trickle;
            }
#ifdef HAVE_FULL_USB_CHARGER_DETECTION
        case DEDICATED_CHARGER:
            USB_DEBUG(("Dedicated Charger Port%s\n", theSink.usb.vbus_okay ? "" : " Limited"));
            if(theSink.usb.vbus_okay)
                return &theSink.usb.config.i_dchg;
            else
                return &theSink.usb.config.i_lim;

        case HOST_OR_HUB_CHARGER:
        case CHARGING_PORT:
            USB_DEBUG(("Charger Port%s\n", theSink.usb.vbus_okay ? "" : " Limited"));
            if(theSink.usb.vbus_okay)
                return &theSink.usb.config.i_chg;
            else
                return &theSink.usb.config.i_lim;
#endif
        case DETACHED:
        default:
            USB_DEBUG(("Detached\n"));
            if(powerManagerIsChargerConnected())
                return &theSink.usb.config.i_disc;
            else
                return NULL;
    }
}
Exemple #19
0
/****************************************************************************
NAME 
    usbSetDeadBattery
    
DESCRIPTION
    Set whether VBAT is below the dead battery threshold
    
RETURNS
    void
*/ 
void usbSetVbatDead(bool dead)
{
    USB_DEBUG(("USB: VBAT %s\n", dead ? "Dead" : "Okay"));
    theSink.usb.dead_battery = dead;
    if(!dead) MessageCancelAll(&theSink.task, EventUsbDeadBatteryTimeout);
}
Exemple #20
0
/****************************************************************************
NAME 
    usbSetVbusLevel
    
DESCRIPTION
    Set whether VBUS is above or below threshold
    
RETURNS
    void
*/ 
void usbSetVbusLevel(voltage_reading vbus) 
{
    USB_DEBUG(("USB: VBUS %dmV [%d]\n", vbus.voltage, vbus.level));
    theSink.usb.vbus_okay = vbus.level;
}
Exemple #21
0
/****************************************************************************
NAME 
    usbTimeCriticalInit
    
DESCRIPTION
    Initialise USB. This function is time critical and must be called from
    _init. This will fail if either Host Interface is not set to USB or
    VM control of USB is FALSE in PS. It may also fail if Transport in the
    project properties is not set to USB VM.
    
RETURNS
    void
*/ 
void usbTimeCriticalInit(void)
{
#ifdef ENABLE_USB_AUDIO
    const usb_plugin_info* plugin;
#endif
    usb_device_class_status status;
    usb_file_info root;
    usb_file_info file;
    usb_file_name_info file_name;

    USB_DEBUG(("USB: Time Critical\n"));

    /* Default to not configured or suspended */
    theSink.usb.ready = FALSE;
    theSink.usb.enumerated = FALSE;
    theSink.usb.suspended  = FALSE;
    theSink.usb.vbus_okay  = TRUE;
    theSink.usb.deconfigured = FALSE;

    /* Check if we booted with dead battery */
    usbSetVbatDead(usbDeadBatteryAtBoot());

    /* Get USB configuration */
    configManagerUsb();

    /* Abort if no device classes supported */
    if(!theSink.usb.config.device_class)
        return;

    usbFileInfo(root_name, sizeof(root_name)-1, &root);
    usbFileName(&root, &file_name);
    usbFileInfo(file_name.name, file_name.size, &file);

    /* If we can't find the help file don't enumerate mass storage */
    if(file.index == FILE_NONE || root.index == FILE_NONE) 
        USB_CLASS_DISABLE(USB_DEVICE_CLASS_TYPE_MASS_STORAGE);

#ifdef ENABLE_USB_AUDIO
    plugin = &usb_plugins[theSink.usb.config.plugin_type];
    USB_DEBUG(("USB: Audio Plugin %d\n", theSink.usb.config.plugin_index));
    UsbDeviceClassConfigure(USB_DEVICE_CLASS_CONFIG_AUDIO_INTERFACE_DESCRIPTORS, 0, 0, (const uint8*)(plugin->usb_descriptors));
#else
    /* If audio not supported don't enumerate as mic or speaker */
    USB_CLASS_DISABLE(USB_DEVICE_CLASS_AUDIO);
#endif

    USB_DEBUG(("USB: Endpoint Setup [0x%04X] - ", theSink.usb.config.device_class));
    /* Attempt to enumerate - abort if failed */
    status = UsbDeviceClassEnumerate(&theSink.task, theSink.usb.config.device_class);

    if(status != usb_device_class_status_success)
    {
        USB_DEBUG(("Error %X\n", status));
        return;
    }

    USB_DEBUG(("Success\n"));
    /* Configure mass storage device */
    if(USB_CLASS_ENABLED(USB_DEVICE_CLASS_TYPE_MASS_STORAGE))
    {
        UsbDeviceClassConfigure(USB_DEVICE_CLASS_CONFIG_MASS_STORAGE_FAT_DATA_AREA, file.index, file.size, 0);
        usbFileInfo(fat_name, sizeof(fat_name)-1, &file);
        UsbDeviceClassConfigure(USB_DEVICE_CLASS_CONFIG_MASS_STORAGE_FAT_TABLE, file.index, file.size, 0);
        UsbDeviceClassConfigure(USB_DEVICE_CLASS_CONFIG_MASS_STORAGE_FAT_ROOT_DIR, root.index, root.size, 0);
    }
}
Exemple #22
0
EFI_STATUS
UsbSelectConfig (
  IN USB_DEVICE           *Device,
  IN UINT8                ConfigValue
  )
/*++

Routine Description:

  Select a new configuration for the device. Each
  device may support several configurations. 

Arguments:

  Device      - The device to select configuration
  ConfigValue - The index of the configuration ( != 0)

Returns:

  EFI_NOT_FOUND        - There is no configuration with the index
  EFI_OUT_OF_RESOURCES - Failed to allocate resource
  EFI_SUCCESS          - The configuration is selected.

--*/
{
  USB_DEVICE_DESC         *DevDesc;
  USB_CONFIG_DESC         *ConfigDesc;
  USB_INTERFACE_DESC      *IfDesc;
  USB_INTERFACE           *UsbIf;
  EFI_STATUS              Status;
  UINT8                   Index;

  //
  // Locate the active config, then set the device's pointer
  //
  DevDesc     = Device->DevDesc;
  ConfigDesc  = NULL;

  for (Index = 0; Index < DevDesc->Desc.NumConfigurations; Index++) {
    ConfigDesc = DevDesc->Configs[Index];

    if (ConfigDesc->Desc.ConfigurationValue == ConfigValue) {
      break;
    }
  }

  if (Index == DevDesc->Desc.NumConfigurations) {
    return EFI_NOT_FOUND;
  }

  Device->ActiveConfig = ConfigDesc;

  USB_DEBUG (("UsbSelectConfig: config %d selected for device %d\n", 
              ConfigValue, Device->Address));

  //
  // Create interfaces for each USB interface descriptor.
  //
  for (Index = 0; Index < ConfigDesc->Desc.NumInterfaces; Index++) {
    //
    // First select the default interface setting, and reset
    // the endpoint toggles to zero for its endpoints.
    //
    IfDesc = ConfigDesc->Interfaces[Index];
    UsbSelectSetting (IfDesc, IfDesc->Settings[0]->Desc.AlternateSetting);

    //
    // Create a USB_INTERFACE and install USB_IO and other protocols
    //
    UsbIf = UsbCreateInterface (Device, ConfigDesc->Interfaces[Index]);

    if (UsbIf == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    Device->Interfaces[Index] = UsbIf;

    //
    // Connect the device to drivers, if it failed, ignore 
    // the error. Don't let the unsupported interfaces to block
    // the supported interfaces.
    //
    Status = UsbConnectDriver (UsbIf);

    if (EFI_ERROR (Status)) {
      USB_ERROR (("UsbSelectConfig: failed to connect driver %r, ignored\n", Status));
    }
  }

  Device->NumOfInterface = Index;

  return EFI_SUCCESS;
}
Exemple #23
0
STATIC
EFI_STATUS
UsbConnectDriver (
  IN USB_INTERFACE        *UsbIf
  )
/*++

Routine Description:

  Connect the USB interface with its driver. EFI USB bus will
  create a USB interface for each seperate interface descriptor.

Arguments:

  UsbIf   - The interface to connect driver to

Returns:

  EFI_SUCCESS : Interface is managed by some driver
  Others      : Failed to locate a driver for this interface
  
--*/
{
  EFI_STATUS              Status;
  EFI_TPL                 OldTpl;
  
  Status = EFI_SUCCESS;

  //
  // Hub is maintained by the USB bus driver. Otherwise try to
  // connect drivers with this interface
  //
  if (UsbIsHubInterface (UsbIf)) {
    USB_DEBUG (("UsbConnectDriver: found a hub device\n"));
    Status = mUsbHubApi.Init (UsbIf);

  } else {
    //
    // This function is called in both UsbIoControlTransfer and
    // the timer callback in hub enumeration. So, at least it is
    // called at EFI_TPL_CALLBACK. Some driver sitting on USB has
    // twisted TPL used. It should be no problem for us to connect
    // or disconnect at CALLBACK.
    //
    
    //
    // Only recursively wanted usb child device
    //
    if (UsbBusIsWantedUsbIO (UsbIf->Device->Bus, UsbIf)) {
      OldTpl            = UsbGetCurrentTpl ();
      USB_DEBUG (("UsbConnectDriver: TPL before connect is %d\n", OldTpl));
      
      gBS->RestoreTPL (EFI_TPL_CALLBACK);

      Status            = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);
      UsbIf->IsManaged  = (BOOLEAN)!EFI_ERROR (Status);

      USB_DEBUG (("UsbConnectDriver: TPL after connect is %d\n", UsbGetCurrentTpl()));
      ASSERT (UsbGetCurrentTpl () == EFI_TPL_CALLBACK);

      gBS->RaiseTPL (OldTpl);  
    }
  }

  return Status;
}
/**
 * \brief   starts a USB transfer
 *
 * \param   xfer    the USB transfer to start
 */
void usb_transfer_start(struct usb_xfer *xfer)
{

    USB_DEBUG_TR_ENTER;

    if (xfer == NULL) {
        USB_DEBUG_XFER("NOTICE: No xfer to start...\n");
        return;
    }

    /*
     * set the started flag
     */

    xfer->flags_internal.started = 1;

    /*
     * if the transfer is already transferring, then we do not
     * have to do sth.
     */
    if (xfer->flags_internal.transferring) {
        USB_DEBUG_XFER("NOTICE: already transferring\n");

        USB_DEBUG_TR_RETURN;
        return;
    }

    /* struct usb_xfer_queue *queue = &(xfer->host_controller->done_queue);

     if (queue->current != xfer) {
     usb_xfer_enqueue(queue, xfer);
     }*/

    /*
     * submitting the transfer to start the USB hardware for the given
     * transfer
     */

    if (!xfer->flags_internal.pipe_open) {
        xfer->flags_internal.pipe_open = 1;
        (xfer->endpoint->pipe_fn->open)(xfer);
    }

    xfer->flags_internal.transferring = 1;
    xfer->flags_internal.done = 0;

    /*
     * check if the transfer is waiting on a queue, and dequeue it
     */
    /* if (xfer->wait_queue) {
     usb_xfer_dequeue(xfer);
     }*/

    // clear the closed flag
    xfer->flags_internal.transfer_closed = 0;

    // clear the DMA delay flag
    xfer->flags_internal.dma_wait = 0;

    // transfers are not immediate cancellable
    xfer->flags_internal.cancellable = 0;

    /*
     * update the status fields of the transfer
     */
    xfer->sum_bytes = 0;
    xfer->actual_bytes = 0;
    xfer->actual_frames = 0;

    xfer->error = USB_ERR_OK;

    if (xfer->device->state < USB_DEVICE_STATE_POWERED) {
        USB_DEBUG("NOTICE: device is not alive anymore...\n");
        usb_xfer_done(xfer, USB_ERR_CANCELLED);
        return;
    }

    if (xfer->num_frames == 0) {
        if (xfer->flags.pipe_stalled) {
            USB_DEBUG_XFER("Want to stall w/o transferring...\n");
            xfer->flags_internal.cancellable = 1;
            assert(!"NYI: stalling\n");
            /* TODO: usb_command_wrapper(&xfer->endpoint->endpoint_q, xfer); */
            return;
        }
        USB_DEBUG(
            "ERROR: invalid number of frames (0) in usb_transfer_start()\n");
        usb_xfer_done(xfer, USB_ERR_INVAL);
        USB_DEBUG_TR_RETURN;
        return;
    }

    for (uint32_t frame = 0; frame < xfer->num_frames; frame++) {
        xfer->frame_lengths[frame + xfer->max_frame_count] =
            xfer->frame_lengths[frame];

        xfer->sum_bytes += xfer->frame_lengths[frame];
        if (xfer->sum_bytes < xfer->frame_lengths[frame]) {
            USB_DEBUG("WARNING: total length wrapped arroud!\n");
            usb_xfer_done(xfer, USB_ERR_INVAL);
            USB_DEBUG_TR_RETURN;
            return;
        }
    }

    xfer->flags_internal.short_frames_ok = 0;
    xfer->flags_internal.short_transfer_ok = 0;

    if (xfer->flags_internal.ctrl_xfer) {
        USB_DEBUG_XFER("usb_transfer_start() - is ctrl transfer...\n");
        if (usb_transfer_ctrl_start(xfer)) {
            debug_printf("WARNING: starting usb ctrl transfer failed..\n");
            usb_xfer_done(xfer, USB_ERR_STALLED);
            USB_DEBUG_TR_RETURN;
            return;
        }
    }

    if ((((xfer)->endpoint_number & 0x80) ? 1 : 0)) {
        if (xfer->flags.short_frames_ok) {
            xfer->flags_internal.short_frames_ok = 1;
            xfer->flags_internal.short_transfer_ok = 1;
        } else if (xfer->flags.short_xfer_ok) {
            xfer->flags_internal.short_transfer_ok = 1;
            if (xfer->flags_internal.ctrl_xfer) {
                xfer->flags_internal.short_frames_ok = 1;
            }
        }
    }

    usb_pipe_enter(xfer);
    USB_DEBUG_TR_RETURN;
}
Exemple #25
0
STATIC
EFI_STATUS
UsbEnumeratePort (
  IN USB_INTERFACE        *HubIf,
  IN UINT8                Port
  )
/*++

Routine Description:

  Process the events on the port.

Arguments:

  HubIf - The HUB that has the device connected
  Port  - The port index of the hub (started with zero)

Returns:

  EFI_SUCCESS          - The device is enumerated (added or removed)
  EFI_OUT_OF_RESOURCES - Failed to allocate resource for the device
  Others               - Failed to enumerate the device

--*/
{
  USB_HUB_API             *HubApi;
  USB_DEVICE              *Child;
  EFI_USB_PORT_STATUS     PortState;
  EFI_STATUS              Status;

  Child   = NULL;
  HubApi  = HubIf->HubApi;
  
  //
  // Host learns of the new device by polling the hub for port changes.
  //
  Status = HubApi->GetPortStatus (HubIf, Port, &PortState);

  if (EFI_ERROR (Status)) {
    USB_ERROR (("UsbEnumeratePort: failed to get state of port %d\n", Port));
    return Status;
  }

  if (PortState.PortChangeStatus == 0) {
    return EFI_SUCCESS;
  }

  USB_DEBUG (("UsbEnumeratePort: port %d state - %x, change - %x\n", 
              Port, PortState.PortStatus, PortState.PortChangeStatus));

  //
  // This driver only process two kinds of events now: over current and 
  // connect/disconnect. Other three events are: ENABLE, SUSPEND, RESET.
  // ENABLE/RESET is used to reset port. SUSPEND isn't supported.
  //
  
  if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_OVERCURRENT)) {     

    if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {
      //
      // Case1:
      //   Both OverCurrent and OverCurrentChange set, means over current occurs, 
      //   which probably is caused by short circuit. It has to wait system hardware
      //   to perform recovery.
      //
      USB_DEBUG (("UsbEnumeratePort: Critical Over Current\n", Port));
      return EFI_DEVICE_ERROR;
      
    } 
    //
    // Case2:
    //   Only OverCurrentChange set, means system has been recoveried from 
    //   over current. As a result, all ports are nearly power-off, so
    //   it's necessary to detach and enumerate all ports again. 
    //
    USB_DEBUG (("UsbEnumeratePort: 2.0 Device Recovery Over Current\n", Port)); 
  }

  if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) {  
    //
    // Case3:
    //   1.1 roothub port reg doesn't reflect over-current state, while its counterpart
    //   on 2.0 roothub does. When over-current has influence on 1.1 device, the port 
    //   would be disabled, so it's also necessary to detach and enumerate again.
    //
    USB_DEBUG (("UsbEnumeratePort: 1.1 Device Recovery Over Current\n", Port));
  }
  
  if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {
    //
    // Case4:
    //   Device connected or disconnected normally. 
    //
    USB_DEBUG (("UsbEnumeratePort: Device Connect/Discount Normally\n", Port));
  }

  // 
  // Following as the above cases, it's safety to remove and create again.
  //
  Child = UsbFindChild (HubIf, Port);
  
  if (Child != NULL) {
    USB_DEBUG (("UsbEnumeratePort: device at port %d removed from system\n", Port));
    UsbRemoveDevice (Child);
  }
  
  if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {
    //
    // Now, new device connected, enumerate and configure the device 
    //
    USB_DEBUG (("UsbEnumeratePort: new device connected at port %d\n", Port));
    Status = UsbEnumerateNewDev (HubIf, Port);
  
  } else {
    USB_DEBUG (("UsbEnumeratePort: device disconnected event on port %d\n", Port));
  }
  
  HubApi->ClearPortChange (HubIf, Port);
  return Status;
}
Exemple #26
0
STATIC
EFI_STATUS
UsbEnumerateNewDev (
  IN USB_INTERFACE        *HubIf,
  IN UINT8                Port
  )
/*++

Routine Description:

  Enumerate and configure the new device on the port of this HUB interface.

Arguments:

  HubIf - The HUB that has the device connected
  Port  - The port index of the hub (started with zero)

Returns:

  EFI_SUCCESS          - The device is enumerated (added or removed)
  EFI_OUT_OF_RESOURCES - Failed to allocate resource for the device
  Others               - Failed to enumerate the device

--*/
{
  USB_BUS                 *Bus;
  USB_HUB_API             *HubApi;
  USB_DEVICE              *Child;
  USB_DEVICE              *Parent;
  EFI_USB_PORT_STATUS     PortState;
  UINT8                   Address;
  UINT8                   Config;
  EFI_STATUS              Status;

  Address = USB_MAX_DEVICES;
  Parent  = HubIf->Device;
  Bus     = Parent->Bus;
  HubApi  = HubIf->HubApi;
  
  gBS->Stall (USB_WAIT_PORT_STABLE_STALL);
  
  //
  // Hub resets the device for at least 10 milliseconds.
  // Host learns device speed. If device is of low/full speed
  // and the hub is a EHCI root hub, ResetPort will release
  // the device to its companion UHCI and return an error.
  //
  Status = HubApi->ResetPort (HubIf, Port);

  if (EFI_ERROR (Status)) {
    USB_ERROR (("UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status));

    return Status;
  }

  USB_DEBUG (("UsbEnumerateNewDev: hub port %d is reset\n", Port));

  Child = UsbCreateDevice (HubIf, Port);

  if (Child == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  
  //
  // OK, now identify the device speed. After reset, hub
  // fully knows the actual device speed.
  //
  Status = HubApi->GetPortStatus (HubIf, Port, &PortState);

  if (EFI_ERROR (Status)) {
    USB_ERROR (("UsbEnumerateNewDev: failed to get speed of port %d\n", Port));
    goto ON_ERROR;
  }

  if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
    Child->Speed = EFI_USB_SPEED_LOW;  

  } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
    Child->Speed = EFI_USB_SPEED_HIGH; 

  } else {
    Child->Speed = EFI_USB_SPEED_FULL;
  }

  USB_DEBUG (("UsbEnumerateNewDev: device is of %d speed\n", Child->Speed));

  if (Child->Speed != EFI_USB_SPEED_HIGH) {
    //
    // If the child isn't a high speed device, it is necessary to
    // set the transaction translator. Port TT is 1-based.
    // This is quite simple:
    //  1. if parent is of high speed, then parent is our translator
    //  2. otherwise use parent's translator.
    //
    if (Parent->Speed == EFI_USB_SPEED_HIGH) {
      Child->Translator.TranslatorHubAddress  = Parent->Address;
      Child->Translator.TranslatorPortNumber  = Port + 1;

    } else {
      Child->Translator = Parent->Translator;
    }

    USB_DEBUG (("UsbEnumerateNewDev: device uses translator (%d, %d)\n", 
                Child->Translator.TranslatorHubAddress, 
                Child->Translator.TranslatorPortNumber));
  }
  
  //
  // After port is reset, hub establishes a signal path between
  // the device and host (DEFALUT state). Device¡¯s registers are
  // reset, use default address 0 (host enumerates one device at
  // a time) , and ready to respond to control transfer at EP 0.
  //
  
  //
  // Host sends a Get_Descriptor request to learn the max packet
  // size of default pipe (only part of the device¡¯s descriptor).
  //
  Status = UsbGetMaxPacketSize0 (Child);

  if (EFI_ERROR (Status)) {
    USB_ERROR (("UsbEnumerateNewDev: failed to get max packet for EP 0 - %r\n", Status));
    goto ON_ERROR;
  }

  USB_DEBUG (("UsbEnumerateNewDev: max packet size for EP 0 is %d\n", Child->MaxPacket0));

  //
  // Host assigns an address to the device. Device completes the
  // status stage with default address, then switches to new address.
  // ADDRESS state. Address zero is reserved for root hub.
  //
  for (Address = 1; Address < USB_MAX_DEVICES; Address++) {
    if (Bus->Devices[Address] == NULL) {
      break;
    }
  }

  if (Address == USB_MAX_DEVICES) {
    USB_ERROR (("UsbEnumerateNewDev: address pool is full for port %d\n", Port));
    
    Status = EFI_ACCESS_DENIED;
    goto ON_ERROR;
  }

  Bus->Devices[Address] = Child;
  Status                = UsbSetAddress (Child, Address);
  Child->Address        = Address;
  
  if (EFI_ERROR (Status)) {
    USB_ERROR (("UsbEnumerateNewDev: failed to set device address - %r\n", Status));
    goto ON_ERROR;
  }
  
  gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);

  USB_DEBUG (("UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address));

  //
  // Host learns about the device¡¯s abilities by requesting device's
  // entire descriptions.
  //
  Status = UsbBuildDescTable (Child);

  if (EFI_ERROR (Status)) {
    USB_ERROR (("UsbEnumerateNewDev: failed to build descriptor table - %r\n", Status));
    goto ON_ERROR;
  }
  
  //
  // Select a default configuration: UEFI must set the configuration
  // before the driver can connect to the device.
  //
  Config = Child->DevDesc->Configs[0]->Desc.ConfigurationValue;
  Status = UsbSetConfig (Child, Config);

  if (EFI_ERROR (Status)) {
    USB_ERROR (("UsbEnumerateNewDev: failed to set configure %d - %r\n", Config, Status));
    goto ON_ERROR;
  }

  USB_DEBUG (("UsbEnumerateNewDev: device %d is now in CONFIGED state\n", Address));
  
  //
  // Host assigns and loads a device driver. 
  //
  Status = UsbSelectConfig (Child, Config);

  if (EFI_ERROR (Status)) {
    USB_ERROR (("UsbEnumerateNewDev: failed to create interfaces - %r\n", Status));  
    goto ON_ERROR;
  }

  return EFI_SUCCESS;

ON_ERROR:
  if (Address != USB_MAX_DEVICES) {
    Bus->Devices[Address] = NULL;
  }

  if (Child != NULL) {
    UsbFreeDevice (Child);
  }

  return Status;
}
Exemple #27
0
/****************************************************************************
NAME 
    handleUsbMessage
    
DESCRIPTION
    Handle firmware USB messages
    
RETURNS
    void
*/ 
void handleUsbMessage(Task task, MessageId id, Message message) 
{
    USB_DEBUG(("USB: "));
    switch (id)
    {
        case MESSAGE_USB_ATTACHED:
        {
            USB_DEBUG(("MESSAGE_USB_ATTACHED\n"));
            usbUpdateChargeCurrent();
            audioHandleRouting(audio_source_none);
            usbSetLowPowerMode(theSink.usb.config.attach_timeout);
            if(theSink.usb.dead_battery)
                MessageSendLater(&theSink.task, EventUsbDeadBatteryTimeout, 0, D_MIN(45));
            break;
        }
        case MESSAGE_USB_DETACHED:
        {
            USB_DEBUG(("MESSAGE_USB_DETACHED\n"));
            theSink.usb.enumerated = FALSE;
            theSink.usb.suspended  = FALSE;
            theSink.usb.deconfigured = FALSE;
            usbUpdateChargeCurrent();
            audioHandleRouting(audio_source_none);
            MessageCancelAll(&theSink.task, EventUsbLowPowerMode);
            MessageCancelAll(&theSink.task, EventUsbDeadBatteryTimeout);
            break;
        }
        case MESSAGE_USB_ENUMERATED:
        {
            USB_DEBUG(("MESSAGE_USB_ENUMERATED\n"));
            if(!theSink.usb.enumerated)
            {
                theSink.usb.enumerated = TRUE;
                usbUpdateChargeCurrent();
                MessageCancelAll(&theSink.task, EventUsbLowPowerMode);
                MessageCancelAll(&theSink.task, EventUsbDeadBatteryTimeout);
            }
            break;
        }
        case MESSAGE_USB_SUSPENDED:
        {
            MessageUsbSuspended* ind = (MessageUsbSuspended*)message;
            USB_DEBUG(("MESSAGE_USB_SUSPENDED - %s\n", (ind->has_suspended ? "Suspend" : "Resume")));
            if(ind->has_suspended != theSink.usb.suspended)
            {
                theSink.usb.suspended = ind->has_suspended;
                usbUpdateChargeCurrent();
            }
            break;
        }
        case MESSAGE_USB_DECONFIGURED:
        {
            USB_DEBUG(("MESSAGE_USB_DECONFIGURED\n"));
            if(theSink.usb.enumerated)
            {
                theSink.usb.enumerated = FALSE;
                theSink.usb.deconfigured  = TRUE;
                usbUpdateChargeCurrent();
                usbSetLowPowerMode(theSink.usb.config.deconfigured_timeout);
            }
            break;
        }
        case MESSAGE_USB_ALT_INTERFACE:
        {
            uint16 interface_id;
            MessageUsbAltInterface* ind = (MessageUsbAltInterface*)message;

            USB_DEBUG(("MESSAGE_USB_ALT_INTERFACE %d %d\n", ind->interface, ind->altsetting));
            UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_MIC_INTERFACE_ID, &interface_id);
            if(interface_id == ind->interface)
            {
                theSink.usb.mic_active = (ind->altsetting ? TRUE : FALSE);
                USB_DEBUG(("USB: Mic ID %d active %d\n", interface_id, theSink.usb.mic_active));
            }
            UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_SPEAKER_INTERFACE_ID, &interface_id);
            if(interface_id == ind->interface)
            {
                theSink.usb.spkr_active = (ind->altsetting ? TRUE : FALSE);
                USB_DEBUG(("USB: Speaker ID %d active %d\n", interface_id, theSink.usb.spkr_active));
            }
#ifdef ENABLE_USB_AUDIO            
            /* check for changes in required audio routing */
            USB_DEBUG(("USB: MESSAGE_USB_ALT_INTERFACE checkAudioRouting\n"));
            MessageCancelFirst(&theSink.task, EventCheckAudioRouting);            
            MessageSendLater(&theSink.task, EventCheckAudioRouting, 0, USB_AUDIO_DISCONNECT_DELAY);            
#endif            
            break;
        }
        case USB_DEVICE_CLASS_MSG_AUDIO_LEVELS_IND:
        {
            USB_DEBUG(("USB_DEVICE_CLASS_MSG_AUDIO_LEVELS_IND\n"));
            usbAudioSetVolume();
            break;
        }
        default:
        {
            USB_DEBUG(("Unhandled USB message 0x%x\n", id));
            break;
        }
    }
}
Exemple #28
0
/**
 * \brief   initializes the OHCI controller hardware
 */
usb_error_t usb_ohci_init(usb_ohci_hc_t *hc, uintptr_t base)
{
    /*
     * initialize the mackerel framework
     */
// TODO: Why does 32-bit expect mackerel_io_t?
#ifdef __x86__
    ohci_initialize(&ohci_base, (mackerel_io_t)base);
#else
    ohci_initialize(&ohci_base, (mackerel_addr_t)base);
#endif
    hc->ohci_base = &ohci_base;

    /*
     * setup the endpoint descriptors
     */
    hc->qh_bulk_last = usb_ohci_init_ed(&hc->qh_bulk_first);
    hc->qh_ctrl_last = usb_ohci_init_ed(&hc->qh_ctrl_first);
    hc->qh_isoc_last = usb_ohci_init_ed(NULL);

    for (uint16_t i = 0; i<USB_OHCI_NO_EP_DESCRIPTORS; i++) {
        hc->qh_intr_last[i] = usb_ohci_init_ed(NULL);
    }

    /**
     * setup the interrupt transfer type tree
     */
    uint16_t bit = USB_OHCI_NO_EP_DESCRIPTORS / 2;
    uint16_t current;
    uint16_t next;
    while (bit) {
        current = bit;
        while (current & bit) {
            next = (current ^ bit) | (bit / 2);

            usb_ohci_ed_t *ed_current = hc->qh_intr_last[current];
            usb_ohci_ed_t *ed_next = hc->qh_intr_last[next];
            ed_current->next = NULL;
            ed_current->ed_nextED = ed_next->ed_self;

            current++;
        }
        bit >>= 1;
    }

    /*
     * after the last interrupt endpoint the isochronus follows
     */
    usb_ohci_ed_t *intr_ed = hc->qh_intr_last[0];
    intr_ed->next = hc->qh_isoc_last;
    intr_ed->ed_nextED = hc->qh_isoc_last->ed_self;
    /*
     * allocate and initiate the HCCA memory region
     */
    hc->hcca = usb_ohci_hcca_alloc();

    for (uint16_t i = 0; i < USB_OHCI_NO_IRQS; i++) {
        hc->hcca->hcca_interrupt_table[i] = hc->qh_intr_last[i
                | USB_OHCI_NO_EP_DESCRIPTORS / 2]->ed_self;
    }

    hc->controller->hcdi_bus_fn = usb_ohci_get_bus_fn();
    hc->controller->usb_revision = USB_REV_1_0;


    /*
     * initialize the hardware
     */
    if (usb_ohci_init_controller(hc, 0) != USB_ERR_OK) {
        return USB_ERR_INVAL;
    }

    USB_DEBUG("usb_ohci_init() - calling usb_ohci_do_poll\n");
    //usb_ohci_do_poll(hc->controller);

    return USB_ERR_OK;

}
void usb_rx_transfer_setup_call(struct usb_manager_binding *bind, uint8_t type,
                                usb_manager_setup_param_t params)
{
    struct usb_tsetup_state *st = malloc(sizeof(struct usb_tsetup_state));

    if (st == NULL) {
        debug_printf("WARNING: Cannot reply, out of memory!\n");
        return;
    }

    struct usb_xfer_config setup;

    st->bind = bind;
    struct usb_xfer *xfer;
    struct usb_device *dev = (struct usb_device *) bind->st;

    memcpy(&setup, &params, sizeof(params));
    if (dev == NULL) {
        st->tid = 0;
        st->error = USB_ERR_BAD_CONTEXT;
        usb_tx_transfer_setup_response(st);
        return;
    }

    setup.xfer_done_cb = &usb_transfer_complete_notify;

    switch ((usb_type_t) type) {
    case USB_TYPE_BULK:
        USB_DEBUG_IDC("received usb_rx_transfer_setup_call [bulk type]\n");
        /* TODO: Handle transfer setup */
        setup.usb_type = USB_TYPE_BULK;
        st->error = USB_ERR_OK;
        xfer->usb_manager_binding = st->bind;
        xfer->usb_driver_binding = dev->usb_driver_binding;
        st->tid = 123;
        break;
    case USB_TYPE_CTRL:
        USB_DEBUG_IDC("received usb_rx_transfer_setup_call [ctrl type]\n");
        /* TODO: Handle transfer setup */
        setup.usb_type = USB_TYPE_CTRL;
        st->error = USB_ERR_OK;
        xfer->usb_manager_binding = st->bind;
        xfer->usb_driver_binding = dev->usb_driver_binding;
        st->tid = 234;
        break;
    case USB_TYPE_ISOC:
        USB_DEBUG_IDC("received usb_rx_transfer_setup_call [isoc type]\n");
        /* TODO: Handle transfer setup */
        setup.usb_type = USB_TYPE_ISOC;
        st->error = USB_ERR_OK;
        xfer->usb_manager_binding = st->bind;
        xfer->usb_driver_binding = dev->usb_driver_binding;
        st->tid = 345;
        break;
    case USB_TYPE_INTR:
        USB_DEBUG_IDC("received usb_rx_transfer_setup_call [intr type]\n");
        /* TODO: Handle transfer setup */
        setup.usb_type = USB_TYPE_INTR;
        st->error = usb_transfer_setup(dev, params.iface, &xfer, &setup);
        xfer->usb_manager_binding = st->bind;
        xfer->usb_driver_binding = dev->usb_driver_binding;
        st->tid = xfer->xfer_id;
        break;
    default:
        USB_DEBUG("received usb_rx_transfer_setup_call [invalid type]\n");
        st->error = USB_ERR_INVAL;
        break;
    }
    usb_tx_transfer_setup_response(st);
}
Exemple #30
0
/**
 * \brief   initializes the host controller hardware
 *
 * \param   hc      the host controller
 * \param   suspend flag the host controller should be suspended
 */
static usb_error_t usb_ohci_init_controller(usb_ohci_hc_t *hc, uint8_t suspend)
{
    USB_DEBUG("usb_ohci_init_controller()\n");

    char status[512];
    ohci_control_pr(status, 512, hc->ohci_base);
    puts(status);

    /*
     * check the ownership of the host controller
     */
    if (ohci_control_ir_rdf(hc->ohci_base)) {
        assert(!"REQEUST OWER CHANGE. ");
    }

    // reset the device
    ohci_control_hcfs_wrf(hc->ohci_base, 0);

    /*
     * TODO: Wait till reset is done
     */
    for(uint32_t i = 0; i < 2000000000; i++);

    USB_DEBUG("usb_ohci_init_controller(): Device Reset done.\n");


    ohci_fm_interval_t ival = ohci_fm_interval_rd(hc->ohci_base);

    ohci_cmdstatus_hcr_wrf(hc->ohci_base, 1);

    for (uint16_t i = 0; i < 10; i++) {
        /*
         * TODO: Wait 10 us
         */
        for(uint32_t j = 0; j < 2000000000; j++);

        if (!ohci_cmdstatus_hcr_rdf(hc->ohci_base)) {
            break;
        }
    }
    if (ohci_cmdstatus_hcr_rdf(hc->ohci_base)) {
        debug_printf("OHCI host controller reset timeout.");
        return USB_ERR_IOERROR;
    }

    if (suspend) {
        ohci_control_hcfs_wrf(hc->ohci_base, 3);
        return USB_ERR_OK;
    }

    /*
     * Setting up register values
     */
    // HCCA pointer
    ohci_hcca_wr(hc->ohci_base, usb_ohci_hcca_physaddr());

    // Control ED head pointer
    ohci_ctrl_head_wr(hc->ohci_base, hc->qh_ctrl_first->ed_self);

    // Bulk ED head pointer
    ohci_bulk_head_wr(hc->ohci_base, hc->qh_bulk_first->ed_self);

    USB_DEBUG("usb_ohci_init() - reset and enable interrupts\n");
    // reset the interrupts
    ohci_intdisable_rawwr(hc->ohci_base, 0x0);
    ohci_interrupt_t enabled_intrs = ohci_intenable_rd(hc->ohci_base);
    enabled_intrs= ohci_interrupt_mie_insert(enabled_intrs, 1);
    enabled_intrs= ohci_interrupt_wdh_insert(enabled_intrs, 1);
    enabled_intrs= ohci_interrupt_rd_insert(enabled_intrs, 1);
    enabled_intrs= ohci_interrupt_ue_insert(enabled_intrs, 1);
    enabled_intrs= ohci_interrupt_oc_insert(enabled_intrs, 1);
    enabled_intrs= ohci_interrupt_rhsc_insert(enabled_intrs, 1);
    ohci_intenable_wr(hc->ohci_base, enabled_intrs);

    hc->enabled_intrs = enabled_intrs;

    // setting the desired features
    ohci_control_t ctrl = ohci_control_rd(hc->ohci_base);
    ctrl = ohci_control_ie_insert(ctrl, 1);
    ctrl = ohci_control_ir_insert(ctrl,0);
    ctrl = ohci_control_cle_insert(ctrl, 1);
    ctrl = ohci_control_ble_insert(ctrl, 1);
    ctrl = ohci_control_cbsr_insert(ctrl, 3);
    ctrl = ohci_control_hcfs_insert(ctrl, 2);
    ctrl = ohci_control_pe_insert(ctrl, 1);
    ctrl = ohci_control_rwe_insert(ctrl, 1);
    ctrl = ohci_control_rwc_insert(ctrl, 1);
    ohci_control_wr(hc->ohci_base, ctrl);

    /*
     * the controller is now OPERATIONAL and running.
     */
    debug_printf("OHCI host controller operational now!\n");
    // setting some remaining registers
    ival = ohci_fm_interval_fit_insert(ival, 0);
    ival = ohci_fm_interval_fsmps_insert(ival, (ival-210)*6/7);
    ohci_fm_interval_wr(hc->ohci_base, ival);
    ohci_period_start_wr(hc->ohci_base, (ival)*9/10);

    // setting some root hub fields
    ohci_rh_descra_nocp_wrf(hc->ohci_base, 1);
    ohci_rh_status_lpsc_wrf(hc->ohci_base, 1);

    /*
     * getting the port numbers
     */
    hc->root_hub_num_ports = 0;
    for (uint8_t i = 0; (i < 10) && (hc->root_hub_num_ports == 0); i++) {
        /*
         * TODO: delay
         */
        for(uint32_t j = 0; j < 100000000; j++);
        hc->root_hub_num_ports = ohci_rh_descra_ndp_rdf(hc->ohci_base);
    }
    debug_printf("OHCI CONTROLLER INTIALIZED. Having %"PRIu8" ports\n",
            hc->root_hub_num_ports );

    //char buf[8001];
    // ohci_rh_descra_pr(buf, 15999, hc->ohci_base);
    //    printf(buf);
    //ohci_pr(buf, 5000, hc->ohci_base);
    //printf(buf);

    //ohci_cmdstatus_ocr_wrf(hc->ohci_base, 0x1);
    usb_ohci_root_hub_interrupt(hc);

    return USB_ERR_OK;
}