void usbc_mode_switch(usb_mode_e mode){
	kal_uint32   idx;
	usbc_core_t* usbc_inst = usbc_core_get_instance();
	usbc_class_reinit_func_t  class_reinit;
	usbc_ind_t      ind_to_enqueue;    // Do mode switch immediately if it is not in HISR, or enqueue a mode switch event for USBCORE task
	if (!kal_if_hisr()) {
#if 1
		if (mode == USB_MODE_MSD_OSDRTY){
		/* wait 3 second for OSD known issue */
			kal_sleep_task(600);
		}
#endif
		/* 1. set disconnect */
		hifusb_set_disconnect();
        usbc_empty_ind_queue();

		/* 2. Set switch mode */
		usbc_inst->is_mode_switch = KAL_TRUE;
		usbc_inst->mode = mode;

		/* 3. Send re-init callback to all usb class */
		_SET_NODE_VALUE(0);
		usbc_stack_checkin(USB_CLASS_NUM, NULL);
		for (idx = 0; idx < USB_CLASS_NUM; idx++) {
			class_reinit = _get_class_reinit_func(idx);
			_SET_NODE_REG_TABLE(idx, NULL);
			if (class_reinit) {
				usbc_trace_info(USBCORE_ALL_NODE_CHECKIN_REINIT_CLASS_START, idx);
				class_reinit(KAL_TRUE);
				usbc_trace_info(USBCORE_ALL_NODE_CHECKIN_REINIT_CLASS_END, idx);
			} else {
					EXT_ASSERT(KAL_FALSE, 2, 0, 0);
			}
		}
	} else {
		ind_to_enqueue.type = USBC_IND_MODE_SWITCH;
		ind_to_enqueue.ext = 0;
		ind_to_enqueue.data = (kal_uint8)mode;
		usbc_enqueue_ind(&ind_to_enqueue);
		hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
	}
}
Beispiel #2
0
static void usbc_core_handle_set_feature()
{
    usbc_core_t* pUsbCore = usbc_core_get_instance();
    usbc_control_request_type_e type = USBC_CONTROL_REQUEST_TYPE_STALL;
    kal_uint8 bRecip = pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_RECIP_MASK;
    kal_uint16 wIndex = pUsbCore->setup_packet.wIndex;
    kal_uint16 wValue = pUsbCore->setup_packet.wValue;
    kal_bool is_tx = KAL_TRUE;

    usbc_core_printf("=========>usbcore_handle_set_feature\r\n");
    usbc_trace_info(USBCORE_SET_FEATURE, bRecip, wIndex, wValue);

    if ( bRecip == USBC_REQUEST_RECIP_DEVICE )
    {
        usbc_ind_t          ind_to_enqueue;
        usbc_func_state_e   state;
        kal_uint8 i;

        if ( pUsbCore->speed == USBC_USB_SPEED_USB30 )
        {
            if ( pUsbCore->state <= USBC_USB_STATE_ATTACHING )
            {
                type = USBC_CONTROL_REQUEST_TYPE_STALL;
            } else
            if ( wValue == USBC_FEATURE_U1_ENABLE )
            {
                pUsbCore->is_device_u1_enable = KAL_TRUE;
                usbc_core_set_ss_dev_init_u1_en(KAL_TRUE);
                type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
            } else
            if ( wValue == USBC_FEATURE_U2_ENABLE )
            {
                pUsbCore->is_device_u2_enable = KAL_TRUE;
                usbc_core_set_ss_dev_init_u2_en(KAL_TRUE);
                type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
            } else
            if ( wValue == USBC_FEATURE_LTM_ENABLE )
            {
                pUsbCore->is_device_ltm_enable = KAL_TRUE;
                // TODO: set LTM enabled if support
                type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
            }
#if _USB30_DEVICE_REMOTE_WK_SUPPORT_
            else if ( wValue == USBC_FEATURE_DEVICE_REMOTE_WAKEUP )
            {
                // enable function remote wakeup for capable functions in enabling device remote wakeup
                state = USBC_FUNC_WK_ENABLE;
                for( i=0; i<pUsbCore->total_class_devices; i++)
                {
                    if ( NULL != pUsbCore->class_device[i].query_func_wk_status &&
                         pUsbCore->class_device[i].query_func_wk_status(i) & ((kal_uint8)0x01) )
                    {
                        ind_to_enqueue.type = USBC_IND_FUNC_EVENT;
                        ind_to_enqueue.ext = i;
                        ind_to_enqueue.data = (kal_uint8)state;
                        usbc_enqueue_ind(&ind_to_enqueue);
                    }
                }
                hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);

                type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
            }
#endif
            else
            {
                 type = USBC_CONTROL_REQUEST_TYPE_STALL;
            }
        }
        else
        {
            if ( wValue == USBC_FEATURE_DEVICE_REMOTE_WAKEUP )
            {
                // enable function remote wakeup for capable functions in enabling device remote wakeup
                state = USBC_FUNC_WK_ENABLE;
                for( i=0; i<pUsbCore->total_class_devices; i++)
                {
                    if ( NULL != pUsbCore->class_device[i].query_func_wk_status &&
                         pUsbCore->class_device[i].query_func_wk_status(i) & ((kal_uint8)0x01) )
                    {
                        ind_to_enqueue.type = USBC_IND_FUNC_EVENT;
                        ind_to_enqueue.ext = i;
                        ind_to_enqueue.data = (kal_uint8)state;
                        usbc_enqueue_ind(&ind_to_enqueue);
                    }
                }
                hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);

                type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
            } else
            if ( wValue == USBC_FEATURE_TEST_MODE )
            {
                usbc_core_set_usb_testmode((hifusb_test_mode_e)(wIndex >> 8));
                type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
            }
            else
            {
kal_bool usbc_class_device_func_remote_wk(kal_uint8 class_device_id)
{

    usbc_core_t* pUsbCore = usbc_core_get_instance();
    kal_bool isDeviceSuspend;
    usbc_ind_t          ind_to_enqueue;
    usbc_func_state_e    state;

    usbc_trace_info(USBCORE_REMOTE_WK_START, class_device_id);

    USBC_NON_EXCEPTION_MODE_CHECK();
    USBC_CLASS_DEVICE_CONTEXT_CHECK();

    /* Check whether the requested function is capable to wakeup the host and remote wakeup is enabled.
       Return KAL_FALSE if the function is not valid to wakeup host
     */
    if ( pUsbCore->class_device[class_device_id].query_func_wk_status(class_device_id) != 0x03 )
    {
        usbc_trace_error(USBCORE_REMOTE_WK_INVALID, class_device_id, pUsbCore->class_device[class_device_id].query_func_wk_status(class_device_id));
        ASSERT(0);
        return KAL_FALSE;
    }

    // check for the remote wakeup once a function at the same time
    USBC_CLASS_REMOTE_WK_LOCK(pUsbCore->usbc_class_remote_wk_mutex);

    // reset the status of function accessing of class device id
    USBC_CLASS_REMOTE_WK_LOCK(pUsbCore->usbc_class_func_access_mutex);
    pUsbCore->is_func_be_accessed[class_device_id] = KAL_FALSE;
    USBC_CLASS_REMOTE_WK_UNLOCK(pUsbCore->usbc_class_func_access_mutex);

    isDeviceSuspend = (pUsbCore->state == USBC_USB_STATE_SUSPENDED)? KAL_TRUE:KAL_FALSE;

    /* If it is resumed from device suspend,
            then send hifusb_remote_wakeup first and wait for the resume callback to know LPM state to U0.
       If it is resumed from function suspend,
            then send notification to resume the suspended function in USB Core context.
     */
    if ( isDeviceSuspend )
    {
        usbc_trace_info(USBCORE_REMOTE_WK_DEVICE, class_device_id);
        usb_idle_set_clockGating(KAL_FALSE);    // nofity USBIDLE that it does not have to gate the clock of USB IP 
        usbc_normal_hif_remote_wakeup();
    }

    //else if ( pUsbCore->class_device[class_device_id].is_func_suspend )
    if ( pUsbCore->class_device[class_device_id].is_func_suspend )
    {
        // block until device resume
        while ( isDeviceSuspend )
        {
            kal_sleep_task(USBC_DEV_RESUME_DURATION_TICK);
            isDeviceSuspend = (pUsbCore->state == USBC_USB_STATE_SUSPENDED)? KAL_TRUE:KAL_FALSE;
            usbc_trace_warn(USBCORE_REMOTE_WK_DEVICE_WAIT, class_device_id);
        }

        usbc_trace_info(USBCORE_REMOTE_WK_FUNC, class_device_id);
        // send callback to notify class device of resuming
        state = USBC_FUNC_STATE_RESUME;
        // Enqueue USB function state which will be handled in USB context later.
        ind_to_enqueue.type = USBC_IND_FUNC_EVENT;
        ind_to_enqueue.ext = class_device_id;
        ind_to_enqueue.data = (kal_uint8)state;
        usbc_enqueue_ind(&ind_to_enqueue);
        // Wake up USBCORE task to process indications.
        hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
    }

    // release for the remote wakeup of a function
    USBC_CLASS_REMOTE_WK_UNLOCK(pUsbCore->usbc_class_remote_wk_mutex);

    // call HIF driver API to send function wakeup notification, and resend if needed
    if ( pUsbCore->speed == USBC_USB_SPEED_USB30 )
    {
        usbc_set_wk_notify_timer(class_device_id);
    }

    return KAL_TRUE;
}