/*
 *  usb_device.h
 *
 * Change Logs:
 * Date          Author      Notes
 * 2024-01-09    weijiac     移植修改于rtthread
 */

#include "usb_common.h"
#include "usb_device.h"
#include "debug.h"

#define USB_DEVICE_CONTROLLER_NAME      "usbd"

#ifdef RT_USB_DEVICE_COMPOSITE
const static char *ustring[] =
{
    "Language",
    "RT-Thread Team.",
    "RTT Composite Device",
    "320219198301",
    "Configuration",
    "Interface",
    USB_STRING_OS
};

static struct udevice_descriptor compsit_desc =
{
    USB_DESC_LENGTH_DEVICE,     //bLength;
    USB_DESC_TYPE_DEVICE,       //type;
    USB_BCD_VERSION,            //bcdUSB;
    USB_CLASS_MISC,             //bDeviceClass;
    0x02,                       //bDeviceSubClass;
    0x01,                       //bDeviceProtocol;
    0x40,                       //bMaxPacketSize0;
    _VENDOR_ID,                 //idVendor;
    _PRODUCT_ID,                //idProduct;
    USB_BCD_DEVICE,             //bcdDevice;
    USB_STRING_MANU_INDEX,      //iManufacturer;
    USB_STRING_PRODUCT_INDEX,   //iProduct;
    USB_STRING_SERIAL_INDEX,    //iSerialNumber;
    USB_DYNAMIC,                //bNumConfigurations;
};

//FS and HS needed
static struct usb_qualifier_descriptor dev_qualifier =
{
    sizeof(dev_qualifier),          //bLength
    USB_DESC_TYPE_DEVICEQUALIFIER,  //bDescriptorType
    0x0200,                         //bcdUSB
    USB_CLASS_MISC,                 //bDeviceClass
    0x02,                           //bDeviceSubClass
    0x01,                           //bDeviceProtocol
    64,                             //bMaxPacketSize0
    0x01,                           //bNumConfigurations
    0,
};
#endif

struct usb_os_comp_id_descriptor usb_comp_id_desc =
{
    //head section
    {
        USB_DYNAMIC,
        0x0100,
        0x04,
        USB_DYNAMIC,
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    },
};

static rt_list_t class_list;
int rt_usbd_class_list_init(void)
{
    rt_list_init(&class_list);
    return 0;
}
INIT_BOARD_EXPORT(rt_usbd_class_list_init);

rt_err_t rt_usbd_class_register(udclass_t udclass)
{
#ifndef RT_USB_DEVICE_COMPOSITE

    if (!rt_list_isempty(&class_list))
    {
        rt_kprintf("[D/USBD] If you want to use usb composite device please define RT_USB_DEVICE_COMPOSITE\n");
        return RT_ERROR;
    }

#endif
    rt_list_insert_before(&class_list, &udclass->list);
    return RT_EOK;
}


extern rt_err_t rt_usbd_ep_init(udevice_t device);

extern void usb_user_init(void);
//修改本接口，将其修改为按照当前devcie，当前cfg初始化硬件等。
rt_err_t rt_usb_device_init(void)
{
    udevice_t cur_udevice ;
    uconfig_t cur_cfg ;
    ufunction_t first_func;
    cur_udevice = rt_usbd_get_curr_device();

    if (cur_udevice == RT_NULL)
    {
        debug("cur_udevice == RT_NULL\n\r");
        return RT_ERROR;
    }

    if (cur_udevice->curr_cfg == RT_NULL)
    {
        debug("cur_udevice->curr_cfg == RT_NULL\n\r");
        return RT_ERROR;
    }

    if (cur_udevice->curr_cfg->func_list.next == &cur_udevice->curr_cfg->func_list)
    {
        debug("cur_udevice->curr_cfg->func_list.prev ==&cur_udevice->curr_cfg->func_list\n\r");
        return RT_ERROR;
    }

    cur_cfg = cur_udevice->curr_cfg;
    /* create a configuration object */
    rt_usbd_device_set_os_comp_id_desc(cur_udevice, &usb_comp_id_desc);
    /* set device descriptor to the device */
#ifdef RT_USB_DEVICE_COMPOSITE
    rt_usbd_device_set_descriptor(cur_udevice, &compsit_desc);
    rt_usbd_device_set_string(cur_udevice, ustring);

    if (cur_udevice->dcd->device_is_hs)
    {
        rt_usbd_device_set_qualifier(cur_udevice, &dev_qualifier);
    }

#else
    first_func = (ufunction_t)cur_cfg->func_list.next;
    rt_usbd_device_set_descriptor(cur_udevice, first_func->dev_desc);
#endif
    //初始化引脚，并将cfg中的端点函数注册到hal层
    rt_usbd_ep_init(cur_udevice);
    return RT_EOK;
}


//修改前
// rt_err_t rt_usb_device_init(void)
// {
//     struct udcd udc;
//     udevice_t udevice;
//     uconfig_t cfg;
//     ufunction_t func;
//     rt_list_t *i;
//     udclass_t udclass;

//     if (rt_list_isempty(&class_list))
//     {
//         rt_kprintf("[D/USBD] No class register on usb device\n");
//         return RT_ERROR;
//     }

//     /* create and startup usb device thread */
//     rt_usbd_core_init();
//     /* create a device object */
//     udevice = rt_usbd_device_new();


//     /* set usb controller driver to the device */
//     rt_usbd_device_set_controller(udevice, &udc);
//     /* create a configuration object */
//     cfg = rt_usbd_config_new();
//     rt_usbd_device_set_os_comp_id_desc(udevice, &usb_comp_id_desc);

//     for (i = class_list.next; i != &class_list; i = i->next)
//     {
//         /* get a class creater */
//         udclass = rt_list_entry(i, struct udclass, list);
//         /* create a function object */
//         func = udclass->rt_usbd_function_create(udevice);
//         /* add the function to the configuration */
//         rt_usbd_config_add_function(cfg, func);
//     }

//     /* set device descriptor to the device */
// #ifdef RT_USB_DEVICE_COMPOSITE
//     rt_usbd_device_set_descriptor(udevice, &compsit_desc);
//     rt_usbd_device_set_string(udevice, ustring);

//     if (udevice->dcd->device_is_hs)
//     {
//         rt_usbd_device_set_qualifier(udevice, &dev_qualifier);
//     }

// #else
//     rt_usbd_device_set_descriptor(udevice, func->dev_desc);
// #endif
//     /* add the configuration to the device */
//     rt_usbd_device_add_config(udevice, cfg);
//     /* set default configuration to 1 */
//     rt_usbd_set_config(udevice, 1);
//     return RT_EOK;
// }
