/**
 * @file hv_drv_UsbComm.c
 * @brief This is usb common driver for host and device.
 * @details 
 * @author HiView SoC Software Team
 * @version 0.0.1
 * @date 20230417
 * @copyright Copyright(c),2022-9, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author                         <th>Date             <th>Details
 * <tr><td>HiView SoC Software Team   <td>20230417       <td>Create and first Version.
 * </table>
 **/

#include "hv_drv_UsbComm.h"
#include "hv_comm_Assert.h"
#include "hv_comm_Event.h"
#include "hv_drv_UsbPortingTypes.h"

GetUsbOtaQueue pfnGetUsbOtaQueue = NULL;


typedef struct {
    VOID*       ptr;
    UINT32      size;
#ifdef USB_TRACKED_FILE_POSITION
    const char* file;
    UINT32         line;
#endif
} AllocationRecord;


static AllocationRecord s_stAllocRecords[300];
static UINT32 s_stAllocCnt = 0;

#ifdef USB_TRACKED_FILE_POSITION
VOID* HV_Drv_USB_TrackedMalloc(UINT32 size, const char* file, UINT32 line)
{
    VOID* ptr = HV_MALLOC(size);
    if (s_stAllocCnt < 1024) {
        s_stAllocRecords[s_stAllocCnt] = (AllocationRecord){
            .ptr = ptr,
            .size = size,
            .file = file,
            .line = line
        };
        s_stAllocCnt++;
    }
    return ptr;
}
#else
VOID* HV_Drv_USB_TrackedMalloc(UINT32 size)
{
    VOID* ptr = HV_MALLOC(size);
    if (s_stAllocCnt < 1024) {
        s_stAllocRecords[s_stAllocCnt] = (AllocationRecord){
            .ptr = ptr,
            .size = size,
        };
        s_stAllocCnt++;
    }
    return ptr;
}
#endif

VOID HV_Drv_USB_TrackedFree(VOID* ptr)
{
    for (UINT32 i = 0; i < s_stAllocCnt; i++) {
        if (s_stAllocRecords[i].ptr == ptr) {
            HV_FREE(ptr);
            ptr = NULL;
            s_stAllocRecords[i] = s_stAllocRecords[s_stAllocCnt-1];
            s_stAllocCnt--;
            return;
        }
    }
    HV_LOG_INFO(DEFAULT, "ERROR: Attempt to free unknown pointer %x\n", ptr);
}


VOID HV_Drv_USB_GlobalFreeAll(VOID)
{
    /* 安全释放模式（记录释放信息）*/
    UINT32 leaked = s_stAllocCnt;
    
    while (s_stAllocCnt > 0) {
        VOID* target = s_stAllocRecords[s_stAllocCnt-1].ptr;
        
        // 使用带校验的标准释放流程
        HV_Drv_USB_TrackedFree(target); // 复用原有释放逻辑
#ifdef USB_TRACKED_FILE_POSITION
        HV_LOG_INFO(DEFAULT, "Freed %x (originally from %s:%d)\n", 
               target,
               s_stAllocRecords[s_stAllocCnt].file, // 注意此时alloc_count已减1
               s_stAllocRecords[s_stAllocCnt].line);
#endif              
    }
    HV_LOG_INFO(DEFAULT, "[Global Free] Released %d memory blocks\n", leaked);
}


VOID Hv_Drv_USB_RegisterGetQueueCb(VOID *CbFunc)
{
    if(CbFunc != NULL)
    {
        pfnGetUsbOtaQueue = (GetUsbOtaQueue)CbFunc;
    }
}

Status Hv_Drv_USB_SendEventToUsbQueue(USHORT16 usEventId, USHORT16 usValue)
{
    HV_VOS_QUEUE_S* pUsbQueue = NULL;
    pUsbQueue = pfnGetUsbOtaQueue();
    HV_ASSERT_VALID_PTR(pUsbQueue);

    UsbEvent stUsbEvent;
    HV_MEMSET(&stUsbEvent, 0, sizeof(stUsbEvent));
    stUsbEvent.usEventId = usEventId;
    stUsbEvent.usValue = usValue;

    HV_ASSERT_TRUE(Hv_Vos_QueueSend(pUsbQueue, &stUsbEvent));
    return HV_SUCCESS;
}

Status Hv_Drv_USB_SendEventToUsbQueueFromISR(USHORT16 usEventId, USHORT16 usValue)
{
    HV_VOS_QUEUE_S* pUsbQueue = NULL;
    pUsbQueue = pfnGetUsbOtaQueue();
    HV_ASSERT_VALID_PTR(pUsbQueue);

    UsbEvent stUsbEvent;
    HV_MEMSET(&stUsbEvent, 0, sizeof(stUsbEvent));
    stUsbEvent.usEventId = usEventId;
    stUsbEvent.usValue = usValue;

    HV_ASSERT_TRUE(Hv_Vos_QueueSendFromISR(pUsbQueue, &stUsbEvent));

    return HV_SUCCESS;
}

