@@ -224,7 +224,6 @@ static inline esp_err_t _uac_host_device_try_lock(uac_device_t *uac_device, uint
224224static inline void _uac_host_device_unlock (uac_device_t * uac_device );
225225static esp_err_t uac_cs_request_set (uac_device_t * uac_device , const uac_cs_request_t * req );
226226static esp_err_t uac_cs_request_set_ep_frequency (uac_iface_t * iface , uint8_t ep_addr , uint32_t freq );
227- static inline bool _iface_ready_check (const uac_iface_t * iface );
228227
229228// --------------------------- Utility Functions --------------------------------
230229/**
@@ -354,6 +353,74 @@ static esp_err_t _ring_buffer_pop(RingbufHandle_t ringbuf_hdl, uint8_t *buf, siz
354353 return ESP_OK ;
355354}
356355
356+ // --------------------------- Interface states --------------------------------
357+
358+ /**
359+ * @brief Check if the interface is in ready state
360+ *
361+ * In caste the interface is currently in suspended state, the function checks interface's last state
362+ *
363+ * @param[in] iface UAC interface
364+ * @return
365+ * - true if the interface is in correct state
366+ * - false if the interface is not in correct state
367+ */
368+ static inline bool _iface_state_ready_check (const uac_iface_t * iface )
369+ {
370+ // Use iface last_state if currently suspended, otherwise use iface state
371+ #ifdef UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
372+ const uac_iface_state_t state = (iface -> state == UAC_INTERFACE_STATE_SUSPENDED ) ? (iface -> last_state ) : (iface -> state );
373+ #else
374+ const uac_iface_state_t state = iface -> state ;
375+ #endif // UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
376+
377+ return (state == UAC_INTERFACE_STATE_READY );
378+ }
379+
380+ /**
381+ * @brief Check if the interface is active state
382+ *
383+ * In caste the interface is currently in suspended state, the function checks interface's last state
384+ *
385+ * @param[in] iface UAC interface
386+ * @return
387+ * - true if the interface is in correct state
388+ * - false if the interface is not in correct state
389+ */
390+ static inline bool _iface_state_active_check (const uac_iface_t * iface )
391+ {
392+ // Use iface last_state if currently suspended, otherwise use iface state
393+ #ifdef UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
394+ const uac_iface_state_t state = (iface -> state == UAC_INTERFACE_STATE_SUSPENDED ) ? (iface -> last_state ) : (iface -> state );
395+ #else
396+ const uac_iface_state_t state = iface -> state ;
397+ #endif // UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
398+
399+ return (state == UAC_INTERFACE_STATE_ACTIVE );
400+ }
401+
402+ /**
403+ * @brief Check if the interface is in active or ready state
404+ *
405+ * In caste the interface is currently in suspended state, the function checks interface's last state
406+ *
407+ * @param[in] iface UAC interface
408+ * @return
409+ * - true if the interface is in correct state
410+ * - false if the interface is not in correct state
411+ */
412+ static inline bool _iface_state_active_ready_check (const uac_iface_t * iface )
413+ {
414+ // Use iface last_state if currently suspended, otherwise use iface state
415+ #ifdef UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
416+ const uac_iface_state_t state = (iface -> state == UAC_INTERFACE_STATE_SUSPENDED ) ? (iface -> last_state ) : (iface -> state );
417+ #else
418+ const uac_iface_state_t state = iface -> state ;
419+ #endif // UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
420+
421+ return ((state == UAC_INTERFACE_STATE_ACTIVE ) || (state == UAC_INTERFACE_STATE_READY ));
422+ }
423+
357424/**
358425 * @brief UAC Host driver event handler internal task
359426 *
@@ -1391,12 +1458,17 @@ static esp_err_t uac_host_interface_release_and_free_transfer(uac_iface_t *iface
13911458 }
13921459
13931460 // Change state
1461+ #ifdef UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
13941462 if (iface -> state == UAC_INTERFACE_STATE_SUSPENDED ) {
13951463 iface -> last_state = UAC_INTERFACE_STATE_IDLE ;
13961464 } else {
13971465 iface -> state = UAC_INTERFACE_STATE_IDLE ;
13981466 }
13991467 return ESP_OK ;
1468+ #else // UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
1469+ iface -> state = UAC_INTERFACE_STATE_IDLE ;
1470+ return ESP_OK ;
1471+ #endif // UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
14001472}
14011473
14021474/**
@@ -1605,9 +1677,9 @@ static esp_err_t uac_host_interface_pause(uac_iface_t *iface)
16051677 UAC_RETURN_ON_INVALID_ARG (iface -> parent );
16061678 UAC_RETURN_ON_INVALID_ARG (iface -> free_xfer_list );
16071679 UAC_RETURN_ON_FALSE (is_interface_in_list (iface ), ESP_ERR_NOT_FOUND , "Interface handle not found" );
1608- UAC_RETURN_ON_FALSE ((UAC_INTERFACE_STATE_ACTIVE == iface -> state ) ||
1609- (UAC_INTERFACE_STATE_ACTIVE == iface -> last_state && UAC_INTERFACE_STATE_SUSPENDED == iface -> state ), ESP_ERR_INVALID_STATE , "Interface wrong state" );
1680+ UAC_RETURN_ON_FALSE (_iface_state_active_check (iface ), ESP_ERR_INVALID_STATE , "Interface wrong state" );
16101681
1682+ #ifdef UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
16111683 if (UAC_INTERFACE_STATE_SUSPENDED == iface -> state ) {
16121684 // endpoints are already flushed by usb_host_lib,
16131685 // ringbuffer is flushed by the suspend routine in uac driver,
@@ -1616,6 +1688,7 @@ static esp_err_t uac_host_interface_pause(uac_iface_t *iface)
16161688 iface -> last_state = UAC_INTERFACE_STATE_READY ;
16171689 return ESP_OK ;
16181690 }
1691+ #endif // UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
16191692
16201693 iface -> state = UAC_INTERFACE_STATE_PAUSING ;
16211694
@@ -1667,9 +1740,7 @@ static esp_err_t uac_host_interface_unpause(uac_iface_t *iface)
16671740 UAC_RETURN_ON_INVALID_ARG (iface -> parent );
16681741 UAC_RETURN_ON_INVALID_ARG (iface -> free_xfer_list );
16691742 UAC_RETURN_ON_FALSE (is_interface_in_list (iface ), ESP_ERR_NOT_FOUND , "Interface handle not found" );
1670- UAC_RETURN_ON_FALSE ((UAC_INTERFACE_STATE_READY == iface -> state ) ||
1671- (UAC_INTERFACE_STATE_SUSPENDED == iface -> state && UAC_INTERFACE_STATE_READY == iface -> last_state ),
1672- ESP_ERR_INVALID_STATE , "Interface wrong state" );
1743+ UAC_RETURN_ON_FALSE (_iface_state_ready_check (iface ), ESP_ERR_INVALID_STATE , "Interface wrong state" );
16731744
16741745 // Set Interface alternate setting
16751746 usb_setup_packet_t usb_request ;
@@ -2476,13 +2547,11 @@ esp_err_t uac_host_device_close(uac_host_device_handle_t uac_dev_handle)
24762547 ESP_LOGD (TAG , "Close addr %d, iface %d, state %d" , uac_iface -> dev_info .addr , uac_iface -> dev_info .iface_num , uac_iface -> state );
24772548
24782549 UAC_RETURN_ON_ERROR (uac_host_interface_try_lock (uac_iface , DEFAULT_CTRL_XFER_TIMEOUT_MS ), "UAC Interface is busy by other task" );
2479- if (UAC_INTERFACE_STATE_ACTIVE == uac_iface -> state ||
2480- (UAC_INTERFACE_STATE_ACTIVE == uac_iface -> last_state && UAC_INTERFACE_STATE_SUSPENDED == uac_iface -> state )) {
2550+ if (_iface_state_active_check (uac_iface )) {
24812551 UAC_GOTO_ON_ERROR (uac_host_interface_pause (uac_iface ), "Unable to disable UAC Interface" );
24822552 }
24832553
2484- if (UAC_INTERFACE_STATE_READY == uac_iface -> state ||
2485- (UAC_INTERFACE_STATE_READY == uac_iface -> last_state && UAC_INTERFACE_STATE_SUSPENDED == uac_iface -> state )) {
2554+ if (_iface_state_ready_check (uac_iface )) {
24862555 UAC_GOTO_ON_ERROR (uac_host_interface_release_and_free_transfer (uac_iface ), "Unable to release UAC Interface" );
24872556 }
24882557
@@ -2602,6 +2671,7 @@ esp_err_t uac_host_device_start(uac_host_device_handle_t uac_dev_handle, const u
26022671 esp_err_t ret = ESP_OK ;
26032672 bool iface_claimed = false;
26042673
2674+ #ifdef UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
26052675 if (UAC_INTERFACE_STATE_SUSPENDED == iface -> state && UAC_INTERFACE_STATE_READY == iface -> last_state ) {
26062676 // If interface's last state was in READY and the current state is SUSPENDED, resume the root port
26072677 // Following usb_host calls require the root port to be suspended to proceed
@@ -2623,17 +2693,18 @@ esp_err_t uac_host_device_start(uac_host_device_handle_t uac_dev_handle, const u
26232693 return ESP_OK ;
26242694 }
26252695
2626- if (UAC_INTERFACE_STATE_ACTIVE == iface -> state || UAC_INTERFACE_STATE_READY == iface -> state ) {
2627- uac_host_interface_unlock (iface );
2628- return ESP_OK ;
2629- }
2630-
26312696 if (UAC_INTERFACE_STATE_SUSPENDED == iface -> state && UAC_INTERFACE_STATE_IDLE == iface -> last_state ) {
26322697 // We can't continue, since the following usb_host_lib api calls require the root port to be resumed
26332698 ESP_LOGE (TAG , "Device in suspended state, resume the device first" );
26342699 uac_host_interface_unlock (iface );
26352700 return ESP_ERR_INVALID_STATE ;
26362701 }
2702+ #endif // UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
2703+
2704+ if (UAC_INTERFACE_STATE_ACTIVE == iface -> state || UAC_INTERFACE_STATE_READY == iface -> state ) {
2705+ uac_host_interface_unlock (iface );
2706+ return ESP_OK ;
2707+ }
26372708
26382709 UAC_GOTO_ON_FALSE ((UAC_INTERFACE_STATE_IDLE == iface -> state ), ESP_ERR_INVALID_STATE , "Interface wrong state" );
26392710
@@ -2704,9 +2775,7 @@ esp_err_t uac_host_device_pause(uac_host_device_handle_t uac_dev_handle)
27042775 return ESP_OK ;
27052776 }
27062777 esp_err_t ret = ESP_OK ;
2707- UAC_GOTO_ON_FALSE ((UAC_INTERFACE_STATE_ACTIVE == iface -> state ) ||
2708- (UAC_INTERFACE_STATE_SUSPENDED == iface -> state && UAC_INTERFACE_STATE_ACTIVE == iface -> last_state )
2709- , ESP_ERR_INVALID_STATE , "device not active" );
2778+ UAC_GOTO_ON_FALSE (_iface_state_active_check (iface ), ESP_ERR_INVALID_STATE , "device not active" );
27102779 UAC_GOTO_ON_ERROR (uac_host_interface_pause (iface ), "Unable to disable UAC Interface" );
27112780
27122781 uac_host_interface_unlock (iface );
@@ -2728,14 +2797,16 @@ esp_err_t uac_host_device_unpause(uac_host_device_handle_t uac_dev_handle)
27282797 return ESP_OK ;
27292798 }
27302799
2800+ #ifdef UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
27312801 // In case user calls this function after the device was suspended from active (unpaused) state
27322802 // Change the last state to ready, so the interface could be automatically resumed and unpaused
27332803 if (UAC_INTERFACE_STATE_SUSPENDED == iface -> state && UAC_INTERFACE_STATE_ACTIVE == iface -> last_state ) {
27342804 iface -> last_state = UAC_INTERFACE_STATE_READY ;
27352805 }
2806+ #endif // UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
27362807
27372808 esp_err_t ret = ESP_OK ;
2738- UAC_GOTO_ON_FALSE (_iface_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready" );
2809+ UAC_GOTO_ON_FALSE (_iface_state_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready" );
27392810 UAC_GOTO_ON_ERROR (uac_host_interface_unpause (iface ), "Unable to enable UAC Interface" );
27402811
27412812 uac_host_interface_unlock (iface );
@@ -2753,13 +2824,11 @@ esp_err_t uac_host_device_stop(uac_host_device_handle_t uac_dev_handle)
27532824
27542825 esp_err_t ret = ESP_OK ;
27552826 UAC_RETURN_ON_ERROR (uac_host_interface_try_lock (iface , DEFAULT_CTRL_XFER_TIMEOUT_MS ), "Unable to lock UAC Interface" );
2756- if ((UAC_INTERFACE_STATE_ACTIVE == iface -> state ) ||
2757- (UAC_INTERFACE_STATE_SUSPENDED == iface -> state && UAC_INTERFACE_STATE_ACTIVE == iface -> last_state )) {
2827+ if (_iface_state_active_check (iface )) {
27582828 UAC_GOTO_ON_ERROR (uac_host_interface_pause (iface ), "Unable to disable UAC Interface" );
27592829 }
27602830
2761- if ((UAC_INTERFACE_STATE_READY == iface -> state ) ||
2762- (UAC_INTERFACE_STATE_SUSPENDED == iface -> state && UAC_INTERFACE_STATE_READY == iface -> last_state )) {
2831+ if (_iface_state_ready_check (iface )) {
27632832 UAC_GOTO_ON_ERROR (uac_host_interface_release_and_free_transfer (iface ), "Unable to release UAC Interface" );
27642833 }
27652834
@@ -2795,61 +2864,6 @@ esp_err_t uac_host_device_read(uac_host_device_handle_t uac_dev_handle, uint8_t
27952864 return ESP_OK ;
27962865}
27972866
2798- /**
2799- * @brief Check if interface is ready
2800- *
2801- * @param[in] iface UAC interface
2802- * @return
2803- * - true if the interface is in correct state
2804- * - false if the interface is not in correct state
2805- */
2806- static inline bool _iface_ready_check (const uac_iface_t * iface )
2807- {
2808- // Use iface last_state if currently suspended, otherwise use iface state
2809- #ifdef UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
2810- const uac_iface_state_t state = (iface -> state == UAC_INTERFACE_STATE_SUSPENDED ) ? (iface -> last_state ) : (iface -> state );
2811- #else
2812- const uac_iface_state_t state = iface -> state ;
2813- #endif // UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
2814-
2815- return (state == UAC_INTERFACE_STATE_READY );
2816- }
2817-
2818- /**
2819- * @brief Check if interface is active or ready
2820- *
2821- * @param[in] iface UAC interface
2822- * @return
2823- * - true if the interface is in correct state
2824- * - false if the interface is not in correct state
2825- */
2826- static inline bool _iface_active_ready_check (const uac_iface_t * iface )
2827- {
2828- // Use iface last_state if currently suspended, otherwise use iface state
2829- #ifdef UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
2830- const uac_iface_state_t state = (iface -> state == UAC_INTERFACE_STATE_SUSPENDED ) ? (iface -> last_state ) : (iface -> state );
2831- #else
2832- const uac_iface_state_t state = iface -> state ;
2833- #endif // UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
2834-
2835- return ((state == UAC_INTERFACE_STATE_ACTIVE ) || (state == UAC_INTERFACE_STATE_READY ));
2836- }
2837-
2838- /**
2839- * @brief Finalize auto-resume procedure
2840- *
2841- * @param[in] iface UAC interface
2842- */
2843- static inline void _iface_auto_resume (const uac_iface_t * iface )
2844- {
2845- #ifdef UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
2846- if (iface -> state == UAC_INTERFACE_STATE_SUSPENDED ) {
2847- // Update the interface state from here instead of from client event handler, as this function takes interface lock
2848- _uac_host_device_auto_resume (iface -> parent );
2849- }
2850- #endif // UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
2851- }
2852-
28532867esp_err_t uac_host_device_write (uac_host_device_handle_t uac_dev_handle , uint8_t * data , uint32_t size , uint32_t timeout )
28542868{
28552869 uac_iface_t * iface = get_iface_by_handle (uac_dev_handle );
@@ -2903,6 +2917,21 @@ esp_err_t uac_host_device_write(uac_host_device_handle_t uac_dev_handle, uint8_t
29032917 return ret ;
29042918}
29052919
2920+ /**
2921+ * @brief Finalize auto-resume procedure
2922+ *
2923+ * @param[in] iface UAC interface
2924+ */
2925+ static inline void _iface_auto_resume (const uac_iface_t * iface )
2926+ {
2927+ #ifdef UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
2928+ if (iface -> state == UAC_INTERFACE_STATE_SUSPENDED ) {
2929+ // Update the interface state from here instead of from client event handler, as this function takes interface lock
2930+ _uac_host_device_auto_resume (iface -> parent );
2931+ }
2932+ #endif // UAC_HOST_SUSPEND_RESUME_API_SUPPORTED
2933+ }
2934+
29062935esp_err_t uac_host_get_device_info (uac_host_device_handle_t uac_dev_handle , uac_host_dev_info_t * uac_dev_info )
29072936{
29082937 uac_iface_t * iface = get_iface_by_handle (uac_dev_handle );
@@ -2919,7 +2948,7 @@ esp_err_t uac_host_device_set_mute(uac_host_device_handle_t uac_dev_handle, bool
29192948 // Check if the device is active or ready
29202949 esp_err_t ret = ESP_OK ;
29212950 UAC_RETURN_ON_ERROR (uac_host_interface_try_lock (iface , DEFAULT_CTRL_XFER_TIMEOUT_MS ), "Unable to lock UAC Interface" );
2922- UAC_GOTO_ON_FALSE (_iface_active_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready or active" );
2951+ UAC_GOTO_ON_FALSE (_iface_state_active_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready or active" );
29232952
29242953 UAC_GOTO_ON_ERROR (uac_cs_request_set_mute (iface , mute ), "Unable to set mute" );
29252954 ESP_LOGI (TAG , "%s Interface %d-%d" , mute ? "Mute" : "Unmute" , iface -> dev_info .iface_num , iface -> cur_alt + 1 );
@@ -2943,7 +2972,7 @@ esp_err_t uac_host_device_get_mute(uac_host_device_handle_t uac_dev_handle, bool
29432972 // Check if the device is active or ready
29442973 esp_err_t ret = ESP_OK ;
29452974 UAC_RETURN_ON_ERROR (uac_host_interface_try_lock (iface , DEFAULT_CTRL_XFER_TIMEOUT_MS ), "Unable to lock UAC Interface" );
2946- UAC_GOTO_ON_FALSE (_iface_active_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready or active" );
2975+ UAC_GOTO_ON_FALSE (_iface_state_active_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready or active" );
29472976
29482977 UAC_GOTO_ON_ERROR (uac_cs_request_get_mute (iface , mute ), "Unable to get mute" );
29492978
@@ -2966,7 +2995,7 @@ esp_err_t uac_host_device_set_volume(uac_host_device_handle_t uac_dev_handle, ui
29662995 // Check if the device is active or ready
29672996 esp_err_t ret = ESP_OK ;
29682997 UAC_RETURN_ON_ERROR (uac_host_interface_try_lock (iface , DEFAULT_CTRL_XFER_TIMEOUT_MS ), "Unable to lock UAC Interface" );
2969- UAC_GOTO_ON_FALSE (_iface_active_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready or active" );
2998+ UAC_GOTO_ON_FALSE (_iface_state_active_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready or active" );
29702999
29713000 // Calculate target volume in float to avoid the int16_t calculation overflow
29723001 float volume_db_f = _volume_db_i16_2_f (iface -> vol_min_db ) + (_volume_db_i16_2_f (iface -> vol_max_db ) - _volume_db_i16_2_f (iface -> vol_min_db )) * (float )volume / 100.0f ;
@@ -2999,7 +3028,7 @@ esp_err_t uac_host_device_get_volume(uac_host_device_handle_t uac_dev_handle, ui
29993028 // Check if the device is active or ready
30003029 esp_err_t ret = ESP_OK ;
30013030 UAC_RETURN_ON_ERROR (uac_host_interface_try_lock (iface , DEFAULT_CTRL_XFER_TIMEOUT_MS ), "Unable to lock UAC Interface" );
3002- UAC_GOTO_ON_FALSE (_iface_active_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready or active" );
3031+ UAC_GOTO_ON_FALSE (_iface_state_active_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready or active" );
30033032
30043033 // Return the backup volume value to avoid the volume reads differently than expected.
30053034 // Because the device volume adjustment step may be relatively large,
@@ -3036,7 +3065,7 @@ esp_err_t uac_host_device_set_volume_db(uac_host_device_handle_t uac_dev_handle,
30363065 // Check if the device is active or ready
30373066 esp_err_t ret = ESP_OK ;
30383067 UAC_RETURN_ON_ERROR (uac_host_interface_try_lock (iface , DEFAULT_CTRL_XFER_TIMEOUT_MS ), "Unable to lock UAC Interface" );
3039- UAC_GOTO_ON_FALSE (_iface_active_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready or active" );
3068+ UAC_GOTO_ON_FALSE (_iface_state_active_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready or active" );
30403069
30413070 // Check if the volume is within the range
30423071 UAC_GOTO_ON_FALSE ((volume_db >= iface -> vol_min_db && volume_db <= iface -> vol_max_db ), ESP_ERR_INVALID_ARG , "Invalid volume value" );
@@ -3061,7 +3090,7 @@ esp_err_t uac_host_device_get_volume_db(uac_host_device_handle_t uac_dev_handle,
30613090 // Check if the device is active or ready
30623091 esp_err_t ret = ESP_OK ;
30633092 UAC_RETURN_ON_ERROR (uac_host_interface_try_lock (iface , DEFAULT_CTRL_XFER_TIMEOUT_MS ), "Unable to lock UAC Interface" );
3064- UAC_GOTO_ON_FALSE (_iface_active_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready or active" );
3093+ UAC_GOTO_ON_FALSE (_iface_state_active_ready_check (iface ), ESP_ERR_INVALID_STATE , "device not ready or active" );
30653094
30663095 UAC_GOTO_ON_ERROR (uac_cs_request_get_volume (iface , volume_db ), "Unable to get volume" );
30673096
0 commit comments