/**************************************************************************** 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); }
/**************************************************************************** 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; } } }
/************************************************************************* NAME handlePowerMessage DESCRIPTION handles the Battery/Charger Monitoring Messages RETURNS */ void handlePowerMessage( Task task, MessageId id, Message message ) { switch(id) { case POWER_INIT_CFM: { POWER_INIT_CFM_T* cfm = (POWER_INIT_CFM_T*)message; PM_DEBUG(("PM: POWER_INIT_CFM\n")); if(!cfm->success) Panic(); /* Update VBUS level */ usbSetVbusLevel(cfm->vchg); /* Only indicate if low/critical (or intial reading feature enabled) */ powerManagerHandleVbat(cfm->vbat, battery_level_initial_reading); /* Update charge current based on battery temperature */ if (!powerManagerChargerSetup(&cfm->vthm)) { /* and if the charger was left disabled then handle initial charge state * to notify the app that charger is disabled */ powerManagerHandleChargeState(cfm->state); } } break; case POWER_BATTERY_VOLTAGE_IND: { POWER_BATTERY_VOLTAGE_IND_T* ind = (POWER_BATTERY_VOLTAGE_IND_T*)message; PM_DEBUG(("PM: POWER_BATTERY_VOLTAGE_IND\n")); powerManagerHandleVbat(ind->vbat, battery_level_automatic); usbUpdateChargeCurrent(); } break ; case POWER_CHARGER_VOLTAGE_IND: { PM_DEBUG(("PM: POWER_CHARGER_VOLTAGE_IND\n")); usbSetVbusLevel(((POWER_CHARGER_VOLTAGE_IND_T*)message)->vchg); usbUpdateChargeCurrent(); } break; case POWER_BATTERY_TEMPERATURE_IND: { POWER_BATTERY_TEMPERATURE_IND_T* ind = (POWER_BATTERY_TEMPERATURE_IND_T*)message; PM_DEBUG(("PM: POWER_BATTERY_TEMPERATURE_IND\n")); powerManagerChargerSetup(&ind->vthm); } break; case POWER_CHARGER_STATE_IND: { POWER_CHARGER_STATE_IND_T* ind = (POWER_CHARGER_STATE_IND_T*)message; /* Send event if not using LED overide feature or state is currently not trickle charge */ PM_DEBUG(("PM: POWER_CHARGER_STATE_IND\n")); powerManagerHandleChargeState(ind->state); /* NB. Charger state will not indicate a change from complete to fast. We assume this doesn't matter as we should run from VBUS when complete so battery should not run down */ powerManagerUpdateChargeCurrent(); } break ; default : PM_DEBUG(("PM: Unhandled Battery msg[%x]\n", id)); break ; } }